diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c2517bef4f..91b78580a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,7 +58,8 @@ * [ENHANCEMENT] Metrics: Add native histogram support to all remaining production histograms, enabling dual-format (classic + native) exposition across all Cortex components. #7636 * [ENHANCEMENT] Ring: Cache `ShuffleShardWithLookback` subrings. The cached entry is invalidated on topology change or once `now` reaches the earliest `RegisteredTimestamp + lookbackPeriod` of any included instance. #7628 * [ENHANCEMENT] Query Frontend: Rename `time_taken` field to `time_taken_ms` and make it return millisecond count. #7649 -* [ENHANCEMENT] Update prometheus alertmanager version to v0.33.0. #7647 +* [ENHANCEMENT] Update prometheus alertmanager version to v0.34.0. #7647 #7820 + - The `reason` label on `cortex_alertmanager_notifications_failed_total` now reports `authError` for HTTP 401/403 and `rateLimited` for HTTP 429. These were previously counted as `clientError`. * [ENHANCEMENT] Querier/Ingester: Detach ingester series from gRPC buffers to reduce heap. #7670 * [ENHANCEMENT] Ingester: Add `cortex_ingester_tsdb_head_max_timestamp` metric that re-exports the TSDB head max timestamp (`prometheus_tsdb_head_max_time`) per user, to help investigate ingestion issues like out-of-bounds (too old sample) errors. #7694 * [ENHANCEMENT] Ingester: Include the TSDB head max time in the `out of bounds` and `too old sample` error messages, so that users can see how far behind the accepted time range a rejected sample is. #7695 diff --git a/go.mod b/go.mod index 48af58b8b3d..d1c48e762d9 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/VictoriaMetrics/fastcache v1.13.3 github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b github.com/alicebob/miniredis/v2 v2.38.0 - github.com/aws/aws-sdk-go-v2 v1.42.0 - github.com/aws/aws-sdk-go-v2/config v1.32.26 + github.com/aws/aws-sdk-go-v2 v1.43.2 + github.com/aws/aws-sdk-go-v2/config v1.32.33 github.com/aws/aws-sdk-go-v2/service/dynamodb v1.59.1 github.com/axiomhq/hyperloglog v0.2.6 github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 @@ -21,8 +21,8 @@ require ( github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb github.com/felixge/fgprof v0.9.5 github.com/go-kit/log v0.2.1 - github.com/go-openapi/strfmt v0.26.4 - github.com/go-openapi/swag/jsonutils v0.27.0 + github.com/go-openapi/strfmt v0.27.0 + github.com/go-openapi/swag/jsonutils v0.28.0 github.com/go-redis/redis/v8 v8.11.5 github.com/gogo/protobuf v1.3.2 github.com/gogo/status v1.1.1 @@ -38,26 +38,26 @@ require ( github.com/hashicorp/go-metrics v0.6.0 github.com/hashicorp/go-sockaddr v1.0.7 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/hashicorp/memberlist v0.5.4 + github.com/hashicorp/memberlist v0.6.0 github.com/json-iterator/go v1.1.12 - github.com/klauspost/compress v1.18.7 + github.com/klauspost/compress v1.19.1 github.com/minio/minio-go/v7 v7.2.1 github.com/mitchellh/go-wordwrap v1.0.1 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 github.com/oklog/ulid v1.3.1 - github.com/oklog/ulid/v2 v2.1.1 + github.com/oklog/ulid/v2 v2.1.2 github.com/opentracing-contrib/go-grpc v0.1.4 github.com/opentracing-contrib/go-stdlib v1.1.1 github.com/opentracing/opentracing-go v1.2.0 github.com/parquet-go/parquet-go v0.30.1 github.com/pkg/errors v0.9.1 github.com/prometheus-community/parquet-common v0.0.0-20260614025832-5f32460b5373 - github.com/prometheus/alertmanager v0.33.0 - github.com/prometheus/client_golang v1.23.2 + github.com/prometheus/alertmanager v0.34.0 + github.com/prometheus/client_golang v1.24.1 github.com/prometheus/client_golang/exp v0.0.0-20251212205219-7ba246a648ca github.com/prometheus/client_model v0.6.2 - github.com/prometheus/common v0.69.0 - github.com/prometheus/procfs v0.21.0 + github.com/prometheus/common v0.70.1 + github.com/prometheus/procfs v0.21.1 // Prometheus maps version 3.x.y to tags v0.30x.y. github.com/prometheus/prometheus v0.309.1 github.com/segmentio/fasthash v1.0.3 @@ -116,29 +116,27 @@ require ( github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.19.25 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.32 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.34 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.14 // indirect github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.12.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.2.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sns v1.39.17 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.31.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.7 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.43.4 // indirect - github.com/aws/smithy-go v1.27.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.33 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.5.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sns v1.42.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.33.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.45.2 // indirect + github.com/aws/smithy-go v1.27.5 // indirect github.com/baidubce/bce-sdk-go v0.9.230 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/caio/go-tdigest v3.1.0+incompatible // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/clbanning/mxj v1.8.4 // indirect github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect - github.com/coder/quartz v0.3.1 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.7.0 // indirect github.com/cristalhq/hedgedhttp v0.9.1 // indirect @@ -153,31 +151,32 @@ require ( github.com/fatih/color v1.19.0 // indirect github.com/fatih/faillint v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.10.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/go-chi/chi/v5 v5.2.4 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-logfmt/logfmt v0.6.1 // indirect github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/analysis v0.25.0 // indirect + github.com/go-openapi/analysis v0.25.5 // indirect github.com/go-openapi/errors v0.22.8 // indirect - github.com/go-openapi/jsonpointer v0.22.5 // indirect - github.com/go-openapi/jsonreference v0.21.5 // indirect - github.com/go-openapi/loads v0.23.3 // indirect - github.com/go-openapi/runtime v0.29.4 // indirect - github.com/go-openapi/spec v0.22.4 // indirect - github.com/go-openapi/swag v0.26.0 // indirect - github.com/go-openapi/swag/cmdutils v0.26.0 // indirect - github.com/go-openapi/swag/conv v0.27.0 // indirect - github.com/go-openapi/swag/fileutils v0.26.0 // indirect - github.com/go-openapi/swag/jsonname v0.26.0 // indirect - github.com/go-openapi/swag/loading v0.26.0 // indirect - github.com/go-openapi/swag/mangling v0.26.0 // indirect - github.com/go-openapi/swag/netutils v0.26.0 // indirect - github.com/go-openapi/swag/stringutils v0.26.0 // indirect - github.com/go-openapi/swag/typeutils v0.27.0 // indirect - github.com/go-openapi/swag/yamlutils v0.26.0 // indirect - github.com/go-openapi/validate v0.25.2 // indirect + github.com/go-openapi/jsonpointer v1.0.0 // indirect + github.com/go-openapi/jsonreference v1.0.0 // indirect + github.com/go-openapi/loads v0.25.0 // indirect + github.com/go-openapi/runtime v0.33.0 // indirect + github.com/go-openapi/runtime/server-middleware v0.33.0 // indirect + github.com/go-openapi/spec v0.22.9 // indirect + github.com/go-openapi/swag v0.28.0 // indirect + github.com/go-openapi/swag/cmdutils v0.28.0 // indirect + github.com/go-openapi/swag/conv v0.28.0 // indirect + github.com/go-openapi/swag/fileutils v0.28.0 // indirect + github.com/go-openapi/swag/loading v0.28.0 // indirect + github.com/go-openapi/swag/mangling v0.28.0 // indirect + github.com/go-openapi/swag/netutils v0.28.0 // indirect + github.com/go-openapi/swag/pools v0.28.0 // indirect + github.com/go-openapi/swag/stringutils v0.28.0 // indirect + github.com/go-openapi/swag/typeutils v0.28.0 // indirect + github.com/go-openapi/swag/yamlutils v0.28.0 // indirect + github.com/go-openapi/validate v0.26.1 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.13.0 // indirect @@ -218,10 +217,10 @@ require ( github.com/lib/pq v1.11.2 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mdlayher/socket v0.5.1 // indirect - github.com/mdlayher/vsock v1.2.1 // indirect + github.com/mdlayher/socket v0.6.0 // indirect + github.com/mdlayher/vsock v1.3.0 // indirect github.com/metalmatze/signal v0.0.0-20210307161603-1c9aa721a97a // indirect - github.com/miekg/dns v1.1.69 // indirect + github.com/miekg/dns v1.1.72 // indirect github.com/minio/crc64nvme v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/sha256-simd v1.0.1 // indirect @@ -247,7 +246,7 @@ require ( github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus-community/prom-label-proxy v0.11.1 // indirect - github.com/prometheus/exporter-toolkit v0.16.0 // indirect + github.com/prometheus/exporter-toolkit v0.17.1 // indirect github.com/prometheus/otlptranslator v1.0.0 // indirect github.com/prometheus/sigv4 v0.4.1 // indirect github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect @@ -263,7 +262,7 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/tencentyun/cos-go-sdk-v5 v0.7.66 // indirect github.com/tinylib/msgp v1.6.1 // indirect - github.com/twmb/franz-go v1.21.2 // indirect + github.com/twmb/franz-go v1.21.5 // indirect github.com/twmb/franz-go/pkg/kmsg v1.13.1 // indirect github.com/twmb/franz-go/plugin/kslog v1.0.0 // indirect github.com/twpayne/go-geom v1.6.1 // indirect @@ -286,13 +285,13 @@ require ( go.opentelemetry.io/collector/semconv v0.128.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.68.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.69.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect go.opentelemetry.io/contrib/propagators/autoprop v0.61.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.36.0 // indirect go.opentelemetry.io/contrib/propagators/jaeger v1.36.0 // indirect go.opentelemetry.io/contrib/propagators/ot v1.36.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 // indirect go.opentelemetry.io/otel/metric v1.45.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.44.0 // indirect go.opentelemetry.io/proto/otlp v1.10.0 // indirect @@ -303,7 +302,7 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.54.0 // indirect golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect - golang.org/x/mod v0.37.0 // indirect + golang.org/x/mod v0.38.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/text v0.40.0 // indirect @@ -336,9 +335,6 @@ replace github.com/hashicorp/memberlist => github.com/grafana/memberlist v0.3.1- // Same version being used by thanos replace github.com/vimeo/galaxycache => github.com/thanos-community/galaxycache v0.0.0-20211122094458-3a32041a1f1e -// v0.20.5 caused go mod checksum error -replace github.com/go-openapi/spec => github.com/go-openapi/spec v0.20.6 - // the v6.0.5851 Prometheus depends on doesn't seem to exist anymore? replace github.com/ionos-cloud/sdk-go/v6 => github.com/ionos-cloud/sdk-go/v6 v6.0.4 diff --git a/go.sum b/go.sum index 14aded077a1..b6748a6b217 100644 --- a/go.sum +++ b/go.sum @@ -158,46 +158,46 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.42.0 h1:XvXMJTkFQtpBKIWZnmr9ZEOc2InWM2yldjXEJ/bymhA= -github.com/aws/aws-sdk-go-v2 v1.42.0/go.mod h1:27+ACypSLljLAEKsCYOmrjKh83vuTRkuAe9Uv/3A4bg= -github.com/aws/aws-sdk-go-v2/config v1.32.26 h1:JI+W5B3jUA8UBz2ggbICGd9UCR6/+SB21G8EFl0SFTQ= -github.com/aws/aws-sdk-go-v2/config v1.32.26/go.mod h1:RLE2Ls/wRstvdSz1GPrIWNnXcKZ/znDdWyMuiQxdBoY= -github.com/aws/aws-sdk-go-v2/credentials v1.19.25 h1:TzPVjfUZ1hsKafvYE+DIzKXIik2KufQxsPHanlkttbo= -github.com/aws/aws-sdk-go-v2/credentials v1.19.25/go.mod h1:K4hw0buguVvtC74HnVfTRr0LzQQHAWPqJbBU9QGk2Pg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 h1:r6qZHbT+wxgWO/e9vYNUEtg7lv5+UN3pRqKhLXvnArg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29/go.mod h1:QRnaRcTVGKPGRy8w78HMQtKUGRYcnMZAANATkeVA6Mo= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 h1:f3vKqSo13fhTYb+JEcXwXefZQE26I1FB5eTSniU67ko= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29/go.mod h1:MzoLFUArKGpGD+ukmPiTPG1X5x4o6M2kq4v2dr1FiEc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 h1:RdwIf/CuUsvJX3RgJagbOyotl/cxoLY4xviKuE7p2GY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29/go.mod h1:71wt8W2EgswdZy9Mf9KNnzxZ3TiZlv4caKghPktDOkA= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 h1:VTGy885W5DKBxWRUJbym9hytNaYzsyaPkCHGRRMAOhU= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30/go.mod h1:AS0HycUvJRFvTt613AYDOgO2jzw+00cVSMny8XB3yMY= +github.com/aws/aws-sdk-go-v2 v1.43.2 h1:cl+IXwWb3qazClUcm08tGSsB6OiuV83JVJO9B0jQcPc= +github.com/aws/aws-sdk-go-v2 v1.43.2/go.mod h1:WEzLKBh/mEjXvx1FtQMWgSxMSTVqxQzjkRtk5fa3wkg= +github.com/aws/aws-sdk-go-v2/config v1.32.33 h1:M1m/Q6f0OKDEDGwhiNOqx1OjTdrewe3v+GDbHmKczWk= +github.com/aws/aws-sdk-go-v2/config v1.32.33/go.mod h1:fGj1iQj2QpIZzp7jE4aQQ+71TE8cd4z9K4+xCd6EqmE= +github.com/aws/aws-sdk-go-v2/credentials v1.19.32 h1:eNE0JnIblBo1NCvd3tqEYuZz9XDefn69R74CHd3nT7U= +github.com/aws/aws-sdk-go-v2/credentials v1.19.32/go.mod h1:yYJu+6tqKUYZuJSYcpSGjz/6sV/SUaAaKIufnWKx2OU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.33 h1:MobhiR6KIerWxmO74Zit5I3379+mSc2DOdZ3DeRFB9w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.33/go.mod h1:xu02847OdZfNr/jAfZpHtyRk0b3v4d0kaoxNHxZGG/w= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.33 h1:HAp1wLFZzch054uh3FK7rcVYg4v7J2FxVf3h3IGNZas= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.33/go.mod h1:mJk5fmqnF+WUlMdPG37pR2Fh3oh6r8F6ZGUgPKvzu0c= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.33 h1:0YA0aCKgsJyno6xkFfaIgjE3/wK08+Qxo9nQfe1UrWM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.33/go.mod h1:UZqj4WIdTH+ga8Y/DgpAuy/8cGjM3h7gDCliJYGg2SE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.34 h1:HQYnjFnXpX8EbPW5M1QT8mXzesRPwly0HEPTcFlS02Y= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.34/go.mod h1:tGzj56niKYZBbDIRhwPGDqrULzmWv5b6uBQGqyNaFZw= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.59.1 h1:GaRPmlTeDxjnp6XipIV4b69PJalB59DcMMClFJeHeMw= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.59.1/go.mod h1:jLkDwIDBkCIpiENQhAOjAR2L9jwj56mZgVEvuro4gUE= github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0 h1:RHJSkRXDGkAKrV4CTEsZsZkOmSpxXKO4aKx4rXd94K4= github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY= github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5 h1:5nkhwt0d/gjuT3AQ2LUK0aFRNB3MGlzB2elqy/ZsKP4= github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5/go.mod h1:LQMlcWBoiFVD3vUVEz42ST0yTiaDujv2dRE6sXt1yPE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 h1:ZD2+BSw9vFsNlKYIasSNt3uDbjqqXIBcM13UJv/Lx2k= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12/go.mod h1:Ms4zlcVBbXbiP7EVLhl+lgjvA/a7YphqQ3Ih3174EmI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.14 h1:SA43nfaY7+1jjMNIc2ywu99JLJLButtIdLP6j+bT870= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.14/go.mod h1:Du3llKcwbQvHsTXSLzTOGQz0DTDBMEzdg7DAGu7inrY= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.12.6 h1:Bs2OwYq0HBgHYwfGmUwYIPtTNaGMGAHkRje4jmW2VoI= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.12.6/go.mod h1:OTctu4cW8t7/TRlTKPLT6akzyOkfceMWhtEHqtYDIQQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 h1:DRebniUGZ2MqiiIVmQJ04vIXr918hubdHMnarSLEWyU= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29/go.mod h1:LfRkPCD8YHDM2E5eTkos2UpwYeZnBcVarTa8L59bJHA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.33 h1:mqI7OrxN/DUH85F5OqVn3cIfuZ3+HVcebUm2N8mLlgQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.33/go.mod h1:eZ5jdEpvaaOU8nWWE4cTAJETSEA5FZoWxvNRao4piHY= github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.10 h1:MQuZZ6Tq1qQabPlkVxrCMdyVl70Ogl4AERZKo+y9Wzo= github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.10/go.mod h1:U5C3JME1ibKESmpzBAqlRpTYZfVbTqrb5ICJm+sVVd8= -github.com/aws/aws-sdk-go-v2/service/signin v1.2.1 h1:BeJmkm5YOZs6lGRGcNoIuLSoTTtGLLCEqlSiRKYodfM= -github.com/aws/aws-sdk-go-v2/service/signin v1.2.1/go.mod h1:LxYujSTLPRlp2vTtcUO/+1ilrew8ytt6SvQyOgejzFQ= -github.com/aws/aws-sdk-go-v2/service/sns v1.39.17 h1:synXIPC/L4Cc489P0XDcrVJzHSLj7krKRpFLalbGM2k= -github.com/aws/aws-sdk-go-v2/service/sns v1.39.17/go.mod h1:4ABZnI23uNK37waIjGwkubnCwGhepIt9x1GvASfljJA= -github.com/aws/aws-sdk-go-v2/service/sso v1.31.4 h1:i465b/3c7xJd++pobNIDOggouekCuiWOnB0goQJy+94= -github.com/aws/aws-sdk-go-v2/service/sso v1.31.4/go.mod h1:Lk7PlmoTYryQmyBG0EXqj5BcUbj3whXdU2s3yGI3EAc= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.7 h1:xbmJAnBbyYPkTzoCNCF/bpJ6ymQHRdXX1vquYfDIGYk= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.7/go.mod h1:Q5N6icH+KJZDLh+ESNwzdv6cZ6vLFF/egy3IOxWhmz4= -github.com/aws/aws-sdk-go-v2/service/sts v1.43.4 h1:Np0vmL7op0Zs5xGacYMMX3v5O5pvZ46xhb5LwDgPj8M= -github.com/aws/aws-sdk-go-v2/service/sts v1.43.4/go.mod h1:r8wkDOuLaaMFqFiYAb8dGY2A3gJCOujMc6CFOVC4Zhc= -github.com/aws/smithy-go v1.27.1 h1:4T340VFndXtADGF52gYa1POyL7s9E4Z1OeZ1hCscIw8= -github.com/aws/smithy-go v1.27.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/aws-sdk-go-v2/service/signin v1.5.2 h1:EjI1CZzDcBxPkTa3j1BdtIrUDbqnOGssFMeyUS+6W0I= +github.com/aws/aws-sdk-go-v2/service/signin v1.5.2/go.mod h1:vN3eb5H8MEAZ4dx0F5Wc9LT8eb3eW7bZZ5BjGJdbw9k= +github.com/aws/aws-sdk-go-v2/service/sns v1.42.2 h1:sG8S3cdfG2+Shse+h8YWTKTrv4sj+48yASyin+YoQHM= +github.com/aws/aws-sdk-go-v2/service/sns v1.42.2/go.mod h1:EHECMrJFM/36j9vLqYP/ksa1js/0Kp5RIzxMEX5Yz1g= +github.com/aws/aws-sdk-go-v2/service/sso v1.33.2 h1:zMP1FDFE08L7sM5f1QqkH/ZgKKg8Uc0Dz7KhSSYqWkw= +github.com/aws/aws-sdk-go-v2/service/sso v1.33.2/go.mod h1:0LoIZSUKjdo2BleHfT1hv/jlD33LQS00IrBlzoUsoUQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.2 h1:9eTqUYl+SyVmaRPMyBXSO9wwqC6TRwZB82pKENK2hdQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.2/go.mod h1:DThweuz22kiLc7lGHop5vQ9c3bx5W6Azs/YqSHa2fu8= +github.com/aws/aws-sdk-go-v2/service/sts v1.45.2 h1:EJd8vZO3E8SE6nmPqxuxlQ1NeSb8as50sf6eGdV4Saw= +github.com/aws/aws-sdk-go-v2/service/sts v1.45.2/go.mod h1:OgpPvKzsO2Ranjpli/20djMkg6UrV5mw4W3pZpq1Mqo= +github.com/aws/smithy-go v1.27.5 h1:d1ro7KpYOYwP6m73YFa+Kc/A130VsAdX68SpsJwARMM= +github.com/aws/smithy-go v1.27.5/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/axiomhq/hyperloglog v0.2.6 h1:sRhvvF3RIXWQgAXaTphLp4yJiX4S0IN3MWTaAgZoRJw= github.com/axiomhq/hyperloglog v0.2.6/go.mod h1:YjX/dQqCR/7QYX0g8mu8UZAjpIenz1FKM71UEsjFoTo= github.com/baidubce/bce-sdk-go v0.9.230 h1:HzELBKiD7QAgYqZ1qHZexoI2A3Lo/6zYGQFvcUbS5cA= @@ -218,8 +218,6 @@ github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf h1:TqhNAT4zKbT github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c= github.com/caio/go-tdigest v3.1.0+incompatible h1:uoVMJ3Q5lXmVLCCqaMGHLBWnbGoN6Lpu7OAUPR60cds= github.com/caio/go-tdigest v3.1.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -252,8 +250,6 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= -github.com/coder/quartz v0.3.1 h1:JMJLj4Xj4NLSrUC1R/g/Hn0y9fkyOvb8tf6P0j+kPn0= -github.com/coder/quartz v0.3.1/go.mod h1:BgE7DOj/8NfvRgvKw0jPLDQH/2Lya2kxcTaNJ8X0rZk= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -344,8 +340,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.10.0 h1:Xx/5Ydg9CeBDX/wi4VJqStNtohYjitZhhlHt4h3St1M= -github.com/fsnotify/fsnotify v1.10.0/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fullstorydev/emulators/storage v0.0.0-20240401123056-edc69752f474 h1:TufioMBjkJ6/Oqmlye/ReuxHFS35HyLmypj/BNy/8GY= github.com/fullstorydev/emulators/storage v0.0.0-20240401123056-edc69752f474/go.mod h1:PQwxF4UU8wuL+srGxr3BOhIW5zXqgucwVlO/nPZLsxw= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= @@ -373,59 +369,56 @@ github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.25.0 h1:EnjAq1yO8wEO9HbPmY8vLPEIkdZuuFhCAKBPvCB7bCs= -github.com/go-openapi/analysis v0.25.0/go.mod h1:5WFTRE43WLkPG9r9OtlMfqkkvUTYLVVCIxLlEpyF8kE= +github.com/go-openapi/analysis v0.25.5 h1:xPYEvTb90o1y0epuiOPAoG4QqahjP3cdp5xNlHeKJRI= +github.com/go-openapi/analysis v0.25.5/go.mod h1:d3UGtQC5uq5Kqqqis2VH09Km/v3vwsWrYkbp4gdm+Rc= github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I= github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.22.5 h1:8on/0Yp4uTb9f4XvTrM2+1CPrV05QPZXu+rvu2o9jcA= -github.com/go-openapi/jsonpointer v0.22.5/go.mod h1:gyUR3sCvGSWchA2sUBJGluYMbe1zazrYWIkWPjjMUY0= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= -github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= -github.com/go-openapi/loads v0.23.3 h1:g5Xap1JfwKkUnZdn+S0L3SzBDpcTIYzZ5Qaag0YDkKQ= -github.com/go-openapi/loads v0.23.3/go.mod h1:NOH07zLajXo8y55hom0omlHWDVVvCwBM/S+csCK8LqA= -github.com/go-openapi/runtime v0.29.4 h1:k2lDxrGoSAJRdhFG2tONKMpkizY/4X1cciSdtzk4Jjo= -github.com/go-openapi/runtime v0.29.4/go.mod h1:K0k/2raY6oqXJnZAgWJB2i/12QKrhUKpZcH4PfV9P18= -github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.26.4 h1:yI6IAEfcWow459BD5UzFY430KUwXZwBHrYusPFkhWlc= -github.com/go-openapi/strfmt v0.26.4/go.mod h1:hNJi6nb5ETD6i7A1yRo03M9S6ZoTPPoWff1iUexmfUc= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.26.0 h1:GVDXCmfvhfu1BxiHo8/FA+BbKmhecHnG3varjON5/RI= -github.com/go-openapi/swag v0.26.0/go.mod h1:82g3193sZJRbocs7bNCqGfIgq8pkuwVwCfhKIRlEQF0= -github.com/go-openapi/swag/cmdutils v0.26.0 h1:iowihOcvq7y4egO8cOq0dmfohz6wfeQ63U1EnuhO2TU= -github.com/go-openapi/swag/cmdutils v0.26.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= -github.com/go-openapi/swag/conv v0.27.0 h1:EKOH4feXrvdo8DbSsXSAqRT8fz1epEnS5O2IfXUOzE8= -github.com/go-openapi/swag/conv v0.27.0/go.mod h1:pfiv0uKQTbaGApk8Zs/lZV3uSjmSpa2FO1y183YngN8= -github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU= -github.com/go-openapi/swag/fileutils v0.26.0/go.mod h1:0WDJ7lp67eNjPMO50wAWYlKvhOb6CQ37rzR7wrgI8Tc= -github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w= -github.com/go-openapi/swag/jsonname v0.26.0/go.mod h1:urBBR8bZNoDYGr653ynhIx+gTeIz0ARZxHkAPktJK2M= -github.com/go-openapi/swag/jsonutils v0.27.0 h1:VYtd9jEQYeU4j8q5vdn5KWotF4vKywhGdMBrALtAsfE= -github.com/go-openapi/swag/jsonutils v0.27.0/go.mod h1:U7pb8AGuwhok3RDicHeHwSG4L3PXSq6PAL98Aon632g= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0 h1:+d7C7Ur/SsGg/UZ9G0JEovnfRqtMNZCJQGKc2h/ojoE= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY= -github.com/go-openapi/swag/loading v0.26.0 h1:Apg6zaKhCJurpJer0DCxq99qwmhFddBhaMX7kilDcko= -github.com/go-openapi/swag/loading v0.26.0/go.mod h1:dBxQ/6V2uBaAQdevN18VELE6xSpJWZxLX4txe12JwDg= -github.com/go-openapi/swag/mangling v0.26.0 h1:Du2YC4YLA/Y5m/YKQd7AnY5qq0wRKSFZTTt8ktFaXcQ= -github.com/go-openapi/swag/mangling v0.26.0/go.mod h1:jifS7W9vbg+pw63bT+GI53otluMQL3CeemuyCHKwVx0= -github.com/go-openapi/swag/netutils v0.26.0 h1:CmZp+ZT7HrmFwrC3GdGsXBq2+42T1bjKBapcqVpIs3c= -github.com/go-openapi/swag/netutils v0.26.0/go.mod h1:5iK+Ok3ZohWWex1C50BFTPexi03UaPwjW4Oj8kgrpwo= -github.com/go-openapi/swag/stringutils v0.26.0 h1:qZQngLxs5s7SLijc3N2ZO+fUq2o8LjuWAASSrJuh+xg= -github.com/go-openapi/swag/stringutils v0.26.0/go.mod h1:sWn5uY+QIIspwPhvgnqJsH8xqFT2ZbYcvbcFanRyhFE= -github.com/go-openapi/swag/typeutils v0.27.0 h1:aCf4MSGo8NLwZP8Q6t32DWLJSvl/WwNqgmEG+xJ6v2o= -github.com/go-openapi/swag/typeutils v0.27.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ= -github.com/go-openapi/swag/yamlutils v0.26.0 h1:H7O8l/8NJJQ/oiReEN+oMpnGMyt8G0hl460nRZxhLMQ= -github.com/go-openapi/swag/yamlutils v0.26.0/go.mod h1:1evKEGAtP37Pkwcc7EWMF0hedX0/x3Rkvei2wtG/TbU= +github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= +github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= +github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= +github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= +github.com/go-openapi/loads v0.25.0 h1:74Bc2snfaVlsHzwdQj/3gsA9XJz3daXTJVs+4ZaK7jI= +github.com/go-openapi/loads v0.25.0/go.mod h1:JFBw4SIB9+PTIFHDfcXuSSy5h6aWzjtUCrPYyx3qWU8= +github.com/go-openapi/runtime v0.33.0 h1:Dd3Oj2ig+WH8ckK95l0Wn2V8a4bH/UqWPRZVT0vc8yU= +github.com/go-openapi/runtime v0.33.0/go.mod h1:+rsupH3+TFKqmFysqkmgBOTxpVJV8eV+j9myvvea2Xw= +github.com/go-openapi/runtime/server-middleware v0.33.0 h1:ZFUNyaa2eUs9DhLd6MTe/QRsuxeYn4Lq0C8iAoY13XE= +github.com/go-openapi/runtime/server-middleware v0.33.0/go.mod h1:OQHTBqMGquJShXhPYQ62yAqDMtC1rYpsEwldNWjYKhA= +github.com/go-openapi/spec v0.22.9 h1:/vKIFDcGKp0ktZWGbym/tJEWbk6/XOEmAVU0kqKMH+w= +github.com/go-openapi/spec v0.22.9/go.mod h1:b/mNUYIOQOyIiUzUzXEE8xzyZqf93KvM9hQGP91yfl0= +github.com/go-openapi/strfmt v0.27.0 h1:kbcTeaD9TXuXD0hhMXzuYa1sdTo6+dWGvwjW93E80IM= +github.com/go-openapi/strfmt v0.27.0/go.mod h1:s/qhDqfY72irigXUGJmtgid2Rm+3tnz3k8hZaRmvWYc= +github.com/go-openapi/swag v0.28.0 h1:xkgbOSKj6DZziNpyqRRAOt3GJGtgjgsd2RoyT30VWuw= +github.com/go-openapi/swag v0.28.0/go.mod h1:4qYnT3Cqr1p1VknOdPo70evN4rgQnAg6jwApHyxSGIg= +github.com/go-openapi/swag/cmdutils v0.28.0 h1:7TOeNtkYru1SG8Y34tDh9WBbLsMqGnptuxWiHREPZ4Q= +github.com/go-openapi/swag/cmdutils v0.28.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= +github.com/go-openapi/swag/conv v0.28.0 h1:GtqqbyFe7vR5Y7ehxG9W6/OvrSFdf1OLeTGp40TqxH8= +github.com/go-openapi/swag/conv v0.28.0/go.mod h1:mbUE+mzctnhxi864m0Q07SpN8OowD9JhxmxuYvZZD/k= +github.com/go-openapi/swag/fileutils v0.28.0 h1:Z04XWQD7R8Eq+7GnOrjovBxPPmZzsS4gt2H2GPGIViU= +github.com/go-openapi/swag/fileutils v0.28.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8= +github.com/go-openapi/swag/jsonutils v0.28.0 h1:YIch6FwO7RXzeAnbO8Tu7dWBZeUEH+4nA0HXltVTnv4= +github.com/go-openapi/swag/jsonutils v0.28.0/go.mod h1:CYM3WlTUcagR2ZoHdz54di/cbBqt82tuxuXgAjxw+mg= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0 h1:qV+VVUAx5Oro8WjVWpZeql7YReTKhT4smR4zhcOQZr0= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY= +github.com/go-openapi/swag/loading v0.28.0 h1:td8QZdZC9MIYGGSnSPKShKiK22I2tU5UQvuUhIBPRLU= +github.com/go-openapi/swag/loading v0.28.0/go.mod h1:rXB0QiQX5mMveXEA7ouM4KiiM9jVJe4K6BVbwhD1M4k= +github.com/go-openapi/swag/mangling v0.28.0 h1:pH8eyeNO9SLYsTMWJrurnNfKmDa28XrlA+HePVD53VM= +github.com/go-openapi/swag/mangling v0.28.0/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w= +github.com/go-openapi/swag/netutils v0.28.0 h1:YXN6TALEi2pzts8/8GNm6T61HTAZsieukGZidap989k= +github.com/go-openapi/swag/netutils v0.28.0/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ= +github.com/go-openapi/swag/pools v0.28.0 h1:HPMZWSAfce3rdVTFcjFiCIBtDg9h4x2QlRrHipwhxeU= +github.com/go-openapi/swag/pools v0.28.0/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE= +github.com/go-openapi/swag/stringutils v0.28.0 h1:ixsc9iYgDPubHL/8nSkbnryEHpD2VRlBMLKpQyPXcDU= +github.com/go-openapi/swag/stringutils v0.28.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM= +github.com/go-openapi/swag/typeutils v0.28.0 h1:nRBKSBXjDgf01VDPB3fWeD9nQuhCOVeIYAkUx2tbkyY= +github.com/go-openapi/swag/typeutils v0.28.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ= +github.com/go-openapi/swag/yamlutils v0.28.0 h1:TV3JXH6DS46KUroDtMLAYHGkdWf5VDq3wVWFirmzROY= +github.com/go-openapi/swag/yamlutils v0.28.0/go.mod h1:x0q/yndZHEgk9Rx3DyDqzFUmHy55KTvIZldvF2dTJXs= github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0= github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo= github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug= github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= -github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0= -github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY= +github.com/go-openapi/validate v0.26.1 h1:pZSbvtRO8G2R2FpWTYRn3w8LrsNwbtaVhP2dWiBa0Us= +github.com/go-openapi/validate v0.26.1/go.mod h1:B8UMgXiQiwwQWIbmuROlwJZDPGlikPuh7iHV1vPX9Oo= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= @@ -685,8 +678,8 @@ github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRt github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU= github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= @@ -730,9 +723,6 @@ github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= github.com/linode/linodego v1.63.0 h1:MdjizfXNJDVJU6ggoJmMO5O9h4KGPGivNX0fzrAnstk= github.com/linode/linodego v1.63.0/go.mod h1:GoiwLVuLdBQcAebxAVKVL3mMYUgJZR/puOUSla04xBE= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -751,16 +741,16 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= -github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= -github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= -github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= +github.com/mdlayher/socket v0.6.0 h1:ScZPaAGyO1icQnbFrhPM8mnXyMu9qukC1K4ZoM2IQKU= +github.com/mdlayher/socket v0.6.0/go.mod h1:q7vozUAnxSqnjHc12Fik5yUKIzfZ8ITCfMkhOtE9z18= +github.com/mdlayher/vsock v1.3.0 h1:bqQfZ1OznI03y6YiXp2sze05RVdzLn/zsfjnjd4+ivI= +github.com/mdlayher/vsock v1.3.0/go.mod h1:WsuksavOvwCnV5UqGHUkvAvCy+Dqy81y4goKQTzxxNY= github.com/metalmatze/signal v0.0.0-20210307161603-1c9aa721a97a h1:0usWxe5SGXKQovz3p+BiQ81Jy845xSMu2CWKuXsXuUM= github.com/metalmatze/signal v0.0.0-20210307161603-1c9aa721a97a/go.mod h1:3OETvrxfELvGsU2RoGGWercfeZ4bCL3+SOwzIWtJH/Q= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.69 h1:Kb7Y/1Jo+SG+a2GtfoFUfDkG//csdRPwRLkCsxDG9Sc= -github.com/miekg/dns v1.1.69/go.mod h1:7OyjD9nEba5OkqQ/hB4fy3PIoxafSZJtducccIelz3g= +github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= +github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI= github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= @@ -808,15 +798,14 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncw/swift v1.0.53 h1:luHjjTNtekIEvHg5KdAFIBaH7bWfNkefwFnpDffSIks= github.com/ncw/swift v1.0.53/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= -github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/oklog/ulid/v2 v2.1.2 h1:IEclFb9JNvzYA6MW2SCxbLzcHTVsfqm3PrqGQJH5zec= +github.com/oklog/ulid/v2 v2.1.2/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= @@ -881,16 +870,16 @@ github.com/prometheus-community/parquet-common v0.0.0-20260614025832-5f32460b537 github.com/prometheus-community/parquet-common v0.0.0-20260614025832-5f32460b5373/go.mod h1:gewN7ZuOXJh0X2I57iGHyDLbLvL891P2Ynko2QM5axY= github.com/prometheus-community/prom-label-proxy v0.11.1 h1:jX+m+BQCNM0z3/P6V6jVxbiDKgugvk91SaICD6bVhT4= github.com/prometheus-community/prom-label-proxy v0.11.1/go.mod h1:uTeQW+wZ/VPV1LL3IPfvUE++wR2nPLex+Y4RE38Cpis= -github.com/prometheus/alertmanager v0.33.0 h1:AAVa3wpCsaDxisTUUPXx+1qhnA2mx0f8Cc+smpAtN7w= -github.com/prometheus/alertmanager v0.33.0/go.mod h1:V06Uc8EZ5X5wLOJRGhtXx+EE2LgrinFIADbKWMVm1RY= +github.com/prometheus/alertmanager v0.34.0 h1:z75n0NoypggESmt3HD4JlTXOaOZj1EBz1ACHO4Z6EUk= +github.com/prometheus/alertmanager v0.34.0/go.mod h1:/qF39A6Vb1MMoDM1SxcySobb7wmpBZha8COwULiKUUo= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= -github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU= +github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= github.com/prometheus/client_golang/exp v0.0.0-20251212205219-7ba246a648ca h1:BOxmsLoL2ymn8lXJtorca7N/m+2vDQUDoEtPjf0iAxA= github.com/prometheus/client_golang/exp v0.0.0-20251212205219-7ba246a648ca/go.mod h1:gndBHh3ZdjBozGcGrjUYjN3UJLRS3l2drALtu4lUt+k= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -903,10 +892,10 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.69.0 h1:OA85nJQS/T/MaYh/Q2CcgDKSGWqNIgrBDvDH85CuiNk= -github.com/prometheus/common v0.69.0/go.mod h1:ZzL3f6u94qUxh9p+tJTrF+FvBS1XXbbRAZCQkytAL0Y= -github.com/prometheus/exporter-toolkit v0.16.0 h1:xT/j7L2XKF+VJd6B4fpUw6xWabHrSmsUf6mYmFqyu0s= -github.com/prometheus/exporter-toolkit v0.16.0/go.mod h1:d1EL8Z9674xQe/iWhwP2wDyCEoBPbXVeqDbqAUsgJWY= +github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY= +github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= +github.com/prometheus/exporter-toolkit v0.17.1 h1:psKN4wM7shBL/BxZkDHgm6YZJ3fAVG36+r86An/+7q0= +github.com/prometheus/exporter-toolkit v0.17.1/go.mod h1:dabwPJvxsC5+tsp2iolQrqBWZh+QlISKlYRpj9Hh5xk= github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -914,8 +903,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.21.0 h1:Qh/e6TlBjZf+XLLqNCqFGmCU6Kj/2Bu7kj3oAc0UnXc= -github.com/prometheus/procfs v0.21.0/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= +github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= +github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= github.com/prometheus/prometheus v0.309.1 h1:jutK6eCYDpWdPTUbVbkcQsNCMO9CCkSwjQRMLds4jSo= github.com/prometheus/prometheus v0.309.1/go.mod h1:d+dOGiVhuNDa4MaFXHVdnUBy/CzqlcNTooR8oM1wdTU= github.com/prometheus/sigv4 v0.4.1 h1:EIc3j+8NBea9u1iV6O5ZAN8uvPq2xOIUPcqCTivHuXs= @@ -1010,8 +999,8 @@ github.com/tinylib/msgp v1.6.1/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77ro github.com/tjhop/slog-gokit v0.2.0 h1:tUNkuukDjpswQ2abhsugEobRRxN1aHEW8h4rvwdHMqU= github.com/tjhop/slog-gokit v0.2.0/go.mod h1:yA48zAHvV+Sg4z4VRyeFyFUNNXd3JY5Zg84u3USICq0= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/twmb/franz-go v1.21.2 h1:WrvV/spF48JzcRylqDQy02Vm6V6W4lhtD9Y4BOYNMu4= -github.com/twmb/franz-go v1.21.2/go.mod h1:rfoMTnVk7107fhTGxfEKIHP/e7tPe6oyij/ywzO0czk= +github.com/twmb/franz-go v1.21.5 h1:cVYI2+JTTKSvohhy8bCOleYrS7G79ZBrLVFIJsoHm8M= +github.com/twmb/franz-go v1.21.5/go.mod h1:rfoMTnVk7107fhTGxfEKIHP/e7tPe6oyij/ywzO0czk= github.com/twmb/franz-go/pkg/kfake v0.0.0-20260515175617-8268a5d078c0 h1:YWmvjmcidrKLLgObwU1k7K9KuesdYTV33OTIS0Ltj8o= github.com/twmb/franz-go/pkg/kfake v0.0.0-20260515175617-8268a5d078c0/go.mod h1:9j4VxU2ng6tHgD4lIkNJ5OJ3D6vgPhhIp3tBa7dJgLA= github.com/twmb/franz-go/pkg/kmsg v1.13.1 h1:fG5kItwysTk5UXqVwb64EpQEy3TydF3vYYK21nUQ+bI= @@ -1109,10 +1098,10 @@ go.opentelemetry.io/contrib/detectors/gcp v1.44.0 h1:NmLfL734pJhM0JKaYd2Y28+nY9d go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.68.0 h1:cuXaPAfIoJKsYjBjPSb2nKZEmgM43zVr25l37IxhKME= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.68.0/go.mod h1:BuzhPofpCzlDi/Q/Xjg54M4/3oWqqyDe2Zeq7A2I0QE= -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/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.69.0 h1:MCcYL7J6Vt/X0kjqbMZkekCmwsurbQRbL69vkiye2lk= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.69.0/go.mod h1:3jnStNwSufK+f5ktjL4EPcwtig4rtd81NS70lqHuXl8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI= go.opentelemetry.io/contrib/propagators/autoprop v0.61.0 h1:cxOVDJ30qfzV27G5p9WMtJUB/3cXC0iL+u9EV1fSOws= go.opentelemetry.io/contrib/propagators/autoprop v0.61.0/go.mod h1:Y+xiUbWetg65vAroDZcIzJ5wyPNWRH32EoIV9rIaa0g= go.opentelemetry.io/contrib/propagators/aws v1.44.0 h1:Rtvfd6nTbAF2csjiw41m1DfuqC5TneXs+gB84ZA3gq4= @@ -1131,8 +1120,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 h1:4YsVu3B8+3qtWYYrsUY go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0/go.mod h1:+wnlSn0mD1ADVMe3v9Z/WIaiz6q6gL2J/ejaAmdmv80= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0 h1:qazEJlUOQzhCpzQpFETGby7EdqjI1wsd0W+6Gg1SCTU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0/go.mod h1:fOD2Yefuxixkx3ahVNf0O/PERb6r4OlbxfATVnYvzCo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 h1:lgh3PiVrRUWMLOVSkQicxzZll5NjF1r+AtsX1XRIHw0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0/go.mod h1:5Cnhth3m/AgOeTgE3ex12pPmiu/gGtZit03kSzx9X7s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1xzhKrotaHy3/KXdPhlWARrCgK+eqUY= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw= go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= @@ -1227,8 +1216,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= -golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= +golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1693,7 +1682,6 @@ google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1719,7 +1707,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/integration/e2ecortex/client.go b/integration/e2ecortex/client.go index 92352031bed..9760a6c18e3 100644 --- a/integration/e2ecortex/client.go +++ b/integration/e2ecortex/client.go @@ -683,7 +683,7 @@ func (c *Client) LabelValues(label string, start, end time.Time, matches []strin } // LabelNames gets label names -func (c *Client) LabelNames(start, end time.Time, matchers ...string) ([]string, error) { +func (c *Client) LabelNames(start, end time.Time, matchers ...string) (model.LabelNames, error) { result, _, err := c.querierClient.LabelNames(context.Background(), matchers, start, end) return result, err } diff --git a/integration/getting_started_single_process_config_local_test.go b/integration/getting_started_single_process_config_local_test.go index 92362fc8e47..f146e63b65f 100644 --- a/integration/getting_started_single_process_config_local_test.go +++ b/integration/getting_started_single_process_config_local_test.go @@ -59,7 +59,7 @@ func TestGettingStartedSingleProcessConfigWithFilesystem(t *testing.T) { labelNames, err := c.LabelNames(time.Time{}, time.Time{}) require.NoError(t, err) - require.Equal(t, []string{"__name__", "foo"}, labelNames) + require.Equal(t, model.LabelNames{"__name__", "foo"}, labelNames) // Check that a range query does not return an error to sanity check the queryrange tripperware. _, err = c.QueryRange("series_1", now.Add(-15*time.Minute), now, 15*time.Second) diff --git a/integration/getting_started_single_process_config_test.go b/integration/getting_started_single_process_config_test.go index f65b2ae86c2..b4b44a0a46b 100644 --- a/integration/getting_started_single_process_config_test.go +++ b/integration/getting_started_single_process_config_test.go @@ -72,7 +72,7 @@ func TestGettingStartedSingleProcessConfigWithBlocksStorage(t *testing.T) { labelNames, err := c.LabelNames(time.Time{}, time.Time{}) require.NoError(t, err) - require.Equal(t, []string{"__name__", "foo"}, labelNames) + require.Equal(t, model.LabelNames{"__name__", "foo"}, labelNames) // Check that a range query does not return an error to sanity check the queryrange tripperware. _, err = c.QueryRange("series_1", now.Add(-15*time.Minute), now, 15*time.Second) diff --git a/integration/otlp_test.go b/integration/otlp_test.go index d43259ec01b..f8ac2c322f0 100644 --- a/integration/otlp_test.go +++ b/integration/otlp_test.go @@ -86,7 +86,7 @@ func TestOTLP(t *testing.T) { labelNames, err := c.LabelNames(time.Time{}, time.Time{}) require.NoError(t, err) - require.Equal(t, []string{"__name__", "foo"}, labelNames) + require.Equal(t, model.LabelNames{"__name__", "foo"}, labelNames) metadataResult, err := c.Metadata("series_1_total", "") require.NoError(t, err) @@ -255,15 +255,15 @@ func TestOTLPPromoteResourceAttributesPerTenant(t *testing.T) { labelSet1, err := c1.LabelNames(now.Add(-time.Minute*5), now, "series_1") require.NoError(t, err) - require.Equal(t, labelSet1, []string{"__name__", "attr1", "instance", "job"}) + require.Equal(t, labelSet1, model.LabelNames{"__name__", "attr1", "instance", "job"}) labelSet2, err := c2.LabelNames(now.Add(-time.Minute*5), now, "series_1") require.NoError(t, err) - require.Equal(t, labelSet2, []string{"__name__", "attr1", "attr2", "instance", "job"}) + require.Equal(t, labelSet2, model.LabelNames{"__name__", "attr1", "attr2", "instance", "job"}) labelSet3, err := c3.LabelNames(now.Add(-time.Minute*5), now, "series_1") require.NoError(t, err) - require.Equal(t, labelSet3, []string{"__name__", "attr1", "attr2", "attr3", "instance", "job"}) + require.Equal(t, labelSet3, model.LabelNames{"__name__", "attr1", "attr2", "attr3", "instance", "job"}) } func TestOTLPEnableTypeAndUnitLabels(t *testing.T) { diff --git a/integration/querier_integration_test.go b/integration/querier_integration_test.go index e1d6fef4ffa..1e492603bf1 100644 --- a/integration/querier_integration_test.go +++ b/integration/querier_integration_test.go @@ -51,7 +51,7 @@ func testMetadataQueriesWithBlocksStorage( labelValuesTests []labelValuesTest - labelNames []string + labelNames model.LabelNames }{ "query metadata entirely inside the head range": { from: firstSeriesInIngesterHeadTs, @@ -87,7 +87,7 @@ func testMetadataQueriesWithBlocksStorage( matches: []string{lastSeriesInStorageName}, }, }, - labelNames: []string{labels.MetricName, firstSeriesInIngesterHeadName}, + labelNames: model.LabelNames{labels.MetricName, model.LabelName(firstSeriesInIngesterHeadName)}, }, "query metadata entirely inside the ingester range but outside the head range": { from: lastSeriesInIngesterBlocksTs, @@ -124,7 +124,7 @@ func testMetadataQueriesWithBlocksStorage( matches: []string{firstSeriesInIngesterHeadName}, }, }, - labelNames: []string{labels.MetricName, lastSeriesInIngesterBlocksName}, + labelNames: model.LabelNames{labels.MetricName, model.LabelName(lastSeriesInIngesterBlocksName)}, }, "query metadata partially inside the ingester range": { from: lastSeriesInStorageTs.Add(-blockRangePeriod), @@ -167,7 +167,7 @@ func testMetadataQueriesWithBlocksStorage( matches: []string{lastSeriesInStorageName, lastSeriesInIngesterBlocksName}, }, }, - labelNames: []string{labels.MetricName, lastSeriesInStorageName, lastSeriesInIngesterBlocksName, firstSeriesInIngesterHeadName}, + labelNames: model.LabelNames{labels.MetricName, model.LabelName(lastSeriesInStorageName), model.LabelName(lastSeriesInIngesterBlocksName), model.LabelName(firstSeriesInIngesterHeadName)}, }, "query metadata entirely outside the ingester range should return the head data as well": { from: lastSeriesInStorageTs.Add(-2 * blockRangePeriod), @@ -204,7 +204,7 @@ func testMetadataQueriesWithBlocksStorage( matches: []string{firstSeriesInIngesterHeadName}, }, }, - labelNames: []string{labels.MetricName, lastSeriesInStorageName, firstSeriesInIngesterHeadName}, + labelNames: model.LabelNames{labels.MetricName, model.LabelName(lastSeriesInStorageName), model.LabelName(firstSeriesInIngesterHeadName)}, }, } diff --git a/integration/utf8_test.go b/integration/utf8_test.go index ec17f76517b..a770c6bd8f2 100644 --- a/integration/utf8_test.go +++ b/integration/utf8_test.go @@ -252,7 +252,7 @@ func Test_PushQuery_UTF8(t *testing.T) { end := now.Add(time.Minute * 5) labelNames, err := c.LabelNames(start, end) require.NoError(t, err) - require.Equal(t, []string{"__name__", "job", "test.utf8.metric"}, labelNames) + require.Equal(t, model.LabelNames{"__name__", "job", "test.utf8.metric"}, labelNames) // series series, err := c.Series([]string{`{"test.utf8.metric"="😄"}`}, start, end) diff --git a/pkg/alertmanager/alertmanager.go b/pkg/alertmanager/alertmanager.go index 39d79e13ff0..39e66e9e186 100644 --- a/pkg/alertmanager/alertmanager.go +++ b/pkg/alertmanager/alertmanager.go @@ -413,6 +413,7 @@ func (am *Alertmanager) ApplyConfig(userID string, conf *config.Config, rawCfg s util_log.GoKitLogToSlog(log.With(am.logger, "component", "dispatcher")), eventrecorder.NopRecorder(), am.dispatcherMetrics, + tmpl, ) // Start the inhibitor and dispatcher and wait for each to finish loading diff --git a/pkg/alertmanager/api.go b/pkg/alertmanager/api.go index 5739d3e972b..af950522149 100644 --- a/pkg/alertmanager/api.go +++ b/pkg/alertmanager/api.go @@ -20,6 +20,10 @@ import ( "github.com/prometheus/alertmanager/notify/jira" "github.com/prometheus/alertmanager/notify/mattermost" "github.com/prometheus/alertmanager/notify/msteams" + "github.com/prometheus/alertmanager/notify/msteamsv2" + "github.com/prometheus/alertmanager/notify/opsgenie" + "github.com/prometheus/alertmanager/notify/pagerduty" + "github.com/prometheus/alertmanager/notify/telegram" "github.com/prometheus/alertmanager/notify/webhook" "github.com/prometheus/alertmanager/template" amtracing "github.com/prometheus/alertmanager/tracing" @@ -354,15 +358,15 @@ var configValidators = map[reflect.Type]func(any) error{ reflect.TypeFor[config.GlobalConfig](): func(v any) error { return validateGlobalConfig(v.(config.GlobalConfig)) }, reflect.TypeFor[commoncfg.HTTPClientConfig](): func(v any) error { return validateReceiverHTTPConfig(v.(commoncfg.HTTPClientConfig)) }, reflect.TypeFor[commoncfg.TLSConfig](): func(v any) error { return validateReceiverTLSConfig(v.(commoncfg.TLSConfig)) }, - reflect.TypeFor[config.OpsGenieConfig](): func(v any) error { return validateOpsGenieConfig(v.(config.OpsGenieConfig)) }, + reflect.TypeFor[opsgenie.OpsGenieConfig](): func(v any) error { return validateOpsGenieConfig(v.(opsgenie.OpsGenieConfig)) }, reflect.TypeFor[config.SlackConfig](): func(v any) error { return validateSlackConfig(v.(config.SlackConfig)) }, reflect.TypeFor[config.VictorOpsConfig](): func(v any) error { return validateVictorOpsConfig(v.(config.VictorOpsConfig)) }, - reflect.TypeFor[config.PagerdutyConfig](): func(v any) error { return validatePagerdutyConfig(v.(config.PagerdutyConfig)) }, + reflect.TypeFor[pagerduty.PagerdutyConfig](): func(v any) error { return validatePagerdutyConfig(v.(pagerduty.PagerdutyConfig)) }, reflect.TypeFor[webhook.WebhookConfig](): func(v any) error { return validateWebhookConfig(v.(webhook.WebhookConfig)) }, reflect.TypeFor[config.PushoverConfig](): func(v any) error { return validatePushOverConfig(v.(config.PushoverConfig)) }, - reflect.TypeFor[config.TelegramConfig](): func(v any) error { return validateTelegramConfig(v.(config.TelegramConfig)) }, + reflect.TypeFor[telegram.TelegramConfig](): func(v any) error { return validateTelegramConfig(v.(telegram.TelegramConfig)) }, reflect.TypeFor[msteams.MSTeamsConfig](): func(v any) error { return validateMSTeamsConfig(v.(msteams.MSTeamsConfig)) }, - reflect.TypeFor[config.MSTeamsV2Config](): func(v any) error { return validateMSTeamsV2Config(v.(config.MSTeamsV2Config)) }, + reflect.TypeFor[msteamsv2.MSTeamsV2Config](): func(v any) error { return validateMSTeamsV2Config(v.(msteamsv2.MSTeamsV2Config)) }, reflect.TypeFor[config.RocketchatConfig](): func(v any) error { return validateRocketChatConfig(v.(config.RocketchatConfig)) }, reflect.TypeFor[discord.DiscordConfig](): func(v any) error { return validateDiscordConfig(v.(discord.DiscordConfig)) }, reflect.TypeFor[config.EmailConfig](): func(v any) error { return validateEmailConfig(v.(config.EmailConfig)) }, @@ -555,7 +559,7 @@ func validateGlobalConfig(cfg config.GlobalConfig) error { // validateOpsGenieConfig validates the OpsGenie config and returns an error if it contains // settings not allowed by Cortex. -func validateOpsGenieConfig(cfg config.OpsGenieConfig) error { +func validateOpsGenieConfig(cfg opsgenie.OpsGenieConfig) error { if cfg.APIKeyFile != "" { return errOpsGenieAPIKeyFileNotAllowed } @@ -585,7 +589,7 @@ func validateVictorOpsConfig(cfg config.VictorOpsConfig) error { // validatePagerdutyConfig validates the pager duty config and returns an error if it contains // settings not allowed by Cortex. -func validatePagerdutyConfig(cfg config.PagerdutyConfig) error { +func validatePagerdutyConfig(cfg pagerduty.PagerdutyConfig) error { if cfg.RoutingKeyFile != "" { return errPagerDutyRoutingKeyFileNotAllowed } @@ -622,7 +626,7 @@ func validatePushOverConfig(cfg config.PushoverConfig) error { // validateTelegramConfig validates the Telegram Config and returns an error if it contains // settings not allowed by Cortex. -func validateTelegramConfig(cfg config.TelegramConfig) error { +func validateTelegramConfig(cfg telegram.TelegramConfig) error { if cfg.BotTokenFile != "" { return errTelegramBotTokenFileNotAllowed } @@ -643,7 +647,7 @@ func validateMSTeamsConfig(cfg msteams.MSTeamsConfig) error { // validateMSTeamsV2Config validates the MSTeamsV2 Config and returns an error if it contains // settings not allowed by Cortex. -func validateMSTeamsV2Config(cfg config.MSTeamsV2Config) error { +func validateMSTeamsV2Config(cfg msteamsv2.MSTeamsV2Config) error { if cfg.WebhookURLFile != "" { return errMSTeamsV2WebhookUrlFileNotAllowed } diff --git a/pkg/alertmanager/merger/v2_alert_groups_test.go b/pkg/alertmanager/merger/v2_alert_groups_test.go index 69981534ded..6c4aefc5e67 100644 --- a/pkg/alertmanager/merger/v2_alert_groups_test.go +++ b/pkg/alertmanager/merger/v2_alert_groups_test.go @@ -45,12 +45,12 @@ func TestV2AlertGroups(t *testing.T) { `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.163+02:00",` + `"status":{"inhibitedBy":[],"mutedBy":[],"silencedBy":[],"state":"unprocessed"},` + `"updatedAt":"2021-04-21T07:47:32.165Z","labels":{"group":"group_1","name":"alert_2"}}],` + - `"labels":{"group":"group_1"},"receiver":{"name":"dummy"}},` + + `"labels":{"group":"group_1"},"receiver":{"name":"dummy"},"routeLabels":null},` + `{"alerts":[{"annotations":{},"endsAt":"2021-04-21T10:47:32.165+02:00","fingerprint":"465de60f606461c3",` + `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.165+02:00",` + `"status":{"inhibitedBy":[],"mutedBy":[],"silencedBy":[],"state":"unprocessed"},` + `"updatedAt":"2021-04-21T07:47:32.167Z","labels":{"group":"group_2","name":"alert_3"}}],` + - `"labels":{"group":"group_2"},"receiver":{"name":"dummy"}}]`) + `"labels":{"group":"group_2"},"receiver":{"name":"dummy"},"routeLabels":null}]`) out, err := V2AlertGroups{}.MergeResponses(in) require.NoError(t, err) diff --git a/pkg/alertmanager/ui/app/dist/assets/index-BUvG_Zbo.js.br b/pkg/alertmanager/ui/app/dist/assets/index-BUvG_Zbo.js.br deleted file mode 100644 index b86353762a5..00000000000 Binary files a/pkg/alertmanager/ui/app/dist/assets/index-BUvG_Zbo.js.br and /dev/null differ diff --git a/pkg/alertmanager/ui/app/dist/assets/index-BUvG_Zbo.js.gz b/pkg/alertmanager/ui/app/dist/assets/index-BUvG_Zbo.js.gz deleted file mode 100644 index 5793cfff77a..00000000000 Binary files a/pkg/alertmanager/ui/app/dist/assets/index-BUvG_Zbo.js.gz and /dev/null differ diff --git a/pkg/alertmanager/ui/app/dist/assets/index-aNRKuvMz.js.br b/pkg/alertmanager/ui/app/dist/assets/index-aNRKuvMz.js.br new file mode 100644 index 00000000000..266aeba12ee Binary files /dev/null and b/pkg/alertmanager/ui/app/dist/assets/index-aNRKuvMz.js.br differ diff --git a/pkg/alertmanager/ui/app/dist/assets/index-aNRKuvMz.js.gz b/pkg/alertmanager/ui/app/dist/assets/index-aNRKuvMz.js.gz new file mode 100644 index 00000000000..104320fc384 Binary files /dev/null and b/pkg/alertmanager/ui/app/dist/assets/index-aNRKuvMz.js.gz differ diff --git a/pkg/alertmanager/ui/app/dist/index.html.br b/pkg/alertmanager/ui/app/dist/index.html.br index 471891610fa..a2343bfacac 100644 Binary files a/pkg/alertmanager/ui/app/dist/index.html.br and b/pkg/alertmanager/ui/app/dist/index.html.br differ diff --git a/pkg/alertmanager/ui/app/dist/index.html.gz b/pkg/alertmanager/ui/app/dist/index.html.gz index 652524ea6a6..88069b8f9c3 100644 Binary files a/pkg/alertmanager/ui/app/dist/index.html.gz and b/pkg/alertmanager/ui/app/dist/index.html.gz differ diff --git a/pkg/alertmanager/ui/update-am-ui.sh b/pkg/alertmanager/ui/update-am-ui.sh index c4459244e8a..8906ce106d7 100755 --- a/pkg/alertmanager/ui/update-am-ui.sh +++ b/pkg/alertmanager/ui/update-am-ui.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash # Usage: ./update-am-ui.sh [version] -# Example: ./update-am-ui.sh 0.33.0 +# Example: ./update-am-ui.sh 0.34.0 set -euo pipefail -VERSION="${1:-0.33.0}" +VERSION="${1:-0.34.0}" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TARGET_DIR="${SCRIPT_DIR}/app/dist" TARBALL="alertmanager-web-ui-${VERSION}.tar.gz" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/config.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/config.go index 372b1512487..0183a1222ac 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/aws/config.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/config.go @@ -164,6 +164,14 @@ type Config struct { // the shared config profile attribute request_min_compression_size_bytes RequestMinCompressSizeBytes int64 + // DisableClockSkewCorrection turns off SDK clock skew correction. When set + // the SDK will not adjust request signing timestamps to compensate for + // drift between the client and service clocks. Set to false (enabled) by + // default. This variable is sourced from the environment variable + // AWS_DISABLE_CLOCK_SKEW_CORRECTION or the shared config profile attribute + // disable_clock_skew_correction. + DisableClockSkewCorrection bool + // Controls how a resolved AWS account ID is handled for endpoint routing. AccountIDEndpointMode AccountIDEndpointMode diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go index 46cb77c209d..7222e27d6d0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go @@ -3,4 +3,4 @@ package aws // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.42.0" +const goModuleVersion = "1.43.2" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go index 6d5f0079c2f..3c4f2caecb7 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go @@ -43,7 +43,12 @@ func (r ClientRequestID) HandleBuild(ctx context.Context, in middleware.BuildInp } // RecordResponseTiming records the response timing for the SDK client requests. -type RecordResponseTiming struct{} +type RecordResponseTiming struct { + // DisableClockSkewCorrection suppresses recording of clock skew observed + // from the response, per the Clock Skew Correction SEP. Response timing is + // still recorded. + DisableClockSkewCorrection bool +} // ID is the middleware identifier func (a *RecordResponseTiming) ID() string { @@ -54,14 +59,17 @@ func (a *RecordResponseTiming) ID() string { func (a RecordResponseTiming) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( out middleware.DeserializeOutput, metadata middleware.Metadata, err error, ) { + requestAt := sdk.NowTime() out, metadata, err = next.HandleDeserialize(ctx, in) responseAt := sdk.NowTime() setResponseAt(&metadata, responseAt) var serverTime time.Time + var hasAgeHeader bool switch resp := out.RawResponse.(type) { case *smithyhttp.Response: + hasAgeHeader = len(resp.Header.Get("Age")) > 0 respDateHeader := resp.Header.Get("Date") if len(respDateHeader) == 0 { break @@ -77,14 +85,45 @@ func (a RecordResponseTiming) HandleDeserialize(ctx context.Context, in middlewa setServerTime(&metadata, serverTime) } - if !serverTime.IsZero() { - attemptSkew := serverTime.Sub(responseAt) - setAttemptSkew(&metadata, attemptSkew) + if !a.DisableClockSkewCorrection { + if skew, ok := computeClockSkew(serverTime, requestAt, responseAt, hasAgeHeader); ok { + setAttemptSkew(&metadata, skew) + } } return out, metadata, err } +// maxTrustedRequestDuration bounds how long a request may take before the SDK +// discards the skew measurement derived from its response. A slower round trip +// could only produce a signing failure if it pushed the timestamp outside the +// SigV4 validity window. See the Clock Skew Correction SEP. +const maxTrustedRequestDuration = 15 * time.Minute + +// computeClockSkew derives a clock skew candidate from a response per the Clock +// Skew Correction SEP. It returns ok=false (no candidate) when the Date header +// was absent/unparseable (serverTime zero), the round trip exceeded the maximum +// trusted request duration, or the response was served from a cache (Age +// header present). Otherwise the skew is the difference between the server's +// Date and the midpoint of the request round trip. +func computeClockSkew(serverTime, requestAt, responseAt time.Time, hasAgeHeader bool) (time.Duration, bool) { + if serverTime.IsZero() { + return 0, false + } + + if hasAgeHeader { + return 0, false + } + + elapsed := responseAt.Sub(requestAt) + if elapsed > maxTrustedRequestDuration { + return 0, false + } + + midpoint := requestAt.Add(elapsed / 2) + return serverTime.Sub(midpoint), true +} + type responseAtKey struct{} // GetResponseAt returns the time response was received at. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go b/vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go index ab024de047b..126dcf47bd7 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go @@ -48,6 +48,12 @@ type Attempt struct { // call. ClientSkew *atomic.Int64 + // DisableClockSkewCorrection disables clock skew correction per the Clock + // Skew Correction SEP: observed skew is not applied to the signing + // timestamp, not recorded into ClientSkew, and clock skew error codes are + // not treated as retry candidates. + DisableClockSkewCorrection bool + retryer aws.RetryerV2 requestCloner RequestCloner } @@ -88,7 +94,7 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn out smithymiddle.FinalizeOutput, metadata smithymiddle.Metadata, err error, ) { var attemptClockSkew time.Duration - if r.ClientSkew != nil { + if !r.DisableClockSkewCorrection && r.ClientSkew != nil { attemptClockSkew = time.Duration(r.ClientSkew.Load()) } @@ -159,7 +165,7 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn // this guarantees we are staying on top of the persistent skew value // (either to apply it or to heal it back if the clocks realign) - if r.ClientSkew != nil { + if !r.DisableClockSkewCorrection && r.ClientSkew != nil { if resultSkew, ok := awsmiddle.GetAttemptSkew(metadata); ok { r.ClientSkew.Store(resultSkew.Nanoseconds()) } @@ -245,7 +251,10 @@ func (r *Attempt) handleAttempt( return out, attemptResult, nopRelease, err } - err = wrapAsClockSkew(ctx, err) + if !r.DisableClockSkewCorrection { + candidateSkew, hasCandidateSkew := awsmiddle.GetAttemptSkew(metadata) + err = wrapAsClockSkew(err, candidateSkew, hasCandidateSkew, retryMetadata.AttemptClockSkew) + } //------------------------------ // Is Retryable and Should Retry @@ -316,37 +325,66 @@ func (r *Attempt) handleAttempt( return out, attemptResult, releaseRetryToken, err } -// errors that, if detected when we know there's a clock skew, -// can be retried and have a high chance of success -var possibleSkewCodes = map[string]struct{}{ +// clockSkewCodes are the error codes that may indicate a clock skew problem. +// Per the Clock Skew Correction SEP these are retryable only when the absolute +// skew observed from the response Date header exceeds the detection threshold. +// The SEP does not distinguish "definite" from "possible" skew errors: modern +// services overload a single code (e.g. InvalidSignatureException) for both +// skewed and genuinely malformed signatures, so every code is gated on the +// observed skew. +var clockSkewCodes = map[string]struct{}{ "InvalidSignatureException": {}, "SignatureDoesNotMatch": {}, "AuthFailure": {}, + "RequestTimeTooSkewed": {}, + "AccessDeniedException": {}, } -var definiteSkewCodes = map[string]struct{}{ - "RequestExpired": {}, - "RequestInTheFuture": {}, - "RequestTimeTooSkewed": {}, -} - -// wrapAsClockSkew checks if this error could be related to a clock skew -// error and if so, wrap the error. -func wrapAsClockSkew(ctx context.Context, err error) error { +// wrapAsClockSkew classifies err as a retryable clock skew error when its code +// is a known clock skew code and the signing time diverges from the server +// time by more than the detection threshold. +// +// The signing time is now() + attemptSkew. The server time is now() + +// candidateSkew (derived from the response Date header). The signing error is: +// +// |attemptSkew - candidateSkew| > skewThreshold +// +// This single check covers both fresh skew detection (attemptSkew is zero on +// first attempt, so the error equals |candidateSkew|) and stale offset healing +// (attemptSkew is large but the server and client clocks have realigned, so +// candidateSkew is near zero). +// +// If no candidate was observed (the Date header was absent, unparseable, or +// discarded as untrusted), the error is not treated as clock skew. +func wrapAsClockSkew(err error, candidateSkew time.Duration, hasCandidateSkew bool, attemptSkew time.Duration) error { var v interface{ ErrorCode() string } if !errors.As(err, &v) { return err } - if _, ok := definiteSkewCodes[v.ErrorCode()]; ok { - return &retryableClockSkewError{Err: err} + + if _, ok := clockSkewCodes[v.ErrorCode()]; !ok { + return err } - _, isPossibleSkewCode := possibleSkewCodes[v.ErrorCode()] - if skew := internalcontext.GetAttemptSkewContext(ctx); skew > skewThreshold && isPossibleSkewCode { + + if !hasCandidateSkew { + return err + } + + if absDuration(attemptSkew-candidateSkew) > skewThreshold { return &retryableClockSkewError{Err: err} } + return err } +func absDuration(d time.Duration) time.Duration { + if d < 0 { + return -d + } + + return d +} + // MetricsHeader attaches SDK request metric header for retries to the transport type MetricsHeader struct{} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md index 520b2379b9c..34989cc52c5 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md @@ -1,3 +1,33 @@ +# v1.32.33 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.32.32 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.32.31 (2026-07-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.32.30 (2026-07-13) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.32.29 (2026-07-08.2) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.32.28 (2026-07-06) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.32.27 (2026-07-01) + +* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde +* **Dependency Update**: Updated to the latest SDK module versions + # v1.32.26 (2026-06-29) * **Dependency Update**: Updated to the latest SDK module versions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/config.go b/vendor/github.com/aws/aws-sdk-go-v2/config/config.go index c6a6365a39a..f056bf416ec 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/config.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/config.go @@ -77,6 +77,8 @@ var defaultAWSConfigResolvers = []awsConfigResolver{ // Sets the DisableRequestCompression if present in env var or shared config profile resolveDisableRequestCompression, + // Sets the DisableClockSkewCorrection if present in env var or shared config profile + resolveDisableClockSkewCorrection, // Sets the RequestMinCompressSizeBytes if present in env var or shared config profile resolveRequestMinCompressSizeBytes, diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go b/vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go index f0619ce8548..886aec4c22b 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go @@ -78,6 +78,8 @@ const ( awsDisableRequestCompressionEnv = "AWS_DISABLE_REQUEST_COMPRESSION" awsRequestMinCompressionSizeBytesEnv = "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES" + awsDisableClockSkewCorrectionEnv = "AWS_DISABLE_CLOCK_SKEW_CORRECTION" + awsS3DisableExpressSessionAuthEnv = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH" awsAccountIDEnv = "AWS_ACCOUNT_ID" @@ -293,6 +295,10 @@ type EnvConfig struct { // retrieved from env var AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES RequestMinCompressSizeBytes *int64 + // determine if clock skew correction is disabled, default to false + // retrieved from env var AWS_DISABLE_CLOCK_SKEW_CORRECTION + DisableClockSkewCorrection *bool + // Whether S3Express auth is disabled. // // This will NOT prevent requests from being made to S3Express buckets, it @@ -364,6 +370,9 @@ func NewEnvConfig() (EnvConfig, error) { if err := setInt64PtrFromEnvVal(&cfg.RequestMinCompressSizeBytes, []string{awsRequestMinCompressionSizeBytesEnv}, smithyrequestcompression.MaxRequestMinCompressSizeBytes); err != nil { return cfg, err } + if err := setBoolPtrFromEnvVal(&cfg.DisableClockSkewCorrection, []string{awsDisableClockSkewCorrectionEnv}); err != nil { + return cfg, err + } if err := setEndpointDiscoveryTypeFromEnvVal(&cfg.EnableEndpointDiscovery, []string{awsEnableEndpointDiscoveryEnv}); err != nil { return cfg, err @@ -453,6 +462,13 @@ func (c EnvConfig) getDisableRequestCompression(context.Context) (bool, bool, er return *c.DisableRequestCompression, true, nil } +func (c EnvConfig) getDisableClockSkewCorrection(context.Context) (bool, bool, error) { + if c.DisableClockSkewCorrection == nil { + return false, false, nil + } + return *c.DisableClockSkewCorrection, true, nil +} + func (c EnvConfig) getRequestMinCompressSizeBytes(context.Context) (int64, bool, error) { if c.RequestMinCompressSizeBytes == nil { return 0, false, nil diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go index c92c427c550..054e37f268e 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go @@ -3,4 +3,4 @@ package config // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.32.26" +const goModuleVersion = "1.32.33" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go b/vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go index 843ea6b7d7f..b7b3d8b2050 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go @@ -214,6 +214,9 @@ type LoadOptions struct { // The inclusive min bytes of a request body that could be compressed RequestMinCompressSizeBytes *int64 + // Specifies whether SDK clock skew correction is disabled + DisableClockSkewCorrection *bool + // Whether S3 Express auth is disabled. S3DisableExpressAuth *bool @@ -299,6 +302,14 @@ func (o LoadOptions) getDisableRequestCompression(ctx context.Context) (bool, bo return *o.DisableRequestCompression, true, nil } +// getDisableClockSkewCorrection returns DisableClockSkewCorrection from config's LoadOptions +func (o LoadOptions) getDisableClockSkewCorrection(ctx context.Context) (bool, bool, error) { + if o.DisableClockSkewCorrection == nil { + return false, false, nil + } + return *o.DisableClockSkewCorrection, true, nil +} + // getRequestMinCompressSizeBytes returns RequestMinCompressSizeBytes from config's LoadOptions func (o LoadOptions) getRequestMinCompressSizeBytes(ctx context.Context) (int64, bool, error) { if o.RequestMinCompressSizeBytes == nil { @@ -369,6 +380,18 @@ func WithDisableRequestCompression(DisableRequestCompression *bool) LoadOptionsF } } +// WithDisableClockSkewCorrection is a helper function to construct functional +// options that sets DisableClockSkewCorrection on config's LoadOptions. +func WithDisableClockSkewCorrection(DisableClockSkewCorrection *bool) LoadOptionsFunc { + return func(o *LoadOptions) error { + if DisableClockSkewCorrection == nil { + return nil + } + o.DisableClockSkewCorrection = DisableClockSkewCorrection + return nil + } +} + // WithRequestMinCompressSizeBytes is a helper function to construct functional options // that sets RequestMinCompressSizeBytes on config's LoadOptions. func WithRequestMinCompressSizeBytes(RequestMinCompressSizeBytes *int64) LoadOptionsFunc { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/provider.go b/vendor/github.com/aws/aws-sdk-go-v2/config/provider.go index deabd29c82c..ae298afb60d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/provider.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/provider.go @@ -208,6 +208,23 @@ func getDisableRequestCompression(ctx context.Context, configs configs) (value b return } +// disableClockSkewCorrectionProvider provides access to the DisableClockSkewCorrection +type disableClockSkewCorrectionProvider interface { + getDisableClockSkewCorrection(context.Context) (bool, bool, error) +} + +func getDisableClockSkewCorrection(ctx context.Context, configs configs) (value bool, found bool, err error) { + for _, cfg := range configs { + if p, ok := cfg.(disableClockSkewCorrectionProvider); ok { + value, found, err = p.getDisableClockSkewCorrection(ctx) + if err != nil || found { + break + } + } + } + return +} + // requestMinCompressSizeBytesProvider provides access to the MinCompressSizeBytes type requestMinCompressSizeBytesProvider interface { getRequestMinCompressSizeBytes(context.Context) (int64, bool, error) diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go b/vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go index b6796fc87e4..a2c56dc625b 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go @@ -151,6 +151,18 @@ func resolveDisableRequestCompression(ctx context.Context, cfg *aws.Config, conf return nil } +// resolveDisableClockSkewCorrection extracts the DisableClockSkewCorrection from +// the configs slice's SharedConfig or EnvConfig +func resolveDisableClockSkewCorrection(ctx context.Context, cfg *aws.Config, configs configs) error { + disable, _, err := getDisableClockSkewCorrection(ctx, configs) + if err != nil { + return err + } + + cfg.DisableClockSkewCorrection = disable + return nil +} + // resolveRequestMinCompressSizeBytes extracts the RequestMinCompressSizeBytes from the configs slice's // SharedConfig or EnvConfig func resolveRequestMinCompressSizeBytes(ctx context.Context, cfg *aws.Config, configs configs) error { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go b/vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go index 5b251f54f57..40b6daf3cfb 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go @@ -113,6 +113,8 @@ const ( disableRequestCompression = "disable_request_compression" requestMinCompressionSizeBytes = "request_min_compression_size_bytes" + disableClockSkewCorrection = "disable_clock_skew_correction" + s3DisableExpressSessionAuthKey = "s3_disable_express_session_auth" accountIDKey = "aws_account_id" @@ -346,6 +348,10 @@ type SharedConfig struct { // retrieved from config file's profile field request_min_compression_size_bytes RequestMinCompressSizeBytes *int64 + // determine if clock skew correction is disabled, default to false + // retrieved from config file's profile field disable_clock_skew_correction + DisableClockSkewCorrection *bool + // Whether S3Express auth is disabled. // // This will NOT prevent requests from being made to S3Express buckets, it @@ -1149,6 +1155,9 @@ func (c *SharedConfig) setFromIniSection(profile string, section ini.Section) er if err := updateDisableRequestCompression(&c.DisableRequestCompression, section, disableRequestCompression); err != nil { return fmt.Errorf("failed to load %s from shared config, %w", disableRequestCompression, err) } + if err := updateDisableRequestCompression(&c.DisableClockSkewCorrection, section, disableClockSkewCorrection); err != nil { + return fmt.Errorf("failed to load %s from shared config, %w", disableClockSkewCorrection, err) + } if err := updateRequestMinCompressSizeBytes(&c.RequestMinCompressSizeBytes, section, requestMinCompressionSizeBytes); err != nil { return fmt.Errorf("failed to load %s from shared config, %w", requestMinCompressionSizeBytes, err) } @@ -1292,6 +1301,13 @@ func (c SharedConfig) getDisableRequestCompression(ctx context.Context) (bool, b return *c.DisableRequestCompression, true, nil } +func (c SharedConfig) getDisableClockSkewCorrection(ctx context.Context) (bool, bool, error) { + if c.DisableClockSkewCorrection == nil { + return false, false, nil + } + return *c.DisableClockSkewCorrection, true, nil +} + func (c SharedConfig) getAccountIDEndpointMode(ctx context.Context) (aws.AccountIDEndpointMode, bool, error) { return c.AccountIDEndpointMode, len(c.AccountIDEndpointMode) > 0, nil } diff --git a/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md index c348b8e13f4..d69df4c866b 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md @@ -1,3 +1,33 @@ +# v1.19.32 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.19.31 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.19.30 (2026-07-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.19.29 (2026-07-13) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.19.28 (2026-07-08.2) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.19.27 (2026-07-06) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.19.26 (2026-07-01) + +* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde +* **Dependency Update**: Updated to the latest SDK module versions + # v1.19.25 (2026-06-29) * **Dependency Update**: Updated to the latest SDK module versions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go index 084ac978f96..fdbe8424743 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go @@ -3,4 +3,4 @@ package credentials // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.19.25" +const goModuleVersion = "1.19.32" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md index a2f7103a97d..96bca6c3af7 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md @@ -1,3 +1,20 @@ +# v1.18.33 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.18.32 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.18.31 (2026-07-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.18.30 (2026-07-01) + +* **Dependency Update**: Updated to the latest SDK module versions + # v1.18.29 (2026-06-08) * **Dependency Update**: Updated to the latest SDK module versions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go index 64d469b041d..83e751954f0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go @@ -3,4 +3,4 @@ package imds // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.18.29" +const goModuleVersion = "1.18.33" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md index 26f507f8b12..afcd57dd3ff 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md @@ -1,3 +1,20 @@ +# v1.4.33 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.32 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.31 (2026-07-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.30 (2026-07-01) + +* **Dependency Update**: Updated to the latest SDK module versions + # v1.4.29 (2026-06-08) * **Dependency Update**: Updated to the latest SDK module versions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go index 851fed2b3ee..f38ccca23f0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go @@ -3,4 +3,4 @@ package configsources // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.4.29" +const goModuleVersion = "1.4.33" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md index 508593b45a8..ae09aa2d065 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md @@ -1,3 +1,20 @@ +# v2.7.33 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v2.7.32 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v2.7.31 (2026-07-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v2.7.30 (2026-07-01) + +* **Dependency Update**: Updated to the latest SDK module versions + # v2.7.29 (2026-06-08) * **Dependency Update**: Updated to the latest SDK module versions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go index 1c161a0a732..98755086c5a 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go @@ -3,4 +3,4 @@ package endpoints // goModuleVersion is the tagged release for this module -const goModuleVersion = "2.7.29" +const goModuleVersion = "2.7.33" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md index 554f43b5e67..19ff9fc6816 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md @@ -1,3 +1,20 @@ +# v1.4.34 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.33 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.32 (2026-07-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.31 (2026-07-01) + +* **Dependency Update**: Updated to the latest SDK module versions + # v1.4.30 (2026-06-08) * **Dependency Update**: Updated to the latest SDK module versions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go index 2703ec797e3..1eb67f426ae 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go @@ -3,4 +3,4 @@ package v4a // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.4.30" +const goModuleVersion = "1.4.34" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md index 2fb0269e710..44b20890073 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md @@ -1,3 +1,11 @@ +# v1.13.14 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. + +# v1.13.13 (2026-07-01) + +* No change notes available for this release. + # v1.13.12 (2026-06-04) * **Dependency Update**: Update to smithy-go v1.27.1 to fix several union-related deserialization bugs in schema-serde-enabled services. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go index b769e842733..2898c5e5253 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go @@ -3,4 +3,4 @@ package acceptencoding // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.13.12" +const goModuleVersion = "1.13.14" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md index 2a082b44f71..90dcc45c999 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md @@ -1,3 +1,20 @@ +# v1.13.33 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.13.32 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.13.31 (2026-07-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.13.30 (2026-07-01) + +* **Dependency Update**: Updated to the latest SDK module versions + # v1.13.29 (2026-06-08) * **Dependency Update**: Updated to the latest SDK module versions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go index 84b406a7846..8a073d2487c 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go @@ -3,4 +3,4 @@ package presignedurl // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.13.29" +const goModuleVersion = "1.13.33" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/CHANGELOG.md index cf926f5bc5a..561b01cb7c7 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/CHANGELOG.md @@ -1,3 +1,34 @@ +# v1.5.2 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.5.1 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.5.0 (2026-07-21) + +* **Feature**: Add an option to clients to disable clock skew +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.1 (2026-07-13) + +* No change notes available for this release. + +# v1.4.0 (2026-07-08.2) + +* **Feature**: Adds support for OAuth 2.0 token operations in AWS Sign-In, CreateOAuth2TokenWithIAM (client credentials flow), IntrospectOAuth2TokenWithIAM (token inspection), and RevokeOAuth2TokenWithIAM (token revocation). + +# v1.3.0 (2026-07-06) + +* **Feature**: Add request serialization snapshot tests. + +# v1.2.2 (2026-07-01) + +* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde +* **Dependency Update**: Updated to the latest SDK module versions + # v1.2.1 (2026-06-29) * No change notes available for this release. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_client.go index 545b8f1066b..2094f01d271 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_client.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_client.go @@ -487,16 +487,17 @@ func setResolvedDefaultsMode(o *Options) { // NewFromConfig returns a new client from the provided config. func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client { opts := Options{ - Region: cfg.Region, - DefaultsMode: cfg.DefaultsMode, - RuntimeEnvironment: cfg.RuntimeEnvironment, - HTTPClient: cfg.HTTPClient, - Credentials: cfg.Credentials, - APIOptions: cfg.APIOptions, - Logger: cfg.Logger, - ClientLogMode: cfg.ClientLogMode, - AppID: cfg.AppID, - AuthSchemePreference: cfg.AuthSchemePreference, + Region: cfg.Region, + DefaultsMode: cfg.DefaultsMode, + RuntimeEnvironment: cfg.RuntimeEnvironment, + HTTPClient: cfg.HTTPClient, + Credentials: cfg.Credentials, + APIOptions: cfg.APIOptions, + Logger: cfg.Logger, + ClientLogMode: cfg.ClientLogMode, + AppID: cfg.AppID, + DisableClockSkewCorrection: cfg.DisableClockSkewCorrection, + AuthSchemePreference: cfg.AuthSchemePreference, } resolveAWSRetryerProvider(cfg, &opts) resolveAWSRetryMaxAttempts(cfg, &opts) @@ -693,8 +694,10 @@ func addRawResponseToMetadata(stack *middleware.Stack) error { return stack.Deserialize.Add(&awsmiddleware.AddRawResponse{}, middleware.Before) } -func addRecordResponseTiming(stack *middleware.Stack) error { - return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{}, middleware.After) +func addRecordResponseTiming(stack *middleware.Stack, options Options) error { + return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{ + DisableClockSkewCorrection: options.DisableClockSkewCorrection, + }, middleware.After) } func addSpanRetryLoop(stack *middleware.Stack, options Options) error { @@ -772,6 +775,7 @@ func addRetry(stack *middleware.Stack, o Options, c *Client) error { m.LogAttempts = o.ClientLogMode.IsRetries() m.OperationMeter = o.MeterProvider.Meter("github.com/aws/aws-sdk-go-v2/service/signin") m.ClientSkew = c.timeOffset + m.DisableClockSkewCorrection = o.DisableClockSkewCorrection }) if err := stack.Finalize.Insert(attempt, "ResolveAuthScheme", middleware.Before); err != nil { return err diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2Token.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2Token.go index 415f9a2b4d5..00bec7fb7ea 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2Token.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2Token.go @@ -126,7 +126,7 @@ func (c *Client) addOperationCreateOAuth2TokenMiddlewares(stack *middleware.Stac if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2TokenWithIAM.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2TokenWithIAM.go new file mode 100644 index 00000000000..f66701cd3db --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2TokenWithIAM.go @@ -0,0 +1,134 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package signin + +import ( + "context" + "github.com/aws/smithy-go/middleware" + "github.com/aws/smithy-go/ptr" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +// Grants permission to exchange client credentials for an OAuth 2.0 access token +// scoped to a resource that can be used to access AWS services from applications +func (c *Client) CreateOAuth2TokenWithIAM(ctx context.Context, params *CreateOAuth2TokenWithIAMInput, optFns ...func(*Options)) (*CreateOAuth2TokenWithIAMOutput, error) { + if params == nil { + params = &CreateOAuth2TokenWithIAMInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "CreateOAuth2TokenWithIAM", params, optFns, c.addOperationCreateOAuth2TokenWithIAMMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*CreateOAuth2TokenWithIAMOutput) + out.ResultMetadata = metadata + return out, nil +} + +// Input structure for CreateOAuth2TokenWithIAM operation +type CreateOAuth2TokenWithIAMInput struct { + + // OAuth 2.0 grant type. Must be "client_credentials". + // + // This member is required. + GrantType *string + + // The OAuth resource for which the access token is requested. Example: + // "aws-mcp.amazonaws.com". + // + // This member is required. + Resource *string + + noSmithyDocumentSerde +} + +func (in *CreateOAuth2TokenWithIAMInput) bindEndpointParams(p *EndpointParameters) { + + p.IsOAuthEndpoint = ptr.Bool(true) +} + +// Output structure for CreateOAuth2TokenWithIAM operation +// +// Contains the JWT access token, token type, and expiration per RFC 6749 §5.1. +type CreateOAuth2TokenWithIAMOutput struct { + + // JWT access token containing principal identity, resource scope, and session + // metadata + // + // This member is required. + AccessToken *string + + // Token lifetime in seconds. Value is the minimum of session validity and 1 hour. + // + // This member is required. + ExpiresIn *int32 + + // Always "Bearer" per OAuth 2.1 specification + // + // This member is required. + TokenType *string + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationCreateOAuth2TokenWithIAMMiddlewares(stack *middleware.Stack, options Options) (err error) { + err = stack.Serialize.Add(&awsRestjson1_serializeOpCreateOAuth2TokenWithIAM{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsRestjson1_deserializeOpCreateOAuth2TokenWithIAM{}, middleware.After) + if err != nil { + return err + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addComputeContentLength(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addComputePayloadSHA256(stack); err != nil { + return err + } + if err = addRecordResponseTiming(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addCredentialSource(stack, options); err != nil { + return err + } + if err = addOpCreateOAuth2TokenWithIAMValidationMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "CreateOAuth2TokenWithIAM"), middleware.Before); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + if err = addInterceptors(stack, options); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteConsoleAuthorizationConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteConsoleAuthorizationConfiguration.go index a9c42942acb..749157c227a 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteConsoleAuthorizationConfiguration.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteConsoleAuthorizationConfiguration.go @@ -85,7 +85,7 @@ func (c *Client) addOperationDeleteConsoleAuthorizationConfigurationMiddlewares( if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteResourcePermissionStatement.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteResourcePermissionStatement.go index add06008dbf..d76325ff805 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteResourcePermissionStatement.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteResourcePermissionStatement.go @@ -75,7 +75,7 @@ func (c *Client) addOperationDeleteResourcePermissionStatementMiddlewares(stack if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetConsoleAuthorizationConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetConsoleAuthorizationConfiguration.go index 2def43d98e5..74a927da1bf 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetConsoleAuthorizationConfiguration.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetConsoleAuthorizationConfiguration.go @@ -85,7 +85,7 @@ func (c *Client) addOperationGetConsoleAuthorizationConfigurationMiddlewares(sta if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetResourcePolicy.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetResourcePolicy.go index 9b571203c5d..4ee0d496ad0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetResourcePolicy.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetResourcePolicy.go @@ -72,7 +72,7 @@ func (c *Client) addOperationGetResourcePolicyMiddlewares(stack *middleware.Stac if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_IntrospectOAuth2TokenWithIAM.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_IntrospectOAuth2TokenWithIAM.go new file mode 100644 index 00000000000..610390995d6 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_IntrospectOAuth2TokenWithIAM.go @@ -0,0 +1,184 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package signin + +import ( + "context" + "github.com/aws/smithy-go/middleware" + "github.com/aws/smithy-go/ptr" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +// Grants permission to inspect the metadata and state of an OAuth 2.0 access +// token or refresh token +// +// Implements RFC 7662 OAuth 2.0 Token Introspection over a SigV4-authenticated +// endpoint. Inspects the metadata of an access_token or refresh_token issued by +// AWS Sign-In and returns the claims associated with it. +// +// Inactive token semantics (RFC 7662 §2.2): when the supplied token is unknown, +// expired, revoked, malformed, or owned by a different account, the response body +// is exactly { "active": false } with all other claims omitted. +func (c *Client) IntrospectOAuth2TokenWithIAM(ctx context.Context, params *IntrospectOAuth2TokenWithIAMInput, optFns ...func(*Options)) (*IntrospectOAuth2TokenWithIAMOutput, error) { + if params == nil { + params = &IntrospectOAuth2TokenWithIAMInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "IntrospectOAuth2TokenWithIAM", params, optFns, c.addOperationIntrospectOAuth2TokenWithIAMMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*IntrospectOAuth2TokenWithIAMOutput) + out.ResultMetadata = metadata + return out, nil +} + +// Input structure for IntrospectOAuth2TokenWithIAM operation +// +// RFC 7662 §2.1 introspection request. Contains the token to inspect and an +// optional hint about the token's type. +type IntrospectOAuth2TokenWithIAMInput struct { + + // The string value of the token to introspect. May be either an access_token or a + // refresh_token issued by AWS Sign-In. + // + // This member is required. + Token *string + + // Optional hint about the type of the token submitted for introspection. The + // server uses this hint to optimize lookup, but still falls back to the other + // token type on miss. Allowed values: access_token, refresh_token. + TokenTypeHint *string + + noSmithyDocumentSerde +} + +func (in *IntrospectOAuth2TokenWithIAMInput) bindEndpointParams(p *EndpointParameters) { + + p.IsOAuthEndpoint = ptr.Bool(true) +} + +// Output structure for IntrospectOAuth2TokenWithIAM operation +// +// RFC 7662 §2.2 introspection response. Only active is required; all other claims +// are omitted when the token is inactive. +type IntrospectOAuth2TokenWithIAMOutput struct { + + // Indicates whether the token is currently active. true only when the token is + // valid, has not expired, has not been revoked, and belongs to the caller's + // account. + // + // This member is required. + Active *bool + + // 12-digit AWS account ID of the token's subject principal. + AccountId *string + + // Audience of the token: the OAuth resource the token is scoped to (for example, + // "aws-mcp.amazonaws.com"). Omitted for refresh tokens. + Aud *string + + // Client identifier for the OAuth 2.0 client that requested the token. + ClientId *string + + // Token expiration time as a NumericDate (Unix epoch seconds). + Exp *int64 + + // Token issuance time as a NumericDate (Unix epoch seconds). + Iat *int64 + + // Issuer of the token. Always "signin.amazonaws.com" for AWS Sign-In. + Iss *string + + // Unique identifier for the token. + Jti *string + + // Token "not before" time as a NumericDate (Unix epoch seconds). + Nbf *int64 + + // The OAuth resource the token is scoped to during Human OAuth flow. Only present + // for refresh token introspection. + Resource *string + + // AWS Sign-In session ARN bound to the token, of the form + // arn:aws:signin:{region}:{account}:session/{uuid}. + SigninSession *string + + // Subject of the token: the IAM principal ARN. For assumed-role sessions, this is + // the session ARN (matches sts:GetCallerIdentity's Arn field), e.g. + // arn:aws:sts::123456789012:assumed-role/MyRole/session-name. + Sub *string + + // Indicates which kind of token was introspected. One of "access_token" or + // "refresh_token". + TokenType *string + + // User identifier matching sts:GetCallerIdentity's UserId field for the token's + // subject principal (e.g. "AIDAEXAMPLE" for an IAM user, or + // "AROAEXAMPLE:session-name" for an assumed role). + UserId *string + + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationIntrospectOAuth2TokenWithIAMMiddlewares(stack *middleware.Stack, options Options) (err error) { + err = stack.Serialize.Add(&awsRestjson1_serializeOpIntrospectOAuth2TokenWithIAM{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsRestjson1_deserializeOpIntrospectOAuth2TokenWithIAM{}, middleware.After) + if err != nil { + return err + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addComputeContentLength(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addComputePayloadSHA256(stack); err != nil { + return err + } + if err = addRecordResponseTiming(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addCredentialSource(stack, options); err != nil { + return err + } + if err = addOpIntrospectOAuth2TokenWithIAMValidationMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "IntrospectOAuth2TokenWithIAM"), middleware.Before); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + if err = addInterceptors(stack, options); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_ListResourcePermissionStatements.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_ListResourcePermissionStatements.go index 46a4c6c89f2..2cb7c5c67ff 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_ListResourcePermissionStatements.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_ListResourcePermissionStatements.go @@ -83,7 +83,7 @@ func (c *Client) addOperationListResourcePermissionStatementsMiddlewares(stack * if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutConsoleAuthorizationConfiguration.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutConsoleAuthorizationConfiguration.go index d54b0d42190..7f2bc68ada0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutConsoleAuthorizationConfiguration.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutConsoleAuthorizationConfiguration.go @@ -85,7 +85,7 @@ func (c *Client) addOperationPutConsoleAuthorizationConfigurationMiddlewares(sta if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutResourcePermissionStatement.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutResourcePermissionStatement.go index e04aaba5c2c..071e1fb506e 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutResourcePermissionStatement.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutResourcePermissionStatement.go @@ -98,7 +98,7 @@ func (c *Client) addOperationPutResourcePermissionStatementMiddlewares(stack *mi if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_RevokeOAuth2TokenWithIAM.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_RevokeOAuth2TokenWithIAM.go new file mode 100644 index 00000000000..3524e1eccd3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_RevokeOAuth2TokenWithIAM.go @@ -0,0 +1,122 @@ +// Code generated by smithy-go-codegen DO NOT EDIT. + +package signin + +import ( + "context" + "github.com/aws/smithy-go/middleware" + "github.com/aws/smithy-go/ptr" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +// Grants permission to revoke an OAuth 2.0 refresh token and its associated +// refresh tokens +// +// Revokes a refresh_token issued by AWS Sign-In, invalidating the entire token +// chain so that the refresh_token can no longer be used to mint new access_tokens. +// +// Idempotency: revoking an already-revoked, expired, or otherwise invalid token +// still returns 200 OK with an empty body. Only the refresh_token type is +// accepted. +func (c *Client) RevokeOAuth2TokenWithIAM(ctx context.Context, params *RevokeOAuth2TokenWithIAMInput, optFns ...func(*Options)) (*RevokeOAuth2TokenWithIAMOutput, error) { + if params == nil { + params = &RevokeOAuth2TokenWithIAMInput{} + } + + result, metadata, err := c.invokeOperation(ctx, "RevokeOAuth2TokenWithIAM", params, optFns, c.addOperationRevokeOAuth2TokenWithIAMMiddlewares) + if err != nil { + return nil, err + } + + out := result.(*RevokeOAuth2TokenWithIAMOutput) + out.ResultMetadata = metadata + return out, nil +} + +// Input structure for RevokeOAuth2TokenWithIAM operation +// +// RFC 7009 §2.1 revocation request. Contains the refresh_token to revoke. +type RevokeOAuth2TokenWithIAMInput struct { + + // The refresh_token to revoke. Must be a refresh_token issued by AWS Sign-In + // (prefix "ASOR"); access_tokens are not accepted for revocation. + // + // This member is required. + Token *string + + noSmithyDocumentSerde +} + +func (in *RevokeOAuth2TokenWithIAMInput) bindEndpointParams(p *EndpointParameters) { + + p.IsOAuthEndpoint = ptr.Bool(true) +} + +// Output structure for RevokeOAuth2TokenWithIAM operation +// +// RFC 7009 §2.2 revocation response. The endpoint returns 200 OK with an empty +// body on success; there are no response fields. +type RevokeOAuth2TokenWithIAMOutput struct { + // Metadata pertaining to the operation's result. + ResultMetadata middleware.Metadata + + noSmithyDocumentSerde +} + +func (c *Client) addOperationRevokeOAuth2TokenWithIAMMiddlewares(stack *middleware.Stack, options Options) (err error) { + err = stack.Serialize.Add(&awsRestjson1_serializeOpRevokeOAuth2TokenWithIAM{}, middleware.After) + if err != nil { + return err + } + err = stack.Deserialize.Add(&awsRestjson1_deserializeOpRevokeOAuth2TokenWithIAM{}, middleware.After) + if err != nil { + return err + } + + if err = addlegacyEndpointContextSetter(stack, options); err != nil { + return err + } + if err = addComputeContentLength(stack); err != nil { + return err + } + if err = addResolveEndpointMiddleware(stack, options); err != nil { + return err + } + if err = addComputePayloadSHA256(stack); err != nil { + return err + } + if err = addRecordResponseTiming(stack, options); err != nil { + return err + } + if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { + return err + } + if err = addCredentialSource(stack, options); err != nil { + return err + } + if err = addOpRevokeOAuth2TokenWithIAMValidationMiddleware(stack); err != nil { + return err + } + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "RevokeOAuth2TokenWithIAM"), middleware.Before); err != nil { + return err + } + if err = addRequestIDRetrieverMiddleware(stack); err != nil { + return err + } + if err = addResponseErrorMiddleware(stack); err != nil { + return err + } + if err = addRequestResponseLogging(stack, options); err != nil { + return err + } + if err = addDisableHTTPSMiddleware(stack, options); err != nil { + return err + } + if err = addInterceptors(stack, options); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/deserializers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/deserializers.go index 12208eaafaa..e78be3229e4 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/deserializers.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/deserializers.go @@ -180,6 +180,193 @@ func awsRestjson1_deserializeOpDocumentCreateOAuth2TokenOutput(v **CreateOAuth2T return nil } +type awsRestjson1_deserializeOpCreateOAuth2TokenWithIAM struct { +} + +func (*awsRestjson1_deserializeOpCreateOAuth2TokenWithIAM) ID() string { + return "OperationDeserializer" +} + +func (m *awsRestjson1_deserializeOpCreateOAuth2TokenWithIAM) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + _, span := tracing.StartSpan(ctx, "OperationDeserializer") + endTimer := startMetricTimer(ctx, "client.call.deserialization_duration") + defer endTimer() + defer span.End() + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsRestjson1_deserializeOpErrorCreateOAuth2TokenWithIAM(response, &metadata) + } + output := &CreateOAuth2TokenWithIAMOutput{} + out.Result = output + + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(response.Body, ringBuffer) + + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return out, metadata, err + } + + err = awsRestjson1_deserializeOpDocumentCreateOAuth2TokenWithIAMOutput(&output, shape) + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + return out, metadata, &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body with invalid JSON, %w", err), + Snapshot: snapshot.Bytes(), + } + } + + span.End() + return out, metadata, err +} + +func awsRestjson1_deserializeOpErrorCreateOAuth2TokenWithIAM(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + headerCode := response.Header.Get("X-Amzn-ErrorType") + if len(headerCode) != 0 { + errorCode = restjson.SanitizeErrorCode(headerCode) + } + + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + jsonCode, message, err := restjson.GetErrorInfo(decoder) + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + if len(headerCode) == 0 && len(jsonCode) != 0 { + errorCode = restjson.SanitizeErrorCode(jsonCode) + } + if len(message) != 0 { + errorMessage = message + } + + switch { + case strings.EqualFold("AccessDeniedException", errorCode): + return awsRestjson1_deserializeErrorAccessDeniedException(response, errorBody) + + case strings.EqualFold("InternalServerException", errorCode): + return awsRestjson1_deserializeErrorInternalServerException(response, errorBody) + + case strings.EqualFold("TooManyRequestsError", errorCode): + return awsRestjson1_deserializeErrorTooManyRequestsError(response, errorBody) + + case strings.EqualFold("ValidationException", errorCode): + return awsRestjson1_deserializeErrorValidationException(response, errorBody) + + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } +} + +func awsRestjson1_deserializeOpDocumentCreateOAuth2TokenWithIAMOutput(v **CreateOAuth2TokenWithIAMOutput, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *CreateOAuth2TokenWithIAMOutput + if *v == nil { + sv = &CreateOAuth2TokenWithIAMOutput{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "access_token": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected OAuthAccessToken to be of type string, got %T instead", value) + } + sv.AccessToken = ptr.String(jtv) + } + + case "expires_in": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected TokenExpiresIn to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.ExpiresIn = ptr.Int32(int32(i64)) + } + + case "token_type": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected BearerTokenType to be of type string, got %T instead", value) + } + sv.TokenType = ptr.String(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + type awsRestjson1_deserializeOpDeleteConsoleAuthorizationConfiguration struct { } @@ -514,7 +701,193 @@ func (m *awsRestjson1_deserializeOpGetConsoleAuthorizationConfiguration) HandleD return out, metadata, err } - err = awsRestjson1_deserializeOpDocumentGetConsoleAuthorizationConfigurationOutput(&output, shape) + err = awsRestjson1_deserializeOpDocumentGetConsoleAuthorizationConfigurationOutput(&output, shape) + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + return out, metadata, &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body with invalid JSON, %w", err), + Snapshot: snapshot.Bytes(), + } + } + + span.End() + return out, metadata, err +} + +func awsRestjson1_deserializeOpErrorGetConsoleAuthorizationConfiguration(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + headerCode := response.Header.Get("X-Amzn-ErrorType") + if len(headerCode) != 0 { + errorCode = restjson.SanitizeErrorCode(headerCode) + } + + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + jsonCode, message, err := restjson.GetErrorInfo(decoder) + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + if len(headerCode) == 0 && len(jsonCode) != 0 { + errorCode = restjson.SanitizeErrorCode(jsonCode) + } + if len(message) != 0 { + errorMessage = message + } + + switch { + case strings.EqualFold("AccessDeniedException", errorCode): + return awsRestjson1_deserializeErrorAccessDeniedException(response, errorBody) + + case strings.EqualFold("InternalServerException", errorCode): + return awsRestjson1_deserializeErrorInternalServerException(response, errorBody) + + case strings.EqualFold("ResourceNotFoundException", errorCode): + return awsRestjson1_deserializeErrorResourceNotFoundException(response, errorBody) + + case strings.EqualFold("TooManyRequestsError", errorCode): + return awsRestjson1_deserializeErrorTooManyRequestsError(response, errorBody) + + case strings.EqualFold("ValidationException", errorCode): + return awsRestjson1_deserializeErrorValidationException(response, errorBody) + + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } +} + +func awsRestjson1_deserializeOpDocumentGetConsoleAuthorizationConfigurationOutput(v **GetConsoleAuthorizationConfigurationOutput, value interface{}) error { + if v == nil { + return fmt.Errorf("unexpected nil of type %T", v) + } + if value == nil { + return nil + } + + shape, ok := value.(map[string]interface{}) + if !ok { + return fmt.Errorf("unexpected JSON type %v", value) + } + + var sv *GetConsoleAuthorizationConfigurationOutput + if *v == nil { + sv = &GetConsoleAuthorizationConfigurationOutput{} + } else { + sv = *v + } + + for key, value := range shape { + switch key { + case "consoleAuthorizationEnabled": + if value != nil { + jtv, ok := value.(bool) + if !ok { + return fmt.Errorf("expected Boolean to be of type *bool, got %T instead", value) + } + sv.ConsoleAuthorizationEnabled = ptr.Bool(jtv) + } + + case "scope": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Scope = ptr.String(jtv) + } + + case "targetId": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected TargetId to be of type string, got %T instead", value) + } + sv.TargetId = ptr.String(jtv) + } + + default: + _, _ = key, value + + } + } + *v = sv + return nil +} + +type awsRestjson1_deserializeOpGetResourcePolicy struct { +} + +func (*awsRestjson1_deserializeOpGetResourcePolicy) ID() string { + return "OperationDeserializer" +} + +func (m *awsRestjson1_deserializeOpGetResourcePolicy) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + _, span := tracing.StartSpan(ctx, "OperationDeserializer") + endTimer := startMetricTimer(ctx, "client.call.deserialization_duration") + defer endTimer() + defer span.End() + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsRestjson1_deserializeOpErrorGetResourcePolicy(response, &metadata) + } + output := &GetResourcePolicyOutput{} + out.Result = output + + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(response.Body, ringBuffer) + + decoder := json.NewDecoder(body) + decoder.UseNumber() + var shape interface{} + if err := decoder.Decode(&shape); err != nil && err != io.EOF { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return out, metadata, err + } + + err = awsRestjson1_deserializeOpDocumentGetResourcePolicyOutput(&output, shape) if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) @@ -528,7 +901,7 @@ func (m *awsRestjson1_deserializeOpGetConsoleAuthorizationConfiguration) HandleD return out, metadata, err } -func awsRestjson1_deserializeOpErrorGetConsoleAuthorizationConfiguration(response *smithyhttp.Response, metadata *middleware.Metadata) error { +func awsRestjson1_deserializeOpErrorGetResourcePolicy(response *smithyhttp.Response, metadata *middleware.Metadata) error { var errorBuffer bytes.Buffer if _, err := io.Copy(&errorBuffer, response.Body); err != nil { return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} @@ -581,9 +954,6 @@ func awsRestjson1_deserializeOpErrorGetConsoleAuthorizationConfiguration(respons case strings.EqualFold("TooManyRequestsError", errorCode): return awsRestjson1_deserializeErrorTooManyRequestsError(response, errorBody) - case strings.EqualFold("ValidationException", errorCode): - return awsRestjson1_deserializeErrorValidationException(response, errorBody) - default: genericError := &smithy.GenericAPIError{ Code: errorCode, @@ -594,7 +964,7 @@ func awsRestjson1_deserializeOpErrorGetConsoleAuthorizationConfiguration(respons } } -func awsRestjson1_deserializeOpDocumentGetConsoleAuthorizationConfigurationOutput(v **GetConsoleAuthorizationConfigurationOutput, value interface{}) error { +func awsRestjson1_deserializeOpDocumentGetResourcePolicyOutput(v **GetResourcePolicyOutput, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) } @@ -607,40 +977,18 @@ func awsRestjson1_deserializeOpDocumentGetConsoleAuthorizationConfigurationOutpu return fmt.Errorf("unexpected JSON type %v", value) } - var sv *GetConsoleAuthorizationConfigurationOutput + var sv *GetResourcePolicyOutput if *v == nil { - sv = &GetConsoleAuthorizationConfigurationOutput{} + sv = &GetResourcePolicyOutput{} } else { sv = *v } for key, value := range shape { switch key { - case "consoleAuthorizationEnabled": - if value != nil { - jtv, ok := value.(bool) - if !ok { - return fmt.Errorf("expected Boolean to be of type *bool, got %T instead", value) - } - sv.ConsoleAuthorizationEnabled = ptr.Bool(jtv) - } - - case "scope": - if value != nil { - jtv, ok := value.(string) - if !ok { - return fmt.Errorf("expected String to be of type string, got %T instead", value) - } - sv.Scope = ptr.String(jtv) - } - - case "targetId": - if value != nil { - jtv, ok := value.(string) - if !ok { - return fmt.Errorf("expected TargetId to be of type string, got %T instead", value) - } - sv.TargetId = ptr.String(jtv) + case "signinResourceBasedPolicy": + if err := awsRestjson1_deserializeDocumentSigninResourceBasedPolicy(&sv.SigninResourceBasedPolicy, value); err != nil { + return err } default: @@ -652,14 +1000,14 @@ func awsRestjson1_deserializeOpDocumentGetConsoleAuthorizationConfigurationOutpu return nil } -type awsRestjson1_deserializeOpGetResourcePolicy struct { +type awsRestjson1_deserializeOpIntrospectOAuth2TokenWithIAM struct { } -func (*awsRestjson1_deserializeOpGetResourcePolicy) ID() string { +func (*awsRestjson1_deserializeOpIntrospectOAuth2TokenWithIAM) ID() string { return "OperationDeserializer" } -func (m *awsRestjson1_deserializeOpGetResourcePolicy) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( +func (m *awsRestjson1_deserializeOpIntrospectOAuth2TokenWithIAM) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( out middleware.DeserializeOutput, metadata middleware.Metadata, err error, ) { out, metadata, err = next.HandleDeserialize(ctx, in) @@ -677,9 +1025,9 @@ func (m *awsRestjson1_deserializeOpGetResourcePolicy) HandleDeserialize(ctx cont } if response.StatusCode < 200 || response.StatusCode >= 300 { - return out, metadata, awsRestjson1_deserializeOpErrorGetResourcePolicy(response, &metadata) + return out, metadata, awsRestjson1_deserializeOpErrorIntrospectOAuth2TokenWithIAM(response, &metadata) } - output := &GetResourcePolicyOutput{} + output := &IntrospectOAuth2TokenWithIAMOutput{} out.Result = output var buff [1024]byte @@ -700,7 +1048,7 @@ func (m *awsRestjson1_deserializeOpGetResourcePolicy) HandleDeserialize(ctx cont return out, metadata, err } - err = awsRestjson1_deserializeOpDocumentGetResourcePolicyOutput(&output, shape) + err = awsRestjson1_deserializeOpDocumentIntrospectOAuth2TokenWithIAMOutput(&output, shape) if err != nil { var snapshot bytes.Buffer io.Copy(&snapshot, ringBuffer) @@ -714,7 +1062,7 @@ func (m *awsRestjson1_deserializeOpGetResourcePolicy) HandleDeserialize(ctx cont return out, metadata, err } -func awsRestjson1_deserializeOpErrorGetResourcePolicy(response *smithyhttp.Response, metadata *middleware.Metadata) error { +func awsRestjson1_deserializeOpErrorIntrospectOAuth2TokenWithIAM(response *smithyhttp.Response, metadata *middleware.Metadata) error { var errorBuffer bytes.Buffer if _, err := io.Copy(&errorBuffer, response.Body); err != nil { return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} @@ -761,12 +1109,12 @@ func awsRestjson1_deserializeOpErrorGetResourcePolicy(response *smithyhttp.Respo case strings.EqualFold("InternalServerException", errorCode): return awsRestjson1_deserializeErrorInternalServerException(response, errorBody) - case strings.EqualFold("ResourceNotFoundException", errorCode): - return awsRestjson1_deserializeErrorResourceNotFoundException(response, errorBody) - case strings.EqualFold("TooManyRequestsError", errorCode): return awsRestjson1_deserializeErrorTooManyRequestsError(response, errorBody) + case strings.EqualFold("ValidationException", errorCode): + return awsRestjson1_deserializeErrorValidationException(response, errorBody) + default: genericError := &smithy.GenericAPIError{ Code: errorCode, @@ -777,7 +1125,7 @@ func awsRestjson1_deserializeOpErrorGetResourcePolicy(response *smithyhttp.Respo } } -func awsRestjson1_deserializeOpDocumentGetResourcePolicyOutput(v **GetResourcePolicyOutput, value interface{}) error { +func awsRestjson1_deserializeOpDocumentIntrospectOAuth2TokenWithIAMOutput(v **IntrospectOAuth2TokenWithIAMOutput, value interface{}) error { if v == nil { return fmt.Errorf("unexpected nil of type %T", v) } @@ -790,18 +1138,151 @@ func awsRestjson1_deserializeOpDocumentGetResourcePolicyOutput(v **GetResourcePo return fmt.Errorf("unexpected JSON type %v", value) } - var sv *GetResourcePolicyOutput + var sv *IntrospectOAuth2TokenWithIAMOutput if *v == nil { - sv = &GetResourcePolicyOutput{} + sv = &IntrospectOAuth2TokenWithIAMOutput{} } else { sv = *v } for key, value := range shape { switch key { - case "signinResourceBasedPolicy": - if err := awsRestjson1_deserializeDocumentSigninResourceBasedPolicy(&sv.SigninResourceBasedPolicy, value); err != nil { - return err + case "account_id": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected AccountId to be of type string, got %T instead", value) + } + sv.AccountId = ptr.String(jtv) + } + + case "active": + if value != nil { + jtv, ok := value.(bool) + if !ok { + return fmt.Errorf("expected Boolean to be of type *bool, got %T instead", value) + } + sv.Active = ptr.Bool(jtv) + } + + case "aud": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Aud = ptr.String(jtv) + } + + case "client_id": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.ClientId = ptr.String(jtv) + } + + case "exp": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Long to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.Exp = ptr.Int64(i64) + } + + case "iat": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Long to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.Iat = ptr.Int64(i64) + } + + case "iss": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Iss = ptr.String(jtv) + } + + case "jti": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Jti = ptr.String(jtv) + } + + case "nbf": + if value != nil { + jtv, ok := value.(json.Number) + if !ok { + return fmt.Errorf("expected Long to be json.Number, got %T instead", value) + } + i64, err := jtv.Int64() + if err != nil { + return err + } + sv.Nbf = ptr.Int64(i64) + } + + case "resource": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Resource = ptr.String(jtv) + } + + case "signin_session": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.SigninSession = ptr.String(jtv) + } + + case "sub": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.Sub = ptr.String(jtv) + } + + case "token_type": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected IntrospectedTokenType to be of type string, got %T instead", value) + } + sv.TokenType = ptr.String(jtv) + } + + case "user_id": + if value != nil { + jtv, ok := value.(string) + if !ok { + return fmt.Errorf("expected String to be of type string, got %T instead", value) + } + sv.UserId = ptr.String(jtv) } default: @@ -1346,6 +1827,103 @@ func awsRestjson1_deserializeOpDocumentPutResourcePermissionStatementOutput(v ** return nil } +type awsRestjson1_deserializeOpRevokeOAuth2TokenWithIAM struct { +} + +func (*awsRestjson1_deserializeOpRevokeOAuth2TokenWithIAM) ID() string { + return "OperationDeserializer" +} + +func (m *awsRestjson1_deserializeOpRevokeOAuth2TokenWithIAM) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err != nil { + return out, metadata, err + } + + _, span := tracing.StartSpan(ctx, "OperationDeserializer") + endTimer := startMetricTimer(ctx, "client.call.deserialization_duration") + defer endTimer() + defer span.End() + response, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)} + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + return out, metadata, awsRestjson1_deserializeOpErrorRevokeOAuth2TokenWithIAM(response, &metadata) + } + output := &RevokeOAuth2TokenWithIAMOutput{} + out.Result = output + + span.End() + return out, metadata, err +} + +func awsRestjson1_deserializeOpErrorRevokeOAuth2TokenWithIAM(response *smithyhttp.Response, metadata *middleware.Metadata) error { + var errorBuffer bytes.Buffer + if _, err := io.Copy(&errorBuffer, response.Body); err != nil { + return &smithy.DeserializationError{Err: fmt.Errorf("failed to copy error response body, %w", err)} + } + errorBody := bytes.NewReader(errorBuffer.Bytes()) + + errorCode := "UnknownError" + errorMessage := errorCode + + headerCode := response.Header.Get("X-Amzn-ErrorType") + if len(headerCode) != 0 { + errorCode = restjson.SanitizeErrorCode(headerCode) + } + + var buff [1024]byte + ringBuffer := smithyio.NewRingBuffer(buff[:]) + + body := io.TeeReader(errorBody, ringBuffer) + decoder := json.NewDecoder(body) + decoder.UseNumber() + jsonCode, message, err := restjson.GetErrorInfo(decoder) + if err != nil { + var snapshot bytes.Buffer + io.Copy(&snapshot, ringBuffer) + err = &smithy.DeserializationError{ + Err: fmt.Errorf("failed to decode response body, %w", err), + Snapshot: snapshot.Bytes(), + } + return err + } + + errorBody.Seek(0, io.SeekStart) + if len(headerCode) == 0 && len(jsonCode) != 0 { + errorCode = restjson.SanitizeErrorCode(jsonCode) + } + if len(message) != 0 { + errorMessage = message + } + + switch { + case strings.EqualFold("AccessDeniedException", errorCode): + return awsRestjson1_deserializeErrorAccessDeniedException(response, errorBody) + + case strings.EqualFold("InternalServerException", errorCode): + return awsRestjson1_deserializeErrorInternalServerException(response, errorBody) + + case strings.EqualFold("TooManyRequestsError", errorCode): + return awsRestjson1_deserializeErrorTooManyRequestsError(response, errorBody) + + case strings.EqualFold("ValidationException", errorCode): + return awsRestjson1_deserializeErrorValidationException(response, errorBody) + + default: + genericError := &smithy.GenericAPIError{ + Code: errorCode, + Message: errorMessage, + } + return genericError + + } +} + func awsRestjson1_deserializeErrorAccessDeniedException(response *smithyhttp.Response, errorBody *bytes.Reader) error { output := &types.AccessDeniedException{} var buff [1024]byte diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/endpoints.go index 16944632691..52c68b3570a 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/endpoints.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/endpoints.go @@ -276,6 +276,12 @@ type EndpointParameters struct { // Parameter is // required. IsControlPlane *bool + + // Indicates if the operation targets the OAuth token endpoint + // + // Parameter is + // required. + IsOAuthEndpoint *bool } // ValidateRequired validates required parameters are set. @@ -306,8 +312,8 @@ func (p EndpointParameters) WithDefaults() EndpointParameters { const bddRoot int32 = 2 -var bddNodes = [99]int32{ - -1, 1, -1, 0, 4, 3, 2, 30, 100000025, 1, 24, 5, 2, 30, 6, 3, 7, 26, 4, 18, 8, 5, 17, 9, 6, 100000004, 10, 7, 100000005, 11, 10, 100000006, 12, 12, 100000007, 13, 13, 100000008, 14, 14, 100000009, 15, 15, 100000010, 16, 16, 100000011, 100000014, 8, 100000022, 100000023, 5, 22, 19, 9, 100000012, 20, 10, 100000013, 21, 11, 100000020, 100000021, 8, 23, 100000019, 11, 100000018, 100000019, 2, 29, 25, 3, 32, 26, 4, 27, 100000025, 5, 100000025, 28, 9, 100000012, 100000025, 3, 32, 30, 4, 100000015, 31, 5, 100000016, 100000017, 6, 100000001, 33, 7, 100000002, 100000003} +var bddNodes = [120]int32{ + -1, 1, -1, 0, 6, 3, 2, 36, 4, 4, 5, 100000027, 6, 100000004, 100000027, 1, 29, 7, 2, 36, 8, 3, 9, 31, 4, 22, 10, 5, 19, 11, 7, 21, 12, 8, 100000007, 13, 10, 100000008, 14, 12, 100000009, 15, 13, 100000010, 16, 14, 100000011, 17, 15, 100000012, 18, 16, 100000013, 100000016, 6, 100000005, 20, 7, 21, 100000006, 17, 100000024, 100000025, 6, 100000004, 23, 7, 27, 24, 9, 100000014, 25, 10, 100000015, 26, 11, 100000022, 100000023, 11, 28, 100000021, 17, 100000020, 100000021, 2, 35, 30, 3, 39, 31, 4, 32, 100000027, 6, 100000004, 33, 7, 100000027, 34, 9, 100000014, 100000027, 3, 39, 36, 4, 38, 37, 7, 100000018, 100000019, 6, 100000004, 100000017, 5, 100000001, 40, 8, 100000002, 100000003} type conditionContext struct { PartitionResult *awsrulesfn.PartitionConfig @@ -335,13 +341,18 @@ func evalCondition(idx int, params *EndpointParameters, c *conditionContext) boo case 4: return *params.UseFIPS == true case 5: - return *params.UseDualStack == true - case 6: return c.PartitionResult.Name == "aws" + case 6: + return func() bool { + if v := params.IsOAuthEndpoint; v != nil { + return *v + } + return false + }() == true case 7: - return c.PartitionResult.Name == "aws-cn" + return *params.UseDualStack == true case 8: - return c.PartitionResult.SupportsDualStack == true + return c.PartitionResult.Name == "aws-cn" case 9: return *params.Region == "us-gov-west-1" case 10: @@ -358,6 +369,8 @@ func evalCondition(idx int, params *EndpointParameters, c *conditionContext) boo return c.PartitionResult.Name == "aws-iso-e" case 16: return c.PartitionResult.Name == "aws-eusc" + case 17: + return c.PartitionResult.SupportsDualStack == true } return false } @@ -467,6 +480,41 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( }(), }, nil case 4: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "FIPS endpoints are not supported for OAuth operations. Disable FIPS or use a non-OAuth operation.") + case 5: + uriString := func() string { + var out strings.Builder + out.WriteString("https://") + out.WriteString(*params.Region) + out.WriteString(".oauth.signin.aws") + return out.String() + }() + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + Properties: func() smithy.Properties { + var out smithy.Properties + smithyauth.SetAuthOptions(&out, []*smithyauth.Option{ + { + SchemeID: "sigv4", + SignerProperties: func() smithy.Properties { + var sp smithy.Properties + smithyhttp.SetSigV4SigningName(&sp, "signin") + smithyhttp.SetSigV4ASigningName(&sp, "signin") + + smithyhttp.SetSigV4SigningRegion(&sp, *params.Region) + return sp + }(), + }, + }) + return out + }(), + }, nil + case 6: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -482,7 +530,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 5: + case 7: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -498,7 +546,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 6: + case 8: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -514,7 +562,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 7: + case 9: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -530,7 +578,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 8: + case 10: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -546,7 +594,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 9: + case 11: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -562,7 +610,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 10: + case 12: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -578,7 +626,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 11: + case 13: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -594,7 +642,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 12: + case 14: uriString := "https://signin-fips.amazonaws-us-gov.com" uri, err := url.Parse(uriString) if err != nil { @@ -604,7 +652,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 13: + case 15: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -620,7 +668,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 14: + case 16: uriString := func() string { var out strings.Builder out.WriteString("https://") @@ -637,11 +685,11 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 15: + case 17: return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: FIPS and custom endpoint are not supported") - case 16: + case 18: return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Dualstack and custom endpoint are not supported") - case 17: + case 19: uriString := *params.Endpoint uri, err := url.Parse(uriString) if err != nil { @@ -651,7 +699,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 18: + case 20: uriString := func() string { var out strings.Builder out.WriteString("https://signin-fips.") @@ -668,9 +716,9 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 19: + case 21: return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "FIPS and DualStack are enabled, but this partition does not support one or both") - case 20: + case 22: uriString := func() string { var out strings.Builder out.WriteString("https://signin-fips.") @@ -687,9 +735,9 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 21: + case 23: return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "FIPS is enabled but this partition does not support FIPS") - case 22: + case 24: uriString := func() string { var out strings.Builder out.WriteString("https://signin.") @@ -706,9 +754,9 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 23: + case 25: return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "DualStack is enabled but this partition does not support DualStack") - case 24: + case 26: uriString := func() string { var out strings.Builder out.WriteString("https://signin.") @@ -725,7 +773,7 @@ func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) ( URI: *uri, Headers: http.Header{}, }, nil - case 25: + case 27: return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Missing Region") } return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, invalid result index: %d", idx) diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/generated.json index 4965af44178..762cc709c93 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/generated.json +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/generated.json @@ -9,13 +9,16 @@ "api_client.go", "api_client_test.go", "api_op_CreateOAuth2Token.go", + "api_op_CreateOAuth2TokenWithIAM.go", "api_op_DeleteConsoleAuthorizationConfiguration.go", "api_op_DeleteResourcePermissionStatement.go", "api_op_GetConsoleAuthorizationConfiguration.go", "api_op_GetResourcePolicy.go", + "api_op_IntrospectOAuth2TokenWithIAM.go", "api_op_ListResourcePermissionStatements.go", "api_op_PutConsoleAuthorizationConfiguration.go", "api_op_PutResourcePermissionStatement.go", + "api_op_RevokeOAuth2TokenWithIAM.go", "auth.go", "deserializers.go", "doc.go", @@ -26,6 +29,8 @@ "internal/endpoints/endpoints.go", "internal/endpoints/endpoints_test.go", "options.go", + "request_snapshot_test.go", + "response_snapshot_test.go", "serializers.go", "snapshot_test.go", "sra_operation_order_test.go", diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/go_module_metadata.go index 685df38e364..d41dad1b6bf 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/go_module_metadata.go @@ -3,4 +3,4 @@ package signin // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.2.1" +const goModuleVersion = "1.5.2" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/options.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/options.go index 551d20c28cd..9b7248ff303 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/options.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/options.go @@ -44,6 +44,11 @@ type Options struct { // clients initial default settings. DefaultsMode aws.DefaultsMode + // Disables SDK clock skew correction. When set, the SDK will not adjust request + // signing timestamps to compensate for clock drift between the client and the + // service. + DisableClockSkewCorrection bool + // The endpoint options to be used when attempting to resolve an endpoint. EndpointOptions EndpointResolverOptions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/serializers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/serializers.go index fe87e71f886..d245732cccd 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/serializers.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/serializers.go @@ -97,6 +97,92 @@ func awsRestjson1_serializeOpHttpBindingsCreateOAuth2TokenInput(v *CreateOAuth2T return nil } +type awsRestjson1_serializeOpCreateOAuth2TokenWithIAM struct { +} + +func (*awsRestjson1_serializeOpCreateOAuth2TokenWithIAM) ID() string { + return "OperationSerializer" +} + +func (m *awsRestjson1_serializeOpCreateOAuth2TokenWithIAM) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + _, span := tracing.StartSpan(ctx, "OperationSerializer") + endTimer := startMetricTimer(ctx, "client.call.serialization_duration") + defer endTimer() + defer span.End() + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*CreateOAuth2TokenWithIAMInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + opPath, opQuery := httpbinding.SplitURI("/v1/token?x-amz-client-auth-method=iam") + request.URL.Path = smithyhttp.JoinPath(request.URL.Path, opPath) + request.URL.RawQuery = smithyhttp.JoinRawQuery(request.URL.RawQuery, opQuery) + request.Method = "POST" + var restEncoder *httpbinding.Encoder + if request.URL.RawPath == "" { + restEncoder, err = httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + } else { + request.URL.RawPath = smithyhttp.JoinPath(request.URL.RawPath, opPath) + restEncoder, err = httpbinding.NewEncoderWithRawPath(request.URL.Path, request.URL.RawPath, request.URL.RawQuery, request.Header) + } + + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + restEncoder.SetHeader("Content-Type").String("application/json") + + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeOpDocumentCreateOAuth2TokenWithIAMInput(input, jsonEncoder.Value); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request, err = request.SetStream(bytes.NewReader(jsonEncoder.Bytes())); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request.Request, err = restEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + endTimer() + span.End() + return next.HandleSerialize(ctx, in) +} +func awsRestjson1_serializeOpHttpBindingsCreateOAuth2TokenWithIAMInput(v *CreateOAuth2TokenWithIAMInput, encoder *httpbinding.Encoder) error { + if v == nil { + return fmt.Errorf("unsupported serialization of nil %T", v) + } + + return nil +} + +func awsRestjson1_serializeOpDocumentCreateOAuth2TokenWithIAMInput(v *CreateOAuth2TokenWithIAMInput, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.GrantType != nil { + ok := object.Key("grant_type") + ok.String(*v.GrantType) + } + + if v.Resource != nil { + ok := object.Key("resource") + ok.String(*v.Resource) + } + + return nil +} + type awsRestjson1_serializeOpDeleteConsoleAuthorizationConfiguration struct { } @@ -403,6 +489,92 @@ func awsRestjson1_serializeOpHttpBindingsGetResourcePolicyInput(v *GetResourcePo return nil } +type awsRestjson1_serializeOpIntrospectOAuth2TokenWithIAM struct { +} + +func (*awsRestjson1_serializeOpIntrospectOAuth2TokenWithIAM) ID() string { + return "OperationSerializer" +} + +func (m *awsRestjson1_serializeOpIntrospectOAuth2TokenWithIAM) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + _, span := tracing.StartSpan(ctx, "OperationSerializer") + endTimer := startMetricTimer(ctx, "client.call.serialization_duration") + defer endTimer() + defer span.End() + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*IntrospectOAuth2TokenWithIAMInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + opPath, opQuery := httpbinding.SplitURI("/v1/introspect?x-amz-client-auth-method=iam") + request.URL.Path = smithyhttp.JoinPath(request.URL.Path, opPath) + request.URL.RawQuery = smithyhttp.JoinRawQuery(request.URL.RawQuery, opQuery) + request.Method = "POST" + var restEncoder *httpbinding.Encoder + if request.URL.RawPath == "" { + restEncoder, err = httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + } else { + request.URL.RawPath = smithyhttp.JoinPath(request.URL.RawPath, opPath) + restEncoder, err = httpbinding.NewEncoderWithRawPath(request.URL.Path, request.URL.RawPath, request.URL.RawQuery, request.Header) + } + + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + restEncoder.SetHeader("Content-Type").String("application/json") + + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeOpDocumentIntrospectOAuth2TokenWithIAMInput(input, jsonEncoder.Value); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request, err = request.SetStream(bytes.NewReader(jsonEncoder.Bytes())); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request.Request, err = restEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + endTimer() + span.End() + return next.HandleSerialize(ctx, in) +} +func awsRestjson1_serializeOpHttpBindingsIntrospectOAuth2TokenWithIAMInput(v *IntrospectOAuth2TokenWithIAMInput, encoder *httpbinding.Encoder) error { + if v == nil { + return fmt.Errorf("unsupported serialization of nil %T", v) + } + + return nil +} + +func awsRestjson1_serializeOpDocumentIntrospectOAuth2TokenWithIAMInput(v *IntrospectOAuth2TokenWithIAMInput, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.Token != nil { + ok := object.Key("token") + ok.String(*v.Token) + } + + if v.TokenTypeHint != nil { + ok := object.Key("token_type_hint") + ok.String(*v.TokenTypeHint) + } + + return nil +} + type awsRestjson1_serializeOpListResourcePermissionStatements struct { } @@ -686,6 +858,87 @@ func awsRestjson1_serializeOpDocumentPutResourcePermissionStatementInput(v *PutR return nil } +type awsRestjson1_serializeOpRevokeOAuth2TokenWithIAM struct { +} + +func (*awsRestjson1_serializeOpRevokeOAuth2TokenWithIAM) ID() string { + return "OperationSerializer" +} + +func (m *awsRestjson1_serializeOpRevokeOAuth2TokenWithIAM) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + _, span := tracing.StartSpan(ctx, "OperationSerializer") + endTimer := startMetricTimer(ctx, "client.call.serialization_duration") + defer endTimer() + defer span.End() + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown transport type %T", in.Request)} + } + + input, ok := in.Parameters.(*RevokeOAuth2TokenWithIAMInput) + _ = input + if !ok { + return out, metadata, &smithy.SerializationError{Err: fmt.Errorf("unknown input parameters type %T", in.Parameters)} + } + + opPath, opQuery := httpbinding.SplitURI("/v1/revoke?x-amz-client-auth-method=iam") + request.URL.Path = smithyhttp.JoinPath(request.URL.Path, opPath) + request.URL.RawQuery = smithyhttp.JoinRawQuery(request.URL.RawQuery, opQuery) + request.Method = "POST" + var restEncoder *httpbinding.Encoder + if request.URL.RawPath == "" { + restEncoder, err = httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, request.Header) + } else { + request.URL.RawPath = smithyhttp.JoinPath(request.URL.RawPath, opPath) + restEncoder, err = httpbinding.NewEncoderWithRawPath(request.URL.Path, request.URL.RawPath, request.URL.RawQuery, request.Header) + } + + if err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + restEncoder.SetHeader("Content-Type").String("application/json") + + jsonEncoder := smithyjson.NewEncoder() + if err := awsRestjson1_serializeOpDocumentRevokeOAuth2TokenWithIAMInput(input, jsonEncoder.Value); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request, err = request.SetStream(bytes.NewReader(jsonEncoder.Bytes())); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + + if request.Request, err = restEncoder.Encode(request.Request); err != nil { + return out, metadata, &smithy.SerializationError{Err: err} + } + in.Request = request + + endTimer() + span.End() + return next.HandleSerialize(ctx, in) +} +func awsRestjson1_serializeOpHttpBindingsRevokeOAuth2TokenWithIAMInput(v *RevokeOAuth2TokenWithIAMInput, encoder *httpbinding.Encoder) error { + if v == nil { + return fmt.Errorf("unsupported serialization of nil %T", v) + } + + return nil +} + +func awsRestjson1_serializeOpDocumentRevokeOAuth2TokenWithIAMInput(v *RevokeOAuth2TokenWithIAMInput, value smithyjson.Value) error { + object := value.Object() + defer object.Close() + + if v.Token != nil { + ok := object.Key("token") + ok.String(*v.Token) + } + + return nil +} + func awsRestjson1_serializeDocumentCreateOAuth2TokenRequestBody(v *types.CreateOAuth2TokenRequestBody, value smithyjson.Value) error { object := value.Object() defer object.Close() diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/types.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/types.go index aa4f7ecbe40..9e8bab7577c 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/types.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/types.go @@ -8,9 +8,7 @@ import ( // AWS credentials structure containing temporary access credentials // -// The scoped-down, 15 minute duration AWS credentials. Scoping down will be based -// on CLI policy (CLI team needs to create it). Similar to cloud shell -// implementation. +// Scoped, temporary AWS credentials with a 15-minute duration. type AccessToken struct { // AWS access key ID for temporary credentials diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/validators.go b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/validators.go index 8570cc5dbb5..8049ca28508 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/signin/validators.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/signin/validators.go @@ -30,6 +30,26 @@ func (m *validateOpCreateOAuth2Token) HandleInitialize(ctx context.Context, in m return next.HandleInitialize(ctx, in) } +type validateOpCreateOAuth2TokenWithIAM struct { +} + +func (*validateOpCreateOAuth2TokenWithIAM) ID() string { + return "OperationInputValidation" +} + +func (m *validateOpCreateOAuth2TokenWithIAM) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( + out middleware.InitializeOutput, metadata middleware.Metadata, err error, +) { + input, ok := in.Parameters.(*CreateOAuth2TokenWithIAMInput) + if !ok { + return out, metadata, fmt.Errorf("unknown input parameters type %T", in.Parameters) + } + if err := validateOpCreateOAuth2TokenWithIAMInput(input); err != nil { + return out, metadata, err + } + return next.HandleInitialize(ctx, in) +} + type validateOpDeleteResourcePermissionStatement struct { } @@ -50,14 +70,66 @@ func (m *validateOpDeleteResourcePermissionStatement) HandleInitialize(ctx conte return next.HandleInitialize(ctx, in) } +type validateOpIntrospectOAuth2TokenWithIAM struct { +} + +func (*validateOpIntrospectOAuth2TokenWithIAM) ID() string { + return "OperationInputValidation" +} + +func (m *validateOpIntrospectOAuth2TokenWithIAM) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( + out middleware.InitializeOutput, metadata middleware.Metadata, err error, +) { + input, ok := in.Parameters.(*IntrospectOAuth2TokenWithIAMInput) + if !ok { + return out, metadata, fmt.Errorf("unknown input parameters type %T", in.Parameters) + } + if err := validateOpIntrospectOAuth2TokenWithIAMInput(input); err != nil { + return out, metadata, err + } + return next.HandleInitialize(ctx, in) +} + +type validateOpRevokeOAuth2TokenWithIAM struct { +} + +func (*validateOpRevokeOAuth2TokenWithIAM) ID() string { + return "OperationInputValidation" +} + +func (m *validateOpRevokeOAuth2TokenWithIAM) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( + out middleware.InitializeOutput, metadata middleware.Metadata, err error, +) { + input, ok := in.Parameters.(*RevokeOAuth2TokenWithIAMInput) + if !ok { + return out, metadata, fmt.Errorf("unknown input parameters type %T", in.Parameters) + } + if err := validateOpRevokeOAuth2TokenWithIAMInput(input); err != nil { + return out, metadata, err + } + return next.HandleInitialize(ctx, in) +} + func addOpCreateOAuth2TokenValidationMiddleware(stack *middleware.Stack) error { return stack.Initialize.Add(&validateOpCreateOAuth2Token{}, middleware.After) } +func addOpCreateOAuth2TokenWithIAMValidationMiddleware(stack *middleware.Stack) error { + return stack.Initialize.Add(&validateOpCreateOAuth2TokenWithIAM{}, middleware.After) +} + func addOpDeleteResourcePermissionStatementValidationMiddleware(stack *middleware.Stack) error { return stack.Initialize.Add(&validateOpDeleteResourcePermissionStatement{}, middleware.After) } +func addOpIntrospectOAuth2TokenWithIAMValidationMiddleware(stack *middleware.Stack) error { + return stack.Initialize.Add(&validateOpIntrospectOAuth2TokenWithIAM{}, middleware.After) +} + +func addOpRevokeOAuth2TokenWithIAMValidationMiddleware(stack *middleware.Stack) error { + return stack.Initialize.Add(&validateOpRevokeOAuth2TokenWithIAM{}, middleware.After) +} + func validateCreateOAuth2TokenRequestBody(v *types.CreateOAuth2TokenRequestBody) error { if v == nil { return nil @@ -95,6 +167,24 @@ func validateOpCreateOAuth2TokenInput(v *CreateOAuth2TokenInput) error { } } +func validateOpCreateOAuth2TokenWithIAMInput(v *CreateOAuth2TokenWithIAMInput) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "CreateOAuth2TokenWithIAMInput"} + if v.GrantType == nil { + invalidParams.Add(smithy.NewErrParamRequired("GrantType")) + } + if v.Resource == nil { + invalidParams.Add(smithy.NewErrParamRequired("Resource")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + func validateOpDeleteResourcePermissionStatementInput(v *DeleteResourcePermissionStatementInput) error { if v == nil { return nil @@ -109,3 +199,33 @@ func validateOpDeleteResourcePermissionStatementInput(v *DeleteResourcePermissio return nil } } + +func validateOpIntrospectOAuth2TokenWithIAMInput(v *IntrospectOAuth2TokenWithIAMInput) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "IntrospectOAuth2TokenWithIAMInput"} + if v.Token == nil { + invalidParams.Add(smithy.NewErrParamRequired("Token")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} + +func validateOpRevokeOAuth2TokenWithIAMInput(v *RevokeOAuth2TokenWithIAMInput) error { + if v == nil { + return nil + } + invalidParams := smithy.InvalidParamsError{Context: "RevokeOAuth2TokenWithIAMInput"} + if v.Token == nil { + invalidParams.Add(smithy.NewErrParamRequired("Token")) + } + if invalidParams.Len() > 0 { + return invalidParams + } else { + return nil + } +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/CHANGELOG.md index b7623b6050c..43fee2689cb 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/CHANGELOG.md @@ -1,3 +1,61 @@ +# v1.42.2 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.42.1 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.42.0 (2026-07-21) + +* **Feature**: Add an option to clients to disable clock skew +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.41.1 (2026-07-13) + +* No change notes available for this release. + +# v1.41.0 (2026-07-06) + +* **Feature**: Add request serialization snapshot tests. + +# v1.40.3 (2026-07-01) + +* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.40.2 (2026-06-29) + +* No change notes available for this release. + +# v1.40.1 (2026-06-08) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.40.0 (2026-06-04) + +* **Feature**: Adding new BDD representation of endpoint ruleset +* **Dependency Update**: Update to smithy-go v1.27.1 to fix several union-related deserialization bugs in schema-serde-enabled services. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.39.21 (2026-06-03) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.39.20 (2026-06-02) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.39.19 (2026-05-29) + +* **Dependency Update**: Update to smithy-go v1.26.0. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.39.18 (2026-05-28) + +* **Dependency Update**: Updated to the latest SDK module versions + # v1.39.17 (2026-04-29) * **Dependency Update**: Update to smithy-go v1.25.1. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_client.go index 1cd8aceccef..e24c36846a3 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_client.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_client.go @@ -260,6 +260,10 @@ func (c *Client) invokeOperation( finalizeClientEndpointResolverOptions(&options) + if err := c.addCommonMiddlewares(stack, options, opID); err != nil { + return nil, metadata, err + } + for _, fn := range stackFns { if err := fn(stack, options); err != nil { return nil, metadata, err @@ -364,6 +368,49 @@ func addProtocolFinalizerMiddlewares(stack *middleware.Stack, options Options, o } return nil } + +func (c *Client) addCommonMiddlewares(stack *middleware.Stack, options Options, operation string) error { + if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { + return err + } + if err := addProtocolFinalizerMiddlewares(stack, options, operation); err != nil { + return fmt.Errorf("add protocol finalizers: %v", err) + } + if err := addSetLoggerMiddleware(stack, options); err != nil { + return err + } + if err := addClientRequestID(stack); err != nil { + return err + } + if err := addRetry(stack, options, c); err != nil { + return err + } + if err := addRawResponseToMetadata(stack); err != nil { + return err + } + if err := addSpanRetryLoop(stack, options); err != nil { + return err + } + if err := addClientUserAgent(stack, options); err != nil { + return err + } + if err := addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { + return err + } + if err := addUserAgentRetryMode(stack, options); err != nil { + return err + } + if err := addRecursionDetection(stack); err != nil { + return err + } + if err := addInterceptBeforeRetryLoop(stack, options); err != nil { + return err + } + if err := addInterceptAttempt(stack, options); err != nil { + return err + } + return nil +} func resolveAuthSchemeResolver(options *Options) { if options.AuthSchemeResolver == nil { options.AuthSchemeResolver = &defaultAuthSchemeResolver{} @@ -437,16 +484,17 @@ func setResolvedDefaultsMode(o *Options) { // NewFromConfig returns a new client from the provided config. func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client { opts := Options{ - Region: cfg.Region, - DefaultsMode: cfg.DefaultsMode, - RuntimeEnvironment: cfg.RuntimeEnvironment, - HTTPClient: cfg.HTTPClient, - Credentials: cfg.Credentials, - APIOptions: cfg.APIOptions, - Logger: cfg.Logger, - ClientLogMode: cfg.ClientLogMode, - AppID: cfg.AppID, - AuthSchemePreference: cfg.AuthSchemePreference, + Region: cfg.Region, + DefaultsMode: cfg.DefaultsMode, + RuntimeEnvironment: cfg.RuntimeEnvironment, + HTTPClient: cfg.HTTPClient, + Credentials: cfg.Credentials, + APIOptions: cfg.APIOptions, + Logger: cfg.Logger, + ClientLogMode: cfg.ClientLogMode, + AppID: cfg.AppID, + DisableClockSkewCorrection: cfg.DisableClockSkewCorrection, + AuthSchemePreference: cfg.AuthSchemePreference, } resolveAWSRetryerProvider(cfg, &opts) resolveAWSRetryMaxAttempts(cfg, &opts) @@ -636,15 +684,17 @@ func addClientRequestID(stack *middleware.Stack) error { } func addComputeContentLength(stack *middleware.Stack) error { - return stack.Build.Add(&smithyhttp.ComputeContentLength{}, middleware.After) + return stack.Build.Insert(&smithyhttp.ComputeContentLength{}, "ClientRequestID", middleware.After) } func addRawResponseToMetadata(stack *middleware.Stack) error { return stack.Deserialize.Add(&awsmiddleware.AddRawResponse{}, middleware.Before) } -func addRecordResponseTiming(stack *middleware.Stack) error { - return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{}, middleware.After) +func addRecordResponseTiming(stack *middleware.Stack, options Options) error { + return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{ + DisableClockSkewCorrection: options.DisableClockSkewCorrection, + }, middleware.After) } func addSpanRetryLoop(stack *middleware.Stack, options Options) error { @@ -715,6 +765,7 @@ func addRetry(stack *middleware.Stack, o Options, c *Client) error { m.LogAttempts = o.ClientLogMode.IsRetries() m.OperationMeter = o.MeterProvider.Meter("github.com/aws/aws-sdk-go-v2/service/sns") m.ClientSkew = c.timeOffset + m.DisableClockSkewCorrection = o.DisableClockSkewCorrection }) if err := stack.Finalize.Insert(attempt, "ResolveAuthScheme", middleware.Before); err != nil { return err @@ -817,6 +868,14 @@ func resolveMeterProvider(options *Options) { } } +func newServiceMetadataMiddleware(region, operation string) *awsmiddleware.RegisterServiceMetadata { + return &awsmiddleware.RegisterServiceMetadata{ + Region: region, + ServiceID: ServiceID, + OperationName: operation, + } +} + func addRecursionDetection(stack *middleware.Stack) error { return stack.Build.Add(&awsmiddleware.RecursionDetection{}, middleware.After) } diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_AddPermission.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_AddPermission.go index 7468af00698..997efd69ac0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_AddPermission.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_AddPermission.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -68,9 +66,6 @@ type AddPermissionOutput struct { } func (c *Client) addOperationAddPermissionMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpAddPermission{}, middleware.After) if err != nil { return err @@ -79,19 +74,10 @@ func (c *Client) addOperationAddPermissionMiddlewares(stack *middleware.Stack, o if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "AddPermission"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -101,19 +87,7 @@ func (c *Client) addOperationAddPermissionMiddlewares(stack *middleware.Stack, o if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -122,22 +96,13 @@ func (c *Client) addOperationAddPermissionMiddlewares(stack *middleware.Stack, o if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpAddPermissionValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opAddPermission(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "AddPermission"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -152,22 +117,8 @@ func (c *Client) addOperationAddPermissionMiddlewares(stack *middleware.Stack, o if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opAddPermission(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "AddPermission", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CheckIfPhoneNumberIsOptedOut.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CheckIfPhoneNumberIsOptedOut.go index 65602dc47f4..b2651e51487 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CheckIfPhoneNumberIsOptedOut.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CheckIfPhoneNumberIsOptedOut.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -61,9 +59,6 @@ type CheckIfPhoneNumberIsOptedOutOutput struct { } func (c *Client) addOperationCheckIfPhoneNumberIsOptedOutMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpCheckIfPhoneNumberIsOptedOut{}, middleware.After) if err != nil { return err @@ -72,19 +67,10 @@ func (c *Client) addOperationCheckIfPhoneNumberIsOptedOutMiddlewares(stack *midd if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "CheckIfPhoneNumberIsOptedOut"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -94,19 +80,7 @@ func (c *Client) addOperationCheckIfPhoneNumberIsOptedOutMiddlewares(stack *midd if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -115,22 +89,13 @@ func (c *Client) addOperationCheckIfPhoneNumberIsOptedOutMiddlewares(stack *midd if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpCheckIfPhoneNumberIsOptedOutValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opCheckIfPhoneNumberIsOptedOut(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "CheckIfPhoneNumberIsOptedOut"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -145,22 +110,8 @@ func (c *Client) addOperationCheckIfPhoneNumberIsOptedOutMiddlewares(stack *midd if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opCheckIfPhoneNumberIsOptedOut(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "CheckIfPhoneNumberIsOptedOut", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ConfirmSubscription.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ConfirmSubscription.go index 2c6f999fdff..24e7ba71b76 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ConfirmSubscription.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ConfirmSubscription.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -65,9 +63,6 @@ type ConfirmSubscriptionOutput struct { } func (c *Client) addOperationConfirmSubscriptionMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpConfirmSubscription{}, middleware.After) if err != nil { return err @@ -76,19 +71,10 @@ func (c *Client) addOperationConfirmSubscriptionMiddlewares(stack *middleware.St if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ConfirmSubscription"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -98,19 +84,7 @@ func (c *Client) addOperationConfirmSubscriptionMiddlewares(stack *middleware.St if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -119,22 +93,13 @@ func (c *Client) addOperationConfirmSubscriptionMiddlewares(stack *middleware.St if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpConfirmSubscriptionValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opConfirmSubscription(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ConfirmSubscription"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -149,22 +114,8 @@ func (c *Client) addOperationConfirmSubscriptionMiddlewares(stack *middleware.St if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opConfirmSubscription(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ConfirmSubscription", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformApplication.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformApplication.go index 8e197226a7e..7fa66f9fd7a 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformApplication.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformApplication.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -103,9 +101,6 @@ type CreatePlatformApplicationOutput struct { } func (c *Client) addOperationCreatePlatformApplicationMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpCreatePlatformApplication{}, middleware.After) if err != nil { return err @@ -114,19 +109,10 @@ func (c *Client) addOperationCreatePlatformApplicationMiddlewares(stack *middlew if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "CreatePlatformApplication"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -136,19 +122,7 @@ func (c *Client) addOperationCreatePlatformApplicationMiddlewares(stack *middlew if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -157,22 +131,13 @@ func (c *Client) addOperationCreatePlatformApplicationMiddlewares(stack *middlew if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpCreatePlatformApplicationValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opCreatePlatformApplication(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "CreatePlatformApplication"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -187,22 +152,8 @@ func (c *Client) addOperationCreatePlatformApplicationMiddlewares(stack *middlew if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opCreatePlatformApplication(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "CreatePlatformApplication", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformEndpoint.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformEndpoint.go index 015898cc48b..aa635cff50d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformEndpoint.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreatePlatformEndpoint.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -83,9 +81,6 @@ type CreatePlatformEndpointOutput struct { } func (c *Client) addOperationCreatePlatformEndpointMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpCreatePlatformEndpoint{}, middleware.After) if err != nil { return err @@ -94,19 +89,10 @@ func (c *Client) addOperationCreatePlatformEndpointMiddlewares(stack *middleware if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "CreatePlatformEndpoint"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -116,19 +102,7 @@ func (c *Client) addOperationCreatePlatformEndpointMiddlewares(stack *middleware if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -137,22 +111,13 @@ func (c *Client) addOperationCreatePlatformEndpointMiddlewares(stack *middleware if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpCreatePlatformEndpointValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opCreatePlatformEndpoint(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "CreatePlatformEndpoint"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -167,22 +132,8 @@ func (c *Client) addOperationCreatePlatformEndpointMiddlewares(stack *middleware if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opCreatePlatformEndpoint(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "CreatePlatformEndpoint", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateSMSSandboxPhoneNumber.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateSMSSandboxPhoneNumber.go index 51953e6b867..fde7128088e 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateSMSSandboxPhoneNumber.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateSMSSandboxPhoneNumber.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -62,9 +60,6 @@ type CreateSMSSandboxPhoneNumberOutput struct { } func (c *Client) addOperationCreateSMSSandboxPhoneNumberMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpCreateSMSSandboxPhoneNumber{}, middleware.After) if err != nil { return err @@ -73,19 +68,10 @@ func (c *Client) addOperationCreateSMSSandboxPhoneNumberMiddlewares(stack *middl if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "CreateSMSSandboxPhoneNumber"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -95,19 +81,7 @@ func (c *Client) addOperationCreateSMSSandboxPhoneNumberMiddlewares(stack *middl if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -116,22 +90,13 @@ func (c *Client) addOperationCreateSMSSandboxPhoneNumberMiddlewares(stack *middl if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpCreateSMSSandboxPhoneNumberValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opCreateSMSSandboxPhoneNumber(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "CreateSMSSandboxPhoneNumber"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -146,22 +111,8 @@ func (c *Client) addOperationCreateSMSSandboxPhoneNumberMiddlewares(stack *middl if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opCreateSMSSandboxPhoneNumber(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "CreateSMSSandboxPhoneNumber", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateTopic.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateTopic.go index e437db13c29..69867e2f949 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateTopic.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_CreateTopic.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -218,9 +216,6 @@ type CreateTopicOutput struct { } func (c *Client) addOperationCreateTopicMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpCreateTopic{}, middleware.After) if err != nil { return err @@ -229,19 +224,10 @@ func (c *Client) addOperationCreateTopicMiddlewares(stack *middleware.Stack, opt if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "CreateTopic"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -251,19 +237,7 @@ func (c *Client) addOperationCreateTopicMiddlewares(stack *middleware.Stack, opt if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -272,22 +246,13 @@ func (c *Client) addOperationCreateTopicMiddlewares(stack *middleware.Stack, opt if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpCreateTopicValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opCreateTopic(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "CreateTopic"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -302,22 +267,8 @@ func (c *Client) addOperationCreateTopicMiddlewares(stack *middleware.Stack, opt if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opCreateTopic(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "CreateTopic", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteEndpoint.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteEndpoint.go index 6f734a175e7..6903d0457ad 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteEndpoint.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteEndpoint.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -51,9 +49,6 @@ type DeleteEndpointOutput struct { } func (c *Client) addOperationDeleteEndpointMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpDeleteEndpoint{}, middleware.After) if err != nil { return err @@ -62,19 +57,10 @@ func (c *Client) addOperationDeleteEndpointMiddlewares(stack *middleware.Stack, if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "DeleteEndpoint"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -84,19 +70,7 @@ func (c *Client) addOperationDeleteEndpointMiddlewares(stack *middleware.Stack, if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -105,22 +79,13 @@ func (c *Client) addOperationDeleteEndpointMiddlewares(stack *middleware.Stack, if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpDeleteEndpointValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDeleteEndpoint(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "DeleteEndpoint"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -135,22 +100,8 @@ func (c *Client) addOperationDeleteEndpointMiddlewares(stack *middleware.Stack, if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opDeleteEndpoint(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "DeleteEndpoint", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeletePlatformApplication.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeletePlatformApplication.go index 391f01b072c..b3ce221aa4d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeletePlatformApplication.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeletePlatformApplication.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -49,9 +47,6 @@ type DeletePlatformApplicationOutput struct { } func (c *Client) addOperationDeletePlatformApplicationMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpDeletePlatformApplication{}, middleware.After) if err != nil { return err @@ -60,19 +55,10 @@ func (c *Client) addOperationDeletePlatformApplicationMiddlewares(stack *middlew if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "DeletePlatformApplication"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -82,19 +68,7 @@ func (c *Client) addOperationDeletePlatformApplicationMiddlewares(stack *middlew if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -103,22 +77,13 @@ func (c *Client) addOperationDeletePlatformApplicationMiddlewares(stack *middlew if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpDeletePlatformApplicationValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDeletePlatformApplication(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "DeletePlatformApplication"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -133,22 +98,8 @@ func (c *Client) addOperationDeletePlatformApplicationMiddlewares(stack *middlew if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opDeletePlatformApplication(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "DeletePlatformApplication", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteSMSSandboxPhoneNumber.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteSMSSandboxPhoneNumber.go index 2e8788814f2..d108d4e9a2b 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteSMSSandboxPhoneNumber.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteSMSSandboxPhoneNumber.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -56,9 +54,6 @@ type DeleteSMSSandboxPhoneNumberOutput struct { } func (c *Client) addOperationDeleteSMSSandboxPhoneNumberMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpDeleteSMSSandboxPhoneNumber{}, middleware.After) if err != nil { return err @@ -67,19 +62,10 @@ func (c *Client) addOperationDeleteSMSSandboxPhoneNumberMiddlewares(stack *middl if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "DeleteSMSSandboxPhoneNumber"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -89,19 +75,7 @@ func (c *Client) addOperationDeleteSMSSandboxPhoneNumberMiddlewares(stack *middl if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -110,22 +84,13 @@ func (c *Client) addOperationDeleteSMSSandboxPhoneNumberMiddlewares(stack *middl if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpDeleteSMSSandboxPhoneNumberValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDeleteSMSSandboxPhoneNumber(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "DeleteSMSSandboxPhoneNumber"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -140,22 +105,8 @@ func (c *Client) addOperationDeleteSMSSandboxPhoneNumberMiddlewares(stack *middl if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opDeleteSMSSandboxPhoneNumber(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "DeleteSMSSandboxPhoneNumber", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteTopic.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteTopic.go index 4e8a4cb8fcc..67a5718d303 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteTopic.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_DeleteTopic.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -47,9 +45,6 @@ type DeleteTopicOutput struct { } func (c *Client) addOperationDeleteTopicMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpDeleteTopic{}, middleware.After) if err != nil { return err @@ -58,19 +53,10 @@ func (c *Client) addOperationDeleteTopicMiddlewares(stack *middleware.Stack, opt if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "DeleteTopic"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -80,19 +66,7 @@ func (c *Client) addOperationDeleteTopicMiddlewares(stack *middleware.Stack, opt if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -101,22 +75,13 @@ func (c *Client) addOperationDeleteTopicMiddlewares(stack *middleware.Stack, opt if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpDeleteTopicValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDeleteTopic(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "DeleteTopic"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -131,22 +96,8 @@ func (c *Client) addOperationDeleteTopicMiddlewares(stack *middleware.Stack, opt if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opDeleteTopic(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "DeleteTopic", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetDataProtectionPolicy.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetDataProtectionPolicy.go index bddc5b9c972..17386c8c212 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetDataProtectionPolicy.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetDataProtectionPolicy.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -54,9 +52,6 @@ type GetDataProtectionPolicyOutput struct { } func (c *Client) addOperationGetDataProtectionPolicyMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpGetDataProtectionPolicy{}, middleware.After) if err != nil { return err @@ -65,19 +60,10 @@ func (c *Client) addOperationGetDataProtectionPolicyMiddlewares(stack *middlewar if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "GetDataProtectionPolicy"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -87,19 +73,7 @@ func (c *Client) addOperationGetDataProtectionPolicyMiddlewares(stack *middlewar if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -108,22 +82,13 @@ func (c *Client) addOperationGetDataProtectionPolicyMiddlewares(stack *middlewar if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpGetDataProtectionPolicyValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetDataProtectionPolicy(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "GetDataProtectionPolicy"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -138,22 +103,8 @@ func (c *Client) addOperationGetDataProtectionPolicyMiddlewares(stack *middlewar if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opGetDataProtectionPolicy(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "GetDataProtectionPolicy", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetEndpointAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetEndpointAttributes.go index 744ec2240ef..fc64f8e84be 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetEndpointAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetEndpointAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -68,9 +66,6 @@ type GetEndpointAttributesOutput struct { } func (c *Client) addOperationGetEndpointAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpGetEndpointAttributes{}, middleware.After) if err != nil { return err @@ -79,19 +74,10 @@ func (c *Client) addOperationGetEndpointAttributesMiddlewares(stack *middleware. if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "GetEndpointAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -101,19 +87,7 @@ func (c *Client) addOperationGetEndpointAttributesMiddlewares(stack *middleware. if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -122,22 +96,13 @@ func (c *Client) addOperationGetEndpointAttributesMiddlewares(stack *middleware. if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpGetEndpointAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetEndpointAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "GetEndpointAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -152,22 +117,8 @@ func (c *Client) addOperationGetEndpointAttributesMiddlewares(stack *middleware. if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opGetEndpointAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "GetEndpointAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetPlatformApplicationAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetPlatformApplicationAttributes.go index 0931c7a263e..26c42aaba33 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetPlatformApplicationAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetPlatformApplicationAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -83,9 +81,6 @@ type GetPlatformApplicationAttributesOutput struct { } func (c *Client) addOperationGetPlatformApplicationAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpGetPlatformApplicationAttributes{}, middleware.After) if err != nil { return err @@ -94,19 +89,10 @@ func (c *Client) addOperationGetPlatformApplicationAttributesMiddlewares(stack * if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "GetPlatformApplicationAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -116,19 +102,7 @@ func (c *Client) addOperationGetPlatformApplicationAttributesMiddlewares(stack * if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -137,22 +111,13 @@ func (c *Client) addOperationGetPlatformApplicationAttributesMiddlewares(stack * if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpGetPlatformApplicationAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetPlatformApplicationAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "GetPlatformApplicationAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -167,22 +132,8 @@ func (c *Client) addOperationGetPlatformApplicationAttributesMiddlewares(stack * if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opGetPlatformApplicationAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "GetPlatformApplicationAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSAttributes.go index be9a4dd7038..0c58ba3f152 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -58,9 +56,6 @@ type GetSMSAttributesOutput struct { } func (c *Client) addOperationGetSMSAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpGetSMSAttributes{}, middleware.After) if err != nil { return err @@ -69,19 +64,10 @@ func (c *Client) addOperationGetSMSAttributesMiddlewares(stack *middleware.Stack if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "GetSMSAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -91,19 +77,7 @@ func (c *Client) addOperationGetSMSAttributesMiddlewares(stack *middleware.Stack if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -112,19 +86,10 @@ func (c *Client) addOperationGetSMSAttributesMiddlewares(stack *middleware.Stack if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetSMSAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "GetSMSAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -139,22 +104,8 @@ func (c *Client) addOperationGetSMSAttributesMiddlewares(stack *middleware.Stack if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opGetSMSAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "GetSMSAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSSandboxAccountStatus.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSSandboxAccountStatus.go index 996a280f7f6..f036a984712 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSSandboxAccountStatus.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSMSSandboxAccountStatus.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -56,9 +54,6 @@ type GetSMSSandboxAccountStatusOutput struct { } func (c *Client) addOperationGetSMSSandboxAccountStatusMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpGetSMSSandboxAccountStatus{}, middleware.After) if err != nil { return err @@ -67,19 +62,10 @@ func (c *Client) addOperationGetSMSSandboxAccountStatusMiddlewares(stack *middle if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "GetSMSSandboxAccountStatus"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -89,19 +75,7 @@ func (c *Client) addOperationGetSMSSandboxAccountStatusMiddlewares(stack *middle if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -110,19 +84,10 @@ func (c *Client) addOperationGetSMSSandboxAccountStatusMiddlewares(stack *middle if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetSMSSandboxAccountStatus(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "GetSMSSandboxAccountStatus"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -137,22 +102,8 @@ func (c *Client) addOperationGetSMSSandboxAccountStatusMiddlewares(stack *middle if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opGetSMSSandboxAccountStatus(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "GetSMSSandboxAccountStatus", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSubscriptionAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSubscriptionAttributes.go index 4987b3004b9..e121c7298d8 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSubscriptionAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetSubscriptionAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -109,9 +107,6 @@ type GetSubscriptionAttributesOutput struct { } func (c *Client) addOperationGetSubscriptionAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpGetSubscriptionAttributes{}, middleware.After) if err != nil { return err @@ -120,19 +115,10 @@ func (c *Client) addOperationGetSubscriptionAttributesMiddlewares(stack *middlew if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "GetSubscriptionAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -142,19 +128,7 @@ func (c *Client) addOperationGetSubscriptionAttributesMiddlewares(stack *middlew if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -163,22 +137,13 @@ func (c *Client) addOperationGetSubscriptionAttributesMiddlewares(stack *middlew if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpGetSubscriptionAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetSubscriptionAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "GetSubscriptionAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -193,22 +158,8 @@ func (c *Client) addOperationGetSubscriptionAttributesMiddlewares(stack *middlew if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opGetSubscriptionAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "GetSubscriptionAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetTopicAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetTopicAttributes.go index 8e1bf5489dd..20fd8b0cb99 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetTopicAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_GetTopicAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -129,9 +127,6 @@ type GetTopicAttributesOutput struct { } func (c *Client) addOperationGetTopicAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpGetTopicAttributes{}, middleware.After) if err != nil { return err @@ -140,19 +135,10 @@ func (c *Client) addOperationGetTopicAttributesMiddlewares(stack *middleware.Sta if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "GetTopicAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -162,19 +148,7 @@ func (c *Client) addOperationGetTopicAttributesMiddlewares(stack *middleware.Sta if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -183,22 +157,13 @@ func (c *Client) addOperationGetTopicAttributesMiddlewares(stack *middleware.Sta if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpGetTopicAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGetTopicAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "GetTopicAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -213,22 +178,8 @@ func (c *Client) addOperationGetTopicAttributesMiddlewares(stack *middleware.Sta if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opGetTopicAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "GetTopicAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListEndpointsByPlatformApplication.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListEndpointsByPlatformApplication.go index 60d70d27259..2b3830d02d0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListEndpointsByPlatformApplication.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListEndpointsByPlatformApplication.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -70,9 +69,6 @@ type ListEndpointsByPlatformApplicationOutput struct { } func (c *Client) addOperationListEndpointsByPlatformApplicationMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListEndpointsByPlatformApplication{}, middleware.After) if err != nil { return err @@ -81,19 +77,10 @@ func (c *Client) addOperationListEndpointsByPlatformApplicationMiddlewares(stack if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListEndpointsByPlatformApplication"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -103,19 +90,7 @@ func (c *Client) addOperationListEndpointsByPlatformApplicationMiddlewares(stack if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -124,22 +99,13 @@ func (c *Client) addOperationListEndpointsByPlatformApplicationMiddlewares(stack if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpListEndpointsByPlatformApplicationValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListEndpointsByPlatformApplication(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListEndpointsByPlatformApplication"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -154,12 +120,6 @@ func (c *Client) addOperationListEndpointsByPlatformApplicationMiddlewares(stack if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -249,11 +209,3 @@ type ListEndpointsByPlatformApplicationAPIClient interface { } var _ ListEndpointsByPlatformApplicationAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListEndpointsByPlatformApplication(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListEndpointsByPlatformApplication", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListOriginationNumbers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListOriginationNumbers.go index b7f5641939b..8c9a35c6ba1 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListOriginationNumbers.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListOriginationNumbers.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -58,9 +57,6 @@ type ListOriginationNumbersOutput struct { } func (c *Client) addOperationListOriginationNumbersMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListOriginationNumbers{}, middleware.After) if err != nil { return err @@ -69,19 +65,10 @@ func (c *Client) addOperationListOriginationNumbersMiddlewares(stack *middleware if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListOriginationNumbers"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -91,19 +78,7 @@ func (c *Client) addOperationListOriginationNumbersMiddlewares(stack *middleware if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -112,19 +87,10 @@ func (c *Client) addOperationListOriginationNumbersMiddlewares(stack *middleware if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListOriginationNumbers(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListOriginationNumbers"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -139,12 +105,6 @@ func (c *Client) addOperationListOriginationNumbersMiddlewares(stack *middleware if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -244,11 +204,3 @@ type ListOriginationNumbersAPIClient interface { } var _ ListOriginationNumbersAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListOriginationNumbers(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListOriginationNumbers", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPhoneNumbersOptedOut.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPhoneNumbersOptedOut.go index 10f4482648a..ae7e506010b 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPhoneNumbersOptedOut.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPhoneNumbersOptedOut.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -62,9 +61,6 @@ type ListPhoneNumbersOptedOutOutput struct { } func (c *Client) addOperationListPhoneNumbersOptedOutMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListPhoneNumbersOptedOut{}, middleware.After) if err != nil { return err @@ -73,19 +69,10 @@ func (c *Client) addOperationListPhoneNumbersOptedOutMiddlewares(stack *middlewa if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListPhoneNumbersOptedOut"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -95,19 +82,7 @@ func (c *Client) addOperationListPhoneNumbersOptedOutMiddlewares(stack *middlewa if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -116,19 +91,10 @@ func (c *Client) addOperationListPhoneNumbersOptedOutMiddlewares(stack *middlewa if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListPhoneNumbersOptedOut(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListPhoneNumbersOptedOut"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -143,12 +109,6 @@ func (c *Client) addOperationListPhoneNumbersOptedOutMiddlewares(stack *middlewa if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -237,11 +197,3 @@ type ListPhoneNumbersOptedOutAPIClient interface { } var _ ListPhoneNumbersOptedOutAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListPhoneNumbersOptedOut(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListPhoneNumbersOptedOut", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPlatformApplications.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPlatformApplications.go index 8c450165dd8..2f87c2d8da6 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPlatformApplications.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListPlatformApplications.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -65,9 +64,6 @@ type ListPlatformApplicationsOutput struct { } func (c *Client) addOperationListPlatformApplicationsMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListPlatformApplications{}, middleware.After) if err != nil { return err @@ -76,19 +72,10 @@ func (c *Client) addOperationListPlatformApplicationsMiddlewares(stack *middlewa if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListPlatformApplications"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -98,19 +85,7 @@ func (c *Client) addOperationListPlatformApplicationsMiddlewares(stack *middlewa if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -119,19 +94,10 @@ func (c *Client) addOperationListPlatformApplicationsMiddlewares(stack *middlewa if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListPlatformApplications(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListPlatformApplications"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -146,12 +112,6 @@ func (c *Client) addOperationListPlatformApplicationsMiddlewares(stack *middlewa if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -240,11 +200,3 @@ type ListPlatformApplicationsAPIClient interface { } var _ ListPlatformApplicationsAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListPlatformApplications(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListPlatformApplications", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSMSSandboxPhoneNumbers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSMSSandboxPhoneNumbers.go index 86b861be4d8..0bb58322ad1 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSMSSandboxPhoneNumbers.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSMSSandboxPhoneNumbers.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -68,9 +67,6 @@ type ListSMSSandboxPhoneNumbersOutput struct { } func (c *Client) addOperationListSMSSandboxPhoneNumbersMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListSMSSandboxPhoneNumbers{}, middleware.After) if err != nil { return err @@ -79,19 +75,10 @@ func (c *Client) addOperationListSMSSandboxPhoneNumbersMiddlewares(stack *middle if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListSMSSandboxPhoneNumbers"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -101,19 +88,7 @@ func (c *Client) addOperationListSMSSandboxPhoneNumbersMiddlewares(stack *middle if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -122,19 +97,10 @@ func (c *Client) addOperationListSMSSandboxPhoneNumbersMiddlewares(stack *middle if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListSMSSandboxPhoneNumbers(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListSMSSandboxPhoneNumbers"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -149,12 +115,6 @@ func (c *Client) addOperationListSMSSandboxPhoneNumbersMiddlewares(stack *middle if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -256,11 +216,3 @@ type ListSMSSandboxPhoneNumbersAPIClient interface { } var _ ListSMSSandboxPhoneNumbersAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListSMSSandboxPhoneNumbers(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListSMSSandboxPhoneNumbers", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptions.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptions.go index 62a54231dc8..157113f548e 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptions.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptions.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -58,9 +57,6 @@ type ListSubscriptionsOutput struct { } func (c *Client) addOperationListSubscriptionsMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListSubscriptions{}, middleware.After) if err != nil { return err @@ -69,19 +65,10 @@ func (c *Client) addOperationListSubscriptionsMiddlewares(stack *middleware.Stac if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListSubscriptions"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -91,19 +78,7 @@ func (c *Client) addOperationListSubscriptionsMiddlewares(stack *middleware.Stac if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -112,19 +87,10 @@ func (c *Client) addOperationListSubscriptionsMiddlewares(stack *middleware.Stac if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListSubscriptions(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListSubscriptions"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -139,12 +105,6 @@ func (c *Client) addOperationListSubscriptionsMiddlewares(stack *middleware.Stac if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -231,11 +191,3 @@ type ListSubscriptionsAPIClient interface { } var _ ListSubscriptionsAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListSubscriptions(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListSubscriptions", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptionsByTopic.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptionsByTopic.go index 64331e986e1..af4acf8aa98 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptionsByTopic.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListSubscriptionsByTopic.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -63,9 +62,6 @@ type ListSubscriptionsByTopicOutput struct { } func (c *Client) addOperationListSubscriptionsByTopicMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListSubscriptionsByTopic{}, middleware.After) if err != nil { return err @@ -74,19 +70,10 @@ func (c *Client) addOperationListSubscriptionsByTopicMiddlewares(stack *middlewa if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListSubscriptionsByTopic"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -96,19 +83,7 @@ func (c *Client) addOperationListSubscriptionsByTopicMiddlewares(stack *middlewa if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -117,22 +92,13 @@ func (c *Client) addOperationListSubscriptionsByTopicMiddlewares(stack *middlewa if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpListSubscriptionsByTopicValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListSubscriptionsByTopic(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListSubscriptionsByTopic"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -147,12 +113,6 @@ func (c *Client) addOperationListSubscriptionsByTopicMiddlewares(stack *middlewa if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -241,11 +201,3 @@ type ListSubscriptionsByTopicAPIClient interface { } var _ ListSubscriptionsByTopicAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListSubscriptionsByTopic(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListSubscriptionsByTopic", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTagsForResource.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTagsForResource.go index fda5e6d1736..5549c0cc786 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTagsForResource.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTagsForResource.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -52,9 +50,6 @@ type ListTagsForResourceOutput struct { } func (c *Client) addOperationListTagsForResourceMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListTagsForResource{}, middleware.After) if err != nil { return err @@ -63,19 +58,10 @@ func (c *Client) addOperationListTagsForResourceMiddlewares(stack *middleware.St if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListTagsForResource"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -85,19 +71,7 @@ func (c *Client) addOperationListTagsForResourceMiddlewares(stack *middleware.St if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -106,22 +80,13 @@ func (c *Client) addOperationListTagsForResourceMiddlewares(stack *middleware.St if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpListTagsForResourceValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListTagsForResource(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListTagsForResource"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -136,22 +101,8 @@ func (c *Client) addOperationListTagsForResourceMiddlewares(stack *middleware.St if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opListTagsForResource(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListTagsForResource", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTopics.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTopics.go index 96101d9cc90..9a1aa250cb2 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTopics.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_ListTopics.go @@ -5,7 +5,6 @@ package sns import ( "context" "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -56,9 +55,6 @@ type ListTopicsOutput struct { } func (c *Client) addOperationListTopicsMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpListTopics{}, middleware.After) if err != nil { return err @@ -67,19 +63,10 @@ func (c *Client) addOperationListTopicsMiddlewares(stack *middleware.Stack, opti if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "ListTopics"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -89,19 +76,7 @@ func (c *Client) addOperationListTopicsMiddlewares(stack *middleware.Stack, opti if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -110,19 +85,10 @@ func (c *Client) addOperationListTopicsMiddlewares(stack *middleware.Stack, opti if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opListTopics(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "ListTopics"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -137,12 +103,6 @@ func (c *Client) addOperationListTopicsMiddlewares(stack *middleware.Stack, opti if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } @@ -228,11 +188,3 @@ type ListTopicsAPIClient interface { } var _ ListTopicsAPIClient = (*Client)(nil) - -func newServiceMetadataMiddleware_opListTopics(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "ListTopics", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_OptInPhoneNumber.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_OptInPhoneNumber.go index f7cb0b03bcf..2031ec00c82 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_OptInPhoneNumber.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_OptInPhoneNumber.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -49,9 +47,6 @@ type OptInPhoneNumberOutput struct { } func (c *Client) addOperationOptInPhoneNumberMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpOptInPhoneNumber{}, middleware.After) if err != nil { return err @@ -60,19 +55,10 @@ func (c *Client) addOperationOptInPhoneNumberMiddlewares(stack *middleware.Stack if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "OptInPhoneNumber"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -82,19 +68,7 @@ func (c *Client) addOperationOptInPhoneNumberMiddlewares(stack *middleware.Stack if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -103,22 +77,13 @@ func (c *Client) addOperationOptInPhoneNumberMiddlewares(stack *middleware.Stack if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpOptInPhoneNumberValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opOptInPhoneNumber(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "OptInPhoneNumber"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -133,22 +98,8 @@ func (c *Client) addOperationOptInPhoneNumberMiddlewares(stack *middleware.Stack if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opOptInPhoneNumber(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "OptInPhoneNumber", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Publish.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Publish.go index d3a31816077..507c9e3ea5e 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Publish.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Publish.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -230,9 +228,6 @@ type PublishOutput struct { } func (c *Client) addOperationPublishMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpPublish{}, middleware.After) if err != nil { return err @@ -241,19 +236,10 @@ func (c *Client) addOperationPublishMiddlewares(stack *middleware.Stack, options if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "Publish"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -263,19 +249,7 @@ func (c *Client) addOperationPublishMiddlewares(stack *middleware.Stack, options if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -284,22 +258,13 @@ func (c *Client) addOperationPublishMiddlewares(stack *middleware.Stack, options if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpPublishValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opPublish(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "Publish"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -314,22 +279,8 @@ func (c *Client) addOperationPublishMiddlewares(stack *middleware.Stack, options if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opPublish(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "Publish", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PublishBatch.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PublishBatch.go index 64292891fc9..7ecc4206995 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PublishBatch.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PublishBatch.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -92,9 +90,6 @@ type PublishBatchOutput struct { } func (c *Client) addOperationPublishBatchMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpPublishBatch{}, middleware.After) if err != nil { return err @@ -103,19 +98,10 @@ func (c *Client) addOperationPublishBatchMiddlewares(stack *middleware.Stack, op if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "PublishBatch"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -125,19 +111,7 @@ func (c *Client) addOperationPublishBatchMiddlewares(stack *middleware.Stack, op if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -146,22 +120,13 @@ func (c *Client) addOperationPublishBatchMiddlewares(stack *middleware.Stack, op if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpPublishBatchValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opPublishBatch(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "PublishBatch"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -176,22 +141,8 @@ func (c *Client) addOperationPublishBatchMiddlewares(stack *middleware.Stack, op if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opPublishBatch(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "PublishBatch", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PutDataProtectionPolicy.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PutDataProtectionPolicy.go index 4325abe7943..718a7ba36c5 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PutDataProtectionPolicy.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_PutDataProtectionPolicy.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -59,9 +57,6 @@ type PutDataProtectionPolicyOutput struct { } func (c *Client) addOperationPutDataProtectionPolicyMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpPutDataProtectionPolicy{}, middleware.After) if err != nil { return err @@ -70,19 +65,10 @@ func (c *Client) addOperationPutDataProtectionPolicyMiddlewares(stack *middlewar if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "PutDataProtectionPolicy"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -92,19 +78,7 @@ func (c *Client) addOperationPutDataProtectionPolicyMiddlewares(stack *middlewar if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -113,22 +87,13 @@ func (c *Client) addOperationPutDataProtectionPolicyMiddlewares(stack *middlewar if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpPutDataProtectionPolicyValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opPutDataProtectionPolicy(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "PutDataProtectionPolicy"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -143,22 +108,8 @@ func (c *Client) addOperationPutDataProtectionPolicyMiddlewares(stack *middlewar if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opPutDataProtectionPolicy(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "PutDataProtectionPolicy", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_RemovePermission.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_RemovePermission.go index ffb401ec0f5..fbe8f4a2b3d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_RemovePermission.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_RemovePermission.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -54,9 +52,6 @@ type RemovePermissionOutput struct { } func (c *Client) addOperationRemovePermissionMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpRemovePermission{}, middleware.After) if err != nil { return err @@ -65,19 +60,10 @@ func (c *Client) addOperationRemovePermissionMiddlewares(stack *middleware.Stack if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "RemovePermission"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -87,19 +73,7 @@ func (c *Client) addOperationRemovePermissionMiddlewares(stack *middleware.Stack if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -108,22 +82,13 @@ func (c *Client) addOperationRemovePermissionMiddlewares(stack *middleware.Stack if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpRemovePermissionValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opRemovePermission(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "RemovePermission"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -138,22 +103,8 @@ func (c *Client) addOperationRemovePermissionMiddlewares(stack *middleware.Stack if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opRemovePermission(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "RemovePermission", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetEndpointAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetEndpointAttributes.go index abb7fc6cadb..b2a2ce917ee 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetEndpointAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetEndpointAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -66,9 +64,6 @@ type SetEndpointAttributesOutput struct { } func (c *Client) addOperationSetEndpointAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpSetEndpointAttributes{}, middleware.After) if err != nil { return err @@ -77,19 +72,10 @@ func (c *Client) addOperationSetEndpointAttributesMiddlewares(stack *middleware. if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "SetEndpointAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -99,19 +85,7 @@ func (c *Client) addOperationSetEndpointAttributesMiddlewares(stack *middleware. if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -120,22 +94,13 @@ func (c *Client) addOperationSetEndpointAttributesMiddlewares(stack *middleware. if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpSetEndpointAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSetEndpointAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "SetEndpointAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -150,22 +115,8 @@ func (c *Client) addOperationSetEndpointAttributesMiddlewares(stack *middleware. if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opSetEndpointAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "SetEndpointAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetPlatformApplicationAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetPlatformApplicationAttributes.go index 34fd715db2e..084be5e2a0f 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetPlatformApplicationAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetPlatformApplicationAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -119,9 +117,6 @@ type SetPlatformApplicationAttributesOutput struct { } func (c *Client) addOperationSetPlatformApplicationAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpSetPlatformApplicationAttributes{}, middleware.After) if err != nil { return err @@ -130,19 +125,10 @@ func (c *Client) addOperationSetPlatformApplicationAttributesMiddlewares(stack * if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "SetPlatformApplicationAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -152,19 +138,7 @@ func (c *Client) addOperationSetPlatformApplicationAttributesMiddlewares(stack * if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -173,22 +147,13 @@ func (c *Client) addOperationSetPlatformApplicationAttributesMiddlewares(stack * if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpSetPlatformApplicationAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSetPlatformApplicationAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "SetPlatformApplicationAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -203,22 +168,8 @@ func (c *Client) addOperationSetPlatformApplicationAttributesMiddlewares(stack * if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opSetPlatformApplicationAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "SetPlatformApplicationAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSMSAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSMSAttributes.go index 5c6d4853a8d..844b713c6cd 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSMSAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSMSAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -130,9 +128,6 @@ type SetSMSAttributesOutput struct { } func (c *Client) addOperationSetSMSAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpSetSMSAttributes{}, middleware.After) if err != nil { return err @@ -141,19 +136,10 @@ func (c *Client) addOperationSetSMSAttributesMiddlewares(stack *middleware.Stack if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "SetSMSAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -163,19 +149,7 @@ func (c *Client) addOperationSetSMSAttributesMiddlewares(stack *middleware.Stack if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -184,22 +158,13 @@ func (c *Client) addOperationSetSMSAttributesMiddlewares(stack *middleware.Stack if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpSetSMSAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSetSMSAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "SetSMSAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -214,22 +179,8 @@ func (c *Client) addOperationSetSMSAttributesMiddlewares(stack *middleware.Stack if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opSetSMSAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "SetSMSAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSubscriptionAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSubscriptionAttributes.go index 1781d4fc128..d4e4f16cbe5 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSubscriptionAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetSubscriptionAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -98,9 +96,6 @@ type SetSubscriptionAttributesOutput struct { } func (c *Client) addOperationSetSubscriptionAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpSetSubscriptionAttributes{}, middleware.After) if err != nil { return err @@ -109,19 +104,10 @@ func (c *Client) addOperationSetSubscriptionAttributesMiddlewares(stack *middlew if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "SetSubscriptionAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -131,19 +117,7 @@ func (c *Client) addOperationSetSubscriptionAttributesMiddlewares(stack *middlew if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -152,22 +126,13 @@ func (c *Client) addOperationSetSubscriptionAttributesMiddlewares(stack *middlew if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpSetSubscriptionAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSetSubscriptionAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "SetSubscriptionAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -182,22 +147,8 @@ func (c *Client) addOperationSetSubscriptionAttributesMiddlewares(stack *middlew if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opSetSubscriptionAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "SetSubscriptionAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetTopicAttributes.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetTopicAttributes.go index 4e48daaef66..8ce7265a606 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetTopicAttributes.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_SetTopicAttributes.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -199,9 +197,6 @@ type SetTopicAttributesOutput struct { } func (c *Client) addOperationSetTopicAttributesMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpSetTopicAttributes{}, middleware.After) if err != nil { return err @@ -210,19 +205,10 @@ func (c *Client) addOperationSetTopicAttributesMiddlewares(stack *middleware.Sta if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "SetTopicAttributes"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -232,19 +218,7 @@ func (c *Client) addOperationSetTopicAttributesMiddlewares(stack *middleware.Sta if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -253,22 +227,13 @@ func (c *Client) addOperationSetTopicAttributesMiddlewares(stack *middleware.Sta if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpSetTopicAttributesValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSetTopicAttributes(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "SetTopicAttributes"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -283,22 +248,8 @@ func (c *Client) addOperationSetTopicAttributesMiddlewares(stack *middleware.Sta if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opSetTopicAttributes(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "SetTopicAttributes", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Subscribe.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Subscribe.go index 1cbad848924..f3bb628662e 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Subscribe.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Subscribe.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -192,9 +190,6 @@ type SubscribeOutput struct { } func (c *Client) addOperationSubscribeMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpSubscribe{}, middleware.After) if err != nil { return err @@ -203,19 +198,10 @@ func (c *Client) addOperationSubscribeMiddlewares(stack *middleware.Stack, optio if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "Subscribe"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -225,19 +211,7 @@ func (c *Client) addOperationSubscribeMiddlewares(stack *middleware.Stack, optio if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -246,22 +220,13 @@ func (c *Client) addOperationSubscribeMiddlewares(stack *middleware.Stack, optio if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpSubscribeValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSubscribe(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "Subscribe"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -276,22 +241,8 @@ func (c *Client) addOperationSubscribeMiddlewares(stack *middleware.Stack, optio if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opSubscribe(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "Subscribe", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_TagResource.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_TagResource.go index b5cb65ad324..70c76471535 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_TagResource.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_TagResource.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/aws-sdk-go-v2/service/sns/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" @@ -71,9 +69,6 @@ type TagResourceOutput struct { } func (c *Client) addOperationTagResourceMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpTagResource{}, middleware.After) if err != nil { return err @@ -82,19 +77,10 @@ func (c *Client) addOperationTagResourceMiddlewares(stack *middleware.Stack, opt if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "TagResource"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -104,19 +90,7 @@ func (c *Client) addOperationTagResourceMiddlewares(stack *middleware.Stack, opt if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -125,22 +99,13 @@ func (c *Client) addOperationTagResourceMiddlewares(stack *middleware.Stack, opt if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpTagResourceValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opTagResource(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "TagResource"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -155,22 +120,8 @@ func (c *Client) addOperationTagResourceMiddlewares(stack *middleware.Stack, opt if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opTagResource(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "TagResource", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Unsubscribe.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Unsubscribe.go index 9b8125d420f..4118e3c6613 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Unsubscribe.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_Unsubscribe.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -53,9 +51,6 @@ type UnsubscribeOutput struct { } func (c *Client) addOperationUnsubscribeMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpUnsubscribe{}, middleware.After) if err != nil { return err @@ -64,19 +59,10 @@ func (c *Client) addOperationUnsubscribeMiddlewares(stack *middleware.Stack, opt if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "Unsubscribe"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -86,19 +72,7 @@ func (c *Client) addOperationUnsubscribeMiddlewares(stack *middleware.Stack, opt if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -107,22 +81,13 @@ func (c *Client) addOperationUnsubscribeMiddlewares(stack *middleware.Stack, opt if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpUnsubscribeValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opUnsubscribe(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "Unsubscribe"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -137,22 +102,8 @@ func (c *Client) addOperationUnsubscribeMiddlewares(stack *middleware.Stack, opt if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opUnsubscribe(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "Unsubscribe", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_UntagResource.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_UntagResource.go index 0764236b4b1..a70340dc265 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_UntagResource.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_UntagResource.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -52,9 +50,6 @@ type UntagResourceOutput struct { } func (c *Client) addOperationUntagResourceMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpUntagResource{}, middleware.After) if err != nil { return err @@ -63,19 +58,10 @@ func (c *Client) addOperationUntagResourceMiddlewares(stack *middleware.Stack, o if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "UntagResource"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -85,19 +71,7 @@ func (c *Client) addOperationUntagResourceMiddlewares(stack *middleware.Stack, o if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -106,22 +80,13 @@ func (c *Client) addOperationUntagResourceMiddlewares(stack *middleware.Stack, o if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpUntagResourceValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opUntagResource(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "UntagResource"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -136,22 +101,8 @@ func (c *Client) addOperationUntagResourceMiddlewares(stack *middleware.Stack, o if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opUntagResource(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "UntagResource", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_VerifySMSSandboxPhoneNumber.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_VerifySMSSandboxPhoneNumber.go index bc4cf67d71e..8ad5ec567a6 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_VerifySMSSandboxPhoneNumber.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/api_op_VerifySMSSandboxPhoneNumber.go @@ -4,8 +4,6 @@ package sns import ( "context" - "fmt" - awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) @@ -63,9 +61,6 @@ type VerifySMSSandboxPhoneNumberOutput struct { } func (c *Client) addOperationVerifySMSSandboxPhoneNumberMiddlewares(stack *middleware.Stack, options Options) (err error) { - if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil { - return err - } err = stack.Serialize.Add(&awsAwsquery_serializeOpVerifySMSSandboxPhoneNumber{}, middleware.After) if err != nil { return err @@ -74,19 +69,10 @@ func (c *Client) addOperationVerifySMSSandboxPhoneNumberMiddlewares(stack *middl if err != nil { return err } - if err := addProtocolFinalizerMiddlewares(stack, options, "VerifySMSSandboxPhoneNumber"); err != nil { - return fmt.Errorf("add protocol finalizers: %v", err) - } if err = addlegacyEndpointContextSetter(stack, options); err != nil { return err } - if err = addSetLoggerMiddleware(stack, options); err != nil { - return err - } - if err = addClientRequestID(stack); err != nil { - return err - } if err = addComputeContentLength(stack); err != nil { return err } @@ -96,19 +82,7 @@ func (c *Client) addOperationVerifySMSSandboxPhoneNumberMiddlewares(stack *middl if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRetry(stack, options, c); err != nil { - return err - } - if err = addRawResponseToMetadata(stack); err != nil { - return err - } - if err = addRecordResponseTiming(stack); err != nil { - return err - } - if err = addSpanRetryLoop(stack, options); err != nil { - return err - } - if err = addClientUserAgent(stack, options); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { @@ -117,22 +91,13 @@ func (c *Client) addOperationVerifySMSSandboxPhoneNumberMiddlewares(stack *middl if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { return err } - if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil { - return err - } - if err = addUserAgentRetryMode(stack, options); err != nil { - return err - } if err = addCredentialSource(stack, options); err != nil { return err } if err = addOpVerifySMSSandboxPhoneNumberValidationMiddleware(stack); err != nil { return err } - if err = stack.Initialize.Add(newServiceMetadataMiddleware_opVerifySMSSandboxPhoneNumber(options.Region), middleware.Before); err != nil { - return err - } - if err = addRecursionDetection(stack); err != nil { + if err = stack.Initialize.Add(newServiceMetadataMiddleware(options.Region, "VerifySMSSandboxPhoneNumber"), middleware.Before); err != nil { return err } if err = addRequestIDRetrieverMiddleware(stack); err != nil { @@ -147,22 +112,8 @@ func (c *Client) addOperationVerifySMSSandboxPhoneNumberMiddlewares(stack *middl if err = addDisableHTTPSMiddleware(stack, options); err != nil { return err } - if err = addInterceptBeforeRetryLoop(stack, options); err != nil { - return err - } - if err = addInterceptAttempt(stack, options); err != nil { - return err - } if err = addInterceptors(stack, options); err != nil { return err } return nil } - -func newServiceMetadataMiddleware_opVerifySMSSandboxPhoneNumber(region string) *awsmiddleware.RegisterServiceMetadata { - return &awsmiddleware.RegisterServiceMetadata{ - Region: region, - ServiceID: ServiceID, - OperationName: "VerifySMSSandboxPhoneNumber", - } -} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/auth.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/auth.go index 9f11cc500bc..c0832d29cb0 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/auth.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/auth.go @@ -184,7 +184,7 @@ func (m *resolveAuthSchemeMiddleware) selectScheme(options []*smithyauth.Option) } for _, scheme := range m.options.AuthSchemes { - if scheme.SchemeID() != option.SchemeID { + if !matchSchemeID(scheme.SchemeID(), option.SchemeID) { continue } @@ -197,6 +197,16 @@ func (m *resolveAuthSchemeMiddleware) selectScheme(options []*smithyauth.Option) return nil, false } +func matchSchemeID(registered, option string) bool { + if registered == option { + return true + } + if i := strings.LastIndex(registered, "#"); i != -1 { + return registered[i+1:] == option + } + return false +} + func sortAuthOptions(options []*smithyauth.Option, preferred []string) []*smithyauth.Option { byPriority := make([]*smithyauth.Option, 0, len(options)) for _, prefName := range preferred { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/deserializers.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/deserializers.go index 2da54823f54..56617b3a97f 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/deserializers.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/deserializers.go @@ -19,7 +19,6 @@ import ( "github.com/aws/smithy-go/tracing" smithyhttp "github.com/aws/smithy-go/transport/http" "io" - "io/ioutil" "strconv" "strings" ) @@ -54,7 +53,7 @@ func (m *awsAwsquery_deserializeOpAddPermission) HandleDeserialize(ctx context.C output := &AddPermissionOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -893,7 +892,7 @@ func (m *awsAwsquery_deserializeOpDeleteEndpoint) HandleDeserialize(ctx context. output := &DeleteEndpointOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -976,7 +975,7 @@ func (m *awsAwsquery_deserializeOpDeletePlatformApplication) HandleDeserialize(c output := &DeletePlatformApplicationOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -1186,7 +1185,7 @@ func (m *awsAwsquery_deserializeOpDeleteTopic) HandleDeserialize(ctx context.Con output := &DeleteTopicOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -3667,7 +3666,7 @@ func (m *awsAwsquery_deserializeOpPutDataProtectionPolicy) HandleDeserialize(ctx output := &PutDataProtectionPolicyOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -3756,7 +3755,7 @@ func (m *awsAwsquery_deserializeOpRemovePermission) HandleDeserialize(ctx contex output := &RemovePermissionOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -3842,7 +3841,7 @@ func (m *awsAwsquery_deserializeOpSetEndpointAttributes) HandleDeserialize(ctx c output := &SetEndpointAttributesOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -3928,7 +3927,7 @@ func (m *awsAwsquery_deserializeOpSetPlatformApplicationAttributes) HandleDeseri output := &SetPlatformApplicationAttributesOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -4135,7 +4134,7 @@ func (m *awsAwsquery_deserializeOpSetSubscriptionAttributes) HandleDeserialize(c output := &SetSubscriptionAttributesOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -4227,7 +4226,7 @@ func (m *awsAwsquery_deserializeOpSetTopicAttributes) HandleDeserialize(ctx cont output := &SetTopicAttributesOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } @@ -4579,7 +4578,7 @@ func (m *awsAwsquery_deserializeOpUnsubscribe) HandleDeserialize(ctx context.Con output := &UnsubscribeOutput{} out.Result = output - if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { + if _, err = io.Copy(io.Discard, response.Body); err != nil { return out, metadata, &smithy.DeserializationError{ Err: fmt.Errorf("failed to discard response body, %w", err), } diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/endpoints.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/endpoints.go index c2af00fcc64..964f713fa8e 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/endpoints.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/endpoints.go @@ -14,6 +14,7 @@ import ( internalendpoints "github.com/aws/aws-sdk-go-v2/service/sns/internal/endpoints" smithyauth "github.com/aws/smithy-go/auth" smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/aws/smithy-go/endpoints/private/bdd" "github.com/aws/smithy-go/endpoints/private/rulesfn" "github.com/aws/smithy-go/middleware" "github.com/aws/smithy-go/ptr" @@ -229,6 +230,8 @@ func bindRegion(region string) (*string, error) { return aws.String(endpoints.MapFIPSRegion(region)), nil } +var _ = rulesfn.StringSlice(nil) + // EndpointParameters provides the parameters that influence how endpoints are // resolved. type EndpointParameters struct { @@ -294,21 +297,163 @@ func (p EndpointParameters) WithDefaults() EndpointParameters { return p } -type stringSlice []string +const bddRoot int32 = 2 -func (s stringSlice) Get(i int) *string { - if i < 0 || i >= len(s) { - return nil - } +var bddNodes = [45]int32{ + -1, 1, -1, 0, 14, 3, 1, 4, 100000013, 2, 5, 100000013, 3, 8, 6, 4, 7, 100000012, 5, 100000010, 100000011, 4, 12, 9, 6, 10, 100000009, 7, 100000006, 11, 8, 100000007, 100000008, 5, 13, 100000005, 6, 100000004, 100000005, 3, 100000001, 15, 4, 100000002, 100000003} + +type conditionContext struct { + PartitionResult *awsrulesfn.PartitionConfig +} + +func evalCondition(idx int, params *EndpointParameters, c *conditionContext) bool { + switch idx { + case 0: + return params.Endpoint != nil + case 1: + return params.Region != nil + case 2: + if v := awsrulesfn.GetPartition(*params.Region); v != nil { + c.PartitionResult = v + return true + } + return false + case 3: + return *params.UseFIPS == true + case 4: + return *params.UseDualStack == true + case 5: + return c.PartitionResult.SupportsDualStack == true + case 6: + return c.PartitionResult.SupportsFIPS == true + case 7: + return *params.Region == "us-gov-east-1" + case 8: + return *params.Region == "us-gov-west-1" + } + return false +} - v := s[i] - return &v +func resolveResult(idx int32, params *EndpointParameters, c *conditionContext) (smithyendpoints.Endpoint, error) { + switch idx { + case 0: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint resolution failed: no matching rule") + case 1: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: FIPS and custom endpoint are not supported") + case 2: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Dualstack and custom endpoint are not supported") + case 3: + uriString := *params.Endpoint + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + }, nil + case 4: + uriString := func() string { + var out strings.Builder + out.WriteString("https://sns-fips.") + out.WriteString(*params.Region) + out.WriteString(".") + out.WriteString(c.PartitionResult.DualStackDnsSuffix) + return out.String() + }() + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + }, nil + case 5: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "FIPS and DualStack are enabled, but this partition does not support one or both") + case 6: + uriString := "https://sns.us-gov-east-1.amazonaws.com" + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + }, nil + case 7: + uriString := "https://sns.us-gov-west-1.amazonaws.com" + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + }, nil + case 8: + uriString := func() string { + var out strings.Builder + out.WriteString("https://sns-fips.") + out.WriteString(*params.Region) + out.WriteString(".") + out.WriteString(c.PartitionResult.DnsSuffix) + return out.String() + }() + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + }, nil + case 9: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "FIPS is enabled but this partition does not support FIPS") + case 10: + uriString := func() string { + var out strings.Builder + out.WriteString("https://sns.") + out.WriteString(*params.Region) + out.WriteString(".") + out.WriteString(c.PartitionResult.DualStackDnsSuffix) + return out.String() + }() + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + }, nil + case 11: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "DualStack is enabled but this partition does not support DualStack") + case 12: + uriString := func() string { + var out strings.Builder + out.WriteString("https://sns.") + out.WriteString(*params.Region) + out.WriteString(".") + out.WriteString(c.PartitionResult.DnsSuffix) + return out.String() + }() + uri, err := url.Parse(uriString) + if err != nil { + return smithyendpoints.Endpoint{}, fmt.Errorf("Failed to parse uri: %s", uriString) + } + return smithyendpoints.Endpoint{ + URI: *uri, + Headers: http.Header{}, + }, nil + case 13: + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Missing Region") + } + return smithyendpoints.Endpoint{}, fmt.Errorf("endpoint rule error, invalid result index: %d", idx) } // EndpointResolverV2 provides the interface for resolving service endpoints. type EndpointResolverV2 interface { - // ResolveEndpoint attempts to resolve the endpoint with the provided options, - // returning the endpoint if found. Otherwise an error is returned. ResolveEndpoint(ctx context.Context, params EndpointParameters) ( smithyendpoints.Endpoint, error, ) @@ -332,159 +477,12 @@ func (r *resolver) ResolveEndpoint( if err = params.ValidateRequired(); err != nil { return endpoint, fmt.Errorf("endpoint parameters are not valid, %w", err) } - _UseDualStack := *params.UseDualStack - _ = _UseDualStack - _UseFIPS := *params.UseFIPS - _ = _UseFIPS - if exprVal := params.Endpoint; exprVal != nil { - _Endpoint := *exprVal - _ = _Endpoint - if _UseFIPS == true { - return endpoint, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: FIPS and custom endpoint are not supported") - } - if _UseDualStack == true { - return endpoint, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Dualstack and custom endpoint are not supported") - } - uriString := _Endpoint - - uri, err := url.Parse(uriString) - if err != nil { - return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString) - } - - return smithyendpoints.Endpoint{ - URI: *uri, - Headers: http.Header{}, - }, nil - } - if exprVal := params.Region; exprVal != nil { - _Region := *exprVal - _ = _Region - if exprVal := awsrulesfn.GetPartition(_Region); exprVal != nil { - _PartitionResult := *exprVal - _ = _PartitionResult - if _UseFIPS == true { - if _UseDualStack == true { - if true == _PartitionResult.SupportsFIPS { - if true == _PartitionResult.SupportsDualStack { - uriString := func() string { - var out strings.Builder - out.WriteString("https://sns-fips.") - out.WriteString(_Region) - out.WriteString(".") - out.WriteString(_PartitionResult.DualStackDnsSuffix) - return out.String() - }() - - uri, err := url.Parse(uriString) - if err != nil { - return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString) - } - - return smithyendpoints.Endpoint{ - URI: *uri, - Headers: http.Header{}, - }, nil - } - } - return endpoint, fmt.Errorf("endpoint rule error, %s", "FIPS and DualStack are enabled, but this partition does not support one or both") - } - } - if _UseFIPS == true { - if _PartitionResult.SupportsFIPS == true { - if _Region == "us-gov-east-1" { - uriString := "https://sns.us-gov-east-1.amazonaws.com" - - uri, err := url.Parse(uriString) - if err != nil { - return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString) - } - - return smithyendpoints.Endpoint{ - URI: *uri, - Headers: http.Header{}, - }, nil - } - if _Region == "us-gov-west-1" { - uriString := "https://sns.us-gov-west-1.amazonaws.com" - - uri, err := url.Parse(uriString) - if err != nil { - return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString) - } - - return smithyendpoints.Endpoint{ - URI: *uri, - Headers: http.Header{}, - }, nil - } - uriString := func() string { - var out strings.Builder - out.WriteString("https://sns-fips.") - out.WriteString(_Region) - out.WriteString(".") - out.WriteString(_PartitionResult.DnsSuffix) - return out.String() - }() - - uri, err := url.Parse(uriString) - if err != nil { - return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString) - } - - return smithyendpoints.Endpoint{ - URI: *uri, - Headers: http.Header{}, - }, nil - } - return endpoint, fmt.Errorf("endpoint rule error, %s", "FIPS is enabled but this partition does not support FIPS") - } - if _UseDualStack == true { - if true == _PartitionResult.SupportsDualStack { - uriString := func() string { - var out strings.Builder - out.WriteString("https://sns.") - out.WriteString(_Region) - out.WriteString(".") - out.WriteString(_PartitionResult.DualStackDnsSuffix) - return out.String() - }() - - uri, err := url.Parse(uriString) - if err != nil { - return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString) - } - - return smithyendpoints.Endpoint{ - URI: *uri, - Headers: http.Header{}, - }, nil - } - return endpoint, fmt.Errorf("endpoint rule error, %s", "DualStack is enabled but this partition does not support DualStack") - } - uriString := func() string { - var out strings.Builder - out.WriteString("https://sns.") - out.WriteString(_Region) - out.WriteString(".") - out.WriteString(_PartitionResult.DnsSuffix) - return out.String() - }() - - uri, err := url.Parse(uriString) - if err != nil { - return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString) - } - - return smithyendpoints.Endpoint{ - URI: *uri, - Headers: http.Header{}, - }, nil - } - return endpoint, fmt.Errorf("Endpoint resolution failed. Invalid operation or environment input.") - } - return endpoint, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Missing Region") + c := &conditionContext{} + ref := bdd.Evaluate(bddNodes[:], bddRoot, func(idx int) bool { + return evalCondition(idx, ¶ms, c) + }) + return resolveResult(ref, ¶ms, c) } type endpointParamsBinder interface { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/generated.json index a57c046a793..af4fe51ffd8 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/generated.json +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/generated.json @@ -60,6 +60,8 @@ "internal/endpoints/endpoints.go", "internal/endpoints/endpoints_test.go", "options.go", + "request_snapshot_test.go", + "response_snapshot_test.go", "serializers.go", "snapshot_test.go", "sra_operation_order_test.go", diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/go_module_metadata.go index 88f8840943f..a78894bdc12 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/go_module_metadata.go @@ -3,4 +3,4 @@ package sns // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.39.17" +const goModuleVersion = "1.42.2" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/options.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/options.go index 690b80c0717..5e6cde32e9d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/options.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/options.go @@ -44,6 +44,11 @@ type Options struct { // clients initial default settings. DefaultsMode aws.DefaultsMode + // Disables SDK clock skew correction. When set, the SDK will not adjust request + // signing timestamps to compensate for clock drift between the client and the + // service. + DisableClockSkewCorrection bool + // The endpoint options to be used when attempting to resolve an endpoint. EndpointOptions EndpointResolverOptions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/types/errors.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/types/errors.go index b52c35306db..79bd763a401 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sns/types/errors.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sns/types/errors.go @@ -166,7 +166,7 @@ func (e *EndpointDisabledException) ErrorFault() smithy.ErrorFault { return smit // Indicates that the number of filter polices in your Amazon Web Services account // exceeds the limit. To add more filter polices, submit an Amazon SNS Limit -// Increase case in the Amazon Web ServicesSupport Center. +// Increase case in the Amazon Web Services Support Center. type FilterPolicyLimitExceededException struct { Message *string diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md index c15b7e19da8..9b0d76107da 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md @@ -1,3 +1,30 @@ +# v1.33.2 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.33.1 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.33.0 (2026-07-21) + +* **Feature**: Add an option to clients to disable clock skew +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.32.1 (2026-07-13) + +* No change notes available for this release. + +# v1.32.0 (2026-07-06) + +* **Feature**: Add request serialization snapshot tests. + +# v1.31.5 (2026-07-01) + +* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde +* **Dependency Update**: Updated to the latest SDK module versions + # v1.31.4 (2026-06-29) * No change notes available for this release. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go index 127944307d2..76b3527d35d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go @@ -483,16 +483,17 @@ func setResolvedDefaultsMode(o *Options) { // NewFromConfig returns a new client from the provided config. func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client { opts := Options{ - Region: cfg.Region, - DefaultsMode: cfg.DefaultsMode, - RuntimeEnvironment: cfg.RuntimeEnvironment, - HTTPClient: cfg.HTTPClient, - Credentials: cfg.Credentials, - APIOptions: cfg.APIOptions, - Logger: cfg.Logger, - ClientLogMode: cfg.ClientLogMode, - AppID: cfg.AppID, - AuthSchemePreference: cfg.AuthSchemePreference, + Region: cfg.Region, + DefaultsMode: cfg.DefaultsMode, + RuntimeEnvironment: cfg.RuntimeEnvironment, + HTTPClient: cfg.HTTPClient, + Credentials: cfg.Credentials, + APIOptions: cfg.APIOptions, + Logger: cfg.Logger, + ClientLogMode: cfg.ClientLogMode, + AppID: cfg.AppID, + DisableClockSkewCorrection: cfg.DisableClockSkewCorrection, + AuthSchemePreference: cfg.AuthSchemePreference, } resolveAWSRetryerProvider(cfg, &opts) resolveAWSRetryMaxAttempts(cfg, &opts) @@ -689,8 +690,10 @@ func addRawResponseToMetadata(stack *middleware.Stack) error { return stack.Deserialize.Add(&awsmiddleware.AddRawResponse{}, middleware.Before) } -func addRecordResponseTiming(stack *middleware.Stack) error { - return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{}, middleware.After) +func addRecordResponseTiming(stack *middleware.Stack, options Options) error { + return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{ + DisableClockSkewCorrection: options.DisableClockSkewCorrection, + }, middleware.After) } func addSpanRetryLoop(stack *middleware.Stack, options Options) error { @@ -761,6 +764,7 @@ func addRetry(stack *middleware.Stack, o Options, c *Client) error { m.LogAttempts = o.ClientLogMode.IsRetries() m.OperationMeter = o.MeterProvider.Meter("github.com/aws/aws-sdk-go-v2/service/sso") m.ClientSkew = c.timeOffset + m.DisableClockSkewCorrection = o.DisableClockSkewCorrection }) if err := stack.Finalize.Insert(attempt, "ResolveAuthScheme", middleware.Before); err != nil { return err diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go index a6532c20f14..cefc88ad8eb 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go @@ -79,7 +79,7 @@ func (c *Client) addOperationGetRoleCredentialsMiddlewares(stack *middleware.Sta if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go index b48097259ad..c766f1c44e4 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go @@ -85,7 +85,7 @@ func (c *Client) addOperationListAccountRolesMiddlewares(stack *middleware.Stack if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go index 6142a5d39e9..e8af94746c2 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go @@ -84,7 +84,7 @@ func (c *Client) addOperationListAccountsMiddlewares(stack *middleware.Stack, op if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go index ccafa26f4cf..2f38f944e14 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go @@ -78,7 +78,7 @@ func (c *Client) addOperationLogoutMiddlewares(stack *middleware.Stack, options if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json index 39a393d441c..7aca52b604f 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json @@ -22,6 +22,8 @@ "internal/endpoints/endpoints.go", "internal/endpoints/endpoints_test.go", "options.go", + "request_snapshot_test.go", + "response_snapshot_test.go", "serializers.go", "snapshot_test.go", "sra_operation_order_test.go", diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go index 7bc725826c3..7366a4fae86 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go @@ -3,4 +3,4 @@ package sso // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.31.4" +const goModuleVersion = "1.33.2" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/options.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/options.go index 8b4e34d0642..fbe3ff2a2e2 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sso/options.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sso/options.go @@ -44,6 +44,11 @@ type Options struct { // clients initial default settings. DefaultsMode aws.DefaultsMode + // Disables SDK clock skew correction. When set, the SDK will not adjust request + // signing timestamps to compensate for clock drift between the client and the + // service. + DisableClockSkewCorrection bool + // The endpoint options to be used when attempting to resolve an endpoint. EndpointOptions EndpointResolverOptions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md index f0bac803b8a..7879f2345de 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md @@ -1,3 +1,30 @@ +# v1.38.2 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.38.1 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.38.0 (2026-07-21) + +* **Feature**: Add an option to clients to disable clock skew +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.37.1 (2026-07-13) + +* No change notes available for this release. + +# v1.37.0 (2026-07-06) + +* **Feature**: Add request serialization snapshot tests. + +# v1.36.8 (2026-07-01) + +* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde +* **Dependency Update**: Updated to the latest SDK module versions + # v1.36.7 (2026-06-29) * No change notes available for this release. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go index ebdaff6e62e..0ab277871b5 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go @@ -483,16 +483,17 @@ func setResolvedDefaultsMode(o *Options) { // NewFromConfig returns a new client from the provided config. func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client { opts := Options{ - Region: cfg.Region, - DefaultsMode: cfg.DefaultsMode, - RuntimeEnvironment: cfg.RuntimeEnvironment, - HTTPClient: cfg.HTTPClient, - Credentials: cfg.Credentials, - APIOptions: cfg.APIOptions, - Logger: cfg.Logger, - ClientLogMode: cfg.ClientLogMode, - AppID: cfg.AppID, - AuthSchemePreference: cfg.AuthSchemePreference, + Region: cfg.Region, + DefaultsMode: cfg.DefaultsMode, + RuntimeEnvironment: cfg.RuntimeEnvironment, + HTTPClient: cfg.HTTPClient, + Credentials: cfg.Credentials, + APIOptions: cfg.APIOptions, + Logger: cfg.Logger, + ClientLogMode: cfg.ClientLogMode, + AppID: cfg.AppID, + DisableClockSkewCorrection: cfg.DisableClockSkewCorrection, + AuthSchemePreference: cfg.AuthSchemePreference, } resolveAWSRetryerProvider(cfg, &opts) resolveAWSRetryMaxAttempts(cfg, &opts) @@ -689,8 +690,10 @@ func addRawResponseToMetadata(stack *middleware.Stack) error { return stack.Deserialize.Add(&awsmiddleware.AddRawResponse{}, middleware.Before) } -func addRecordResponseTiming(stack *middleware.Stack) error { - return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{}, middleware.After) +func addRecordResponseTiming(stack *middleware.Stack, options Options) error { + return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{ + DisableClockSkewCorrection: options.DisableClockSkewCorrection, + }, middleware.After) } func addSpanRetryLoop(stack *middleware.Stack, options Options) error { @@ -761,6 +764,7 @@ func addRetry(stack *middleware.Stack, o Options, c *Client) error { m.LogAttempts = o.ClientLogMode.IsRetries() m.OperationMeter = o.MeterProvider.Meter("github.com/aws/aws-sdk-go-v2/service/ssooidc") m.ClientSkew = c.timeOffset + m.DisableClockSkewCorrection = o.DisableClockSkewCorrection }) if err := stack.Finalize.Insert(attempt, "ResolveAuthScheme", middleware.Before); err != nil { return err diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go index 5c1df1c088b..bba750bc707 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go @@ -149,7 +149,7 @@ func (c *Client) addOperationCreateTokenMiddlewares(stack *middleware.Stack, opt if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go index 088e7f2ec88..2c6de5a8394 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go @@ -196,7 +196,7 @@ func (c *Client) addOperationCreateTokenWithIAMMiddlewares(stack *middleware.Sta if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go index 4632f365695..2df6cba224a 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go @@ -120,7 +120,7 @@ func (c *Client) addOperationRegisterClientMiddlewares(stack *middleware.Stack, if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go index 3417f8dbd33..232ff802ebd 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go @@ -102,7 +102,7 @@ func (c *Client) addOperationStartDeviceAuthorizationMiddlewares(stack *middlewa if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json index 1e34b9a9d50..8f46b38d329 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json @@ -22,6 +22,8 @@ "internal/endpoints/endpoints.go", "internal/endpoints/endpoints_test.go", "options.go", + "request_snapshot_test.go", + "response_snapshot_test.go", "serializers.go", "snapshot_test.go", "sra_operation_order_test.go", diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go index d1f579cfae8..7b63f480f71 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go @@ -3,4 +3,4 @@ package ssooidc // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.36.7" +const goModuleVersion = "1.38.2" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/options.go b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/options.go index c2eac091904..73a47ccfb8c 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/options.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/options.go @@ -44,6 +44,11 @@ type Options struct { // clients initial default settings. DefaultsMode aws.DefaultsMode + // Disables SDK clock skew correction. When set, the SDK will not adjust request + // signing timestamps to compensate for clock drift between the client and the + // service. + DisableClockSkewCorrection bool + // The endpoint options to be used when attempting to resolve an endpoint. EndpointOptions EndpointResolverOptions diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md index d0dbd1b80f9..4613abde315 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md @@ -1,3 +1,30 @@ +# v1.45.2 (2026-07-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.45.1 (2026-07-28) + +* **Dependency Update**: Update to smithy-go v1.27.5. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.45.0 (2026-07-21) + +* **Feature**: Add an option to clients to disable clock skew +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.44.1 (2026-07-13) + +* No change notes available for this release. + +# v1.44.0 (2026-07-06) + +* **Feature**: Add request serialization snapshot tests. + +# v1.43.5 (2026-07-01) + +* **Bug Fix**: Bump smithy-go to 1.27.3, fix JSON encorder for document.Number, endpoint host label format validation and CBOR union serialization on new serde +* **Dependency Update**: Updated to the latest SDK module versions + # v1.43.4 (2026-06-29) * No change notes available for this release. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go index c0d927a0c8d..da6a5b3060c 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go @@ -497,16 +497,17 @@ func setResolvedDefaultsMode(o *Options) { // NewFromConfig returns a new client from the provided config. func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client { opts := Options{ - Region: cfg.Region, - DefaultsMode: cfg.DefaultsMode, - RuntimeEnvironment: cfg.RuntimeEnvironment, - HTTPClient: cfg.HTTPClient, - Credentials: cfg.Credentials, - APIOptions: cfg.APIOptions, - Logger: cfg.Logger, - ClientLogMode: cfg.ClientLogMode, - AppID: cfg.AppID, - AuthSchemePreference: cfg.AuthSchemePreference, + Region: cfg.Region, + DefaultsMode: cfg.DefaultsMode, + RuntimeEnvironment: cfg.RuntimeEnvironment, + HTTPClient: cfg.HTTPClient, + Credentials: cfg.Credentials, + APIOptions: cfg.APIOptions, + Logger: cfg.Logger, + ClientLogMode: cfg.ClientLogMode, + AppID: cfg.AppID, + DisableClockSkewCorrection: cfg.DisableClockSkewCorrection, + AuthSchemePreference: cfg.AuthSchemePreference, } resolveAWSRetryerProvider(cfg, &opts) resolveAWSRetryMaxAttempts(cfg, &opts) @@ -703,8 +704,10 @@ func addRawResponseToMetadata(stack *middleware.Stack) error { return stack.Deserialize.Add(&awsmiddleware.AddRawResponse{}, middleware.Before) } -func addRecordResponseTiming(stack *middleware.Stack) error { - return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{}, middleware.After) +func addRecordResponseTiming(stack *middleware.Stack, options Options) error { + return stack.Deserialize.Add(&awsmiddleware.RecordResponseTiming{ + DisableClockSkewCorrection: options.DisableClockSkewCorrection, + }, middleware.After) } func addSpanRetryLoop(stack *middleware.Stack, options Options) error { @@ -775,6 +778,7 @@ func addRetry(stack *middleware.Stack, o Options, c *Client) error { m.LogAttempts = o.ClientLogMode.IsRetries() m.OperationMeter = o.MeterProvider.Meter("github.com/aws/aws-sdk-go-v2/service/sts") m.ClientSkew = c.timeOffset + m.DisableClockSkewCorrection = o.DisableClockSkewCorrection }) if err := stack.Finalize.Insert(attempt, "ResolveAuthScheme", middleware.Before); err != nil { return err diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go index a1c0534bc54..d10f11a620c 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go @@ -434,7 +434,7 @@ func (c *Client) addOperationAssumeRoleMiddlewares(stack *middleware.Stack, opti if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go index 16ffcf2efba..bd5bfdc224c 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go @@ -369,7 +369,7 @@ func (c *Client) addOperationAssumeRoleWithSAMLMiddlewares(stack *middleware.Sta if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go index 2fe5f9284f1..6f6ea05b5ed 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go @@ -386,7 +386,7 @@ func (c *Client) addOperationAssumeRoleWithWebIdentityMiddlewares(stack *middlew if err = addResolveEndpointMiddleware(stack, options); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go index 353512bb265..92aee490801 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go @@ -143,7 +143,7 @@ func (c *Client) addOperationAssumeRootMiddlewares(stack *middleware.Stack, opti if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go index 2e54340ef41..e3294e3241d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go @@ -103,7 +103,7 @@ func (c *Client) addOperationDecodeAuthorizationMessageMiddlewares(stack *middle if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go index c1e9af44033..4d1dbed59dc 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go @@ -94,7 +94,7 @@ func (c *Client) addOperationGetAccessKeyInfoMiddlewares(stack *middleware.Stack if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go index 7c2b4e92203..8901bef2c40 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go @@ -85,7 +85,7 @@ func (c *Client) addOperationGetCallerIdentityMiddlewares(stack *middleware.Stac if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go index e00165161e3..f013cb9330d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go @@ -83,7 +83,7 @@ func (c *Client) addOperationGetDelegatedAccessTokenMiddlewares(stack *middlewar if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go index ba5f92bef8c..fbee53221e7 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go @@ -307,7 +307,7 @@ func (c *Client) addOperationGetFederationTokenMiddlewares(stack *middleware.Sta if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go index 644e95ece86..6b5c8ed171d 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go @@ -156,7 +156,7 @@ func (c *Client) addOperationGetSessionTokenMiddlewares(stack *middleware.Stack, if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetWebIdentityToken.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetWebIdentityToken.go index 09cbebc2531..1c45a28e736 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetWebIdentityToken.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetWebIdentityToken.go @@ -106,7 +106,7 @@ func (c *Client) addOperationGetWebIdentityTokenMiddlewares(stack *middleware.St if err = addComputePayloadSHA256(stack); err != nil { return err } - if err = addRecordResponseTiming(stack); err != nil { + if err = addRecordResponseTiming(stack, options); err != nil { return err } if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json index 2fc7b400f7c..6a759b4cc20 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json @@ -32,6 +32,8 @@ "internal/endpoints/endpoints.go", "internal/endpoints/endpoints_test.go", "options.go", + "request_snapshot_test.go", + "response_snapshot_test.go", "serializers.go", "snapshot_test.go", "sra_operation_order_test.go", diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go index 92bbf3754ba..6079b28d330 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go @@ -3,4 +3,4 @@ package sts // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.43.4" +const goModuleVersion = "1.45.2" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/options.go b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/options.go index a9f2361fd32..b3c9df17f3c 100644 --- a/vendor/github.com/aws/aws-sdk-go-v2/service/sts/options.go +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/sts/options.go @@ -46,6 +46,11 @@ type Options struct { // clients initial default settings. DefaultsMode aws.DefaultsMode + // Disables SDK clock skew correction. When set, the SDK will not adjust request + // signing timestamps to compensate for clock drift between the client and the + // service. + DisableClockSkewCorrection bool + // The endpoint options to be used when attempting to resolve an endpoint. EndpointOptions EndpointResolverOptions diff --git a/vendor/github.com/aws/smithy-go/AGENTS.md b/vendor/github.com/aws/smithy-go/AGENTS.md index e2a75b8ea19..de1e3b2bbe9 100644 --- a/vendor/github.com/aws/smithy-go/AGENTS.md +++ b/vendor/github.com/aws/smithy-go/AGENTS.md @@ -68,8 +68,9 @@ cd codegen && ./gradlew build cd codegen && ./gradlew publishToMavenLocal ``` -The codegen artifact version is fixed at `0.1.0` and is not published to -Maven Central — you **MUST** `publishToMavenLocal`. +The codegen artifact version is published to Maven Central and bumped on each +release. For local development against unreleased codegen changes, use +`publishToMavenLocal` and point consumers at `mavenLocal()`. ## Runtime architecture diff --git a/vendor/github.com/aws/smithy-go/CHANGELOG.md b/vendor/github.com/aws/smithy-go/CHANGELOG.md index 6ff611a8df0..0140cf10eab 100644 --- a/vendor/github.com/aws/smithy-go/CHANGELOG.md +++ b/vendor/github.com/aws/smithy-go/CHANGELOG.md @@ -1,3 +1,41 @@ +# Release (2026-07-27) + +## General Highlights +* **Dependency Update**: Updated to the latest SDK module versions + +## Module Highlights +* `github.com/aws/smithy-go`: v1.27.5 + * **Bug Fix**: Fix a performance issue in awsQuery with large response payloads. + +# Release (2026-07-16) + +## General Highlights +* **Dependency Update**: Updated to the latest SDK module versions + +## Module Highlights +* `github.com/aws/smithy-go/aws-http-auth`: [v1.2.1](aws-http-auth/CHANGELOG.md#v121-2026-07-16) + * **Bug Fix**: Use r.URL.Host when r.Host is unset. +* `github.com/aws/smithy-go/aws-http-auth-schemes`: [v1.0.0](aws-http-auth-schemes/CHANGELOG.md#v100-2026-07-16) + * **Release**: Module `github.com/aws/smithy-go/aws-http-auth-schemes` adds generic smithy-go client support for AWS Sigv4 and Sigv4a. + +# Release (2026-06-26) + +## General Highlights +* **Dependency Update**: Updated to the latest SDK module versions + +## Module Highlights +* `github.com/aws/smithy-go`: v1.27.3 + * **Bug Fix**: Fix bug in JSON doc encoder and endpoint host label format validation + +# Release (2026-06-05) + +## General Highlights +* **Dependency Update**: Updated to the latest SDK module versions + +## Module Highlights +* `github.com/aws/smithy-go`: v1.27.2 + * **Bug Fix**: Fix incorrect serialization of unions in CBOR-based protocols. + # Release (2026-06-04) ## General Highlights diff --git a/vendor/github.com/aws/smithy-go/README.md b/vendor/github.com/aws/smithy-go/README.md index c5e14564b41..ac5a0a6139f 100644 --- a/vendor/github.com/aws/smithy-go/README.md +++ b/vendor/github.com/aws/smithy-go/README.md @@ -11,8 +11,8 @@ The smithy-go runtime requires a minimum version of Go 1.24. ## :warning: Client codegen is unstable The client code generator in this repository powers the aws-sdk-go-v2. -Arbitrary client generation, while technically possible, is in an early stage -of development: +Arbitrary client generation, while possible, is in an early stage of +development: * Generated clients are missing certain features that were originally implemented SDK-side (e.g. retries) @@ -32,8 +32,6 @@ This repository implements the following Smithy build plugins: | `go-server-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go server code generation for Smithy models. | | `go-shape-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go shape code generation (types only) for Smithy models. | -**NOTE: Build plugins are not currently published to mavenCentral. You must publish to mavenLocal to make the build plugins visible to the Smithy CLI. The artifact version is currently fixed at 0.1.0.** - ## `go-codegen` ### Configuration @@ -79,7 +77,7 @@ example created from `smithy init`: ], "maven": { "dependencies": [ - "software.amazon.smithy.go:smithy-go-codegen:0.1.0" + "software.amazon.smithy.go:smithy-go-codegen:[0.1.0,2.0)" ] }, "plugins": { diff --git a/vendor/github.com/aws/smithy-go/encoding/json/value.go b/vendor/github.com/aws/smithy-go/encoding/json/value.go index b41ff1e15c2..eac49c44c2e 100644 --- a/vendor/github.com/aws/smithy-go/encoding/json/value.go +++ b/vendor/github.com/aws/smithy-go/encoding/json/value.go @@ -106,6 +106,11 @@ func (jv Value) BigInteger(v *big.Int) { // BigDecimal encodes v as JSON value func (jv Value) BigDecimal(v *big.Float) { + if v.Sign() == 0 && v.Signbit() { + // Preserve negative zero sign which Int64() would lose. + jv.w.Write([]byte("-0")) + return + } if i, accuracy := v.Int64(); accuracy == big.Exact { jv.Long(i) return diff --git a/vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/uri.go b/vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/uri.go index 0c11541276b..68828dbfe94 100644 --- a/vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/uri.go +++ b/vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/uri.go @@ -27,6 +27,9 @@ func IsValidHostLabel(input string, allowSubDomains bool) bool { if !smithyhttp.ValidHostLabel(label) { return false } + if label[0] == '-' || label[len(label)-1] == '-' { + return false + } } return true diff --git a/vendor/github.com/aws/smithy-go/go_module_metadata.go b/vendor/github.com/aws/smithy-go/go_module_metadata.go index ba81f77281f..4277e6869ad 100644 --- a/vendor/github.com/aws/smithy-go/go_module_metadata.go +++ b/vendor/github.com/aws/smithy-go/go_module_metadata.go @@ -3,4 +3,4 @@ package smithy // goModuleVersion is the tagged release for this module -const goModuleVersion = "1.27.1" +const goModuleVersion = "1.27.5" diff --git a/vendor/github.com/aws/smithy-go/transport/http/host.go b/vendor/github.com/aws/smithy-go/transport/http/host.go index db9801bea52..b504a455da2 100644 --- a/vendor/github.com/aws/smithy-go/transport/http/host.go +++ b/vendor/github.com/aws/smithy-go/transport/http/host.go @@ -69,7 +69,7 @@ func ValidPortNumber(port string) bool { return true } -// ValidHostLabel returns whether the label is a valid RFC 3986 host label. +// ValidHostLabel returns whether the label is a valid RFC 952/1123 host label. func ValidHostLabel(label string) bool { if l := len(label); l == 0 || l > 63 { return false diff --git a/vendor/github.com/cenkalti/backoff/v4/.gitignore b/vendor/github.com/cenkalti/backoff/v4/.gitignore deleted file mode 100644 index 50d95c548b6..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -# IDEs -.idea/ diff --git a/vendor/github.com/cenkalti/backoff/v4/LICENSE b/vendor/github.com/cenkalti/backoff/v4/LICENSE deleted file mode 100644 index 89b81799655..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Cenk Altı - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/cenkalti/backoff/v4/README.md b/vendor/github.com/cenkalti/backoff/v4/README.md deleted file mode 100644 index 9433004a280..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Coverage Status][coveralls image]][coveralls] - -This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. - -[Exponential backoff][exponential backoff wiki] -is an algorithm that uses feedback to multiplicatively decrease the rate of some process, -in order to gradually find an acceptable rate. -The retries exponentially increase and stop increasing when a certain threshold is met. - -## Usage - -Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end. - -Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation. - -## Contributing - -* I would like to keep this library as small as possible. -* Please don't send a PR without opening an issue and discussing it first. -* If proposed change is not a common use case, I will probably not accept it. - -[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4 -[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png -[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master -[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master - -[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java -[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff - -[advanced example]: https://pkg.go.dev/github.com/cenkalti/backoff/v4?tab=doc#pkg-examples diff --git a/vendor/github.com/cenkalti/backoff/v4/backoff.go b/vendor/github.com/cenkalti/backoff/v4/backoff.go deleted file mode 100644 index 3676ee405d8..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/backoff.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package backoff implements backoff algorithms for retrying operations. -// -// Use Retry function for retrying operations that may fail. -// If Retry does not meet your needs, -// copy/paste the function into your project and modify as you wish. -// -// There is also Ticker type similar to time.Ticker. -// You can use it if you need to work with channels. -// -// See Examples section below for usage examples. -package backoff - -import "time" - -// BackOff is a backoff policy for retrying an operation. -type BackOff interface { - // NextBackOff returns the duration to wait before retrying the operation, - // or backoff. Stop to indicate that no more retries should be made. - // - // Example usage: - // - // duration := backoff.NextBackOff(); - // if (duration == backoff.Stop) { - // // Do not retry operation. - // } else { - // // Sleep for duration and retry operation. - // } - // - NextBackOff() time.Duration - - // Reset to initial state. - Reset() -} - -// Stop indicates that no more retries should be made for use in NextBackOff(). -const Stop time.Duration = -1 - -// ZeroBackOff is a fixed backoff policy whose backoff time is always zero, -// meaning that the operation is retried immediately without waiting, indefinitely. -type ZeroBackOff struct{} - -func (b *ZeroBackOff) Reset() {} - -func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } - -// StopBackOff is a fixed backoff policy that always returns backoff.Stop for -// NextBackOff(), meaning that the operation should never be retried. -type StopBackOff struct{} - -func (b *StopBackOff) Reset() {} - -func (b *StopBackOff) NextBackOff() time.Duration { return Stop } - -// ConstantBackOff is a backoff policy that always returns the same backoff delay. -// This is in contrast to an exponential backoff policy, -// which returns a delay that grows longer as you call NextBackOff() over and over again. -type ConstantBackOff struct { - Interval time.Duration -} - -func (b *ConstantBackOff) Reset() {} -func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } - -func NewConstantBackOff(d time.Duration) *ConstantBackOff { - return &ConstantBackOff{Interval: d} -} diff --git a/vendor/github.com/cenkalti/backoff/v4/context.go b/vendor/github.com/cenkalti/backoff/v4/context.go deleted file mode 100644 index 48482330eb7..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/context.go +++ /dev/null @@ -1,62 +0,0 @@ -package backoff - -import ( - "context" - "time" -) - -// BackOffContext is a backoff policy that stops retrying after the context -// is canceled. -type BackOffContext interface { // nolint: golint - BackOff - Context() context.Context -} - -type backOffContext struct { - BackOff - ctx context.Context -} - -// WithContext returns a BackOffContext with context ctx -// -// ctx must not be nil -func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint - if ctx == nil { - panic("nil context") - } - - if b, ok := b.(*backOffContext); ok { - return &backOffContext{ - BackOff: b.BackOff, - ctx: ctx, - } - } - - return &backOffContext{ - BackOff: b, - ctx: ctx, - } -} - -func getContext(b BackOff) context.Context { - if cb, ok := b.(BackOffContext); ok { - return cb.Context() - } - if tb, ok := b.(*backOffTries); ok { - return getContext(tb.delegate) - } - return context.Background() -} - -func (b *backOffContext) Context() context.Context { - return b.ctx -} - -func (b *backOffContext) NextBackOff() time.Duration { - select { - case <-b.ctx.Done(): - return Stop - default: - return b.BackOff.NextBackOff() - } -} diff --git a/vendor/github.com/cenkalti/backoff/v4/exponential.go b/vendor/github.com/cenkalti/backoff/v4/exponential.go deleted file mode 100644 index aac99f196ad..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/exponential.go +++ /dev/null @@ -1,216 +0,0 @@ -package backoff - -import ( - "math/rand" - "time" -) - -/* -ExponentialBackOff is a backoff implementation that increases the backoff -period for each retry attempt using a randomization function that grows exponentially. - -NextBackOff() is calculated using the following formula: - - randomized interval = - RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) - -In other words NextBackOff() will range between the randomization factor -percentage below and above the retry interval. - -For example, given the following parameters: - - RetryInterval = 2 - RandomizationFactor = 0.5 - Multiplier = 2 - -the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, -multiplied by the exponential, that is, between 2 and 6 seconds. - -Note: MaxInterval caps the RetryInterval and not the randomized interval. - -If the time elapsed since an ExponentialBackOff instance is created goes past the -MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop. - -The elapsed time can be reset by calling Reset(). - -Example: Given the following default arguments, for 10 tries the sequence will be, -and assuming we go over the MaxElapsedTime on the 10th try: - - Request # RetryInterval (seconds) Randomized Interval (seconds) - - 1 0.5 [0.25, 0.75] - 2 0.75 [0.375, 1.125] - 3 1.125 [0.562, 1.687] - 4 1.687 [0.8435, 2.53] - 5 2.53 [1.265, 3.795] - 6 3.795 [1.897, 5.692] - 7 5.692 [2.846, 8.538] - 8 8.538 [4.269, 12.807] - 9 12.807 [6.403, 19.210] - 10 19.210 backoff.Stop - -Note: Implementation is not thread-safe. -*/ -type ExponentialBackOff struct { - InitialInterval time.Duration - RandomizationFactor float64 - Multiplier float64 - MaxInterval time.Duration - // After MaxElapsedTime the ExponentialBackOff returns Stop. - // It never stops if MaxElapsedTime == 0. - MaxElapsedTime time.Duration - Stop time.Duration - Clock Clock - - currentInterval time.Duration - startTime time.Time -} - -// Clock is an interface that returns current time for BackOff. -type Clock interface { - Now() time.Time -} - -// ExponentialBackOffOpts is a function type used to configure ExponentialBackOff options. -type ExponentialBackOffOpts func(*ExponentialBackOff) - -// Default values for ExponentialBackOff. -const ( - DefaultInitialInterval = 500 * time.Millisecond - DefaultRandomizationFactor = 0.5 - DefaultMultiplier = 1.5 - DefaultMaxInterval = 60 * time.Second - DefaultMaxElapsedTime = 15 * time.Minute -) - -// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. -func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff { - b := &ExponentialBackOff{ - InitialInterval: DefaultInitialInterval, - RandomizationFactor: DefaultRandomizationFactor, - Multiplier: DefaultMultiplier, - MaxInterval: DefaultMaxInterval, - MaxElapsedTime: DefaultMaxElapsedTime, - Stop: Stop, - Clock: SystemClock, - } - for _, fn := range opts { - fn(b) - } - b.Reset() - return b -} - -// WithInitialInterval sets the initial interval between retries. -func WithInitialInterval(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.InitialInterval = duration - } -} - -// WithRandomizationFactor sets the randomization factor to add jitter to intervals. -func WithRandomizationFactor(randomizationFactor float64) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.RandomizationFactor = randomizationFactor - } -} - -// WithMultiplier sets the multiplier for increasing the interval after each retry. -func WithMultiplier(multiplier float64) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.Multiplier = multiplier - } -} - -// WithMaxInterval sets the maximum interval between retries. -func WithMaxInterval(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.MaxInterval = duration - } -} - -// WithMaxElapsedTime sets the maximum total time for retries. -func WithMaxElapsedTime(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.MaxElapsedTime = duration - } -} - -// WithRetryStopDuration sets the duration after which retries should stop. -func WithRetryStopDuration(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.Stop = duration - } -} - -// WithClockProvider sets the clock used to measure time. -func WithClockProvider(clock Clock) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.Clock = clock - } -} - -type systemClock struct{} - -func (t systemClock) Now() time.Time { - return time.Now() -} - -// SystemClock implements Clock interface that uses time.Now(). -var SystemClock = systemClock{} - -// Reset the interval back to the initial retry interval and restarts the timer. -// Reset must be called before using b. -func (b *ExponentialBackOff) Reset() { - b.currentInterval = b.InitialInterval - b.startTime = b.Clock.Now() -} - -// NextBackOff calculates the next backoff interval using the formula: -// Randomized interval = RetryInterval * (1 ± RandomizationFactor) -func (b *ExponentialBackOff) NextBackOff() time.Duration { - // Make sure we have not gone over the maximum elapsed time. - elapsed := b.GetElapsedTime() - next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) - b.incrementCurrentInterval() - if b.MaxElapsedTime != 0 && elapsed+next > b.MaxElapsedTime { - return b.Stop - } - return next -} - -// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance -// is created and is reset when Reset() is called. -// -// The elapsed time is computed using time.Now().UnixNano(). It is -// safe to call even while the backoff policy is used by a running -// ticker. -func (b *ExponentialBackOff) GetElapsedTime() time.Duration { - return b.Clock.Now().Sub(b.startTime) -} - -// Increments the current interval by multiplying it with the multiplier. -func (b *ExponentialBackOff) incrementCurrentInterval() { - // Check for overflow, if overflow is detected set the current interval to the max interval. - if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { - b.currentInterval = b.MaxInterval - } else { - b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) - } -} - -// Returns a random value from the following interval: -// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval]. -func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { - if randomizationFactor == 0 { - return currentInterval // make sure no randomness is used when randomizationFactor is 0. - } - var delta = randomizationFactor * float64(currentInterval) - var minInterval = float64(currentInterval) - delta - var maxInterval = float64(currentInterval) + delta - - // Get a random value from the range [minInterval, maxInterval]. - // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then - // we want a 33% chance for selecting either 1, 2 or 3. - return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) -} diff --git a/vendor/github.com/cenkalti/backoff/v4/retry.go b/vendor/github.com/cenkalti/backoff/v4/retry.go deleted file mode 100644 index b9c0c51cd75..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/retry.go +++ /dev/null @@ -1,146 +0,0 @@ -package backoff - -import ( - "errors" - "time" -) - -// An OperationWithData is executing by RetryWithData() or RetryNotifyWithData(). -// The operation will be retried using a backoff policy if it returns an error. -type OperationWithData[T any] func() (T, error) - -// An Operation is executing by Retry() or RetryNotify(). -// The operation will be retried using a backoff policy if it returns an error. -type Operation func() error - -func (o Operation) withEmptyData() OperationWithData[struct{}] { - return func() (struct{}, error) { - return struct{}{}, o() - } -} - -// Notify is a notify-on-error function. It receives an operation error and -// backoff delay if the operation failed (with an error). -// -// NOTE that if the backoff policy stated to stop retrying, -// the notify function isn't called. -type Notify func(error, time.Duration) - -// Retry the operation o until it does not return error or BackOff stops. -// o is guaranteed to be run at least once. -// -// If o returns a *PermanentError, the operation is not retried, and the -// wrapped error is returned. -// -// Retry sleeps the goroutine for the duration returned by BackOff after a -// failed operation returns. -func Retry(o Operation, b BackOff) error { - return RetryNotify(o, b, nil) -} - -// RetryWithData is like Retry but returns data in the response too. -func RetryWithData[T any](o OperationWithData[T], b BackOff) (T, error) { - return RetryNotifyWithData(o, b, nil) -} - -// RetryNotify calls notify function with the error and wait duration -// for each failed attempt before sleep. -func RetryNotify(operation Operation, b BackOff, notify Notify) error { - return RetryNotifyWithTimer(operation, b, notify, nil) -} - -// RetryNotifyWithData is like RetryNotify but returns data in the response too. -func RetryNotifyWithData[T any](operation OperationWithData[T], b BackOff, notify Notify) (T, error) { - return doRetryNotify(operation, b, notify, nil) -} - -// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer -// for each failed attempt before sleep. -// A default timer that uses system timer is used when nil is passed. -func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error { - _, err := doRetryNotify(operation.withEmptyData(), b, notify, t) - return err -} - -// RetryNotifyWithTimerAndData is like RetryNotifyWithTimer but returns data in the response too. -func RetryNotifyWithTimerAndData[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) { - return doRetryNotify(operation, b, notify, t) -} - -func doRetryNotify[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) { - var ( - err error - next time.Duration - res T - ) - if t == nil { - t = &defaultTimer{} - } - - defer func() { - t.Stop() - }() - - ctx := getContext(b) - - b.Reset() - for { - res, err = operation() - if err == nil { - return res, nil - } - - var permanent *PermanentError - if errors.As(err, &permanent) { - return res, permanent.Err - } - - if next = b.NextBackOff(); next == Stop { - if cerr := ctx.Err(); cerr != nil { - return res, cerr - } - - return res, err - } - - if notify != nil { - notify(err, next) - } - - t.Start(next) - - select { - case <-ctx.Done(): - return res, ctx.Err() - case <-t.C(): - } - } -} - -// PermanentError signals that the operation should not be retried. -type PermanentError struct { - Err error -} - -func (e *PermanentError) Error() string { - return e.Err.Error() -} - -func (e *PermanentError) Unwrap() error { - return e.Err -} - -func (e *PermanentError) Is(target error) bool { - _, ok := target.(*PermanentError) - return ok -} - -// Permanent wraps the given err in a *PermanentError. -func Permanent(err error) error { - if err == nil { - return nil - } - return &PermanentError{ - Err: err, - } -} diff --git a/vendor/github.com/cenkalti/backoff/v4/ticker.go b/vendor/github.com/cenkalti/backoff/v4/ticker.go deleted file mode 100644 index df9d68bce52..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/ticker.go +++ /dev/null @@ -1,97 +0,0 @@ -package backoff - -import ( - "context" - "sync" - "time" -) - -// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. -// -// Ticks will continue to arrive when the previous operation is still running, -// so operations that take a while to fail could run in quick succession. -type Ticker struct { - C <-chan time.Time - c chan time.Time - b BackOff - ctx context.Context - timer Timer - stop chan struct{} - stopOnce sync.Once -} - -// NewTicker returns a new Ticker containing a channel that will send -// the time at times specified by the BackOff argument. Ticker is -// guaranteed to tick at least once. The channel is closed when Stop -// method is called or BackOff stops. It is not safe to manipulate the -// provided backoff policy (notably calling NextBackOff or Reset) -// while the ticker is running. -func NewTicker(b BackOff) *Ticker { - return NewTickerWithTimer(b, &defaultTimer{}) -} - -// NewTickerWithTimer returns a new Ticker with a custom timer. -// A default timer that uses system timer is used when nil is passed. -func NewTickerWithTimer(b BackOff, timer Timer) *Ticker { - if timer == nil { - timer = &defaultTimer{} - } - c := make(chan time.Time) - t := &Ticker{ - C: c, - c: c, - b: b, - ctx: getContext(b), - timer: timer, - stop: make(chan struct{}), - } - t.b.Reset() - go t.run() - return t -} - -// Stop turns off a ticker. After Stop, no more ticks will be sent. -func (t *Ticker) Stop() { - t.stopOnce.Do(func() { close(t.stop) }) -} - -func (t *Ticker) run() { - c := t.c - defer close(c) - - // Ticker is guaranteed to tick at least once. - afterC := t.send(time.Now()) - - for { - if afterC == nil { - return - } - - select { - case tick := <-afterC: - afterC = t.send(tick) - case <-t.stop: - t.c = nil // Prevent future ticks from being sent to the channel. - return - case <-t.ctx.Done(): - return - } - } -} - -func (t *Ticker) send(tick time.Time) <-chan time.Time { - select { - case t.c <- tick: - case <-t.stop: - return nil - } - - next := t.b.NextBackOff() - if next == Stop { - t.Stop() - return nil - } - - t.timer.Start(next) - return t.timer.C() -} diff --git a/vendor/github.com/cenkalti/backoff/v4/timer.go b/vendor/github.com/cenkalti/backoff/v4/timer.go deleted file mode 100644 index 8120d0213c5..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/timer.go +++ /dev/null @@ -1,35 +0,0 @@ -package backoff - -import "time" - -type Timer interface { - Start(duration time.Duration) - Stop() - C() <-chan time.Time -} - -// defaultTimer implements Timer interface using time.Timer -type defaultTimer struct { - timer *time.Timer -} - -// C returns the timers channel which receives the current time when the timer fires. -func (t *defaultTimer) C() <-chan time.Time { - return t.timer.C -} - -// Start starts the timer to fire after the given duration -func (t *defaultTimer) Start(duration time.Duration) { - if t.timer == nil { - t.timer = time.NewTimer(duration) - } else { - t.timer.Reset(duration) - } -} - -// Stop is called when the timer is not used anymore and resources may be freed. -func (t *defaultTimer) Stop() { - if t.timer != nil { - t.timer.Stop() - } -} diff --git a/vendor/github.com/cenkalti/backoff/v4/tries.go b/vendor/github.com/cenkalti/backoff/v4/tries.go deleted file mode 100644 index 28d58ca37c6..00000000000 --- a/vendor/github.com/cenkalti/backoff/v4/tries.go +++ /dev/null @@ -1,38 +0,0 @@ -package backoff - -import "time" - -/* -WithMaxRetries creates a wrapper around another BackOff, which will -return Stop if NextBackOff() has been called too many times since -the last time Reset() was called - -Note: Implementation is not thread-safe. -*/ -func WithMaxRetries(b BackOff, max uint64) BackOff { - return &backOffTries{delegate: b, maxTries: max} -} - -type backOffTries struct { - delegate BackOff - maxTries uint64 - numTries uint64 -} - -func (b *backOffTries) NextBackOff() time.Duration { - if b.maxTries == 0 { - return Stop - } - if b.maxTries > 0 { - if b.maxTries <= b.numTries { - return Stop - } - b.numTries++ - } - return b.delegate.NextBackOff() -} - -func (b *backOffTries) Reset() { - b.numTries = 0 - b.delegate.Reset() -} diff --git a/vendor/github.com/coder/quartz/.gitignore b/vendor/github.com/coder/quartz/.gitignore deleted file mode 100644 index 62c893550ad..00000000000 --- a/vendor/github.com/coder/quartz/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea/ \ No newline at end of file diff --git a/vendor/github.com/coder/quartz/LICENSE b/vendor/github.com/coder/quartz/LICENSE deleted file mode 100644 index aee8c1d627f..00000000000 --- a/vendor/github.com/coder/quartz/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -MIT No Attribution - -Copyright (c) Coder Technologies, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/coder/quartz/README.md b/vendor/github.com/coder/quartz/README.md deleted file mode 100644 index b0da401ec4f..00000000000 --- a/vendor/github.com/coder/quartz/README.md +++ /dev/null @@ -1,632 +0,0 @@ -# Quartz - -A Go time testing library for writing deterministic unit tests - -Our high level goal is to write unit tests that - -1. execute quickly -2. don't flake -3. are straightforward to write and understand - -For tests to execute quickly without flakes, we want to focus on _determinism_: the test should run -the same each time, and it should be easy to force the system into a known state (no races) before -executing test assertions. `time.Sleep`, `runtime.Gosched()`, and -polling/[Eventually](https://pkg.go.dev/github.com/stretchr/testify/assert#Eventually) are all -symptoms of an inability to do this easily. - -## Usage - -### `Clock` interface - -In your application code, maintain a reference to a `quartz.Clock` instance to start timers and -tickers, instead of the bare `time` standard library. - -```go -import "github.com/coder/quartz" - -type Component struct { - ... - - // for testing - clock quartz.Clock -} -``` - -Whenever you would call into `time` to start a timer or ticker, call `Component`'s `clock` instead. - -In production, set this clock to `quartz.NewReal()` to create a clock that just transparently passes -through to the standard `time` library. - -### Mocking - -In your tests, you can use a `*Mock` to control the tickers and timers your code under test gets. - -```go -import ( - "testing" - "github.com/coder/quartz" -) - -func TestComponent(t *testing.T) { - mClock := quartz.NewMock(t) - comp := &Component{ - ... - clock: mClock, - } -} -``` - -The `*Mock` clock starts at Jan 1, 2024, 00:00 UTC by default, but you can set any start time you'd like prior to your test. - -```go -mClock := quartz.NewMock(t) -mClock.Set(time.Date(2021, 6, 18, 12, 0, 0, 0, time.UTC)) // June 18, 2021 @ 12pm UTC -``` - -#### Advancing the clock - -Once you begin setting timers or tickers, you cannot change the time backward, only advance it -forward. You may continue to use `Set()`, but it is often easier and clearer to use `Advance()`. - -For example, with a timer: - -```go -fired := false - -tmr := mClock.AfterFunc(time.Second, func() { - fired = true -}) -mClock.Advance(time.Second) -``` - -When you call `Advance()` it immediately moves the clock forward the given amount, and triggers any -tickers or timers that are scheduled to happen at that time. Any triggered events happen on separate -goroutines, so _do not_ immediately assert the results: - -```go -fired := false - -tmr := mClock.AfterFunc(time.Second, func() { - fired = true -}) -mClock.Advance(time.Second) - -// RACE CONDITION, DO NOT DO THIS! -if !fired { - t.Fatal("didn't fire") -} -``` - -`Advance()` (and `Set()` for that matter) return an `AdvanceWaiter` object you can use to wait for -all triggered events to complete. - -```go -fired := false -// set a test timeout so we don't wait the default `go test` timeout for a failure -ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - -tmr := mClock.AfterFunc(time.Second, func() { - fired = true -}) - -w := mClock.Advance(time.Second) -err := w.Wait(ctx) -if err != nil { - t.Fatal("AfterFunc f never completed") -} -if !fired { - t.Fatal("didn't fire") -} -``` - -The construction of waiting for the triggered events and failing the test if they don't complete is -very common, so there is a shorthand: - -```go -w := mClock.Advance(time.Second) -err := w.Wait(ctx) -if err != nil { - t.Fatal("AfterFunc f never completed") -} -``` - -is equivalent to: - -```go -w := mClock.Advance(time.Second) -w.MustWait(ctx) -``` - -or even more briefly: - -```go -mClock.Advance(time.Second).MustWait(ctx) -``` - -### Advance only to the next event - -One important restriction on advancing the clock is that you may only advance forward to the next -timer or ticker event and no further. The following will result in a test failure: - -```go -func TestAdvanceTooFar(t *testing.T) { - ctx, cancel := context.WithTimeout(10*time.Second) - defer cancel() - mClock := quartz.NewMock(t) - var firedAt time.Time - mClock.AfterFunc(time.Second, func() { - firedAt := mClock.Now() - }) - mClock.Advance(2*time.Second).MustWait(ctx) -} -``` - -This is a deliberate design decision to allow `Advance()` to immediately and synchronously move the -clock forward (even without calling `Wait()` on returned waiter). This helps meet Quartz's design -goals of writing deterministic and easy to understand unit tests. It also allows the clock to be -advanced, deterministically _during_ the execution of a tick or timer function, as explained in the -next sections on Traps. - -Advancing multiple events can be accomplished via looping. E.g. if you have a 1-second ticker - -```go -for i := 0; i < 10; i++ { - mClock.Advance(time.Second).MustWait(ctx) -} -``` - -will advance 10 ticks. - -If you don't know or don't want to compute the time to the next event, you can use `AdvanceNext()`. - -```go -d, w := mClock.AdvanceNext() -w.MustWait(ctx) -// d contains the duration we advanced -``` - -`d, ok := Peek()` returns the duration until the next event, if any (`ok` is `true`). You can use -this to advance a specific time, regardless of the tickers and timer events: - -```go -desired := time.Minute // time to advance -for desired > 0 { - p, ok := mClock.Peek() - if !ok || p > desired { - mClock.Advance(desired).MustWait(ctx) - break - } - mClock.Advance(p).MustWait(ctx) - desired -= p -} -``` - -### Traps - -A trap allows you to match specific calls into the library while mocking, block their return, -inspect their arguments, then release them to allow them to return. They help you write -deterministic unit tests even when the code under test executes asynchronously from the test. - -You set your traps prior to executing code under test, and then wait for them to be triggered. - -```go -func TestTrap(t *testing.T) { - ctx, cancel := context.WithTimeout(10*time.Second) - defer cancel() - mClock := quartz.NewMock(t) - trap := mClock.Trap().AfterFunc() - defer trap.Close() // stop trapping AfterFunc calls - - count := 0 - go mClock.AfterFunc(time.Hour, func(){ - count++ - }) - call := trap.MustWait(ctx) - call.MustRelease(ctx) - if call.Duration != time.Hour { - t.Fatal("wrong duration") - } - - // Now that the async call to AfterFunc has occurred, we can advance the clock to trigger it - mClock.Advance(call.Duration).MustWait(ctx) - if count != 1 { - t.Fatal("wrong count") - } -} -``` - -In this test, the trap serves 2 purposes. Firstly, it allows us to capture and assert the duration -passed to the `AfterFunc` call. Secondly, it prevents a race between setting the timer and advancing -it. Since these things happen on different goroutines, if `Advance()` completes before -`AfterFunc()` is called, then the timer never pops in this test. - -Any untrapped calls immediately complete using the current time, and calling `Close()` on a trap -causes the mock clock to stop trapping those calls. - -You may also `Advance()` the clock between trapping a call and releasing it. The call uses the -current (mocked) time at the moment it is released. - -```go -func TestTrap2(t *testing.T) { - ctx, cancel := context.WithTimeout(10*time.Second) - defer cancel() - mClock := quartz.NewMock(t) - trap := mClock.Trap().Now() - defer trap.Close() // stop trapping AfterFunc calls - - var logs []string - done := make(chan struct{}) - go func(clk quartz.Clock){ - defer close(done) - start := clk.Now() - phase1() - p1end := clk.Now() - logs = append(fmt.Sprintf("Phase 1 took %s", p1end.Sub(start).String())) - phase2() - p2end := clk.Now() - logs = append(fmt.Sprintf("Phase 2 took %s", p2end.Sub(p1end).String())) - }(mClock) - - // start - trap.MustWait(ctx).MustRelease(ctx) - // phase 1 - call := trap.MustWait(ctx) - mClock.Advance(3*time.Second).MustWait(ctx) - call.MustRelease(ctx) - // phase 2 - call = trap.MustWait(ctx) - mClock.Advance(5*time.Second).MustWait(ctx) - call.MustRelease(ctx) - - <-done - // Now logs contains []string{"Phase 1 took 3s", "Phase 2 took 5s"} -} -``` - -### Tags - -When multiple goroutines in the code under test call into the Clock, you can use `tags` to -distinguish them in your traps. - -```go -trap := mClock.Trap.Now("foo") // traps any calls that contain "foo" -defer trap.Close() - -foo := make(chan time.Time) -go func(){ - foo <- mClock.Now("foo", "bar") -}() -baz := make(chan time.Time) -go func(){ - baz <- mClock.Now("baz") -}() -call := trap.MustWait(ctx) -mClock.Advance(time.Second).MustWait(ctx) -call.MustRelease(ctx) -// call.Tags contains []string{"foo", "bar"} - -gotFoo := <-foo // 1s after start -gotBaz := <-baz // ?? never trapped, so races with Advance() -``` - -Tags appear as an optional suffix on all `Clock` methods (type `...string`) and are ignored entirely -by the real clock. They also appear on all methods on returned timers and tickers. - -## Recommended Patterns - -### Options - -We use the Option pattern to inject the mock clock for testing, keeping the call signature in -production clean. The option pattern is compatible with other optional fields as well. - -```go -type Option func(*Thing) - -// WithTestClock is used in tests to inject a mock Clock -func WithTestClock(clk quartz.Clock) Option { - return func(t *Thing) { - t.clock = clk - } -} - -func NewThing(, opts ...Option) *Thing { - t := &Thing{ - ... - clock: quartz.NewReal() - } - for _, o := range opts { - o(t) - } - return t -} -``` - -In tests, this becomes - -```go -func TestThing(t *testing.T) { - mClock := quartz.NewMock(t) - thing := NewThing(, WithTestClock(mClock)) - ... -} -``` - -### Tagging convention - -Tag your `Clock` method calls as: - -```go -func (c *Component) Method() { - now := c.clock.Now("Component", "Method") -} -``` - -or - -```go -func (c *Component) Method() { - start := c.clock.Now("Component", "Method", "start") - ... - end := c.clock.Now("Component", "Method", "end") -} -``` - -This makes it much less likely that code changes that introduce new components or methods will spoil -existing unit tests. - -## Why another time testing library? - -Writing good unit tests for components and functions that use the `time` package is difficult, even -though several open source libraries exist. In building Quartz, we took some inspiration from - -- [github.com/benbjohnson/clock](https://github.com/benbjohnson/clock) -- Tailscale's [tstest.Clock](https://github.com/coder/tailscale/blob/main/tstest/clock.go) -- [github.com/aspenmesh/tock](https://github.com/aspenmesh/tock) - -Quartz shares the high level design of a `Clock` interface that closely resembles the functions in -the `time` standard library, and a "real" clock passes thru to the standard library in production, -while a mock clock gives precise control in testing. - -As mentioned in our introduction, our high level goal is to write unit tests that - -1. execute quickly -2. don't flake -3. are straightforward to write and understand - -For several reasons, this is a tall order when it comes to code that depends on time, and we found -the existing libraries insufficient for our goals. - -### Preventing test flakes - -The following example comes from the README from benbjohnson/clock: - -```go -mock := clock.NewMock() -count := 0 - -// Kick off a timer to increment every 1 mock second. -go func() { - ticker := mock.Ticker(1 * time.Second) - for { - <-ticker.C - count++ - } -}() -runtime.Gosched() - -// Move the clock forward 10 seconds. -mock.Add(10 * time.Second) - -// This prints 10. -fmt.Println(count) -``` - -The first race condition is fairly obvious: moving the clock forward 10 seconds may generate 10 -ticks on the `ticker.C` channel, but there is no guarantee that `count++` executes before -`fmt.Println(count)`. - -The second race condition is more subtle, but `runtime.Gosched()` is the tell. Since the ticker -is started on a separate goroutine, there is no guarantee that `mock.Ticker()` executes before -`mock.Add()`. `runtime.Gosched()` is an attempt to get this to happen, but it makes no hard -promises. On a busy system, especially when running tests in parallel, this can flake, advance the -time 10 seconds first, then start the ticker and never generate a tick. - -Let's talk about how Quartz tackles these problems. - -In our experience, an extremely common use case is creating a ticker then doing a 2-arm `select` -with ticks in one and context expiring in another, i.e. - -```go -t := time.NewTicker(duration) -for { - select { - case <-ctx.Done(): - return ctx.Err() - case <-t.C: - err := do() - if err != nil { - return err - } - } -} -``` - -In Quartz, we refactor this to be more compact and testing friendly: - -```go -t := clock.TickerFunc(ctx, duration, do) -return t.Wait() -``` - -This affords the mock `Clock` the ability to explicitly know when processing of a tick is finished -because it's wrapped in the function passed to `TickerFunc` (`do()` in this example). - -In Quartz, when you advance the clock, you are returned an object you can `Wait()` on to ensure all -ticks and timers triggered are finished. This solves the first race condition in the example. - -(As an aside, we still support a traditional standard library-style `Ticker`. You may find it useful -if you want to keep your code as close as possible to the standard library, or if you need to use -the channel in a larger `select` block. In that case, you'll have to find some other mechanism to -sync tick processing to your test code.) - -To prevent race conditions related to the starting of the ticker, Quartz allows you to set "traps" -for calls that access the clock. - -```go -func TestTicker(t *testing.T) { - mClock := quartz.NewMock(t) - trap := mClock.Trap().TickerFunc() - defer trap.Close() // stop trapping at end - go runMyTicker(mClock) // async calls TickerFunc() - call := trap.MustWait(context.Background()) // waits for a call and blocks its return - call.MustRelease(ctx) // allow the TickerFunc() call to return - // optionally check the duration using call.Duration - // Move the clock forward 1 tick - mClock.Advance(time.Second).MustWait(context.Background()) - // assert results of the tick -} -``` - -Trapping and then releasing the call to `TickerFunc()` ensures the ticker is started at a -deterministic time, so our calls to `Advance()` will have a predictable effect. - -Take a look at `TestExampleTickerFunc` in `example_test.go` for a complete worked example. - -### Complex time dependence - -Another difficult issue to handle when unit testing is when some code under test makes multiple -calls that depend on the time, and you want to simulate some time passing between them. - -A very basic example is measuring how long something took: - -```go -var measurement time.Duration -go func(clock quartz.Clock) { - start := clock.Now() - doSomething() - measurement = clock.Since(start) -}(mClock) - -// how to get measurement to be, say, 5 seconds? -``` - -The two calls into the clock happen asynchronously, so we need to be able to advance the clock after -the first call to `Now()` but before the call to `Since()`. Doing this with the libraries we -mentioned above means that you have to be able to mock out or otherwise block the completion of -`doSomething()`. - -But, with the trap functionality we mentioned in the previous section, you can deterministically -control the time each call sees. - -```go -trap := mClock.Trap().Since() -var measurement time.Duration -go func(clock quartz.Clock) { - start := clock.Now() - doSomething() - measurement = clock.Since(start) -}(mClock) - -c := trap.MustWait(ctx) -mClock.Advance(5*time.Second) -c.MustRelease(ctx) -``` - -We wait until we trap the `clock.Since()` call, which implies that `clock.Now()` has completed, then -advance the mock clock 5 seconds. Finally, we release the `clock.Since()` call. Any changes to the -clock that happen _before_ we release the call will be included in the time used for the -`clock.Since()` call. - -As a more involved example, consider an inactivity timeout: we want something to happen if there is -no activity recorded for some period, say 10 minutes in the following example: - -```go -type InactivityTimer struct { - mu sync.Mutex - activity time.Time - clock quartz.Clock -} - -func (i *InactivityTimer) Start() { - i.mu.Lock() - defer i.mu.Unlock() - next := i.clock.Until(i.activity.Add(10*time.Minute)) - t := i.clock.AfterFunc(next, func() { - i.mu.Lock() - defer i.mu.Unlock() - next := i.clock.Until(i.activity.Add(10*time.Minute)) - if next == 0 { - i.timeoutLocked() - return - } - t.Reset(next) - }) -} -``` - -The actual contents of `timeoutLocked()` doesn't matter for this example, and assume there are other -functions that record the latest `activity`. - -We found that some time testing libraries hold a lock on the mock clock while calling the function -passed to `AfterFunc`, resulting in a deadlock if you made clock calls from within. - -Others allow this sort of thing, but don't have the flexibility to test edge cases. There is a -subtle bug in our `Start()` function. The timer may pop a little late, and/or some measurable real -time may elapse before `Until()` gets called inside the `AfterFunc`. If there hasn't been activity, -`next` might be negative. - -To test this in Quartz, we'll use a trap. We only want to trap the inner `Until()` call, not the -initial one, so to make testing easier we can "tag" the call we want. Like this: - -```go -func (i *InactivityTimer) Start() { - i.mu.Lock() - defer i.mu.Unlock() - next := i.clock.Until(i.activity.Add(10*time.Minute)) - t := i.clock.AfterFunc(next, func() { - i.mu.Lock() - defer i.mu.Unlock() - next := i.clock.Until(i.activity.Add(10*time.Minute), "inner") - if next == 0 { - i.timeoutLocked() - return - } - t.Reset(next) - }) -} -``` - -All Quartz `Clock` functions, and functions on returned timers and tickers support zero or more -string tags that allow traps to match on them. - -```go -func TestInactivityTimer_Late(t *testing.T) { - // set a timeout on the test itself, so that if Wait functions get blocked, we don't have to - // wait for the default test timeout of 10 minutes. - ctx, cancel := context.WithTimeout(10*time.Second) - defer cancel() - mClock := quartz.NewMock(t) - trap := mClock.Trap.Until("inner") - defer trap.Close() - - it := &InactivityTimer{ - activity: mClock.Now(), - clock: mClock, - } - it.Start() - - // Trigger the AfterFunc - w := mClock.Advance(10*time.Minute) - c := trap.MustWait(ctx) - // Advance the clock a few ms to simulate a busy system - mClock.Advance(3*time.Millisecond) - c.MustRelease(ctx) // Until() returns - w.MustWait(ctx) // Wait for the AfterFunc to wrap up - - // Assert that the timeoutLocked() function was called -} -``` - -This test case will fail with our bugged implementation, since the triggered AfterFunc won't call -`timeoutLocked()` and instead will reset the timer with a negative number. The fix is easy, use -`next <= 0` as the comparison. diff --git a/vendor/github.com/coder/quartz/clock.go b/vendor/github.com/coder/quartz/clock.go deleted file mode 100644 index 729edfa5623..00000000000 --- a/vendor/github.com/coder/quartz/clock.go +++ /dev/null @@ -1,43 +0,0 @@ -// Package quartz is a library for testing time related code. It exports an interface Clock that -// mimics the standard library time package functions. In production, an implementation that calls -// thru to the standard library is used. In testing, a Mock clock is used to precisely control and -// intercept time functions. -package quartz - -import ( - "context" - "time" -) - -type Clock interface { - // NewTicker returns a new Ticker containing a channel that will send the current time on the - // channel after each tick. The period of the ticks is specified by the duration argument. The - // ticker will adjust the time interval or drop ticks to make up for slow receivers. The - // duration d must be greater than zero; if not, NewTicker will panic. Stop the ticker to - // release associated resources. - NewTicker(d time.Duration, tags ...string) *Ticker - // TickerFunc is a convenience function that calls f on the interval d until either the given - // context expires or f returns an error. Callers may call Wait() on the returned Waiter to - // wait until this happens and obtain the error. The duration d must be greater than zero; if - // not, TickerFunc will panic. - TickerFunc(ctx context.Context, d time.Duration, f func() error, tags ...string) Waiter - // NewTimer creates a new Timer that will send the current time on its channel after at least - // duration d. - NewTimer(d time.Duration, tags ...string) *Timer - // AfterFunc waits for the duration to elapse and then calls f in its own goroutine. It returns - // a Timer that can be used to cancel the call using its Stop method. The returned Timer's C - // field is not used and will be nil. - AfterFunc(d time.Duration, f func(), tags ...string) *Timer - - // Now returns the current local time. - Now(tags ...string) time.Time - // Since returns the time elapsed since t. It is shorthand for Clock.Now().Sub(t). - Since(t time.Time, tags ...string) time.Duration - // Until returns the duration until t. It is shorthand for t.Sub(Clock.Now()). - Until(t time.Time, tags ...string) time.Duration -} - -// Waiter can be waited on for an error. -type Waiter interface { - Wait(tags ...string) error -} diff --git a/vendor/github.com/coder/quartz/mock.go b/vendor/github.com/coder/quartz/mock.go deleted file mode 100644 index 7255aff99bd..00000000000 --- a/vendor/github.com/coder/quartz/mock.go +++ /dev/null @@ -1,851 +0,0 @@ -package quartz - -import ( - "context" - "errors" - "fmt" - "slices" - "sync" - "time" -) - -// TestingT is the minimal interface required from a testing framework for the Mock. -type TestingT interface { - Helper() - - Log(...any) - Logf(string, ...any) - Error(...any) - Errorf(string, ...any) - Fatal(...any) - Fatalf(string, ...any) - - Cleanup(func()) -} - -// Mock is the testing implementation of Clock. It tracks a time that monotonically increases -// during a test, triggering any timers or tickers automatically. -type Mock struct { - tb TestingT - logger Logger - mu sync.Mutex - testOver bool - - // cur is the current time - cur time.Time - - all []event - nextTime time.Time - nextEvents []event - traps []*Trap -} - -type event interface { - next() time.Time - fire(t time.Time) -} - -func (m *Mock) TickerFunc(ctx context.Context, d time.Duration, f func() error, tags ...string) Waiter { - if d <= 0 { - panic("TickerFunc called with negative or zero duration") - } - m.mu.Lock() - defer m.mu.Unlock() - c := newCall(clockFunctionTickerFunc, tags, withDuration(d)) - m.matchCallLocked(c) - defer close(c.complete) - t := &mockTickerFunc{ - ctx: ctx, - d: d, - f: f, - nxt: m.cur.Add(d), - mock: m, - cond: sync.NewCond(&m.mu), - } - m.all = append(m.all, t) - m.recomputeNextLocked() - go t.waitForCtx() - return t -} - -// NewTicker creates a mocked ticker attached to this Mock. Note that it will cease sending ticks on its channel at the -// end of the test, to avoid leaking any goroutines. Ticks are suppressed even if the mock clock is advanced after the -// test completes. Best practice is to only manipulate the mock time in the main goroutine of the test. -func (m *Mock) NewTicker(d time.Duration, tags ...string) *Ticker { - if d <= 0 { - panic("NewTicker called with negative or zero duration") - } - m.mu.Lock() - defer m.mu.Unlock() - c := newCall(clockFunctionNewTicker, tags, withDuration(d)) - m.matchCallLocked(c) - defer close(c.complete) - return newMockTickerLocked(m, d) -} - -func (m *Mock) NewTimer(d time.Duration, tags ...string) *Timer { - m.mu.Lock() - defer m.mu.Unlock() - c := newCall(clockFunctionNewTimer, tags, withDuration(d)) - defer close(c.complete) - m.matchCallLocked(c) - ch := make(chan time.Time) - t := &Timer{ - C: ch, - c: ch, - nxt: m.cur.Add(d), - mock: m, - } - if d <= 0 { - // zero or negative duration timer means we should immediately fire - // it, rather than add it. - go t.fire(t.mock.cur) - return t - } - m.addEventLocked(t) - return t -} - -func (m *Mock) AfterFunc(d time.Duration, f func(), tags ...string) *Timer { - m.mu.Lock() - defer m.mu.Unlock() - c := newCall(clockFunctionAfterFunc, tags, withDuration(d)) - defer close(c.complete) - m.matchCallLocked(c) - t := &Timer{ - nxt: m.cur.Add(d), - fn: f, - mock: m, - } - if d <= 0 { - // zero or negative duration timer means we should immediately fire - // it, rather than add it. - go t.fire(t.mock.cur) - return t - } - m.addEventLocked(t) - return t -} - -func (m *Mock) Now(tags ...string) time.Time { - m.mu.Lock() - defer m.mu.Unlock() - c := newCall(clockFunctionNow, tags) - defer close(c.complete) - m.matchCallLocked(c) - return m.cur -} - -func (m *Mock) Since(t time.Time, tags ...string) time.Duration { - m.mu.Lock() - defer m.mu.Unlock() - c := newCall(clockFunctionSince, tags, withTime(t)) - defer close(c.complete) - m.matchCallLocked(c) - return m.cur.Sub(t) -} - -func (m *Mock) Until(t time.Time, tags ...string) time.Duration { - m.mu.Lock() - defer m.mu.Unlock() - c := newCall(clockFunctionUntil, tags, withTime(t)) - defer close(c.complete) - m.matchCallLocked(c) - return t.Sub(m.cur) -} - -func (m *Mock) addEventLocked(e event) { - m.all = append(m.all, e) - m.recomputeNextLocked() -} - -func (m *Mock) recomputeNextLocked() { - var best time.Time - var events []event - for _, e := range m.all { - if best.IsZero() || e.next().Before(best) { - best = e.next() - events = []event{e} - continue - } - if e.next().Equal(best) { - events = append(events, e) - continue - } - } - m.nextTime = best - m.nextEvents = events -} - -func (m *Mock) removeTimer(t *Timer) { - m.mu.Lock() - defer m.mu.Unlock() - m.removeTimerLocked(t) -} - -func (m *Mock) removeTimerLocked(t *Timer) { - t.stopped = true - m.removeEventLocked(t) -} - -func (m *Mock) removeEventLocked(e event) { - defer m.recomputeNextLocked() - for i := range m.all { - if m.all[i] == e { - m.all = append(m.all[:i], m.all[i+1:]...) - return - } - } -} - -func (m *Mock) matchCallLocked(c *apiCall) { - var traps []*Trap - for _, t := range m.traps { - if t.matches(c) { - traps = append(traps, t) - } - } - if !m.testOver { - m.logger.Logf("Mock Clock - %s call, matched %d traps", c, len(traps)) - } - if len(traps) == 0 { - return - } - c.releases.Add(len(traps)) - m.mu.Unlock() - for _, t := range traps { - go t.catch(c) - } - c.releases.Wait() - m.mu.Lock() -} - -// AdvanceWaiter is returned from Advance and Set calls and allows you to wait for ticks and timers -// to complete. In the case of functions passed to AfterFunc or TickerFunc, it waits for the -// functions to return. For other ticks & timers, it just waits for the tick to be delivered to -// the channel. -// -// If multiple timers or tickers trigger simultaneously, they are all run on separate -// go routines. -type AdvanceWaiter struct { - tb TestingT - ch chan struct{} -} - -// Wait for all timers and ticks to complete, or until context expires. -func (w AdvanceWaiter) Wait(ctx context.Context) error { - select { - case <-w.ch: - return nil - case <-ctx.Done(): - return ctx.Err() - } -} - -// MustWait waits for all timers and ticks to complete, and fails the test immediately if the -// context completes first. MustWait must be called from the goroutine running the test or -// benchmark, similar to `t.FailNow()`. -func (w AdvanceWaiter) MustWait(ctx context.Context) { - w.tb.Helper() - select { - case <-w.ch: - return - case <-ctx.Done(): - w.tb.Fatalf("context expired while waiting for clock to advance: %s", ctx.Err()) - } -} - -// Done returns a channel that is closed when all timers and ticks complete. -func (w AdvanceWaiter) Done() <-chan struct{} { - return w.ch -} - -// Advance moves the clock forward by d, triggering any timers or tickers. The returned value can -// be used to wait for all timers and ticks to complete. Advance sets the clock forward before -// returning, and can only advance up to the next timer or tick event. It will fail the test if you -// attempt to advance beyond. -// -// If you need to advance exactly to the next event, and don't know or don't wish to calculate it, -// consider AdvanceNext(). -func (m *Mock) Advance(d time.Duration) AdvanceWaiter { - m.tb.Helper() - w := AdvanceWaiter{tb: m.tb, ch: make(chan struct{})} - m.mu.Lock() - if !m.testOver { - m.logger.Logf("Mock Clock - Advance(%s)", d) - } - fin := m.cur.Add(d) - // nextTime.IsZero implies no events scheduled. - if m.nextTime.IsZero() || fin.Before(m.nextTime) { - m.cur = fin - m.mu.Unlock() - close(w.ch) - return w - } - if fin.After(m.nextTime) { - m.tb.Errorf("cannot advance %s which is beyond next timer/ticker event in %s", - d.String(), m.nextTime.Sub(m.cur)) - m.mu.Unlock() - close(w.ch) - return w - } - - m.cur = m.nextTime - go m.advanceLocked(w) - return w -} - -func (m *Mock) advanceLocked(w AdvanceWaiter) { - defer close(w.ch) - wg := sync.WaitGroup{} - for i := range m.nextEvents { - e := m.nextEvents[i] - t := m.cur - wg.Add(1) - go func() { - e.fire(t) - wg.Done() - }() - } - // release the lock and let the events resolve. This allows them to call back into the - // Mock to query the time or set new timers. Each event should remove or reschedule - // itself from nextEvents. - m.mu.Unlock() - wg.Wait() -} - -// Set the time to t. If the time is after the current mocked time, then this is equivalent to -// Advance() with the difference. You may only Set the time earlier than the current time before -// starting tickers and timers (e.g. at the start of your test case). -func (m *Mock) Set(t time.Time) AdvanceWaiter { - m.tb.Helper() - w := AdvanceWaiter{tb: m.tb, ch: make(chan struct{})} - m.mu.Lock() - if !m.testOver { - m.logger.Logf("Mock Clock - Set(%s)", t) - } - if t.Before(m.cur) { - defer close(w.ch) - defer m.mu.Unlock() - // past - if !m.nextTime.IsZero() { - m.tb.Error("Set mock clock to the past after timers/tickers started") - } - m.cur = t - return w - } - // future - // nextTime.IsZero implies no events scheduled. - if m.nextTime.IsZero() || t.Before(m.nextTime) { - defer close(w.ch) - defer m.mu.Unlock() - m.cur = t - return w - } - if t.After(m.nextTime) { - defer close(w.ch) - defer m.mu.Unlock() - m.tb.Errorf("cannot Set time to %s which is beyond next timer/ticker event at %s", - t.String(), m.nextTime) - return w - } - - m.cur = m.nextTime - go m.advanceLocked(w) - return w -} - -// AdvanceNext advances the clock to the next timer or tick event. It fails the test if there are -// none scheduled. It returns the duration the clock was advanced and a waiter that can be used to -// wait for the timer/tick event(s) to finish. -func (m *Mock) AdvanceNext() (time.Duration, AdvanceWaiter) { - m.mu.Lock() - if !m.testOver { - m.logger.Logf("Mock Clock - AdvanceNext()") - } - m.tb.Helper() - w := AdvanceWaiter{tb: m.tb, ch: make(chan struct{})} - if m.nextTime.IsZero() { - defer close(w.ch) - defer m.mu.Unlock() - m.tb.Error("cannot AdvanceNext because there are no timers or tickers running") - return 0, w - } - d := m.nextTime.Sub(m.cur) - m.cur = m.nextTime - go m.advanceLocked(w) - return d, w -} - -// Peek returns the duration until the next ticker or timer event and the value -// true, or, if there are no running tickers or timers, it returns zero and -// false. -func (m *Mock) Peek() (d time.Duration, ok bool) { - m.mu.Lock() - defer m.mu.Unlock() - if m.nextTime.IsZero() { - return 0, false - } - return m.nextTime.Sub(m.cur), true -} - -// Trapper allows the creation of Traps -type Trapper struct { - // mock is the underlying Mock. This is a thin wrapper around Mock so that - // we can have our interface look like mClock.Trap().NewTimer("foo") - mock *Mock -} - -func (t Trapper) NewTimer(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionNewTimer, tags) -} - -func (t Trapper) AfterFunc(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionAfterFunc, tags) -} - -func (t Trapper) TimerStop(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionTimerStop, tags) -} - -func (t Trapper) TimerReset(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionTimerReset, tags) -} - -func (t Trapper) TickerFunc(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionTickerFunc, tags) -} - -func (t Trapper) TickerFuncWait(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionTickerFuncWait, tags) -} - -func (t Trapper) NewTicker(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionNewTicker, tags) -} - -func (t Trapper) TickerStop(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionTickerStop, tags) -} - -func (t Trapper) TickerReset(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionTickerReset, tags) -} - -func (t Trapper) Now(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionNow, tags) -} - -func (t Trapper) Since(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionSince, tags) -} - -func (t Trapper) Until(tags ...string) *Trap { - return t.mock.newTrap(clockFunctionUntil, tags) -} - -func (m *Mock) Trap() Trapper { - return Trapper{m} -} - -func (m *Mock) newTrap(fn clockFunction, tags []string) *Trap { - m.mu.Lock() - defer m.mu.Unlock() - if !m.testOver { - m.logger.Logf("Mock Clock - Trap %s(..., %v)", fn, tags) - } - tr := &Trap{ - fn: fn, - tags: tags, - mock: m, - calls: make(chan *apiCall), - done: make(chan struct{}), - } - m.traps = append(m.traps, tr) - return tr -} - -// WithLogger replaces the default testing logger with a custom one. -// -// This can be used to discard log messages with: -// -// quartz.NewMock(t).WithLogger(quartz.NoOpLogger) -func (m *Mock) WithLogger(l Logger) *Mock { - m.mu.Lock() - defer m.mu.Unlock() - m.logger = l - return m -} - -// NewMock creates a new Mock with the time set to midnight UTC on Jan 1, 2024. -// You may re-set the time earlier than this, but only before timers or tickers -// are created. -func NewMock(tb TestingT) *Mock { - cur, err := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z") - if err != nil { - panic(err) - } - m := &Mock{ - tb: tb, - logger: tb, - cur: cur, - } - tb.Cleanup(func() { - m.mu.Lock() - defer m.mu.Unlock() - m.testOver = true - m.logger.Logf("Mock Clock - test cleanup; will no longer log clock events") - }) - return m -} - -var _ Clock = &Mock{} - -type mockTickerFunc struct { - ctx context.Context - d time.Duration - f func() error - nxt time.Time - mock *Mock - - // cond is a condition Locked on the main Mock.mu - cond *sync.Cond - // inProgress is true when we are actively calling f - inProgress bool - // done is true when the ticker exits - done bool - // err holds the error when the ticker exits - err error -} - -func (m *mockTickerFunc) next() time.Time { - return m.nxt -} - -func (m *mockTickerFunc) fire(_ time.Time) { - m.mock.mu.Lock() - if m.done { - m.mock.mu.Unlock() - return - } - m.nxt = m.nxt.Add(m.d) - m.mock.recomputeNextLocked() - // we need this check to happen after we've computed the next tick, - // otherwise it will be immediately rescheduled. - if m.inProgress { - m.mock.mu.Unlock() - return - } - - m.inProgress = true - m.mock.mu.Unlock() - err := m.f() - m.mock.mu.Lock() - defer m.mock.mu.Unlock() - m.inProgress = false - m.cond.Broadcast() // wake up anything waiting for f to finish - if err != nil { - m.exitLocked(err) - } -} - -func (m *mockTickerFunc) exitLocked(err error) { - if m.done { - return - } - m.done = true - m.err = err - m.mock.removeEventLocked(m) - m.cond.Broadcast() -} - -func (m *mockTickerFunc) waitForCtx() { - <-m.ctx.Done() - m.mock.mu.Lock() - defer m.mock.mu.Unlock() - for m.inProgress { - m.cond.Wait() - } - m.exitLocked(m.ctx.Err()) -} - -func (m *mockTickerFunc) Wait(tags ...string) error { - m.mock.mu.Lock() - defer m.mock.mu.Unlock() - c := newCall(clockFunctionTickerFuncWait, tags) - m.mock.matchCallLocked(c) - defer close(c.complete) - for !m.done { - m.cond.Wait() - } - return m.err -} - -var _ Waiter = &mockTickerFunc{} - -type clockFunction int - -const ( - clockFunctionNewTimer clockFunction = iota - clockFunctionAfterFunc - clockFunctionTimerStop - clockFunctionTimerReset - clockFunctionTickerFunc - clockFunctionTickerFuncWait - clockFunctionNewTicker - clockFunctionTickerReset - clockFunctionTickerStop - clockFunctionNow - clockFunctionSince - clockFunctionUntil -) - -func (c clockFunction) String() string { - switch c { - case clockFunctionNewTimer: - return "NewTimer" - case clockFunctionAfterFunc: - return "AfterFunc" - case clockFunctionTimerStop: - return "Timer.Stop" - case clockFunctionTimerReset: - return "Timer.Reset" - case clockFunctionTickerFunc: - return "TickerFunc" - case clockFunctionTickerFuncWait: - return "TickerFunc.Wait" - case clockFunctionNewTicker: - return "NewTicker" - case clockFunctionTickerReset: - return "Ticker.Reset" - case clockFunctionTickerStop: - return "Ticker.Stop" - case clockFunctionNow: - return "Now" - case clockFunctionSince: - return "Since" - case clockFunctionUntil: - return "Until" - default: - return fmt.Sprintf("Unknown clockFunction(%d)", c) - } -} - -type callArg func(c *apiCall) - -// apiCall represents a single call to one of the Clock APIs. -type apiCall struct { - Time time.Time - Duration time.Duration - Tags []string - - fn clockFunction - releases sync.WaitGroup - complete chan struct{} -} - -func (a *apiCall) String() string { - switch a.fn { - case clockFunctionNewTimer: - return fmt.Sprintf("NewTimer(%s, %v)", a.Duration, a.Tags) - case clockFunctionAfterFunc: - return fmt.Sprintf("AfterFunc(%s, , %v)", a.Duration, a.Tags) - case clockFunctionTimerStop: - return fmt.Sprintf("Timer.Stop(%v)", a.Tags) - case clockFunctionTimerReset: - return fmt.Sprintf("Timer.Reset(%s, %v)", a.Duration, a.Tags) - case clockFunctionTickerFunc: - return fmt.Sprintf("TickerFunc(, %s, , %s)", a.Duration, a.Tags) - case clockFunctionTickerFuncWait: - return fmt.Sprintf("TickerFunc.Wait(%v)", a.Tags) - case clockFunctionNewTicker: - return fmt.Sprintf("NewTicker(%s, %v)", a.Duration, a.Tags) - case clockFunctionTickerReset: - return fmt.Sprintf("Ticker.Reset(%s, %v)", a.Duration, a.Tags) - case clockFunctionTickerStop: - return fmt.Sprintf("Ticker.Stop(%v)", a.Tags) - case clockFunctionNow: - return fmt.Sprintf("Now(%v)", a.Tags) - case clockFunctionSince: - return fmt.Sprintf("Since(%s, %v)", a.Time, a.Tags) - case clockFunctionUntil: - return fmt.Sprintf("Until(%s, %v)", a.Time, a.Tags) - default: - return fmt.Sprintf("Unknown clockFunction(%d)", a.fn) - } -} - -// Call represents an apiCall that has been trapped. -type Call struct { - Time time.Time - Duration time.Duration - Tags []string - - tb TestingT - apiCall *apiCall - trap *Trap -} - -// Release the call and wait for it to complete. If the provided context expires before the call completes, it returns -// an error. -// -// IMPORTANT: If a call is trapped by more than one trap, they all must release the call before it can complete, and -// they must do so from different goroutines. -func (c *Call) Release(ctx context.Context) error { - c.apiCall.releases.Done() - select { - case <-ctx.Done(): - return fmt.Errorf("timed out waiting for release; did more than one trap capture the call?: %w", ctx.Err()) - case <-c.apiCall.complete: - // OK - } - c.trap.callReleased() - return nil -} - -// MustRelease releases the call and waits for it to complete. If the provided context expires before the call -// completes, it fails the test. -// -// IMPORTANT: If a call is trapped by more than one trap, they all must release the call before it can complete, and -// they must do so from different goroutines. -func (c *Call) MustRelease(ctx context.Context) { - if err := c.Release(ctx); err != nil { - c.tb.Helper() - c.tb.Fatal(err.Error()) - } -} - -func withTime(t time.Time) callArg { - return func(c *apiCall) { - c.Time = t - } -} - -func withDuration(d time.Duration) callArg { - return func(c *apiCall) { - c.Duration = d - } -} - -func newCall(fn clockFunction, tags []string, args ...callArg) *apiCall { - c := &apiCall{ - fn: fn, - Tags: tags, - complete: make(chan struct{}), - } - for _, a := range args { - a(c) - } - return c -} - -type Trap struct { - fn clockFunction - tags []string - mock *Mock - calls chan *apiCall - done chan struct{} - - // mu protects the unreleasedCalls count - mu sync.Mutex - unreleasedCalls int -} - -func (t *Trap) String() string { - return fmt.Sprintf("Trap %s(..., %v)", t.fn.String(), t.tags) -} - -func (t *Trap) catch(c *apiCall) { - select { - case t.calls <- c: - case <-t.done: - c.releases.Done() - } -} - -func (t *Trap) matches(c *apiCall) bool { - if t.fn != c.fn { - return false - } - for _, tag := range t.tags { - if !slices.Contains(c.Tags, tag) { - return false - } - } - return true -} - -func (t *Trap) Close() { - t.mock.mu.Lock() - defer t.mock.mu.Unlock() - select { - case <-t.done: - t.mock.tb.Logf("%s already Closed()", t) - return // already closed - default: - } - if t.unreleasedCalls != 0 { - t.mock.tb.Helper() - t.mock.tb.Errorf("%s Closed() with %d unreleased calls", t, t.unreleasedCalls) - } - for i, tr := range t.mock.traps { - if t == tr { - t.mock.traps = append(t.mock.traps[:i], t.mock.traps[i+1:]...) - } - } - close(t.done) -} - -func (t *Trap) callReleased() { - t.mu.Lock() - defer t.mu.Unlock() - t.unreleasedCalls-- -} - -var ErrTrapClosed = errors.New("trap closed") - -func (t *Trap) Wait(ctx context.Context) (*Call, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-t.done: - return nil, ErrTrapClosed - case a := <-t.calls: - c := &Call{ - Time: a.Time, - Duration: a.Duration, - Tags: a.Tags, - apiCall: a, - trap: t, - tb: t.mock.tb, - } - t.mu.Lock() - defer t.mu.Unlock() - t.unreleasedCalls++ - return c, nil - } -} - -// MustWait calls Wait() and then if there is an error, immediately fails the -// test via tb.Fatalf() -func (t *Trap) MustWait(ctx context.Context) *Call { - t.mock.tb.Helper() - c, err := t.Wait(ctx) - if err != nil { - t.mock.tb.Fatalf("context expired while waiting for %s: %s", t, err.Error()) - } - return c -} - -type Logger interface { - Log(args ...any) - Logf(format string, args ...any) -} - -// NoOpLogger is a Logger that discards all log messages. -var NoOpLogger Logger = noOpLogger{} - -type noOpLogger struct{} - -func (noOpLogger) Log(args ...any) {} -func (noOpLogger) Logf(format string, args ...any) {} diff --git a/vendor/github.com/coder/quartz/real.go b/vendor/github.com/coder/quartz/real.go deleted file mode 100644 index f39fb1163e8..00000000000 --- a/vendor/github.com/coder/quartz/real.go +++ /dev/null @@ -1,80 +0,0 @@ -package quartz - -import ( - "context" - "time" -) - -type realClock struct{} - -func NewReal() Clock { - return realClock{} -} - -func (realClock) NewTicker(d time.Duration, _ ...string) *Ticker { - tkr := time.NewTicker(d) - return &Ticker{ticker: tkr, C: tkr.C} -} - -func (realClock) TickerFunc(ctx context.Context, d time.Duration, f func() error, _ ...string) Waiter { - ct := &realContextTicker{ - ctx: ctx, - tkr: time.NewTicker(d), - f: f, - err: make(chan error, 1), - } - go ct.run() - return ct -} - -type realContextTicker struct { - ctx context.Context - tkr *time.Ticker - f func() error - err chan error -} - -func (t *realContextTicker) Wait(_ ...string) error { - return <-t.err -} - -func (t *realContextTicker) run() { - defer t.tkr.Stop() - for { - select { - case <-t.ctx.Done(): - t.err <- t.ctx.Err() - return - case <-t.tkr.C: - err := t.f() - if err != nil { - t.err <- err - return - } - } - } -} - -func (realClock) NewTimer(d time.Duration, _ ...string) *Timer { - rt := time.NewTimer(d) - return &Timer{C: rt.C, timer: rt} -} - -func (realClock) AfterFunc(d time.Duration, f func(), _ ...string) *Timer { - rt := time.AfterFunc(d, f) - return &Timer{C: rt.C, timer: rt} -} - -func (realClock) Now(_ ...string) time.Time { - return time.Now() -} - -func (realClock) Since(t time.Time, _ ...string) time.Duration { - return time.Since(t) -} - -func (realClock) Until(t time.Time, _ ...string) time.Duration { - return time.Until(t) -} - -var _ Clock = realClock{} diff --git a/vendor/github.com/coder/quartz/ticker.go b/vendor/github.com/coder/quartz/ticker.go deleted file mode 100644 index f4a4b066502..00000000000 --- a/vendor/github.com/coder/quartz/ticker.go +++ /dev/null @@ -1,151 +0,0 @@ -package quartz - -import "time" - -// A Ticker holds a channel that delivers “ticks” of a clock at intervals. -type Ticker struct { - C <-chan time.Time - //nolint: revive - c chan time.Time - ticker *time.Ticker // realtime impl, if set - d time.Duration // period, if set - nxt time.Time // next tick time - mock *Mock // mock clock, if set - stopped bool // true if the ticker is not running - internalTicks chan time.Time // used to deliver ticks to the runLoop goroutine - - // As of Go 1.23, ticker channels are unbuffered and guaranteed to block forever after a call to stop. - // - // When a mocked ticker fires, we don't want to block on a channel write, because it's fine for the code under test - // not to be reading. That means we need to start a new goroutine to do the channel write (runLoop) if we are a - // channel-based ticker. - // - // They also are not supposed to leak even if they are never read or stopped (Go runtime can garbage collect them). - // We can't garbage-collect because we can't check if any other code besides the mock references, but we can ensure - // that we don't leak goroutines so that the garbage collector can do its job when the mock is no longer - // referenced. The channels below allow us to interrupt the runLoop goroutine. - interrupt chan struct{} -} - -func (t *Ticker) fire(tt time.Time) { - t.mock.mu.Lock() - defer t.mock.mu.Unlock() - if t.stopped { - return - } - for !t.nxt.After(t.mock.cur) { - t.nxt = t.nxt.Add(t.d) - } - t.mock.recomputeNextLocked() - if t.interrupt != nil { // implies runLoop is still going. - t.internalTicks <- tt - } -} - -func (t *Ticker) next() time.Time { - return t.nxt -} - -// Stop turns off a ticker. After Stop, no more ticks will be sent. Stop does -// not close the channel, to prevent a concurrent goroutine reading from the -// channel from seeing an erroneous "tick". -func (t *Ticker) Stop(tags ...string) { - if t.ticker != nil { - t.ticker.Stop() - return - } - t.mock.mu.Lock() - defer t.mock.mu.Unlock() - c := newCall(clockFunctionTickerStop, tags) - t.mock.matchCallLocked(c) - defer close(c.complete) - t.mock.removeEventLocked(t) - t.stopped = true - // check if we've already fired, and if so, interrupt it. - if t.interrupt != nil { - <-t.interrupt - t.interrupt = nil - } -} - -// Reset stops a ticker and resets its period to the specified duration. The -// next tick will arrive after the new period elapses. The duration d must be -// greater than zero; if not, Reset will panic. -func (t *Ticker) Reset(d time.Duration, tags ...string) { - if t.ticker != nil { - t.ticker.Reset(d) - return - } - t.mock.mu.Lock() - defer t.mock.mu.Unlock() - c := newCall(clockFunctionTickerReset, tags, withDuration(d)) - t.mock.matchCallLocked(c) - defer close(c.complete) - t.nxt = t.mock.cur.Add(d) - t.d = d - if t.stopped { - t.stopped = false - t.mock.addEventLocked(t) - } else { - t.mock.recomputeNextLocked() - } - if t.interrupt == nil { - t.startRunLoopLocked() - } -} - -func (t *Ticker) runLoop(interrupt chan struct{}) { - defer close(interrupt) -outer: - for { - select { - case tt := <-t.internalTicks: - for { - select { - case t.c <- tt: - continue outer - case <-t.internalTicks: - // Discard future ticks until we can send this one. - case interrupt <- struct{}{}: - return - } - } - case interrupt <- struct{}{}: - return - } - } -} - -func (t *Ticker) startRunLoopLocked() { - // assert some assumptions. If these fire, it is a bug in Quartz itself. - if t.interrupt != nil { - t.mock.tb.Error("called startRunLoopLocked when interrupt suggests we are already running") - } - interrupt := make(chan struct{}) - t.interrupt = interrupt - go t.runLoop(interrupt) -} - -func newMockTickerLocked(m *Mock, d time.Duration) *Ticker { - // no buffer follows Go 1.23+ behavior - ticks := make(chan time.Time) - t := &Ticker{ - C: ticks, - c: ticks, - d: d, - nxt: m.cur.Add(d), - mock: m, - internalTicks: make(chan time.Time), - } - m.addEventLocked(t) - m.tb.Cleanup(func() { - m.mu.Lock() - defer m.mu.Unlock() - if t.interrupt != nil { - <-t.interrupt - t.interrupt = nil - } - }) - t.startRunLoopLocked() - return t -} diff --git a/vendor/github.com/coder/quartz/timer.go b/vendor/github.com/coder/quartz/timer.go deleted file mode 100644 index 8f571eb0dc6..00000000000 --- a/vendor/github.com/coder/quartz/timer.go +++ /dev/null @@ -1,118 +0,0 @@ -package quartz - -import ( - "time" -) - -// The Timer type represents a single event. When the Timer expires, the current time will be sent -// on C, unless the Timer was created by AfterFunc. A Timer must be created with NewTimer or -// AfterFunc. -type Timer struct { - C <-chan time.Time - //nolint: revive - c chan time.Time - timer *time.Timer // realtime impl, if set - nxt time.Time // next tick time - mock *Mock // mock clock, if set - fn func() // AfterFunc function, if set - stopped bool // True if stopped, false if running - - // As of Go 1.23, timer channels are unbuffered and guaranteed to block forever after a call to stop. - // - // When a mocked timer fires, we don't want to block on a channel write, because it's fine for the code under test - // not to be reading. That means we need to start a new goroutine to do the channel write if we are a channel-based - // timer. - // - // They also are not supposed to leak even if they are never read or stopped (Go runtime can garbage collect them). - // We can't garbage-collect because we can't check if any other code besides the mock references, but we can ensure - // that we don't leak goroutines so that the garbage collector can do its job when the mock is no longer - // referenced. The channels below allow us to interrupt the channel write goroutine. - interrupt chan struct{} -} - -func (t *Timer) fire(tt time.Time) { - t.mock.mu.Lock() - t.mock.removeTimerLocked(t) - if t.fn != nil { - t.mock.mu.Unlock() - t.fn() - return - } else { - interrupt := make(chan struct{}) - // Prevents the goroutine from leaking beyond the test. Side effect is that timer channels cannot be read - // after the test exits. - t.mock.tb.Cleanup(func() { - <-interrupt - }) - t.interrupt = interrupt - t.mock.mu.Unlock() - go func() { - defer close(interrupt) - select { - case t.c <- tt: - case interrupt <- struct{}{}: - } - }() - } -} - -func (t *Timer) next() time.Time { - return t.nxt -} - -// Stop prevents the Timer from firing. It returns true if the call stops the timer, false if the -// timer has already expired or been stopped. Stop does not close the channel, to prevent a read -// from the channel succeeding incorrectly. -// -// See https://pkg.go.dev/time#Timer.Stop for more information. -func (t *Timer) Stop(tags ...string) bool { - if t.timer != nil { - return t.timer.Stop() - } - t.mock.mu.Lock() - defer t.mock.mu.Unlock() - c := newCall(clockFunctionTimerStop, tags) - t.mock.matchCallLocked(c) - defer close(c.complete) - result := !t.stopped - t.mock.removeTimerLocked(t) - // check if we've already fired, and if so, interrupt it. - if t.interrupt != nil { - <-t.interrupt - t.interrupt = nil - } - return result -} - -// Reset changes the timer to expire after duration d. It returns true if the timer had been active, -// false if the timer had expired or been stopped. -// -// See https://pkg.go.dev/time#Timer.Reset for more information. -func (t *Timer) Reset(d time.Duration, tags ...string) bool { - if t.timer != nil { - return t.timer.Reset(d) - } - t.mock.mu.Lock() - defer t.mock.mu.Unlock() - c := newCall(clockFunctionTimerReset, tags, withDuration(d)) - t.mock.matchCallLocked(c) - defer close(c.complete) - result := !t.stopped - // check if we've already fired, and if so, interrupt it. - if t.interrupt != nil { - <-t.interrupt - t.interrupt = nil - } - if d <= 0 { - // zero or negative duration timer means we should immediately re-fire - // it, rather than remove and re-add it. - t.stopped = false - go t.fire(t.mock.cur) - return result - } - t.mock.removeTimerLocked(t) - t.stopped = false - t.nxt = t.mock.cur.Add(d) - t.mock.addEventLocked(t) - return result -} diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index 4ed4864f475..3027f3c67a2 100644 --- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +1.10.1 2026-05-04 +----------------- + +### Changes and fixes + +- inotify: don't remove sibling watches sharing a path prefix ([#754]) + +- inotify, windows: don't rename sibling watches sharing a path prefix + ([#755]) + + +[#754]: https://github.com/fsnotify/fsnotify/pull/754 +[#755]: https://github.com/fsnotify/fsnotify/pull/755 + + 1.10.0 2026-04-30 ----------------- This version of fsnotify needs Go 1.23. diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md index d8441aa0614..2e56ef4c9a5 100644 --- a/vendor/github.com/fsnotify/fsnotify/README.md +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -171,6 +171,38 @@ distro's documentation): fs.inotify.max_user_watches=200000 fs.inotify.max_user_instances=256 +### Windows +Recursive watching is not currently enabled through fsnotify's public API +(see the FAQ "Are subdirectories watched?" above). The notes below +describe Windows backend behavior observed when recursive watching is +enabled internally (for example, in fsnotify's own tests). They are kept +here as a reference for maintainers and contributors who encounter the +behavior, since the recursive code path still exists in the backend. + +When recursive watching is enabled and you watch a directory, you may +receive a `Write` event for an intermediate directory whenever a child +entry inside it is created, renamed, or removed. For example, with a +recursive watch on `/a` and a new file `/a/b/c`, you will receive +`Create /a/b/c` and may also receive `Write /a/b`. + +This happens because, on NTFS-backed volumes, modifying the entries of a +directory updates that directory's last-write time, and the Windows +backend requests `FILE_NOTIFY_CHANGE_LAST_WRITE` to support `Write` events +on files. The same `Write` filter therefore picks up the directory's +metadata update. + +kqueue has the same "directory `Write` = directory contents changed" +semantics, so portable code that treats `Write` on a directory as +"something inside it changed" works on Windows and BSD/macOS, but not on +Linux (inotify uses `Write` only for file-content changes). If you only +care about file content, filter out `Write` events whose path refers to a +directory. + +Whether the directory `Write` is actually delivered alongside the child +events is not guaranteed: it depends on `ReadDirectoryChangesW` buffering, +NTFS metadata update timing, and event coalescing, none of which fsnotify +controls. + ### kqueue (macOS, all BSD systems) kqueue requires opening a file descriptor for every file that's being watched; diff --git a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go index cdb7812ac12..4c3f6f7c283 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go @@ -82,6 +82,13 @@ func (w *watches) len() int { return len(w.wd) } func (w *watches) add(ww *watch) { w.wd[ww.wd] = ww; w.path[ww.path] = ww.wd } func (w *watches) remove(watch *watch) { delete(w.path, watch.path); delete(w.wd, watch.wd) } +func isSameOrDescendantPath(path, root string) bool { + if path == root { + return true + } + return strings.HasPrefix(path, root+string(os.PathSeparator)) +} + func (w *watches) removePath(path string) ([]uint32, error) { path, recurse := recursivePath(path) wd, ok := w.path[path] @@ -103,7 +110,7 @@ func (w *watches) removePath(path string) ([]uint32, error) { wds := make([]uint32, 0, 8) wds = append(wds, wd) for p, rwd := range w.path { - if strings.HasPrefix(p, path) { + if isSameOrDescendantPath(p, path) { delete(w.path, p) delete(w.wd, rwd) wds = append(wds, rwd) @@ -501,7 +508,7 @@ func (w *inotify) handleEvent(inEvent *unix.InotifyEvent, buf *[65536]byte, offs if k == watch.wd || ww.path == ev.Name { continue } - if strings.HasPrefix(ww.path, ev.renamedFrom) { + if isSameOrDescendantPath(ww.path, ev.renamedFrom) { ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1) w.watches.wd[k] = ww } diff --git a/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/vendor/github.com/fsnotify/fsnotify/backend_windows.go index 8ef0eb0f621..fb9210f24ed 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_windows.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_windows.go @@ -36,6 +36,13 @@ type readDirChangesW struct { var defaultBufferSize = 50 +func isSameOrDescendantPath(path, root string) bool { + if path == root { + return true + } + return strings.HasPrefix(path, root+string(os.PathSeparator)) +} + func newBackend(ev chan Event, errs chan error) (backend, error) { port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0) if err != nil { @@ -605,7 +612,7 @@ func (w *readDirChangesW) readEvents() { w.mu.Lock() for _, watchMap := range w.watches { for _, ww := range watchMap { - if strings.HasPrefix(ww.path, old) { + if isSameOrDescendantPath(ww.path, old) { ww.path = filepath.Join(fullname, strings.TrimPrefix(ww.path, old)) } } diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index c7a4cb309cc..38cb4dd481c 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -92,6 +92,28 @@ import ( // Sometimes it will send events for all files, sometimes it will send no // events, and often only for some files. // +// Recursive watching is not currently enabled through fsnotify's public +// API; the recursive code path is gated and only exercised by fsnotify's +// own tests. The note below describes backend behavior observed when +// recursive watching is enabled internally, and is kept here as a +// reference for maintainers and contributors who encounter it. +// +// When recursive watching is enabled and you watch a directory, you may +// receive a Write event for an intermediate directory whenever a child +// entry inside it is created, renamed, or removed. For example, with a +// recursive watch on /a and a new file /a/b/c, you will receive +// Create /a/b/c and may also receive Write /a/b. +// +// This happens because, on NTFS-backed volumes, modifying the entries of a +// directory updates that directory's last-write time, and the Windows +// backend requests FILE_NOTIFY_CHANGE_LAST_WRITE to support Write events +// on files. The same Write filter therefore picks up the directory's +// metadata update. +// +// Whether the directory Write is actually delivered alongside the child +// events is not guaranteed; it depends on ReadDirectoryChangesW buffering, +// NTFS metadata update timing, and event coalescing. +// // The default ReadDirectoryChangesW() buffer size is 64K, which is the largest // value that is guaranteed to work with SMB filesystems. If you have many // events in quick succession this may not be enough, and you will have to use @@ -128,8 +150,12 @@ type Watcher struct { // want to wait until you've stopped receiving them // (see the dedup example in cmd/fsnotify). // - // Some systems may send Write event for directories - // when the directory content changes. + // Some systems also send Write events for directories + // when the directory contents change. This is the + // case for kqueue, and on Windows for the directory + // that contains a created, renamed, or removed child + // entry. It does not happen on inotify. See the + // per-platform notes on [Watcher]. // // fsnotify.Chmod Attributes were changed. On Linux this is also sent // when a file is removed (or more accurately, when a @@ -178,7 +204,9 @@ const ( Create Op = 1 << iota // The pathname was written to; this does *not* mean the write has finished, - // and a write can be followed by more writes. + // and a write can be followed by more writes. On Windows and kqueue, a + // Write on a directory can also indicate that its contents changed; see + // the per-platform notes on [Watcher]. Write // The path was removed; any watches on it will be removed. Some "remove" diff --git a/vendor/github.com/go-openapi/analysis/.gitignore b/vendor/github.com/go-openapi/analysis/.gitignore index d8f4186fe59..20c4e0fa048 100644 --- a/vendor/github.com/go-openapi/analysis/.gitignore +++ b/vendor/github.com/go-openapi/analysis/.gitignore @@ -3,3 +3,5 @@ .idea .env .mcp.json +go.work.sum +.worktrees diff --git a/vendor/github.com/go-openapi/analysis/.golangci.yml b/vendor/github.com/go-openapi/analysis/.golangci.yml index b97d68077f8..0d7baa1d7fb 100644 --- a/vendor/github.com/go-openapi/analysis/.golangci.yml +++ b/vendor/github.com/go-openapi/analysis/.golangci.yml @@ -4,8 +4,11 @@ linters: disable: - depguard - funlen + - goconst - godox - gomoddirectives + - gomodguard + - gomodguard_v2 - exhaustruct - nlreturn - nonamedreturns diff --git a/vendor/github.com/go-openapi/analysis/CONTRIBUTORS.md b/vendor/github.com/go-openapi/analysis/CONTRIBUTORS.md index 2f85f1c0504..a89274cdbc3 100644 --- a/vendor/github.com/go-openapi/analysis/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/analysis/CONTRIBUTORS.md @@ -4,24 +4,31 @@ | Total Contributors | Total Contributions | | --- | --- | -| 15 | 207 | +| 22 | 273 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | -| @fredbi | 104 | | -| @casualjim | 70 | | +| @fredbi | 133 | | +| @casualjim | 91 | | | @keramix | 9 | | | @youyuanwu | 8 | | -| @msample | 3 | | +| @wjase | 7 | | | @kul-amr | 3 | | +| @schafle | 3 | | +| @msample | 3 | | | @mbohlool | 2 | | -| @Copilot | 1 | | -| @danielfbm | 1 | | -| @gregmarr | 1 | | -| @guillemj | 1 | | -| @knweiss | 1 | | -| @tklauser | 1 | | -| @cuishuang | 1 | | +| @zmay2030 | 2 | | | @ujjwalsh | 1 | | +| @itengfei | 1 | | +| @nrnrk | 1 | | +| @cuishuang | 1 | | +| @tklauser | 1 | | +| @Shimizu1111 | 1 | | +| @thaJeztah | 1 | | +| @knweiss | 1 | | +| @guillemj | 1 | | +| @gregmarr | 1 | | +| @danielfbm | 1 | | +| @Copilot | 1 | | _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/analysis/README.md b/vendor/github.com/go-openapi/analysis/README.md index 82c782fcdd4..2a90462974e 100644 --- a/vendor/github.com/go-openapi/analysis/README.md +++ b/vendor/github.com/go-openapi/analysis/README.md @@ -12,18 +12,15 @@ --- -A foundational library to analyze an OAI specification document for easier reasoning about the content. +A foundational library to analyze, diff, flatten, merge, and fix OAI specification documents for easier reasoning about the content. ## Announcements * **2025-12-19** : new community chat on discord * a new discord community channel is available to be notified of changes and support users - * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] -Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] - ## Status API is stable. @@ -38,6 +35,7 @@ go get github.com/go-openapi/analysis * An analyzer providing methods to walk the functional content of a specification * A spec flattener producing a self-contained document bundle, while preserving `$ref`s +* A spec differ ("diff") to compare two specs and report structural and compatibility changes * A spec merger ("mixin") to merge several spec documents into a primary spec * A spec "fixer" ensuring that response descriptions are non empty @@ -78,9 +76,9 @@ on top of which it has been built. ## Other documentation * [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines](.github/CONTRIBUTING.md) -* [Maintainers documentation](docs/MAINTAINERS.md) -* [Code style](docs/STYLE.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] ## Cutting a new release @@ -111,9 +109,6 @@ Maintainers can cut a new release by either: [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/analysis [godoc-url]: http://pkg.go.dev/github.com/go-openapi/analysis -[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png -[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM -[slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue [discord-url]: https://discord.gg/FfnFYaC3k5 @@ -125,3 +120,7 @@ Maintainers can cut a new release by either: [goversion-url]: https://github.com/go-openapi/analysis/blob/master/go.mod [top-badge]: https://img.shields.io/github/languages/top/go-openapi/analysis [commits-badge]: https://img.shields.io/github/commits-since/go-openapi/analysis/latest + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/analysis/analyzer.go b/vendor/github.com/go-openapi/analysis/analyzer.go index 1c91b8c5507..c24811aaeb5 100644 --- a/vendor/github.com/go-openapi/analysis/analyzer.go +++ b/vendor/github.com/go-openapi/analysis/analyzer.go @@ -145,19 +145,27 @@ type Spec struct { enums enumAnalysis allSchemas map[string]SchemaRef allOfs map[string]SchemaRef + mangler mangling.NameMangler } // New takes a swagger spec object and returns an analyzed spec document. // The analyzed document contains a number of indices that make it easier to // reason about semantics of a swagger specification for use in code generation // or validation etc. -func New(doc *spec.Swagger) *Spec { +func New(doc *spec.Swagger, opts ...Option) *Spec { + o := &analyzerOptions{} + for _, opt := range opts { + opt(o) + } + a := &Spec{ spec: doc, references: referenceAnalysis{}, patterns: patternAnalysis{}, enums: enumAnalysis{}, + mangler: mangling.NewNameMangler(o.manglerOpts...), } + a.reset() a.initialize() @@ -288,20 +296,6 @@ func (s *Spec) ProducesFor(operation *spec.Operation) []string { return s.structMapKeys(prod) } -func mapKeyFromParam(param *spec.Parameter) string { - return fmt.Sprintf("%s#%s", param.In, fieldNameFromParam(param)) -} - -func fieldNameFromParam(param *spec.Parameter) string { - // TODO: this should be x-go-name - if nm, ok := param.Extensions.GetString("go-name"); ok { - return nm - } - mangler := mangling.NewNameMangler() - - return mangler.ToGoName(param.Name) -} - // ErrorOnParamFunc is a callback function to be invoked // whenever an error is encountered while resolving references // on parameters. @@ -651,6 +645,19 @@ func (s *Spec) AllEnums() map[string][]any { return cloneEnumMap(s.enums.allEnums) } +func (s *Spec) mapKeyFromParam(param *spec.Parameter) string { + return fmt.Sprintf("%s#%s", param.In, s.fieldNameFromParam(param)) +} + +func (s *Spec) fieldNameFromParam(param *spec.Parameter) string { + // TODO: this should be x-go-name + if nm, ok := param.Extensions.GetString("go-name"); ok { + return nm + } + + return s.mangler.ToGoName(param.Name) +} + func (s *Spec) structMapKeys(mp map[string]struct{}) []string { if len(mp) == 0 { return nil @@ -668,7 +675,7 @@ func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Para for _, param := range parameters { pr := param if pr.Ref.String() == "" { - res[mapKeyFromParam(&pr)] = pr + res[s.mapKeyFromParam(&pr)] = pr continue } @@ -699,7 +706,7 @@ func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Para } pr = objAsParam - res[mapKeyFromParam(&pr)] = pr + res[s.mapKeyFromParam(&pr)] = pr } } diff --git a/vendor/github.com/go-openapi/analysis/flatten.go b/vendor/github.com/go-openapi/analysis/flatten.go index d7ee0064b6f..c90456f6a05 100644 --- a/vendor/github.com/go-openapi/analysis/flatten.go +++ b/vendor/github.com/go-openapi/analysis/flatten.go @@ -243,7 +243,7 @@ func nameInlinedSchemas(opts *FlattenOpts) error { continue } - asch, err := Schema(SchemaOpts{Schema: sch.Schema, Root: opts.Swagger(), BasePath: opts.BasePath}) + asch, err := Schema(SchemaOpts{Schema: sch.Schema, Root: opts.Swagger(), BasePath: opts.BasePath, PathLoaderWithOptions: opts.PathLoaderWithOptions}) if err != nil { return ErrAtKey(key, err) } @@ -554,6 +554,7 @@ func updateRefParents(allRefs map[string]spec.Ref, r *newRef) { } } +//nolint:gocognit,gocyclo,cyclop // legacy from a lot of design choices that led to concentrate the complexity just here. func stripOAIGenForRef(opts *FlattenOpts, k string, r *newRef) (bool, error) { replacedWithComplex := false @@ -574,7 +575,7 @@ func stripOAIGenForRef(opts *FlattenOpts, k string, r *newRef) (bool, error) { } // rewrite other parents to point to first parent - if len(pr) > 1 { + if len(pr) > 1 { //nolint:nestif // should be refactored at a later time for _, p := range pr[1:] { replacingRef := spec.MustCreateRef(pr[0]) @@ -656,7 +657,7 @@ func stripOAIGenForRef(opts *FlattenOpts, k string, r *newRef) (bool, error) { // determine if the previous substitution did inline a complex schema if r.schema != nil && r.schema.Ref.String() == "" { // inline schema - asch, err := Schema(SchemaOpts{Schema: r.schema, Root: opts.Swagger(), BasePath: opts.BasePath}) + asch, err := Schema(SchemaOpts{Schema: r.schema, Root: opts.Swagger(), BasePath: opts.BasePath, PathLoaderWithOptions: opts.PathLoaderWithOptions}) if err != nil { return false, err } @@ -760,7 +761,7 @@ func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]Schema debugLog("namePointers at %s for %s", key, v.Ref.String()) // qualify the expanded schema - asch, ers := Schema(SchemaOpts{Schema: v.Schema, Root: opts.Swagger(), BasePath: opts.BasePath}) + asch, ers := Schema(SchemaOpts{Schema: v.Schema, Root: opts.Swagger(), BasePath: opts.BasePath, PathLoaderWithOptions: opts.PathLoaderWithOptions}) if ers != nil { return ErrAtKey(key, ers) } diff --git a/vendor/github.com/go-openapi/analysis/flatten_name.go b/vendor/github.com/go-openapi/analysis/flatten_name.go index 922cae55c5e..9d732171840 100644 --- a/vendor/github.com/go-openapi/analysis/flatten_name.go +++ b/vendor/github.com/go-openapi/analysis/flatten_name.go @@ -273,9 +273,9 @@ func mangler(o *FlattenOpts) func(string) string { if o.KeepNames { return func(in string) string { return in } } - mangler := mangling.NewNameMangler() + m := mangling.NewNameMangler(o.ManglerOpts...) - return mangler.ToJSONName + return m.ToJSONName } func nameFromRef(ref spec.Ref, o *FlattenOpts) string { diff --git a/vendor/github.com/go-openapi/analysis/flatten_options.go b/vendor/github.com/go-openapi/analysis/flatten_options.go index 23a57ea1aca..1e182ad4355 100644 --- a/vendor/github.com/go-openapi/analysis/flatten_options.go +++ b/vendor/github.com/go-openapi/analysis/flatten_options.go @@ -4,9 +4,12 @@ package analysis import ( + "encoding/json" "log" "github.com/go-openapi/spec" + "github.com/go-openapi/swag/loading" + "github.com/go-openapi/swag/mangling" ) // FlattenOpts configuration for flattening a swagger specification. @@ -24,12 +27,23 @@ type FlattenOpts struct { BasePath string // The location of the root document for this spec to resolve relative $ref // Flattening options - Expand bool // When true, skip flattening the spec and expand it instead (if Minimal is false) - Minimal bool // When true, do not decompose complex structures such as allOf - Verbose bool // enable some reporting on possible name conflicts detected - RemoveUnused bool // When true, remove unused parameters, responses and definitions after expansion/flattening - ContinueOnError bool // Continue when spec expansion issues are found - KeepNames bool // Do not attempt to jsonify names from references when flattening + Expand bool // When true, skip flattening the spec and expand it instead (if Minimal is false) + Minimal bool // When true, do not decompose complex structures such as allOf + Verbose bool // enable some reporting on possible name conflicts detected + RemoveUnused bool // When true, remove unused parameters, responses and definitions after expansion/flattening + ContinueOnError bool // Continue when spec expansion issues are found + KeepNames bool // Do not attempt to jsonify names from references when flattening + ManglerOpts []mangling.Option `json:"-"` // Options for the name mangler used to jsonify names + + // PathLoaderWithOptions injects the document loader used to resolve remote and relative $ref + // while flattening or expanding the specification. It matches the option-aware loader signature + // of github.com/go-openapi/swag/loading (and go-openapi/loads). + // + // Security: when flattening a specification obtained from an untrusted source, set this to a + // confined loader — for example one built with loading.WithRoot (to confine local reads) and + // loading.WithHTTPClient (to restrict remote fetches), or a restricted loader from + // go-openapi/loads. Left nil, the spec package default (unsandboxed) loader is used. + PathLoaderWithOptions func(string, ...loading.Option) (json.RawMessage, error) `json:"-"` /* Extra keys */ _ struct{} // require keys @@ -38,9 +52,10 @@ type FlattenOpts struct { // ExpandOpts creates a spec.[spec.ExpandOptions] to configure expanding a specification document. func (f *FlattenOpts) ExpandOpts(skipSchemas bool) *spec.ExpandOptions { return &spec.ExpandOptions{ - RelativeBase: f.BasePath, - SkipSchemas: skipSchemas, - ContinueOnError: f.ContinueOnError, + RelativeBase: f.BasePath, + SkipSchemas: skipSchemas, + ContinueOnError: f.ContinueOnError, + PathLoaderWithOptions: f.PathLoaderWithOptions, } } diff --git a/vendor/github.com/go-openapi/analysis/go.work.sum b/vendor/github.com/go-openapi/analysis/go.work.sum deleted file mode 100644 index 899a68976e7..00000000000 --- a/vendor/github.com/go-openapi/analysis/go.work.sum +++ /dev/null @@ -1,47 +0,0 @@ -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 h1:BHT1/DKsYDGkUgQ2jmMaozVcdk+sVfz0+1ZJq4zkWgw= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= -go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= -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/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -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/telemetry v0.0.0-20260209163413-e7419c687ee4 h1:bTLqdHv7xrGlFbvf5/TXNxy/iUwwdkjhqQTJDjW7aj0= -golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4/go.mod h1:g5NllXBEermZrmR51cJDQxmJUHUOfRAaNyWBM+R+548= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= -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/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= diff --git a/vendor/github.com/go-openapi/analysis/mixin.go b/vendor/github.com/go-openapi/analysis/mixin.go index a7a9306cb37..635b1b0ad4a 100644 --- a/vendor/github.com/go-openapi/analysis/mixin.go +++ b/vendor/github.com/go-openapi/analysis/mixin.go @@ -11,37 +11,66 @@ import ( "github.com/go-openapi/spec" ) -// Mixin modifies the primary swagger spec by adding the paths and -// definitions from the mixin specs. Top level parameters and -// responses from the mixins are also carried over. Operation id -// collisions are avoided by appending "Mixin" but only if -// needed. +// Mixin merges one or more Swagger 2.0 documents into a primary document. // -// The following parts of primary are subject to merge, filling empty details +// # Argument order and precedence // -// - Info +// The first argument is the primary spec, which Mixin modifies in place. +// Subsequent arguments are mixins, listed in decreasing order of priority. +// On any collision, the primary always wins; among mixins, the earliest one +// wins. +// +// Example: given a primary spec with host "a.example.com" and a mixin with +// host "b.example.com", the merged result keeps "a.example.com" (primary +// wins, the mixin value is dropped). Given a primary without a host and a +// mixin with host "b.example.com", the merged result uses "b.example.com" +// (the mixin fills in the empty field on the primary). +// +// # What gets merged +// +// Top-level scalar fields on the primary are filled from the first mixin +// that provides them, but only if the primary's value is the zero value: +// +// - Info (including the nested Contact and License) // - BasePath // - Host // - ExternalDocs // -// Consider calling [FixEmptyResponseDescriptions]() on the modified primary -// if you read them from storage and they are valid to start with. +// Map and slice fields are merged entry by entry. This covers: +// +// - paths, definitions, parameters, responses +// - securityDefinitions, security, tags +// - top-level and Info extensions +// +// Duplicate keys (or equal security requirements, or equal tag names) are +// skipped with a warning; warnings are returned as a slice and intended to +// be inspected by the caller (e.g. compared to an expected collision count +// in build scripts). +// +// Schemes, consumes and produces are merged as the union of distinct +// values. Duplicates there are silently dropped, no warning is emitted. +// +// Operation id collisions are auto-resolved by appending "Mixin" to the +// mixin operation id (N is the mixin index), so the merged spec keeps +// unique operation ids. +// +// # Notes and limitations // -// Entries in "paths", "definitions", "parameters" and "responses" are -// added to the primary in the order of the given mixins. If the entry -// already exists in primary it is skipped with a warning message. +// Consider calling [FixEmptyResponseDescriptions] on the modified primary +// if you read responses from storage and they are valid to start with. // -// The count of skipped entries (from collisions) is returned so any -// deviation from the number expected can flag a warning in your build -// scripts. Carefully review the collisions before accepting them; -// consider renaming things if possible. +// No key normalization takes place. Ensure paths, type names, etc. are +// canonical if your downstream tools rely on normalized forms. // -// No key normalization takes place (paths, type defs, -// etc). Ensure they are canonical if your downstream tools do -// key normalization of any form. +// YAML anchors (& / *) are resolved by the YAML parser before Mixin sees +// the document, so they are not preserved in the merged output, and they +// cannot be shared across input files. Use $ref for cross-file reuse. See +// https://goswagger.io/go-swagger/faq/faq_swagger/#does-swagger-mixin-preserve-yaml-anchors // -// Merging schemes ([http], https), and consumers/producers do not account for -// collisions. +// The order of paths and definitions in the merged output is alphabetical: +// the underlying spec model stores them as Go maps, which serialize with +// sorted keys. Source-file order is not preserved. See +// https://goswagger.io/go-swagger/faq/faq_swagger/#can-i-control-the-path-or-operation-order-in-swagger-mixin-output func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string { skipped := make([]string, 0, len(mixins)) opIDs := getOpIDs(primary) @@ -101,6 +130,7 @@ func pathItemOps(p spec.PathItem) []*spec.Operation { rv = appendOp(rv, p.Post) rv = appendOp(rv, p.Delete) rv = appendOp(rv, p.Head) + rv = appendOp(rv, p.Options) rv = appendOp(rv, p.Patch) return rv @@ -184,9 +214,9 @@ func mergePaths(primary *spec.Swagger, m *spec.Swagger, opIDs map[string]bool, m // Swagger requires that operationIds be // unique within a spec. If we find a // collision we append "Mixin0" to the - // operatoinId we are adding, where 0 is mixin + // operationId we are adding, where 0 is mixin // index. We assume that operationIds with - // all the proivded specs are already unique. + // all the provided specs are already unique. piops := pathItemOps(v) for _, piop := range piops { if opIDs[piop.ID] { @@ -329,7 +359,7 @@ func mergeSwaggerProps(primary *spec.Swagger, m *spec.Swagger) []string { if primary.ExternalDocs == nil { primary.ExternalDocs = m.ExternalDocs - } else if m != nil { + } else if m.ExternalDocs != nil { skippedDocs = mergeExternalDocs(primary.ExternalDocs, m.ExternalDocs) skipped = append(skipped, skippedDocs...) } diff --git a/vendor/github.com/go-openapi/analysis/options.go b/vendor/github.com/go-openapi/analysis/options.go new file mode 100644 index 00000000000..b46cd2ca693 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/options.go @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package analysis + +import "github.com/go-openapi/swag/mangling" + +// Option configures the behavior of a new [Spec] analyzer. +type Option func(*analyzerOptions) + +type analyzerOptions struct { + manglerOpts []mangling.Option +} + +// WithManglerOptions sets the name mangler options used when building +// Go identifiers from specification names (e.g. parameter names). +func WithManglerOptions(opts ...mangling.Option) Option { + return func(o *analyzerOptions) { + o.manglerOpts = append(o.manglerOpts, opts...) + } +} diff --git a/vendor/github.com/go-openapi/analysis/schema.go b/vendor/github.com/go-openapi/analysis/schema.go index bedea652acf..2c250461eb0 100644 --- a/vendor/github.com/go-openapi/analysis/schema.go +++ b/vendor/github.com/go-openapi/analysis/schema.go @@ -4,8 +4,11 @@ package analysis import ( + "encoding/json" + "github.com/go-openapi/spec" "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag/loading" ) // SchemaOpts configures the schema analyzer. @@ -13,7 +16,17 @@ type SchemaOpts struct { Schema *spec.Schema Root any BasePath string - _ struct{} + + // PathLoaderWithOptions injects the document loader (with loading options) used to resolve + // remote and relative $ref while analyzing a schema. + // + // Security: set this to a confined loader — for example one built with loading.WithRoot and + // loading.WithHTTPClient, or a restricted loader from go-openapi/loads — when the schema may + // derive from an untrusted source. Left nil, the spec package default (unsandboxed) loader is + // used. + PathLoaderWithOptions func(string, ...loading.Option) (json.RawMessage, error) + + _ struct{} } // Schema analysis, will classify the schema according to known @@ -24,9 +37,10 @@ func Schema(opts SchemaOpts) (*AnalyzedSchema, error) { } a := &AnalyzedSchema{ - schema: opts.Schema, - root: opts.Root, - basePath: opts.BasePath, + schema: opts.Schema, + root: opts.Root, + basePath: opts.BasePath, + pathLoaderWithOptions: opts.PathLoaderWithOptions, } a.initializeFlags() @@ -54,9 +68,10 @@ func Schema(opts SchemaOpts) (*AnalyzedSchema, error) { // AnalyzedSchema indicates what the schema represents. type AnalyzedSchema struct { - schema *spec.Schema - root any - basePath string + schema *spec.Schema + root any + basePath string + pathLoaderWithOptions func(string, ...loading.Option) (json.RawMessage, error) hasProps bool hasAllOf bool @@ -103,19 +118,32 @@ func (a *AnalyzedSchema) inherits(other *AnalyzedSchema) { a.IsEnum = other.IsEnum } +// subSchemaOpts builds SchemaOpts for a nested schema, propagating the root, base path and the +// injected document loader so that confinement applies throughout the recursive analysis. +func (a *AnalyzedSchema) subSchemaOpts(sch *spec.Schema) SchemaOpts { + return SchemaOpts{ + Schema: sch, + Root: a.root, + BasePath: a.basePath, + PathLoaderWithOptions: a.pathLoaderWithOptions, + } +} + +// expandOpts builds the spec expand options for this analysis, carrying the injected loader so +// remote/relative $ref are resolved through it (rather than the unsandboxed package default). +func (a *AnalyzedSchema) expandOpts() *spec.ExpandOptions { + return &spec.ExpandOptions{PathLoaderWithOptions: a.pathLoaderWithOptions} +} + func (a *AnalyzedSchema) inferFromRef() error { if a.hasRef { sch := new(spec.Schema) sch.Ref = a.schema.Ref - err := spec.ExpandSchema(sch, a.root, nil) + err := spec.ExpandSchemaWithOptions(sch, a.root, nil, a.expandOpts()) if err != nil { return err } - rsch, err := Schema(SchemaOpts{ - Schema: sch, - Root: a.root, - BasePath: a.basePath, - }) + rsch, err := Schema(a.subSchemaOpts(sch)) if err != nil { // NOTE(fredbi): currently the only cause for errors is // unresolved ref. Since spec.ExpandSchema() expands the @@ -159,11 +187,7 @@ func (a *AnalyzedSchema) inferMap() error { // maps if a.schema.AdditionalProperties.Schema != nil { - msch, err := Schema(SchemaOpts{ - Schema: a.schema.AdditionalProperties.Schema, - Root: a.root, - BasePath: a.basePath, - }) + msch, err := Schema(a.subSchemaOpts(a.schema.AdditionalProperties.Schema)) if err != nil { return err } @@ -186,11 +210,7 @@ func (a *AnalyzedSchema) inferArray() error { a.IsArray = a.isArrayType() && (a.schema.Items == nil || a.schema.Items.Schemas == nil) if a.IsArray && a.hasItems { if a.schema.Items.Schema != nil { - itsch, err := Schema(SchemaOpts{ - Schema: a.schema.Items.Schema, - Root: a.root, - BasePath: a.basePath, - }) + itsch, err := Schema(a.subSchemaOpts(a.schema.Items.Schema)) if err != nil { return err } diff --git a/vendor/github.com/go-openapi/jsonpointer/.cliff.toml b/vendor/github.com/go-openapi/jsonpointer/.cliff.toml deleted file mode 100644 index 702629f5dc3..00000000000 --- a/vendor/github.com/go-openapi/jsonpointer/.cliff.toml +++ /dev/null @@ -1,181 +0,0 @@ -# git-cliff ~ configuration file -# https://git-cliff.org/docs/configuration - -[changelog] -header = """ -""" - -footer = """ - ------ - -**[{{ remote.github.repo }}]({{ self::remote_url() }}) license terms** - -[![License][license-badge]][license-url] - -[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg -[license-url]: {{ self::remote_url() }}/?tab=Apache-2.0-1-ov-file#readme - -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} -""" - -body = """ -{%- if version %} -## [{{ version | trim_start_matches(pat="v") }}]({{ self::remote_url() }}/tree/{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }} -{%- else %} -## [unreleased] -{%- endif %} -{%- if message %} - {%- raw %}\n{% endraw %} -{{ message }} - {%- raw %}\n{% endraw %} -{%- endif %} -{%- if version %} - {%- if previous.version %} - -**Full Changelog**: <{{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }}> - {%- endif %} -{%- else %} - {%- raw %}\n{% endraw %} -{%- endif %} - -{%- if statistics %}{% if statistics.commit_count %} - {%- raw %}\n{% endraw %} -{{ statistics.commit_count }} commits in this release. - {%- raw %}\n{% endraw %} -{%- endif %}{% endif %} ------ - -{%- for group, commits in commits | group_by(attribute="group") %} - {%- raw %}\n{% endraw %} -### {{ group | upper_first }} - {%- raw %}\n{% endraw %} - {%- for commit in commits %} - {%- if commit.remote.pr_title %} - {%- set commit_message = commit.remote.pr_title %} - {%- else %} - {%- set commit_message = commit.message %} - {%- endif %} -* {{ commit_message | split(pat="\n") | first | trim }} - {%- if commit.remote.username %} -{%- raw %} {% endraw %}by [@{{ commit.remote.username }}](https://github.com/{{ commit.remote.username }}) - {%- endif %} - {%- if commit.remote.pr_number %} -{%- raw %} {% endraw %}in [#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) - {%- endif %} -{%- raw %} {% endraw %}[...]({{ self::remote_url() }}/commit/{{ commit.id }}) - {%- endfor %} -{%- endfor %} - -{%- if github %} -{%- raw %}\n{% endraw -%} - {%- set all_contributors = github.contributors | length %} - {%- if github.contributors | filter(attribute="username", value="dependabot[bot]") | length < all_contributors %} ------ - -### People who contributed to this release - {% endif %} - {%- for contributor in github.contributors | filter(attribute="username") | sort(attribute="username") %} - {%- if contributor.username != "dependabot[bot]" and contributor.username != "github-actions[bot]" %} -* [@{{ contributor.username }}](https://github.com/{{ contributor.username }}) - {%- endif %} - {%- endfor %} - - {% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} ------ - {%- raw %}\n{% endraw %} - -### New Contributors - {%- endif %} - - {%- for contributor in github.contributors | filter(attribute="is_first_time", value=true) %} - {%- if contributor.username != "dependabot[bot]" and contributor.username != "github-actions[bot]" %} -* @{{ contributor.username }} made their first contribution - {%- if contributor.pr_number %} - in [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ - {%- endif %} - {%- endif %} - {%- endfor %} -{%- endif %} - -{%- raw %}\n{% endraw %} - -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} -""" -# Remove leading and trailing whitespaces from the changelog's body. -trim = true -# Render body even when there are no releases to process. -render_always = true -# An array of regex based postprocessors to modify the changelog. -postprocessors = [ - # Replace the placeholder with a URL. - #{ pattern = '', replace = "https://github.com/orhun/git-cliff" }, -] -# output file path -# output = "test.md" - -[git] -# Parse commits according to the conventional commits specification. -# See https://www.conventionalcommits.org -conventional_commits = false -# Exclude commits that do not match the conventional commits specification. -filter_unconventional = false -# Require all commits to be conventional. -# Takes precedence over filter_unconventional. -require_conventional = false -# Split commits on newlines, treating each line as an individual commit. -split_commits = false -# An array of regex based parsers to modify commit messages prior to further processing. -commit_preprocessors = [ - # Replace issue numbers with link templates to be updated in `changelog.postprocessors`. - #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, - # Check spelling of the commit message using https://github.com/crate-ci/typos. - # If the spelling is incorrect, it will be fixed automatically. - #{ pattern = '.*', replace_command = 'typos --write-changes -' } -] -# Prevent commits that are breaking from being excluded by commit parsers. -protect_breaking_commits = false -# An array of regex based parsers for extracting data from the commit message. -# Assigns commits to groups. -# Optionally sets the commit's scope and can decide to exclude commits from further processing. -commit_parsers = [ - { message = "^[Cc]hore\\([Rr]elease\\): prepare for", skip = true }, - { message = "(^[Mm]erge)|([Mm]erge conflict)", skip = true }, - { field = "author.name", pattern = "dependabot*", group = "Updates" }, - { message = "([Ss]ecurity)|([Vv]uln)", group = "Security" }, - { body = "(.*[Ss]ecurity)|([Vv]uln)", group = "Security" }, - { message = "([Cc]hore\\(lint\\))|(style)|(lint)|(codeql)|(golangci)", group = "Code quality" }, - { message = "(^[Dd]oc)|((?i)readme)|(badge)|(typo)|(documentation)", group = "Documentation" }, - { message = "(^[Ff]eat)|(^[Ee]nhancement)", group = "Implemented enhancements" }, - { message = "(^ci)|(\\(ci\\))|(fixup\\s+ci)|(fix\\s+ci)|(license)|(example)", group = "Miscellaneous tasks" }, - { message = "^test", group = "Testing" }, - { message = "(^fix)|(panic)", group = "Fixed bugs" }, - { message = "(^refact)|(rework)", group = "Refactor" }, - { message = "(^[Pp]erf)|(performance)", group = "Performance" }, - { message = "(^[Cc]hore)", group = "Miscellaneous tasks" }, - { message = "^[Rr]evert", group = "Reverted changes" }, - { message = "(upgrade.*?go)|(go\\s+version)", group = "Updates" }, - { message = ".*", group = "Other" }, -] -# Exclude commits that are not matched by any commit parser. -filter_commits = false -# An array of link parsers for extracting external references, and turning them into URLs, using regex. -link_parsers = [] -# Include only the tags that belong to the current branch. -use_branch_tags = false -# Order releases topologically instead of chronologically. -topo_order = false -# Order releases topologically instead of chronologically. -topo_order_commits = true -# Order of commits in each group/release within the changelog. -# Allowed values: newest, oldest -sort_commits = "newest" -# Process submodules commits -recurse_submodules = false - -#[remote.github] -#owner = "go-openapi" diff --git a/vendor/github.com/go-openapi/jsonpointer/.gitignore b/vendor/github.com/go-openapi/jsonpointer/.gitignore index 885dc27ab0b..d8f4186fe59 100644 --- a/vendor/github.com/go-openapi/jsonpointer/.gitignore +++ b/vendor/github.com/go-openapi/jsonpointer/.gitignore @@ -3,4 +3,3 @@ .idea .env .mcp.json -.claude/ diff --git a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml index dc7c96053de..9d2733176ea 100644 --- a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml +++ b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml @@ -4,7 +4,10 @@ linters: disable: - depguard - funlen + - goconst - godox + - gomodguard + - gomodguard_v2 - exhaustruct - nlreturn - nonamedreturns diff --git a/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md index 2ebebedc150..de0bf5c04ba 100644 --- a/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md @@ -4,14 +4,15 @@ | Total Contributors | Total Contributions | | --- | --- | -| 12 | 101 | +| 13 | 132 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | -| @fredbi | 54 | | +| @fredbi | 83 | | | @casualjim | 33 | | | @magodo | 3 | | | @youyuanwu | 3 | | +| @alexandear | 2 | | | @gaiaz-iusipov | 1 | | | @gbjk | 1 | | | @gordallott | 1 | | @@ -21,4 +22,4 @@ | @olivierlemasle | 1 | | | @testwill | 1 | | - _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_ + _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/jsonpointer/NOTICE b/vendor/github.com/go-openapi/jsonpointer/NOTICE index f3b51939a95..201908d2f08 100644 --- a/vendor/github.com/go-openapi/jsonpointer/NOTICE +++ b/vendor/github.com/go-openapi/jsonpointer/NOTICE @@ -18,7 +18,7 @@ It ships with copies of other software which license terms are recalled below. The original software was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). -github.com/sigh-399/jsonpointer +github.com/sigu-399/jsonpointer =========================== // SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) diff --git a/vendor/github.com/go-openapi/jsonpointer/README.md b/vendor/github.com/go-openapi/jsonpointer/README.md index c52803e2e8f..6e7929c64b3 100644 --- a/vendor/github.com/go-openapi/jsonpointer/README.md +++ b/vendor/github.com/go-openapi/jsonpointer/README.md @@ -16,17 +16,34 @@ An implementation of JSON Pointer for golang, which supports go `struct`. ## Announcements -* **2025-12-19** : new community chat on discord - * a new discord community channel is available to be notified of changes and support users - * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** - -You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] - -Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] +* **2026-07-07** : landing v1.0.0 + * stable API pledge + +* **2026-06-29** : reinsourced external dependency to swag (v0.24.0) + * module `github.com/go-openapi/swag/jsonname` is source directly here, so we no longer have any external dependency + * `jsonname` was never really used by any other package, so it makes sense to deprecate it away from the `swag` family + and retrofit its functionality here. `jsonpointer` no longer get external dependencies, besides test dependencies. + +* **2026-04-15** : added support for trailing "-" for arrays (v0.23.0) + * this brings full support of [RFC6901][RFC6901] + * this is supported for types relying on the reflection-based implemented + * API semantics remain essentially unaltered. Exception: `Pointer.Set(document any,value any) (document any, err error)` + can only perform a best-effort to mutate the input document in place. In the case of adding elements to an array with a + trailing "-", either pass a mutable array (`*[]T`) as the input document, or use the returned updated document instead. + * types that implement the `JSONSetable` interface may not implement the mutation implied by the trailing "-" + +* **2026-04-15** : added support for optional alternate JSON name providers + * for struct support the defaults might not suit all situations: there are known limitations + when it comes to handle untagged fields or embedded types. + * the default name provider in use is not fully aligned with go JSON stdlib + * exposed an option (or global setting) to change the provider that resolves a struct into json keys + * the default behavior is not altered ## Status -API is stable. +API is stable and feature-complete. + +The project continues to receive regular updates, bug fixes and hygiene maintenance (CI, linting, etc). ## Import this library in your project @@ -88,7 +105,7 @@ See -also known as [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) +also known as [RFC6901][RFC6901]. ## Licensing @@ -99,19 +116,19 @@ on top of which it has been built. ## Limitations -The 4.Evaluation part of the previous reference, starting with 'If the currently referenced value is a JSON array, -the reference token MUST contain either...' is not implemented. - -That is because our implementation of the JSON pointer only supports explicit references to array elements: -the provision in the spec to resolve non-existent members as "the last element in the array", -using the special trailing character "-" is not implemented. +* [RFC6901][RFC6901] is now fully supported, including trailing "-" semantics for arrays (for `Set` operations). +* Default behavior: JSON name detection in go `struct`s + - Unlike go standard marshaling, untagged fields do not default to the go field name and are ignored. + - anonymous fields are not traversed if untagged + - the above limitations may be overcome by calling `UseGoNameProvider()` at initialization time. + - alternatively, users may inject the desired custom behavior for naming fields as an option. ## Other documentation * [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines](.github/CONTRIBUTING.md) -* [Maintainers documentation](docs/MAINTAINERS.md) -* [Code style](docs/STYLE.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] ## Cutting a new release @@ -142,11 +159,8 @@ Maintainers can cut a new release by either: [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/jsonpointer [godoc-url]: http://pkg.go.dev/github.com/go-openapi/jsonpointer -[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png -[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM -[slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue -[discord-url]: https://discord.gg/twZ9BwT3 +[discord-url]: https://discord.gg/FfnFYaC3k5 [license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg @@ -156,3 +170,8 @@ Maintainers can cut a new release by either: [goversion-url]: https://github.com/go-openapi/jsonpointer/blob/master/go.mod [top-badge]: https://img.shields.io/github/languages/top/go-openapi/jsonpointer [commits-badge]: https://img.shields.io/github/commits-since/go-openapi/jsonpointer/latest +[RFC6901]: https://www.rfc-editor.org/rfc/rfc6901 + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/jsonpointer/errors.go b/vendor/github.com/go-openapi/jsonpointer/errors.go index 8c50dde8bcf..2ae6e3cfb3e 100644 --- a/vendor/github.com/go-openapi/jsonpointer/errors.go +++ b/vendor/github.com/go-openapi/jsonpointer/errors.go @@ -16,12 +16,25 @@ const ( ErrPointer pointerError = "JSON pointer error" // ErrInvalidStart states that a JSON pointer must start with a separator ("/"). - ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator + ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator + `"` // ErrUnsupportedValueType indicates that a value of the wrong type is being set. ErrUnsupportedValueType pointerError = "only structs, pointers, maps and slices are supported for setting values" + + // ErrDashToken indicates use of the RFC 6901 "-" reference token in a context where it cannot be + // resolved. + // + // Per RFC 6901 §4 the "-" token refers to the (nonexistent) element after the last array element. + // It may only be used as the terminal token of a [Pointer.Set] against a slice, where it means + // "append". + // + // Any other use (get, offset, intermediate traversal, non-slice target) is an error condition that + // wraps this sentinel. + ErrDashToken pointerError = `the "-" array token cannot be resolved here` //nolint:gosec // G101 false positive: this is a JSON Pointer reference token, not a credential. ) +const dashToken = "-" + func errNoKey(key string) error { return fmt.Errorf("object has no key %q: %w", key, ErrPointer) } @@ -33,3 +46,15 @@ func errOutOfBounds(length, idx int) error { func errInvalidReference(token string) error { return fmt.Errorf("invalid token reference %q: %w", token, ErrPointer) } + +func errDashOnGet() error { + return fmt.Errorf("cannot resolve %q token on get: %w: %w", dashToken, ErrDashToken, ErrPointer) +} + +func errDashIntermediate() error { + return fmt.Errorf("the %q token may only appear as the terminal token of a pointer: %w: %w", dashToken, ErrDashToken, ErrPointer) +} + +func errDashOnOffset() error { + return fmt.Errorf("cannot compute offset for %q token (nonexistent element): %w: %w", dashToken, ErrDashToken, ErrPointer) +} diff --git a/vendor/github.com/go-openapi/jsonpointer/ifaces.go b/vendor/github.com/go-openapi/jsonpointer/ifaces.go new file mode 100644 index 00000000000..31359c48fad --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/ifaces.go @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonpointer + +import "reflect" + +// JSONPointable is an interface for structs to implement, when they need to customize the json +// pointer process or want to avoid the use of reflection. +type JSONPointable interface { + // JSONLookup returns a value pointed at this (unescaped) key. + JSONLookup(key string) (any, error) +} + +// JSONSetable is an interface for structs to implement, when they need to customize the json +// pointer process or want to avoid the use of reflection. +// +// # Handling of the RFC 6901 "-" token +// +// When a type implementing JSONSetable is the terminal parent of a [Pointer.Set] call, the library +// passes the raw reference token to JSONSet without interpretation. +// +// In particular, the RFC 6901 "-" token (which conventionally means "append" for arrays, per RFC +// 6902) is forwarded verbatim as the key argument. +// +// Implementations that model an array-like container are expected to give "-" the append semantics; +// implementations that do not should return an error wrapping [ErrDashToken] (or [ErrPointer]) for +// clarity. +// +// Implementations are responsible for any in-place mutation: the library does not attempt to rebind +// the result of JSONSet into a parent container. +type JSONSetable interface { + // JSONSet sets the value pointed at the (unescaped) key. + // + // The key may be the RFC 6901 "-" token when the pointer targets a slice-like member; see the + // interface documentation for details. + JSONSet(key string, value any) error +} + +// NameProvider knows how to resolve go struct fields into json names. +// +// The default provider is brought by +// [github.com/go-openapi/jsonpointer/jsonname.DefaultJSONNameProvider]. +type NameProvider interface { + // GetGoName gets the go name for a json property name + GetGoName(subject any, name string) (string, bool) + + // GetGoNameForType gets the go name for a given type for a json property name + GetGoNameForType(tpe reflect.Type, name string) (string, bool) +} diff --git a/vendor/github.com/go-openapi/swag/jsonname/doc.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/doc.go similarity index 100% rename from vendor/github.com/go-openapi/swag/jsonname/doc.go rename to vendor/github.com/go-openapi/jsonpointer/jsonname/doc.go diff --git a/vendor/github.com/go-openapi/swag/jsonname/go_name_provider.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/go_name_provider.go similarity index 88% rename from vendor/github.com/go-openapi/swag/jsonname/go_name_provider.go rename to vendor/github.com/go-openapi/jsonpointer/jsonname/go_name_provider.go index adc4426873c..5eec18fbfd0 100644 --- a/vendor/github.com/go-openapi/swag/jsonname/go_name_provider.go +++ b/vendor/github.com/go-openapi/jsonpointer/jsonname/go_name_provider.go @@ -11,11 +11,11 @@ import ( var _ providerIface = (*GoNameProvider)(nil) -// GoNameProvider resolves json property names to go struct field names following -// the same rules as the standard library's [encoding/json] package. +// GoNameProvider resolves json property names to go struct field names following the same rules as +// the standard library's [encoding/json] package. // -// Contrary to [NameProvider], it considers exported fields without a json tag, -// and promotes fields from anonymous embedded struct types. +// Contrary to [NameProvider], it considers exported fields without a json tag, and promotes fields +// from anonymous embedded struct types. // // Rules (aligned with encoding/json): // @@ -104,9 +104,9 @@ func (n *GoNameProvider) nameIndexFor(tpe reflect.Type) nameIndex { return names } -// fieldEntry captures a candidate field discovered while walking a struct -// along with the indirection path from the root type (used to resolve conflicts -// by depth in the same way encoding/json does). +// fieldEntry captures a candidate field discovered while walking a struct along with the +// indirection path from the root type (used to resolve conflicts by depth in the same way +// encoding/json does). type fieldEntry struct { goName string jsonName string @@ -129,6 +129,8 @@ func buildGoNameIndex(tpe reflect.Type) nameIndex { // collectGoFields walks tpe breadth-first along anonymous struct fields, // reproducing the field selection performed by encoding/json.typeFields. +// +//nolint:gocognit // everything is inlined to help the compiler determine what escapes and what doesn't func collectGoFields(tpe reflect.Type) []fieldEntry { if tpe.Kind() != reflect.Struct { return nil @@ -157,12 +159,12 @@ func collectGoFields(tpe reflect.Type) []fieldEntry { } for _, q := range current { - for i := 0; i < q.typ.NumField(); i++ { + for i := range q.typ.NumField() { sf := q.typ.Field(i) if sf.Anonymous { ft := sf.Type - if ft.Kind() == reflect.Ptr { + if ft.Kind() == reflect.Pointer { ft = ft.Elem() } if !sf.IsExported() && ft.Kind() != reflect.Struct { @@ -180,7 +182,7 @@ func collectGoFields(tpe reflect.Type) []fieldEntry { tagged := jsonName != "" ft := sf.Type - if ft.Kind() == reflect.Ptr { + if ft.Kind() == reflect.Pointer { ft = ft.Elem() } @@ -221,9 +223,9 @@ func collectGoFields(tpe reflect.Type) []fieldEntry { return dominantFields(candidates) } -// dominantFields applies the Go encoding/json conflict resolution rules: -// at each JSON name, the shallowest field wins; at equal depth, a uniquely -// tagged candidate wins; otherwise all candidates for that name are dropped. +// dominantFields applies the Go encoding/json conflict resolution rules: at each JSON name, the +// shallowest field wins; at equal depth, a uniquely tagged candidate wins; otherwise all candidates +// for that name are dropped. func dominantFields(candidates []fieldEntry) []fieldEntry { byName := make(map[string][]fieldEntry, len(candidates)) for _, c := range candidates { @@ -272,14 +274,14 @@ func dominantFields(candidates []fieldEntry) []fieldEntry { return out } -// parseJSONTag returns the name component of a json struct tag and whether -// it carried any non-name option (kept for future-proofing, e.g. "omitempty"). +// parseJSONTag returns the name component of a json struct tag and whether it carried any non-name +// option (kept for future-proofing, e.g. "omitempty"). func parseJSONTag(tag string) (string, string) { if tag == "" { return "", "" } - if idx := strings.IndexByte(tag, ','); idx >= 0 { - return tag[:idx], tag[idx+1:] + if before, after, ok := strings.Cut(tag, ","); ok { + return before, after } return tag, "" diff --git a/vendor/github.com/go-openapi/swag/jsonname/ifaces.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/ifaces.go similarity index 77% rename from vendor/github.com/go-openapi/swag/jsonname/ifaces.go rename to vendor/github.com/go-openapi/jsonpointer/jsonname/ifaces.go index 812ace5639f..64871f0d276 100644 --- a/vendor/github.com/go-openapi/swag/jsonname/ifaces.go +++ b/vendor/github.com/go-openapi/jsonpointer/jsonname/ifaces.go @@ -5,9 +5,11 @@ package jsonname import "reflect" -// providerIface is an unexported compile-time contract that every name provider -// in this package is expected to satisfy. -// It mirrors the interface declared by the main consumer of this module: [github.com/go-openapi/jsonpointer.NameProvider]. +// providerIface is an unexported compile-time contract that every name provider in this package is +// expected to satisfy. +// +// It mirrors the interface declared by the main consumer of this module: +// [github.com/go-openapi/jsonpointer.NameProvider]. type providerIface interface { GetGoName(subject any, name string) (string, bool) GetGoNameForType(tpe reflect.Type, name string) (string, bool) diff --git a/vendor/github.com/go-openapi/swag/jsonname/name_provider.go b/vendor/github.com/go-openapi/jsonpointer/jsonname/name_provider.go similarity index 83% rename from vendor/github.com/go-openapi/swag/jsonname/name_provider.go rename to vendor/github.com/go-openapi/jsonpointer/jsonname/name_provider.go index 9f5da7a0165..1bec2406b52 100644 --- a/vendor/github.com/go-openapi/swag/jsonname/name_provider.go +++ b/vendor/github.com/go-openapi/jsonpointer/jsonname/name_provider.go @@ -10,12 +10,12 @@ import ( ) // DefaultJSONNameProvider is the default cache for types. -var DefaultJSONNameProvider = NewNameProvider() +var DefaultJSONNameProvider = NewNameProvider() //nolint:gochecknoglobals // default settings, for backward compatible package-level settings var _ providerIface = (*NameProvider)(nil) -// NameProvider represents an object capable of translating from go property names -// to json property names. +// NameProvider represents an object capable of translating from go property names to json property +// names. // // This type is thread-safe. // @@ -30,7 +30,7 @@ type nameIndex struct { goNames map[string]string } -// NewNameProvider creates a new name provider +// NewNameProvider creates a new name provider. func NewNameProvider() *NameProvider { return &NameProvider{ lock: &sync.Mutex{}, @@ -39,7 +39,7 @@ func NewNameProvider() *NameProvider { } func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) { - for i := 0; i < tpe.NumField(); i++ { + for i := range tpe.NumField() { targetDes := tpe.Field(i) if targetDes.PkgPath != "" { // unexported @@ -73,14 +73,14 @@ func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) { } func newNameIndex(tpe reflect.Type) nameIndex { - var idx = make(map[string]string, tpe.NumField()) - var reverseIdx = make(map[string]string, tpe.NumField()) + idx := make(map[string]string, tpe.NumField()) + reverseIdx := make(map[string]string, tpe.NumField()) buildnameIndex(tpe, idx, reverseIdx) return nameIndex{jsonNames: idx, goNames: reverseIdx} } -// GetJSONNames gets all the json property names for a type +// GetJSONNames gets all the json property names for a type. func (n *NameProvider) GetJSONNames(subject any) []string { n.lock.Lock() defer n.lock.Unlock() @@ -97,13 +97,13 @@ func (n *NameProvider) GetJSONNames(subject any) []string { return res } -// GetJSONName gets the json name for a go property name +// GetJSONName gets the json name for a go property name. func (n *NameProvider) GetJSONName(subject any, name string) (string, bool) { tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() return n.GetJSONNameForType(tpe, name) } -// GetJSONNameForType gets the json name for a go property name on a given type +// GetJSONNameForType gets the json name for a go property name on a given type. func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) { n.lock.Lock() defer n.lock.Unlock() @@ -115,13 +115,13 @@ func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string return nme, ok } -// GetGoName gets the go name for a json property name +// GetGoName gets the go name for a json property name. func (n *NameProvider) GetGoName(subject any, name string) (string, bool) { tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() return n.GetGoNameForType(tpe, name) } -// GetGoNameForType gets the go name for a given type for a json property name +// GetGoNameForType gets the go name for a given type for a json property name. func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) { n.lock.Lock() defer n.lock.Unlock() diff --git a/vendor/github.com/go-openapi/jsonpointer/options.go b/vendor/github.com/go-openapi/jsonpointer/options.go new file mode 100644 index 00000000000..223c1e5ff0e --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/options.go @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonpointer + +import ( + "sync" + + "github.com/go-openapi/jsonpointer/jsonname" +) + +// Option to tune the behavior of a JSON [Pointer]. +type Option func(*options) + +var ( + //nolint:gochecknoglobals // package level defaults are provided as a convenient, backward-compatible way to adopt options. + defaultOptions = options{ + provider: jsonname.DefaultJSONNameProvider, + } + //nolint:gochecknoglobals // guards defaultOptions against concurrent SetDefaultNameProvider / read races (testing) + defaultOptionsMu sync.RWMutex +) + +// SetDefaultNameProvider sets the [NameProvider] as a package-level default. +// +// By default, the default provider is [jsonname.DefaultJSONNameProvider]. +// +// It is safe to call concurrently with [Pointer.Get], [Pointer.Set], [GetForToken] and +// [SetForToken]. +// The typical usage is to call it once at initialization time. +// +// A nil provider is ignored. +func SetDefaultNameProvider(provider NameProvider) { + if provider == nil { + return + } + + defaultOptionsMu.Lock() + defer defaultOptionsMu.Unlock() + + defaultOptions.provider = provider +} + +// UseGoNameProvider sets the [NameProvider] as a package-level default to the alternative provider +// [jsonname.GoNameProvider], that covers a few areas not supported by the default name provider. +// +// This implementation supports untagged exported fields and embedded types in go struct. +// It follows strictly the behavior of the JSON standard library regarding field naming conventions. +// +// It is safe to call concurrently with [Pointer.Get], [Pointer.Set], [GetForToken] and +// [SetForToken]. +// The typical usage is to call it once at initialization time. +func UseGoNameProvider() { + SetDefaultNameProvider(jsonname.NewGoNameProvider()) +} + +// DefaultNameProvider returns the current package-level [NameProvider]. +func DefaultNameProvider() NameProvider { //nolint:ireturn // returning the interface is the point — callers pick their own implementation. + defaultOptionsMu.RLock() + defer defaultOptionsMu.RUnlock() + + return defaultOptions.provider +} + +// WithNameProvider injects a custom [NameProvider] to resolve json names from go struct types. +func WithNameProvider(provider NameProvider) Option { + return func(o *options) { + o.provider = provider + } +} + +type options struct { + provider NameProvider +} + +func optionsWithDefaults(opts []Option) options { + var o options + o.provider = DefaultNameProvider() + + for _, apply := range opts { + apply(&o) + } + + return o +} diff --git a/vendor/github.com/go-openapi/jsonpointer/pointer.go b/vendor/github.com/go-openapi/jsonpointer/pointer.go index 7df49af3b96..05fc863ee60 100644 --- a/vendor/github.com/go-openapi/jsonpointer/pointer.go +++ b/vendor/github.com/go-openapi/jsonpointer/pointer.go @@ -11,8 +11,6 @@ import ( "reflect" "strconv" "strings" - - "github.com/go-openapi/swag/jsonname" ) const ( @@ -20,20 +18,6 @@ const ( pointerSeparator = `/` ) -// JSONPointable is an interface for structs to implement, -// when they need to customize the json pointer process or want to avoid the use of reflection. -type JSONPointable interface { - // JSONLookup returns a value pointed at this (unescaped) key. - JSONLookup(key string) (any, error) -} - -// JSONSetable is an interface for structs to implement, -// when they need to customize the json pointer process or want to avoid the use of reflection. -type JSONSetable interface { - // JSONSet sets the value pointed at the (unescaped) key. - JSONSet(key string, value any) error -} - // Pointer is a representation of a json pointer. // // Use [Pointer.Get] to retrieve a value or [Pointer.Set] to set a value. @@ -41,7 +25,7 @@ type JSONSetable interface { // It works with any go type interpreted as a JSON document, which means: // // - if a type implements [JSONPointable], its [JSONPointable.JSONLookup] method is used to resolve [Pointer.Get] -// - if a type implements [JSONSetable], its [JSONPointable.JSONSet] method is used to resolve [Pointer.Set] +// - if a type implements [JSONSetable], its [JSONSetable.JSONSet] method is used to resolve [Pointer.Set] // - a go map[K]V is interpreted as an object, with type K assignable to a string // - a go slice []T is interpreted as an array // - a go struct is interpreted as an object, with exported fields interpreted as keys @@ -50,7 +34,8 @@ type JSONSetable interface { // // For struct s resolved by reflection, key mappings honor the conventional struct tag `json`. // -// Fields that do not specify a `json` tag, or specify an empty one, or are tagged as `json:"-"` are ignored. +// Fields that do not specify a `json` tag, or specify an empty one, or are tagged as `json:"-"` are +// ignored. // // # Limitations // @@ -71,16 +56,36 @@ func New(jsonPointerString string) (Pointer, error) { // Get uses the pointer to retrieve a value from a JSON document. // // It returns the value with its type as a [reflect.Kind] or an error. -func (p *Pointer) Get(document any) (any, reflect.Kind, error) { - return p.get(document, jsonname.DefaultJSONNameProvider) +func (p *Pointer) Get(document any, opts ...Option) (any, reflect.Kind, error) { + o := optionsWithDefaults(opts) + + return p.get(document, o.provider) } -// Set uses the pointer to set a value from a data type -// that represent a JSON document. +// Set uses the pointer to set a value from a data type that represent a JSON document. +// +// # Mutation contract // -// It returns the updated document. -func (p *Pointer) Set(document any, value any) (any, error) { - return document, p.set(document, value, jsonname.DefaultJSONNameProvider) +// Set mutates the provided document in place whenever Go's type system allows it: when document is +// a map, a pointer, or when the targeted value is reached through an addressable ancestor (e.g. a +// struct field traversed via a pointer, a slice element). +// +// Callers that rely on this in-place behavior may continue to ignore the returned document. +// +// The returned document is only load-bearing when Set cannot mutate in place. +// +// This happens in one specific case: appending to a top-level slice passed by value (e.g. document +// of type []T rather than *[]T) via the RFC 6901 "-" terminal token. reflect.Append produces a new +// slice header that the library cannot rebind into the caller's variable; the updated document is +// returned instead. +// +// Pass *[]T if you want in-place rebind for that case as well. +// +// See [ErrDashToken] for the semantics of the "-" token. +func (p *Pointer) Set(document any, value any, opts ...Option) (any, error) { + o := optionsWithDefaults(opts) + + return p.set(document, value, o.provider) } // DecodedTokens returns the decoded (unescaped) tokens of this JSON pointer. @@ -109,6 +114,46 @@ func (p *Pointer) String() string { return pointerSeparator + strings.Join(p.referenceTokens, pointerSeparator) } +// Offset returns the byte offset, in the raw JSON text of document, of the location referenced by +// this pointer's terminal token. +// +// Unlike [Pointer.Get] and [Pointer.Set], which operate on a decoded Go value, Offset operates +// directly on the textual JSON source. +// +// It drives an [encoding/json.Decoder] over the string and stops at the terminal token, returning +// the position at which the decoder was about to read that token. +// +// It is primarily intended for tooling that needs to map a pointer back to a region of the original +// source: reporting line/column for validation or parse diagnostics, extracting a sub-document by +// slicing the raw bytes, or highlighting the referenced span in an editor. +// +// # Offset semantics +// +// The meaning of the returned offset depends on whether the terminal token addresses an object +// property or an array element: +// +// - Object property: the offset points to the first byte of the key (its +// opening quote character), not to the associated value. For example, +// pointer "/foo/bar" against {"foo": {"bar": 21}} returns 9, the index of +// the opening quote of "bar". +// - Array element: the offset points to the first byte of the value at that +// index. For example, pointer "/0/1" against [[1,2], [3,4]] returns 4, +// the index of the digit 2. +// +// # Errors +// +// Offset returns an error in any of these cases: +// +// - document is not syntactically valid JSON; +// - the structure of document does not match the pointer (e.g. traversing +// into a scalar, or a token that is neither a valid key nor a valid +// numeric index); +// - a referenced key or index does not exist in document; +// - the pointer's terminal token is the RFC 6901 "-" array token, which +// designates a nonexistent element and therefore has no offset in the +// source. The returned error wraps [ErrDashToken]. +// +// All errors wrap [ErrPointer]. func (p *Pointer) Offset(document string) (int64, error) { dec := json.NewDecoder(strings.NewReader(document)) var offset int64 @@ -137,7 +182,34 @@ func (p *Pointer) Offset(document string) (int64, error) { return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) } } - return offset, nil + return skipJSONSeparator(document, offset), nil +} + +// skipJSONSeparator advances offset past trailing JSON whitespace and at most one value separator +// (comma) in document, so the result points at the first byte of the next JSON token. +// +// The streaming decoder's InputOffset sits right after the most recently consumed token, which +// between values is the comma (or whitespace) — not the following token. +// +// Normalizing here keeps Offset's contract uniform: for both object keys and array elements, and +// regardless of position within the parent container, the returned offset always points at the +// first byte of the addressed token. +func skipJSONSeparator(document string, offset int64) int64 { + n := int64(len(document)) + for offset < n && isJSONWhitespace(document[offset]) { + offset++ + } + if offset < n && document[offset] == ',' { + offset++ + } + for offset < n && isJSONWhitespace(document[offset]) { + offset++ + } + return offset +} + +func isJSONWhitespace(c byte) bool { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' } // "Constructor", parses the given string JSON pointer. @@ -157,9 +229,9 @@ func (p *Pointer) parse(jsonPointerString string) error { return nil } -func (p *Pointer) get(node any, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) { +func (p *Pointer) get(node any, nameProvider NameProvider) (any, reflect.Kind, error) { if nameProvider == nil { - nameProvider = jsonname.DefaultJSONNameProvider + nameProvider = defaultOptions.provider } kind := reflect.Invalid @@ -185,50 +257,128 @@ func (p *Pointer) get(node any, nameProvider *jsonname.NameProvider) (any, refle return node, kind, nil } -func (p *Pointer) set(node, data any, nameProvider *jsonname.NameProvider) error { +func (p *Pointer) set(node, data any, nameProvider NameProvider) (any, error) { knd := reflect.ValueOf(node).Kind() if knd != reflect.Pointer && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array { - return errors.Join( + return node, errors.Join( fmt.Errorf("unexpected type: %T", node), //nolint:err113 // err wrapping is carried out by errors.Join, not fmt.Errorf. ErrUnsupportedValueType, ErrPointer, ) } - l := len(p.referenceTokens) - // full document when empty - if l == 0 { - return nil + if len(p.referenceTokens) == 0 { + return node, nil } if nameProvider == nil { - nameProvider = jsonname.DefaultJSONNameProvider + nameProvider = defaultOptions.provider } - var decodedToken string - lastIndex := l - 1 + return p.setAt(node, p.referenceTokens, data, nameProvider) +} - if lastIndex > 0 { // skip if we only have one token in pointer - for _, token := range p.referenceTokens[:lastIndex] { - decodedToken = Unescape(token) - next, err := p.resolveNodeForToken(node, decodedToken, nameProvider) - if err != nil { - return err - } +// setAt recursively walks the token list, setting the data at the terminal token and rebinding any +// new child reference (e.g. a slice header returned by an "-" append) into its parent on the way +// back up. +// +// Returning the (possibly new) node at each level is what makes append work at any depth without +// requiring the caller to pass a pointer to the containing slice: the new slice header propagates +// up and each parent rebinds it via the appropriate kind-specific setter. +func (p *Pointer) setAt(node any, tokens []string, data any, nameProvider NameProvider) (any, error) { + decodedToken := Unescape(tokens[0]) + + if len(tokens) == 1 { + return setSingleImpl(node, data, decodedToken, nameProvider) + } - node = next - } + child, err := p.resolveNodeForToken(node, decodedToken, nameProvider) + if err != nil { + return node, err } - // last token - decodedToken = Unescape(p.referenceTokens[lastIndex]) + newChild, err := p.setAt(child, tokens[1:], data, nameProvider) + if err != nil { + return node, err + } - return setSingleImpl(node, data, decodedToken, nameProvider) + return rebindChild(node, decodedToken, newChild, nameProvider) } -func (p *Pointer) resolveNodeForToken(node any, decodedToken string, nameProvider *jsonname.NameProvider) (next any, err error) { +// rebindChild writes newChild back into node at decodedToken. +// +// For cases where the child was already mutated in place (pointer aliasing, addressable slice +// elements) the rebind is a safe no-op. +// +// For cases where the child was returned by value (map entries holding a slice, slices reached +// through a non-addressable ancestor), the rebind propagates the new value into the parent. +// +// Parents implementing [JSONPointable] are left alone: they took ownership of the child via +// JSONLookup and did not opt into a JSONSet-based rebind on intermediate tokens. +func rebindChild(node any, decodedToken string, newChild any, nameProvider NameProvider) (any, error) { + if _, ok := node.(JSONPointable); ok { + return node, nil + } + + rValue := reflect.Indirect(reflect.ValueOf(node)) + + switch rValue.Kind() { + case reflect.Struct: + nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) + if !ok { + return node, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) + } + fld := rValue.FieldByName(nm) + if !fld.CanSet() { + return node, nil + } + assignReflectValue(fld, newChild) + return node, nil + + case reflect.Map: + rValue.SetMapIndex(reflect.ValueOf(decodedToken), reflect.ValueOf(newChild)) + return node, nil + + case reflect.Slice: + if decodedToken == dashToken { + return node, errDashIntermediate() + } + idx, err := strconv.Atoi(decodedToken) + if err != nil { + return node, errors.Join(err, ErrPointer) + } + elem := rValue.Index(idx) + if !elem.CanSet() { + return node, nil + } + assignReflectValue(elem, newChild) + return node, nil + + default: + return node, errInvalidReference(decodedToken) + } +} + +// assignReflectValue assigns src into dst, unwrapping a pointer when dst expects the pointee type. +// +// This tolerates the pointer-wrapping performed by [typeFromValue] for addressable fields. +func assignReflectValue(dst reflect.Value, src any) { + nv := reflect.ValueOf(src) + if !nv.IsValid() { + return + } + if nv.Type().AssignableTo(dst.Type()) { + dst.Set(nv) + return + } + if nv.Kind() == reflect.Pointer && nv.Elem().Type().AssignableTo(dst.Type()) { + dst.Set(nv.Elem()) + } +} + +func (p *Pointer) resolveNodeForToken(node any, decodedToken string, nameProvider NameProvider) (next any, err error) { // check for nil during traversal if isNil(node) { return nil, fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer) @@ -272,6 +422,9 @@ func (p *Pointer) resolveNodeForToken(node any, decodedToken string, nameProvide return typeFromValue(mv), nil case reflect.Slice: + if decodedToken == dashToken { + return nil, errDashIntermediate() + } tokenIndex, err := strconv.Atoi(decodedToken) if err != nil { return nil, errors.Join(err, ErrPointer) @@ -312,16 +465,23 @@ func typeFromValue(v reflect.Value) any { } // GetForToken gets a value for a json pointer token 1 level deep. -func GetForToken(document any, decodedToken string) (any, reflect.Kind, error) { - return getSingleImpl(document, decodedToken, jsonname.DefaultJSONNameProvider) +func GetForToken(document any, decodedToken string, opts ...Option) (any, reflect.Kind, error) { + o := optionsWithDefaults(opts) + + return getSingleImpl(document, decodedToken, o.provider) } // SetForToken sets a value for a json pointer token 1 level deep. -func SetForToken(document any, decodedToken string, value any) (any, error) { - return document, setSingleImpl(document, value, decodedToken, jsonname.DefaultJSONNameProvider) +// +// See [Pointer.Set] for the mutation contract, in particular the handling of the RFC 6901 "-" token +// on slices. +func SetForToken(document any, decodedToken string, value any, opts ...Option) (any, error) { + o := optionsWithDefaults(opts) + + return setSingleImpl(document, value, decodedToken, o.provider) } -func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) { +func getSingleImpl(node any, decodedToken string, nameProvider NameProvider) (any, reflect.Kind, error) { rValue := reflect.Indirect(reflect.ValueOf(node)) kind := rValue.Kind() if isNil(node) { @@ -361,6 +521,9 @@ func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NamePro return nil, kind, errNoKey(decodedToken) case reflect.Slice: + if decodedToken == dashToken { + return nil, kind, errDashOnGet() + } tokenIndex, err := strconv.Atoi(decodedToken) if err != nil { return nil, kind, errors.Join(err, ErrPointer) @@ -378,14 +541,14 @@ func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NamePro } } -func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.NameProvider) error { +func setSingleImpl(node, data any, decodedToken string, nameProvider NameProvider) (any, error) { // check for nil to prevent panic when calling rValue.Type() if isNil(node) { - return fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer) + return node, fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer) } if ns, ok := node.(JSONSetable); ok { - return ns.JSONSet(decodedToken, data) + return node, ns.JSONSet(decodedToken, data) } rValue := reflect.Indirect(reflect.ValueOf(node)) @@ -394,12 +557,12 @@ func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.N case reflect.Struct: nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) if !ok { - return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) + return node, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) } fld := rValue.FieldByName(nm) if !fld.CanSet() { - return fmt.Errorf("can't set struct field %s to %v: %w", nm, data, ErrPointer) + return node, fmt.Errorf("can't set struct field %s to %v: %w", nm, data, ErrPointer) } value := reflect.ValueOf(data) @@ -407,33 +570,51 @@ func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.N assignedType := fld.Type() if !valueType.AssignableTo(assignedType) { - return fmt.Errorf("can't set value with type %T to field %s with type %v: %w", data, nm, assignedType, ErrPointer) + return node, fmt.Errorf("can't set value with type %T to field %s with type %v: %w", data, nm, assignedType, ErrPointer) } fld.Set(value) - return nil + return node, nil case reflect.Map: kv := reflect.ValueOf(decodedToken) rValue.SetMapIndex(kv, reflect.ValueOf(data)) - return nil + return node, nil case reflect.Slice: + if decodedToken == dashToken { + // RFC 6901 §4 / RFC 6902 append semantics: terminal "-" appends the value to the slice. + // + // We rebind in place when the slice is reachable via an addressable ancestor; otherwise we + // return the new slice header for the parent (or the public Set) to rebind. + value := reflect.ValueOf(data) + elemType := rValue.Type().Elem() + if !value.Type().AssignableTo(elemType) { + return node, fmt.Errorf("can't append value of type %T to slice of %v: %w", data, elemType, ErrPointer) + } + newSlice := reflect.Append(rValue, value) + if rValue.CanSet() { + rValue.Set(newSlice) + return node, nil + } + return newSlice.Interface(), nil + } + tokenIndex, err := strconv.Atoi(decodedToken) if err != nil { - return errors.Join(err, ErrPointer) + return node, errors.Join(err, ErrPointer) } sLength := rValue.Len() if tokenIndex < 0 || tokenIndex >= sLength { - return errOutOfBounds(sLength, tokenIndex) + return node, errOutOfBounds(sLength, tokenIndex) } elem := rValue.Index(tokenIndex) if !elem.CanSet() { - return fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer) + return node, fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer) } value := reflect.ValueOf(data) @@ -441,15 +622,15 @@ func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.N assignedType := elem.Type() if !valueType.AssignableTo(assignedType) { - return fmt.Errorf("can't set value with type %T to slice element %d with type %v: %w", data, tokenIndex, assignedType, ErrPointer) + return node, fmt.Errorf("can't set value with type %T to slice element %d with type %v: %w", data, tokenIndex, assignedType, ErrPointer) } elem.Set(value) - return nil + return node, nil default: - return errInvalidReference(decodedToken) + return node, errInvalidReference(decodedToken) } } @@ -460,24 +641,27 @@ func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) { if err != nil { return 0, err } - switch tk := tk.(type) { - case json.Delim: - switch tk { - case '{': - if err = drainSingle(dec); err != nil { - return 0, err - } - case '[': + key, ok := tk.(string) + if !ok { + return 0, fmt.Errorf("invalid key token %#v: %w", tk, ErrPointer) + } + if key == decodedToken { + return offset, nil + } + + // Consume the associated value. + // Scalars are fully read by a single Token() call; composite values must be drained. + tk, err = dec.Token() + if err != nil { + return 0, err + } + if delim, isDelim := tk.(json.Delim); isDelim { + switch delim { + case '{', '[': if err = drainSingle(dec); err != nil { return 0, err } } - case string: - if tk == decodedToken { - return offset, nil - } - default: - return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) } } @@ -485,6 +669,9 @@ func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) { } func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) { + if decodedToken == dashToken { + return 0, errDashOnOffset() + } idx, err := strconv.Atoi(decodedToken) if err != nil { return 0, fmt.Errorf("token reference %q is not a number: %w: %w", decodedToken, err, ErrPointer) @@ -548,10 +735,7 @@ func drainSingle(dec *json.Decoder) error { return nil } -// JSON pointer encoding: -// ~0 => ~ -// ~1 => / -// ... and vice versa +// JSON pointer encoding: ~0 => ~ ~1 => / ... and vice versa. const ( encRefTok0 = `~0` diff --git a/vendor/github.com/go-openapi/jsonreference/.gitignore b/vendor/github.com/go-openapi/jsonreference/.gitignore index 885dc27ab0b..d8f4186fe59 100644 --- a/vendor/github.com/go-openapi/jsonreference/.gitignore +++ b/vendor/github.com/go-openapi/jsonreference/.gitignore @@ -3,4 +3,3 @@ .idea .env .mcp.json -.claude/ diff --git a/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md index 7faeb83a77d..d20737c946d 100644 --- a/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md @@ -4,18 +4,18 @@ | Total Contributors | Total Contributions | | --- | --- | -| 9 | 73 | +| 9 | 83 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | -| @fredbi | 36 | https://github.com/go-openapi/jsonreference/commits?author=fredbi | -| @casualjim | 25 | https://github.com/go-openapi/jsonreference/commits?author=casualjim | -| @youyuanwu | 5 | https://github.com/go-openapi/jsonreference/commits?author=youyuanwu | -| @olivierlemasle | 2 | https://github.com/go-openapi/jsonreference/commits?author=olivierlemasle | -| @apelisse | 1 | https://github.com/go-openapi/jsonreference/commits?author=apelisse | -| @gbjk | 1 | https://github.com/go-openapi/jsonreference/commits?author=gbjk | -| @honza | 1 | https://github.com/go-openapi/jsonreference/commits?author=honza | -| @Neo2308 | 1 | https://github.com/go-openapi/jsonreference/commits?author=Neo2308 | -| @erraggy | 1 | https://github.com/go-openapi/jsonreference/commits?author=erraggy | +| @fredbi | 46 | | +| @casualjim | 25 | | +| @youyuanwu | 5 | | +| @olivierlemasle | 2 | | +| @apelisse | 1 | | +| @gbjk | 1 | | +| @honza | 1 | | +| @Neo2308 | 1 | | +| @erraggy | 1 | | - _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_ + _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/jsonreference/README.md b/vendor/github.com/go-openapi/jsonreference/README.md index adea1606197..fbd16cf8924 100644 --- a/vendor/github.com/go-openapi/jsonreference/README.md +++ b/vendor/github.com/go-openapi/jsonreference/README.md @@ -16,13 +16,8 @@ An implementation of JSON Reference for golang. ## Announcements -* **2025-12-19** : new community chat on discord - * a new discord community channel is available to be notified of changes and support users - * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** - -You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] - -Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] +* **2026-07-07** : landing v1.0.0 + * stable API pledge ## Status @@ -74,9 +69,9 @@ on top of which it has been built. ## Other documentation * [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines](.github/CONTRIBUTING.md) -* [Maintainers documentation](docs/MAINTAINERS.md) -* [Code style](docs/STYLE.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] ## Cutting a new release @@ -111,11 +106,8 @@ Maintainers can cut a new release by either: [doc-url]: https://goswagger.io/go-openapi [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/jsonreference [godoc-url]: http://pkg.go.dev/github.com/go-openapi/jsonreference -[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png -[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM -[slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue -[discord-url]: https://discord.gg/twZ9BwT3 +[discord-url]: https://discord.gg/FfnFYaC3k5 [license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg @@ -125,3 +117,7 @@ Maintainers can cut a new release by either: [goversion-url]: https://github.com/go-openapi/jsonreference/blob/master/go.mod [top-badge]: https://img.shields.io/github/languages/top/go-openapi/jsonreference [commits-badge]: https://img.shields.io/github/commits-since/go-openapi/jsonreference/latest + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/loads/.gitignore b/vendor/github.com/go-openapi/loads/.gitignore index d8f4186fe59..fbb78de2c34 100644 --- a/vendor/github.com/go-openapi/loads/.gitignore +++ b/vendor/github.com/go-openapi/loads/.gitignore @@ -3,3 +3,4 @@ .idea .env .mcp.json +.worktrees diff --git a/vendor/github.com/go-openapi/loads/.golangci.yml b/vendor/github.com/go-openapi/loads/.golangci.yml index 83968f3faeb..272b14e545d 100644 --- a/vendor/github.com/go-openapi/loads/.golangci.yml +++ b/vendor/github.com/go-openapi/loads/.golangci.yml @@ -7,6 +7,8 @@ linters: - gochecknoglobals # on this repo, it is hard to refactor without globals/inits and no breaking change - gochecknoinits - godox + - gomodguard + - gomodguard_v2 - exhaustruct - nlreturn - nonamedreturns diff --git a/vendor/github.com/go-openapi/loads/CONTRIBUTORS.md b/vendor/github.com/go-openapi/loads/CONTRIBUTORS.md index 36b836a3d5a..ff3fd35081f 100644 --- a/vendor/github.com/go-openapi/loads/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/loads/CONTRIBUTORS.md @@ -4,12 +4,12 @@ | Total Contributors | Total Contributions | | --- | --- | -| 14 | 123 | +| 14 | 136 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | +| @fredbi | 58 | | | @casualjim | 48 | | -| @fredbi | 45 | | | @youyuanwu | 6 | | | @vburenin | 4 | | | @keramix | 4 | | @@ -23,4 +23,4 @@ | @kreativka | 1 | | | @petrkotas | 1 | | - _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_ + _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/loads/README.md b/vendor/github.com/go-openapi/loads/README.md index d92e62a040d..293f79bb6a0 100644 --- a/vendor/github.com/go-openapi/loads/README.md +++ b/vendor/github.com/go-openapi/loads/README.md @@ -20,12 +20,9 @@ Supports JSON and YAML documents. * **2025-12-19** : new community chat on discord * a new discord community channel is available to be notified of changes and support users - * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] -Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] - ## Status API is stable. @@ -58,6 +55,41 @@ go get github.com/go-openapi/loads See also the provided [examples](https://pkg.go.dev/github.com/go-openapi/loads#pkg-examples). +## Security + +This library does not enforce a security policy of its own: it reads whatever the configured +loader is allowed to read. + +This is deliberate — like `go-openapi/swag/loading`, it is a base utility, +and sanitizing or containing untrusted input is the caller's responsibility, +just as sanitizing a file name before passing it to `os.ReadFile` is not that function's job. + +When a spec — its path or its `$ref` contents — may come from an untrusted source, confine +loading explicitly (e.g. `loading.WithRoot` for local files and a restricted +`loading.WithHTTPClient` for remote URLs, passed via `loads.WithLoadingOptions`). + +For the common case, the pre-baked `loads.SpecRestricted` / `loads.JSONSpecRestricted` loaders +bundle a trusted root with a network-restricted client (`loads.RestrictedHTTPClient`) and apply +the confinement to `$ref` resolution as well: + +```go +doc, err := loads.SpecRestricted(path, trustedRoot) +``` + +To harden the package-level default in one call — so even callers that rely on the global +loader (including cross-package `$ref` resolution via `spec.PathLoader`) are confined, with no +unconfined fallback left — use `loads.SetRestrictedLoaders` at startup: + +```go +loads.SetRestrictedLoaders(trustedRoot) +``` + +Note that `loads.AddLoader` only *prepends* to the default chain, leaving the unconfined loader +reachable; use `loads.SetLoaders` / `loads.SetRestrictedLoaders` to replace it. + +See the [Security section of the package documentation][security-doc] for the threat model and +runnable examples. For the project's vulnerability reporting policy, see [SECURITY.md](./SECURITY.md). + ## Change log See @@ -69,9 +101,9 @@ This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). ## Other documentation * [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines](.github/CONTRIBUTING.md) -* [Maintainers documentation](docs/MAINTAINERS.md) -* [Code style](docs/STYLE.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] ## Cutting a new release @@ -102,11 +134,8 @@ Maintainers can cut a new release by either: [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/loads [godoc-url]: http://pkg.go.dev/github.com/go-openapi/loads -[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png -[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM -[slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue -[discord-url]: https://discord.gg/twZ9BwT3 +[discord-url]: https://discord.gg/FfnFYaC3k5 [license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg @@ -116,3 +145,9 @@ Maintainers can cut a new release by either: [goversion-url]: https://github.com/go-openapi/loads/blob/master/go.mod [top-badge]: https://img.shields.io/github/languages/top/go-openapi/loads [commits-badge]: https://img.shields.io/github/commits-since/go-openapi/loads/latest + +[security-doc]: https://pkg.go.dev/github.com/go-openapi/loads#hdr-Security + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/loads/doc.go b/vendor/github.com/go-openapi/loads/doc.go index 67a5e2f8d95..0fafe4f4683 100644 --- a/vendor/github.com/go-openapi/loads/doc.go +++ b/vendor/github.com/go-openapi/loads/doc.go @@ -6,4 +6,72 @@ // It is used by other go-openapi packages to load and run analysis on local or remote spec documents. // // Loaders support JSON and YAML documents. +// +// # Security +// +// This package does not enforce a security policy of its own: like the underlying +// [github.com/go-openapi/swag/loading] utilities, it reads whatever the configured loader is +// allowed to read. +// +// When a spec — its path or its contents — may derive from untrusted input, the caller must confine loading explicitly. +// +// This is a deliberate design choice. +// Both this package and the [github.com/go-openapi/swag/loading] utilities are base building blocks: +// deciding which sources are legitimate, and containing access to them, +// requires application context that a general-purpose loader does not have. +// +// Just as sanitizing a file name before handing it to [os.ReadFile] is the caller's +// responsibility and not that function's, sanitizing and containing the path and references +// resolved here is the responsibility of the code that may feed them untrusted input. +// +// There are two distinct attack surfaces: +// +// - The path passed to [Spec], [JSONSpec], or [Embedded]. By default a local path is read +// with no confinement, so a caller-controlled path (including an absolute path or a +// "file:///etc/passwd" URI) may read any file the process can access. A remote path is +// fetched with [net/http.DefaultClient], which follows redirects and performs no +// destination filtering, so a caller-controlled URL may reach internal services or cloud +// metadata endpoints (server-side request forgery). +// +// - The contents of the spec, when references are resolved. [Document.Expanded] follows the +// "$ref" pointers found inside the document by calling the same loader recursively. A spec +// obtained even from a trusted path can therefore drive arbitrary local reads +// ("$ref": "file:///etc/passwd") or SSRF ("$ref": "http://169.254.169.254/...") through +// its own contents. This amplification is specific to reference resolution and does not +// exist in the raw loading utilities. +// +// Mitigation. Pass [github.com/go-openapi/swag/loading] options through [WithLoadingOptions]; +// they are attached to the document's loader and so apply both to the initial load and to +// every "$ref" resolved during expansion: +// +// - [github.com/go-openapi/swag/loading.WithRoot] confines local reads to a trusted +// directory, rejecting absolute paths, ".." traversal, and symlinks that escape it. Prefer +// it over a [github.com/go-openapi/swag/loading.WithFS] built from [os.DirFS], which does +// not block symlink escapes. +// +// - [github.com/go-openapi/swag/loading.WithHTTPClient] allows to supply a restricted HTTP client. +// Enforce the network policy at dial time (a [net.Dialer] Control hook), so it also covers +// redirects and DNS rebinding, which a URL-string allowlist cannot. See the example on +// [Spec]. +// +// Pre-baked loaders. When the opinionated defaults fit, [SpecRestricted], [JSONSpecRestricted] +// and [JSONDocRestricted] bundle a trusted root with a network-restricted client +// ([RestrictedHTTPClient]), and apply the confinement to "$ref" resolution as well — so the +// common case needs no manual wiring. To harden the global default in one call (so even callers +// that rely on the package-level loader are confined), use [SetRestrictedLoaders]. Reach for the +// options above when you need a custom policy; [IsForbiddenAddress] exposes the default network +// policy so you can reuse it as the base of your own HTTP client. +// +// Caveats: +// +// - The package-level default loader (also installed as [github.com/go-openapi/spec.PathLoader]) +// carries no loading options and is therefore unconfined. It is used as a fallback when +// expansion runs without a document loader, and by other go-openapi packages that resolve +// references on their own. [AddLoader] does not fix this — it only prepends, leaving the +// unconfined fallback reachable. Either build a confined loader per call, or replace the +// global default outright with [SetLoaders] / [SetRestrictedLoaders]. +// +// - A custom loader installed via [WithDocLoader] or [AddLoader] only honors these +// protections if its loading function actually applies the [github.com/go-openapi/swag/loading] +// options it is given. package loads diff --git a/vendor/github.com/go-openapi/loads/errors.go b/vendor/github.com/go-openapi/loads/errors.go index 14a8186b6ca..e94f038f947 100644 --- a/vendor/github.com/go-openapi/loads/errors.go +++ b/vendor/github.com/go-openapi/loads/errors.go @@ -15,4 +15,8 @@ const ( // ErrNoLoader indicates that no configured loader matched the input. ErrNoLoader loaderError = "no loader matched" + + // ErrForbiddenAddress is returned by [RestrictedHTTPClient] when a connection is attempted + // to a non-public address (loopback, private, link-local, or unspecified). + ErrForbiddenAddress loaderError = "blocked dial to a non-public address" ) diff --git a/vendor/github.com/go-openapi/loads/loaders.go b/vendor/github.com/go-openapi/loads/loaders.go index ac8adfe8b20..ba5c48b65f8 100644 --- a/vendor/github.com/go-openapi/loads/loaders.go +++ b/vendor/github.com/go-openapi/loads/loaders.go @@ -21,6 +21,15 @@ import ( var loaders *loader func init() { + loaders = defaultLoaders() + + // sets the global default loader for go-openapi/spec + spec.PathLoader = loaders.Load +} + +// defaultLoaders builds the built-in loader chain: a YAML matcher first, with a JSON loader as +// the catch-all fallback. +func defaultLoaders() *loader { jsonLoader := &loader{ DocLoaderWithMatch: DocLoaderWithMatch{ Match: func(_ string) bool { @@ -30,20 +39,85 @@ func init() { }, } - loaders = jsonLoader.WithHead(&loader{ + return jsonLoader.WithHead(&loader{ DocLoaderWithMatch: DocLoaderWithMatch{ Match: loading.YAMLMatcher, Fn: loading.YAMLDoc, }, }) +} - // sets the global default loader for go-openapi/spec - spec.PathLoader = loaders.Load +// LoaderChain links a list of [DocLoaderWithMatch] into a single [DocLoader], preserving order. +// Entries with a nil Fn are skipped. Loading options passed at call time are forwarded to the +// matched loader. +// +// Combined with [LoaderWithOptions], it composes a self-contained loader (for example a +// format-dispatching YAML/JSON chain, each entry carrying its own options) that a caller can inject +// through [WithDocLoader] instead of relying on the package-level global loaders. +// +// The returned DocLoader is never nil: when no usable loader is provided, it yields [ErrNoLoader] +// on every call. This fails closed rather than returning nil (which every caller would have to +// guard against, at the risk of a nil-func panic) or silently falling back to an unconfined +// loader. +func LoaderChain(ldrs ...DocLoaderWithMatch) DocLoader { + loader := buildLoaderChain(ldrs...) + + return func(pth string, opts ...loading.Option) (json.RawMessage, error) { + l := loader.clone() + if l != nil { + l.loadingOptions = opts + } + + return l.Load(pth) // nil-safe: yields ErrNoLoader when the chain is empty + } +} + +// buildLoaderChain links a list of [DocLoaderWithMatch] into a loader chain, preserving order. +// Entries with a nil Fn are skipped. Returns nil when no usable loader is provided. +func buildLoaderChain(ldrs ...DocLoaderWithMatch) *loader { + var final, prev *loader + for _, ldr := range ldrs { + if ldr.Fn == nil { + continue + } + + node := &loader{DocLoaderWithMatch: ldr} + if prev == nil { + final = node + prev = node + + continue + } + + prev = prev.WithNext(node) + } + + return final } // DocLoader represents a doc loader type. type DocLoader func(string, ...loading.Option) (json.RawMessage, error) +// LoaderWithOptions returns a [DocLoader] that always applies opts. +// +// Use it to bind a set of [loading.Option] to a loader so they apply to every load — for example a +// custom HTTP client or timeout, authentication or custom headers, an embedded or rooted file +// system, or a remote-address restriction. This is the building block for a document loader that +// carries its own options, avoiding reliance on the package-level global loaders. +// +// opts are appended after any options passed at call time, so they take precedence (loading +// options are last-wins). This also makes confinement options (e.g. [loading.WithRoot]) win over +// any caller-supplied options. +func LoaderWithOptions(fn DocLoader, opts ...loading.Option) DocLoader { + return func(path string, callOpts ...loading.Option) (json.RawMessage, error) { + all := make([]loading.Option, 0, len(callOpts)+len(opts)) + all = append(all, callOpts...) + all = append(all, opts...) + + return fn(path, all...) + } +} + // DocMatcher represents a predicate to check if a loader matches. type DocMatcher func(string) bool @@ -141,6 +215,17 @@ func JSONDoc(path string, opts ...loading.Option) (json.RawMessage, error) { // // This function updates the default loader used by [github.com/go-openapi/spec]. // Since this sets package level globals, you shouldn't call this concurrently. +// +// # Security +// +// AddLoader only *prepends* to the default chain: the previous loaders — including the +// unconfined JSON fallback — remain reachable, both here and via cross-package "$ref" +// resolution. It is therefore the wrong tool for hardening the global default. To replace the +// chain entirely (leaving no unconfined fallback) use [SetLoaders], or [SetRestrictedLoaders] +// for a one-call confined setup. For a single load, prefer a confined per-call loader via +// [WithLoadingOptions] or [WithDocLoaderMatches]. A custom loader registered here only honors +// the protections if its loading function applies the [github.com/go-openapi/swag/loading] +// options it is given. See the package documentation on Security. func AddLoader(predicate DocMatcher, load DocLoader) { loaders = loaders.WithHead(&loader{ DocLoaderWithMatch: DocLoaderWithMatch{ @@ -152,3 +237,36 @@ func AddLoader(predicate DocMatcher, load DocLoader) { // sets the global default loader for go-openapi/spec spec.PathLoader = loaders.Load } + +// SetLoaders replaces the package-level default loader chain with the given loaders, tried in +// order, and re-points [github.com/go-openapi/spec.PathLoader] at it. +// +// Unlike [AddLoader], nothing of the previous default survives — so when the replacement is +// confined, no unconfined fallback remains for any caller relying on the global default +// (including cross-package "$ref" resolution). An entry with a nil Match is a catch-all; you +// are responsible for providing a suitable fallback. Calling SetLoaders with no usable loader +// restores the built-in default (a YAML matcher with a JSON fallback). +// +// # Concurrency +// +// This sets package-level globals and the [github.com/go-openapi/spec] global loader. It is +// not safe to call concurrently with other loads or with [AddLoader]; configure it once at +// startup, before serving. +// +// # Security +// +// This is the way to harden the global default in one place. For a ready-made confined setup, +// see [SetRestrictedLoaders]. As with [AddLoader], a custom loader only honors the protections +// if its loading function applies the [github.com/go-openapi/swag/loading] options it is given. +// See the package documentation on Security. +func SetLoaders(ldrs ...DocLoaderWithMatch) { + chain := buildLoaderChain(ldrs...) + if chain == nil { + chain = defaultLoaders() + } + + loaders = chain + + // sets the global default loader for go-openapi/spec + spec.PathLoader = loaders.Load +} diff --git a/vendor/github.com/go-openapi/loads/options.go b/vendor/github.com/go-openapi/loads/options.go index 045ece5e095..6a4bc6983bc 100644 --- a/vendor/github.com/go-openapi/loads/options.go +++ b/vendor/github.com/go-openapi/loads/options.go @@ -51,25 +51,17 @@ func WithDocLoader(l DocLoader) LoaderOption { // Loaders are executed in the order of provided [DocLoaderWithMatch] 'es. func WithDocLoaderMatches(l ...DocLoaderWithMatch) LoaderOption { return func(opt *options) { - var final, prev *loader - for _, ldr := range l { - if ldr.Fn == nil { - continue - } - - if prev == nil { - final = &loader{DocLoaderWithMatch: ldr} - prev = final - continue - } - - prev = prev.WithNext(&loader{DocLoaderWithMatch: ldr}) - } - opt.loader = final + opt.loader = buildLoaderChain(l...) } } // WithLoadingOptions adds some [loading.Option] to be added when calling a registered loader. +// +// The options are attached to the document's loader, so they apply both to the initial load +// and to every "$ref" resolved during [Document.Expanded]. +// +// This is the recommended place to confine loading of untrusted input, for example with [loading.WithRoot] (local) and +// [loading.WithHTTPClient] (remote). See the package documentation on Security. func WithLoadingOptions(loadingOptions ...loading.Option) LoaderOption { return func(opt *options) { opt.loadingOptions = loadingOptions diff --git a/vendor/github.com/go-openapi/loads/restricted.go b/vendor/github.com/go-openapi/loads/restricted.go new file mode 100644 index 00000000000..022a9a8572a --- /dev/null +++ b/vendor/github.com/go-openapi/loads/restricted.go @@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package loads + +import ( + "encoding/json" + "net" + "net/http" + "net/netip" + "syscall" + "time" + + "github.com/go-openapi/swag/loading" +) + +const ( + // numConfinementOptions is the count of loading options appended to enforce confinement + // (WithRoot + WithHTTPClient), used to size the bundled option slice. + numConfinementOptions = 2 + + defaultTLSHandshakeTimeout = 10 * time.Second +) + +// RestrictedHTTPClient returns an [http.Client] that refuses, at dial time, to connect to +// loopback, private, link-local (including cloud-metadata endpoints such as 169.254.169.254), +// or unspecified addresses. A blocked connection fails with an error wrapping +// [ErrForbiddenAddress]. +// +// The check runs in the dialer Control hook, after DNS resolution and before connect, so it +// also covers HTTP redirects and DNS rebinding — which a URL-string allowlist cannot. The +// client does not honor proxy environment variables, so the guard always inspects the real +// destination rather than a proxy address. +// +// This is the network half of the restricted loaders ([JSONDocRestricted], +// [JSONSpecRestricted], [SpecRestricted]). It may also be used directly with +// [github.com/go-openapi/swag/loading.WithHTTPClient]. +// +// The policy is opinionated and deliberately simple. For a different one (a custom allow/deny +// list, an explicit proxy, mutual TLS, ...), build your own client and pass it with +// [github.com/go-openapi/swag/loading.WithHTTPClient]. To keep the default address policy as a +// base, reuse [IsForbiddenAddress] in your own dialer Control hook — see the package examples +// for the pattern. +func RestrictedHTTPClient() *http.Client { + control := func(_, address string, _ syscall.RawConn) error { + host, _, err := net.SplitHostPort(address) + if err != nil { + return err + } + addr, err := netip.ParseAddr(host) + if err != nil { + return err + } + if IsForbiddenAddress(addr) { + return ErrForbiddenAddress + } + + return nil + } + + return &http.Client{ + Transport: &http.Transport{ + Proxy: nil, // dial the real destination so the guard inspects it + DialContext: (&net.Dialer{Control: control}).DialContext, + ForceAttemptHTTP2: true, + TLSHandshakeTimeout: defaultTLSHandshakeTimeout, + }, + } +} + +// IsForbiddenAddress reports whether addr is one that [RestrictedHTTPClient] refuses to dial: +// a loopback, private, link-local (including cloud-metadata endpoints such as 169.254.169.254), +// or unspecified address. IPv4-mapped IPv6 addresses are unmapped before the check. +// +// It is exported so callers can reuse or extend the default policy when building their own +// dialer Control hook, for example to also reject a CGNAT range or to carve out a single +// trusted internal host: +// +// control := func(_, address string, _ syscall.RawConn) error { +// host, _, err := net.SplitHostPort(address) +// if err != nil { +// return err +// } +// addr, err := netip.ParseAddr(host) +// if err != nil { +// return err +// } +// if loads.IsForbiddenAddress(addr) && host != allowedInternalHost { +// return loads.ErrForbiddenAddress +// } +// return nil +// } +func IsForbiddenAddress(addr netip.Addr) bool { + a := addr.Unmap() + + return a.IsLoopback() || a.IsPrivate() || a.IsLinkLocalUnicast() || a.IsUnspecified() +} + +// restrictedLoadingOptions bundles caller-supplied options with the confinement options, +// appended last so that local rooting and the restricted client always take precedence +// (the loading options are last-wins). +func restrictedLoadingOptions(root string, extra []loading.Option) []loading.Option { + out := make([]loading.Option, 0, len(extra)+numConfinementOptions) + out = append(out, extra...) + out = append(out, loading.WithRoot(root), loading.WithHTTPClient(RestrictedHTTPClient())) + + return out +} + +// JSONDocRestricted returns a JSON [DocLoader] that confines local reads to root (via +// [github.com/go-openapi/swag/loading.WithRoot]) and restricts remote fetches with +// [RestrictedHTTPClient]. +// +// The returned loader may be registered with [WithDocLoader] or [AddLoader]. The confinement +// always takes precedence over any option passed here or at call time, so a caller cannot +// loosen it through [WithLoadingOptions]. +// +// Like [JSONDoc], it loads JSON only: it does not convert YAML. For specs whose references may +// point at YAML documents, prefer [SpecRestricted], which keeps the default JSON/YAML chain. +func JSONDocRestricted(root string, opts ...loading.Option) DocLoader { + // one restricted client, reused for every path and $ref + return restrictedDocLoader(JSONDoc, restrictedLoadingOptions(root, opts)) +} + +// restrictedDocLoader wraps a [DocLoader] so that the confinement options in base are always +// applied, appended after any call-time options so they take precedence (loading options are +// last-wins). +func restrictedDocLoader(fn DocLoader, base []loading.Option) DocLoader { + return func(path string, callOpts ...loading.Option) (json.RawMessage, error) { + if len(callOpts) == 0 { + return fn(path, base...) + } + + all := make([]loading.Option, 0, len(callOpts)+len(base)) + all = append(all, callOpts...) + all = append(all, base...) // confinement (tail of base) still wins + + return fn(path, all...) + } +} + +// JSONSpecRestricted loads a JSON spec like [JSONSpec], but confines local reads to root and +// restricts remote fetches with [RestrictedHTTPClient]. +// +// The confinement is attached to the document's loader, so it also applies to every "$ref" +// resolved by [Document.Expanded]. Extra [github.com/go-openapi/swag/loading] options (custom +// headers, basic auth, timeout, ...) may be supplied; the confinement always wins over them. +func JSONSpecRestricted(path, root string, opts ...loading.Option) (*Document, error) { + return JSONSpec(path, WithLoadingOptions(restrictedLoadingOptions(root, opts)...)) +} + +// SpecRestricted loads a spec like [Spec] — with JSON/YAML auto-detection — but confines local +// reads to root and restricts remote fetches with [RestrictedHTTPClient]. +// +// The confinement is attached to the document's loader, so it also applies to every "$ref" +// resolved by [Document.Expanded]. Extra [github.com/go-openapi/swag/loading] options (custom +// headers, basic auth, timeout, ...) may be supplied; the confinement always wins over them. +func SpecRestricted(path, root string, opts ...loading.Option) (*Document, error) { + return Spec(path, WithLoadingOptions(restrictedLoadingOptions(root, opts)...)) +} + +// SetRestrictedLoaders hardens the package-level default in a single call: it installs a +// confined JSON/YAML loader chain — local reads rooted at root, remote fetches through +// [RestrictedHTTPClient] — as the global default and as +// [github.com/go-openapi/spec.PathLoader]. +// +// After this call, every load that relies on the package default ([Spec], [JSONSpec], and any +// cross-package "$ref" resolution) is confined, with no unconfined fallback left behind. It is +// the global counterpart of [SpecRestricted]; a single restricted client is shared across the +// chain. Extra [github.com/go-openapi/swag/loading] options may be supplied; the confinement +// always wins over them. +// +// # Concurrency +// +// Like [SetLoaders], this mutates package-level and [github.com/go-openapi/spec] globals and is +// not safe to call concurrently. Configure it once at startup, before serving. To revert, call +// [SetLoaders] with no arguments. +func SetRestrictedLoaders(root string, opts ...loading.Option) { + base := restrictedLoadingOptions(root, opts) // one restricted client shared by the whole chain + + SetLoaders( + NewDocLoaderWithMatch(restrictedDocLoader(loading.YAMLDoc, base), loading.YAMLMatcher), + NewDocLoaderWithMatch(restrictedDocLoader(JSONDoc, base), nil), // nil matcher: JSON catch-all fallback + ) +} diff --git a/vendor/github.com/go-openapi/loads/spec.go b/vendor/github.com/go-openapi/loads/spec.go index 606a01d8e9f..40eaff2c73b 100644 --- a/vendor/github.com/go-openapi/loads/spec.go +++ b/vendor/github.com/go-openapi/loads/spec.go @@ -77,6 +77,14 @@ func Embedded(orig, flat json.RawMessage, opts ...LoaderOption) (*Document, erro // Spec loads a new spec document from a local or remote path. // // By default it uses a JSON or YAML loader, with auto-detection based on the resource extension. +// +// Security: by default the path is read with no confinement (local) and fetched with +// [net/http.DefaultClient] (remote), and any "$ref" later resolved by [Document.Expanded] is +// loaded the same way. When the path or the spec contents may derive from untrusted input, +// confine loading with [WithLoadingOptions] (for example +// [github.com/go-openapi/swag/loading.WithRoot] and +// [github.com/go-openapi/swag/loading.WithHTTPClient]). See the package documentation on +// Security. func Spec(path string, opts ...LoaderOption) (*Document, error) { ldr := loaderFromOptions(opts) @@ -157,6 +165,14 @@ func trimData(in json.RawMessage) (json.RawMessage, error) { } // Expanded expands the $ref fields in the spec [Document] and returns a new expanded [Document]. +// +// Security: expansion resolves every "$ref" by calling the document's loader recursively, so +// the spec contents drive further loads. A spec from an untrusted source can thus trigger +// arbitrary local reads or SSRF through its references. The loader carries the +// [github.com/go-openapi/swag/loading] options supplied via [WithLoadingOptions] at load time; +// configure confinement there so it applies to expansion as well. When no document loader is +// set, expansion falls back to the unconfined package-level loader. See the package +// documentation on Security. func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) { swspec := new(spec.Swagger) if err := json.Unmarshal(d.raw, swspec); err != nil { diff --git a/vendor/github.com/go-openapi/runtime/.codecov.yml b/vendor/github.com/go-openapi/runtime/.codecov.yml new file mode 100644 index 00000000000..a5ba8e96d8e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/.codecov.yml @@ -0,0 +1,9 @@ +codecov: + notify: + after_n_builds: 2 + +coverage: + status: + patch: + default: + target: 80% diff --git a/vendor/github.com/go-openapi/runtime/.gitignore b/vendor/github.com/go-openapi/runtime/.gitignore index d8f4186fe59..c0bc15bebe6 100644 --- a/vendor/github.com/go-openapi/runtime/.gitignore +++ b/vendor/github.com/go-openapi/runtime/.gitignore @@ -3,3 +3,5 @@ .idea .env .mcp.json +go.work.sum +.worktrees/ diff --git a/vendor/github.com/go-openapi/runtime/.golangci.yml b/vendor/github.com/go-openapi/runtime/.golangci.yml index 0087ed31130..affd69c88a4 100644 --- a/vendor/github.com/go-openapi/runtime/.golangci.yml +++ b/vendor/github.com/go-openapi/runtime/.golangci.yml @@ -2,13 +2,9 @@ version: "2" linters: default: all disable: - - cyclop - depguard - err113 # disabled temporarily: there are just too many issues to address - - errchkjson - - errorlint - exhaustruct - - forcetypeassert - funlen - gochecknoglobals - gochecknoinits @@ -16,12 +12,12 @@ linters: - godot - godox - gomoddirectives # moved to mono-repo, multi-modules, so replace directives are needed + - gomodguard + - gomodguard_v2 - gosmopolitan - inamedparam - - ireturn - - lll + - ireturn # this repo adopted a pattern where there are quite many returned interfaces. To be challenged with v2 - musttag - - nestif - nilerr # nilerr crashes on this repo - nlreturn - noinlineerr @@ -31,7 +27,6 @@ linters: - testpackage - thelper - tparallel - - unparam - varnamelen - whitespace - wrapcheck @@ -41,10 +36,19 @@ linters: dupl: threshold: 200 goconst: - min-len: 2 + min-len: 9 min-occurrences: 3 + cyclop: + max-complexity: 25 gocyclo: - min-complexity: 45 + min-complexity: 25 + gocognit: + min-complexity: 35 + exhaustive: + default-signifies-exhaustive: true + default-case-required: true + lll: + line-length: 180 exclusions: generated: lax presets: @@ -53,6 +57,7 @@ linters: - legacy - std-error-handling paths: + - .worktrees - third_party$ - builtin$ - examples$ @@ -60,12 +65,17 @@ formatters: enable: - gofmt - goimports + settings: + # local prefixes regroup imports from these packages + goimports: + local-prefixes: + - github.com/go-openapi exclusions: generated: lax paths: + - .worktrees - third_party$ - builtin$ - - examples$ issues: # Maximum issues count per one linter. # Set to 0 to disable. diff --git a/vendor/github.com/go-openapi/runtime/CONTRIBUTORS.md b/vendor/github.com/go-openapi/runtime/CONTRIBUTORS.md index 541fd575e01..9c959ef4823 100644 --- a/vendor/github.com/go-openapi/runtime/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/runtime/CONTRIBUTORS.md @@ -4,20 +4,21 @@ | Total Contributors | Total Contributions | | --- | --- | -| 69 | 490 | +| 71 | 570 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | | @casualjim | 268 | | -| @fredbi | 69 | | +| @fredbi | 144 | | | @youyuanwu | 19 | | | @josephwoodward | 13 | | | @kenjones-cisco | 12 | | | @GlenDC | 7 | | -| @elakito | 6 | | | @moenning | 6 | | | @mstoykov | 6 | | +| @elakito | 6 | | | @ifraixedes | 5 | | +| @Copilot | 4 | | | @zeitlinger | 4 | | | @jkawamoto | 3 | | | @stoyanr | 3 | | @@ -44,7 +45,7 @@ | @petrkotas | 1 | | | @maxatome | 1 | | | @maxkarelov | 1 | | -| @aleksandr-vin | 1 | | +| @tooolbox | 1 | | | @akutz | 1 | | | @yabberyabber | 1 | | | @elv-gilles | 1 | | @@ -56,6 +57,7 @@ | @tte | 1 | | | @martian4202 | 1 | | | @yan-zhuang | 1 | | +| @aleksandr-vin | 1 | | | @azylman | 1 | | | @anasmuhmd | 1 | | | @ArFe | 1 | | @@ -74,8 +76,8 @@ | @JoakimSoderberg | 1 | | | @robbert229 | 1 | | | @jonathaningram | 1 | | +| @KuaaMU | 1 | | | @germanhs | 1 | | | @pracucci | 1 | | -| @tooolbox | 1 | | _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/runtime/README.md b/vendor/github.com/go-openapi/runtime/README.md index fa749062b34..134d930cd9f 100644 --- a/vendor/github.com/go-openapi/runtime/README.md +++ b/vendor/github.com/go-openapi/runtime/README.md @@ -8,8 +8,7 @@ [![Release][release-badge]][release-url] [![Go Report Card][gocard-badge]][gocard-url] [![CodeFactor Grade][codefactor-badge]][codefactor-url] [![License][license-badge]][license-url] -[![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge] - +[![Doc][doc-badge]][doc-url] [![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge] --- A runtime for go OpenAPI toolkit. @@ -18,13 +17,44 @@ The runtime component for use in code generation or as untyped usage. ## Announcements -* **2025-12-19** : new community chat on discord - * a new discord community channel is available to be notified of changes and support users - * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** +[**Complete documentation as github pages**][doc-url] + +**Changes to the API surface in `v0.30.0`**: + +* utility package `header` has now moved to `github.com/go-openapi/runtime/server-middleware/negotiate/header` + +> A shim is provided to support existing programs, with a deprecation notice. + +**Changes in semantics in `v0.30.0`**: + +Function `negotiate.NegotiateContentType` (available as an alias for backward compatibility as `middleware.NegotiateContentType` +now performs a full match considering MIME parameters. + +The previous behavior (matching in order of appearance after stripping parameters) may be enabled explicitly with +option `negotiate.WithIgnoreParameters`. + +* **2026-05-07** : exposed UI and Spec middleware as a separate, dependency-free module. + +> Newly available package: `github.com/go-openapi/runtime/server-middleware/docui` that now holds our +> UI and spec serve middleware. +> +> A shim is available in `github.com/go-openapi/runtime/middleware` to bridge the older UI options to the new ones, +> with a deprecation notice. +> +> Methods that were unduly exported and purely used to manipulate options (e.g. `SwaggerUIOpts.EnsureDefaults`) have been +> removed. New options in `docui` should be used instead. + +> Users may reuse this middleware to serve a Redoc, Rapidoc or SwaggerUI documentation without +> importing the complete go-openapi scaffolding. -You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] +* **2026-05-05** : exposed content negotiation methods as a separate, dependency-free module -Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] +> Users may reuse these utilities to support content-negotiation without extra dependencies. +> +> Newly available module: `github.com/go-openapi/runtime/server-middleware` +> +> Newly available packages: `github.com/go-openapi/runtime/server-middleware/negotiate` and +> `github.com/go-openapi/runtime/server-middleware/mediatype`. ## Status @@ -40,18 +70,21 @@ go get github.com/go-openapi/runtime See -For pre-v0.30.0 releases see [release notes](docs/NOTES.md). +For v0.29.0 release see [release notes](docs/NOTES.md). +From that release onwards, changes are tracked in the github release notes. **What coming next?** Moving forward, we want to : -* [ ] continue narrowing down the scope of dependencies: - * yaml support in an independent module +* [x] fix a few known issues with some file upload requests (e.g. #286) +* [] continue narrowing down the scope of dependencies: + * [x] split middleware and other useful utilities as a separate dependency-free module + * yaml support in an independent module (v2) * introduce more up-to-date support for opentelemetry as a separate module that evolves independently from the main package (to avoid breaking changes, the existing API - will remain maintained, but evolve at a slower pace than opentelemetry). -* [ ] fix a few known issues with some file upload requests (e.g. #286) + will remain maintained, but evolve at a slower pace than opentelemetry). (v2) +* [] publish proper documentation and examples ## Licensing @@ -62,11 +95,11 @@ on top of which it has been built. ## Other documentation -* [FAQ](docs/FAQ.md) +* [FAQ](https://go-openapi.github.io/runtime/tutorials/faq/) · [Media-type selection](https://go-openapi.github.io/runtime/tutorials/media-types/) · [Client keep-alive](https://go-openapi.github.io/runtime/tutorials/keep-alive/) * [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines](.github/CONTRIBUTING.md) -* [Maintainers documentation](docs/MAINTAINERS.md) -* [Code style](docs/STYLE.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] ## Cutting a new release @@ -95,11 +128,10 @@ Maintainers can cut a new release by either: [codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/runtime [codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/runtime +[doc-badge]: https://img.shields.io/badge/doc-site-blue?link=https%3A%2F%2Fgo-openapi.github.io%2Fruntime%2F +[doc-url]: https://go-openapi.github.io/runtime [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/runtime [godoc-url]: http://pkg.go.dev/github.com/go-openapi/runtime -[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png -[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM -[slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue [discord-url]: https://discord.gg/FfnFYaC3k5 @@ -111,3 +143,7 @@ Maintainers can cut a new release by either: [goversion-url]: https://github.com/go-openapi/runtime/blob/master/go.mod [top-badge]: https://img.shields.io/github/languages/top/go-openapi/runtime [commits-badge]: https://img.shields.io/github/commits-since/go-openapi/runtime/latest + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/runtime/bytestream.go b/vendor/github.com/go-openapi/runtime/bytestream.go index 8701c8e3d66..9371ea4ea1f 100644 --- a/vendor/github.com/go-openapi/runtime/bytestream.go +++ b/vendor/github.com/go-openapi/runtime/bytestream.go @@ -97,7 +97,7 @@ func ByteStreamConsumer(opts ...byteStreamOpt) Consumer { } default: // check for the underlying type to be pointer to []byte or string, - if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr { + if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Pointer { return errors.New("destination must be a pointer") } @@ -126,13 +126,13 @@ func ByteStreamConsumer(opts ...byteStreamOpt) Consumer { // // Supported input underlying types and interfaces, prioritized in this order: // -// - [io.WriterTo] (for maximum control) -// - [io.Reader] (performs [io.Copy]). A ReadCloser is closed before exiting. -// - [encoding.BinaryMarshaler] -// - error (writes as a string) -// - []byte -// - string -// - struct, other slices: writes as JSON. +// - [io.WriterTo] (for maximum control) +// - [io.Reader] (performs [io.Copy]). A ReadCloser is closed before exiting. +// - [encoding.BinaryMarshaler] +// - error (writes as a string) +// - []byte +// - string +// - struct, other slices: writes as JSON. func ByteStreamProducer(opts ...byteStreamOpt) Producer { var vals byteStreamOpts for _, opt := range opts { diff --git a/vendor/github.com/go-openapi/runtime/client/httptrace.go b/vendor/github.com/go-openapi/runtime/client/httptrace.go new file mode 100644 index 00000000000..5bdea4e2418 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/httptrace.go @@ -0,0 +1,520 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "context" + "crypto/tls" + "fmt" + "io" + "net/http/httptrace" + "strings" + "sync" + "time" + + "github.com/go-openapi/runtime/logger" +) + +// traceSession owns the per-request state for [Runtime.Trace]. +// +// It tracks the t=0 anchor for the connection phase, accumulates +// per-phase timestamps (for the trailing summary), and emits each +// event to the runtime logger as it fires. One session per +// SubmitContext call. +type traceSession struct { + logger logger.Logger + method string + url string + + // tlsCfg points at the *tls.Config of the http.Transport that + // will run the request, when introspectable (i.e. the transport + // is an *http.Transport). Used by the TLS diagnostic mode to + // cross-check user configuration against what the handshake + // actually attempted. Nil when the transport is custom and + // the config cannot be reached. + tlsCfg *tls.Config + + mu sync.Mutex + start time.Time + last time.Time // last printed event, for relative-dt rendering + phases phaseTimings + gotConn httptrace.GotConnInfo + tlsDone tlsResult + + dnsStartAt time.Time + connectStartAt time.Time + tlsHandshakeStartAt time.Time + wait100StartAt time.Time + gotConnAt time.Time + wroteHeadersAt time.Time + wroteRequestAt time.Time + ttfbAt time.Time + + statusCode int + rtError error +} + +// phaseTimings holds the per-phase durations for the trailing +// summary line. Zero values mean "phase did not occur" (e.g. no +// DNS lookup on a reused conn, no TLS on http://). +type phaseTimings struct { + dns time.Duration + dial time.Duration + tls time.Duration + ttfb time.Duration // time from GotConn to first response byte +} + +// tlsResult captures whatever we learned from TLSHandshakeDone. +// On the happy path err is nil and state is fully populated; on +// failure state may be partial (and is what the TLS diagnostic +// mode in httptrace_tls.go works from). +type tlsResult struct { + state tls.ConnectionState + err error + done bool +} + +const tracePrefix = "[trace] " + +// staleIdleThreshold is the idle duration above which a reused +// pooled connection earns a HEADS-UP annotation. Per-runtime +// configurability is deferred to v2; 30s matches the issue #336 +// territory (typical NAT idle timeouts start in the 60–350s +// range, so a 30s reuse is already in "could be stale" zone). +const staleIdleThreshold = 30 * time.Second + +// newTraceSession allocates a session and pre-renders the opening +// line (method + url). The session is not yet attached to a +// context — that's the caller's responsibility via session.attach. +// +// tlsCfg may be nil; when non-nil it is used by the TLS diagnostic +// mode to cross-check user-configured constraints (MinVersion, +// CipherSuites, custom RootCAs) against handshake failures. +func newTraceSession(log logger.Logger, method, url string, tlsCfg *tls.Config) *traceSession { + s := &traceSession{ + logger: log, + method: method, + url: url, + tlsCfg: tlsCfg, + start: time.Now(), + } + s.last = s.start + s.emitf("%s %s", method, url) + return s +} + +// attach installs the session's ClientTrace on ctx and returns the +// derived context. Callers pass the returned context to +// http.Client.Do (typically by setting it on req via +// req.WithContext) so the transport fires the hooks. +func (s *traceSession) attach(ctx context.Context) context.Context { + return httptrace.WithClientTrace(ctx, s.clientTrace()) +} + +// clientTrace wires every httptrace hook to the corresponding +// session method. Each callback is responsible for its own +// locking; the stdlib does not serialize trace callbacks. +func (s *traceSession) clientTrace() *httptrace.ClientTrace { + return &httptrace.ClientTrace{ + GetConn: s.onGetConn, + GotConn: s.onGotConn, + PutIdleConn: s.onPutIdleConn, + GotFirstResponseByte: s.onGotFirstResponseByte, + Got100Continue: s.onGot100Continue, + DNSStart: s.onDNSStart, + DNSDone: s.onDNSDone, + ConnectStart: s.onConnectStart, + ConnectDone: s.onConnectDone, + TLSHandshakeStart: s.onTLSHandshakeStart, + TLSHandshakeDone: s.onTLSHandshakeDone, + WroteHeaders: s.onWroteHeaders, + Wait100Continue: s.onWait100Continue, + WroteRequest: s.onWroteRequest, + } +} + +// --------------------------------------------------------------- +// Phase callbacks (stdlib httptrace hooks) +// --------------------------------------------------------------- + +func (s *traceSession) onGetConn(hostPort string) { + s.emitTf("GetConn(%s)", hostPort) +} + +func (s *traceSession) onGotConn(info httptrace.GotConnInfo) { + s.mu.Lock() + s.gotConn = info + s.gotConnAt = time.Now() + s.mu.Unlock() + + if info.Reused { + s.emitTf("GotConn(reused=true, idle=%t, idle-time=%s)", + info.WasIdle, info.IdleTime.Round(time.Millisecond)) + } else { + s.emitTf("GotConn(reused=false)") + } + + if isStaleIdleReuse(info) { + s.emitf("# HEADS-UP: reused idle connection (idle for %s).", + info.IdleTime.Round(time.Second)) + s.emitf("# If this request fails with EOF/connection reset, the server") + s.emitf("# or an in-path NAT may have dropped the conn silently.") + } +} + +// isStaleIdleReuse reports whether a GotConn info indicates the +// connection came from the idle pool after sitting idle for +// longer than [staleIdleThreshold]. This is the issue #336 +// pattern: long-idle pooled conns are the ones most likely to be +// dead by the time the next request tries to use them. +func isStaleIdleReuse(info httptrace.GotConnInfo) bool { + return info.Reused && info.WasIdle && info.IdleTime > staleIdleThreshold +} + +func (s *traceSession) onPutIdleConn(err error) { + if err != nil { + s.emitTf("PutIdleConn(err=%v)", err) + return + } + s.emitTf("PutIdleConn") +} + +func (s *traceSession) onGotFirstResponseByte() { + s.mu.Lock() + s.ttfbAt = time.Now() + if !s.gotConnAt.IsZero() { + s.phases.ttfb = s.ttfbAt.Sub(s.gotConnAt) + } + s.mu.Unlock() + s.emitTf("GotFirstResponseByte (TTFB)") +} + +func (s *traceSession) onGot100Continue() { + s.emitTf("Got100Continue") +} + +func (s *traceSession) onDNSStart(info httptrace.DNSStartInfo) { + s.mu.Lock() + s.dnsStartAt = time.Now() + s.mu.Unlock() + s.emitTf("DNSStart(host=%s)", info.Host) +} + +func (s *traceSession) onDNSDone(info httptrace.DNSDoneInfo) { + s.mu.Lock() + if !s.dnsStartAt.IsZero() { + s.phases.dns = time.Since(s.dnsStartAt) + } + s.mu.Unlock() + + addrs := make([]string, 0, len(info.Addrs)) + for _, a := range info.Addrs { + addrs = append(addrs, a.String()) + } + if info.Err != nil { + s.emitTf("DNSDone(err=%v, addrs=[%s], coalesced=%t)", + info.Err, strings.Join(addrs, " "), info.Coalesced) + return + } + s.emitTf("DNSDone(addrs=[%s], coalesced=%t)", + strings.Join(addrs, " "), info.Coalesced) +} + +func (s *traceSession) onConnectStart(network, addr string) { + s.mu.Lock() + s.connectStartAt = time.Now() + s.mu.Unlock() + s.emitTf("ConnectStart(%s %s)", network, addr) +} + +func (s *traceSession) onConnectDone(network, addr string, err error) { + s.mu.Lock() + if !s.connectStartAt.IsZero() { + s.phases.dial = time.Since(s.connectStartAt) + } + s.mu.Unlock() + + if err != nil { + s.emitTf("ConnectDone(%s %s, err=%v)", network, addr, err) + return + } + s.emitTf("ConnectDone(%s %s)", network, addr) +} + +func (s *traceSession) onTLSHandshakeStart() { + s.mu.Lock() + s.tlsHandshakeStartAt = time.Now() + s.mu.Unlock() + s.emitTf("TLSHandshakeStart") +} + +func (s *traceSession) onTLSHandshakeDone(state tls.ConnectionState, err error) { + s.mu.Lock() + if !s.tlsHandshakeStartAt.IsZero() { + s.phases.tls = time.Since(s.tlsHandshakeStartAt) + } + s.tlsDone = tlsResult{state: state, err: err, done: true} + s.mu.Unlock() + + if err != nil { + s.emitTf("TLSHandshakeDone(err=%v)", err) + s.emitTLSDiagnostic(state, err) + return + } + s.emitTf("TLSHandshakeDone(tls=%s, cipher=%s, server=%s%s)", + tlsVersionName(state.Version), + tls.CipherSuiteName(state.CipherSuite), + state.ServerName, + certExpiryFragment(state), + ) +} + +func (s *traceSession) onWroteHeaders() { + s.mu.Lock() + s.wroteHeadersAt = time.Now() + s.mu.Unlock() + s.emitTf("WroteHeaders") +} + +func (s *traceSession) onWait100Continue() { + s.mu.Lock() + s.wait100StartAt = time.Now() + s.mu.Unlock() + s.emitTf("Wait100Continue") +} + +func (s *traceSession) onWroteRequest(info httptrace.WroteRequestInfo) { + s.mu.Lock() + s.wroteRequestAt = time.Now() + s.mu.Unlock() + + if info.Err != nil { + s.emitTf("WroteRequest(err=%v)", info.Err) + return + } + s.emitTf("WroteRequest") +} + +// --------------------------------------------------------------- +// Body wrapping +// --------------------------------------------------------------- + +// bodySide identifies which direction an instrumented body is on. +type bodySide string + +const ( + bodySend bodySide = "Sent" + bodyRecv bodySide = "Received" +) + +// instrumentedBody wraps an [io.ReadCloser] and emits a +// BodyChunk{Sent,Received} trace event per Read call. Tracks the +// inter-read delay in `dt` so users can see streaming-body +// cadence. +// +// Read granularity: bytes returned by the underlying body, not +// HTTP/1.1 chunked-framing units. For wire-level chunking, use +// [Runtime.Debug] instead. +// +// Concurrency: a single body is read from a single goroutine in +// practice (http.Transport for request bodies, the application +// for response bodies), so no internal locking is needed beyond +// what the underlying ReadCloser provides. +type instrumentedBody struct { + wrapped io.ReadCloser + sess *traceSession + side bodySide + last time.Time +} + +func (b *instrumentedBody) Read(p []byte) (int, error) { + n, err := b.wrapped.Read(p) + if n > 0 { + first := b.last.IsZero() + var dt time.Duration + if !first { + dt = time.Since(b.last) + } + b.last = time.Now() + b.sess.onBodyChunk(b.side, n, dt, first) + } + return n, err +} + +func (b *instrumentedBody) Close() error { + return b.wrapped.Close() +} + +// wrapRequestBody returns an instrumented wrapper around the +// outgoing request body, or the original body if nil (which is +// the common case for GET requests). The wrapper observes +// Transport-side reads, so BodyChunkSent events appear between +// WroteHeaders and WroteRequest in the trace timeline. +func (s *traceSession) wrapRequestBody(body io.ReadCloser) io.ReadCloser { + if body == nil { + return nil + } + return &instrumentedBody{wrapped: body, sess: s, side: bodySend} +} + +// wrapResponseBody returns an instrumented wrapper around the +// incoming response body. Stacks cleanly above +// [KeepAliveTransport]'s drain-on-close behavior. +func (s *traceSession) wrapResponseBody(body io.ReadCloser) io.ReadCloser { + if body == nil { + return nil + } + return &instrumentedBody{wrapped: body, sess: s, side: bodyRecv} +} + +// onBodyChunk renders a single BodyChunk{Sent,Received} event. +// dt is the duration since the previous Read on the same body and +// is meaningful only when `first` is false. The first chunk has no +// preceding read, so the dt= field is suppressed; every subsequent +// chunk emits dt= unconditionally — even when the measured value +// rounds to zero (common on Windows, where the system clock +// resolution is coarser than a fast loopback read loop). +func (s *traceSession) onBodyChunk(side bodySide, n int, dt time.Duration, first bool) { + if first { + s.emitTf("BodyChunk%s(n=%d)", side, n) + return + } + s.emitTf("BodyChunk%s(n=%d, dt=%s)", side, n, round(dt)) +} + +// --------------------------------------------------------------- +// Submit-level lifecycle hooks (called from SubmitContext) +// --------------------------------------------------------------- + +// onRoundTripError is called by SubmitContext when http.Client.Do +// returns an error. It records the error for the summary line. +func (s *traceSession) onRoundTripError(err error) { + s.mu.Lock() + s.rtError = err + s.mu.Unlock() + s.emitTf("! error: %v", err) +} + +// onResponse is called when http.Client.Do returns successfully. +// It records the status code for the summary line. +func (s *traceSession) onResponse(statusCode int) { + s.mu.Lock() + s.statusCode = statusCode + s.mu.Unlock() +} + +// finish renders the trailing single-line summary and is called +// by SubmitContext after the response body has been consumed (or +// on error path, after the error was recorded). When a round-trip +// error happened on a stale-idle reused connection, a tail block +// flags the issue #336 pattern explicitly. +func (s *traceSession) finish() { + s.mu.Lock() + defer s.mu.Unlock() + + total := time.Since(s.start) + var b strings.Builder + fmt.Fprintf(&b, "Summary: %s — ", s.method) + if s.rtError != nil { + fmt.Fprintf(&b, "FAILED (%v)", s.rtError) + } else { + fmt.Fprintf(&b, "%d", s.statusCode) + } + if s.phases.dns > 0 { + fmt.Fprintf(&b, ", dns=%s", round(s.phases.dns)) + } + if s.phases.dial > 0 { + fmt.Fprintf(&b, ", dial=%s", round(s.phases.dial)) + } + if s.phases.tls > 0 { + fmt.Fprintf(&b, ", tls=%s", round(s.phases.tls)) + } + if s.phases.ttfb > 0 { + fmt.Fprintf(&b, ", ttfb=%s", round(s.phases.ttfb)) + } + fmt.Fprintf(&b, ", total=%s", round(total)) + + s.emitRaw(b.String()) + + // issue #336 tail annotation: a round-trip failure on a + // stale-idle reused conn is the canonical pattern. + if s.rtError != nil && isStaleIdleReuse(s.gotConn) { + s.emitf("# FAILED on a reused idle conn (%s idle).", + s.gotConn.IdleTime.Round(time.Second)) + s.emitf("# Silently closed the conn while it sat in the idle pool.") + s.emitf("# Consider lowering http.Transport.IdleConnTimeout to evict") + s.emitf("# pooled conns before the NAT/server side does.") + } +} + +// --------------------------------------------------------------- +// Emission helpers +// --------------------------------------------------------------- + +// emitf prints a plain event line (no t= timestamp). Used for the +// opening line and the summary. +func (s *traceSession) emitf(format string, args ...any) { + s.logger.Debugf(tracePrefix+format, args...) +} + +// emitRaw is like emitf but takes an already-rendered string. Used +// by finish() which builds its line via strings.Builder. +func (s *traceSession) emitRaw(line string) { + s.logger.Debugf("%s", tracePrefix+line) +} + +// emitTf prints a phase event with a cumulative t=... offset from +// the session start. +func (s *traceSession) emitTf(format string, args ...any) { + t := round(time.Since(s.start)) + msg := fmt.Sprintf(format, args...) + s.logger.Debugf(tracePrefix+"%s (t=%s)", msg, t) +} + +// traceRoundUnit is the rounding granularity for >=1ms durations +// rendered in trace output. 100µs keeps lines readable while +// preserving enough resolution to spot millisecond-scale phase +// differences. +const traceRoundUnit = 100 * time.Microsecond + +// round trims durations for human-readable trace output. +// Sub-millisecond durations round to 1µs (preserves visibility on +// fast loopback servers); >=1ms durations round to [traceRoundUnit]. +func round(d time.Duration) time.Duration { + if d <= 0 { + return 0 + } + if d < time.Millisecond { + return d.Round(time.Microsecond) + } + return d.Round(traceRoundUnit) +} + +// --------------------------------------------------------------- +// TLS rendering helpers +// --------------------------------------------------------------- + +func tlsVersionName(v uint16) string { + switch v { + case tls.VersionTLS10: + return "1.0" + case tls.VersionTLS11: + return "1.1" + case tls.VersionTLS12: + return "1.2" + case tls.VersionTLS13: + return "1.3" + default: + return fmt.Sprintf("0x%04x", v) + } +} + +// certExpiryFragment renders ", expires=YYYY-MM-DD" for the leaf +// cert when available, or an empty string otherwise. +func certExpiryFragment(state tls.ConnectionState) string { + if len(state.PeerCertificates) == 0 { + return "" + } + return ", expires=" + state.PeerCertificates[0].NotAfter.UTC().Format("2006-01-02") +} diff --git a/vendor/github.com/go-openapi/runtime/client/httptrace_tls.go b/vendor/github.com/go-openapi/runtime/client/httptrace_tls.go new file mode 100644 index 00000000000..063fb259272 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/httptrace_tls.go @@ -0,0 +1,353 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "net/http" + "strings" + "time" +) + +// TLS alert codes used by the diagnostic to classify handshake +// failures. The crypto/tls package does not export named constants +// for individual alerts, so we declare the ones we care about. +// Values are from RFC 8446 §6 (the TLS 1.3 alert protocol; the +// numbering is shared with earlier TLS versions for these alerts). +// +// The `err`-prefixed names satisfy the errname linter — tls.AlertError +// implements error, so these are sentinel errors. +const ( + errTLSAlertHandshakeFailure tls.AlertError = 40 + errTLSAlertProtocolVersion tls.AlertError = 70 +) + +// introspectTLSConfig returns the *tls.Config of the http.Transport +// that will run a request, when reachable, or nil otherwise. +// +// Reachable means the client's Transport is an *http.Transport +// (the default and most common case). Custom transports — wrappers +// around the default, or entirely user-provided — break introspection; +// the TLS diagnostic falls back to "configured: not introspectable" +// in that case. +// +// A nil client (zero value) or nil Transport falls through to +// [http.DefaultTransport], whose TLSClientConfig is also nil; the +// function returns nil and the diagnostic reports defaults. +func introspectTLSConfig(client *http.Client) *tls.Config { + if client == nil { + return nil + } + transport := client.Transport + if transport == nil { + transport = http.DefaultTransport + } + t, ok := transport.(*http.Transport) + if !ok { + return nil + } + return t.TLSClientConfig +} + +// emitTLSDiagnostic renders the failure-mode TLS diagnostic block. +// Called from [traceSession.onTLSHandshakeDone] when err != nil. +// +// The block covers three axes (per the plan): +// +// 1. Protocol-version negotiation — detected from +// [errTLSAlertProtocolVersion] or a "protocol version" substring. +// 2. Cipher-suite negotiation — detected from +// [errTLSAlertHandshakeFailure] when the user pinned CipherSuites. +// 3. Certificate-chain validity — detected from +// [x509.CertificateInvalidError], [x509.UnknownAuthorityError] +// or [x509.HostnameError]. +// +// When none of the specific axes match, a generic fallback emits +// the raw error and whatever inspectable config the session holds. +func (s *traceSession) emitTLSDiagnostic(state tls.ConnectionState, err error) { + s.emitf("# TLS DIAGNOSTIC") + + // tlsAxisGeneric is handled by the default branch. + switch axis := classifyTLSError(err); axis { + case tlsAxisProtocolVersion: + s.diagnoseProtocolVersion(state, err) + case tlsAxisCipher: + s.diagnoseCipher(err) + case tlsAxisCertChain: + s.diagnoseCertChain(err) + default: + s.diagnoseTLSGeneric(err) + } +} + +// tlsAxis is the diagnostic dimension a TLS handshake error maps +// to. Axes are mutually exclusive at classification time. +type tlsAxis int + +const ( + tlsAxisGeneric tlsAxis = iota + tlsAxisProtocolVersion + tlsAxisCipher + tlsAxisCertChain +) + +// classifyTLSError maps a TLS handshake error to one of the +// diagnostic axes. The ordering matters: cert-chain errors win +// over the generic handshake_failure alert because the alert is +// what the server sends back, but the local error type carries +// the more specific reason. +func classifyTLSError(err error) tlsAxis { + if err == nil { + return tlsAxisGeneric + } + + // Cert-chain errors are the most specific local diagnostic + // and should be reported even if a generic alert is also + // present in the chain. + var certInvalid x509.CertificateInvalidError + if errors.As(err, &certInvalid) { + return tlsAxisCertChain + } + var unknownAuth x509.UnknownAuthorityError + if errors.As(err, &unknownAuth) { + return tlsAxisCertChain + } + var hostnameErr x509.HostnameError + if errors.As(err, &hostnameErr) { + return tlsAxisCertChain + } + + // TLS alert classification. + var alert tls.AlertError + if errors.As(err, &alert) { + switch alert { + case errTLSAlertProtocolVersion: + return tlsAxisProtocolVersion + case errTLSAlertHandshakeFailure: + return tlsAxisCipher + } + } + + // Fall back on substring detection for protocol-version + // failures that arrive via the local error path rather than + // a server-side alert (e.g. when the client refuses the + // server's offered version). + msg := err.Error() + if strings.Contains(msg, "protocol version") || strings.Contains(msg, "unsupported protocol") { + return tlsAxisProtocolVersion + } + + return tlsAxisGeneric +} + +// --------------------------------------------------------------- +// Axis renderers +// --------------------------------------------------------------- + +func (s *traceSession) diagnoseProtocolVersion(state tls.ConnectionState, err error) { + s.emitf("# axis: protocol-version") + s.emitf("# error: %v", err) + + configuredMin, configuredMax := configuredVersionRange(s.tlsCfg) + s.emitf("# client offered: TLS %s — TLS %s", + tlsVersionName(configuredMin), tlsVersionName(configuredMax)) + + if state.Version != 0 { + s.emitf("# negotiated up to: TLS %s", tlsVersionName(state.Version)) + } + s.emitf("# suggested: widen TLSClientOptions.MinVersion/MaxVersion,") + s.emitf("# or pin to a version the server speaks.") +} + +func (s *traceSession) diagnoseCipher(err error) { + s.emitf("# axis: cipher-suite") + s.emitf("# error: %v", err) + + if s.tlsCfg != nil && len(s.tlsCfg.CipherSuites) > 0 { + s.emitf("# client configured: [%s]", + strings.Join(cipherSuiteNames(s.tlsCfg.CipherSuites), ", ")) + s.emitf("# server set: not exposed by Go stdlib") + s.emitf("# (capture with: openssl s_client -cipher ALL)") + s.emitf("# suggested: drop the explicit CipherSuites restriction,") + s.emitf("# or align it with the server's policy.") + return + } + // No client-side restriction. The handshake_failure alert + // is generic; without more info we can only surface the + // fact and suggest investigation. + s.emitf("# client configured: defaults (no CipherSuites restriction)") + s.emitf("# note: alert 40 is generic; the server may have rejected") + s.emitf("# the handshake for a non-cipher reason. Try") + s.emitf("# openssl s_client to capture details.") +} + +func (s *traceSession) diagnoseCertChain(err error) { + s.emitf("# axis: cert-chain") + + var certInvalid x509.CertificateInvalidError + if errors.As(err, &certInvalid) { + s.diagnoseCertInvalid(certInvalid) + return + } + + var unknownAuth x509.UnknownAuthorityError + if errors.As(err, &unknownAuth) { + s.diagnoseUnknownAuthority(unknownAuth) + return + } + + var hostnameErr x509.HostnameError + if errors.As(err, &hostnameErr) { + s.diagnoseHostnameMismatch(hostnameErr) + return + } + + // Defensive: should not happen — classifyTLSError already + // matched one of the three. + s.emitf("# error: %v", err) +} + +func (s *traceSession) diagnoseCertInvalid(certInvalid x509.CertificateInvalidError) { + cert := certInvalid.Cert + s.emitf("# reason: %s", certInvalidReasonName(certInvalid.Reason)) + + switch certInvalid.Reason { + case x509.Expired: + s.emitf("# leaf: subject=%s", cert.Subject) + s.emitf("# NotBefore=%s", cert.NotBefore.UTC().Format(time.RFC3339)) + s.emitf("# NotAfter=%s", cert.NotAfter.UTC().Format(time.RFC3339)) + s.emitf("# now=%s", time.Now().UTC().Format(time.RFC3339)) + delta := time.Since(cert.NotAfter).Round(time.Hour) + s.emitf("# expired %s ago", delta) + s.emitf("# suggested: renew the server cert.") + case x509.NameMismatch, x509.CANotAuthorizedForThisName: + s.emitf("# leaf: subject=%s", cert.Subject) + s.emitf("# DNS SANs=%v", cert.DNSNames) + s.emitf("# suggested: set TLSClientOptions.ServerName to match") + s.emitf("# one of the cert SANs, or fix the cert.") + default: + // Less-common reasons render via the default branch (issuer + NotAfter dump). + s.emitf("# leaf: subject=%s, issuer=%s", cert.Subject, cert.Issuer) + s.emitf("# NotBefore=%s", cert.NotBefore.UTC().Format(time.RFC3339)) + s.emitf("# NotAfter=%s", cert.NotAfter.UTC().Format(time.RFC3339)) + s.emitf("# error: %v", certInvalid) + } +} + +func (s *traceSession) diagnoseUnknownAuthority(unknownAuth x509.UnknownAuthorityError) { + s.emitf("# reason: chain root not in trust store (unknown-CA)") + if cert := unknownAuth.Cert; cert != nil { + s.emitf("# offending: subject=%s", cert.Subject) + s.emitf("# issuer=%s", cert.Issuer) + s.emitf("# NotAfter=%s", cert.NotAfter.UTC().Format(time.RFC3339)) + } + + trust := "SystemCertPool" + if s.tlsCfg != nil && s.tlsCfg.RootCAs != nil { + trust = "TLSClientOptions.CA (custom RootCAs)" + } + s.emitf("# trust store in use: %s", trust) + + s.emitf("# suggested: set TLSClientOptions.CA to a bundle that") + s.emitf("# includes the issuing CA, or add it to the") + s.emitf("# OS trust store.") +} + +func (s *traceSession) diagnoseHostnameMismatch(hostnameErr x509.HostnameError) { + s.emitf("# reason: hostname mismatch") + s.emitf("# dialed: %s", hostnameErr.Host) + if cert := hostnameErr.Certificate; cert != nil { + s.emitf("# leaf: subject=%s", cert.Subject) + s.emitf("# DNS SANs=%v", cert.DNSNames) + s.emitf("# IP SANs=%v", cert.IPAddresses) + } + if s.tlsCfg != nil && s.tlsCfg.ServerName != "" { + s.emitf("# TLSClientOptions.ServerName=%q", s.tlsCfg.ServerName) + } + s.emitf("# suggested: dial the hostname listed in the cert SANs,") + s.emitf("# or set TLSClientOptions.ServerName to match.") +} + +func (s *traceSession) diagnoseTLSGeneric(err error) { + s.emitf("# axis: unclassified") + s.emitf("# error: %v", err) + if s.tlsCfg != nil { + minV, maxV := configuredVersionRange(s.tlsCfg) + s.emitf("# configured: MinVersion=TLS %s, MaxVersion=TLS %s", + tlsVersionName(minV), tlsVersionName(maxV)) + if s.tlsCfg.InsecureSkipVerify { + s.emitf("# note: TLSClientOptions.InsecureSkipVerify=true — yet") + s.emitf("# a TLS error still surfaced. Something deeper than") + s.emitf("# certificate verification is failing.") + } + } +} + +// --------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------- + +// configuredVersionRange returns the effective (Min, Max) TLS +// version range a client config negotiates. Zero values in the +// stdlib config mean "use Go default", which is TLS 1.2 .. 1.3 in +// modern Go. We materialize those defaults for display. +func configuredVersionRange(cfg *tls.Config) (uint16, uint16) { + const ( + defaultMin = tls.VersionTLS12 + defaultMax = tls.VersionTLS13 + ) + if cfg == nil { + return defaultMin, defaultMax + } + minV := cfg.MinVersion + if minV == 0 { + minV = defaultMin + } + maxV := cfg.MaxVersion + if maxV == 0 { + maxV = defaultMax + } + return minV, maxV +} + +func cipherSuiteNames(ids []uint16) []string { + out := make([]string, 0, len(ids)) + for _, id := range ids { + out = append(out, tls.CipherSuiteName(id)) + } + return out +} + +// certInvalidReasonName renders an x509.InvalidReason as a short +// human-readable label. The stdlib does not expose a String() +// method for these, so we keep a small table. +// +// Anything outside the listed cases falls through to the numeric default. +func certInvalidReasonName(r x509.InvalidReason) string { + switch r { + case x509.NotAuthorizedToSign: + return "not-authorized-to-sign" + case x509.Expired: + return "expired" + case x509.CANotAuthorizedForThisName: + return "ca-not-authorized-for-this-name" + case x509.TooManyIntermediates: + return "too-many-intermediates" + case x509.IncompatibleUsage: + return "incompatible-usage" + case x509.NameMismatch: + return "name-mismatch" + case x509.NameConstraintsWithoutSANs: + return "name-constraints-without-sans" + case x509.TooManyConstraints: + return "too-many-constraints" + case x509.CANotAuthorizedForExtKeyUsage: + return "ca-not-authorized-for-ext-key-usage" + default: + return fmt.Sprintf("invalid-reason-%d", r) + } +} diff --git a/vendor/github.com/go-openapi/runtime/client/internal/request/request.go b/vendor/github.com/go-openapi/runtime/client/internal/request/request.go new file mode 100644 index 00000000000..22d3f64c01b --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/internal/request/request.go @@ -0,0 +1,945 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package request + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "log" + "mime" + "mime/multipart" + "net/http" + "net/textproto" + "net/url" + "os" + "path" + "path/filepath" + "strings" + "time" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" +) + +var _ runtime.ClientRequest = new(Request) // ensure compliance to the interface + +// Request represents a swagger client request. +// It binds parameters to a HTTP request. +// +// The main purpose of this struct is to hide the machinery of adding OpenAPI v2 parameters to a transport request. +// +// A generated client only implements what is necessary to turn a parameter into a valid value for these methods. +// +// There is no parameter validation here, it is assumed to be used after a spec has been validated. +// +// # Request binding +// +// The binding of parameters is carried out by method [Request.BuildHTTPContext]. +// +// It analyzes parameters, which may come in different flavors: +// +// - a file or multipart form containing a file +// - a body which is a [io.Reader] +// - a buffered body (regular schema body, including urlencoded form) +// +// In all cases, we may also have query or path parameters encoded in the URL, or header parameters. +// +// The result is a [http.Request], with the following properties: +// +// - file, multipart form or [io.Reader] body: a streaming request with an attached go routine that consumes the [io.Reader]. +// - buffered body: a simple request +// +// The caller passes the parent [context.Context] to [Request.BuildHTTPContext] and receives back a cancel +// function to release the resources held by the derived request context once the response is consumed. +// +// # Authentication +// +// Authentication is built in the request by using a [runtime.ClientAuthInfoWriter]. +// This helper may need to inspect the body of the request before sending authentication info. +// To cover that case, streaming bodies use a copy of the body [io.Reader] for the [runtime.ClientAuthInfoWriter] +// to consume if it wants to. +// +// # Content negotiation +// +// The [Request] detects `multipart/form-data` to switch to streamed request. +// +// `application/x-www-form-urlencoded` is also honored, even for file parameters, which are not streamed in this case. +// File parameters default behavior is `multipart/form-data`. +// +// The natural way to define the `Content-Type` header is to use the `contentType` parameter to switch to the map of +// available body producers. +// +// For buffered requests, this setting override any `Content-Type` header possibly set by calling [Request.SetHeaderParam]. +// +// For streamed requests, users may want more flexibility, as we enter custom territory, with use-cases not supported by OpenAPI v2. +// +// The `Content-Type` header of a streamed request is defined using the following sequence: +// +// 1. if the caller sets an explicit value already in header — the user set it via +// [Request.SetHeaderParam] during WriteToRequest, and we treat that as an intentional escape hatch +// 2. use payload's [runtime.ContentTyper] declaration (in this case, the produced payload knows its content type) +// 3. use `application/octet-stream` if it is available in the registered producers +// 4. otherwise set the picker's mediaType +// +// For multi-part requests, the content type of each part is auto-detected using the following sequence: +// +// 1. use [runtime.ContentTyper] declaration (in this case, the file payload knows its content type) +// 2. use [http.DetectContentType] on the first 512 bytes of the file +// +// # Concurrency +// +// A [Request] is a disposable object that is NOT intended to be reused or called concurrently. +// +// # Future evolutions +// +// There might be other similar structs that convert to other transports. +type Request struct { + pathPattern string + method string + writer runtime.ClientRequestWriter + + pathParams map[string]string + header http.Header + query url.Values + formFields url.Values + fileFields map[string][]runtime.NamedReadCloser + payload any + // consumes carries the operation's full ConsumesMediaTypes list so + // that buildHTTP — which runs after the writer populates the payload + // — can apply payload-aware fallback rules (see streamFallbackMime). + // + // This is set by Runtime.createHttpRequest. + consumes []string + timeout time.Duration + buf *bytes.Buffer + + getBody func(r *Request) []byte +} + +// New creates a new http client [Request] to handle OpenAPI v2 parameters. +func New(method, pathPattern string, writer runtime.ClientRequestWriter) *Request { + return &Request{ + pathPattern: pathPattern, + method: method, + writer: writer, + header: make(http.Header), + query: make(url.Values), + timeout: 0, + getBody: getRequestBuffer, + } +} + +// GetMethod yields the method being used. +func (r *Request) GetMethod() string { + return r.method +} + +// GetPath yields the URL path being used. +func (r *Request) GetPath() string { + pth := r.pathPattern + for k, v := range r.pathParams { + pth = strings.ReplaceAll(pth, "{"+k+"}", v) + } + + return pth +} + +// GetBody returns the request body, if any. +// +// For streaming requests, this is a copy of the original [io.Reader]. +func (r *Request) GetBody() []byte { + return r.getBody(r) +} + +// SetHeaderParam adds a header parameter to the request. +// +// The header key is always canonicalized. +// +// - when there is only 1 value provided, it will set it. +// - when there are several values provided, it will add all of those (no overriding). +func (r *Request) SetHeaderParam(name string, values ...string) error { + if r.header == nil { + r.header = make(http.Header) + } + r.header[http.CanonicalHeaderKey(name)] = values + + return nil +} + +// GetHeaderParams returns all headers currently set for the request. +func (r *Request) GetHeaderParams() http.Header { + return r.header +} + +// SetQueryParam adds a query parameter to the request. +// +// - when there is only 1 value provided, it will set it. +// - when there are several values provided, it will add all of those (no overriding). +func (r *Request) SetQueryParam(name string, values ...string) error { + if r.query == nil { + r.query = make(url.Values) + } + r.query[name] = values + + return nil +} + +// GetQueryParams returns a copy of all query params currently set for the request. +func (r *Request) GetQueryParams() url.Values { + result := make(url.Values, len(r.query)) + for key, values := range r.query { + result[key] = append([]string{}, values...) + } + + return result +} + +// SetFormParam adds a form param to the request. +// +// - when there is only 1 value provided, it will set it. +// - when there are several values provided, it will add all of those (no overriding). +func (r *Request) SetFormParam(name string, values ...string) error { + if r.formFields == nil { + r.formFields = make(url.Values) + } + r.formFields[name] = values + + return nil +} + +// SetPathParam adds a path param to the request. +func (r *Request) SetPathParam(name string, value string) error { + if r.pathParams == nil { + r.pathParams = make(map[string]string) + } + + r.pathParams[name] = value + + return nil +} + +// SetFileParam adds a file parameter to the request. +// +// Files must implement [runtime.NamedReadCloser]. +// +// [runtime.File] is proposed as the default concrete implementation. +func (r *Request) SetFileParam(name string, files ...runtime.NamedReadCloser) error { + for _, file := range files { + if actualFile, ok := file.(*os.File); ok { + fi, err := os.Stat(actualFile.Name()) + if err != nil { + return err + } + + if fi.IsDir() { + return fmt.Errorf("%q is a directory, only files are supported", file.Name()) + } + } + } + + if r.fileFields == nil { + r.fileFields = make(map[string][]runtime.NamedReadCloser) + } + + if r.formFields == nil { + r.formFields = make(url.Values) + } + + r.fileFields[name] = files + + return nil +} + +// GetFileParam yields all file parameters. +func (r *Request) GetFileParam() map[string][]runtime.NamedReadCloser { + return r.fileFields +} + +// SetBodyParam sets a body parameter on the request. +// +// This does not yet serialize the object: actual serialization happens as late as possible. +func (r *Request) SetBodyParam(payload any) error { + r.payload = payload + + return nil +} + +// GetBodyParam returns the body payload. +func (r *Request) GetBodyParam() any { + return r.payload +} + +// GetTimeout sets the timeout for a request. +func (r *Request) GetTimeout() time.Duration { + return r.timeout +} + +// SetTimeout sets the timeout for a request. +func (r *Request) SetTimeout(timeout time.Duration) error { + r.timeout = timeout + + return nil +} + +// SetConsumes sets the list of registered consumed content for a request. +func (r *Request) SetConsumes(consumers []string) { + r.consumes = consumers +} + +// BuildHTTPContext binds the request parameters and returns a ready-to-send [http.Request]. +// +// Dispatch picks one of two end-to-end builders based on whether: +// +// - the body source is a stream (multipart pipe or stream payload) +// - or a buffer (urlencoded form, producer output, or no body) +// +// It starts by writing the request, then proceed with adding authentication, +// then finally assembling URL or header parameters. +// +// The split mirrors the auth question: streaming bodies require a lazy body-copy closure during [AuthenticateRequest], +// whereas buffered bodies do not. +// +// The returned [http.Request] carries a context derived from parentCtx that: +// +// - inherits any deadline or cancellation already set on parentCtx; +// - additionally honors the per-request timeout set via [Request.SetTimeout] +// (the [runtime.ClientRequestWriter] may override the runtime default during +// WriteToRequest, which is why the derivation happens here rather than +// at the call site). +// +// The returned cancel must be invoked by the caller (typically deferred) +// once the response has been fully read; otherwise resources held by the +// derived context — including any timeout timer — are leaked. +// +// On error the cancel is invoked internally and a no-op cancel is returned, +// so callers can defer cancel unconditionally. +func (r *Request) BuildHTTPContext(parentCtx context.Context, mediaType, basePath string, + producers map[string]runtime.Producer, registry strfmt.Registry, auth runtime.ClientAuthInfoWriter, +) (*http.Request, context.CancelFunc, error) { + if err := r.writer.WriteToRequest(r, registry); err != nil { + return nil, noop, err + } + + ctx, cancel := deriveRequestContext(parentCtx, r.timeout) + r.buf = bytes.NewBuffer(nil) + + var ( + httpReq *http.Request + err error + ) + if r.usesStreamingBody(mediaType) { + httpReq, err = r.buildStreamingRequest(ctx, mediaType, basePath, producers, registry, auth) + } else { + httpReq, err = r.buildBufferedRequest(ctx, mediaType, basePath, producers, registry, auth) + } + if err != nil { + cancel() + return nil, noop, err + } + return httpReq, cancel, nil +} + +func noop() {} + +// deriveRequestContext returns a child of parent bounded by timeout. +// If timeout == 0 the child is only canceled when the caller invokes +// cancel; any deadline already on parent is preserved. If timeout > 0 +// the child uses the shortest of timeout and parent's existing deadline. +func deriveRequestContext(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc) { + if timeout == 0 { + return context.WithCancel(parent) + } + return context.WithTimeout(parent, timeout) +} + +// usesStreamingBody reports whether the request body must be assembled +// as a stream (an io.Pipe for multipart, or the payload's own reader +// for stream payloads). +// +// The complementary case is a fully buffered body in r.buf — urlencoded form, producer output, or no body at all. +func (r *Request) usesStreamingBody(mediaType string) bool { + if (len(r.formFields) > 0 || len(r.fileFields) > 0) && r.isMultipart(mediaType) { + return true + } + + if r.payload != nil { + if _, ok := r.payload.(io.Reader); ok { + return true + } + } + + return false +} + +func (r *Request) isMultipart(mediaType string) bool { + // Strip media-type parameters before comparing: callers may legally + // pass `multipart/form-data; boundary=…` or + // `application/x-www-form-urlencoded; charset=utf-8` per RFC 7231, + // and a bare-string compare would route those to the wrong flow. + // + // mime.ParseMediaType lowercases the type/subtype and is + // case-insensitive on input, so plain == against our (lowercase) + // constants is sufficient on the happy path. + base, _, err := mime.ParseMediaType(mediaType) + if err != nil { + // Malformed mediaType: only the file-presence shortcut can + // fire — by definition we cannot recognize either canonical + // form mime in unparseable input. + return len(r.fileFields) > 0 + } + + // An explicit application/x-www-form-urlencoded choice is honored even when + // file fields are present: the spec allows files to travel as URL-encoded + // form values, although it does not stream and is discouraged. Without this + // short-circuit, picking urlencoded with files would silently fall back to + // multipart and emit an inconsistent Content-Type. + if base == runtime.URLencodedFormMime { + return false + } + + if len(r.fileFields) > 0 { + return true + } + + return base == runtime.MultipartFormMime +} + +// buildBufferedRequest assembles a request whose body is fully +// buffered in r.buf before AuthenticateRequest runs — urlencoded form, +// producer-serialized payload, or no body. +// +// Auth is trivial in this flow because the buffer is already populated when the auth helper +// asks for the body via r.GetBody(). +func (r *Request) buildBufferedRequest(ctx context.Context, mediaType, basePath string, + producers map[string]runtime.Producer, registry strfmt.Registry, auth runtime.ClientAuthInfoWriter, +) (*http.Request, error) { + var body io.Reader + var err error + + switch { + case len(r.formFields) > 0 || len(r.fileFields) > 0: + body, err = r.writeURLEncodedBody(mediaType) + case r.payload != nil: + body, err = r.writeNonStreamPayload(mediaType, producers) + } + if err != nil { + return nil, err + } + + if runtime.CanHaveBody(r.method) && body != nil && r.header.Get(runtime.HeaderContentType) == "" { + r.header.Set(runtime.HeaderContentType, mediaType) + } + + if auth != nil { + if err := auth.AuthenticateRequest(r, registry); err != nil { + return nil, err + } + } + + return r.assembleRequest(ctx, basePath, body) +} + +// buildStreamingRequest assembles a request whose body is a stream — +// either an io.Pipe filled by the multipart goroutine, or the +// payload's own io.Reader. +// +// AuthenticateRequest consumes the body lazily through the getBody closure installed by +// applyAuthWithBodyCopy, which buffers the stream into r.buf so the http.Request can use the buffered copy. +// +// On any error path before the http.Request takes ownership of body, we close the body to release +// the underlying resource. +// +// For multipart this unblocks the spawned writer goroutine +// (it would otherwise park forever on pw.Write with no reader). +// +// For stream payloads it closes the user-provided io.ReadCloser. +func (r *Request) buildStreamingRequest(ctx context.Context, mediaType, basePath string, + producers map[string]runtime.Producer, registry strfmt.Registry, auth runtime.ClientAuthInfoWriter, +) (req *http.Request, retErr error) { + var body io.Reader + if len(r.formFields) > 0 || len(r.fileFields) > 0 { + body = r.writeMultipartBody(ctx, mediaType) + } else { + body = r.writeStreamPayload(mediaType, producers) + } + + defer func() { + if retErr == nil { + return + } + if c, ok := body.(io.Closer); ok { + _ = c.Close() + } + }() + + if runtime.CanHaveBody(r.method) && body != nil && r.header.Get(runtime.HeaderContentType) == "" { + r.header.Set(runtime.HeaderContentType, mediaType) + } + + body, err := r.applyAuthWithBodyCopy(auth, body, registry) + if err != nil { + return nil, err + } + + return r.assembleRequest(ctx, basePath, body) +} + +// assembleRequest is the shared tail of both flows: build the URL +// path, create the http.Request, merge static query parameters, and +// finalize headers/query. +func (r *Request) assembleRequest(ctx context.Context, basePath string, body io.Reader) (*http.Request, error) { + urlPath, staticQueryParams, err := r.resolveURLPath(basePath) + if err != nil { + return nil, err + } + + req, err := http.NewRequestWithContext(ctx, r.method, urlPath, body) + if err != nil { + return nil, err + } + + if err := r.mergeStaticQuery(staticQueryParams); err != nil { + return nil, err + } + + req.URL.RawQuery = r.query.Encode() + req.Header = r.header + + return req, nil +} + +// resolveURLPath builds the final url path string and returns the static +// query parameters extracted from basePath and r.pathPattern. +// +// Static query parameters from the path pattern take precedence over those +// from the base path; merging with r.query is the caller's responsibility +// (see [request.mergeStaticQuery]). +// +// The path is assembled from basePath + pathPattern with path-param +// substitution and trailing-slash preservation when the original +// pathPattern carried one. +func (r *Request) resolveURLPath(basePath string) (string, url.Values, error) { + basePathURL, err := url.Parse(basePath) + if err != nil { + return "", nil, err + } + staticQueryParams := basePathURL.Query() + + pathPatternURL, err := url.Parse(r.pathPattern) + if err != nil { + return "", nil, err + } + for name, values := range pathPatternURL.Query() { + if _, present := staticQueryParams[name]; present { + staticQueryParams.Del(name) + } + for _, value := range values { + staticQueryParams.Add(name, value) + } + } + + // path.Join strips trailing slashes; reinstate one whenever the + // pathPattern carried it, including the bare-root case ("/" under a + // non-empty basePath, which path.Join would collapse to "/basepath"). + // The HasSuffix check on urlPath keeps the rewrite idempotent and + // avoids producing "//" when basePath is "/" or empty. + reinstateSlash := strings.HasSuffix(pathPatternURL.Path, "/") + + urlPath := path.Join(basePathURL.Path, pathPatternURL.Path) + for k, v := range r.pathParams { + urlPath = strings.ReplaceAll(urlPath, "{"+k+"}", url.PathEscape(v)) + } + if reinstateSlash && !strings.HasSuffix(urlPath, "/") { + urlPath += "/" + } + + return urlPath, staticQueryParams, nil +} + +// applyAuthWithBodyCopy runs auth.AuthenticateRequest for the +// streaming flow, where the http.Request body is a pipe or a payload +// reader rather than r.buf. If AuthenticateRequest asks for the body +// via r.GetBody(), the lazy closure copies the stream into r.buf on +// demand and reassigns body to r.buf so the post-auth source passed +// to http.NewRequestWithContext is the buffered copy. +// +// The closure is registered lazily because there is no way to know +// ahead of time whether AuthenticateRequest will read the body. +// +// On error precedence: a copy error is reported in preference to the +// AuthenticateRequest error, because a mis-read body may have +// interfered with auth. +// +// No-op when auth is nil; returns body unchanged. +func (r *Request) applyAuthWithBodyCopy(auth runtime.ClientAuthInfoWriter, body io.Reader, registry strfmt.Registry) (io.Reader, error) { + if auth == nil { + return body, nil + } + + var copyErr error + var copied bool + r.getBody = func(r *Request) []byte { + if copied { + return getRequestBuffer(r) + } + + defer func() { + copied = true + }() + + if _, copyErr = io.Copy(r.buf, body); copyErr != nil { + return nil + } + + if closer, ok := body.(io.ReadCloser); ok { + if copyErr = closer.Close(); copyErr != nil { + return nil + } + } + + body = r.buf + return getRequestBuffer(r) + } + + authErr := auth.AuthenticateRequest(r, registry) + + // On error we return body alongside the error so the caller's + // cleanup defer (in buildStreamingRequest) can close the + // underlying pipe/stream. Caller treats body as ignorable when + // err != nil per Go convention; the defer reads it via closure. + if copyErr != nil { + return body, fmt.Errorf("error copying the request body: %w", copyErr) + } + + if authErr != nil { + return body, authErr + } + + return body, nil +} + +// mergeStaticQuery overlays staticQuery onto r.query. On conflict r.query +// wins — the parameters set by the client take precedence over the ones +// extracted from basePath / pathPattern. +func (r *Request) mergeStaticQuery(staticQuery url.Values) error { + originalParams := r.GetQueryParams() + for k, v := range staticQuery { + if _, present := originalParams[k]; present { + continue + } + if err := r.SetQueryParam(k, v...); err != nil { + return err + } + } + return nil +} + +// writeURLEncodedBody serializes form fields (and any file fields, per +// Swagger 2.0 fallback semantics) into r.buf as +// application/x-www-form-urlencoded. Sets Content-Type to mediaType and +// returns r.buf as the body source. +// +// Per Swagger 2.0, file form parameters can be sent under +// application/x-www-form-urlencoded by including the file content as a +// regular form-field value. The whole form is then percent-encoded as +// usual. This buffers the entire payload and does not preserve a +// per-file Content-Type — multipart/form-data is preferred when both +// are advertised by the operation. +func (r *Request) writeURLEncodedBody(mediaType string) (io.Reader, error) { + r.header.Set(runtime.HeaderContentType, mediaType) + values := url.Values{} + for k, vs := range r.formFields { + values[k] = append(values[k], vs...) + } + for fn, ff := range r.fileFields { + for _, fi := range ff { + data, ferr := io.ReadAll(fi) + if cerr := fi.Close(); cerr != nil && ferr == nil { + ferr = cerr + } + if ferr != nil { + return nil, ferr + } + values.Add(fn, string(data)) + } + } + r.buf.WriteString(values.Encode()) + return r.buf, nil +} + +// writeMultipartBody assembles a multipart/form-data body via an +// io.Pipe. A goroutine streams form fields and files into the pipe +// writer; the pipe reader is returned as the body. Sets Content-Type to +// the multipart media type with the writer's boundary parameter. +// +// The goroutine owns the pipe writer's lifecycle: it closes the +// multipart writer (flushing the closing boundary) and the pipe writer +// when it finishes or hits an error. +func (r *Request) writeMultipartBody(ctx context.Context, mediaType string) io.Reader { + pr, pw := io.Pipe() + mp := multipart.NewWriter(pw) + r.header.Set(runtime.HeaderContentType, mangleContentType(mediaType, mp.Boundary())) + + go r.streamMultipartParts(ctx, mp, pw) + + return pr +} + +// streamMultipartParts writes form fields then file fields to mp, +// closing mp and pw when done. +// +// Errors are reported by closing pw with the error so the consumer of pr observes them on its next Read. +// +// Context cancellation is observed at iteration boundaries (between +// fields and between files) and during file copy via a context-aware +// reader. When ctx is canceled the pipe writer is closed with ctx.Err() +// so the body consumer surfaces the cancellation as the read error. +func (r *Request) streamMultipartParts(ctx context.Context, mp *multipart.Writer, pw *io.PipeWriter) { + defer func() { + mp.Close() + pw.Close() + }() + + for fn, v := range r.formFields { + for _, vi := range v { + if err := ctx.Err(); err != nil { + _ = pw.CloseWithError(err) + return + } + if err := mp.WriteField(fn, vi); err != nil { + logClose(err, pw) + return + } + } + } + + defer func() { + for _, ff := range r.fileFields { + for _, ffi := range ff { + ffi.Close() + } + } + }() + + for fn, f := range r.fileFields { + for _, fi := range f { + if err := ctx.Err(); err != nil { + _ = pw.CloseWithError(err) + return + } + + var fileContentType string + if p, ok := fi.(runtime.ContentTyper); ok { + fileContentType = p.ContentType() + } else { + // Need to read the data so that we can detect the content type + const contentTypeBufferSize = 512 + buf := make([]byte, contentTypeBufferSize) + size, err := fi.Read(buf) + if err != nil && !errors.Is(err, io.EOF) { + logClose(err, pw) + return + } + fileContentType = http.DetectContentType(buf) + fi = runtime.NamedReader(fi.Name(), io.MultiReader(bytes.NewReader(buf[:size]), fi)) + } + + // Create the MIME headers for the new part + h := make(textproto.MIMEHeader) + h.Set("Content-Disposition", + fmt.Sprintf(`form-data; name="%s"; filename="%s"`, + escapeQuotes(fn), escapeQuotes(filepath.Base(fi.Name())))) + h.Set("Content-Type", fileContentType) + + wrtr, err := mp.CreatePart(h) + if err != nil { + logClose(err, pw) + return + } + if _, err := io.Copy(wrtr, &ctxReader{ctx: ctx, r: fi}); err != nil { + logClose(err, pw) + return + } + } + } +} + +// ctxReader wraps an [io.Reader] with a context check on each Read. Once +// ctx is done, subsequent Reads return ctx.Err() instead of delegating +// to the underlying reader. It does not preempt a Read already in flight +// — that is the source's responsibility (e.g. *os.File honors Close from +// another goroutine, network sources honor SetDeadline). +type ctxReader struct { + ctx context.Context //nolint:containedctx // io.Reader's Read method has no ctx parameter, so the wrapper must carry it on the struct + r io.Reader +} + +func (cr *ctxReader) Read(p []byte) (int, error) { + if err := cr.ctx.Err(); err != nil { + return 0, err + } + return cr.r.Read(p) +} + +// writeStreamPayload handles a stream payload (io.Reader / +// io.ReadCloser). The bytes flow through verbatim — no producer is +// invoked. The wire Content-Type is resolved via setStreamContentType +// (priority: existing header, payload's ContentTyper, +// streamFallbackMime, mediaType). +// +// Caller must ensure r.payload satisfies io.Reader (see +// [request.usesStreamingBody]). +func (r *Request) writeStreamPayload(mediaType string, producers map[string]runtime.Producer) io.Reader { + setStreamContentType(r.header, r.payload, mediaType, r.consumes, producers) + if rdr, ok := r.payload.(io.ReadCloser); ok { + return rdr + } + + rdr, ok := r.payload.(io.Reader) + if !ok { + panic("internal error: payload expected to be an io.Reader") // guaranteed by earlier checks + } + + return rdr +} + +// writeNonStreamPayload runs the producer registered for mediaType +// against r.payload, writing into r.buf. The Content-Type header +// reflects the picker. +// +// SetHeaderParam("Content-Type", …) is intentionally NOT honored on +// the producer path because the producer is dispatched off mediaType — +// the wire header would otherwise misrepresent the body. +// +// The same reasoning applies to the form/multipart branch. +func (r *Request) writeNonStreamPayload(mediaType string, producers map[string]runtime.Producer) (io.Reader, error) { + r.header.Set(runtime.HeaderContentType, mediaType) + producer, ok := producers[mediaType] + if !ok { + return nil, fmt.Errorf("no producer registered for content type %q (register one with Runtime.Producers)", mediaType) + } + + if err := producer.Produce(r.buf, r.payload); err != nil { + return nil, err + } + return r.buf, nil +} + +var quoter = strings.NewReplacer( + "\\", "\\\\", + `"`, "\\\"", + "\r", "_", + "\n", "_", +) + +// escapeQuotes escapes backslash and double-quote for embedding in a +// quoted-string Content-Disposition parameter value, and rewrites +// CR / LF to '_' to prevent header-injection through attacker-influenced +// field names or filenames. +// +// RFC 7578 §4.2 limits parameter values to printable characters; this +// is the conservative subset relevant to security (control characters +// that would split the header line into a forged header or part). +// Mirrors the known stdlib gap golang/go#19038. +func escapeQuotes(s string) string { + return quoter.Replace(s) +} + +// setStreamContentType resolves and writes the wire Content-Type for a +// stream payload (io.Reader / io.ReadCloser). Priority: +// +// 1. an explicit value already in header — the user set it via +// SetHeaderParam during [ClientRequestWriter.WriteToRequest], and we treat that as an +// intentional escape hatch; +// 2. payload's [runtime.ContentTyper] declaration; +// 3. [streamFallbackMime] (Stage-2 octet-stream upgrade); +// 4. the picker's mediaType (passed in as the chain's terminal +// fallback). +// +// Does not apply to non-stream payloads or to form/multipart bodies — +// see the comment above the call site in [request.buildHTTP]. +func setStreamContentType( + header http.Header, + payload any, + mediaType string, + candidates []string, + producers map[string]runtime.Producer, +) { + if header.Get(runtime.HeaderContentType) != "" { + return + } + fallback := streamFallbackMime(mediaType, candidates, producers) + header.Set(runtime.HeaderContentType, payloadContentType(payload, fallback)) +} + +// payloadContentType returns the payload's declared content type when +// it implements [runtime.ContentTyper] with a non-empty result, and +// fallback otherwise. Mirrors the per-file convention already used for +// multipart upload parts (see [request.buildHTTP] file-fields branch). +func payloadContentType(payload any, fallback string) string { + if t, ok := payload.(runtime.ContentTyper); ok { + if ct := t.ContentType(); ct != "" { + return ct + } + } + + return fallback +} + +// streamFallbackMime selects a wire content-type for a stream payload +// (io.Reader / io.ReadCloser) that has neither implemented +// `ContentType() string` nor declared an explicit value. +// +// The picker (Stage 1) ran without seeing the payload, so its choice +// may be wildly wrong for raw bytes — e.g. picking application/json +// for a payload that is just a stream of opaque data. When the +// candidate consumes list also offers application/octet-stream and +// the runtime has an octet-stream producer registered, that's a +// safer wire type than the picker's choice: it advertises "raw bytes" +// rather than making a structural claim about the body. +// +// If octet-stream is unavailable in either the candidate list or the +// producer set, the picker's choice is preserved. The wire header +// then continues to misrepresent the body — but no correct +// alternative exists and we cannot infer one without more +// information from the caller. +func streamFallbackMime(picked string, candidates []string, producers map[string]runtime.Producer) string { + if strings.EqualFold(picked, runtime.DefaultMime) { + return picked + } + + for _, c := range candidates { + if strings.EqualFold(c, runtime.DefaultMime) { + if _, ok := producers[runtime.DefaultMime]; ok { + return runtime.DefaultMime + } + } + } + + return picked +} + +func getRequestBuffer(r *Request) []byte { + if r.buf == nil { + return nil + } + return r.buf.Bytes() +} + +func logClose(err error, pw *io.PipeWriter) { + log.Println(err) + closeErr := pw.CloseWithError(err) + if closeErr != nil { + log.Println(closeErr) + } +} + +func mangleContentType(mediaType, boundary string) string { + _ = mediaType // reserved for future enhancement: honor caller-provided media type + // Proposal for enhancement: honor caller's boundary if specified + return "multipart/form-data; boundary=" + boundary +} diff --git a/vendor/github.com/go-openapi/runtime/client/keepalive.go b/vendor/github.com/go-openapi/runtime/client/keepalive.go index 3bac5e272cf..6b6097d206f 100644 --- a/vendor/github.com/go-openapi/runtime/client/keepalive.go +++ b/vendor/github.com/go-openapi/runtime/client/keepalive.go @@ -34,20 +34,20 @@ func (k *keepAliveTransport) RoundTrip(r *http.Request) (*http.Response, error) type drainingReadCloser struct { rdr io.ReadCloser - seenEOF uint32 + seenEOF atomic.Uint32 } func (d *drainingReadCloser) Read(p []byte) (n int, err error) { n, err = d.rdr.Read(p) if err == io.EOF || n == 0 { - atomic.StoreUint32(&d.seenEOF, 1) + d.seenEOF.Store(1) } return } func (d *drainingReadCloser) Close() error { // drain buffer - if atomic.LoadUint32(&d.seenEOF) != 1 { + if d.seenEOF.Load() != 1 { // If the reader side (a HTTP server) is misbehaving, it still may send // some bytes, but the closer ignores them to keep the underling // connection open. diff --git a/vendor/github.com/go-openapi/runtime/client/opentelemetry.go b/vendor/github.com/go-openapi/runtime/client/opentelemetry.go index 5054878c06c..e422f83cb12 100644 --- a/vendor/github.com/go-openapi/runtime/client/opentelemetry.go +++ b/vendor/github.com/go-openapi/runtime/client/opentelemetry.go @@ -4,18 +4,20 @@ package client import ( + "context" "fmt" "net/http" "strings" - "github.com/go-openapi/runtime" - "github.com/go-openapi/strfmt" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" semconv "go.opentelemetry.io/otel/semconv/v1.37.0" "go.opentelemetry.io/otel/trace" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" ) const ( @@ -23,6 +25,52 @@ const ( tracerName = "go-openapi" ) +// WithOpenTelemetry adds opentelemetry support to the provided runtime. +// A new client span is created for each request. +// The provided opts are applied to each spans - for example to add global tags. +// +// The returned transport satisfies [runtime.ContextualTransport]: callers +// should prefer [openTelemetryTransport.SubmitContext] over the +// legacy [runtime.ClientOperation.Context] field. Setting that +// field is still honored on the [openTelemetryTransport.Submit] +// compatibility path. +func (r *Runtime) WithOpenTelemetry(opts ...OpenTelemetryOpt) runtime.ContextualTransport { + return newOpenTelemetryTransport(r, r.Host, opts) +} + +// WithOpenTracing adds opentracing support to the provided runtime. +// A new client span is created for each request. +// If the context of the client operation does not contain an active span, no span is created. +// The provided opts are applied to each spans - for example to add global tags. +// +// Deprecated: use [WithOpenTelemetry] instead, as opentracing is now archived and superseded by opentelemetry. +// +// # Deprecation notice +// +// The [Runtime.WithOpenTracing] method has been deprecated in favor of [Runtime.WithOpenTelemetry]. +// +// The method is still around so programs calling it will still build. However, it will return +// an opentelemetry transport. +// +// If you have a strict requirement on using opentracing, you may still do so by importing +// module [github.com/go-openapi/runtime/client-[middleware]/opentracing] and using +// [github.com/go-openapi/runtime/client-[middleware]/opentracing.WithOpenTracing] with your +// usual opentracing options and opentracing-enabled transport. +// +// Passed options are ignored unless they are of type [OpenTelemetryOpt]. +func (r *Runtime) WithOpenTracing(opts ...any) runtime.ContextualTransport { + otelOpts := make([]OpenTelemetryOpt, 0, len(opts)) + for _, o := range opts { + otelOpt, ok := o.(OpenTelemetryOpt) + if !ok { + continue + } + otelOpts = append(otelOpts, otelOpt) + } + + return r.WithOpenTelemetry(otelOpts...) +} + type config struct { Tracer trace.Tracer Propagator propagation.TextMapPropagator @@ -113,11 +161,31 @@ func newOpenTelemetryTransport(transport runtime.ClientTransport, host string, o return tr } +// Submit implements [runtime.ClientTransport]. It honors the legacy +// [runtime.ClientOperation.Context] field for backward compatibility +// — that field is being phased out; new code should call +// [openTelemetryTransport.SubmitContext] directly with an explicit +// context. func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (any, error) { - if op.Context == nil { - return t.transport.Submit(op) + ctx := op.Context + if ctx == nil { + ctx = context.Background() } + return t.SubmitContext(ctx, op) +} +// SubmitContext submits an operation with an explicit context that +// drives both the tracing span and (when supported) the wrapped +// transport's SubmitContext call. The legacy +// [runtime.ClientOperation.Context] field is not consulted. +// +// When the wrapped transport implements [runtime.ContextualTransport], ctx is +// forwarded directly via its SubmitContext. Otherwise, the legacy +// Submit path is used: ctx is stamped onto op.Context for the +// duration of that call and restored afterwards, so the wrapped +// transport still receives a usable context. The legacy fallback +// disappears once SubmitContext is universal (v2). +func (t *openTelemetryTransport) SubmitContext(ctx context.Context, op *runtime.ClientOperation) (any, error) { params := op.Params reader := op.Reader @@ -129,7 +197,7 @@ func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (any, error }() op.Params = runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { - span = t.newOpenTelemetrySpan(op, req.GetHeaderParams()) + span = t.newOpenTelemetrySpan(ctx, op, req.GetHeaderParams()) return params.WriteToRequest(req, reg) }) @@ -149,7 +217,7 @@ func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (any, error return reader.ReadResponse(response, consumer) }) - submit, err := t.transport.Submit(op) + submit, err := t.submitWrapped(ctx, op) if err != nil && span != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) @@ -158,9 +226,18 @@ func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (any, error return submit, err } -func (t *openTelemetryTransport) newOpenTelemetrySpan(op *runtime.ClientOperation, header http.Header) trace.Span { - ctx := op.Context +//nolint:contextcheck // ctx is forwarded verbatim; the legacy Submit branch only stamps it onto op.Context for the wrapped transport. +func (t *openTelemetryTransport) submitWrapped(ctx context.Context, op *runtime.ClientOperation) (any, error) { + if sc, ok := t.transport.(runtime.ContextualTransport); ok { + return sc.SubmitContext(ctx, op) + } + prev := op.Context + op.Context = ctx + defer func() { op.Context = prev }() + return t.transport.Submit(op) +} +func (t *openTelemetryTransport) newOpenTelemetrySpan(ctx context.Context, op *runtime.ClientOperation, header http.Header) trace.Span { tracer := t.tracer if tracer == nil { if span := trace.SpanFromContext(ctx); span.SpanContext().IsValid() { diff --git a/vendor/github.com/go-openapi/runtime/client/request.go b/vendor/github.com/go-openapi/runtime/client/request.go deleted file mode 100644 index f16ee487bab..00000000000 --- a/vendor/github.com/go-openapi/runtime/client/request.go +++ /dev/null @@ -1,468 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package client - -import ( - "bytes" - "context" - "fmt" - "io" - "log" - "mime/multipart" - "net/http" - "net/textproto" - "net/url" - "os" - "path" - "path/filepath" - "strings" - "time" - - "github.com/go-openapi/runtime" - "github.com/go-openapi/strfmt" -) - -var _ runtime.ClientRequest = new(request) // ensure compliance to the interface - -// Request represents a swagger client request. -// -// This Request struct converts to a HTTP request. -// There might be others that convert to other transports. -// There is no error checking here, it is assumed to be used after a spec has been validated. -// so impossible combinations should not arise (hopefully). -// -// The main purpose of this struct is to hide the machinery of adding params to a transport request. -// The generated code only implements what is necessary to turn a param into a valid value for these methods. -type request struct { - pathPattern string - method string - writer runtime.ClientRequestWriter - - pathParams map[string]string - header http.Header - query url.Values - formFields url.Values - fileFields map[string][]runtime.NamedReadCloser - payload any - timeout time.Duration - buf *bytes.Buffer - - getBody func(r *request) []byte -} - -// NewRequest creates a new swagger http client request. -func newRequest(method, pathPattern string, writer runtime.ClientRequestWriter) *request { - return &request{ - pathPattern: pathPattern, - method: method, - writer: writer, - header: make(http.Header), - query: make(url.Values), - timeout: DefaultTimeout, - getBody: getRequestBuffer, - } -} - -// BuildHTTP creates a new http request based on the data from the params. -func (r *request) BuildHTTP(mediaType, basePath string, producers map[string]runtime.Producer, registry strfmt.Registry) (*http.Request, error) { - return r.buildHTTP(mediaType, basePath, producers, registry, nil) -} - -func (r *request) GetMethod() string { - return r.method -} - -func (r *request) GetPath() string { - path := r.pathPattern - for k, v := range r.pathParams { - path = strings.ReplaceAll(path, "{"+k+"}", v) - } - return path -} - -func (r *request) GetBody() []byte { - return r.getBody(r) -} - -// SetHeaderParam adds a header param to the request -// when there is only 1 value provided for the varargs, it will set it. -// when there are several values provided for the varargs it will add it (no overriding). -func (r *request) SetHeaderParam(name string, values ...string) error { - if r.header == nil { - r.header = make(http.Header) - } - r.header[http.CanonicalHeaderKey(name)] = values - return nil -} - -// GetHeaderParams returns the all headers currently set for the request. -func (r *request) GetHeaderParams() http.Header { - return r.header -} - -// SetQueryParam adds a query param to the request -// when there is only 1 value provided for the varargs, it will set it. -// when there are several values provided for the varargs it will add it (no overriding). -func (r *request) SetQueryParam(name string, values ...string) error { - if r.query == nil { - r.query = make(url.Values) - } - r.query[name] = values - return nil -} - -// GetQueryParams returns a copy of all query params currently set for the request. -func (r *request) GetQueryParams() url.Values { - var result = make(url.Values) - for key, value := range r.query { - result[key] = append([]string{}, value...) - } - return result -} - -// SetFormParam adds a forn param to the request -// when there is only 1 value provided for the varargs, it will set it. -// when there are several values provided for the varargs it will add it (no overriding). -func (r *request) SetFormParam(name string, values ...string) error { - if r.formFields == nil { - r.formFields = make(url.Values) - } - r.formFields[name] = values - return nil -} - -// SetPathParam adds a path param to the request. -func (r *request) SetPathParam(name string, value string) error { - if r.pathParams == nil { - r.pathParams = make(map[string]string) - } - - r.pathParams[name] = value - return nil -} - -// SetFileParam adds a file param to the request. -func (r *request) SetFileParam(name string, files ...runtime.NamedReadCloser) error { - for _, file := range files { - if actualFile, ok := file.(*os.File); ok { - fi, err := os.Stat(actualFile.Name()) - if err != nil { - return err - } - if fi.IsDir() { - return fmt.Errorf("%q is a directory, only files are supported", file.Name()) - } - } - } - - if r.fileFields == nil { - r.fileFields = make(map[string][]runtime.NamedReadCloser) - } - if r.formFields == nil { - r.formFields = make(url.Values) - } - - r.fileFields[name] = files - return nil -} - -func (r *request) GetFileParam() map[string][]runtime.NamedReadCloser { - return r.fileFields -} - -// SetBodyParam sets a body parameter on the request. -// This does not yet serialze the object, this happens as late as possible. -func (r *request) SetBodyParam(payload any) error { - r.payload = payload - return nil -} - -func (r *request) GetBodyParam() any { - return r.payload -} - -// SetTimeout sets the timeout for a request. -func (r *request) SetTimeout(timeout time.Duration) error { - r.timeout = timeout - return nil -} - -func (r *request) isMultipart(mediaType string) bool { - if len(r.fileFields) > 0 { - return true - } - - return runtime.MultipartFormMime == mediaType -} - -func (r *request) buildHTTP(mediaType, basePath string, producers map[string]runtime.Producer, registry strfmt.Registry, auth runtime.ClientAuthInfoWriter) (*http.Request, error) { //nolint:gocyclo,maintidx - // build the data - if err := r.writer.WriteToRequest(r, registry); err != nil { - return nil, err - } - - // Our body must be an io.Reader. - // When we create the http.Request, if we pass it a - // bytes.Buffer then it will wrap it in an io.ReadCloser - // and set the content length automatically. - var body io.Reader - var pr *io.PipeReader - var pw *io.PipeWriter - - r.buf = bytes.NewBuffer(nil) - if r.payload != nil || len(r.formFields) > 0 || len(r.fileFields) > 0 { - body = r.buf - if r.isMultipart(mediaType) { - pr, pw = io.Pipe() - body = pr - } - } - - // check if this is a form type request - if len(r.formFields) > 0 || len(r.fileFields) > 0 { - if !r.isMultipart(mediaType) { - r.header.Set(runtime.HeaderContentType, mediaType) - formString := r.formFields.Encode() - r.buf.WriteString(formString) - goto DoneChoosingBodySource - } - - mp := multipart.NewWriter(pw) - r.header.Set(runtime.HeaderContentType, mangleContentType(mediaType, mp.Boundary())) - - go func() { - defer func() { - mp.Close() - pw.Close() - }() - - for fn, v := range r.formFields { - for _, vi := range v { - if err := mp.WriteField(fn, vi); err != nil { - logClose(err, pw) - return - } - } - } - - defer func() { - for _, ff := range r.fileFields { - for _, ffi := range ff { - ffi.Close() - } - } - }() - for fn, f := range r.fileFields { - for _, fi := range f { - var fileContentType string - if p, ok := fi.(interface { - ContentType() string - }); ok { - fileContentType = p.ContentType() - } else { - // Need to read the data so that we can detect the content type - const contentTypeBufferSize = 512 - buf := make([]byte, contentTypeBufferSize) - size, err := fi.Read(buf) - if err != nil && err != io.EOF { - logClose(err, pw) - return - } - fileContentType = http.DetectContentType(buf) - fi = runtime.NamedReader(fi.Name(), io.MultiReader(bytes.NewReader(buf[:size]), fi)) - } - - // Create the MIME headers for the new part - h := make(textproto.MIMEHeader) - h.Set("Content-Disposition", - fmt.Sprintf(`form-data; name="%s"; filename="%s"`, - escapeQuotes(fn), escapeQuotes(filepath.Base(fi.Name())))) - h.Set("Content-Type", fileContentType) - - wrtr, err := mp.CreatePart(h) - if err != nil { - logClose(err, pw) - return - } - if _, err := io.Copy(wrtr, fi); err != nil { - logClose(err, pw) - } - } - } - }() - - goto DoneChoosingBodySource - } - - // if there is payload, use the producer to write the payload, and then - // set the header to the content-type appropriate for the payload produced - if r.payload != nil { - // Enhancement proposal: https://github.com/go-openapi/runtime/issues/387 - r.header.Set(runtime.HeaderContentType, mediaType) - if rdr, ok := r.payload.(io.ReadCloser); ok { - body = rdr - goto DoneChoosingBodySource - } - - if rdr, ok := r.payload.(io.Reader); ok { - body = rdr - goto DoneChoosingBodySource - } - - producer := producers[mediaType] - if err := producer.Produce(r.buf, r.payload); err != nil { - return nil, err - } - } - -DoneChoosingBodySource: - - if runtime.CanHaveBody(r.method) && body != nil && r.header.Get(runtime.HeaderContentType) == "" { - r.header.Set(runtime.HeaderContentType, mediaType) - } - - if auth != nil { - // If we're not using r.buf as our http.Request's body, - // either the payload is an io.Reader or io.ReadCloser, - // or we're doing a multipart form/file. - // - // In those cases, if the AuthenticateRequest call asks for the body, - // we must read it into a buffer and provide that, then use that buffer - // as the body of our http.Request. - // - // This is done in-line with the GetBody() request rather than ahead - // of time, because there's no way to know if the AuthenticateRequest - // will even ask for the body of the request. - // - // If for some reason the copy fails, there's no way to return that - // error to the GetBody() call, so return it afterwards. - // - // An error from the copy action is prioritized over any error - // from the AuthenticateRequest call, because the mis-read - // body may have interfered with the auth. - // - var copyErr error - if buf, ok := body.(*bytes.Buffer); body != nil && (!ok || buf != r.buf) { - var copied bool - r.getBody = func(r *request) []byte { - if copied { - return getRequestBuffer(r) - } - - defer func() { - copied = true - }() - - if _, copyErr = io.Copy(r.buf, body); copyErr != nil { - return nil - } - - if closer, ok := body.(io.ReadCloser); ok { - if copyErr = closer.Close(); copyErr != nil { - return nil - } - } - - body = r.buf - return getRequestBuffer(r) - } - } - - authErr := auth.AuthenticateRequest(r, registry) - - if copyErr != nil { - return nil, fmt.Errorf("error retrieving the response body: %v", copyErr) - } - - if authErr != nil { - return nil, authErr - } - } - - // In case the basePath or the request pathPattern include static query parameters, - // parse those out before constructing the final path. The parameters themselves - // will be merged with the ones set by the client, with the priority given first to - // the ones set by the client, then the path pattern, and lastly the base path. - basePathURL, err := url.Parse(basePath) - if err != nil { - return nil, err - } - staticQueryParams := basePathURL.Query() - - pathPatternURL, err := url.Parse(r.pathPattern) - if err != nil { - return nil, err - } - for name, values := range pathPatternURL.Query() { - if _, present := staticQueryParams[name]; present { - staticQueryParams.Del(name) - } - for _, value := range values { - staticQueryParams.Add(name, value) - } - } - - // create http request - var reinstateSlash bool - if pathPatternURL.Path != "" && pathPatternURL.Path != "/" && pathPatternURL.Path[len(pathPatternURL.Path)-1] == '/' { - reinstateSlash = true - } - - urlPath := path.Join(basePathURL.Path, pathPatternURL.Path) - for k, v := range r.pathParams { - urlPath = strings.ReplaceAll(urlPath, "{"+k+"}", url.PathEscape(v)) - } - if reinstateSlash { - urlPath += "/" - } - - req, err := http.NewRequestWithContext(context.Background(), r.method, urlPath, body) - if err != nil { - return nil, err - } - - originalParams := r.GetQueryParams() - - // Merge the query parameters extracted from the basePath with the ones set by - // the client in this struct. In case of conflict, the client wins. - for k, v := range staticQueryParams { - _, present := originalParams[k] - if !present { - if err = r.SetQueryParam(k, v...); err != nil { - return nil, err - } - } - } - - req.URL.RawQuery = r.query.Encode() - req.Header = r.header - - return req, nil -} - -func escapeQuotes(s string) string { - return strings.NewReplacer("\\", "\\\\", `"`, "\\\"").Replace(s) -} - -func getRequestBuffer(r *request) []byte { - if r.buf == nil { - return nil - } - return r.buf.Bytes() -} - -func logClose(err error, pw *io.PipeWriter) { - log.Println(err) - closeErr := pw.CloseWithError(err) - if closeErr != nil { - log.Println(closeErr) - } -} - -func mangleContentType(mediaType, boundary string) string { - if strings.ToLower(mediaType) == runtime.URLencodedFormMime { - return fmt.Sprintf("%s; boundary=%s", mediaType, boundary) - } - return "multipart/form-data; boundary=" + boundary -} diff --git a/vendor/github.com/go-openapi/runtime/client/runtime.go b/vendor/github.com/go-openapi/runtime/client/runtime.go index eeb17dfb24e..b890f9f4133 100644 --- a/vendor/github.com/go-openapi/runtime/client/runtime.go +++ b/vendor/github.com/go-openapi/runtime/client/runtime.go @@ -5,25 +5,19 @@ package client import ( "context" - "crypto" - "crypto/ecdsa" - "crypto/rsa" - "crypto/tls" - "crypto/x509" - "encoding/pem" - "errors" "fmt" "mime" "net/http" "net/http/httputil" - "os" "strings" "sync" "time" "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/client/internal/request" "github.com/go-openapi/runtime/logger" "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/server-middleware/mediatype" "github.com/go-openapi/runtime/yamlpc" "github.com/go-openapi/strfmt" ) @@ -36,184 +30,6 @@ const ( // DefaultTimeout the default request timeout. var DefaultTimeout = 30 * time.Second -// TLSClientOptions to configure client authentication with mutual TLS. -type TLSClientOptions struct { - // Certificate is the path to a PEM-encoded certificate to be used for - // client authentication. If set then Key must also be set. - Certificate string - - // LoadedCertificate is the certificate to be used for client authentication. - // This field is ignored if Certificate is set. If this field is set, LoadedKey - // is also required. - LoadedCertificate *x509.Certificate - - // Key is the path to an unencrypted PEM-encoded private key for client - // authentication. This field is required if Certificate is set. - Key string - - // LoadedKey is the key for client authentication. This field is required if - // LoadedCertificate is set. - LoadedKey crypto.PrivateKey - - // CA is a path to a PEM-encoded certificate that specifies the root certificate - // to use when validating the TLS certificate presented by the server. If this field - // (and LoadedCA) is not set, the system certificate pool is used. This field is ignored if LoadedCA - // is set. - CA string - - // LoadedCA specifies the root certificate to use when validating the server's TLS certificate. - // If this field (and CA) is not set, the system certificate pool is used. - LoadedCA *x509.Certificate - - // LoadedCAPool specifies a pool of RootCAs to use when validating the server's TLS certificate. - // If set, it will be combined with the other loaded certificates (see LoadedCA and CA). - // If neither LoadedCA or CA is set, the provided pool with override the system - // certificate pool. - // The caller must not use the supplied pool after calling TLSClientAuth. - LoadedCAPool *x509.CertPool - - // ServerName specifies the hostname to use when verifying the server certificate. - // If this field is set then InsecureSkipVerify will be ignored and treated as - // false. - ServerName string - - // InsecureSkipVerify controls whether the certificate chain and hostname presented - // by the server are validated. If true, any certificate is accepted. - InsecureSkipVerify bool - - // VerifyPeerCertificate, if not nil, is called after normal - // certificate verification. It receives the raw ASN.1 certificates - // provided by the peer and also any verified chains that normal processing found. - // If it returns a non-nil error, the handshake is aborted and that error results. - // - // If normal verification fails then the handshake will abort before - // considering this callback. If normal verification is disabled by - // setting InsecureSkipVerify then this callback will be considered but - // the verifiedChains argument will always be nil. - VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error - - // VerifyConnection, if not nil, is called after normal certificate - // verification and after [TLSClientOptions.VerifyPeerCertificate] by either a TLS client or - // server. It receives the [tls.ConnectionState] which may be inspected. - // - // Unlike VerifyPeerCertificate, this callback is invoked on every - // connection, including resumed ones, making it suitable for checks - // that must always apply (e.g. certificate pinning). - // - // If it returns a non-nil error, the handshake is aborted and that error results. - VerifyConnection func(tls.ConnectionState) error - - // SessionTicketsDisabled may be set to true to disable session ticket and - // PSK (resumption) support. Note that on clients, session ticket support is - // also disabled if ClientSessionCache is nil. - SessionTicketsDisabled bool - - // ClientSessionCache is a cache of ClientSessionState entries for TLS - // session resumption. It is only used by clients. - ClientSessionCache tls.ClientSessionCache - - // Prevents callers using unkeyed fields. - _ struct{} -} - -// TLSClientAuth creates a [tls.Config] for mutual auth. -func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) { - // create client tls config - cfg := &tls.Config{ - MinVersion: tls.VersionTLS12, - } - - // load client cert if specified - if opts.Certificate != "" { - cert, err := tls.LoadX509KeyPair(opts.Certificate, opts.Key) - if err != nil { - return nil, fmt.Errorf("tls client cert: %v", err) - } - cfg.Certificates = []tls.Certificate{cert} - } else if opts.LoadedCertificate != nil { - block := pem.Block{Type: "CERTIFICATE", Bytes: opts.LoadedCertificate.Raw} - certPem := pem.EncodeToMemory(&block) - - var keyBytes []byte - switch k := opts.LoadedKey.(type) { - case *rsa.PrivateKey: - keyBytes = x509.MarshalPKCS1PrivateKey(k) - case *ecdsa.PrivateKey: - var err error - keyBytes, err = x509.MarshalECPrivateKey(k) - if err != nil { - return nil, fmt.Errorf("tls client priv key: %v", err) - } - default: - return nil, errors.New("tls client priv key: unsupported key type") - } - - block = pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes} - keyPem := pem.EncodeToMemory(&block) - - cert, err := tls.X509KeyPair(certPem, keyPem) - if err != nil { - return nil, fmt.Errorf("tls client cert: %v", err) - } - cfg.Certificates = []tls.Certificate{cert} - } - - cfg.InsecureSkipVerify = opts.InsecureSkipVerify - - cfg.VerifyPeerCertificate = opts.VerifyPeerCertificate - cfg.VerifyConnection = opts.VerifyConnection - cfg.SessionTicketsDisabled = opts.SessionTicketsDisabled - cfg.ClientSessionCache = opts.ClientSessionCache - - // When no CA certificate is provided, default to the system cert pool - // that way when a request is made to a server known by the system trust store, - // the name is still verified - switch { - case opts.LoadedCA != nil: - caCertPool := basePool(opts.LoadedCAPool) - caCertPool.AddCert(opts.LoadedCA) - cfg.RootCAs = caCertPool - case opts.CA != "": - // load ca cert - caCert, err := os.ReadFile(opts.CA) - if err != nil { - return nil, fmt.Errorf("tls client ca: %v", err) - } - caCertPool := basePool(opts.LoadedCAPool) - caCertPool.AppendCertsFromPEM(caCert) - cfg.RootCAs = caCertPool - case opts.LoadedCAPool != nil: - cfg.RootCAs = opts.LoadedCAPool - } - - // apply servername overrride - if opts.ServerName != "" { - cfg.InsecureSkipVerify = false - cfg.ServerName = opts.ServerName - } - - return cfg, nil -} - -// TLSTransport creates a [http] client transport suitable for mutual [tls] auth. -func TLSTransport(opts TLSClientOptions) (http.RoundTripper, error) { - cfg, err := TLSClientAuth(opts) - if err != nil { - return nil, err - } - - return &http.Transport{TLSClientConfig: cfg}, nil -} - -// TLSClient creates a [http.Client] for mutual auth. -func TLSClient(opts TLSClientOptions) (*http.Client, error) { - transport, err := TLSTransport(opts) - if err != nil { - return nil, err - } - return &http.Client{Transport: transport}, nil -} - // Runtime represents an API client that uses the transport // to make [http] requests based on a swagger specification. type Runtime struct { @@ -228,17 +44,50 @@ type Runtime struct { Host string BasePath string Formats strfmt.Registry - Context context.Context //nolint:containedctx // we precisely want this type to contain the request context + // Deprecated: prefer [runtime.ContextualTransport.SubmitContext] to pass the request context explicitly. + Context context.Context //nolint:containedctx // we precisely want this type to contain the request context + + Debug bool + + // Trace enables connection-level diagnostic output via + // [net/http/httptrace]. When true, the runtime narrates the + // connection lifecycle of every request through r.logger.Debugf: + // DNS, dial, TLS handshake, idle-pool reuse, request body + // transfer, time-to-first-byte, response body transfer, and a + // trailing per-request summary line. + // + // Trace is orthogonal to Debug: Debug dumps wire bytes (request + // and response headers and body), Trace narrates how the + // connection got there. Both may be enabled independently. + // + // Trace is not coupled to the SWAGGER_DEBUG / DEBUG environment + // variables: it defaults to false and is only enabled by + // explicit assignment. + // + // Trace is primarily intended as a problem-investigation tool + // (the local equivalent of curl -vvv), not an always-on tracer. + // For distributed-trace correlation, use the OpenTelemetry + // integration ([Runtime.WithOpenTelemetry]). + Trace bool - Debug bool logger logger.Logger + // MatchSuffix enables RFC 6839 structured-syntax suffix tolerance + // for codec lookup. When true, a response with Content-Type + // "application/problem+json" finds the JSON consumer registered + // under "application/json"; with the default false, the lookup + // is strict and falls through to the "*/*" wildcard if present. + // See [mediatype.AllowSuffix] for the semantics. + MatchSuffix bool + clientOnce *sync.Once client *http.Client schemes []string response ClientResponseFunc } +var _ runtime.ContextualTransport = &Runtime{} + // New creates a new default runtime for a swagger api runtime.Client. func New(host, basePath string, schemes []string) *Runtime { var rt Runtime @@ -246,13 +95,15 @@ func New(host, basePath string, schemes []string) *Runtime { // Enhancement proposal: https://github.com/go-openapi/runtime/issues/385 rt.Consumers = map[string]runtime.Consumer{ - runtime.YAMLMime: yamlpc.YAMLConsumer(), - runtime.JSONMime: runtime.JSONConsumer(), - runtime.XMLMime: runtime.XMLConsumer(), - runtime.TextMime: runtime.TextConsumer(), - runtime.HTMLMime: runtime.TextConsumer(), - runtime.CSVMime: runtime.CSVConsumer(), - runtime.DefaultMime: runtime.ByteStreamConsumer(), + runtime.YAMLMime: yamlpc.YAMLConsumer(), + runtime.JSONMime: runtime.JSONConsumer(), + runtime.XMLMime: runtime.XMLConsumer(), + runtime.TextMime: runtime.TextConsumer(), + runtime.HTMLMime: runtime.TextConsumer(), + runtime.CSVMime: runtime.CSVConsumer(), + runtime.MultipartFormMime: runtime.ByteStreamConsumer(), + runtime.URLencodedFormMime: runtime.ByteStreamConsumer(), + runtime.DefaultMime: runtime.ByteStreamConsumer(), } rt.Producers = map[string]runtime.Producer{ runtime.YAMLMime: yamlpc.YAMLProducer(), @@ -294,47 +145,6 @@ func NewWithClient(host, basePath string, schemes []string, client *http.Client) return rt } -// WithOpenTracing adds opentracing support to the provided runtime. -// A new client span is created for each request. -// If the context of the client operation does not contain an active span, no span is created. -// The provided opts are applied to each spans - for example to add global tags. -// -// Deprecated: use [WithOpenTelemetry] instead, as opentracing is now archived and superseded by opentelemetry. -// -// # Deprecation notice -// -// The [Runtime.WithOpenTracing] method has been deprecated in favor of [Runtime.WithOpenTelemetry]. -// -// The method is still around so programs calling it will still build. However, it will return -// an opentelemetry transport. -// -// If you have a strict requirement on using opentracing, you may still do so by importing -// module [github.com/go-openapi/runtime/client-[middleware]/opentracing] and using -// [github.com/go-openapi/runtime/client-[middleware]/opentracing.WithOpenTracing] with your -// usual opentracing options and opentracing-enabled transport. -// -// Passed options are ignored unless they are of type [OpenTelemetryOpt]. -func (r *Runtime) WithOpenTracing(opts ...any) runtime.ClientTransport { - otelOpts := make([]OpenTelemetryOpt, 0, len(opts)) - for _, o := range opts { - otelOpt, ok := o.(OpenTelemetryOpt) - if !ok { - continue - } - otelOpts = append(otelOpts, otelOpt) - } - - return r.WithOpenTelemetry(otelOpts...) -} - -// WithOpenTelemetry adds opentelemetry support to the provided runtime. -// A new client span is created for each request. -// If the context of the client operation does not contain an active span, no span is created. -// The provided opts are applied to each spans - for example to add global tags. -func (r *Runtime) WithOpenTelemetry(opts ...OpenTelemetryOpt) runtime.ClientTransport { - return newOpenTelemetryTransport(r, r.Host, opts) -} - // EnableConnectionReuse drains the remaining body from a response // so that go will reuse the TCP connections. // @@ -357,105 +167,109 @@ func (r *Runtime) EnableConnectionReuse() { ) } +// CreateHTTPRequestContext creates the requests and bind the parameters, but does not send it over the wire +// like [Runtime.SubmitContext]. +// +// The [http.Request] is complete with authentication, headers and body (including streamed body) and ready for callers +// to submit it to a [http.Client] of their choice, then consume the [http.Response]. +// +// Most users would simply use [Runtime.SubmitContext], which wraps all these operations in one call. +func (r *Runtime) CreateHTTPRequestContext(ctx context.Context, operation *runtime.ClientOperation) (req *http.Request, cancel context.CancelFunc, err error) { + req, cancel, err = r.createHTTPRequestContext(ctx, operation) + return +} + +// CreateHttpRequest builds the [http.Request] for the given operation, using +// [context.Background] as the request context. +// +// Any per-operation timeout declared by the operation's [runtime.ClientRequestWriter] +// is silently ignored here, which can leak a context-cancellation channel if the +// caller relies on it. +// +// Deprecated: use [Runtime.CreateHTTPRequestContext] instead, with explicit +// control over the request context and its cancellation. func (r *Runtime) CreateHttpRequest(operation *runtime.ClientOperation) (req *http.Request, err error) { //nolint:revive - _, req, err = r.createHttpRequest(operation) + req, _, err = r.createHTTPRequestContext(context.Background(), operation) return } // Submit a request and when there is a body on success it will turn that into the result // all other things are turned into an api error for swagger which retains the status code. +// +// This call inherits the context possibly put in the operation, otherwise the one possibly put in the [Runtime]. +// If none are set, use [context.Background]. +// +// Any timeout set by parameters is honored. func (r *Runtime) Submit(operation *runtime.ClientOperation) (any, error) { - _, readResponse, _ := operation.Params, operation.Reader, operation.AuthInfo + return r.SubmitContext(r.ensureContext(operation), operation) +} - request, req, err := r.createHttpRequest(operation) +// SubmitContext submits a request and returns the result. +// +// Errors are turned into an api error for swagger which retains the status code. +// +// Unlike [Submit], [SubmitContext] only injects the context provided by the caller: +// contexts possibly cached in operation or runtime are ignored. +// +// On the other hand, a timeout set by parameters is honored. +func (r *Runtime) SubmitContext(parentCtx context.Context, operation *runtime.ClientOperation) (any, error) { + req, cancel, err := r.createHTTPRequestContext(parentCtx, operation) if err != nil { return nil, err } + defer cancel() - r.clientOnce.Do(func() { - r.client = &http.Client{ - Transport: r.Transport, - Jar: r.Jar, - } - }) - - if r.Debug { - b, err2 := httputil.DumpRequestOut(req, true) - if err2 != nil { - return nil, err2 - } - r.logger.Debugf("%s\n", string(b)) - } + r.ensureClient() - var parentCtx context.Context - switch { - case operation.Context != nil: - parentCtx = operation.Context - case r.Context != nil: - parentCtx = r.Context - default: - parentCtx = context.Background() + if err := r.dumpRequest(req); err != nil { + return nil, err } - var ( - ctx context.Context - cancel context.CancelFunc - ) - if request.timeout == 0 { - // There may be a deadline in the context passed to the operation. - // Otherwise, there is no timeout set. - ctx, cancel = context.WithCancel(parentCtx) - } else { - // Sets the timeout passed from request params (by default runtime.DefaultTimeout). - // If there is already a deadline in the parent context, the shortest will - // apply. - ctx, cancel = context.WithTimeout(parentCtx, request.timeout) + // Attach the trace session before Do so the httptrace hooks + // fire during the round-trip. The session emits its trailing + // summary on finish; the response body is consumed by + // ReadResponse downstream, after which finish is called. + var trace *traceSession + if r.Trace { + trace = newTraceSession(r.logger, req.Method, req.URL.String(), + introspectTLSConfig(r.pickClient(operation))) + //nolint:contextcheck // We intentionally derive from req.Context() to layer the trace hooks onto the existing request context. + req = req.WithContext(trace.attach(req.Context())) + if req.Body != nil { + req.Body = trace.wrapRequestBody(req.Body) + } + defer trace.finish() } - defer cancel() - var client *http.Client - if operation.Client != nil { - client = operation.Client - } else { - client = r.client - } - req = req.WithContext(ctx) - res, err := client.Do(req) // make requests, by default follows 10 redirects before failing + res, err := r.pickClient(operation).Do(req) if err != nil { + if trace != nil { + trace.onRoundTripError(err) + } return nil, err } defer res.Body.Close() + if trace != nil { + trace.onResponse(res.StatusCode) + res.Body = trace.wrapResponseBody(res.Body) + } + ct := res.Header.Get(runtime.HeaderContentType) if ct == "" { // this should really never occur ct = r.DefaultMediaType } - if r.Debug { - printBody := true - if ct == runtime.DefaultMime { - printBody = false // Spare the terminal from a binary blob. - } - b, err2 := httputil.DumpResponse(res, printBody) - if err2 != nil { - return nil, err2 - } - r.logger.Debugf("%s\n", string(b)) + if err := r.dumpResponse(res, ct); err != nil { + return nil, err } - mt, _, err := mime.ParseMediaType(ct) + cons, err := r.resolveConsumer(ct) if err != nil { - return nil, fmt.Errorf("parse content type: %s", err) + return nil, err } - cons, ok := r.Consumers[mt] - if !ok { - if cons, ok = r.Consumers["*/*"]; !ok { - // scream about not knowing what to do - return nil, fmt.Errorf("no consumer: %q", ct) - } - } - return readResponse.ReadResponse(r.response(res), cons) + return operation.Reader.ReadResponse(r.response(res), cons) } // SetDebug changes the debug flag. @@ -482,6 +296,17 @@ func (r *Runtime) SetResponseReader(f ClientResponseFunc) { r.response = f } +func (r *Runtime) ensureContext(operation *runtime.ClientOperation) context.Context { + switch { + case operation.Context != nil: //nolint:staticcheck // kept for backward compatibility + return operation.Context + case r.Context != nil: + return r.Context + default: + return context.Background() + } +} + func (r *Runtime) pickScheme(schemes []string) string { if v := r.selectScheme(r.schemes); v != "" { return v @@ -518,16 +343,121 @@ func transportOrDefault(left, right http.RoundTripper) http.RoundTripper { return left } -// takes a client operation and creates equivalent http.Request. -func (r *Runtime) createHttpRequest(operation *runtime.ClientOperation) (*request, *http.Request, error) { //nolint:revive +// ensureClient lazily initializes r.client from r.Transport and r.Jar +// on first use. Safe under concurrent calls via sync.Once. +func (r *Runtime) ensureClient() { + r.clientOnce.Do(func() { + r.client = &http.Client{ + Transport: r.Transport, + Jar: r.Jar, + } + }) +} + +// pickClient returns the http.Client to use for this operation: the +// per-operation override if set, else the runtime's shared client. +func (r *Runtime) pickClient(operation *runtime.ClientOperation) *http.Client { + if operation.Client != nil { + return operation.Client + } + return r.client +} + +// dumpRequest writes the outgoing request to the debug logger when +// r.Debug is enabled. No-op otherwise. Returns the dump error so the +// caller can decide whether to abort the submit. +func (r *Runtime) dumpRequest(req *http.Request) error { + if !r.Debug { + return nil + } + b, err := httputil.DumpRequestOut(req, true) + if err != nil { + return err + } + r.logger.Debugf("%s\n", string(b)) + return nil +} + +// dumpResponse writes the incoming response to the debug logger when +// r.Debug is enabled. The body is omitted for runtime.DefaultMime +// (binary blob). No-op otherwise. +func (r *Runtime) dumpResponse(res *http.Response, ct string) error { + if !r.Debug { + return nil + } + printBody := ct != runtime.DefaultMime // Spare the terminal from a binary blob. + b, err := httputil.DumpResponse(res, printBody) + if err != nil { + return err + } + r.logger.Debugf("%s\n", string(b)) + return nil +} + +// resolveConsumer parses ct and returns the registered Consumer for +// that media type. Lookup is alias-aware (RFC 9512 §2.1 — yaml +// aliases) and, when [Runtime.MatchSuffix] is true, also tolerates +// RFC 6839 structured-syntax suffix media types (+json, +xml, +yaml). +// Falls back to the "*/*" entry if no match found. +func (r *Runtime) resolveConsumer(ct string) (runtime.Consumer, error) { + if _, _, err := mime.ParseMediaType(ct); err != nil { + return nil, fmt.Errorf("parse content type: %w", err) + } + if cons, ok := mediatype.Lookup(r.Consumers, ct, r.matchOpts()...); ok { + return cons, nil + } + if cons, ok := r.Consumers["*/*"]; ok { + return cons, nil + } + // scream about not knowing what to do + return nil, fmt.Errorf("no consumer: %q", ct) +} + +// matchOpts builds the mediatype.MatchOption slice for codec +// lookups on the Runtime, currently just the AllowSuffix opt-in. +func (r *Runtime) matchOpts() []mediatype.MatchOption { + if !r.MatchSuffix { + return nil + } + + return []mediatype.MatchOption{mediatype.AllowSuffix()} +} + +// createHTTPRequestContext is the context-aware builder of a [http.Request]. +// +// The returned [http.Request] carries a context derived from parentCtx that +// honors the per-request timeout set during WriteToRequest. Callers must +// invoke cancel once the response is fully read. +func (r *Runtime) createHTTPRequestContext(parentCtx context.Context, operation *runtime.ClientOperation) (*http.Request, context.CancelFunc, error) { + req, cmt, auth, err := r.prepareRequest(operation) + if err != nil { + return nil, nil, err + } + + httpReq, cancel, err := req.BuildHTTPContext(parentCtx, cmt, r.BasePath, r.Producers, r.Formats, auth) + if err != nil { + return nil, nil, err + } + + r.applyHostScheme(httpReq, operation) + + return httpReq, cancel, nil +} + +// prepareRequest performs the operation-to-request setup that is +// independent of how the http.Request is finally assembled: parameters, +// headers, default authentication, and consumes-media-type selection. +func (r *Runtime) prepareRequest(operation *runtime.ClientOperation) (*request.Request, string, runtime.ClientAuthInfoWriter, error) { params, _, auth := operation.Params, operation.Reader, operation.AuthInfo - request := newRequest(operation.Method, operation.PathPattern, params) + req := request.New(operation.Method, operation.PathPattern, params) + _ = req.SetTimeout(DefaultTimeout) // the timeout may be overridden by ClientRequestWriter + req.SetConsumes(operation.ConsumesMediaTypes) accept := make([]string, 0, len(operation.ProducesMediaTypes)) accept = append(accept, operation.ProducesMediaTypes...) - if err := request.SetHeaderParam(runtime.HeaderAccept, accept...); err != nil { - return nil, nil, err + if err := req.SetHeaderParam(runtime.HeaderAccept, accept...); err != nil { + return nil, "", nil, err } if auth == nil && r.DefaultAuthentication != nil { @@ -538,39 +468,75 @@ func (r *Runtime) createHttpRequest(operation *runtime.ClientOperation) (*reques return r.DefaultAuthentication.AuthenticateRequest(req, reg) }) } - // if auth != nil { - // if err := auth.AuthenticateRequest(request, r.Formats); err != nil { - // return nil, err - // } - //} - - // Enhancement proposal: https://github.com/go-openapi/runtime/issues/386 - cmt := r.DefaultMediaType - for _, mediaType := range operation.ConsumesMediaTypes { - // Pick first non-empty media type - if mediaType != "" { - cmt = mediaType - break - } - } - if _, ok := r.Producers[cmt]; !ok && cmt != runtime.MultipartFormMime && cmt != runtime.URLencodedFormMime { - return nil, nil, fmt.Errorf("none of producers: %v registered. try %s", r.Producers, cmt) + cmt := pickConsumesMediaType(operation.ConsumesMediaTypes, r.Producers, r.DefaultMediaType, r.matchOpts()...) + if _, ok := mediatype.Lookup(r.Producers, cmt, r.matchOpts()...); !ok && cmt != runtime.MultipartFormMime && cmt != runtime.URLencodedFormMime { + return nil, "", nil, fmt.Errorf("none of producers: %v registered. try %s", r.Producers, cmt) } - req, err := request.buildHTTP(cmt, r.BasePath, r.Producers, r.Formats, auth) - if err != nil { - return nil, nil, err - } - req.URL.Scheme = r.pickScheme(operation.Schemes) - req.URL.Host = r.Host - req.Host = r.Host - return request, req, nil + return req, cmt, auth, nil } -func basePool(pool *x509.CertPool) *x509.CertPool { - if pool == nil { - return x509.NewCertPool() +// applyHostScheme stamps the runtime's host and the operation-selected +// scheme onto the freshly built http.Request. +func (r *Runtime) applyHostScheme(httpReq *http.Request, operation *runtime.ClientOperation) { + httpReq.URL.Scheme = r.pickScheme(operation.Schemes) + httpReq.URL.Host = r.Host + httpReq.Host = r.Host +} + +// pickConsumesMediaType selects which Content-Type the client will send. +// +// Selection rules, in priority order: +// +// 1. multipart/form-data if any consumes entry advertises it (it streams +// and preserves per-file Content-Type, regardless of codegen ordering; +// resolves issue #286); +// 2. the first non-empty entry whose mime is either structural +// (multipart/form-data or application/x-www-form-urlencoded — these +// do not need a producer in the map) or has a producer registered in +// producers — this lets the client gracefully skip unregistered +// spec entries instead of erroring at the gate that follows; +// 3. the first non-empty entry overall (preserves the historical error +// path: the gate at the call site reports "none of producers" with +// the unregistered mime, so the diagnostic is unchanged when nothing +// in consumes is registered); +// 4. def, if consumes is empty or all empty strings. +// +// Step 2 closes part of issues #32 and #386: an operation declaring +// `consumes: [application/x-vendor, application/json]` with no vendor +// producer registered now silently uses JSON instead of erroring. +func pickConsumesMediaType(consumes []string, producers map[string]runtime.Producer, def string, opts ...mediatype.MatchOption) string { + for _, mt := range consumes { + if strings.EqualFold(mt, runtime.MultipartFormMime) { + return mt + } + } + var firstNonEmpty string + for _, mt := range consumes { + if mt == "" { + continue + } + if firstNonEmpty == "" { + firstNonEmpty = mt + } + if isStructuralMime(mt) { + return mt + } + if _, ok := mediatype.Lookup(producers, mt, opts...); ok { + return mt + } + } + if firstNonEmpty != "" { + return firstNonEmpty } - return pool + return def +} + +// isStructuralMime reports whether mt is a media type whose body shape +// is owned by the runtime (multipart envelope, urlencoded form). These +// do not require an entry in the producers map. +func isStructuralMime(mt string) bool { + return strings.EqualFold(mt, runtime.MultipartFormMime) || + strings.EqualFold(mt, runtime.URLencodedFormMime) } diff --git a/vendor/github.com/go-openapi/runtime/client/tls.go b/vendor/github.com/go-openapi/runtime/client/tls.go new file mode 100644 index 00000000000..017694fae08 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/tls.go @@ -0,0 +1,197 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package client + +import ( + "crypto" + "crypto/tls" + "crypto/x509" + "encoding/pem" + "fmt" + "net/http" + "os" +) + +// TLSClientOptions to configure client authentication with mutual TLS. +type TLSClientOptions struct { + // Certificate is the path to a PEM-encoded certificate to be used for + // client authentication. If set then Key must also be set. + Certificate string + + // LoadedCertificate is the certificate to be used for client authentication. + // This field is ignored if Certificate is set. If this field is set, LoadedKey + // is also required. + LoadedCertificate *x509.Certificate + + // Key is the path to an unencrypted PEM-encoded private key for client + // authentication. This field is required if Certificate is set. + Key string + + // LoadedKey is the key for client authentication. This field is required if + // LoadedCertificate is set. + LoadedKey crypto.PrivateKey + + // CA is a path to a PEM-encoded certificate that specifies the root certificate + // to use when validating the TLS certificate presented by the server. If this field + // (and LoadedCA) is not set, the system certificate pool is used. This field is ignored if LoadedCA + // is set. + CA string + + // LoadedCA specifies the root certificate to use when validating the server's TLS certificate. + // If this field (and CA) is not set, the system certificate pool is used. + LoadedCA *x509.Certificate + + // LoadedCAPool specifies a pool of RootCAs to use when validating the server's TLS certificate. + // If set, it will be combined with the other loaded certificates (see LoadedCA and CA). + // If neither LoadedCA or CA is set, the provided pool will override the system + // certificate pool. + // + // The caller must not use the supplied pool after calling TLSClientAuth. + LoadedCAPool *x509.CertPool + + // ServerName specifies the hostname to use when verifying the server certificate. + // If this field is set then InsecureSkipVerify will be ignored and treated as + // false. + ServerName string + + // InsecureSkipVerify controls whether the certificate chain and hostname presented + // by the server are validated. If true, any certificate is accepted. + InsecureSkipVerify bool + + // VerifyPeerCertificate, if not nil, is called after normal + // certificate verification. It receives the raw ASN.1 certificates + // provided by the peer and also any verified chains that normal processing found. + // If it returns a non-nil error, the handshake is aborted and that error results. + // + // If normal verification fails then the handshake will abort before + // considering this callback. If normal verification is disabled by + // setting InsecureSkipVerify then this callback will be considered but + // the verifiedChains argument will always be nil. + VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error + + // VerifyConnection, if not nil, is called after normal certificate + // verification and after [TLSClientOptions.VerifyPeerCertificate] by either a TLS client or + // server. It receives the [tls.ConnectionState] which may be inspected. + // + // Unlike VerifyPeerCertificate, this callback is invoked on every + // connection, including resumed ones, making it suitable for checks + // that must always apply (e.g. certificate pinning). + // + // If it returns a non-nil error, the handshake is aborted and that error results. + VerifyConnection func(tls.ConnectionState) error + + // SessionTicketsDisabled may be set to true to disable session ticket and + // PSK (resumption) support. Note that on clients, session ticket support is + // also disabled if ClientSessionCache is nil. + SessionTicketsDisabled bool + + // ClientSessionCache is a cache of ClientSessionState entries for TLS + // session resumption. It is only used by clients. + ClientSessionCache tls.ClientSessionCache + + // Prevents callers using unkeyed fields. + _ struct{} +} + +// TLSClientAuth creates a [tls.Config] for mutual auth. +func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) { + // create client tls config + cfg := &tls.Config{ + MinVersion: tls.VersionTLS12, + } + + // load client cert if specified + if opts.Certificate != "" { + cert, err := tls.LoadX509KeyPair(opts.Certificate, opts.Key) + if err != nil { + return nil, fmt.Errorf("tls client cert: %w", err) + } + cfg.Certificates = []tls.Certificate{cert} + } else if opts.LoadedCertificate != nil { + block := pem.Block{Type: "CERTIFICATE", Bytes: opts.LoadedCertificate.Raw} + certPem := pem.EncodeToMemory(&block) + + // PKCS#8 covers RSA, ECDSA, Ed25519, X25519 (the key types tls.X509KeyPair + // understands) and pairs with the canonical "PRIVATE KEY" PEM label. + keyBytes, err := x509.MarshalPKCS8PrivateKey(opts.LoadedKey) + if err != nil { + return nil, fmt.Errorf("tls client priv key: %w", err) + } + + block = pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes} + keyPem := pem.EncodeToMemory(&block) + + cert, err := tls.X509KeyPair(certPem, keyPem) + if err != nil { + return nil, fmt.Errorf("tls client cert: %w", err) + } + cfg.Certificates = []tls.Certificate{cert} + } + + cfg.InsecureSkipVerify = opts.InsecureSkipVerify + + cfg.VerifyPeerCertificate = opts.VerifyPeerCertificate + cfg.VerifyConnection = opts.VerifyConnection + cfg.SessionTicketsDisabled = opts.SessionTicketsDisabled + cfg.ClientSessionCache = opts.ClientSessionCache + + // When no CA certificate is provided, default to the system cert pool + // that way when a request is made to a server known by the system trust store, + // the name is still verified + switch { + case opts.LoadedCA != nil: + caCertPool := basePool(opts.LoadedCAPool) + caCertPool.AddCert(opts.LoadedCA) + cfg.RootCAs = caCertPool + case opts.CA != "": + // load ca cert + caCert, err := os.ReadFile(opts.CA) + if err != nil { + return nil, fmt.Errorf("tls client ca: %w", err) + } + caCertPool := basePool(opts.LoadedCAPool) + caCertPool.AppendCertsFromPEM(caCert) + cfg.RootCAs = caCertPool + case opts.LoadedCAPool != nil: + cfg.RootCAs = opts.LoadedCAPool + } + + // apply servername override + if opts.ServerName != "" { + cfg.InsecureSkipVerify = false + cfg.ServerName = opts.ServerName + } + + return cfg, nil +} + +// TLSTransport creates a [http.RoundTripper] for a client transport,suitable for mutual TLS auth. +func TLSTransport(opts TLSClientOptions) (http.RoundTripper, error) { + cfg, err := TLSClientAuth(opts) + if err != nil { + return nil, err + } + + return &http.Transport{TLSClientConfig: cfg}, nil +} + +// TLSClient creates a [http.Client] for mutual auth. +func TLSClient(opts TLSClientOptions) (*http.Client, error) { + transport, err := TLSTransport(opts) + if err != nil { + return nil, err + } + return &http.Client{Transport: transport}, nil +} + +// basePool returns pool if non-nil; otherwise it returns a new empty cert pool. +// +// Clones the pool provided up front by the caller. +func basePool(pool *x509.CertPool) *x509.CertPool { + if pool == nil { + return x509.NewCertPool() + } + + return pool.Clone() +} diff --git a/vendor/github.com/go-openapi/runtime/client_operation.go b/vendor/github.com/go-openapi/runtime/client_operation.go index ad7277e091f..61f6ead34a2 100644 --- a/vendor/github.com/go-openapi/runtime/client_operation.go +++ b/vendor/github.com/go-openapi/runtime/client_operation.go @@ -19,12 +19,30 @@ type ClientOperation struct { AuthInfo ClientAuthInfoWriter Params ClientRequestWriter Reader ClientResponseReader - Context context.Context //nolint:containedctx // we precisely want this type to contain the request context - Client *http.Client + // Deprecated: prefer [ContextualTransport.SubmitContext] to pass the request context explicitly. + Context context.Context //nolint:containedctx // we precisely want this type to contain the request context + Client *http.Client } // A ClientTransport implementor knows how to submit Request objects to some destination. type ClientTransport interface { - // Submit(string, RequestWriter, ResponseReader, AuthInfoWriter) (interface{}, error) + // Submit the operation and return the deserialized response or an error. Submit(*ClientOperation) (any, error) } + +// ContextualTransport extends [ClientTransport] with an explicit +// context-aware submission method. +// +// Wrappers such as the OpenTelemetry transport type-assert to this +// interface so they can forward an explicit context to the underlying +// transport without setting the cached [ClientOperation.Context] field. +// +// In v2, SubmitContext will be folded into [ClientTransport] itself +// and the cached [ClientOperation.Context] field removed; this interface +// is the v0.x bridge. +type ContextualTransport interface { + ClientTransport + + // SubmitContext submits the operation using ctx as the request context. + SubmitContext(ctx context.Context, operation *ClientOperation) (any, error) +} diff --git a/vendor/github.com/go-openapi/runtime/client_response.go b/vendor/github.com/go-openapi/runtime/client_response.go index 92668db4ece..7b4b7e40df7 100644 --- a/vendor/github.com/go-openapi/runtime/client_response.go +++ b/vendor/github.com/go-openapi/runtime/client_response.go @@ -59,7 +59,7 @@ func (o *APIError) Error() string { if err, ok := o.Response.(error); ok { resp = []byte("'" + sanitizer.Replace(err.Error()) + "'") } else { - resp, _ = json.Marshal(o.Response) + resp, _ = json.Marshal(o.Response) //nolint:errchkjson // error swallowed as this is our last best effort attempt } return fmt.Sprintf("%s (status %d): %s", o.OperationName, o.Code, resp) diff --git a/vendor/github.com/go-openapi/runtime/constants.go b/vendor/github.com/go-openapi/runtime/constants.go index 80de6c80868..ea86cfadbc1 100644 --- a/vendor/github.com/go-openapi/runtime/constants.go +++ b/vendor/github.com/go-openapi/runtime/constants.go @@ -21,8 +21,12 @@ const ( DefaultMime = "application/octet-stream" // JSONMime the json mime type. JSONMime = "application/json" - // YAMLMime the [yaml] mime type. - YAMLMime = "application/x-yaml" + // YAMLMime the [yaml] mime type. Set to the canonical RFC 9512 + // name (application/yaml). Legacy forms application/x-yaml, + // text/yaml, and text/x-yaml — per RFC 9512 §2.1 "Deprecated + // alias names for this type" — resolve to the same codec via + // the mediatype alias bridge. + YAMLMime = "application/yaml" // XMLMime the [xml] mime type. XMLMime = "application/xml" // TextMime the text mime type. diff --git a/vendor/github.com/go-openapi/runtime/csv.go b/vendor/github.com/go-openapi/runtime/csv.go index 558d0cb99aa..11d60872c3e 100644 --- a/vendor/github.com/go-openapi/runtime/csv.go +++ b/vendor/github.com/go-openapi/runtime/csv.go @@ -100,7 +100,7 @@ func CSVConsumer(opts ...CSVOpt) Consumer { default: // support *[][]string, *[]byte, *string - if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr { + if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Pointer { return errors.New("destination must be a pointer") } @@ -159,14 +159,14 @@ func CSVConsumer(opts ...CSVOpt) Consumer { // // Supported input underlying types and interfaces, prioritized in this order: // -// - *[csv.Reader] -// - [CSVReader] (reader options are ignored) -// - [io.Reader] -// - [io.WriterTo] -// - [encoding.BinaryMarshaler] -// - [][]string -// - []byte -// - string +// - *[csv.Reader] +// - [CSVReader] (reader options are ignored) +// - [io.Reader] +// - [io.WriterTo] +// - [encoding.BinaryMarshaler] +// - [][]string +// - []byte +// - string // // The producer prioritizes situations where buffering the input is not required. func CSVProducer(opts ...CSVOpt) Producer { diff --git a/vendor/github.com/go-openapi/runtime/file.go b/vendor/github.com/go-openapi/runtime/file.go index 2a85379a748..0420db9440a 100644 --- a/vendor/github.com/go-openapi/runtime/file.go +++ b/vendor/github.com/go-openapi/runtime/file.go @@ -5,4 +5,10 @@ package runtime import "github.com/go-openapi/swag/fileutils" +// File represents an uploaded file. Re-exported from +// [fileutils.File] for backwards compatibility. +// +// See [BindForm] (in form.go) for the orchestrator that parses +// multipart / urlencoded request bodies and binds declared file +// fields onto handler-side targets. type File = fileutils.File diff --git a/vendor/github.com/go-openapi/runtime/form.go b/vendor/github.com/go-openapi/runtime/form.go new file mode 100644 index 00000000000..213757f1f4c --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/form.go @@ -0,0 +1,362 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package runtime + +import ( + stderrors "errors" + "fmt" + "mime/multipart" + "net/http" + "strings" + + "github.com/go-openapi/errors" +) + +// DefaultMaxUploadFilenameLength is the default cap applied to +// FileHeader.Filename for each declared file when [BindForm] is invoked +// without an explicit [BindFormMaxFilenameLen] option. +// +// Multipart headers are allocated per part; an attacker submitting +// multi-MB filenames inflates the parser's memory footprint. 1 KiB +// matches the IETF guidance for sane filename length and is enough +// for realistic uploads. +const DefaultMaxUploadFilenameLength = 1024 + +// DefaultMaxUploadBodySize limits the size of the body to upload forms to 32MB. +// +// Use an explicit [BindFormMaxBody] option to change this limit. +const DefaultMaxUploadBodySize = int64(32) << 20 + +// filenamePreviewLen caps the byte length of the FileHeader.Filename +// preview embedded as the ParseError.Value field when the helper +// rejects a too-long filename. +const filenamePreviewLen = 32 + +// ValidateFilenameLength enforces the FileHeader.Filename length cap +// that [BindForm] applies via [BindFormFile] declarations. Untyped +// binder paths that fetch the file via [http.Request.FormFile] +// directly (rather than declaring the file through [BindFormFile]) call +// this to opt into the same protection. +// +// Returns nil if filename length is within maxLen or maxLen <= 0. +// Otherwise returns a [*errors.ParseError] suitable for direct return +// from a parameter binder. The error embeds a truncated preview of +// the offending filename to keep the error message bounded. +func ValidateFilenameLength(paramName, paramIn, filename string, maxLen int) error { + if maxLen <= 0 || len(filename) <= maxLen { + return nil + } + preview := filename[:min(len(filename), filenamePreviewLen)] + return errors.NewParseError(paramName, paramIn, preview, + fmt.Errorf("filename length %d exceeds limit %d", len(filename), maxLen)) +} + +// FileBinder is the per-file callback invoked by [BindForm] when a +// declared file field is present. +// +// The callback is responsible for BOTH validating the file (size, MIME, etc.) AND assigning the bound +// file to its destination — typically using: +// +// o.FieldName = &runtime.File{Data: file, Header: header} +// +// Returning a non-nil error surfaces the error in [BindForm]'s per-field +// accumulator. Errors from the binder flow through verbatim — the +// binder is expected to produce HTTP-aware errors (e.g. +// [errors.ExceedsMaximum] from go-openapi/validate). +type FileBinder func(file multipart.File, header *multipart.FileHeader) error + +// BindOption configures [BindForm]. The variadic style keeps simple +// call sites simple and lets new knobs (security caps, additional +// behaviour) be added without breaking the signature. +type BindOption func(*bindConfig) + +type multipartFormLimits struct { + maxBody int64 + maxFiles int + maxFilenameLen int +} + +type bindConfig struct { + multipartFormLimits + + maxParseMemory int64 + files []formFileSpec +} + +type formFileSpec struct { + name string + required bool + bind FileBinder +} + +// BindFormMaxParseMemory caps the in-memory portion of a multipart +// body. Bytes beyond this are spilled to temporary files on disk by +// the stdlib parser. 0 (the default) defers to the stdlib's 32 MB. +// +// This option does NOT cap total body bytes — see [BindFormMaxBody] +// for that. The default body cap ([DefaultMaxUploadBodySize] = 32 MB) +// is applied even when this option is not supplied, so out of the box +// [BindForm] is bounded; callers with stricter or looser requirements +// adjust via [BindFormMaxBody]. +func BindFormMaxParseMemory(n int64) BindOption { + return func(c *bindConfig) { c.maxParseMemory = n } +} + +// BindFormMaxBody caps the size of the body read from a http form before parsing. +// +// The limit is set to 32MB by default. This default limit is applied for any n=0. +// +// The limit is disabled for n<0, assuming the caller has already capped the body size upstream. +func BindFormMaxBody(n int64) BindOption { + return func(c *bindConfig) { c.maxBody = n } +} + +// BindFormMaxFiles rejects parses where the total number of file +// parts across all field names exceeds n. 0 (the default) means no +// cap. Exceeding the cap is a fatal error — [BindForm] returns +// fatal=true and no per-file binders run. +func BindFormMaxFiles(n int) BindOption { + return func(c *bindConfig) { c.maxFiles = n } +} + +// BindFormMaxFilenameLen rejects per-file headers whose Filename +// length exceeds n. 0 means no cap; the default applied when this +// option is not supplied is [DefaultMaxUploadFilenameLength]. The +// cap is a per-field bind error (non-fatal); other declared files +// still run. +func BindFormMaxFilenameLen(n int) BindOption { + return func(c *bindConfig) { c.maxFilenameLen = n } +} + +// BindFormFile declares a file field to bind under the given form +// name. If required is true and the field is absent, [BindForm] +// produces the per-field error. +// +// errors.NewParseError(name, "formData", "", http.ErrMissingFile) +// +// If required is false, absence is silent (no error, no bind). +// +// The bind callback runs only when the field is present. It is the +// site where both validation and assignment happen — see [FileBinder]. +// +// FileHeader.Filename is attacker-controlled text; the binder MUST +// NOT use it directly as a filesystem path. The helper does not +// touch the filesystem. +func BindFormFile(name string, required bool, bind FileBinder) BindOption { + return func(c *bindConfig) { + c.files = append(c.files, formFileSpec{ + name: name, + required: required, + bind: bind, + }) + } +} + +// BindForm parses r as multipart/form-data, falling back to +// application/x-www-form-urlencoded when the request is not +// multipart. On success, r.MultipartForm and r.PostForm are populated; +// the caller can read non-file form values via [Values](r.Form) after +// the call returns. +// +// All errors produced by BindForm itself (parse failure, missing +// required field, cap exceeded) are [*errors.ParseError] values built +// via [errors.NewParseError], matching the untyped +// middleware/parameter.go path. Errors returned by per-file binders +// flow through verbatim — binders own their HTTP-aware error shape. +// +// Per-file binders declared via [BindFormFile] run in declaration +// order after a successful parse. Their errors are accumulated and +// returned wrapped in [errors.CompositeValidationError]; the caller +// typically appends the returned err to its own []error and continues +// with non-file parameter binding. +// +// Return semantics: +// +// - fatal=true, err!=nil: parse failure or a hard cap (e.g. +// [BindFormMaxFiles]) was exceeded. No per-file binders ran; the +// caller MUST return err immediately. +// - fatal=false, err!=nil: one or more per-file binders produced +// errors. The form parsed successfully; r.Form is populated. The +// caller appends err to its accumulator and continues. +// - fatal=false, err==nil: full success. +// +// fatal==true implies err!=nil. +// +// Defaults applied out of the box: +// +// - Total body bytes capped at [DefaultMaxUploadBodySize] (32 MB) +// via [http.MaxBytesReader]. Adjust with [BindFormMaxBody] +// (negative n disables, when the caller has already capped the +// body upstream). +// - FileHeader.Filename length capped at +// [DefaultMaxUploadFilenameLength]. Adjust with +// [BindFormMaxFilenameLen]. +// +// Caller responsibilities the helper does NOT cover: +// +// - Set [http.Server.ReadTimeout] / [http.Server.IdleTimeout] to defend +// against slow-read attacks. +// - Decompress Content-Encoding: gzip request bodies upstream if +// the API accepts them, using a size-limited reader. +// - Treat FileHeader.Filename as untrusted user input; never use +// it directly as a filesystem path. +func BindForm(r *http.Request, opts ...BindOption) (fatal bool, err error) { + cfg := bindConfig{ + multipartFormLimits: multipartFormLimits{ + maxFilenameLen: DefaultMaxUploadFilenameLength, + }, + } + for _, opt := range opts { + opt(&cfg) + } + + if perr := parseFormBody(r, cfg.maxParseMemory, cfg.maxBody); perr != nil { + // Body-cap hit gets the 413 status; everything else maps to a + // 400 ParseError. parseFormBody returns the raw stdlib error + // in both cases — the HTTP-aware wrapping happens here. + var maxBytesErr *http.MaxBytesError + if stderrors.As(perr, &maxBytesErr) { + return true, errors.New(http.StatusRequestEntityTooLarge, "formData: %v", perr) + } + return true, errors.NewParseError("body", "formData", "", perr) + } + + if cfg.maxFiles > 0 { + if got := countFileParts(r); got > cfg.maxFiles { + return true, errors.NewParseError("body", "formData", "", + fmt.Errorf("multipart form contains %d file parts, exceeds limit %d", got, cfg.maxFiles)) + } + } + + var bindErrs []error + for _, spec := range cfg.files { + if e := bindFormFile(r, spec, cfg.maxFilenameLen); e != nil { + bindErrs = append(bindErrs, e) + } + } + if len(bindErrs) > 0 { + return false, errors.CompositeValidationError(bindErrs...) + } + return false, nil +} + +// parseFormBody parses the request body. Content-Type drives the +// parser: multipart/form-data → r.ParseMultipartForm, everything else +// → r.ParseForm (stdlib's parsePostForm only actually reads the body +// when Content-Type is application/x-www-form-urlencoded, so calling +// ParseForm is safe for unrecognised types). +// +// Caveat: ParseMultipartForm calls ParseForm internally and discards its error +// when the body turns out not to be multipart, returning ErrNotMultipart instead +// — the subsequent retry then short-circuits because r.PostForm is already +// set. Content-type-based routing avoids the lossy detour. +// +// Returns the raw stdlib error on failure; the caller (BindForm) +// handles HTTP-aware wrapping (413 for MaxBytesError, 400 ParseError +// otherwise). +// +// maxMemory == 0 falls through to the stdlib default (32 MB). +// maxBody == 0 defaults to DefaultMaxUploadBodySize; maxBody < 0 +// disables the body cap (caller has capped upstream). +func parseFormBody(r *http.Request, maxMemory, maxBody int64) error { + if r.Body != nil && maxBody >= 0 { + if maxBody == 0 { + maxBody = DefaultMaxUploadBodySize + } + r.Body = http.MaxBytesReader(nil, r.Body, maxBody) + } + + mt, _, _ := ContentType(r.Header) + if mt == MultipartFormMime { + //nolint:gosec // G120: false positive -- see below + // gosec doesn't track the Body. + // See https://github.com/securego/gosec/blob/de65614d10a6b84029e3e1215567b8ce7e490f23/testutils/g120_samples.go#L57 + return r.ParseMultipartForm(maxMemory) + } + return r.ParseForm() +} + +func countFileParts(r *http.Request) int { + if r.MultipartForm == nil { + return 0 + } + var n int + for _, fhs := range r.MultipartForm.File { + n += len(fhs) + } + + return n +} + +// FormFile resolves a file field from a parsed form body, transparently +// handling both content types accepted for `type: file` parameters by +// the OpenAPI 2.0 spec: +// +// - multipart/form-data — delegates to [http.Request.FormFile]. +// - application/x-www-form-urlencoded — looks up the field in +// r.PostForm and synthesizes a [multipart.File] backed by the +// value bytes plus a [multipart.FileHeader] with Filename equal +// to the field name and Size set to the byte length. +// +// Returns [http.ErrMissingFile] when the field is absent under either +// content type. Callers must have parsed the body upstream (e.g. via +// [BindForm] or [http.Request.ParseForm]) before reading from the +// urlencoded path — [http.Request.FormFile] takes care of parsing on +// the multipart path. +// +// Presence is the only criterion for binding a urlencoded file: an +// empty value (e.g. `file=`) is bound as a zero-byte file. +func FormFile(r *http.Request, name string) (multipart.File, *multipart.FileHeader, error) { + file, header, err := r.FormFile(name) + if err == nil { + return file, header, nil + } + if !stderrors.Is(err, http.ErrNotMultipart) { + return nil, nil, err + } + + values, present := r.PostForm[name] + if !present { + return nil, nil, http.ErrMissingFile + } + value := values[0] + return urlencodedFile{Reader: strings.NewReader(value)}, + &multipart.FileHeader{Filename: name, Size: int64(len(value))}, + nil +} + +// urlencodedFile adapts a urlencoded form value (already buffered in +// memory by [http.Request.ParseForm]) to the [multipart.File] +// interface. The embedded [strings.Reader] supplies Read/ReadAt/Seek; +// Close is a no-op since there is no resource to release. +type urlencodedFile struct { + *strings.Reader +} + +func (urlencodedFile) Close() error { return nil } + +func bindFormFile(r *http.Request, spec formFileSpec, maxFilenameLen int) error { + file, header, err := FormFile(r, spec.name) + if err != nil { + if stderrors.Is(err, http.ErrMissingFile) { + if spec.required { + return errors.New(http.StatusBadRequest, "formData: %v", http.ErrMissingFile) + } + + return nil + } + + return errors.NewParseError(spec.name, "formData", "", err) + } + + if err := ValidateFilenameLength(spec.name, "formData", header.Filename, maxFilenameLen); err != nil { + return err + } + + if spec.bind == nil { + return nil + } + + return spec.bind(file, header) +} diff --git a/vendor/github.com/go-openapi/runtime/go.work b/vendor/github.com/go-openapi/runtime/go.work index efa29dcac20..73479f9ad8f 100644 --- a/vendor/github.com/go-openapi/runtime/go.work +++ b/vendor/github.com/go-openapi/runtime/go.work @@ -1,6 +1,8 @@ use ( . ./client-middleware/opentracing + ./docs/examples + ./server-middleware ) go 1.25.0 diff --git a/vendor/github.com/go-openapi/runtime/go.work.sum b/vendor/github.com/go-openapi/runtime/go.work.sum deleted file mode 100644 index eaf8fddf6b9..00000000000 --- a/vendor/github.com/go-openapi/runtime/go.work.sum +++ /dev/null @@ -1,119 +0,0 @@ -github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/go-openapi/errors v0.22.2/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= -github.com/go-openapi/jsonpointer v0.22.0/go.mod h1:xt3jV88UtExdIkkL7NloURjRQjbeUgcxFblMjq2iaiU= -github.com/go-openapi/jsonreference v0.21.1/go.mod h1:PWs8rO4xxTUqKGu+lEvvCxD5k2X7QYkKAepJyCmSTT8= -github.com/go-openapi/swag v0.24.1/go.mod h1:sm8I3lCPlspsBBwUm1t5oZeWZS0s7m/A+Psg0ooRU0A= -github.com/go-openapi/swag/cmdutils v0.24.0/go.mod h1:uxib2FAeQMByyHomTlsP8h1TtPd54Msu2ZDU/H5Vuf8= -github.com/go-openapi/swag/conv v0.24.0/go.mod h1:jbn140mZd7EW2g8a8Y5bwm8/Wy1slLySQQ0ND6DPc2c= -github.com/go-openapi/swag/fileutils v0.24.0/go.mod h1:3SCrCSBHyP1/N+3oErQ1gP+OX1GV2QYFSnrTbzwli90= -github.com/go-openapi/swag/jsonname v0.24.0/go.mod h1:GXqrPzGJe611P7LG4QB9JKPtUZ7flE4DOVechNaDd7Q= -github.com/go-openapi/swag/jsonutils v0.24.0/go.mod h1:vBowZtF5Z4DDApIoxcIVfR8v0l9oq5PpYRUuteVu6f0= -github.com/go-openapi/swag/loading v0.24.0/go.mod h1:gShCN4woKZYIxPxbfbyHgjXAhO61m88tmjy0lp/LkJk= -github.com/go-openapi/swag/mangling v0.24.0/go.mod h1:Jm5Go9LHkycsz0wfoaBDkdc4CkpuSnIEf62brzyCbhc= -github.com/go-openapi/swag/netutils v0.24.0/go.mod h1:WRgiHcYTnx+IqfMCtu0hy9oOaPR0HnPbmArSRN1SkZM= -github.com/go-openapi/swag/stringutils v0.24.0/go.mod h1:5nUXB4xA0kw2df5PRipZDslPJgJut+NjL7D25zPZ/4w= -github.com/go-openapi/swag/typeutils v0.24.0/go.mod h1:q8C3Kmk/vh2VhpCLaoR2MVWOGP8y7Jc8l82qCTd1DYI= -github.com/go-openapi/swag/yamlutils v0.24.0/go.mod h1:DpKv5aYuaGm/sULePoeiG8uwMpZSfReo1HR3Ik0yaG8= -github.com/go-openapi/testify/enable/yaml/v2 v2.4.0/go.mod h1:14iV8jyyQlinc9StD7w1xVPW3CO3q1Gj04Jy//Kw4VM= -github.com/go-openapi/testify/v2 v2.4.0/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 h1:BHT1/DKsYDGkUgQ2jmMaozVcdk+sVfz0+1ZJq4zkWgw= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= -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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= -golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw= -golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= -golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= -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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/vendor/github.com/go-openapi/runtime/interfaces.go b/vendor/github.com/go-openapi/runtime/interfaces.go index a8b4b318d9c..85211989078 100644 --- a/vendor/github.com/go-openapi/runtime/interfaces.go +++ b/vendor/github.com/go-openapi/runtime/interfaces.go @@ -99,3 +99,25 @@ type Validatable interface { type ContextValidatable interface { ContextValidate(context.Context, strfmt.Registry) error } + +// ContentTyper is implemented by values that declare their own MIME +// content type. The client runtime consults it in two places: +// +// - on a body payload set via [SetBodyParam]: when the payload is a +// stream (io.Reader, io.ReadCloser) and ContentType returns a +// non-empty value, that value becomes the wire Content-Type +// header instead of the operation's picked consumes entry. +// +// - on individual file values inside a multipart upload: their per- +// part Content-Type header is taken from ContentType() rather +// than sniffed via http.DetectContentType. +// +// An empty string return is treated as "no opinion" and the runtime +// falls back to its default selection. Values that have no content +// type to declare may simply not implement the interface. +// +// See docs/MEDIA_TYPES.md for the full client-side selection +// algorithm. +type ContentTyper interface { + ContentType() string +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/context.go b/vendor/github.com/go-openapi/runtime/middleware/context.go index 1f85e86b538..12abfd4829d 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/context.go +++ b/vendor/github.com/go-openapi/runtime/middleware/context.go @@ -5,10 +5,9 @@ package middleware import ( stdContext "context" + stderrors "errors" "fmt" "net/http" - "net/url" - "path" "strings" "sync" @@ -17,19 +16,21 @@ import ( "github.com/go-openapi/loads" "github.com/go-openapi/spec" "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag/typeutils" "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/logger" "github.com/go-openapi/runtime/middleware/untyped" "github.com/go-openapi/runtime/security" + "github.com/go-openapi/runtime/server-middleware/docui" + "github.com/go-openapi/runtime/server-middleware/mediatype" + "github.com/go-openapi/runtime/server-middleware/negotiate" ) // Debug when true turns on verbose logging. var Debug = logger.DebugEnabled() // Logger is the standard library logger used for printing debug messages. -// -// (Note: The correct spelling is "library", not "libra". "Libra" is a zodiac sign/constellation and wouldn't make sense in this context.) var Logger logger.Logger = logger.StandardLogger{} func debugLogfFunc(lg logger.Logger) func(string, ...any) { @@ -75,11 +76,103 @@ func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Produce // used throughout to store request context with the standard context attached // to the [http.Request]. type Context struct { - spec *loads.Document - analyzer *analysis.Spec - api RoutableAPI - router Router - debugLogf func(string, ...any) // a logging function to debug context and all components using it + spec *loads.Document + analyzer *analysis.Spec + api RoutableAPI + router Router + debugLogf func(string, ...any) // a logging function to debug context and all components using it + ignoreParameters bool // see SetIgnoreParameters / WithIgnoreParameters + matchSuffix bool // see SetMatchSuffix / WithMatchSuffix +} + +// NewRoutableContext creates a new context for a routable API. +// +// If a nil Router is provided, the [DefaultRouter] ([denco]-based) will be used. +func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context { + var an *analysis.Spec + if spec != nil { + an = analysis.New(spec.Spec()) + } + + return NewRoutableContextWithAnalyzedSpec(spec, an, routableAPI, routes) +} + +// NewRoutableContextWithAnalyzedSpec is like [NewRoutableContext] but takes as input an already analysed spec. +// +// If a nil Router is provided, the [DefaultRouter] ([denco]-based) will be used. +func NewRoutableContextWithAnalyzedSpec(spec *loads.Document, an *analysis.Spec, routableAPI RoutableAPI, routes Router) *Context { + // Either there are no spec doc and analysis, or both of them. + if (spec != nil || an != nil) && (spec == nil || an == nil) { + panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, "routable context requires either both spec doc and analysis, or none of them")) + } + + return &Context{ + spec: spec, + api: routableAPI, + analyzer: an, + router: routes, + debugLogf: debugLogfFunc(nil), + } +} + +// NewContext creates a new context wrapper. +// +// If a nil Router is provided, the [DefaultRouter] ([denco]-based) will be used. +func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context { + var an *analysis.Spec + if spec != nil { + an = analysis.New(spec.Spec()) + } + ctx := &Context{ + spec: spec, + analyzer: an, + router: routes, + debugLogf: debugLogfFunc(nil), + } + ctx.api = newRoutableUntypedAPI(spec, api, ctx) + + return ctx +} + +// Serve serves the specified spec with the specified api registrations as a [http.Handler]. +func Serve(spec *loads.Document, api *untyped.API) http.Handler { + return ServeWithBuilder(spec, api, PassthroughBuilder) +} + +// SetIgnoreParameters toggles the legacy parameter-stripping behaviour for +// Accept negotiation server-wide. When set, every internal call to +// [NegotiateContentType] from this Context applies [WithIgnoreParameters]. +// +// Returns the receiver for fluent configuration: +// +// ctx := middleware.NewContext(spec, api, nil).SetIgnoreParameters(true) +// +// See [WithIgnoreParameters] for the rationale and an example. +func (c *Context) SetIgnoreParameters(ignore bool) *Context { + c.ignoreParameters = ignore + + return c +} + +// SetMatchSuffix toggles RFC 6839 structured-syntax suffix tolerance +// server-wide. When enabled, both Accept negotiation and codec lookup +// fall back through the suffix base for the recognised suffixes +// (+json, +xml, +yaml) — so an operation declaring +// consumes: [application/json] also accepts request bodies sent with +// Content-Type: application/vnd.api+json (or any other +json variant). +// +// Default: strict (false). Use only when interoperating with clients +// that do not strictly abide by the spec. +// +// Returns the receiver for fluent configuration: +// +// ctx := middleware.NewContext(spec, api, nil).SetMatchSuffix(true) +// +// See [negotiate.WithMatchSuffix] for the per-call form and rationale. +func (c *Context) SetMatchSuffix(enable bool) *Context { + c.matchSuffix = enable + + return c } type routableUntypedAPI struct { @@ -95,53 +188,57 @@ func newRoutableUntypedAPI(spec *loads.Document, api *untyped.API, context *Cont if spec == nil || api == nil { return nil } + analyzer := analysis.New(spec.Spec()) for method, hls := range analyzer.Operations() { um := strings.ToUpper(method) for path, op := range hls { schemes := analyzer.SecurityRequirementsFor(op) - if oh, ok := api.OperationHandlerFor(method, path); ok { - if handlers == nil { - handlers = make(map[string]map[string]http.Handler) + oh, ok := api.OperationHandlerFor(method, path) + if !ok { + continue + } + + if handlers == nil { + handlers = make(map[string]map[string]http.Handler) + } + if b, ok := handlers[um]; !ok || b == nil { + handlers[um] = make(map[string]http.Handler) + } + + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // lookup route info in the context + route, rCtx, _ := context.RouteInfo(r) + if rCtx != nil { + r = rCtx } - if b, ok := handlers[um]; !ok || b == nil { - handlers[um] = make(map[string]http.Handler) + + // bind and validate the request using reflection + var bound any + var validation error + bound, r, validation = context.BindAndValidate(r, route) + if validation != nil { + context.Respond(w, r, route.Produces, route, validation) + return } - var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // lookup route info in the context - route, rCtx, _ := context.RouteInfo(r) - if rCtx != nil { - r = rCtx - } - - // bind and validate the request using reflection - var bound any - var validation error - bound, r, validation = context.BindAndValidate(r, route) - if validation != nil { - context.Respond(w, r, route.Produces, route, validation) - return - } - - // actually handle the request - result, err := oh.Handle(bound) - if err != nil { - // respond with failure - context.Respond(w, r, route.Produces, route, err) - return - } - - // respond with success - context.Respond(w, r, route.Produces, route, result) - }) - - if len(schemes) > 0 { - handler = newSecureAPI(context, handler) + // actually handle the request + result, err := oh.Handle(bound) + if err != nil { + // respond with failure + context.Respond(w, r, route.Produces, route, err) + return } - handlers[um][path] = handler + + // respond with success + context.Respond(w, r, route.Produces, route, result) + }) + + if len(schemes) > 0 { + handler = newSecureAPI(context, handler) } + handlers[um][path] = handler } } @@ -192,60 +289,6 @@ func (r *routableUntypedAPI) DefaultConsumes() string { return r.defaultConsumes } -// NewRoutableContext creates a new context for a routable API. -// -// If a nil Router is provided, the [DefaultRouter] ([denco]-based) will be used. -func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context { - var an *analysis.Spec - if spec != nil { - an = analysis.New(spec.Spec()) - } - - return NewRoutableContextWithAnalyzedSpec(spec, an, routableAPI, routes) -} - -// NewRoutableContextWithAnalyzedSpec is like [NewRoutableContext] but takes as input an already analysed spec. -// -// If a nil Router is provided, the [DefaultRouter] ([denco]-based) will be used. -func NewRoutableContextWithAnalyzedSpec(spec *loads.Document, an *analysis.Spec, routableAPI RoutableAPI, routes Router) *Context { - // Either there are no spec doc and analysis, or both of them. - if (spec != nil || an != nil) && (spec == nil || an == nil) { - panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, "routable context requires either both spec doc and analysis, or none of them")) - } - - return &Context{ - spec: spec, - api: routableAPI, - analyzer: an, - router: routes, - debugLogf: debugLogfFunc(nil), - } -} - -// NewContext creates a new context wrapper. -// -// If a nil Router is provided, the [DefaultRouter] ([denco]-based) will be used. -func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context { - var an *analysis.Spec - if spec != nil { - an = analysis.New(spec.Spec()) - } - ctx := &Context{ - spec: spec, - analyzer: an, - router: routes, - debugLogf: debugLogfFunc(nil), - } - ctx.api = newRoutableUntypedAPI(spec, api, ctx) - - return ctx -} - -// Serve serves the specified spec with the specified api registrations as a [http.Handler]. -func Serve(spec *loads.Document, api *untyped.API) http.Handler { - return ServeWithBuilder(spec, api, PassthroughBuilder) -} - // ServeWithBuilder serves the specified spec with the specified api registrations as a [http.Handler] that is decorated // by the Builder. func ServeWithBuilder(spec *loads.Document, api *untyped.API, builder Builder) http.Handler { @@ -319,57 +362,42 @@ func (c *Context) RequiredProduces() []string { // BindValidRequest binds a params object to a request but only when the request is valid // if the request is not valid an error will be returned. func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, binder RequestBinder) error { - var res []error var requestContentType string // check and validate content type, select consumer if runtime.HasBody(request) { - ct, _, err := runtime.ContentType(request.Header) + ct, cons, err := c.bindRequestBody(request, route) if err != nil { - res = append(res, err) - } else { - c.debugLogf("validating content type for %q against [%s]", ct, strings.Join(route.Consumes, ", ")) - if err := validateContentType(route.Consumes, ct); err != nil { - res = append(res, err) - } - if len(res) == 0 { - cons, ok := route.Consumers[ct] - if !ok { - res = append(res, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct)) - } else { - route.Consumer = cons - requestContentType = ct - } - } + return errors.CompositeValidationError(err) } + + // happy path + requestContentType = ct + route.Consumer = cons } // check and validate the response format - if len(res) == 0 { - // if the route does not provide Produces and a default contentType could not be identified - // based on a body, typical for GET and DELETE requests, then default contentType to. - if len(route.Produces) == 0 && requestContentType == "" { - requestContentType = "*/*" - } + // if the route does not provide Produces and a default contentType could not be identified + // based on a body, typical for GET and DELETE requests, then default contentType to. + if len(route.Produces) == 0 && requestContentType == "" { + requestContentType = "*/*" + } - if str := NegotiateContentType(request, route.Produces, requestContentType); str == "" { - res = append(res, errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces)) - } + str := negotiate.ContentType(request, route.Produces, requestContentType, c.negotiateOpts()...) + if str == "" { + return errors.CompositeValidationError( + errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces), + ) + } + + if binder == nil { + return nil } // now bind the request with the provided binder // it's assumed the binder will also validate the request and return an error if the // request is invalid - if binder != nil && len(res) == 0 { - if err := binder.BindRequest(request, route); err != nil { - return err - } - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil + return binder.BindRequest(request, route) } // ContentType gets the parsed value of a content type @@ -414,6 +442,7 @@ func (c *Context) RouteInfo(request *http.Request) (*MatchedRoute, *http.Request if route, ok := c.LookupRoute(request); ok { rCtx = stdContext.WithValue(rCtx, ctxMatchedRoute, route) + request.Pattern = route.BasePath + route.PathPattern return route, request.WithContext(rCtx), ok } @@ -431,7 +460,7 @@ func (c *Context) ResponseFormat(r *http.Request, offers []string) (string, *htt return v, r } - format := NegotiateContentType(r, offers, "") + format := negotiate.ContentType(r, offers, "", c.negotiateOpts()...) if format != "" { c.debugLogf("[%s %s] set response format %q in context", r.Method, r.URL.Path, format) r = r.WithContext(stdContext.WithValue(rCtx, ctxResponseFormat, format)) @@ -453,44 +482,6 @@ func (c *Context) ResetAuth(request *http.Request) *http.Request { return request.WithContext(rctx) } -// Authorize authorizes the request -// Returns the principal object and a shallow copy of the request when its -// context doesn't contain the principal, otherwise the same request or an error -// (the last) if one of the authenticators returns one or an Unauthenticated error. -func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (any, *http.Request, error) { - if route == nil || !route.HasAuth() { - return nil, nil, nil - } - - var rCtx = request.Context() - if v := rCtx.Value(ctxSecurityPrincipal); v != nil { - return v, request, nil - } - - applies, usr, err := route.Authenticators.Authenticate(request, route) - if !applies || err != nil || !route.Authenticators.AllowsAnonymous() && usr == nil { - if err != nil { - return nil, nil, err - } - return nil, nil, errors.Unauthenticated("invalid credentials") - } - if route.Authorizer != nil { - if err := route.Authorizer.Authorize(request, usr); err != nil { - if _, ok := err.(errors.Error); ok { - return nil, nil, err - } - - return nil, nil, errors.New(http.StatusForbidden, "%v", err) - } - } - - rCtx = request.Context() - - rCtx = stdContext.WithValue(rCtx, ctxSecurityPrincipal, usr) - rCtx = stdContext.WithValue(rCtx, ctxSecurityScopes, route.Authenticator.AllScopes()) - return usr, request.WithContext(rCtx), nil -} - // BindAndValidate binds and validates the request // Returns the validation map and a shallow copy of the request when its context // doesn't contain the validation, otherwise it returns the same request or an @@ -523,91 +514,29 @@ func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) { // Respond renders the response after doing some content negotiation. func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data any) { c.debugLogf("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces) - offers := []string{} - for _, mt := range produces { - if mt != c.api.DefaultProduces() { - offers = append(offers, mt) - } - } - // the default producer is last so more specific producers take precedence - offers = append(offers, c.api.DefaultProduces()) - c.debugLogf("offers: %v", offers) + offers := c.buildOffers(produces) var format string format, r = c.ResponseFormat(r, offers) rw.Header().Set(runtime.HeaderContentType, format) if resp, ok := data.(Responder); ok { - producers := route.Producers - // producers contains keys with normalized format, if a format has MIME type parameter such as `text/plain; charset=utf-8` - // then you must provide `text/plain` to get the correct producer. HOWEVER, format here is not normalized. - prod, ok := producers[normalizeOffer(format)] - if !ok { - prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()})) - pr, ok := prods[c.api.DefaultProduces()] - if !ok { - panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format))) - } - prod = pr - } - resp.WriteResponse(rw, prod) + c.respondWithResponder(rw, r, route, resp, format) return } if err, ok := data.(error); ok { - if format == "" { - rw.Header().Set(runtime.HeaderContentType, runtime.JSONMime) - } - - if realm := security.FailedBasicAuth(r); realm != "" { - rw.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=%q", realm)) - } - - if route == nil || route.Operation == nil { - c.api.ServeErrorFor("")(rw, r, err) - return - } - c.api.ServeErrorFor(route.Operation.ID)(rw, r, err) + c.respondWithError(rw, r, produces, route, err, format) return } if route == nil || route.Operation == nil { - rw.WriteHeader(http.StatusOK) - if r.Method == http.MethodHead { - return - } - producers := c.api.ProducersFor(normalizeOffers(offers)) - prod, ok := producers[format] - if !ok { - panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format))) - } - if err := prod.Produce(rw, data); err != nil { - panic(err) // let the recovery middleware deal with this - } + c.respondWithoutCode(rw, r, data, format, offers) return } if _, code, ok := route.Operation.SuccessResponse(); ok { - rw.WriteHeader(code) - if code == http.StatusNoContent || r.Method == http.MethodHead { - return - } - - producers := route.Producers - prod, ok := producers[format] - if !ok { - if !ok { - prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()})) - pr, ok := prods[c.api.DefaultProduces()] - if !ok { - panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format))) - } - prod = pr - } - } - if err := prod.Produce(rw, data); err != nil { - panic(err) // let the recovery middleware deal with this - } + c.respondWithCode(rw, r, route, code, data, format) return } @@ -618,57 +547,76 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st // // This handler includes a swagger spec, router and the contract defined in the swagger spec. // -// A spec UI ([SwaggerUI]) is served at {API base path}/docs and the spec document at /swagger.json -// (these can be modified with uiOptions). +// A spec UI ([docui.SwaggerUI]) is served at {API base path}/docs and the spec document at /swagger.json +// (these can be modified with combined [UIOption]). +// +// Deprecated: use [Context.APIHandlerWithUI] with [docui.SwaggerUI] middleware instead. func (c *Context) APIHandlerSwaggerUI(builder Builder, opts ...UIOption) http.Handler { - b := builder - if b == nil { - b = PassthroughBuilder - } - - specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts) - var swaggerUIOpts SwaggerUIOpts - fromCommonToAnyOptions(uiOpts, &swaggerUIOpts) - - return Spec(specPath, c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)), specOpts...) + return c.APIHandlerWithUI(builder, docui.UseSwaggerUI, c.uiOptionsForHandler(opts)...) } // APIHandlerRapiDoc returns a handler to serve the API. // // This handler includes a swagger spec, router and the contract defined in the swagger spec. // -// A spec UI ([RapiDoc]) is served at {API base path}/docs and the spec document at /swagger.json -// (these can be modified with uiOptions). +// A spec UI ([docui.RapiDoc]) is served at {API base path}/docs and the spec document at /swagger.json +// (these can be modified with combined [UIOption]). +// +// Deprecated: use [Context.APIHandlerWithUI] with [docui.UseRapiDoc] middleware instead. func (c *Context) APIHandlerRapiDoc(builder Builder, opts ...UIOption) http.Handler { - b := builder - if b == nil { - b = PassthroughBuilder - } - - specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts) - var rapidocUIOpts RapiDocOpts - fromCommonToAnyOptions(uiOpts, &rapidocUIOpts) - - return Spec(specPath, c.spec.Raw(), RapiDoc(rapidocUIOpts, c.RoutesHandler(b)), specOpts...) + return c.APIHandlerWithUI(builder, docui.UseRapiDoc, c.uiOptionsForHandler(opts)...) } // APIHandler returns a handler to serve the API. // // This handler includes a swagger spec, router and the contract defined in the swagger spec. // -// A spec UI ([Redoc]) is served at {API base path}/docs and the spec document at /swagger.json -// (these can be modified with uiOptions). +// A spec UI ([docui.Redoc]) is served at {API base path}/docs and the spec document at /swagger.json +// (these can be modified with combined [UIOption]). +// +// Notice that you may use [Context.APIHandlerWithUI] to use an alternate UI-serving middleware. func (c *Context) APIHandler(builder Builder, opts ...UIOption) http.Handler { + return c.APIHandlerWithUI(builder, docui.UseRedoc, c.uiOptionsForHandler(opts)...) +} + +// APIHandlerWithUI returns a handler to serve the API with a swagger spec and a UI. +// +// This handler includes a swagger spec, router and the contract defined in the swagger spec. +// +// A spec UI is served at {API base path}/docs and the spec document at /swagger.json +// (these can be modified with combined [UIOption]). +// +// Notice that any function that accepts the [docui.Option] set and returns a valid middleware may be injected here. +// +// [Context.APIHandlerWithUI] extends [Context.APIHandler], and supersedes [Context.APIHandlerRapiDoc] and [Context.APIHandlerSwaggerUI]. +func (c *Context) APIHandlerWithUI(builder Builder, uiMiddleware docui.UIMiddleware, opts ...docui.Option) http.Handler { b := builder if b == nil { b = PassthroughBuilder } - specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts) - var redocOpts RedocOpts - fromCommonToAnyOptions(uiOpts, &redocOpts) + // the UI titles defaults to the title in the spec + const extraOptions = 2 + prepend := make([]docui.Option, 0, len(opts)+extraOptions) + var title string - return Spec(specPath, c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)), specOpts...) + sp := c.spec.Spec() + if sp != nil && sp.Info != nil && sp.Info.Title != "" { + title = sp.Info.Title + } + if title != "" { + prepend = append(prepend, docui.WithUITitle(title)) + } + + prepend = append(prepend, docui.WithUIBasePath(c.BasePath())) + prepend = append(prepend, opts...) + + // aligns spec serve path with UI setting to fetch spec document. + return docui.UseSpec(c.spec.Raw(), docui.WithSpecPathFromOptions(prepend...))( + uiMiddleware(prepend...)( + c.RoutesHandler(b), + ), + ) } // RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec. @@ -680,37 +628,192 @@ func (c *Context) RoutesHandler(builder Builder) http.Handler { return NewRouter(c, b(NewOperationExecutor(c))) } -func (c Context) uiOptionsForHandler(opts []UIOption) (string, uiOptions, []SpecOption) { - var title string - sp := c.spec.Spec() - if sp != nil && sp.Info != nil && sp.Info.Title != "" { - title = sp.Info.Title +// authorizeImpl is the real authentication+authorization body shared +// between the production and dev-only variants of [Context.Authorize]. +// See context_skipauth_disabled.go (default build) and +// context_skipauth_enabled.go (the `openapi_unsafe_skipauth` build tag). +// +// The doc on the exported Authorize describes the user-facing +// contract; this function MUST NOT change semantics for the +// production path. +func (c *Context) authorizeImpl(request *http.Request, route *MatchedRoute) (any, *http.Request, error) { + if route == nil || !route.HasAuth() { + return nil, nil, nil } - // default options (may be overridden) - const baseOptions = 2 - optsForContext := make([]UIOption, 0, len(opts)+baseOptions) - optsForContext = append(optsForContext, - WithUIBasePath(c.BasePath()), - WithUITitle(title), - ) - optsForContext = append(optsForContext, opts...) - uiOpts := uiOptionsWithDefaults(optsForContext) + var rCtx = request.Context() + if v := rCtx.Value(ctxSecurityPrincipal); v != nil { + return v, request, nil + } + + applies, usr, err := route.Authenticators.Authenticate(request, route) + if !applies || err != nil || !route.Authenticators.AllowsAnonymous() && typeutils.IsZero(usr) { + if err != nil { + return nil, nil, err + } + return nil, nil, errors.Unauthenticated("invalid credentials") + } + if route.Authorizer != nil { + if err := route.Authorizer.Authorize(request, usr); err != nil { + var apiError errors.Error + if stderrors.As(err, &apiError) { + return nil, nil, err + } + + return nil, nil, errors.New(http.StatusForbidden, "%v", err) + } + } + + rCtx = request.Context() + + rCtx = stdContext.WithValue(rCtx, ctxSecurityPrincipal, usr) + rCtx = stdContext.WithValue(rCtx, ctxSecurityScopes, route.Authenticator.AllScopes()) + return usr, request.WithContext(rCtx), nil +} + +func (c *Context) bindRequestBody(request *http.Request, route *MatchedRoute) (string, runtime.Consumer, error) { + ct, _, err := runtime.ContentType(request.Header) + if err != nil { + return "", nil, err + } + + c.debugLogf("validating content type for %q against [%s]", ct, strings.Join(route.Consumes, ", ")) + if err := validateContentType(route.Consumes, ct); err != nil { + return "", nil, err + } + + cons, ok := mediatype.Lookup(route.Consumers, ct, c.matchOpts()...) + if !ok { + return "", nil, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct) + } + + return ct, cons, nil +} + +func (c *Context) respondWithResponder(rw http.ResponseWriter, r *http.Request, route *MatchedRoute, resp Responder, format string) { + _ = r + producers := route.Producers + + // producers contains keys with normalized format, if a format has MIME type parameter such as `text/plain; charset=utf-8` + // then you must provide `text/plain` to get the correct producer. HOWEVER, format here is not normalized. + prod, ok := producers[normalizeOffer(format)] + if !ok { + prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()})) + pr, ok := prods[c.api.DefaultProduces()] + if !ok { + panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format))) + } + prod = pr + } + + resp.WriteResponse(rw, prod) +} + +func (c *Context) respondWithError(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, err error, format string) { + _ = produces + + if format == "" { + rw.Header().Set(runtime.HeaderContentType, runtime.JSONMime) + } + + if realm := security.FailedBasicAuth(r); realm != "" { + rw.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=%q", realm)) + } + + if route == nil || route.Operation == nil { + c.api.ServeErrorFor("")(rw, r, err) + return + } + + c.api.ServeErrorFor(route.Operation.ID)(rw, r, err) +} + +func (c *Context) respondWithoutCode(rw http.ResponseWriter, r *http.Request, data any, format string, offers []string) { + rw.WriteHeader(http.StatusOK) + if r.Method == http.MethodHead { + return + } + + producers := c.api.ProducersFor(normalizeOffers(offers)) + prod, ok := producers[format] + if !ok { + panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format))) + } + + if err := prod.Produce(rw, data); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +func (c *Context) buildOffers(produces []string) []string { + offers := make([]string, 0, len(produces)+1) + + for _, mt := range produces { + if mt != c.api.DefaultProduces() { + offers = append(offers, mt) + } + } + + // the default producer is last so more specific producers take precedence + offers = append(offers, c.api.DefaultProduces()) + c.debugLogf("offers: %v", offers) + + return offers +} + +func (c *Context) respondWithCode(rw http.ResponseWriter, r *http.Request, route *MatchedRoute, code int, data any, format string) { + rw.WriteHeader(code) + if code == http.StatusNoContent || r.Method == http.MethodHead { + return + } + + producers := route.Producers + prod, ok := producers[format] + if !ok { + if !ok { + prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()})) + pr, ok := prods[c.api.DefaultProduces()] + if !ok { + panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format))) + } + prod = pr + } + } - // If spec URL is provided, there is a non-default path to serve the spec. - // This makes sure that the UI middleware is aligned with the Spec middleware. - u, _ := url.Parse(uiOpts.SpecURL) - var specPath string - if u != nil { - specPath = u.Path + if err := prod.Produce(rw, data); err != nil { + panic(err) // let the recovery middleware deal with this } +} + +// uiOptionsForHandler bridges the deprecated [UIOption] set to the new [docui.Option] set. +func (c Context) uiOptionsForHandler(opts []UIOption) []docui.Option { + uiOpts := uiOptionsWithDefaults(opts) - pth, doc := path.Split(specPath) - if pth == "." { - pth = "" + return uiOpts.toFuncOptions() +} + +func (c *Context) negotiateOpts() []negotiate.Option { + var opts []negotiate.Option + if c.ignoreParameters { + opts = append(opts, negotiate.WithIgnoreParameters(true)) + } + if c.matchSuffix { + opts = append(opts, negotiate.WithMatchSuffix(true)) + } + + return opts +} + +// matchOpts builds the mediatype.MatchOption slice that the +// codec-lookup and Content-Type validation paths apply server-wide. +// Mirrors negotiateOpts but at the mediatype level (without going +// through the negotiate.Option wrapper). +func (c *Context) matchOpts() []mediatype.MatchOption { + if !c.matchSuffix { + return nil } - return pth, uiOpts, []SpecOption{WithSpecDocument(doc)} + return []mediatype.MatchOption{mediatype.AllowSuffix()} } func cantFindProducer(format string) string { diff --git a/vendor/github.com/go-openapi/runtime/middleware/context_skipauth_disabled.go b/vendor/github.com/go-openapi/runtime/middleware/context_skipauth_disabled.go new file mode 100644 index 00000000000..c8cd01a4343 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/context_skipauth_disabled.go @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +//go:build !openapi_unsafe_skipauth + +package middleware + +import "net/http" + +// Authorize authorizes the request. +// +// Returns the principal object and a shallow copy of the request when its +// context doesn't contain the principal, otherwise the same request or an error +// (the last) if one of the authenticators returns one or an Unauthenticated error. +// +// This is the production variant — compiled when the build tag +// `openapi_unsafe_skipauth` is NOT set. There is no skip-auth check +// in this codepath; the field, setter, and storage for the bypass +// flag are entirely absent from the binary. See the alternate +// implementation in context_skipauth_enabled.go for the dev-only +// bypass mechanism. +func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (any, *http.Request, error) { + return c.authorizeImpl(request, route) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/context_skipauth_enabled.go b/vendor/github.com/go-openapi/runtime/middleware/context_skipauth_enabled.go new file mode 100644 index 00000000000..2ac87068187 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/context_skipauth_enabled.go @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +//go:build openapi_unsafe_skipauth + +package middleware + +import ( + "log" + "net/http" + "sync/atomic" +) + +// skipAuthEnabled holds the process-wide skip-auth flag. It only +// exists in binaries built with the `openapi_unsafe_skipauth` tag — +// production binaries (built without the tag) have no field, no +// setter, no storage, and no skip-checking branch in [Context.Authorize]. +// Reflection, unsafe-pointer arithmetic, or a debugger cannot flip +// what is not in the binary. +var skipAuthEnabled atomic.Bool + +// SetSkipAuth toggles a PROCESS-WIDE bypass of authentication AND +// authorization for every operation served by every Context in the +// running program. +// +// DANGER: this disables ALL authentication and ALL authorization. +// Every request to every secured endpoint runs as if it had been +// authorized with a nil principal. Use ONLY on developer +// workstations during early prototyping (e.g. while +// authentication is not yet wired up). +// +// This function exists only when the build tag +// `openapi_unsafe_skipauth` is set: +// +// go build -tags openapi_unsafe_skipauth ./... +// +// Production CI MUST NOT pass this tag. Calls compile to a symbol +// that does not exist in production binaries. +// +// Calling with true emits a one-line WARNING via the stdlib `log` +// package (stderr by default) so the bypass is visible at startup. +// Calling with false silently disables it. +func SetSkipAuth(skip bool) { + skipAuthEnabled.Store(skip) + if skip { + log.Println("WARNING: go-openapi/runtime: SetSkipAuth(true) — authentication and authorization are bypassed for ALL operations. This MUST NOT run in production.") + } +} + +// Authorize is the dev-build variant of the production +// [Context.Authorize] (see context_skipauth_disabled.go for the +// production path). When [SetSkipAuth] has enabled the bypass, this +// returns a nil principal with the original request and no error — +// handlers downstream receive a nil-value principal. Otherwise it +// delegates to the standard authentication+authorization body. +func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (any, *http.Request, error) { + if skipAuthEnabled.Load() { + return nil, request, nil + } + return c.authorizeImpl(request, route) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go index f89d761cf2a..e380a138d50 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go @@ -9,6 +9,7 @@ package denco import ( "errors" "fmt" + "slices" "sort" "strings" ) @@ -29,8 +30,8 @@ const ( // PathParamCharacter indicates a RESTCONF path param. PathParamCharacter = '=' - // MaxSize is max size of records and internal slice. - MaxSize = (1 << 22) - 1 //nolint:mnd + // MaxSize is the maximum size of records and internal slice (encoded over 22 bits). + MaxSize = (1 << baseBits) - 1 ) // Router represents a URL router. @@ -53,9 +54,12 @@ func New() *Router { } } -// Lookup returns data and path parameters that associated with path. +// Lookup returns data and path parameters which are associated to the path. +// // params is a slice of the [Param] that arranged in the order in which parameters appeared. -// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}]. +// +// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice", +// params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}]. func (rt *Router) Lookup(path string) (data any, params Params, found bool) { if data, found = rt.static[path]; found { return data, nil, true @@ -144,6 +148,7 @@ func newDoubleArray() *doubleArray { type baseCheck uint32 const ( + baseBits = 22 flagsBits = 10 checkBits = 8 ) @@ -157,7 +162,7 @@ func (bc *baseCheck) SetBase(base int) { } func (bc baseCheck) Check() byte { - return byte(bc) //nolint:gosec // integer conversion is ok + return byte(bc) //nolint:gosec // integer conversion is ok: we pick the last 8 bits } func (bc *baseCheck) SetCheck(check byte) { @@ -213,8 +218,8 @@ func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Pa } BACKTRACKING: - for j := len(indices) - 1; j >= 0; j-- { - i, idx := int(indices[j]>>indexOffset), int(indices[j]&indexMask) + for _, j := range slices.Backward(indices) { + i, idx := int(j>>indexOffset), int(j&indexMask) if da.bc[idx].IsSingleParam() { nextIdx := nextIndex(da.bc[idx].Base(), ParamCharacter) if nextIdx >= len(da.bc) { diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/server.go b/vendor/github.com/go-openapi/runtime/middleware/denco/server.go index e6c0976d8b2..3bbbc679d92 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/denco/server.go +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/server.go @@ -9,7 +9,7 @@ import ( "net/http" ) -// Mux represents a multiplexer for HTTP request. +// Mux represents a multiplexer for HTTP requests. type Mux struct{} // NewMux returns a new [Mux]. @@ -17,27 +17,27 @@ func NewMux() *Mux { return &Mux{} } -// GET is shorthand of [Mux].Handler("GET", path, handler). +// GET is shorthand for [Mux.Handler] ("GET", path, handler). func (m *Mux) GET(path string, handler HandlerFunc) Handler { return m.Handler("GET", path, handler) } -// POST is shorthand of [Mux].Handler("POST", path, handler). +// POST is shorthand for [Mux.Handler] ("POST", path, handler). func (m *Mux) POST(path string, handler HandlerFunc) Handler { return m.Handler("POST", path, handler) } -// PUT is shorthand of [Mux].Handler("PUT", path, handler). +// PUT is shorthand for [Mux.Handler] ("PUT", path, handler). func (m *Mux) PUT(path string, handler HandlerFunc) Handler { return m.Handler("PUT", path, handler) } -// HEAD is shorthand of [Mux].Handler("HEAD", path, handler). +// HEAD is shorthand for [Mux.Handler]("HEAD", path, handler). func (m *Mux) HEAD(path string, handler HandlerFunc) Handler { return m.Handler("HEAD", path, handler) } -// Handler returns a handler for HTTP method. +// Handler returns a [Handler] for a HTTP method. func (m *Mux) Handler(method, path string, handler HandlerFunc) Handler { return Handler{ Method: method, @@ -63,7 +63,7 @@ func (m *Mux) Build(handlers []Handler) (http.Handler, error) { return mux, nil } -// Handler represents a handler of HTTP request. +// Handler represents a handler of HTTP requests. type Handler struct { // Method is an HTTP method. Method string @@ -75,7 +75,7 @@ type Handler struct { Func HandlerFunc } -// HandlerFunc is aliased to type of handler function. +// HandlerFunc is an alias to the handler function, similar to [http.HandlerFunc]. type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params) type serveMux struct { @@ -88,7 +88,7 @@ func newServeMux() *serveMux { } } -// ServeHTTP implements http.Handler interface. +// ServeHTTP implements the [http.Handler] interface. func (mux *serveMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { handler, params := mux.handler(r.Method, r.URL.Path) handler(w, r, params) @@ -97,15 +97,17 @@ func (mux *serveMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (mux *serveMux) handler(method, path string) (HandlerFunc, []Param) { if router, found := mux.routers[method]; found { if handler, params, found := router.Lookup(path); found { - return handler.(HandlerFunc), params + return handler.(HandlerFunc), params //nolint:forcetypeassert // type is guaranteed when the path is found } } return NotFound, nil } // NotFound replies to the request with an HTTP 404 not found error. -// NotFound is called when unknown HTTP method or a handler not found. -// If you want to use the your own NotFound handler, please overwrite this variable. +// +// NotFound is called when unknown HTTP methods are being user or a handler not found. +// +// If you want to use your own NotFound handler, please overwrite this variable. var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) { http.NotFound(w, r) } diff --git a/vendor/github.com/go-openapi/runtime/middleware/negotiate.go b/vendor/github.com/go-openapi/runtime/middleware/negotiate.go deleted file mode 100644 index cb0a85283c1..00000000000 --- a/vendor/github.com/go-openapi/runtime/middleware/negotiate.go +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -// Copyright 2013 The Go Authors. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd. - -// this file was taken from the github.com/golang/gddo repository - -package middleware - -import ( - "net/http" - "strings" - - "github.com/go-openapi/runtime/middleware/header" -) - -// NegotiateContentEncoding returns the best offered content encoding for the -// request's Accept-Encoding header. If two offers match with equal weight and -// then the offer earlier in the list is preferred. If no offers are -// acceptable, then "" is returned. -func NegotiateContentEncoding(r *http.Request, offers []string) string { - bestOffer := "identity" - bestQ := -1.0 - specs := header.ParseAccept(r.Header, "Accept-Encoding") - for _, offer := range offers { - for _, spec := range specs { - if spec.Q > bestQ && - (spec.Value == "*" || spec.Value == offer) { - bestQ = spec.Q - bestOffer = offer - } - } - } - if bestQ == 0 { - bestOffer = "" - } - return bestOffer -} - -// NegotiateContentType returns the best offered content type for the request's -// Accept header. If two offers match with equal weight, then the more specific -// offer is preferred. For example, text/* trumps */*. If two offers match -// with equal weight and specificity, then the offer earlier in the list is -// preferred. If no offers match, then defaultOffer is returned. -func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string { - bestOffer := defaultOffer - bestQ := -1.0 - bestWild := 3 - specs := header.ParseAccept(r.Header, "Accept") - for _, rawOffer := range offers { - offer := normalizeOffer(rawOffer) - // No Accept header: just return the first offer. - if len(specs) == 0 { - return rawOffer - } - for _, spec := range specs { - switch { - case spec.Q == 0.0: - // ignore - case spec.Q < bestQ: - // better match found - case spec.Value == "*/*": - if spec.Q > bestQ || bestWild > 2 { - bestQ = spec.Q - bestWild = 2 - bestOffer = rawOffer - } - case strings.HasSuffix(spec.Value, "/*"): - if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) && - (spec.Q > bestQ || bestWild > 1) { - bestQ = spec.Q - bestWild = 1 - bestOffer = rawOffer - } - default: - if spec.Value == offer && - (spec.Q > bestQ || bestWild > 0) { - bestQ = spec.Q - bestWild = 0 - bestOffer = rawOffer - } - } - } - } - return bestOffer -} - -func normalizeOffers(orig []string) (norm []string) { - for _, o := range orig { - norm = append(norm, normalizeOffer(o)) - } - return -} - -func normalizeOffer(orig string) string { - const maxParts = 2 - return strings.SplitN(orig, ";", maxParts)[0] -} diff --git a/vendor/github.com/go-openapi/runtime/middleware/parameter.go b/vendor/github.com/go-openapi/runtime/middleware/parameter.go index a9d2a36460b..4ae8e3d62d6 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/parameter.go +++ b/vendor/github.com/go-openapi/runtime/middleware/parameter.go @@ -6,7 +6,7 @@ package middleware import ( "encoding" "encoding/base64" - "fmt" + stderrors "errors" "io" "net/http" "reflect" @@ -56,126 +56,153 @@ func (p *untypedParamBinder) Type() reflect.Type { } func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, target reflect.Value) error { - // fmt.Println("binding", p.name, "as", p.Type()) switch p.parameter.In { case "query": - data, custom, hasKey, err := p.readValue(runtime.Values(request.URL.Query()), target) - if err != nil { - return err - } - if custom { - return nil - } - - return p.bindValue(data, hasKey, target) + return p.bindQuery(request, routeParams, consumer, target) case "header": - data, custom, hasKey, err := p.readValue(runtime.Values(request.Header), target) - if err != nil { - return err - } - if custom { - return nil - } - return p.bindValue(data, hasKey, target) + return p.bindHeader(request, routeParams, consumer, target) case "path": - data, custom, hasKey, err := p.readValue(routeParams, target) - if err != nil { - return err - } - if custom { - return nil - } - return p.bindValue(data, hasKey, target) + return p.bindPath(request, routeParams, consumer, target) case "formData": - var err error - var mt string + return p.bindFormData(request, routeParams, consumer, target) - mt, _, e := runtime.ContentType(request.Header) - if e != nil { - // because of the interface conversion go thinks the error is not nil - // so we first check for nil and then set the err var if it's not nil - err = e - } + case "body": + return p.bindBody(request, routeParams, consumer, target) + default: + return errors.New(http.StatusInternalServerError, "invalid parameter location: %q", p.parameter.In) + } +} - if err != nil { - return errors.InvalidContentType("", []string{"multipart/form-data", "application/x-www-form-urlencoded"}) - } +func (p *untypedParamBinder) bindQuery(request *http.Request, _ RouteParams, _ runtime.Consumer, target reflect.Value) error { + data, custom, hasKey, err := p.readValue(runtime.Values(request.URL.Query()), target) + if err != nil { + return err + } + if custom { + return nil + } - if mt != "multipart/form-data" && mt != "application/x-www-form-urlencoded" { - return errors.InvalidContentType(mt, []string{"multipart/form-data", "application/x-www-form-urlencoded"}) - } + return p.bindValue(data, hasKey, target) +} - if mt == "multipart/form-data" { - if err = request.ParseMultipartForm(defaultMaxMemory); err != nil { - return errors.NewParseError(p.Name, p.parameter.In, "", err) - } - } +func (p *untypedParamBinder) bindHeader(request *http.Request, _ RouteParams, _ runtime.Consumer, target reflect.Value) error { + data, custom, hasKey, err := p.readValue(runtime.Values(request.Header), target) + if err != nil { + return err + } + if custom { + return nil + } + return p.bindValue(data, hasKey, target) +} - if err = request.ParseForm(); err != nil { - return errors.NewParseError(p.Name, p.parameter.In, "", err) - } +func (p *untypedParamBinder) bindPath(_ *http.Request, routeParams RouteParams, _ runtime.Consumer, target reflect.Value) error { + data, custom, hasKey, err := p.readValue(routeParams, target) + if err != nil { + return err + } + if custom { + return nil + } + return p.bindValue(data, hasKey, target) +} - if p.parameter.Type == "file" { - file, header, ffErr := request.FormFile(p.parameter.Name) - if ffErr != nil { - if p.parameter.Required { - return errors.NewParseError(p.Name, p.parameter.In, "", ffErr) - } +func (p *untypedParamBinder) bindFormData(request *http.Request, _ RouteParams, _ runtime.Consumer, target reflect.Value) error { + mt, _, ctErr := runtime.ContentType(request.Header) + if ctErr != nil { + return errors.InvalidContentType("", []string{runtime.MultipartFormMime, runtime.URLencodedFormMime}) + } - return nil - } + if mt != runtime.MultipartFormMime && mt != runtime.URLencodedFormMime { + return errors.InvalidContentType(mt, []string{runtime.MultipartFormMime, runtime.URLencodedFormMime}) + } - target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header})) - return nil - } + // Parse via the shared helper. The helper routes on Content-Type + // (multipart/form-data → ParseMultipartForm; all non-multipart types, + // including application/x-www-form-urlencoded, → ParseForm) + // and applies the default 32 MiB body cap via http.MaxBytesReader. + // Idempotent across the per-parameter loop: stdlib short-circuits + // when r.MultipartForm / r.PostForm are already populated. + if _, perr := runtime.BindForm(request, runtime.BindFormMaxParseMemory(defaultMaxMemory)); perr != nil { + return perr + } - if request.MultipartForm != nil { - data, custom, hasKey, rvErr := p.readValue(runtime.Values(request.MultipartForm.Value), target) - if rvErr != nil { - return rvErr - } - if custom { + if p.parameter.Type == "file" { + // runtime.FormFile handles both multipart/form-data and + // application/x-www-form-urlencoded (OpenAPI 2.0 permits + // either consumes for `type: file`), and surfaces a + // missing field as http.ErrMissingFile under both. + file, header, ffErr := runtime.FormFile(request, p.parameter.Name) + if ffErr != nil { + if stderrors.Is(ffErr, http.ErrMissingFile) { + if p.parameter.Required { + return errors.NewParseError(p.Name, p.parameter.In, "", http.ErrMissingFile) + } return nil } - return p.bindValue(data, hasKey, target) + return errors.NewParseError(p.Name, p.parameter.In, "", ffErr) } - data, custom, hasKey, err := p.readValue(runtime.Values(request.PostForm), target) - if err != nil { + + // Mirror the FileHeader.Filename length cap that BindForm + // applies to typed (codegen) paths through BindFormFile, so + // untyped formData bindings get the same protection. + if err := runtime.ValidateFilenameLength(p.Name, p.parameter.In, header.Filename, + runtime.DefaultMaxUploadFilenameLength); err != nil { return err } + + target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header})) + return nil + } + + if request.MultipartForm != nil { + data, custom, hasKey, rvErr := p.readValue(runtime.Values(request.MultipartForm.Value), target) + if rvErr != nil { + return rvErr + } if custom { return nil } return p.bindValue(data, hasKey, target) + } + data, custom, hasKey, err := p.readValue(runtime.Values(request.PostForm), target) + if err != nil { + return err + } + if custom { + return nil + } + return p.bindValue(data, hasKey, target) +} - case "body": - newValue := reflect.New(target.Type()) - if !runtime.HasBody(request) { - if p.parameter.Default != nil { - target.Set(reflect.ValueOf(p.parameter.Default)) - } +func (p *untypedParamBinder) bindBody(request *http.Request, _ RouteParams, consumer runtime.Consumer, target reflect.Value) error { + newValue := reflect.New(target.Type()) + if !runtime.HasBody(request) { + if p.parameter.Default != nil { + target.Set(reflect.ValueOf(p.parameter.Default)) + } + return nil + } + + if err := consumer.Consume(request.Body, newValue.Interface()); err != nil { + if stderrors.Is(err, io.EOF) && p.parameter.Default != nil { + target.Set(reflect.ValueOf(p.parameter.Default)) return nil } - if err := consumer.Consume(request.Body, newValue.Interface()); err != nil { - if err == io.EOF && p.parameter.Default != nil { - target.Set(reflect.ValueOf(p.parameter.Default)) - return nil - } - tpe := p.parameter.Type - if p.parameter.Format != "" { - tpe = p.parameter.Format - } - return errors.InvalidType(p.Name, p.parameter.In, tpe, nil) + tpe := p.parameter.Type + if p.parameter.Format != "" { + tpe = p.parameter.Format } - target.Set(reflect.Indirect(newValue)) - return nil - default: - return fmt.Errorf("%d: invalid parameter location %q", http.StatusInternalServerError, p.parameter.In) + return errors.InvalidType(p.Name, p.parameter.In, tpe, nil) } + + target.Set(reflect.Indirect(newValue)) + + return nil } func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type { @@ -261,20 +288,51 @@ func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflec if p.parameter.Type == typeArray { return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey) } + var d string if len(data) > 0 { d = data[len(data)-1] } + return p.setFieldValue(target, p.parameter.Default, d, hasKey) } -func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue any, data string, hasKey bool) error { //nolint:gocyclo +func (p *untypedParamBinder) isMissingAndRequired(hasKey bool, data string) bool { + return p.parameter.Required && + p.parameter.Default == nil && + (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) +} + +func (p *untypedParamBinder) setByte(target, defVal reflect.Value, tpe, data string) error { + if data == "" { + if target.CanSet() { + target.SetBytes(defVal.Bytes()) + } + + return nil + } + + b, err := base64.StdEncoding.DecodeString(data) + if err != nil { + b, err = base64.URLEncoding.DecodeString(data) + if err != nil { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + } + if target.CanSet() { + target.SetBytes(b) + } + + return nil +} + +func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue any, data string, hasKey bool) error { tpe := p.parameter.Type if p.parameter.Format != "" { tpe = p.parameter.Format } - if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil { + if p.isMissingAndRequired(hasKey, data) { return errors.Required(p.Name, p.parameter.In, data) } @@ -292,27 +350,15 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue an } if tpe == "byte" { - if data == "" { - if target.CanSet() { - target.SetBytes(defVal.Bytes()) - } - return nil - } - - b, err := base64.StdEncoding.DecodeString(data) - if err != nil { - b, err = base64.URLEncoding.DecodeString(data) - if err != nil { - return errors.InvalidType(p.Name, p.parameter.In, tpe, data) - } - } - if target.CanSet() { - target.SetBytes(b) - } - return nil + return p.setByte(target, defVal, tpe, data) } - switch target.Kind() { //nolint:exhaustive // we want to check only types that map from a swagger parameter + return p.setReflectFieldValue(target, defVal, tpe, data, hasKey) +} + +//nolint:gocyclo,cyclop // not much we can simplify further significantly: the big case with all types is unavoidable. +func (p *untypedParamBinder) setReflectFieldValue(target, defVal reflect.Value, tpe, data string, hasKey bool) error { + switch target.Kind() { // we want to check only types that map from a swagger parameter case reflect.Bool: if data == "" { if target.CanSet() { @@ -327,6 +373,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue an if target.CanSet() { target.SetBool(b) } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if data == "" { if target.CanSet() { @@ -394,8 +441,8 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue an target.SetString(value) } - case reflect.Ptr: - if data == "" && defVal.Kind() == reflect.Ptr { + case reflect.Pointer: + if data == "" && defVal.Kind() == reflect.Pointer { if target.CanSet() { target.Set(defVal) } @@ -412,6 +459,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue an default: return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } + return nil } @@ -419,20 +467,30 @@ func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue a if !target.CanSet() { return false, nil } + // When a type implements encoding.TextUnmarshaler we'll use that instead of reflecting some more - if reflect.PointerTo(target.Type()).Implements(textUnmarshalType) { - if defaultValue != nil && len(data) == 0 { - target.Set(reflect.ValueOf(defaultValue)) - return true, nil - } - value := reflect.New(target.Type()) - if err := value.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(data)); err != nil { - return true, err - } - target.Set(reflect.Indirect(value)) + ttyp := target.Type() + if !reflect.PointerTo(ttyp).Implements(textUnmarshalType) { + return false, nil + } + + if defaultValue != nil && len(data) == 0 { + target.Set(reflect.ValueOf(defaultValue)) return true, nil } - return false, nil + + value := reflect.New(ttyp) + if !value.CanInterface() { + return false, nil + } + + if err := value.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(data)); err != nil { //nolint:forcetypeassert // this is guaranteed by the reflect check above + return true, err + } + + target.Set(reflect.Indirect(value)) + + return true, nil } func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target reflect.Value) ([]string, bool, error) { diff --git a/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go b/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go deleted file mode 100644 index 1574defb41a..00000000000 --- a/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package middleware - -import ( - "bytes" - "fmt" - "html/template" - "net/http" - "path" -) - -// RapiDocOpts configures the [RapiDoc] middlewares. -type RapiDocOpts struct { - // BasePath for the UI, defaults to: / - BasePath string - - // Path combines with BasePath to construct the path to the UI, defaults to: "docs". - Path string - - // SpecURL is the URL of the spec document. - // - // Defaults to: /swagger.json - SpecURL string - - // Title for the documentation site, default to: API documentation - Title string - - // Template specifies a custom template to serve the UI - Template string - - // RapiDocURL points to the js asset that generates the rapidoc site. - // - // Defaults to https://unpkg.com/rapidoc/dist/rapidoc-min.js - RapiDocURL string -} - -func (r *RapiDocOpts) EnsureDefaults() { - common := toCommonUIOptions(r) - common.EnsureDefaults() - fromCommonToAnyOptions(common, r) - - // rapidoc-specifics - if r.RapiDocURL == "" { - r.RapiDocURL = rapidocLatest - } - if r.Template == "" { - r.Template = rapidocTemplate - } -} - -// RapiDoc creates a [middleware] to serve a documentation site for a swagger spec. -// -// This allows for altering the spec before starting the [http] listener. -func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler { - opts.EnsureDefaults() - - pth := path.Join(opts.BasePath, opts.Path) - tmpl := template.Must(template.New("rapidoc").Parse(opts.Template)) - assets := bytes.NewBuffer(nil) - if err := tmpl.Execute(assets, opts); err != nil { - panic(fmt.Errorf("cannot execute template: %w", err)) - } - - return serveUI(pth, assets.Bytes(), next) -} - -const ( - rapidocLatest = "https://unpkg.com/rapidoc/dist/rapidoc-min.js" - rapidocTemplate = ` - - - {{ .Title }} - - - - - - - -` -) diff --git a/vendor/github.com/go-openapi/runtime/middleware/redoc.go b/vendor/github.com/go-openapi/runtime/middleware/redoc.go deleted file mode 100644 index 1007409a30b..00000000000 --- a/vendor/github.com/go-openapi/runtime/middleware/redoc.go +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package middleware - -import ( - "bytes" - "fmt" - "html/template" - "net/http" - "path" -) - -// RedocOpts configures the [Redoc] middlewares. -type RedocOpts struct { - // BasePath for the UI, defaults to: / - BasePath string - - // Path combines with BasePath to construct the path to the UI, defaults to: "docs". - Path string - - // SpecURL is the URL of the spec document. - // - // Defaults to: /swagger.json - SpecURL string - - // Title for the documentation site, default to: API documentation - Title string - - // Template specifies a custom template to serve the UI - Template string - - // RedocURL points to the js that generates the redoc site. - // - // Defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js - RedocURL string -} - -// EnsureDefaults in case some options are missing. -func (r *RedocOpts) EnsureDefaults() { - common := toCommonUIOptions(r) - common.EnsureDefaults() - fromCommonToAnyOptions(common, r) - - // redoc-specifics - if r.RedocURL == "" { - r.RedocURL = redocLatest - } - if r.Template == "" { - r.Template = redocTemplate - } -} - -// Redoc creates a [middleware] to serve a documentation site for a swagger spec. -// -// This allows for altering the spec before starting the [http] listener. -func Redoc(opts RedocOpts, next http.Handler) http.Handler { - opts.EnsureDefaults() - - pth := path.Join(opts.BasePath, opts.Path) - tmpl := template.Must(template.New("redoc").Parse(opts.Template)) - assets := bytes.NewBuffer(nil) - if err := tmpl.Execute(assets, opts); err != nil { - panic(fmt.Errorf("cannot execute template: %w", err)) - } - - return serveUI(pth, assets.Bytes(), next) -} - -const ( - redocLatest = "https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js" - redocTemplate = ` - - - {{ .Title }} - - - - - - - - - - - - - -` -) diff --git a/vendor/github.com/go-openapi/runtime/middleware/request.go b/vendor/github.com/go-openapi/runtime/middleware/request.go index ad781663b8b..2b8aab08d22 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/request.go +++ b/vendor/github.com/go-openapi/runtime/middleware/request.go @@ -40,8 +40,25 @@ func NewUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Sw // Bind perform the databinding and validation. func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data any) error { + err := o.bind(request, routeParams, consumer, data) + if err == nil { + return nil // avoids returning a nil-interface + } + + return err +} + +// SetLogger allows for injecting a logger to catch debug entries. +// +// The logger is enabled in DEBUG mode only. +func (o *UntypedRequestBinder) SetLogger(lg logger.Logger) { + o.debugLogf = debugLogfFunc(lg) +} + +func (o *UntypedRequestBinder) bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data any) *errors.CompositeError { val := reflect.Indirect(reflect.ValueOf(data)) isMap := val.Kind() == reflect.Map + var result []error o.debugLogf("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath()) for fieldName, param := range o.Parameters { @@ -56,7 +73,7 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara if isMap { tpe := binder.Type() if tpe == nil { - if param.Schema.Type.Contains(typeArray) { + if param.Schema != nil && param.Schema.Type.Contains(typeArray) { tpe = reflect.TypeFor[[]any]() } else { tpe = reflect.TypeFor[map[string]any]() @@ -94,13 +111,6 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara return nil } -// SetLogger allows for injecting a logger to catch debug entries. -// -// The logger is enabled in DEBUG mode only. -func (o *UntypedRequestBinder) SetLogger(lg logger.Logger) { - o.debugLogf = debugLogfFunc(lg) -} - func (o *UntypedRequestBinder) setDebugLogf(fn func(string, ...any)) { o.debugLogf = fn } diff --git a/vendor/github.com/go-openapi/runtime/middleware/router.go b/vendor/github.com/go-openapi/runtime/middleware/router.go index e828653be7a..939cf7337ab 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/router.go +++ b/vendor/github.com/go-openapi/runtime/middleware/router.go @@ -21,6 +21,7 @@ import ( "github.com/go-openapi/spec" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag/stringutils" + "github.com/go-openapi/swag/typeutils" ) // RouteParam is a object to capture route params in a framework agnostic way. @@ -292,7 +293,7 @@ func (ras RouteAuthenticators) Authenticate(req *http.Request, route *MatchedRou continue } applies, usr, err := ra.Authenticate(req, route) - if !applies || err != nil || usr == nil { + if !applies || err != nil || typeutils.IsZero(usr) { if err != nil { lastError = err } @@ -348,49 +349,62 @@ func (m *MatchedRoute) NeedsAuth() bool { func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) { mth := strings.ToUpper(method) d.debugLogf("looking up route for %s %s", method, path) - if Debug { - if len(d.routers) == 0 { + if len(d.routers) == 0 { + if Debug { d.debugLogf("there are no known routers") } + panic("internal error: no router is configured") + } + + if Debug { for meth := range d.routers { d.debugLogf("got a router for %s", meth) } } - if router, ok := d.routers[mth]; ok { - if m, rp, ok := router.Lookup(fpath.Clean(path)); ok && m != nil { - if entry, ok := m.(*routeEntry); ok { - d.debugLogf("found a route for %s %s with %d parameters", method, path, len(entry.Parameters)) - var params RouteParams - for _, p := range rp { - v, err := url.PathUnescape(p.Value) - if err != nil { - d.debugLogf("failed to escape %q: %v", p.Value, err) - v = p.Value - } - // a workaround to handle fragment/composing parameters until they are supported in denco router - // check if this parameter is a fragment within a path segment - const enclosureSize = 2 - if xpos := strings.Index(entry.PathPattern, fmt.Sprintf("{%s}", p.Name)) + len(p.Name) + enclosureSize; xpos < len(entry.PathPattern) && entry.PathPattern[xpos] != '/' { - // extract fragment parameters - ep := strings.Split(entry.PathPattern[xpos:], "/")[0] - pnames, pvalues := decodeCompositParams(p.Name, v, ep, nil, nil) - for i, pname := range pnames { - params = append(params, RouteParam{Name: pname, Value: pvalues[i]}) - } - } else { - // use the parameter directly - params = append(params, RouteParam{Name: p.Name, Value: v}) - } - } - return &MatchedRoute{routeEntry: *entry, Params: params}, true + + router, ok := d.routers[mth] + if !ok { + d.debugLogf("couldn't find a route by method for %s %s", method, path) + return nil, false + } + + m, rp, ok := router.Lookup(fpath.Clean(escapeLiteralColons(path))) + if !ok || m == nil { + d.debugLogf("couldn't find a route by path for %s %s", method, path) + return nil, false + } + + entry, ok := m.(*routeEntry) + if !ok { + return nil, false + } + + d.debugLogf("found a route for %s %s with %d parameters", method, path, len(entry.Parameters)) + var params RouteParams + for _, p := range rp { + v, err := url.PathUnescape(p.Value) + if err != nil { + d.debugLogf("failed to escape %q: %v", p.Value, err) + v = p.Value + } + + // a workaround to handle fragment/composing parameters until they are supported in denco router + // check if this parameter is a fragment within a path segment + const enclosureSize = 2 + if xpos := strings.Index(entry.PathPattern, fmt.Sprintf("{%s}", p.Name)) + len(p.Name) + enclosureSize; xpos < len(entry.PathPattern) && entry.PathPattern[xpos] != '/' { + // extract fragment parameters + ep := strings.Split(entry.PathPattern[xpos:], "/")[0] + pnames, pvalues := decodeCompositParams(p.Name, v, ep, nil, nil) + for i, pname := range pnames { + params = append(params, RouteParam{Name: pname, Value: pvalues[i]}) } } else { - d.debugLogf("couldn't find a route by path for %s %s", method, path) + // use the parameter directly + params = append(params, RouteParam{Name: p.Name, Value: v}) } - } else { - d.debugLogf("couldn't find a route by method for %s %s", method, path) } - return nil, false + + return &MatchedRoute{routeEntry: *entry, Params: params}, true } func (d *defaultRouter) OtherMethods(method, path string) []string { @@ -398,7 +412,7 @@ func (d *defaultRouter) OtherMethods(method, path string) []string { var methods []string for k, v := range d.routers { if k != mn { - if _, _, ok := v.Lookup(fpath.Clean(path)); ok { + if _, _, ok := v.Lookup(fpath.Clean(escapeLiteralColons(path))); ok { methods = append(methods, k) continue } @@ -414,28 +428,39 @@ func (d *defaultRouter) SetLogger(lg logger.Logger) { // convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco. var pathConverter = regexp.MustCompile(`{(.+?)}([^/]*)`) +// escapeLiteralColons replaces literal ':' characters with their URL-encoded +// equivalent "%3A". This prevents the denco router from misinterpreting ':' +// in URL path segments as parameter delimiters. The ':' character is valid in +// URL paths per RFC 3986 section 3.3. +func escapeLiteralColons(path string) string { + return strings.ReplaceAll(path, ":", "%3A") +} + func decodeCompositParams(name string, value string, pattern string, names []string, values []string) ([]string, []string) { pleft := strings.Index(pattern, "{") names = append(names, name) + if pleft < 0 { if strings.HasSuffix(value, pattern) { values = append(values, value[:len(value)-len(pattern)]) } else { values = append(values, "") } + + return names, values + } + + toskip := pattern[:pleft] + pright := strings.Index(pattern, "}") + vright := strings.Index(value, toskip) + if vright >= 0 { + values = append(values, value[:vright]) } else { - toskip := pattern[:pleft] - pright := strings.Index(pattern, "}") - vright := strings.Index(value, toskip) - if vright >= 0 { - values = append(values, value[:vright]) - } else { - values = append(values, "") - value = "" - } - return decodeCompositParams(pattern[pleft+1:pright], value[vright+len(toskip):], pattern[pright+1:], names, values) + values = append(values, "") + value = "" } - return names, values + + return decodeCompositParams(pattern[pleft+1:pright], value[vright+len(toskip):], pattern[pright+1:], names, values) } func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Operation) { @@ -463,7 +488,7 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper requestBinder := NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()) requestBinder.setDebugLogf(d.debugLogf) - record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{ + record := denco.NewRecord(pathConverter.ReplaceAllString(escapeLiteralColons(path), ":$1"), &routeEntry{ BasePath: bp, PathPattern: path, Operation: operation, diff --git a/vendor/github.com/go-openapi/runtime/middleware/seam.go b/vendor/github.com/go-openapi/runtime/middleware/seam.go new file mode 100644 index 00000000000..b234395f19c --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/seam.go @@ -0,0 +1,482 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package middleware + +import ( + "net/http" + "path" + "strings" + + "github.com/go-openapi/runtime/server-middleware/docui" + "github.com/go-openapi/runtime/server-middleware/negotiate" +) + +/////////////////////////////////////////////////////////: +// Seam to the negotiate options introduced in v0.29.5 +/////////////////////////////////////////////////////////: + +// NegotiateOption configures [NegotiateContentType] behaviour. +// +// Deprecated: moved to the [negotiate] package. Use [negotiate.Option] instead. +type NegotiateOption = negotiate.Option + +// NegotiateContentType returns the best offered content type for the +// request's Accept header. +// +// Deprecated: moved to the [negotiate] package. Use [negotiate.ContentType] instead. +func NegotiateContentType(r *http.Request, offers []string, defaultOffer string, opts ...NegotiateOption) string { + return negotiate.ContentType(r, offers, defaultOffer, opts...) +} + +// NegotiateContentEncoding returns the best offered content encoding for +// the request's Accept-Encoding header. +// +// Deprecated: moved to the [negotiate] package. Use [negotiate.ContentEncoding] instead. +func NegotiateContentEncoding(r *http.Request, offers []string) string { + return negotiate.ContentEncoding(r, offers) +} + +// WithIgnoreParameters returns a [NegotiateOption] that strips MIME-type +// parameters from both Accept entries and offers before matching, +// restoring the pre-v0.30 behaviour. +// +// Deprecated: moved to the [negotiate] package. Use [negotiate.WithIgnoreParameters] instead. +func WithIgnoreParameters(ignore bool) NegotiateOption { + return negotiate.WithIgnoreParameters(ignore) +} + +/////////////////////////////////////////////////////////: +// Seam to the UI options +/////////////////////////////////////////////////////////: + +// RapiDoc creates a [http.Handler] to serve a documentation site for a swagger spec. +// +// This allows for altering the spec before starting the [http] listener. +// +// Deprecated: moved to the [docui] package. Use [docui.RapiDoc] instead. +func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler { + return docui.RapiDoc(next, opts.toFuncOptions()...) +} + +// Redoc creates a [http.Handler] to serve a documentation site for a swagger spec. +// +// This allows for altering the spec before starting the [http] listener. +// +// Deprecated: moved to the [docui] package. Use [docui.Redoc] instead. +func Redoc(opts RedocOpts, next http.Handler) http.Handler { + return docui.Redoc(next, opts.toFuncOptions()...) +} + +// SwaggerUI creates a [http.Handler] to serve a documentation site for a swagger spec. +// +// This allows for altering the spec before starting the [http] listener. +// +// Deprecated: moved to the [docui] package. Use [docui.SwaggerUI] instead. +func SwaggerUI(opts SwaggerUIOpts, next http.Handler) http.Handler { + return docui.SwaggerUI(next, opts.toFuncOptions()...) +} + +// SwaggerUIOAuth2Callback creates a middleware that serves the OAuth2 callback page used by Swagger UI. +// +// Deprecated: moved to the [docui] package. Use [docui.SwaggerUIOAuth2Callback] instead. +func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler { + return docui.SwaggerUIOAuth2Callback(next, opts.toFuncOptions()...) +} + +/////////////////////////////////////////////////////////: +// Seam to the spec middleware options +/////////////////////////////////////////////////////////: + +// SpecOption can be applied to the [Spec] serving [middleware]. +// +// Deprecated: moved to the [docui] package. Use [docui.SpecOption] instead. +type SpecOption func(*specOptions) + +type specOptions struct { + BasePath string + Path string + Document string +} + +func (o specOptions) fullPath() string { + return path.Join(o.BasePath, o.Path, o.Document) +} + +func specOptionsWithDefaults(basePath string, opts []SpecOption) specOptions { + o := specOptions{ + BasePath: "/", + Path: "", + Document: "swagger.json", + } + + for _, apply := range opts { + apply(&o) + } + if basePath != "" { + o.BasePath = basePath + } + + return o +} + +// Spec creates a [middleware] to serve a swagger spec as a JSON document. +// +// This allows for altering the spec before starting the [http] listener. +// +// The basePath argument indicates the path of the spec document (defaults to "/"). +// Additional [SpecOption] can be used to change the name of the document (defaults to "swagger.json"). +// +// Deprecated: moved to the [docui] package as [docui.ServeSpec]. +func Spec(basePath string, spec []byte, next http.Handler, opts ...SpecOption) http.Handler { + o := specOptionsWithDefaults(basePath, opts) + + return docui.ServeSpec(spec, next, docui.WithSpecPath(o.fullPath())) + +} + +// WithSpecPath sets the path to be joined to the base path of the +// spec-serving middleware (see [docui.ServeSpec]). +// +// This is empty by default. +func WithSpecPath(pth string) SpecOption { + return func(o *specOptions) { + o.Path = pth + } +} + +// WithSpecDocument sets the name of the JSON document served as a spec. +// +// By default, this is "swagger.json". +func WithSpecDocument(doc string) SpecOption { + return func(o *specOptions) { + if doc == "" { + return + } + + o.Document = doc + } +} + +// UIOptions defines common options for UI serving middlewares. +// +// Deprecated: use instead the function options provided by [docui]. +type UIOptions struct { + // BasePath for the UI, defaults to: / + BasePath string + + // Path combines with BasePath to construct the path to the UI, defaults to: "docs". + Path string + + // SpecURL is the URL of the spec document. + // + // Defaults to: /swagger.json + SpecURL string + + // Title for the documentation site, default to: API documentation + Title string + + // Template specifies a custom template to serve the UI + Template string +} + +// toFuncOptions bridges the deprecated options struct with the newer function options in [docui]. +func (o UIOptions) toFuncOptions() []docui.Option { + const structMembers = 5 + opts := make([]docui.Option, 0, structMembers) + + if o.BasePath != "" { + opts = append(opts, docui.WithUIBasePath(o.BasePath)) + } + + if o.Path != "" { + opts = append(opts, docui.WithUIPath(o.Path)) + } + + if o.SpecURL != "" { + opts = append(opts, docui.WithSpecURL(o.SpecURL)) + } + + if o.Title != "" { + opts = append(opts, docui.WithUITitle(o.Title)) + } + + if o.Template != "" { + opts = append(opts, docui.WithUITemplate(o.Template)) + } + + return opts +} + +// RapiDocOpts configures the [RapiDoc] middlewares. +// +// Deprecated: use instead the function options provided by [docui]. +type RapiDocOpts struct { + // BasePath for the UI, defaults to: / + BasePath string + + // Path combines with BasePath to construct the path to the UI, defaults to: "docs". + Path string + + // SpecURL is the URL of the spec document. + // + // Defaults to: /swagger.json + SpecURL string + + // Title for the documentation site, default to: API documentation + Title string + + // Template specifies a custom template to serve the UI + Template string + + // RapiDocURL points to the js asset that generates the rapidoc site. + // + // Defaults to https://unpkg.com/rapidoc/dist/rapidoc-min.js + RapiDocURL string +} + +func (o RapiDocOpts) toFuncOptions() []docui.Option { + const structMembers = 6 + opts := make([]docui.Option, 0, structMembers) + + if o.BasePath != "" { + opts = append(opts, docui.WithUIBasePath(o.BasePath)) + } + + if o.Path != "" { + opts = append(opts, docui.WithUIPath(o.Path)) + } + + if o.SpecURL != "" { + opts = append(opts, docui.WithSpecURL(o.SpecURL)) + } + + if o.Title != "" { + opts = append(opts, docui.WithUITitle(o.Title)) + } + + if o.Template != "" { + opts = append(opts, docui.WithUITemplate(o.Template)) + } + + if o.RapiDocURL != "" { + opts = append(opts, docui.WithUIAssetsURL(o.RapiDocURL)) + } + + return opts +} + +// RedocOpts configures the [Redoc] middlewares. +// +// Deprecated: use instead the function options provided by [docui]. +type RedocOpts struct { + // BasePath for the UI, defaults to: / + BasePath string + + // Path combines with BasePath to construct the path to the UI, defaults to: "docs". + Path string + + // SpecURL is the URL of the spec document. + // + // Defaults to: /swagger.json + SpecURL string + + // Title for the documentation site, default to: API documentation + Title string + + // Template specifies a custom template to serve the UI + Template string + + // RedocURL points to the js that generates the redoc site. + // + // Defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js + RedocURL string +} + +func (o RedocOpts) toFuncOptions() []docui.Option { + const structMembers = 6 + opts := make([]docui.Option, 0, structMembers) + + if o.BasePath != "" { + opts = append(opts, docui.WithUIBasePath(o.BasePath)) + } + + if o.Path != "" { + opts = append(opts, docui.WithUIPath(o.Path)) + } + + if o.SpecURL != "" { + opts = append(opts, docui.WithSpecURL(o.SpecURL)) + } + + if o.Title != "" { + opts = append(opts, docui.WithUITitle(o.Title)) + } + + if o.Template != "" { + opts = append(opts, docui.WithUITemplate(o.Template)) + } + + if o.RedocURL != "" { + opts = append(opts, docui.WithUIAssetsURL(o.RedocURL)) + } + + return opts +} + +// SwaggerUIOpts configures the [SwaggerUI] [middleware]. +// +// Deprecated: use instead the function options provided by [docui]. +type SwaggerUIOpts struct { + // BasePath for the API, defaults to: / + BasePath string + + // Path combines with BasePath to construct the path to the UI, defaults to: "docs". + Path string + + // SpecURL is the URL of the spec document. + // + // Defaults to: /swagger.json + SpecURL string + + // Title for the documentation site, default to: API documentation + Title string + + // Template specifies a custom template to serve the UI + Template string + + // OAuthCallbackURL the url called after OAuth2 login + // + // NOTE: in the new [docui.SwaggerUIOptions] type, this field is named `OAuth2CallbackURL`, + // which is more appropriate. + OAuthCallbackURL string + + // The three components needed to embed swagger-ui + + // SwaggerURL points to the js that generates the SwaggerUI site. + // + // Defaults to: https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js + SwaggerURL string + + SwaggerPresetURL string + SwaggerStylesURL string + + Favicon32 string + Favicon16 string +} + +func (o SwaggerUIOpts) toFuncOptions() []docui.Option { + const structMembers = 6 + opts := make([]docui.Option, 0, structMembers) + + if o.BasePath != "" { + opts = append(opts, docui.WithUIBasePath(o.BasePath)) + } + + if o.Path != "" { + opts = append(opts, docui.WithUIPath(o.Path)) + } + + if o.SpecURL != "" { + opts = append(opts, docui.WithSpecURL(o.SpecURL)) + } + + if o.Title != "" { + opts = append(opts, docui.WithUITitle(o.Title)) + } + + if o.Template != "" { + opts = append(opts, docui.WithUITemplate(o.Template)) + } + + if o.SwaggerURL != "" { + opts = append(opts, docui.WithUIAssetsURL(o.SwaggerURL)) + } + + var empty SwaggerUIOpts + if o != empty { + swaggeruiOpts := docui.SwaggerUIOptions{ + OAuth2CallbackURL: o.OAuthCallbackURL, + SwaggerPresetURL: o.SwaggerPresetURL, + SwaggerStylesURL: o.SwaggerStylesURL, + Favicon32: o.Favicon32, + Favicon16: o.Favicon16, + } + opts = append(opts, docui.WithSwaggerUIOptions(swaggeruiOpts)) + } + + return opts +} + +// UIOption can be applied to UI serving [middleware] to alter the default +// behavior. +// +// Deprecated: use instead the function options provided by [docui]. +type UIOption func(*UIOptions) + +// uiOptionsWithDefaults applies the given options on top of an empty +// [UIOptions]. Per-flavor handlers ([SwaggerUI], [Redoc], [RapiDoc]) +// fill in the remaining defaults via [UIOptions.EnsureDefaults] when +// the option struct is used. +func uiOptionsWithDefaults(opts []UIOption) UIOptions { + var o UIOptions + for _, apply := range opts { + apply(&o) + } + + return o +} + +// WithUIBasePath sets the base path from where to serve the UI assets. +// +// Deprecated: use instead the function options provided by [docui]. +func WithUIBasePath(base string) UIOption { + return func(o *UIOptions) { + if !strings.HasPrefix(base, "/") { + base = "/" + base + } + o.BasePath = base + } +} + +// WithUIPath sets the path from where to serve the UI assets (i.e. /{basepath}/{path}. +// +// Deprecated: use instead the function options provided by [docui]. +func WithUIPath(pth string) UIOption { + return func(o *UIOptions) { + o.Path = pth + } +} + +// WithUISpecURL sets the path from where to serve swagger spec document. +// +// This may be specified as a full URL or a path. +// +// By default, this is "/swagger.json". +// +// Deprecated: use instead the function options provided by [docui]. +func WithUISpecURL(specURL string) UIOption { + return func(o *UIOptions) { + o.SpecURL = specURL + } +} + +// WithUITitle sets the title of the UI. +// +// Deprecated: use instead the function options provided by [docui]. +func WithUITitle(title string) UIOption { + return func(o *UIOptions) { + o.Title = title + } +} + +// WithTemplate allows to set a custom template for the UI. +// +// UI [middleware] will panic if the template does not parse or execute properly. +// +// Deprecated: use instead the function options provided by [docui]. +func WithTemplate(tpl string) UIOption { + return func(o *UIOptions) { + o.Template = tpl + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/spec.go b/vendor/github.com/go-openapi/runtime/middleware/spec.go deleted file mode 100644 index 0a64a9572b5..00000000000 --- a/vendor/github.com/go-openapi/runtime/middleware/spec.go +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package middleware - -import ( - "net/http" - "path" -) - -const ( - contentTypeHeader = "Content-Type" - applicationJSON = "application/json" -) - -// SpecOption can be applied to the Spec serving [middleware]. -type SpecOption func(*specOptions) - -var defaultSpecOptions = specOptions{ - Path: "", - Document: "swagger.json", -} - -type specOptions struct { - Path string - Document string -} - -func specOptionsWithDefaults(opts []SpecOption) specOptions { - o := defaultSpecOptions - for _, apply := range opts { - apply(&o) - } - - return o -} - -// Spec creates a [middleware] to serve a swagger spec as a JSON document. -// -// This allows for altering the spec before starting the [http] listener. -// -// The basePath argument indicates the path of the spec document (defaults to "/"). -// Additional [SpecOption] can be used to change the name of the document (defaults to "swagger.json"). -func Spec(basePath string, b []byte, next http.Handler, opts ...SpecOption) http.Handler { - if basePath == "" { - basePath = "/" - } - o := specOptionsWithDefaults(opts) - pth := path.Join(basePath, o.Path, o.Document) - - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - if path.Clean(r.URL.Path) == pth { - rw.Header().Set(contentTypeHeader, applicationJSON) - rw.WriteHeader(http.StatusOK) - _, _ = rw.Write(b) - - return - } - - if next != nil { - next.ServeHTTP(rw, r) - - return - } - - rw.Header().Set(contentTypeHeader, applicationJSON) - rw.WriteHeader(http.StatusNotFound) - }) -} - -// WithSpecPath sets the path to be joined to the base path of the Spec [middleware]. -// -// This is empty by default. -func WithSpecPath(pth string) SpecOption { - return func(o *specOptions) { - o.Path = pth - } -} - -// WithSpecDocument sets the name of the JSON document served as a spec. -// -// By default, this is "swagger.json". -func WithSpecDocument(doc string) SpecOption { - return func(o *specOptions) { - if doc == "" { - return - } - - o.Document = doc - } -} diff --git a/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go b/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go deleted file mode 100644 index 14ed37ced69..00000000000 --- a/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package middleware - -import ( - "bytes" - "fmt" - "html/template" - "net/http" - "path" -) - -// SwaggerUIOpts configures the [SwaggerUI] [middleware]. -type SwaggerUIOpts struct { - // BasePath for the API, defaults to: / - BasePath string - - // Path combines with BasePath to construct the path to the UI, defaults to: "docs". - Path string - - // SpecURL is the URL of the spec document. - // - // Defaults to: /swagger.json - SpecURL string - - // Title for the documentation site, default to: API documentation - Title string - - // Template specifies a custom template to serve the UI - Template string - - // OAuthCallbackURL the url called after OAuth2 login - OAuthCallbackURL string - - // The three components needed to embed swagger-ui - - // SwaggerURL points to the js that generates the SwaggerUI site. - // - // Defaults to: https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js - SwaggerURL string - - SwaggerPresetURL string - SwaggerStylesURL string - - Favicon32 string - Favicon16 string -} - -// EnsureDefaults in case some options are missing. -func (r *SwaggerUIOpts) EnsureDefaults() { - r.ensureDefaults() - - if r.Template == "" { - r.Template = swaggeruiTemplate - } -} - -func (r *SwaggerUIOpts) EnsureDefaultsOauth2() { - r.ensureDefaults() - - if r.Template == "" { - r.Template = swaggerOAuthTemplate - } -} - -func (r *SwaggerUIOpts) ensureDefaults() { - common := toCommonUIOptions(r) - common.EnsureDefaults() - fromCommonToAnyOptions(common, r) - - // swaggerui-specifics - if r.OAuthCallbackURL == "" { - r.OAuthCallbackURL = path.Join(r.BasePath, r.Path, "oauth2-callback") - } - if r.SwaggerURL == "" { - r.SwaggerURL = swaggerLatest - } - if r.SwaggerPresetURL == "" { - r.SwaggerPresetURL = swaggerPresetLatest - } - if r.SwaggerStylesURL == "" { - r.SwaggerStylesURL = swaggerStylesLatest - } - if r.Favicon16 == "" { - r.Favicon16 = swaggerFavicon16Latest - } - if r.Favicon32 == "" { - r.Favicon32 = swaggerFavicon32Latest - } -} - -// SwaggerUI creates a [middleware] to serve a documentation site for a swagger spec. -// -// This allows for altering the spec before starting the [http] listener. -func SwaggerUI(opts SwaggerUIOpts, next http.Handler) http.Handler { - opts.EnsureDefaults() - - pth := path.Join(opts.BasePath, opts.Path) - tmpl := template.Must(template.New("swaggerui").Parse(opts.Template)) - assets := bytes.NewBuffer(nil) - if err := tmpl.Execute(assets, opts); err != nil { - panic(fmt.Errorf("cannot execute template: %w", err)) - } - - return serveUI(pth, assets.Bytes(), next) -} - -const ( - swaggerLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js" - swaggerPresetLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js" - swaggerStylesLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui.css" - swaggerFavicon32Latest = "https://unpkg.com/swagger-ui-dist/favicon-32x32.png" - swaggerFavicon16Latest = "https://unpkg.com/swagger-ui-dist/favicon-16x16.png" - swaggeruiTemplate = ` - - - - - {{ .Title }} - - - - - - - - -
- - - - - - -` -) diff --git a/vendor/github.com/go-openapi/runtime/middleware/typeutils.go b/vendor/github.com/go-openapi/runtime/middleware/typeutils.go new file mode 100644 index 00000000000..3f7d7976a1f --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/typeutils.go @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package middleware + +import "strings" + +// normalizeOffer strips the parameter section (";...") from a media-type +// string. +func normalizeOffer(orig string) string { + // NOTE(maintainers): Despite its name (kept for historical reasons), this helper is + // not about Accept negotiation — it is used to derive the bare type that + // keys the producer/consumer maps registered on a [RoutableAPI]. + // Those maps are looked up by the bare media type, so an entry registered as + // "application/json" satisfies a route that declares "application/json; + // charset=utf-8" and vice-versa. + const maxParts = 2 + + return strings.SplitN(orig, ";", maxParts)[0] +} + +// normalizeOffers is the slice form of [normalizeOffer]. +func normalizeOffers(orig []string) []string { + norm := make([]string, 0, len(orig)) + for _, o := range orig { + norm = append(norm, normalizeOffer(o)) + } + + return norm +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/ui_options.go b/vendor/github.com/go-openapi/runtime/middleware/ui_options.go deleted file mode 100644 index ed255426ad8..00000000000 --- a/vendor/github.com/go-openapi/runtime/middleware/ui_options.go +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers -// SPDX-License-Identifier: Apache-2.0 - -package middleware - -import ( - "bytes" - "encoding/gob" - "fmt" - "net/http" - "path" - "strings" -) - -const ( - // constants that are common to all UI-serving middlewares. - defaultDocsPath = "docs" - defaultDocsURL = "/swagger.json" - defaultDocsTitle = "API Documentation" -) - -// uiOptions defines common options for UI serving middlewares. -type uiOptions struct { - // BasePath for the UI, defaults to: / - BasePath string - - // Path combines with BasePath to construct the path to the UI, defaults to: "docs". - Path string - - // SpecURL is the URL of the spec document. - // - // Defaults to: /swagger.json - SpecURL string - - // Title for the documentation site, default to: API documentation - Title string - - // Template specifies a custom template to serve the UI - Template string -} - -// toCommonUIOptions converts any UI option type to retain the common options. -// -// This uses gob encoding/decoding to convert common fields from one struct to another. -func toCommonUIOptions(opts any) uiOptions { - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - dec := gob.NewDecoder(&buf) - var o uiOptions - err := enc.Encode(opts) - if err != nil { - panic(err) - } - - err = dec.Decode(&o) - if err != nil { - panic(err) - } - - return o -} - -func fromCommonToAnyOptions[T any](source uiOptions, target *T) { - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - dec := gob.NewDecoder(&buf) - err := enc.Encode(source) - if err != nil { - panic(err) - } - - err = dec.Decode(target) - if err != nil { - panic(err) - } -} - -// UIOption can be applied to UI serving [middleware], such as Context.[APIHandler] or -// Context.[APIHandlerSwaggerUI] to alter the default behavior. -type UIOption func(*uiOptions) - -func uiOptionsWithDefaults(opts []UIOption) uiOptions { - var o uiOptions - for _, apply := range opts { - apply(&o) - } - - return o -} - -// WithUIBasePath sets the base path from where to serve the UI assets. -// -// By default, Context [middleware] sets this value to the API base path. -func WithUIBasePath(base string) UIOption { - return func(o *uiOptions) { - if !strings.HasPrefix(base, "/") { - base = "/" + base - } - o.BasePath = base - } -} - -// WithUIPath sets the path from where to serve the UI assets (i.e. /{basepath}/{path}. -func WithUIPath(pth string) UIOption { - return func(o *uiOptions) { - o.Path = pth - } -} - -// WithUISpecURL sets the path from where to serve swagger spec document. -// -// This may be specified as a full URL or a path. -// -// By default, this is "/swagger.json". -func WithUISpecURL(specURL string) UIOption { - return func(o *uiOptions) { - o.SpecURL = specURL - } -} - -// WithUITitle sets the title of the UI. -// -// By default, Context [middleware] sets this value to the title found in the API spec. -func WithUITitle(title string) UIOption { - return func(o *uiOptions) { - o.Title = title - } -} - -// WithTemplate allows to set a custom template for the UI. -// -// UI [middleware] will panic if the template does not parse or execute properly. -func WithTemplate(tpl string) UIOption { - return func(o *uiOptions) { - o.Template = tpl - } -} - -// EnsureDefaults in case some options are missing. -func (r *uiOptions) EnsureDefaults() { - if r.BasePath == "" { - r.BasePath = "/" - } - if r.Path == "" { - r.Path = defaultDocsPath - } - if r.SpecURL == "" { - r.SpecURL = defaultDocsURL - } - if r.Title == "" { - r.Title = defaultDocsTitle - } -} - -// serveUI creates a middleware that serves a templated asset as text/html. -func serveUI(pth string, assets []byte, next http.Handler) http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - if path.Clean(r.URL.Path) == pth { - rw.Header().Set(contentTypeHeader, "text/html; charset=utf-8") - rw.WriteHeader(http.StatusOK) - _, _ = rw.Write(assets) - - return - } - - if next != nil { - next.ServeHTTP(rw, r) - - return - } - - rw.Header().Set(contentTypeHeader, "text/plain") - rw.WriteHeader(http.StatusNotFound) - _, _ = fmt.Fprintf(rw, "%q not found", pth) - }) -} diff --git a/vendor/github.com/go-openapi/runtime/middleware/validation.go b/vendor/github.com/go-openapi/runtime/middleware/validation.go index 8a56490639e..63a78d482a8 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/validation.go +++ b/vendor/github.com/go-openapi/runtime/middleware/validation.go @@ -4,13 +4,14 @@ package middleware import ( - "mime" + stderrors "errors" "net/http" "strings" "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" - "github.com/go-openapi/swag/stringutils" + "github.com/go-openapi/runtime/server-middleware/mediatype" ) type validation struct { @@ -21,24 +22,28 @@ type validation struct { bound map[string]any } -// ContentType validates the content type of a request. -func validateContentType(allowed []string, actual string) error { +// validateContentType maps [mediatype.MatchFirst] to the runtime's +// validation errors: +// +// - actual fails to parse → HTTP 400 ([errors.NewParseError]). +// - actual is well-formed but +// no allowed entry accepts it → HTTP 415 ([errors.InvalidContentType]). +// +// In the standard runtime flow, malformed Content-Type headers are +// already caught upstream by [runtime.ContentType] (which itself returns +// a 400 [errors.ParseError]). This function therefore only sees the +// malformed case when invoked directly by callers that have bypassed +// that step. +func validateContentType(allowed []string, actual string, opts ...mediatype.MatchOption) error { if len(allowed) == 0 { return nil } - mt, _, err := mime.ParseMediaType(actual) - if err != nil { - return errors.InvalidContentType(actual, allowed) - } - if stringutils.ContainsStringsCI(allowed, mt) { - return nil - } - if stringutils.ContainsStringsCI(allowed, "*/*") { + _, ok, err := mediatype.MatchFirst(allowed, actual, opts...) + if ok { return nil } - parts := strings.Split(actual, "/") - if len(parts) == 2 && stringutils.ContainsStringsCI(allowed, parts[0]+"/*") { - return nil + if err != nil { + return errors.NewParseError(runtime.HeaderContentType, "header", actual, err) } return errors.InvalidContentType(actual, allowed) } @@ -69,46 +74,53 @@ func (v *validation) debugLogf(format string, args ...any) { func (v *validation) parameters() { v.debugLogf("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath()) - if result := v.route.Binder.Bind(v.request, v.route.Params, v.route.Consumer, v.bound); result != nil { - if result.Error() == "validation failure list" { - for _, e := range result.(*errors.Validation).Value.([]any) { - v.result = append(v.result, e.(error)) - } - return + result := v.route.Binder.bind(v.request, v.route.Params, v.route.Consumer, v.bound) + if result == nil { + return + } + + for _, e := range result.Errors { + var validationErr *errors.Validation + if stderrors.As(e, &validationErr) { + v.result = append(v.result, validationErr) } - v.result = append(v.result, result) } } func (v *validation) contentType() { - if len(v.result) == 0 && runtime.HasBody(v.request) { - v.debugLogf("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath()) - ct, _, req, err := v.context.ContentType(v.request) - if err != nil { + if len(v.result) > 0 || !runtime.HasBody(v.request) { + return + } + + v.debugLogf("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath()) + ct, _, req, err := v.context.ContentType(v.request) + if err != nil { + v.result = append(v.result, err) + } else { + v.request = req + } + + if len(v.result) == 0 { + v.debugLogf("validating content type for %q against [%s]", ct, strings.Join(v.route.Consumes, ", ")) + if err := validateContentType(v.route.Consumes, ct, v.context.matchOpts()...); err != nil { v.result = append(v.result, err) - } else { - v.request = req } + } - if len(v.result) == 0 { - v.debugLogf("validating content type for %q against [%s]", ct, strings.Join(v.route.Consumes, ", ")) - if err := validateContentType(v.route.Consumes, ct); err != nil { - v.result = append(v.result, err) - } - } - if ct != "" && v.route.Consumer == nil { - cons, ok := v.route.Consumers[ct] - if !ok { - v.result = append(v.result, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct)) - } else { - v.route.Consumer = cons - } - } + if ct == "" || v.route.Consumer != nil { + return + } + + cons, ok := mediatype.Lookup(v.route.Consumers, ct, v.context.matchOpts()...) + if !ok { + v.result = append(v.result, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct)) + } else { + v.route.Consumer = cons } } func (v *validation) responseFormat() { - // if the route provides values for Produces and no format could be identify then return an error. + // if the route provides values for Produces and no format could be identified then return an error. // if the route does not specify values for Produces then treat request as valid since the API designer // choose not to specify the format for responses. if str, rCtx := v.context.ResponseFormat(v.request, v.route.Produces); str == "" && len(v.route.Produces) > 0 { diff --git a/vendor/github.com/go-openapi/runtime/multipart_stream.go b/vendor/github.com/go-openapi/runtime/multipart_stream.go new file mode 100644 index 00000000000..76e1bf4607a --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/multipart_stream.go @@ -0,0 +1,556 @@ +// SPDX-FileCopyrightText: Copyright 2015-2026 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package runtime + +import ( + "context" + stderrors "errors" + "fmt" + "io" + "mime" + "mime/multipart" + "net/http" + "net/textproto" + "net/url" + + "github.com/go-openapi/errors" +) + +// MultipartFormStreamOption configures [NewMultipartFormStream]. +type MultipartFormStreamOption func(*multipartFormStreamConfig) + +const defaultMultipartFormStreamMaxParts = 1000 + +type multipartFormStreamConfig struct { + multipartFormLimits + + maxParts int +} + +// MultipartFormStreamMaxBody caps the total number of request-body bytes read +// by a [MultipartFormStream]. +// +// A value of 0 applies [DefaultMaxUploadBodySize]. A negative value disables +// the cap when the caller has already limited the request body upstream. +func MultipartFormStreamMaxBody(n int64) MultipartFormStreamOption { + return func(c *multipartFormStreamConfig) { c.maxBody = n } +} + +// MultipartFormStreamMaxFiles rejects a multipart stream after more than n +// file parts have been encountered. A value of 0 means no file-count cap. +func MultipartFormStreamMaxFiles(n int) MultipartFormStreamOption { + return func(c *multipartFormStreamConfig) { c.maxFiles = n } +} + +// MultipartFormStreamMaxParts rejects a multipart stream after more than n +// total parts have been encountered. The default is 1000, matching +// [multipart.Reader.ReadForm]. A value of 0 disables the limit. +func MultipartFormStreamMaxParts(n int) MultipartFormStreamOption { + return func(c *multipartFormStreamConfig) { c.maxParts = n } +} + +// MultipartFormStreamMaxFilenameLen rejects file parts whose filename exceeds +// n bytes. A value of 0 disables the limit. When this option is not supplied, +// [DefaultMaxUploadFilenameLength] is used. +func MultipartFormStreamMaxFilenameLen(n int) MultipartFormStreamOption { + return func(c *multipartFormStreamConfig) { c.maxFilenameLen = n } +} + +// StreamedFile exposes a file part directly from the multipart request body. +// +// Reads block until bytes arrive from the client. StreamedFile is not seekable +// and is not safe for concurrent use. Its form name, filename and MIME headers +// are available before the payload is consumed. The underlying [multipart.Part] +// remains private so callers cannot bypass Close and its error-preserving drain +// semantics; Header exposes the part metadata without exposing that lifecycle. +// +// Closing a StreamedFile drains only the unread remainder of that file part. +// Close may therefore block while the client is still uploading the current +// part. The owning [MultipartFormStream] may then advance to the next part. +type StreamedFile struct { + FieldName string + Filename string + Header textproto.MIMEHeader + part *multipart.Part + closeErr error +} + +// MultipartFileInfo describes a file part discovered by [MultipartFormStream]. +// +// The payload reader is intentionally omitted. File parts remain sequential and +// are consumed through [MultipartFormStream.NextFile]. Header is a snapshot of +// the client-supplied MIME headers and must be treated as untrusted input. +type MultipartFileInfo struct { + FieldName string + Filename string + Header textproto.MIMEHeader +} + +// Read reads file payload bytes directly from the request body. +func (f *StreamedFile) Read(p []byte) (int, error) { + if f == nil || f.part == nil { + return 0, io.ErrClosedPipe + } + + return f.part.Read(p) +} + +// Close discards the unread remainder of this file part. +// +// Close does not close the underlying HTTP request body and does not consume +// subsequent multipart parts. After Close returns successfully, the parent +// MultipartFormStream may advance to the next part. +// +// Any error encountered while discarding the unread payload is returned. +func (f *StreamedFile) Close() error { + if f == nil { + return nil + } + if f.part == nil { + return f.closeErr + } + + part := f.part + f.part = nil + // multipart.Part.Close drains with io.Copy but intentionally discards the + // resulting error, so drain explicitly to preserve error propagation. + _, f.closeErr = io.Copy(io.Discard, part) + + return f.closeErr +} + +// MultipartFormStream reads multipart/form-data sequentially without parsing +// the complete request body before exposing file payloads. +// +// [MultipartFormStream.NextFile] consumes ordinary form fields until it reaches +// the next file part. Fields are appended to request.PostForm and request.Form +// as they are encountered. Consequently, fields after a file become visible +// only after the caller consumes or closes that file and advances the stream. +// +// A stream and its returned files are not safe for concurrent use. There is at +// most one active file part. Calling [MultipartFormStream.NextFile] closes and +// drains an unread active file before advancing, and may therefore block until +// the current part finishes arriving. No background goroutines are started. +// +// The caller owns the stream. Call [MultipartFormStream.Drain] to consume the +// remaining body, collect trailing fields and allow HTTP connection reuse when +// possible. Call [MultipartFormStream.Close] to stop multipart processing +// without explicitly draining the remaining parts. +// +// [MultipartFormStream.Fields] and [MultipartFormStream.Files] expose snapshots +// of the multipart fields and file metadata discovered so far. They never read +// ahead: fields or files after the active file become visible only after the +// stream advances. +type MultipartFormStream struct { + multipartFormStreamConfig + + request *http.Request + reader *multipart.Reader + current *StreamedFile + + fields url.Values + fileInfos []MultipartFileInfo + parts int + closed bool + done bool +} + +// NewMultipartFormStream creates a sequential multipart/form-data stream over +// r.Body. +// +// For POST, PUT and PATCH requests, the constructor accepts only +// multipart/form-data, validates that a non-empty boundary is present, but does +// not consume multipart parts. For other methods, it returns an empty stream +// whose NextFile method reports io.EOF without reading the request body. +// +// The constructor initializes request.Form and request.PostForm in the same way +// as [http.Request.ParseForm], then populates multipart values incrementally as +// [MultipartFormStream.NextFile] advances. +// +// For POST, PUT and PATCH requests, NewMultipartFormStream marks the request +// as handled by MultipartReader. Callers must not subsequently call +// [http.Request.ParseMultipartForm] or [BindForm] for the same request. +// +// File payloads are exposed directly from the request body and are not buffered +// in memory or temporary files. Ordinary form values are read into memory as +// they are encountered. Parts are processed in wire order. +// +// At most one StreamedFile may be active at a time. Calling +// [MultipartFormStream.NextFile] automatically closes and drains an unread +// current file before advancing. No background goroutines are started. +// +// MultipartFormStream is not safe for concurrent use. +// +// File names and MIME headers are supplied by the client and remain untrusted. +func NewMultipartFormStream(r *http.Request, opts ...MultipartFormStreamOption) (*MultipartFormStream, error) { + cfg := multipartFormStreamConfig{ + multipartFormLimits: multipartFormLimits{ + maxFilenameLen: DefaultMaxUploadFilenameLength, + }, + maxParts: defaultMultipartFormStreamMaxParts, + } + for _, opt := range opts { + opt(&cfg) + } + + if r == nil { + return nil, errors.NewParseError("body", "formData", "", stderrors.New("nil request")) + } + + if !supportsMultipartFormStream(r.Method) { + if err := r.ParseForm(); err != nil { + return nil, errors.NewParseError("body", "formData", "", err) + } + + return &MultipartFormStream{ + request: r, + multipartFormStreamConfig: cfg, + fields: make(url.Values), + done: true, + }, nil + } + + if r.Body == nil { + return nil, errors.NewParseError("body", "formData", "", stderrors.New("nil request body")) + } + + contentType := r.Header.Get(HeaderContentType) + mediaType, params, err := mime.ParseMediaType(contentType) + if err != nil { + return nil, errors.NewParseError(HeaderContentType, "header", contentType, err) + } + if mediaType != MultipartFormMime { + return nil, errors.NewParseError(HeaderContentType, "header", mediaType, http.ErrNotMultipart) + } + if params["boundary"] == "" { + return nil, errors.NewParseError(HeaderContentType, "header", contentType, http.ErrMissingBoundary) + } + if err = r.ParseForm(); err != nil { + return nil, errors.NewParseError("body", "formData", "", err) + } + + body := r.Body + if cfg.maxBody >= 0 { + maxBody := cfg.maxBody + if maxBody == 0 { + maxBody = DefaultMaxUploadBodySize + } + body = http.MaxBytesReader(nil, body, maxBody) + } + body = &contextReadCloser{ctx: r.Context(), ReadCloser: body} + r.Body = body + + reader, err := r.MultipartReader() + if err != nil { + return nil, errors.NewParseError("body", "formData", "", err) + } + + return &MultipartFormStream{ + request: r, + reader: reader, + multipartFormStreamConfig: cfg, + fields: make(url.Values), + }, nil +} + +// Fields returns a snapshot of ordinary multipart form fields discovered so far. +// +// URL query values are not included. Repeated multipart fields preserve their +// encounter order. Fields after the active file are not visible until that file +// is consumed or closed and the stream advances. Mutating the returned values +// does not affect the stream or the request. +func (s *MultipartFormStream) Fields() url.Values { + if s == nil { + return nil + } + + return cloneMultipartValues(s.fields) +} + +// Files returns snapshots of file metadata discovered so far in wire order. +// +// The currently active file is included as soon as NextFile returns it. Payload +// readers are not retained in the index. Mutating the returned slice or MIME +// headers does not affect the stream. +func (s *MultipartFormStream) Files() []MultipartFileInfo { + if s == nil { + return nil + } + + files := make([]MultipartFileInfo, len(s.fileInfos)) + for i, file := range s.fileInfos { + files[i] = MultipartFileInfo{ + FieldName: file.FieldName, + Filename: file.Filename, + Header: cloneMultipartMIMEHeader(file.Header), + } + } + + return files +} + +// NextFile advances through the multipart body and returns the next file part. +// Ordinary form fields encountered before that file are added to request.Form +// and request.PostForm. +// +// If the previously returned file is still open, NextFile closes and drains it +// before advancing. This may block while the client is still uploading that +// part. Any drain error is returned and the stream is aborted. +// +// NextFile returns io.EOF when no file parts remain. At that point all trailing +// ordinary fields have been collected. +func (s *MultipartFormStream) NextFile() (*StreamedFile, error) { + if err := s.prepareNextFile(); err != nil { + return nil, err + } + + return s.readNextFile() +} + +// Drain consumes the rest of the multipart body. +// +// Unread file payloads are discarded. Non-file form fields encountered while +// draining are collected in the request form values. +// +// Drain closes the underlying request body after reaching EOF. Subsequent calls +// to NextFile return io.EOF. Drain returns any multipart parsing, payload drain +// or request-body close error. +func (s *MultipartFormStream) Drain() error { + if s == nil || s.closed { + return nil + } + + for { + file, err := s.NextFile() + if stderrors.Is(err, io.EOF) { + return s.Close() + } + if err != nil { + return stderrors.Join(err, s.Close()) + } + if err = file.Close(); err != nil { + return stderrors.Join(err, s.Close()) + } + } +} + +// Close stops multipart processing and closes the underlying HTTP request body +// without explicitly draining the remaining multipart parts. +// +// The concrete request body may perform its own work during Close. In +// particular, a net/http server request body may discard a limited amount of +// unread data to allow connection reuse, so Close is not guaranteed to return +// immediately. Call Drain when trailing form fields must be collected. +func (s *MultipartFormStream) Close() error { + if s == nil || s.closed { + return nil + } + + s.closed = true + if s.current != nil { + s.current.part = nil + s.current = nil + } + + if s.request == nil || s.request.Body == nil { + return nil + } + + return s.request.Body.Close() +} + +func supportsMultipartFormStream(method string) bool { + switch method { + case http.MethodPost, http.MethodPut, http.MethodPatch: + return true + default: + return false + } +} + +func (s *MultipartFormStream) abort(err error) error { + return stderrors.Join(err, s.Close()) +} + +func (s *MultipartFormStream) closeCurrent() error { + if s.current == nil { + return nil + } + + err := s.current.Close() + s.current = nil + + return err +} + +func (s *MultipartFormStream) bindValue(part *multipart.Part, name string) error { + value, err := io.ReadAll(part) + if err != nil { + return err + } + + s.fields.Add(name, string(value)) + s.request.PostForm.Add(name, string(value)) + // Match net/http.ParseMultipartForm: query values already present in Form + // keep precedence over multipart body values, which are appended. + s.request.Form.Add(name, string(value)) + + return nil +} + +func discardPart(part *multipart.Part) error { + _, err := io.Copy(io.Discard, part) + + return err +} + +func cloneMultipartValues(values url.Values) url.Values { + cloned := make(url.Values, len(values)) + for name, entries := range values { + cloned[name] = append([]string(nil), entries...) + } + + return cloned +} + +func cloneMultipartMIMEHeader(header textproto.MIMEHeader) textproto.MIMEHeader { + cloned := make(textproto.MIMEHeader, len(header)) + for name, entries := range header { + cloned[name] = append([]string(nil), entries...) + } + + return cloned +} + +type contextReadCloser struct { + io.ReadCloser + + ctx context.Context //nolint:containedctx // Read has no context parameter, so the wrapper must retain it +} + +func (r *contextReadCloser) Read(p []byte) (int, error) { + if err := r.ctx.Err(); err != nil { + return 0, err + } + + return r.ReadCloser.Read(p) +} + +func (s *MultipartFormStream) prepareNextFile() error { + if s == nil { + return io.ErrClosedPipe + } + if s.done { + return io.EOF + } + if s.closed { + return io.ErrClosedPipe + } + if err := s.closeCurrent(); err != nil { + return s.abort(err) + } + + return nil +} + +func (s *MultipartFormStream) readNextFile() (*StreamedFile, error) { + for { + part, err := s.reader.NextPart() + if err != nil { + return nil, s.handleNextPartError(err) + } + + s.parts++ + if s.maxParts > 0 && s.parts > s.maxParts { + err := errors.NewParseError( + "body", + "formData", + "", + fmt.Errorf( + "multipart form contains %d parts, exceeds limit %d", + s.parts, + s.maxParts, + ), + ) + + return nil, s.abort(err) + } + + fieldName := part.FormName() + if fieldName == "" { + if err := discardPart(part); err != nil { + return nil, s.abort(err) + } + + continue + } + + filename := part.FileName() + if filename == "" { + if err := s.bindValue(part, fieldName); err != nil { + return nil, s.abort(err) + } + + continue + } + + return s.openFile(part, fieldName, filename) + } +} + +func (s *MultipartFormStream) handleNextPartError(err error) error { + if stderrors.Is(err, io.EOF) { + s.done = true + + return io.EOF + } + + return s.abort(err) +} + +func (s *MultipartFormStream) openFile( + part *multipart.Part, + fieldName string, + filename string, +) (*StreamedFile, error) { + fileCount := len(s.fileInfos) + 1 + if s.maxFiles > 0 && fileCount > s.maxFiles { + err := errors.NewParseError( + "body", + "formData", + "", + fmt.Errorf( + "multipart form contains %d file parts, exceeds limit %d", + fileCount, + s.maxFiles, + ), + ) + + return nil, s.abort(err) + } + + if err := ValidateFilenameLength( + fieldName, + "formData", + filename, + s.maxFilenameLen, + ); err != nil { + return nil, s.abort(err) + } + + file := &StreamedFile{ + FieldName: fieldName, + Filename: filename, + Header: part.Header, + part: part, + } + s.fileInfos = append(s.fileInfos, MultipartFileInfo{ + FieldName: fieldName, + Filename: filename, + Header: cloneMultipartMIMEHeader(part.Header), + }) + s.current = file + + return file, nil +} diff --git a/vendor/github.com/go-openapi/runtime/security/authenticator.go b/vendor/github.com/go-openapi/runtime/security/authenticator.go index 4c091018265..e521d95ef16 100644 --- a/vendor/github.com/go-openapi/runtime/security/authenticator.go +++ b/vendor/github.com/go-openapi/runtime/security/authenticator.go @@ -19,8 +19,8 @@ const ( accessTokenParam = "access_token" ) -// HttpAuthenticator is a function that authenticates a HTTP request. -func HttpAuthenticator(handler func(*http.Request) (bool, any, error)) runtime.Authenticator { //nolint:revive +// HTTPAuthenticator is a function that authenticates a HTTP request. +func HTTPAuthenticator(handler func(*http.Request) (bool, any, error)) runtime.Authenticator { return runtime.AuthenticatorFunc(func(params any) (bool, any, error) { if request, ok := params.(*http.Request); ok { return handler(request) @@ -32,7 +32,14 @@ func HttpAuthenticator(handler func(*http.Request) (bool, any, error)) runtime.A }) } -// ScopedAuthenticator is a function that authenticates a HTTP request against a list of valid scopes. +// HttpAuthenticator aliases [HTTPAuthenticator] for backward-compatibility. +// +// Deprecated: use [HTTPAuthenticator] instead. +func HttpAuthenticator(handler func(*http.Request) (bool, any, error)) runtime.Authenticator { //nolint:revive + return HTTPAuthenticator(handler) +} + +// ScopedAuthenticator is a function that authenticates an [http.Request] against a list of valid scopes. func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, any, error)) runtime.Authenticator { return runtime.AuthenticatorFunc(func(params any) (bool, any, error) { if request, ok := params.(*ScopedAuthRequest); ok { @@ -42,22 +49,42 @@ func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, any, error)) ru }) } -// UserPassAuthentication authentication function. +// UserPassAuthentication validates a basic-auth credential. +// +// Implementations comparing the password (or any derived secret) against a +// known value MUST use [crypto/subtle.ConstantTimeCompare]: the runtime +// extracts the credential from the request and delegates the comparison +// here, and does not enforce a constant-time posture on the caller's behalf. type UserPassAuthentication func(string, string) (any, error) -// UserPassAuthenticationCtx authentication function with [context.Context]. +// UserPassAuthenticationCtx is the [context.Context]-aware variant of +// [UserPassAuthentication]. The same constant-time-comparison guidance +// applies. type UserPassAuthenticationCtx func(context.Context, string, string) (context.Context, any, error) -// TokenAuthentication authentication function. +// TokenAuthentication validates an API-key token. +// +// Implementations comparing the token against a known value MUST use +// [crypto/subtle.ConstantTimeCompare]; the runtime delegates the comparison +// here and does not enforce a constant-time posture on the caller's behalf. type TokenAuthentication func(string) (any, error) -// TokenAuthenticationCtx authentication function with [context.Context]. +// TokenAuthenticationCtx is the [context.Context]-aware variant of +// [TokenAuthentication]. The same constant-time-comparison guidance +// applies. type TokenAuthenticationCtx func(context.Context, string) (context.Context, any, error) -// ScopedTokenAuthentication authentication function. +// ScopedTokenAuthentication validates a bearer/OAuth2 token along with the +// scopes required for the operation. +// +// Implementations comparing the token against a known value MUST use +// [crypto/subtle.ConstantTimeCompare]; the runtime delegates the comparison +// here and does not enforce a constant-time posture on the caller's behalf. type ScopedTokenAuthentication func(string, []string) (any, error) -// ScopedTokenAuthenticationCtx authentication function with [context.Context]. +// ScopedTokenAuthenticationCtx is the [context.Context]-aware variant of +// [ScopedTokenAuthentication]. The same constant-time-comparison guidance +// applies. type ScopedTokenAuthenticationCtx func(context.Context, string, []string) (context.Context, any, error) var DefaultRealmName = "API" @@ -199,7 +226,7 @@ func APIKeyAuthCtx(name, in string, authenticate TokenAuthenticationCtx) runtime }) } -// ScopedAuthRequest contains both a [http] request and the required scopes for a particular operation. +// ScopedAuthRequest contains both the [http.Request] and the required scopes for a particular operation. type ScopedAuthRequest struct { Request *http.Request RequiredScopes []string diff --git a/vendor/github.com/go-openapi/swag/jsonname/LICENSE b/vendor/github.com/go-openapi/runtime/server-middleware/LICENSE similarity index 100% rename from vendor/github.com/go-openapi/swag/jsonname/LICENSE rename to vendor/github.com/go-openapi/runtime/server-middleware/LICENSE diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/docui/doc.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/doc.go new file mode 100644 index 00000000000..809296d5c4f --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/doc.go @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package docui provides standalone HTTP middlewares that serve OpenAPI +// documentation UIs (Swagger UI, ReDoc, RapiDoc) and the spec document +// itself. +// +// The package is stdlib-only and has no transitive dependency on any +// OpenAPI spec, loading or validation library, so it may be imported by +// any net/http application that simply wants to mount a documentation +// site. +package docui diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/docui/options.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/options.go new file mode 100644 index 00000000000..c9e45f77946 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/options.go @@ -0,0 +1,253 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package docui + +import ( + "net/http" + "net/url" + "strings" +) + +const ( + // constants that are common to all UI-serving middlewares. + defaultDocsPath = "docs" + defaultDocsURL = "/swagger.json" + defaultDocsTitle = "API Documentation" + + contentTypeHeader = "Content-Type" + applicationJSON = "application/json" +) + +// UIMiddleware is a function returning a http middleware which accepts UI [Option]. +type UIMiddleware func(...Option) func(http.Handler) http.Handler + +// Option to tune your swagger documentation UI middleware. +// +// Options may be combined to alter the route at which the UI asset is served, +// the URL of the spec document, the source URL of the UI asset and the title of the UI page. +// +// The embedded js scriptlet served may be modified using [WithUITemplate]. +type Option func(*options) + +// SpecOption can be applied to the [ServeSpec] middleware. +type SpecOption func(*specOptions) + +// SwaggerUIOptions define a group of extra options specific to the SwaggerUI component. +type SwaggerUIOptions struct { + // OAuth2CallbackURL sets the URL called after OAuth2 login + OAuth2CallbackURL string + + // Defines the URL of the swagger UI assets with presets. + // + // Default: https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js + SwaggerPresetURL string + + // Defines style sheet URL. + // + // Default: https://unpkg.com/swagger-ui-dist/swagger-ui.css + SwaggerStylesURL string + + // Define the favicons URLs. + // + // Defaults: + // + // - 16x16: https://unpkg.com/swagger-ui-dist/favicon-16x16.png + // - 32x32: https://unpkg.com/swagger-ui-dist/favicon-32x32.png + Favicon32 string + Favicon16 string +} + +func (o *SwaggerUIOptions) applySwaggerUIDefaults() { + if o.SwaggerPresetURL == "" { + o.SwaggerPresetURL = swaggerPresetLatest + } + if o.SwaggerStylesURL == "" { + o.SwaggerStylesURL = swaggerStylesLatest + } + if o.Favicon16 == "" || o.Favicon32 == "" { + o.Favicon16 = swaggerFavicon16Latest + o.Favicon32 = swaggerFavicon32Latest + } +} + +type ( + options struct { + SwaggerUIOptions + + // BasePath for the UI, defaults to: / + BasePath string + + // Path combines with BasePath to construct the path to the UI, defaults to: "docs". + Path string + + // SpecURL is the URL of the spec document. + SpecURL string + + // Title for the documentation site, default to: API documentation + Title string + + // Template specifies a custom template to serve the UI + Template string + + // AssetsURL points to the js asset that generates the documentation page. + AssetsURL string + } + + specOptions struct { + Path string + Document string + } +) + +//////////////////////////////////////////////////////////// +// Common UI options +//////////////////////////////////////////////////////////// + +// WithUIBasePath sets the base path from where to serve the UI assets. +// +// Default: "/" +func WithUIBasePath(base string) Option { + return func(o *options) { + if !strings.HasPrefix(base, "/") { + base = "/" + base + } + o.BasePath = base + } +} + +// WithUIPath sets the path from where to serve the UI assets (i.e. /{basepath}/{path}). +// +// Default: "docs" +func WithUIPath(pth string) Option { + return func(o *options) { + o.Path = pth + } +} + +// WithUITitle sets the title of the UI. +// +// Default: "API documentation" +func WithUITitle(title string) Option { + return func(o *options) { + o.Title = title + } +} + +// WithUIAssetsURL sets the URL from where to fetch the js assets. +// +// Defaults: +// +// - for Redoc: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js +// - for RapiDoc, this defaults to: https://unpkg.com/rapidoc/dist/rapidoc-min.js +// - for SwaggerUI: https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js +func WithUIAssetsURL(assets string) Option { + return func(o *options) { + o.AssetsURL = assets + } +} + +// WithUITemplate allows to set a custom template for the UI. +// +// This allows the caller to fully customize the rendered UI, using the advanced options +// provided by any UI. +// +// The UI [middleware] will panic if the template does not parse or execute properly. +// +// Reference documentations to customize your js scriptlet: +// +// - for Redoc: https://github.com/Redocly/redoc/blob/main/docs/deployment/html.md +// - for RapiDoc: https://github.com/rapi-doc/RapiDoc +// - for SwaggerUI: https://github.com/swagger-api/swagger-ui +func WithUITemplate[StringOrBytes ~string | ~[]byte](tpl StringOrBytes) Option { + return func(o *options) { + o.Template = string(tpl) + } +} + +// WithSpecURL sets the URL of the spec document. +// +// Defaults to: /swagger.json +func WithSpecURL(u string) Option { + return func(o *options) { + o.SpecURL = u + } +} + +//////////////////////////////////////////////////////////// +// SwaggerUI UI options +//////////////////////////////////////////////////////////// + +func WithSwaggerUIOptions(opts SwaggerUIOptions) Option { + return func(o *options) { + o.SwaggerUIOptions = opts + } +} + +//////////////////////////////////////////////////////////// +// Spec options +//////////////////////////////////////////////////////////// + +// WithSpecPath sets the path of the spec document. +// +// This is "/swagger.json" by default. +func WithSpecPath(pth string) SpecOption { + return func(o *specOptions) { + if pth == "" { + return + } + + o.Path = pth + } +} + +// WithSpecPathFromOptions reuses the same SpecPath as the one specified in +// a set of UI [Option] (extract the path from the URL provided by [WithSpecURL]). +func WithSpecPathFromOptions(opts ...Option) SpecOption { + return func(o *specOptions) { + uiOpts := optionsWithDefaults(opts) + + // If the spec URL is provided, there is a non-default path to serve the spec. + // + // This makes sure that the UI middleware is aligned with the Spec middleware. + u, _ := url.Parse(uiOpts.SpecURL) + + if u.Path == "" { + return + } + + o.Path = u.Path + } +} + +func optionsWithDefaults(opts []Option, prepend ...Option) options { + o := options{ + BasePath: "/", + Path: defaultDocsPath, + SpecURL: defaultDocsURL, + Title: defaultDocsTitle, + } + + prepend = append(prepend, opts...) + for _, apply := range prepend { + apply(&o) + } + + return o +} + +func specOptionsWithDefaults(opts []SpecOption) specOptions { + o := specOptions{ + Path: defaultDocsURL, + } + + for _, apply := range opts { + apply(&o) + } + + if !strings.HasPrefix(o.Path, "/") { + o.Path = "/" + o.Path + } + + return o +} diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/docui/rapidoc.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/rapidoc.go new file mode 100644 index 00000000000..c050331b4b0 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/rapidoc.go @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package docui + +import ( + "bytes" + "fmt" + "html/template" + "net/http" + "path" +) + +// UseRapiDoc creates a middleware to serve a documentation site for a swagger spec using [RapidDoc]. +// +// [RapiDoc]: https://github.com/rapi-doc/RapiDoc +func UseRapiDoc(opts ...Option) func(next http.Handler) http.Handler { + pth, assets := rapiDocSetup(opts) + return func(next http.Handler) http.Handler { + return serveUI(pth, assets, next) + } +} + +// RapiDoc creates a [http.Handler] to serve a documentation site for a swagger spec using [RapidDoc]. +// +// By default, the UI is served at route "/docs" +// +// This allows for altering the spec before starting the [http] listener. +// +// [RapiDoc]: https://github.com/rapi-doc/RapiDoc +func RapiDoc(next http.Handler, opts ...Option) http.Handler { + pth, assets := rapiDocSetup(opts) + + return serveUI(pth, assets, next) +} + +func rapiDocSetup(opts []Option) (pth string, assets []byte) { + o := optionsWithDefaults(opts, + // defaults for rapiDoc + WithUITemplate(rapidocTemplate), + WithUIAssetsURL(rapidocLatest), + ) + pth = path.Join(o.BasePath, o.Path) + tmpl := template.Must(template.New("rapidoc").Parse(o.Template)) + buf := bytes.NewBuffer(nil) + if err := tmpl.Execute(buf, o); err != nil { + panic(fmt.Errorf("cannot execute template: %w", err)) + } + + return pth, buf.Bytes() +} + +const ( + rapidocLatest = "https://unpkg.com/rapidoc/dist/rapidoc-min.js" + rapidocTemplate = ` + + + {{ .Title }} + + + + + + + +` +) diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/docui/redoc.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/redoc.go new file mode 100644 index 00000000000..31054a2476e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/redoc.go @@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package docui + +import ( + "bytes" + "fmt" + "html/template" + "net/http" + "path" +) + +// UseRedoc creates a middleware to serve a documentation site for a swagger spec using [Redoc]. +// +// [Redoc]: https://redocly.com/docs/redoc +func UseRedoc(opts ...Option) func(next http.Handler) http.Handler { + pth, assets := redocSetup(opts) + + return func(next http.Handler) http.Handler { + return serveUI(pth, assets, next) + } +} + +// Redoc creates a [http.Handler] to serve a documentation site for a swagger spec using [Redoc]. +// +// By default, the UI is served at route "/docs" +// +// This allows for altering the spec before starting the [http] listener. +// +// [Redoc]: https://redocly.com/docs/redoc +func Redoc(next http.Handler, opts ...Option) http.Handler { + pth, assets := redocSetup(opts) + + return serveUI(pth, assets, next) +} + +func redocSetup(opts []Option) (pth string, assets []byte) { + o := optionsWithDefaults(opts, + // defaults for redoc + WithUITemplate(redocTemplate), + WithUIAssetsURL(redocLatest), + ) + + pth = path.Join(o.BasePath, o.Path) + tmpl := template.Must(template.New("redoc").Parse(o.Template)) + buf := bytes.NewBuffer(nil) + if err := tmpl.Execute(buf, o); err != nil { + panic(fmt.Errorf("cannot execute template: %w", err)) + } + + return pth, buf.Bytes() +} + +const ( + redocLatest = "https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js" // "https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js" + redocTemplate = ` + + + {{ .Title }} + + + + + + + + + + + + + +` +) diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/docui/render.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/render.go new file mode 100644 index 00000000000..1fb744fd005 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/render.go @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package docui + +import ( + "fmt" + "net/http" + "path" +) + +// serveUI creates a [http.Handler] that serves a templated asset as text/html. +func serveUI(pth string, assets []byte, next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + if path.Clean(r.URL.Path) == pth { + rw.Header().Set(contentTypeHeader, "text/html; charset=utf-8") + rw.WriteHeader(http.StatusOK) + _, _ = rw.Write(assets) + + return + } + + if next != nil { + next.ServeHTTP(rw, r) + + return + } + + rw.Header().Set(contentTypeHeader, "text/plain") + rw.WriteHeader(http.StatusNotFound) + _, _ = fmt.Fprintf(rw, "%q not found", pth) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/docui/spec.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/spec.go new file mode 100644 index 00000000000..59780199d5b --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/spec.go @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package docui + +import ( + "net/http" + "path" +) + +// UseSpec creates a middleware to serve a swagger spec as a JSON document. +func UseSpec(spec []byte, opts ...SpecOption) func(next http.Handler) http.Handler { + o := specOptionsWithDefaults(opts) + + return func(next http.Handler) http.Handler { + return handleSpec(o.Path, spec, next) + } +} + +// ServeSpec creates a [http.Handler] to serve a swagger spec as a JSON document. +// +// This allows for altering the spec before starting the [http] listener. +// +// Additional [SpecOption] can be used to change the path and the name of the document (defaults to "/swagger.json"). +func ServeSpec(spec []byte, next http.Handler, opts ...SpecOption) http.Handler { + o := specOptionsWithDefaults(opts) + + return handleSpec(o.Path, spec, next) +} + +func handleSpec(pth string, spec []byte, next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + if path.Clean(r.URL.Path) == pth { + rw.Header().Set(contentTypeHeader, applicationJSON) + rw.WriteHeader(http.StatusOK) + _, _ = rw.Write(spec) + + return + } + + if next != nil { + next.ServeHTTP(rw, r) + + return + } + + rw.Header().Set(contentTypeHeader, applicationJSON) + rw.WriteHeader(http.StatusNotFound) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/docui/swaggerui.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/swaggerui.go new file mode 100644 index 00000000000..db0aa05e6ab --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/swaggerui.go @@ -0,0 +1,138 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package docui + +import ( + "bytes" + "fmt" + "html/template" + "net/http" + "path" +) + +// UseSwaggerUI creates a middleware to serve a documentation site for a swagger spec using [SwaggerUI]. +// +// [SwaggerUI]: https://swagger.io/tools/swagger-ui +func UseSwaggerUI(opts ...Option) func(next http.Handler) http.Handler { + pth, assets := swaggeruiSetup(opts) + + return func(next http.Handler) http.Handler { + return serveUI(pth, assets, next) + } +} + +// SwaggerUI creates a [http.Handler] to serve a documentation site for a swagger spec using [SwaggerUI]. +// +// By default, the UI is served at route "/docs" +// +// This allows for altering the spec before starting the [http] listener. +// +// [SwaggerUI]: https://swagger.io/tools/swagger-ui +func SwaggerUI(next http.Handler, opts ...Option) http.Handler { + pth, assets := swaggeruiSetup(opts) + + return serveUI(pth, assets, next) +} + +func swaggeruiSetup(opts []Option) (pth string, assets []byte) { + o := optionsWithDefaults(opts, + // defaults for SwaggerUI + WithUITemplate(swaggeruiTemplate), + WithUIAssetsURL(swaggerLatest), + ) + o.applySwaggerUIDefaults() + if o.OAuth2CallbackURL == "" { + o.OAuth2CallbackURL = path.Join(o.BasePath, o.Path, "oauth2-callback") + } + + pth = path.Join(o.BasePath, o.Path) + tmpl := template.Must(template.New("swaggerui").Parse(o.Template)) + buf := bytes.NewBuffer(nil) + if err := tmpl.Execute(buf, o); err != nil { + panic(fmt.Errorf("cannot execute template: %w", err)) + } + + return pth, buf.Bytes() +} + +const ( + swaggerLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js" + swaggerPresetLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js" + swaggerStylesLatest = "https://unpkg.com/swagger-ui-dist/swagger-ui.css" + swaggerFavicon32Latest = "https://unpkg.com/swagger-ui-dist/favicon-32x32.png" + swaggerFavicon16Latest = "https://unpkg.com/swagger-ui-dist/favicon-16x16.png" + swaggeruiTemplate = ` + + + + + {{ .Title }} + + {{- if .SwaggerStylesURL }} + + {{- end }} + {{- if .Favicon32 }} + + {{- end }} + {{- if .Favicon16 }} + + {{- end }} + + + + +
+ + + {{- if .SwaggerPresetURL }} + + {{- end }} + + + +` +) diff --git a/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go b/vendor/github.com/go-openapi/runtime/server-middleware/docui/swaggerui_oauth2.go similarity index 70% rename from vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go rename to vendor/github.com/go-openapi/runtime/server-middleware/docui/swaggerui_oauth2.go index 879bdbaadea..a38e408f153 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go +++ b/vendor/github.com/go-openapi/runtime/server-middleware/docui/swaggerui_oauth2.go @@ -1,30 +1,56 @@ // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers // SPDX-License-Identifier: Apache-2.0 -package middleware +package docui import ( "bytes" "fmt" "net/http" + "path" "text/template" ) -func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler { - opts.EnsureDefaultsOauth2() +// UseSwaggerUIOAuth2Callback creates a middleware that serves a callback URL to complete +// a OAuth2 token handshake. +func UseSwaggerUIOAuth2Callback(opts ...Option) func(next http.Handler) http.Handler { + pth, assets := swaggeruiOAuth2Setup(opts) - pth := opts.OAuthCallbackURL - tmpl := template.Must(template.New("swaggeroauth").Parse(opts.Template)) - assets := bytes.NewBuffer(nil) - if err := tmpl.Execute(assets, opts); err != nil { + return func(next http.Handler) http.Handler { + return serveUI(pth, assets, next) + } +} + +// SwaggerUIOAuth2Callback creates a [http.Handler] that serves a callback URL to complete +// a OAuth2 token handshake. +func SwaggerUIOAuth2Callback(next http.Handler, opts ...Option) http.Handler { + pth, assets := swaggeruiOAuth2Setup(opts) + + return serveUI(pth, assets, next) +} + +func swaggeruiOAuth2Setup(opts []Option) (pth string, assets []byte) { + o := optionsWithDefaults(opts, + // defaults for SwaggerUI OAuth2 callback endpoint + WithUITemplate(swaggerOAuth2Template), + WithUIAssetsURL(swaggerLatest), + ) + o.applySwaggerUIDefaults() + if o.OAuth2CallbackURL == "" { + o.OAuth2CallbackURL = path.Join(o.BasePath, o.Path, "oauth2-callback") + } + + pth = o.OAuth2CallbackURL + tmpl := template.Must(template.New("swaggeroauth2").Parse(o.Template)) + buf := bytes.NewBuffer(nil) + if err := tmpl.Execute(buf, o); err != nil { panic(fmt.Errorf("cannot execute template: %w", err)) } - return serveUI(pth, assets.Bytes(), next) + return pth, buf.Bytes() } -const ( - swaggerOAuthTemplate = ` +const swaggerOAuth2Template = ` @@ -105,4 +131,3 @@ const ( ` -) diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/doc.go b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/doc.go new file mode 100644 index 00000000000..6f8aa313523 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/doc.go @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package mediatype provides a typed value for media types +// defined by RFC 7231 and RFC 2045. +// +// The matching/selection primitives used by both server-side +// validation and Accept-header negotiation. +// +// The package is stdlib-only. +// +// # The matching rule +// +// [MediaType.Matches] is asymmetric. The receiver acts as the "bound" +// (an allowed entry on the server side, or a candidate offer when +// matching against an Accept entry); the argument is the constraint +// (the actual incoming request, or the Accept entry being satisfied). +// +// - bare type/subtype must agree, with wildcard handling on either +// side ("*/*" matches anything; "type/*" matches any subtype); +// - if the receiver carries no parameters, any constraint is +// accepted regardless of its parameters; +// - otherwise every (key,value) pair on the constraint must be +// present on the receiver, with case-insensitive value +// comparison. The receiver may carry additional parameters the +// constraint does not list. +// +// q-values are NOT considered by [MediaType.Matches] — they are the +// negotiator's concern, handled inside [Set.BestMatch]. +package mediatype diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/lookup.go b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/lookup.go new file mode 100644 index 00000000000..598b60aca35 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/lookup.go @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mediatype + +// Lookup finds the entry in m matching mediaType, with alias-aware +// fallback. It is the canonical seam for codec-map lookups in both +// the client and server runtimes — placing the fallback policy here +// keeps alias definitions (and any future lookup tolerances) in one +// place. +// +// Lookup tries the following, in order, returning the first hit: +// +// 1. mediaType verbatim (fast path for callers that already pass a +// canonical, parameter-free string and store map keys in the +// same form). +// 2. An alias-aware walk against the parsed "type/subtype" form: +// a direct map hit on the parsed key, on its alias canonical +// if any, and finally an O(len(m)) scan returning any map +// entry whose key alias-canonicalizes to the same target. +// Catches both "map keyed by canonical, query uses alias" and +// "map keyed by one alias, query uses another alias of the +// same canonical". +// 3. When [AllowSuffix] is passed in opts: the same alias-aware +// walk against the RFC 6839 structured-syntax suffix base. +// Catches the "spec/traffic divergence" case (request for +// application/vnd.api+json finds a JSON consumer registered +// under application/json). Query-side suffix fold only — no +// map-side suffix folding. +// +// Lookup does NOT fall back to "*/*". Callers that want wildcard +// behavior (the historical resolveConsumer pattern in the client +// runtime) chain that themselves after a Lookup miss — keeping +// wildcard semantics explicit at each call site. +// +// Map keys are expected in canonical "type/subtype" form (no +// parameters). The runtime's default Consumers / Producers maps +// follow this convention. +// +// Returns (zero, false) when: +// +// - m is empty; +// - mediaType fails to parse and is not present verbatim; +// - none of the active steps hits. +// +// The malformed-vs-not-found distinction is intentionally elided: +// codec-lookup callers treat both as the same "no codec" error path. +func Lookup[T any](m map[string]T, mediaType string, opts ...MatchOption) (T, bool) { + var zero T + if len(m) == 0 { + return zero, false + } + o := applyMatchOptions(opts) + // Fast path: raw key (preserves any caller behaviour that stored + // non-canonical strings as map keys, and skips parsing in the + // common already-canonical case). + if v, ok := m[mediaType]; ok { + return v, true + } + mt, err := Parse(mediaType) + if err != nil { + return zero, false + } + key := mt.Type + "/" + mt.Subtype + if v, ok := findByCanonical(m, key); ok { + return v, true + } + if o.allowSuffix && mt.Suffix != "" { + base := mt.Base() + if baseKey := base.Type + "/" + base.Subtype; baseKey != key { + if v, ok := findByCanonical(m, baseKey); ok { + return v, true + } + } + } + return zero, false +} + +// findByCanonical returns the first entry in m whose key +// alias-canonicalizes to the same value as target. +// +// Tries direct hits before the O(len(m)) walk: +// +// 1. m[target] — map keyed by the same string. +// 2. m[aliases[target]] — map keyed by the canonical when target +// is an alias. +// 3. Walk m: return any entry where canonical(k) == canonical(target). +// Catches the "map keyed by an alias different from the query +// side" case (e.g. registered under text/yaml, queried as +// application/x-yaml — both canonicalize to application/yaml). +// +// Map size is single-digit for the runtime's codec maps, so the +// walk is negligible. +func findByCanonical[T any](m map[string]T, target string) (T, bool) { + if v, ok := m[target]; ok { + return v, true + } + canonTarget := target + if canon, ok := aliases[target]; ok { + canonTarget = canon + if v, ok := m[canonTarget]; ok { + return v, true + } + } + for k, v := range m { + kCanon := k + if c, ok := aliases[k]; ok { + kCanon = c + } + if kCanon == canonTarget { + return v, true + } + } + var zero T + return zero, false +} diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/match.go b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/match.go new file mode 100644 index 00000000000..6a16d0b6f2e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/match.go @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mediatype + +// MatchFirst reports whether actual matches any entry in allowed, +// using [MediaType.Match] — the param-aware RFC 7231 rule plus the +// alias bridge from the package-internal alias table. +// +// The scan is multi-pass and tier-ordered: the first pass returns +// the first allowed entry that matches under [MatchExact] (RFC 7231 +// semantics); the second pass looks for a [MatchAlias] match; when +// [AllowSuffix] is in opts a third pass looks for a [MatchSuffix] +// match. This preserves the "stronger tier wins" ordering from +// [Set.BestMatch] while keeping the "first match wins" semantics +// within each tier. +// +// Return values: +// +// - (matched, true, nil) — the first allowed entry that +// matches, with exact matches preferred over alias matches. +// - (zero, false, nil) — actual is well-formed but no +// allowed entry accepts it. Maps to an HTTP 415 outcome. +// - (zero, false, err) — actual fails to parse. err +// wraps [ErrMalformed], so callers can use [errors.Is] to +// distinguish this case. Maps to an HTTP 400 outcome. +// +// Allowed entries that themselves fail to parse are skipped (they +// cannot match any well-formed actual), and no error is surfaced +// for them. +// +// An empty allowed list returns (zero, false, nil). MatchFirst is +// the primitive; callers decide what no-constraints means in their +// context. +func MatchFirst(allowed []string, actual string, opts ...MatchOption) (MediaType, bool, error) { + if len(allowed) == 0 { + return MediaType{}, false, nil + } + actualMT, err := Parse(actual) + if err != nil { + return MediaType{}, false, err + } + o := applyMatchOptions(opts) + // Tier-ordered passes over the allowed list. The list is + // typically short (an operation's Consumes set), so re-parsing + // each entry on every pass is cheaper than caching parses across + // passes. + tiers := []MatchKind{MatchExact, MatchAlias} + if o.allowSuffix { + tiers = append(tiers, MatchSuffix) + } + for _, want := range tiers { + for _, a := range allowed { + allowedMT, perr := Parse(a) + if perr != nil { + continue + } + if allowedMT.Match(actualMT) == want { + return allowedMT, true, nil + } + } + } + + return MediaType{}, false, nil +} diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/mediatype.go b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/mediatype.go new file mode 100644 index 00000000000..41a32a160a8 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/mediatype.go @@ -0,0 +1,392 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mediatype + +import ( + "fmt" + "mime" + "strconv" + "strings" +) + +const wildcard = "*" + +// Internal constants for the suffixBase table and any future +// in-package references to the well-known base media types. +const ( + typeApplication = "application" + subtypeJSON = "json" + subtypeXML = "xml" + subtypeYAML = "yaml" + + mtYAML = typeApplication + "/" + subtypeYAML +) + +// Specificity scores returned by [MediaType.Specificity], ordered from +// least to most specific. +const ( + SpecificityAny = iota // "*/*" + SpecificityType // "type/*" + SpecificityExact // "type/subtype" (no params) + SpecificityExactWithParams // "type/subtype;k=v" +) + +// MatchKind classifies the strength of a match between two media +// types. Larger values represent stronger matches and win in +// negotiation tie-breaks. +// +// MatchExact covers direct subtype or wildcard agreement under RFC +// 7231 rules; MatchAlias is returned when the strict comparison +// fails but the two values agree after canonicalization through the +// internal alias table (see [MediaType.Canonical]); MatchSuffix is +// returned only when both alias and exact comparisons fail but the +// two values agree after folding the RFC 6839 structured-syntax +// suffix (see [MediaType.Base]). +// +// MatchSuffix matches are off by default at the negotiation / +// lookup callers — they count only when [AllowSuffix] is passed to +// [Set.BestMatch], [MatchFirst], or [Lookup]. The opt-in is the +// single user-visible knob; [MediaType.Match] itself always returns +// the strongest tier that succeeds. +type MatchKind int + +// MatchKind values. Returned by [MediaType.Match]. +const ( + MatchNone MatchKind = iota // no match + MatchSuffix // matched via the RFC 6839 suffix base + MatchAlias // matched via the alias table + MatchExact // matched directly (RFC 7231 semantics) +) + +// MatchOption configures the matching tolerances used by +// [Set.BestMatch], [MatchFirst], and [Lookup]. The zero behaviour +// is strict: only [MatchAlias] and [MatchExact] count. +type MatchOption func(*matchOptions) + +type matchOptions struct { + allowSuffix bool +} + +func applyMatchOptions(opts []MatchOption) matchOptions { + var o matchOptions + for _, opt := range opts { + opt(&o) + } + return o +} + +// AllowSuffix returns a [MatchOption] that lets the caller count +// [MatchSuffix] results as valid matches. Use this to opt into +// RFC 6839 structured-syntax suffix tolerance for situations where +// the client/server traffic does not strictly abide by the spec +// (typical example: server returning application/problem+json +// against operations that only declare application/json in +// produces). +func AllowSuffix() MatchOption { + return func(o *matchOptions) { + o.allowSuffix = true + } +} + +type mediaTypeError string + +func (e mediaTypeError) Error() string { + return string(e) +} + +// ErrMalformed is the sentinel returned (wrapped) by [Parse] when its input +// cannot be parsed as an RFC 7231 media type. +// +// Callers can test for it with [errors.Is] to distinguish a client-side +// malformed Content-Type header (an HTTP 400 outcome) from a well-formed +// value that simply matches no allowed entry (an HTTP 415 outcome). +const ErrMalformed mediaTypeError = "mediatype: malformed" + +// MediaType is a parsed RFC 7231 media type with optional parameters and +// an optional q-value (used by Accept negotiation). +// +// Type, Subtype and the keys of Params are lowercased. Parameter values +// are preserved verbatim; comparisons are case-insensitive (matching the +// pre-v0.30 behaviour and the common convention for charset, version, etc.). +// +// Suffix exposes the RFC 6839 structured syntax suffix (the token after +// the final '+' in Subtype) as a parallel hint. Subtype itself retains +// the full wire value, so existing callers comparing Subtype against a +// string see no change. +type MediaType struct { + Type string + Subtype string + Suffix string + Params map[string]string + Q float64 +} + +// suffixBase maps a known RFC 6839 / RFC 9512 structured syntax +// suffix (without the leading '+', lowercased) to its base media +// type. It is the authoritative table consulted by [MediaType.Base]. +// +// The table is intentionally small: only suffixes whose base type +// has a codec in the default runtime maps are listed. CBOR, zip, +// BER, DER, FastInfoset and WBXML are registered by IANA but have +// no default codec in this runtime; adding them is gated on having +// something to do with them. +// +// Package-internal by design: the external API is [MediaType.Base]. +// If users ever need to extend the table, a Register-style function +// is the right answer, not an exported mutable map. +var suffixBase = map[string]MediaType{ + subtypeJSON: {Type: typeApplication, Subtype: subtypeJSON}, + subtypeXML: {Type: typeApplication, Subtype: subtypeXML}, + subtypeYAML: {Type: typeApplication, Subtype: subtypeYAML}, +} + +// aliases maps a deprecated or legacy media-type name to its +// canonical registered equivalent. Keys are the lowercased +// "type/subtype" form with no parameters; values are the canonical +// "type/subtype" form, also without parameters. +// +// Entries are limited to media types whose authoritative RFC +// explicitly names the alias. The seed entries cite RFC 9512 §2.1, +// which enumerates "Deprecated alias names for this type: +// application/x-yaml, text/yaml, and text/x-yaml" as part of the +// IANA registration template for application/yaml. +// +// Pull requests adding entries need an analogous citation in the +// commit message; entries without authoritative backing belong in +// caller-side canonicalization, not here. +// +// Package-internal by design: the external API is +// [MediaType.Canonical] and [MediaType.Match]. If users ever need +// to register their own aliases, a Register-style function is the +// right answer, not an exported mutable map. +var aliases = map[string]string{ + "application/x-yaml": mtYAML, // RFC 9512 §2.1 + "text/yaml": mtYAML, // RFC 9512 §2.1 + "text/x-yaml": mtYAML, // RFC 9512 §2.1 +} + +// Parse parses a single media type. The input may carry parameters and a +// q-value; the q-value is extracted into [MediaType.Q] and removed from +// [MediaType.Params]. +// +// An empty input returns an error. +func Parse(s string) (MediaType, error) { + s = strings.TrimSpace(s) + if s == "" { + return MediaType{}, fmt.Errorf("%w: empty value", ErrMalformed) + } + full, params, err := mime.ParseMediaType(s) + if err != nil { + return MediaType{}, fmt.Errorf("%w: %w", ErrMalformed, err) + } + slash := strings.IndexByte(full, '/') + if slash <= 0 || slash == len(full)-1 { + return MediaType{}, fmt.Errorf("%w: %q has no subtype", ErrMalformed, s) + } + mt := MediaType{ + Type: full[:slash], + Subtype: full[slash+1:], + Q: 1.0, + } + // RFC 6839: structured syntax suffix is the trailing '+'-delimited + // token of the subtype. Only the last '+' counts ("foo+bar+json" → + // suffix "json"). A trailing '+' with nothing after it is not a + // valid suffix and is ignored. mime.ParseMediaType has already + // lowercased the subtype, so no further ToLower is needed. + if plus := strings.LastIndexByte(mt.Subtype, '+'); plus >= 0 && plus < len(mt.Subtype)-1 { + mt.Suffix = mt.Subtype[plus+1:] + } + + if q, ok := params["q"]; ok { + if qf, isFloat := boundedQ(q); isFloat { + mt.Q = qf + } + delete(params, "q") + } + + if len(params) > 0 { + mt.Params = params + } + + return mt, nil +} + +// String renders the canonical "type/subtype;k=v;k=v" form. Parameters are +// emitted in lexicographic key order (the standard library guarantees this) +// so the result is stable. The q-value is NOT emitted — it is meta, not +// part of the media type identity. +func (m MediaType) String() string { + if m.Type == "" && m.Subtype == "" { + return "" + } + + return mime.FormatMediaType(m.Type+"/"+m.Subtype, m.Params) +} + +// Matches reports whether the receiver accepts other, per the package +// documentation: the receiver is the bound, other is the constraint. +func (m MediaType) Matches(other MediaType) bool { + if !typeAgrees(m.Type, other.Type) { + return false + } + if !subtypeAgrees(m.Type, m.Subtype, other.Type, other.Subtype) { + return false + } + if len(m.Params) == 0 { + return true + } + for k, v := range other.Params { + sv, ok := m.Params[k] + if !ok || !strings.EqualFold(sv, v) { + return false + } + } + + return true +} + +// Specificity returns a numeric score for ordering matches. Higher is more +// specific. The returned value is one of [SpecificityAny], +// [SpecificityType], [SpecificityExact] or [SpecificityExactWithParams]. +func (m MediaType) Specificity() int { + if m.Type == wildcard && m.Subtype == wildcard { + return SpecificityAny + } + if m.Subtype == wildcard { + return SpecificityType + } + if len(m.Params) == 0 { + return SpecificityExact + } + + return SpecificityExactWithParams +} + +func boundedQ(q string) (float64, bool) { + qf, err := strconv.ParseFloat(q, 64) + if err != nil { + return 0, false + } + + if qf < 0 { + qf = 0 + } + + if qf > 1 { + qf = 1 + } + + return qf, true +} + +// typeAgrees reports whether two top-level types match, allowing "*" on +// either side. A type of "*" without a "*" subtype is rejected per RFC +// 7231 §5.3.2 ("*/sub" is not valid), but Parse never produces such a +// shape — it goes through mime.ParseMediaType. +func typeAgrees(a, b string) bool { + return a == wildcard || b == wildcard || a == b +} + +// subtypeAgrees handles the "type/*" wildcard: the bare type must match +// (a "*/*" pair has already been accepted by typeAgrees above). +func subtypeAgrees(at, asub, bt, bsub string) bool { + if at == wildcard || bt == wildcard { + // at least one side is "*/*" or "*/sub". With typeAgrees having + // returned true, we accept. + return true + } + if asub == wildcard || bsub == wildcard { + return true + } + + return asub == bsub +} + +// StripParams returns a copy of m with no parameters. Q is preserved +// because it drives negotiation ordering, not media-type identity. +// +// Useful for the legacy "ignore parameters" negotiation mode. +func (m MediaType) StripParams() MediaType { + return MediaType{Type: m.Type, Subtype: m.Subtype, Suffix: m.Suffix, Q: m.Q} +} + +// Base returns the base media type implied by the RFC 6839 structured +// syntax suffix, or m unchanged when: +// +// - Suffix is empty; +// - Suffix is not present in the package-internal suffix→base table. +// +// The returned value represents the structural base only: it carries +// no parameters and no q-value. Use it to find a codec for the +// underlying wire format — for example, "application/vnd.api+json" +// resolves to "application/json". +// +// Base does not mutate the receiver. +func (m MediaType) Base() MediaType { + if m.Suffix == "" { + return m + } + base, ok := suffixBase[m.Suffix] + if !ok { + return m + } + return base +} + +// Canonical returns m rewritten to its canonical media type via +// the package-internal alias table, or m unchanged when +// (Type, Subtype) is not a known alias. Params and Q are preserved on the returned value; Suffix +// is recomputed from the canonical Subtype (none of the current +// entries carry a suffix, but the contract is forward-safe). +// +// Canonical does not mutate the receiver. +func (m MediaType) Canonical() MediaType { + key := m.Type + "/" + m.Subtype + canon, ok := aliases[key] + if !ok { + return m + } + slash := strings.IndexByte(canon, '/') + out := m + out.Type = canon[:slash] + out.Subtype = canon[slash+1:] + out.Suffix = "" + if plus := strings.LastIndexByte(out.Subtype, '+'); plus >= 0 && plus < len(out.Subtype)-1 { + out.Suffix = out.Subtype[plus+1:] + } + return out +} + +// Match reports how m matches other, classifying the result by +// [MatchKind]. Used by negotiation to rank candidate offers: +// stronger tiers win when both apply. +// +// Returns, strongest first: +// +// - MatchExact when m.Matches(other) is true under the strict +// RFC 7231 rules (including wildcards and the param subset +// rule). +// - MatchAlias when m.Canonical().Matches(other.Canonical()) +// is true but the strict comparison failed. +// - MatchSuffix when m.Base().Canonical().Matches( +// other.Base().Canonical()) is true but the alias comparison +// failed (RFC 6839 structured-syntax suffix fold). +// - MatchNone otherwise. +// +// The asymmetric "bound vs constraint" rule of [MediaType.Matches] +// is preserved at every tier. Match itself is always lenient — the +// opt-in to count MatchSuffix lives one level up at [Set.BestMatch], +// [MatchFirst], and [Lookup] via [AllowSuffix]. +func (m MediaType) Match(other MediaType) MatchKind { + if m.Matches(other) { + return MatchExact + } + if m.Canonical().Matches(other.Canonical()) { + return MatchAlias + } + if m.Base().Canonical().Matches(other.Base().Canonical()) { + return MatchSuffix + } + return MatchNone +} diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/set.go b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/set.go new file mode 100644 index 00000000000..70f62a18d41 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/mediatype/set.go @@ -0,0 +1,138 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mediatype + +import ( + "strings" +) + +// Set is a list of media types — typically the parsed value of an Accept +// header, or a list of server-side offers. +type Set []MediaType + +// ParseAccept parses a comma-separated list of media types, as found in +// the Accept, Accept-Charset (etc.) HTTP headers. Malformed entries are +// skipped silently — be liberal in what you accept. +// +// An empty input returns nil. +func ParseAccept(s string) Set { + parts := splitTopLevel(s) + if len(parts) == 0 { + return nil + } + out := make(Set, 0, len(parts)) + for _, p := range parts { + mt, err := Parse(p) + if err != nil { + continue + } + out = append(out, mt) + } + + return out +} + +// BestMatch picks the offer most acceptable to the receiver's Accept +// entries. Selection follows RFC 7231 §5.3.2 plus tier-aware +// ranking: +// +// - highest q-value wins; +// - ties on q broken by the highest [MediaType.Specificity] of the +// matching Accept entry; +// - ties on specificity broken by [MatchKind] (MatchExact beats +// MatchAlias beats MatchSuffix); +// - ties on match kind broken by earliest position in offered. +// +// Accept entries with q=0 are treated as exclusions and never match. +// MatchSuffix results are only counted when [AllowSuffix] is passed. +// Returns ok=false if no offer matched any non-zero-q entry. +func (s Set) BestMatch(offered Set, opts ...MatchOption) (best MediaType, ok bool) { + if len(s) == 0 || len(offered) == 0 { + return MediaType{}, false + } + o := applyMatchOptions(opts) + bestQ := -1.0 + bestSpec := -1 + bestKind := MatchNone + bestIdx := -1 + for i, offer := range offered { + for _, entry := range s { + if entry.Q == 0 { + continue + } + kind := offer.Match(entry) + if kind == MatchNone { + continue + } + if kind == MatchSuffix && !o.allowSuffix { + continue + } + spec := entry.Specificity() + switch { + case entry.Q > bestQ: + best, ok = offer, true + bestQ = entry.Q + bestSpec = spec + bestKind = kind + bestIdx = i + case entry.Q < bestQ: + // not better + case spec > bestSpec: + best, ok = offer, true + bestSpec = spec + bestKind = kind + bestIdx = i + case spec < bestSpec: + // not better + case kind > bestKind: + best, ok = offer, true + bestKind = kind + bestIdx = i + case kind < bestKind: + // not better + case bestIdx < 0 || i < bestIdx: + best, ok = offer, true + bestIdx = i + } + } + } + + return best, ok +} + +// splitTopLevel splits s on top-level commas, respecting double-quoted +// strings (RFC 7230 §3.2.6 — quoted-string). +func splitTopLevel(s string) []string { + if strings.IndexByte(s, ',') < 0 { + if t := strings.TrimSpace(s); t != "" { + return []string{t} + } + return nil + } + var out []string + start := 0 + inQuote := false + escape := false + for i := range len(s) { + c := s[i] + switch { + case escape: + escape = false + case inQuote && c == '\\': + escape = true + case c == '"': + inQuote = !inQuote + case c == ',' && !inQuote: + if t := strings.TrimSpace(s[start:i]); t != "" { + out = append(out, t) + } + start = i + 1 + } + } + if t := strings.TrimSpace(s[start:]); t != "" { + out = append(out, t) + } + + return out +} diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/doc.go b/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/doc.go new file mode 100644 index 00000000000..a9f278c31b1 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/doc.go @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package negotiate provides server-side HTTP content negotiation +// helpers — selecting the response Content-Type from an Accept header +// and the response Content-Encoding from an Accept-Encoding header. +// +// The package is stdlib-only (modulo the typed [mediatype.MediaType] +// values it consumes). +// +// The exported [ContentType] honours MIME-type parameters by default; +// use [WithIgnoreParameters] to restore the pre-v0.30 looser match. +package negotiate diff --git a/vendor/github.com/go-openapi/runtime/middleware/header/header.go b/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/header/header.go similarity index 97% rename from vendor/github.com/go-openapi/runtime/middleware/header/header.go rename to vendor/github.com/go-openapi/runtime/server-middleware/negotiate/header/header.go index 6ce870d8936..6f3c3f00382 100644 --- a/vendor/github.com/go-openapi/runtime/middleware/header/header.go +++ b/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/header/header.go @@ -300,7 +300,13 @@ func expectQuality(s string) (q float64, rest string) { n = n*10 + int(b) - '0' d *= 10 } - return q + float64(n)/float64(d), s[i:] + result := q + float64(n)/float64(d) + // RFC 7231 §5.3.1: qvalue is in [0, 1]. Inputs like "1.1" + // would otherwise yield > 1; reject as malformed. + if result > 1 { + return -1, s[i:] + } + return result, s[i:] } func expectTokenOrQuoted(s string) (value string, rest string) { diff --git a/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/negotiate.go b/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/negotiate.go new file mode 100644 index 00000000000..3c932a1969d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/server-middleware/negotiate/negotiate.go @@ -0,0 +1,215 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package negotiate + +import ( + "net/http" + "strings" + + "github.com/go-openapi/runtime/server-middleware/mediatype" + "github.com/go-openapi/runtime/server-middleware/negotiate/header" +) + +// Option configures [ContentType] behaviour. +type Option func(*options) + +type options struct { + ignoreParameters bool + matchSuffix bool +} + +func optionsWithDefaults(opts []Option) options { + var o options + for _, apply := range opts { + apply(&o) + } + + return o +} + +// WithIgnoreParameters returns an [Option] that strips MIME-type +// parameters from both Accept entries and offers before matching, restoring +// the behaviour the runtime had before v0.30. +// +// New code should leave parameters honoured (the default). This option +// exists for applications that depend on the looser pre-v0.30 match — +// most often because their producers and Accept clients use mismatched +// charset or version params that they treat as informational. +// +// Example — per-call opt-out: +// +// chosen := negotiate.ContentType(r, offers, "", +// negotiate.WithIgnoreParameters(true), +// ) +// +// Example — server-wide opt-out (via [middleware.Context]): +// +// ctx := middleware.NewContext(spec, api, nil).SetIgnoreParameters(true) +func WithIgnoreParameters(ignore bool) Option { + return func(o *options) { + o.ignoreParameters = ignore + } +} + +// WithMatchSuffix returns an [Option] that extends content +// negotiation to tolerate RFC 6839 structured-syntax suffix media +// types. When enabled, an Accept entry of "application/json" +// matches an offer of "application/vnd.api+json" and vice versa, +// for the suffixes recognised by the runtime (+json, +xml, +yaml). +// +// Default: strict (false). Use only when interoperating with +// clients or servers that do not strictly abide by the spec — for +// example, servers returning application/problem+json error +// responses against operations that only declare application/json +// in produces. +// +// Suffix matches always lose to exact and alias matches when those +// are on offer; see [mediatype.MatchKind] for the tier ordering. +// +// Example — per-call opt-in: +// +// chosen := negotiate.ContentType(r, offers, "", +// negotiate.WithMatchSuffix(true), +// ) +// +// Example — server-wide opt-in (via [middleware.Context]): +// +// ctx := middleware.NewContext(spec, api, nil).SetMatchSuffix(true) +func WithMatchSuffix(enable bool) Option { + return func(o *options) { + o.matchSuffix = enable + } +} + +// ContentEncoding returns the best offered content encoding for the +// request's Accept-Encoding header. If two offers match with equal +// weight then the offer earlier in the list is preferred. If no offers +// are acceptable, then "" is returned. +// +// Encoding tokens have no parameters, so this function is unaffected by +// the v0.30 parameter-honouring change to [ContentType]. +// +// Deprecated: ContentEncoding negotiation is not used by the components +// of this project. +// +// This historical addition has never been associated with proper +// compression middleware and is thus half a feature. +// The runtime does not ship compression. +// Use github.com/CAFxX/httpcompression or github.com/klauspost/compress/gzhttp +// at the http.Handler level, or github.com/klauspost/compress/* for client +// transport wrapping. See docs/examples/middleware for a recipe. +func ContentEncoding(r *http.Request, offers []string) string { + bestOffer := "identity" + bestQ := -1.0 + specs := header.ParseAccept(r.Header, "Accept-Encoding") + for _, offer := range offers { + for _, spec := range specs { + if spec.Q > bestQ && + (spec.Value == "*" || spec.Value == offer) { + bestQ = spec.Q + bestOffer = offer + } + } + } + if bestQ == 0 { + bestOffer = "" + } + + return bestOffer +} + +// ContentType returns the best offered content type for the request's +// Accept header. If two offers match with equal weight, then the more +// specific offer is preferred (text/* trumps */*; type/subtype trumps +// type/*). If two offers match with equal weight and specificity, then +// the offer earlier in the list is preferred. If no offers match, then +// defaultOffer is returned. +// +// As of v0.30 the matching rule honours MIME-type parameters: an Accept +// entry of "text/plain;charset=utf-8" matches an offer of bare +// "text/plain" (offer carries no constraint), but it does NOT match an +// offer of "text/plain;charset=ascii" (charset values disagree). Pass +// [WithIgnoreParameters](true) to restore the pre-v0.30 behaviour where +// parameters were stripped before matching — see [WithIgnoreParameters] +// for details and an example. +// +// When the Accept header is absent, the first offer is returned +// unchanged (param-stripping is irrelevant in that case). +func ContentType(r *http.Request, offers []string, defaultOffer string, opts ...Option) string { + if len(offers) == 0 { + return defaultOffer + } + o := optionsWithDefaults(opts) + + // Per RFC 7230 §3.2.2, multiple Accept headers are equivalent to a + // single comma-joined value. Join before parsing so we don't drop + // later entries. + acceptValues := r.Header.Values("Accept") + if len(acceptValues) == 0 { + return offers[0] + } + acceptSet := mediatype.ParseAccept(strings.Join(acceptValues, ", ")) + if len(acceptSet) == 0 { + return defaultOffer + } + + offerSet := make(mediatype.Set, 0, len(offers)) + rawByIdx := make([]string, 0, len(offers)) + for _, raw := range offers { + mt, err := mediatype.Parse(raw) + if err != nil { + continue + } + offerSet = append(offerSet, mt) + rawByIdx = append(rawByIdx, raw) + } + if len(offerSet) == 0 { + return defaultOffer + } + + if o.ignoreParameters { + acceptSet = stripSet(acceptSet) + offerSet = stripSet(offerSet) + } + + var matchOpts []mediatype.MatchOption + if o.matchSuffix { + matchOpts = append(matchOpts, mediatype.AllowSuffix()) + } + best, ok := acceptSet.BestMatch(offerSet, matchOpts...) + if !ok { + return defaultOffer + } + // Return the original raw offer string so callers receive the value + // they declared, with its parameters preserved. + for i, mt := range offerSet { + if mt.Type == best.Type && mt.Subtype == best.Subtype && sameParams(mt.Params, best.Params) { + return rawByIdx[i] + } + } + + return best.String() +} + +func stripSet(s mediatype.Set) mediatype.Set { + out := make(mediatype.Set, len(s)) + for i, m := range s { + out[i] = m.StripParams() + } + + return out +} + +func sameParams(a, b map[string]string) bool { + if len(a) != len(b) { + return false + } + for k, v := range a { + if b[k] != v { + return false + } + } + + return true +} diff --git a/vendor/github.com/go-openapi/runtime/statuses.go b/vendor/github.com/go-openapi/runtime/statuses.go index c0f3e6b4477..273d9c6ced3 100644 --- a/vendor/github.com/go-openapi/runtime/statuses.go +++ b/vendor/github.com/go-openapi/runtime/statuses.go @@ -60,7 +60,7 @@ var Statuses = map[int]string{ 444: "No Response", 449: "Retry With", 450: "Blocked by Windows Parental Controls", - 451: "Wrong Exchange Server", + 451: "Unavailable For Legal Reasons", 499: "Client Closed Request", 500: "Internal Server Error", 501: "Not Implemented", diff --git a/vendor/github.com/go-openapi/runtime/text.go b/vendor/github.com/go-openapi/runtime/text.go index 1252ac88c71..3764a87fe51 100644 --- a/vendor/github.com/go-openapi/runtime/text.go +++ b/vendor/github.com/go-openapi/runtime/text.go @@ -36,14 +36,14 @@ func TextConsumer() Consumer { if tu, ok := data.(encoding.TextUnmarshaler); ok { err := tu.UnmarshalText(b) if err != nil { - return fmt.Errorf("text consumer: %v", err) + return fmt.Errorf("text consumer: %w", err) } return nil } t := reflect.TypeOf(data) - if data != nil && t.Kind() == reflect.Ptr { + if data != nil && t.Kind() == reflect.Pointer { v := reflect.Indirect(reflect.ValueOf(data)) if t.Elem().Kind() == reflect.String { v.SetString(string(b)) @@ -70,7 +70,7 @@ func TextProducer() Producer { if tm, ok := data.(encoding.TextMarshaler); ok { txt, err := tm.MarshalText() if err != nil { - return fmt.Errorf("text producer: %v", err) + return fmt.Errorf("text producer: %w", err) } _, err = writer.Write(txt) return err diff --git a/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go index ca71edbb1ba..b7fab88906c 100644 --- a/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go +++ b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go @@ -6,8 +6,9 @@ package yamlpc import ( "io" - "github.com/go-openapi/runtime" yaml "go.yaml.in/yaml/v3" + + "github.com/go-openapi/runtime" ) // YAMLConsumer creates a consumer for [yaml] data. diff --git a/vendor/github.com/go-openapi/spec/.gitignore b/vendor/github.com/go-openapi/spec/.gitignore index dd91ed6a04e..d8f4186fe59 100644 --- a/vendor/github.com/go-openapi/spec/.gitignore +++ b/vendor/github.com/go-openapi/spec/.gitignore @@ -1,2 +1,5 @@ -secrets.yml -coverage.out +*.out +*.cov +.idea +.env +.mcp.json diff --git a/vendor/github.com/go-openapi/spec/.golangci.yml b/vendor/github.com/go-openapi/spec/.golangci.yml index 835d55e7425..9d2733176ea 100644 --- a/vendor/github.com/go-openapi/spec/.golangci.yml +++ b/vendor/github.com/go-openapi/spec/.golangci.yml @@ -1,42 +1,70 @@ -linters-settings: - govet: - check-shadowing: true - golint: - min-confidence: 0 - gocyclo: - min-complexity: 45 - maligned: - suggest-new: true - dupl: - threshold: 200 - goconst: - min-len: 2 - min-occurrences: 2 - +version: "2" linters: - enable-all: true + default: all disable: - - maligned - - unparam - - lll - - gochecknoinits - - gochecknoglobals + - depguard - funlen + - goconst - godox - - gocognit - - whitespace - - wsl - - wrapcheck - - testpackage + - gomodguard + - gomodguard_v2 + - exhaustruct - nlreturn - - gomnd - - exhaustivestruct - - goerr113 - - errorlint - - nestif - - godot - - gofumpt + - nonamedreturns + - noinlineerr - paralleltest - - tparallel + - recvcheck + - testpackage - thelper - - ifshort + - tparallel + - varnamelen + - whitespace + - wrapcheck + - wsl + - wsl_v5 + settings: + dupl: + threshold: 200 + goconst: + min-len: 2 + min-occurrences: 3 + cyclop: + max-complexity: 20 + gocyclo: + min-complexity: 20 + exhaustive: + default-signifies-exhaustive: true + default-case-required: true + lll: + line-length: 180 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + - gofumpt + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ +issues: + # Maximum issues count per one linter. + # Set to 0 to disable. + # Default: 50 + max-issues-per-linter: 0 + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 0 diff --git a/vendor/github.com/go-openapi/spec/.travis.yml b/vendor/github.com/go-openapi/spec/.travis.yml deleted file mode 100644 index 2281a07b057..00000000000 --- a/vendor/github.com/go-openapi/spec/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -after_success: -- bash <(curl -s https://codecov.io/bash) -go: -- 1.16.x -- 1.x -arch: - - amd64 -jobs: - include: - # only run fast tests on ppc64le - - go: 1.x - arch: ppc64le - script: - - gotestsum -f short-verbose -- ./... - - # include linting job, but only for latest go version and amd64 arch - - go: 1.x - arch: amd64 - install: - go get github.com/golangci/golangci-lint/cmd/golangci-lint - script: - - golangci-lint run --new-from-rev master - -install: -- GO111MODULE=off go get -u gotest.tools/gotestsum -language: go -notifications: - slack: - secure: QUWvCkBBK09GF7YtEvHHVt70JOkdlNBG0nIKu/5qc4/nW5HP8I2w0SEf/XR2je0eED1Qe3L/AfMCWwrEj+IUZc3l4v+ju8X8R3Lomhme0Eb0jd1MTMCuPcBT47YCj0M7RON7vXtbFfm1hFJ/jLe5+9FXz0hpXsR24PJc5ZIi/ogNwkaPqG4BmndzecpSh0vc2FJPZUD9LT0I09REY/vXR0oQAalLkW0asGD5taHZTUZq/kBpsNxaAFrLM23i4mUcf33M5fjLpvx5LRICrX/57XpBrDh2TooBU6Qj3CgoY0uPRYUmSNxbVx1czNzl2JtEpb5yjoxfVPQeg0BvQM00G8LJINISR+ohrjhkZmAqchDupAX+yFrxTtORa78CtnIL6z/aTNlgwwVD8kvL/1pFA/JWYmKDmz93mV/+6wubGzNSQCstzjkFA4/iZEKewKUoRIAi/fxyscP6L/rCpmY/4llZZvrnyTqVbt6URWpopUpH4rwYqreXAtJxJsfBJIeSmUIiDIOMGkCTvyTEW3fWGmGoqWtSHLoaWDyAIGb7azb+KvfpWtEcoPFWfSWU+LGee0A/YsUhBl7ADB9A0CJEuR8q4BPpKpfLwPKSiKSAXL7zDkyjExyhtgqbSl2jS+rKIHOZNL8JkCcTP2MKMVd563C5rC5FMKqu3S9m2b6380E= -script: -- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./... diff --git a/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md index 9322b065e37..bac878f216a 100644 --- a/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md +++ b/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md @@ -23,7 +23,9 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or + advances + * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic @@ -55,7 +57,7 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at ivan+abuse@flanders.co.nz. All +reported by contacting the project team at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. @@ -68,7 +70,7 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at [][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/spec/CONTRIBUTORS.md b/vendor/github.com/go-openapi/spec/CONTRIBUTORS.md new file mode 100644 index 00000000000..12fd069b0fd --- /dev/null +++ b/vendor/github.com/go-openapi/spec/CONTRIBUTORS.md @@ -0,0 +1,50 @@ +# Contributors + +- Repository: ['go-openapi/spec'] + +| Total Contributors | Total Contributions | +| --- | --- | +| 38 | 403 | + +| Username | All Time Contribution Count | All Commits | +| --- | --- | --- | +| @casualjim | 191 | | +| @fredbi | 101 | | +| @pytlesk4 | 26 | | +| @kul-amr | 10 | | +| @keramix | 10 | | +| @youyuanwu | 8 | | +| @pengsrc | 7 | | +| @alphacentory | 5 | | +| @mtfelian | 4 | | +| @Capstan | 4 | | +| @sdghchj | 4 | | +| @databus23 | 2 | | +| @vburenin | 2 | | +| @petrkotas | 2 | | +| @nikhita | 2 | | +| @hypnoglow | 2 | | +| @carvind | 2 | | +| @ujjwalsh | 1 | | +| @mbohlool | 1 | | +| @j2gg0s | 1 | | +| @ishveda | 1 | | +| @micln | 1 | | +| @GlenDC | 1 | | +| @agmikhailov | 1 | | +| @tgraf | 1 | | +| @zhsj | 1 | | +| @sebastien-rosset | 1 | | +| @alexandear | 1 | | +| @morlay | 1 | | +| @mikedanese | 1 | | +| @koron | 1 | | +| @honza | 1 | | +| @gbjk | 1 | | +| @faguirre1 | 1 | | +| @ethantkoenig | 1 | | +| @sttts | 1 | | +| @ChandanChainani | 1 | | +| @bvwells | 1 | | + + _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/spec/README.md b/vendor/github.com/go-openapi/spec/README.md index 18782c6dafe..7c96eb9a586 100644 --- a/vendor/github.com/go-openapi/spec/README.md +++ b/vendor/github.com/go-openapi/spec/README.md @@ -1,14 +1,35 @@ -# OAI object model +# spec -[![Build Status](https://travis-ci.org/go-openapi/spec.svg?branch=master)](https://travis-ci.org/go-openapi/spec) - -[![codecov](https://codecov.io/gh/go-openapi/spec/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/spec) -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/spec.svg)](https://pkg.go.dev/github.com/go-openapi/spec) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/spec)](https://goreportcard.com/report/github.com/go-openapi/spec) + +[![Tests][test-badge]][test-url] [![Coverage][cov-badge]][cov-url] [![CI vuln scan][vuln-scan-badge]][vuln-scan-url] [![CodeQL][codeql-badge]][codeql-url] + + + +[![Release][release-badge]][release-url] [![Go Report Card][gocard-badge]][gocard-url] [![CodeFactor Grade][codefactor-badge]][codefactor-url] [![License][license-badge]][license-url] + + +[![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge] -The object model for OpenAPI specification documents. +--- + +The object model for OpenAPI v2 specification documents. + +## Announcements + +* **2025-12-19** : new community chat on discord + * a new discord community channel is available to be notified of changes and support users + +You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] + +## Status + +API is stable. + +## Import this library in your project + +```cmd +go get github.com/go-openapi/spec +``` ### FAQ @@ -31,4 +52,95 @@ The object model for OpenAPI specification documents. > There is no plan to make it evolve toward supporting OpenAPI 3.x. > This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story. > -> An early attempt to support Swagger 3 may be found at: https://github.com/go-openapi/spec3 +> An early attempt to support Swagger 3 may be found at: + +* Does the unmarshaling support YAML? + +> Not directly. The exposed types know only how to unmarshal from JSON. +> +> In order to load a YAML document as a Swagger spec, you need to use the loaders provided by +> github.com/go-openapi/loads +> +> Take a look at the example there: +> +> See also + +* How can I validate a spec? + +Validation is provided by [the validate package](http://github.com/go-openapi/validate) + +* Why do we have an `ID` field for `Schema` which is not part of the swagger spec? + +> We found jsonschema compatibility more important: since `id` in jsonschema influences +> how `$ref` are resolved. +> This `id` does not conflict with any property named `id`. +> +> See also + +## Change log + +See + +## References + + + +## Licensing + +This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). + +## Other documentation + +* [All-time contributors](./CONTRIBUTORS.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] + +## Cutting a new release + +Maintainers can cut a new release by either: + +* running [this workflow](https://github.com/go-openapi/spec/actions/workflows/bump-release.yml) +* or pushing a semver tag + * signed tags are preferred + * The tag message is prepended to release notes + + +[test-badge]: https://github.com/go-openapi/spec/actions/workflows/go-test.yml/badge.svg +[test-url]: https://github.com/go-openapi/spec/actions/workflows/go-test.yml +[cov-badge]: https://codecov.io/gh/go-openapi/spec/branch/master/graph/badge.svg +[cov-url]: https://codecov.io/gh/go-openapi/spec +[vuln-scan-badge]: https://github.com/go-openapi/spec/actions/workflows/scanner.yml/badge.svg +[vuln-scan-url]: https://github.com/go-openapi/spec/actions/workflows/scanner.yml +[codeql-badge]: https://github.com/go-openapi/spec/actions/workflows/codeql.yml/badge.svg +[codeql-url]: https://github.com/go-openapi/spec/actions/workflows/codeql.yml + +[release-badge]: https://badge.fury.io/gh/go-openapi%2Fspec.svg +[release-url]: https://badge.fury.io/gh/go-openapi%2Fspec +[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fspec.svg +[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fspec + +[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/spec +[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/spec +[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/spec +[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/spec + +[doc-badge]: https://img.shields.io/badge/doc-site-blue?link=https%3A%2F%2Fgoswagger.io%2Fgo-openapi%2F +[doc-url]: https://goswagger.io/go-openapi +[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/spec +[godoc-url]: http://pkg.go.dev/github.com/go-openapi/spec +[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue +[discord-url]: https://discord.gg/FfnFYaC3k5 + + +[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg +[license-url]: https://github.com/go-openapi/spec/?tab=Apache-2.0-1-ov-file#readme + +[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/spec +[goversion-url]: https://github.com/go-openapi/spec/blob/master/go.mod +[top-badge]: https://img.shields.io/github/languages/top/go-openapi/spec +[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/spec/latest + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/spec/SECURITY.md b/vendor/github.com/go-openapi/spec/SECURITY.md new file mode 100644 index 00000000000..1fea2c5736a --- /dev/null +++ b/vendor/github.com/go-openapi/spec/SECURITY.md @@ -0,0 +1,37 @@ +# Security Policy + +This policy outlines the commitment and practices of the go-openapi maintainers regarding security. + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| O.x | :white_check_mark: | + +## Vulnerability checks in place + +This repository uses automated vulnerability scans, at every merged commit and at least once a week. + +We use: + +* [`GitHub CodeQL`][codeql-url] +* [`trivy`][trivy-url] +* [`govulncheck`][govulncheck-url] + +Reports are centralized in github security reports and visible only to the maintainers. + +## Reporting a vulnerability + +If you become aware of a security vulnerability that affects the current repository, +**please report it privately to the maintainers** +rather than opening a publicly visible GitHub issue. + +Please follow the instructions provided by github to [Privately report a security vulnerability][github-guidance-url]. + +> [!NOTE] +> On Github, navigate to the project's "Security" tab then click on "Report a vulnerability". + +[codeql-url]: https://github.com/github/codeql +[trivy-url]: https://trivy.dev/docs/latest/getting-started +[govulncheck-url]: https://go.dev/blog/govulncheck +[github-guidance-url]: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability diff --git a/vendor/github.com/go-openapi/spec/appveyor.yml b/vendor/github.com/go-openapi/spec/appveyor.yml deleted file mode 100644 index 0903593916e..00000000000 --- a/vendor/github.com/go-openapi/spec/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: "0.1.{build}" - -clone_folder: C:\go-openapi\spec -shallow_clone: true # for startup speed -pull_requests: - do_not_increment_build_number: true - -#skip_tags: true -#skip_branch_with_pr: true - -# appveyor.yml -build: off - -environment: - GOPATH: c:\gopath - -stack: go 1.15 - -test_script: - - go test -v -timeout 20m ./... - -deploy: off - -notifications: - - provider: Slack - incoming_webhook: https://hooks.slack.com/services/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 - auth_token: - secure: Sf7kZf7ZGbnwWUMpffHwMu5A0cHkLK2MYY32LNTPj4+/3qC3Ghl7+9v4TSLOqOlCwdRNjOGblAq7s+GDJed6/xgRQl1JtCi1klzZNrYX4q01pgTPvvGcwbBkIYgeMaPeIRcK9OZnud7sRXdttozgTOpytps2U6Js32ip7uj5mHSg2ub0FwoSJwlS6dbezZ8+eDhoha0F/guY99BEwx8Bd+zROrT2TFGsSGOFGN6wFc7moCqTHO/YkWib13a2QNXqOxCCVBy/lt76Wp+JkeFppjHlzs/2lP3EAk13RIUAaesdEUHvIHrzCyNJEd3/+KO2DzsWOYfpktd+KBCvgaYOsoo7ubdT3IROeAegZdCgo/6xgCEsmFc9ZcqCfN5yNx2A+BZ2Vwmpws+bQ1E1+B5HDzzaiLcYfG4X2O210QVGVDLWsv1jqD+uPYeHY2WRfh5ZsIUFvaqgUEnwHwrK44/8REAhQavt1QAj5uJpsRd7CkRVPWRNK+yIky+wgbVUFEchRNmS55E7QWf+W4+4QZkQi7vUTMc9nbTUu2Es9NfvfudOpM2wZbn98fjpb/qq/nRv6Bk+ca+7XD5/IgNLMbWp2ouDdzbiHLCOfDUiHiDJhLfFZx9Bwo7ZwfzeOlbrQX66bx7xRKYmOe4DLrXhNcpbsMa8qbfxlZRCmYbubB/Y8h4= - channel: bots - on_build_success: false - on_build_failure: true - on_build_status_changed: true diff --git a/vendor/github.com/go-openapi/spec/bindata.go b/vendor/github.com/go-openapi/spec/bindata.go deleted file mode 100644 index afc83850c2e..00000000000 --- a/vendor/github.com/go-openapi/spec/bindata.go +++ /dev/null @@ -1,297 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. -// sources: -// schemas/jsonschema-draft-04.json (4.357kB) -// schemas/v2/schema.json (40.248kB) - -package spec - -import ( - "bytes" - "compress/gzip" - "crypto/sha256" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _jsonschemaDraft04Json = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x57\x3d\x6f\xdb\x3c\x10\xde\xf3\x2b\x08\x26\x63\xf2\x2a\x2f\xd0\xc9\x5b\xd1\x2e\x01\x5a\x34\x43\x37\x23\x03\x6d\x9d\x6c\x06\x14\xa9\x50\x54\x60\xc3\xd0\x7f\x2f\x28\x4a\x14\x29\x91\x92\x2d\xa7\x8d\x97\x28\xbc\xaf\xe7\x8e\xf7\xc5\xd3\x0d\x42\x08\x61\x9a\xe2\x15\xc2\x7b\xa5\x8a\x55\x92\xbc\x96\x82\x3f\x94\xdb\x3d\xe4\xe4\x3f\x21\x77\x49\x2a\x49\xa6\x1e\x1e\xbf\x24\xe6\xec\x16\xdf\x1b\xa1\x3b\xf3\xff\x02\xc9\x14\xca\xad\xa4\x85\xa2\x82\x6b\xe9\x6f\x42\x02\x32\x2c\x28\x07\x45\x5a\x15\x3d\x77\x46\x39\xd5\xcc\x25\x5e\x21\x83\xb8\x21\x18\xb6\xaf\x52\x92\xa3\x47\x68\x88\xea\x58\x80\x56\x4e\x1a\xf2\xbd\x4f\xcc\x29\x7f\x52\x90\x6b\x7d\xff\x0f\x48\xb4\x3d\x3f\x21\x7c\x27\x21\xd3\x2a\x6e\x31\xaa\x2d\x53\xdd\xf3\xe3\x42\x94\x54\xd1\x77\x78\xe2\x0a\x76\x20\xe3\x20\x68\xcb\x30\x86\x41\xf3\x2a\xc7\x2b\xf4\x78\x8e\xfe\xef\x90\x91\x8a\xa9\xc7\xb1\x1d\xc2\xd8\x2f\x0d\x75\xed\xc1\x4e\x9c\xc8\x25\x43\xac\xa8\xbe\xd7\xcc\xa9\xd1\xa9\x21\xa0\x1a\xbd\x04\x61\x94\x34\x2f\x18\xfc\x3e\x16\x50\x8e\x4d\x03\x6f\x1c\x58\xdb\x48\x23\xbc\x11\x82\x01\xe1\xfa\xd3\x3a\x8e\x30\xaf\x18\x33\x7f\xf3\x8d\x39\x11\x9b\x57\xd8\x2a\xfd\x55\x2a\x49\xf9\x0e\xc7\xec\x37\xd4\x25\xf7\xec\x5c\x66\xc7\xd7\x99\xaa\xcf\x4f\x89\x8a\xd3\xb7\x0a\x3a\xaa\x92\x15\xf4\x30\x6f\x1c\xb0\xd6\x46\xe7\x98\x39\x2d\xa4\x28\x40\x2a\x3a\x88\x9e\x29\xba\x88\x37\x2d\xca\x60\x38\xfa\xba\x5b\x20\xac\xa8\x62\xb0\x4c\xd4\xaf\xda\x45\x0a\xba\x5c\x3b\xb9\xc7\x79\xc5\x14\x2d\x18\x34\x19\x1c\x51\xdb\x25\x4d\xb4\x7e\x06\x14\x38\x6c\x59\x55\xd2\x77\xf8\x69\x59\xfc\x7b\x73\xed\x93\x43\xcb\x32\x6d\x3c\x28\xdc\x1b\x9a\xd3\x62\xab\xc2\x27\xf7\x41\xc9\x08\x2b\x23\x08\xad\x13\x57\x21\x9c\xd3\x72\x0d\x42\x72\xf8\x01\x7c\xa7\xf6\x83\xce\x39\xd7\x82\x3c\x1f\x2f\xd6\x60\x1b\xa2\xdf\x35\x89\x52\x20\xe7\x73\x74\xe0\x66\x26\x64\x4e\xb4\x97\x58\xc2\x0e\x0e\xe1\x60\x92\x34\x6d\xa0\x10\xd6\xb5\x83\x61\x27\xe6\x47\xd3\x89\xbd\x63\xfd\x3b\x8d\x03\x3d\x6c\x42\x2d\x5b\x70\xee\xe8\xdf\x4b\xf4\x66\x4e\xe1\x01\x45\x17\x80\x74\xad\x4f\xc3\xf3\xae\xc6\x1d\xc6\xd7\xc2\xce\xc9\xe1\x29\x30\x86\x2f\x4a\xa6\x4b\x15\x84\x73\xc9\x6f\xfd\x7f\xa5\x6e\x9e\xbd\xf1\xb0\xd4\xdd\x45\x5a\xc2\x3e\x4b\x78\xab\xa8\x84\x74\x4a\x91\x3b\x92\x23\x05\xf2\x1c\x1e\x7b\xf3\x09\xf8\xcf\xab\x24\xb6\x60\xa2\xe8\x4c\x9f\x75\x77\xaa\x8c\xe6\x01\x45\x36\x86\xcf\xc3\x63\x3a\xea\xd4\x8d\x7e\x06\xac\x14\x0a\xe0\x29\xf0\xed\x07\x22\x1a\x65\xda\x44\xae\xa2\x73\x1a\xe6\x90\x69\xa2\x8c\x46\xb2\x2f\xde\x49\x38\x08\xed\xfe\xfd\x41\xaf\x9f\xa9\x55\xd7\xdd\x22\x8d\xfa\x45\x63\xc5\x0f\x80\xf3\xb4\x08\xd6\x79\x30\x9e\x93\xee\x59\xa6\xd0\x4b\xee\x22\xe3\x33\xc1\x3a\x27\x68\x36\x78\x7e\x87\x0a\x06\xd5\x2e\x20\xd3\xaf\x15\xfb\xd8\x3b\x73\x14\xbb\x92\xed\x05\x5d\x2e\x29\x38\x2c\x94\xe4\x42\x45\x5e\xd3\xb5\x7d\xdf\x47\xca\x38\xb4\x5c\xaf\xfb\x7d\xdd\x6d\xf4\xa1\x2d\x77\xdd\x2f\xce\x6d\xc4\x7b\x8b\x4e\x67\xa9\x6f\xfe\x04\x00\x00\xff\xff\xb1\xd1\x27\x78\x05\x11\x00\x00") - -func jsonschemaDraft04JsonBytes() ([]byte, error) { - return bindataRead( - _jsonschemaDraft04Json, - "jsonschema-draft-04.json", - ) -} - -func jsonschemaDraft04Json() (*asset, error) { - bytes, err := jsonschemaDraft04JsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "jsonschema-draft-04.json", size: 4357, mode: os.FileMode(0640), modTime: time.Unix(1568963823, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe1, 0x48, 0x9d, 0xb, 0x47, 0x55, 0xf0, 0x27, 0x93, 0x30, 0x25, 0x91, 0xd3, 0xfc, 0xb8, 0xf0, 0x7b, 0x68, 0x93, 0xa8, 0x2a, 0x94, 0xf2, 0x48, 0x95, 0xf8, 0xe4, 0xed, 0xf1, 0x1b, 0x82, 0xe2}} - return a, nil -} - -var _v2SchemaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\x4f\x93\xdb\x36\xb2\xbf\xfb\x53\xa0\x14\x57\xd9\xae\xd8\x92\xe3\xf7\x2e\xcf\x97\xd4\xbc\xd8\x49\x66\x37\x5e\x4f\x79\x26\xbb\x87\x78\x5c\x05\x91\x2d\x09\x09\x09\x30\x00\x38\x33\x5a\xef\x7c\xf7\x2d\xf0\x9f\x08\x02\x20\x41\x8a\xd2\xc8\x0e\x0f\xa9\x78\x28\xa0\xd1\xdd\x68\x34\x7e\xdd\xf8\xf7\xf9\x11\x42\x33\x49\x64\x04\xb3\xd7\x68\x76\x86\xfe\x76\xf9\xfe\x1f\xe8\x32\xd8\x40\x8c\xd1\x8a\x71\x74\x79\x8b\xd7\x6b\xe0\xe8\xd5\xfc\x25\x3a\xbb\x38\x9f\xcf\x9e\xab\x0a\x24\x54\xa5\x37\x52\x26\xaf\x17\x0b\x91\x17\x99\x13\xb6\xb8\x79\xb5\x10\x59\xdd\xf9\xef\x82\xd1\x6f\xf2\xc2\x8f\xf3\x4f\xb5\x1a\xea\xc7\x17\x45\x41\xc6\xd7\x8b\x90\xe3\x95\x7c\xf1\xf2\x7f\x8b\xca\x45\x3d\xb9\x4d\x32\xa6\xd8\xf2\x77\x08\x64\xfe\x8d\xc3\x9f\x29\xe1\xa0\x9a\xff\xed\x11\x42\x08\xcd\x8a\xd6\xb3\x9f\x15\x67\x74\xc5\xca\x7f\x27\x58\x6e\xc4\xec\x11\x42\xd7\x59\x5d\x1c\x86\x44\x12\x46\x71\x74\xc1\x59\x02\x5c\x12\x10\xb3\xd7\x68\x85\x23\x01\x59\x81\x04\x4b\x09\x9c\x6a\xbf\x7e\xce\x49\x7d\xba\x7b\x51\xfd\xa1\x44\xe2\xb0\x52\xac\x7d\xb3\x08\x61\x45\x68\x46\x56\x2c\x6e\x80\x86\x8c\xbf\xbd\x93\x40\x05\x61\x74\x96\x95\xbe\x7f\x84\xd0\x7d\x4e\xde\x42\xb7\xe4\xbe\x46\xbb\x14\x5b\x48\x4e\xe8\xba\x90\x05\xa1\x19\xd0\x34\xae\xc4\xce\xbe\xbc\x9a\xbf\x9c\x15\x7f\x5d\x57\xc5\x42\x10\x01\x27\x89\xe2\x48\x51\xb9\xda\x40\xd5\x87\x37\xc0\x15\x5f\x88\xad\x90\xdc\x10\x81\x42\x16\xa4\x31\x50\x39\x2f\x38\xad\xab\xb0\x53\xd8\xac\x94\x56\x6f\xc3\x84\xf4\x11\xa4\x50\xb3\xfa\xe9\xd3\x6f\x9f\x3e\xdf\x2f\xd0\xeb\x8f\x1f\x3f\x7e\xbc\xfe\xf6\xe9\xf7\xaf\x5f\x7f\xfc\x18\x7e\xfb\xec\xfb\xc7\xb3\x36\x79\x54\x43\xe8\x29\xc5\x31\x20\xc6\x11\x49\x9e\xe5\x12\x41\x66\xa0\xe8\xed\x1d\x8e\x93\x08\x5e\xa3\x27\x3b\xc3\x7c\xa2\x73\xba\xc4\x02\x2e\xb0\xdc\xf4\xe5\x76\xd1\xca\x96\xa2\x8a\x94\xcd\x21\xc9\x6c\xec\x2c\x70\x42\x9e\x34\x74\x9d\x19\x7c\xcd\x20\x9c\xea\x2e\x0a\xfe\x42\x84\xd4\x29\x04\x8c\x8a\xb4\x41\xa2\xc1\xdc\x19\x8a\x88\x90\x4a\x49\xef\xce\xdf\xbd\x45\x4a\x52\x81\x70\x10\x40\x22\x21\x44\xcb\x6d\xc5\xec\x4e\x3c\x1c\x45\xef\x57\x9a\xb5\x7d\xae\xfe\xe5\xe4\x31\x86\x90\xe0\xab\x6d\x02\x3b\x2e\xcb\x11\x90\xd9\xa8\xc6\x77\xc2\x59\x98\x06\xfd\xf9\x2e\x78\x45\x01\xa6\xa8\xa0\x71\x5c\xbe\x33\xa7\xd2\xd9\x5f\x95\xef\xd9\xd5\xac\xfd\xdc\x5d\xbf\x5e\xb8\xd1\x3e\xc7\x31\x48\xe0\x5e\x4c\x14\x65\xdf\xb8\xa8\x71\x10\x09\xa3\xc2\xc7\x02\xcb\xa2\x4e\x5a\x02\x82\x94\x13\xb9\xf5\x30\xe6\xb2\xa4\xb5\xfe\x9b\x3e\x7a\xb2\x55\xd2\xa8\x4a\xbc\x16\xb6\x71\x8e\x39\xc7\xdb\x9d\xe1\x10\x09\x71\xbd\x9c\xb3\x41\x89\xd7\xa5\x89\xdc\x57\xb5\x53\x4a\xfe\x4c\xe1\xbc\xa0\x21\x79\x0a\x1a\x0f\x70\xa7\x5c\x08\x8e\xde\xb0\xc0\x43\x24\xad\x74\x63\x0e\xb1\xd9\x90\xe1\xb0\x2d\x13\xa7\x6d\x78\xfd\x04\x14\x38\x8e\x90\xaa\xce\x63\xac\x3e\x23\xbc\x64\xa9\xb4\xf8\x03\x63\xde\xcd\xbe\x16\x13\x4a\x55\xac\x82\x12\xc6\xac\xd4\x35\xf7\x22\xd4\x3a\xff\x22\x73\x0e\x6e\x51\xa0\x75\x1e\xae\x8f\xe8\x5d\xc7\x59\xe6\xe4\x9a\x18\x8d\xd6\x1c\x53\x84\x4d\xb7\x67\x28\x37\x09\x84\x69\x88\x12\x0e\x01\x11\x80\x32\xa2\xf5\xb9\xaa\xc6\xd9\x73\x53\xab\xfb\xb4\x2e\x20\xc6\x54\x92\xa0\x9a\xf3\x69\x1a\x2f\x81\x77\x37\xae\x53\x1a\xce\x40\xc4\xa8\x82\x1c\xb5\xef\xda\x24\x7d\xb9\x61\x69\x14\xa2\x25\xa0\x90\xac\x56\xc0\x81\x4a\xb4\xe2\x2c\xce\x4a\x64\x7a\x9a\x23\xf4\x13\x91\x3f\xa7\x4b\xf4\x63\x84\x6f\x18\x87\x10\xbd\xc3\xfc\x8f\x90\xdd\x52\x44\x04\xc2\x51\xc4\x6e\x21\x74\x48\x21\x81\xc7\xe2\xfd\xea\x12\xf8\x0d\x09\xf6\xe9\x47\x35\xaf\x67\xc4\x14\xf7\x22\x27\x97\xe1\xe2\x76\x2d\x06\x8c\x4a\x1c\x48\x3f\x73\x2d\x0b\x5b\x29\x45\x24\x00\x2a\x0c\x11\xec\x94\xca\xc2\xa6\xc1\x37\x21\x43\x83\x3b\x5f\x97\xf1\x43\x5e\x53\x73\x19\xa5\x36\xd8\x2d\x05\x2e\x34\x0b\xeb\x39\xfc\x1d\x63\x51\x01\xbd\x3d\xbb\x90\x84\x40\x25\x59\x6d\x09\x5d\xa3\x1c\x37\xe6\x5c\x16\x9a\x40\x09\x70\xc1\xe8\x82\xf1\x35\xa6\xe4\xdf\x99\x5c\x8e\x9e\x4d\x79\xb4\x27\x2f\xbf\x7e\xf8\x05\x25\x8c\x50\xa9\x98\x29\x90\x62\x60\xea\x75\xae\x13\xca\xbf\x2b\x1a\x29\x27\x76\xd6\x20\xc6\x64\x5f\xe6\x32\x1a\x08\x87\x21\x07\x21\xbc\xb4\xe4\xe0\x32\x67\xa6\xcd\xf3\x1e\xcd\xd9\x6b\xb6\x6f\x8e\x27\xa7\xed\xdb\xe7\xbc\xcc\x1a\x07\xce\x6f\x87\x33\xf0\xba\x51\x17\x22\x66\x78\x79\x8e\xce\xe5\x13\x81\x80\x06\x2c\xe5\x78\x0d\xa1\xb2\xb8\x54\xa8\x79\x09\xbd\xbf\x3c\x47\x01\x8b\x13\x2c\xc9\x32\xaa\xaa\x1d\xd5\xee\xab\x36\xbd\x6c\xfd\x54\x6c\xc8\x08\x01\x3c\xbd\xe7\x07\x88\xb0\x24\x37\x79\x90\x28\x4a\x1d\x10\x1a\x92\x1b\x12\xa6\x38\x42\x40\xc3\x4c\x43\x62\x8e\xae\x36\xb0\x45\x71\x2a\xa4\x9a\x23\x79\x59\xb1\xa8\xf2\xa4\x0c\x60\x9f\xcc\x8d\x40\xf5\x80\xca\xa8\x99\xc3\xa7\x85\x1f\x31\x25\xa9\x82\xc5\x6d\xbd\xd8\x36\x76\x7c\x02\x28\x97\xf6\x1d\x74\x3b\x11\x7e\x91\xae\x32\xf8\x6c\xf4\xe6\x7b\x9a\xa5\x1f\x62\xc6\x21\xcf\x9a\xe5\xed\x8b\x02\xf3\x2c\x33\x33\xdf\x00\xca\xc9\x09\xb4\x04\xf5\xa5\x08\xd7\xc3\x02\x18\x66\xf1\xab\x1e\x83\x37\x4c\xcd\x12\xc1\x1d\x50\xf6\xaa\xbd\xfe\xe2\x73\x48\x38\x08\xa0\x32\x9b\x18\x44\x86\x0b\x6a\xc1\xaa\x26\x96\x2d\x96\x3c\xa0\x54\x65\x73\xe3\x08\xb5\x8b\x99\xbd\x82\xbc\x9e\xc2\xe8\x53\x46\x83\x3f\x33\x54\x2b\x5b\xad\x92\x79\xd9\x8f\x5d\x93\x98\xf2\xe6\xc6\x1c\xe6\x9a\x9e\xfc\x43\x82\x31\x66\x8e\x53\x77\xfe\x90\xe7\xf3\xf6\xe9\x62\x23\x3f\x10\x93\x18\xae\x72\x1a\x9d\xf9\x48\xcb\xcc\x5a\x65\xc7\x4a\x04\xf0\xf3\xd5\xd5\x05\x8a\x41\x08\xbc\x86\x86\x43\x51\x6c\xe0\x46\x57\xf6\x44\x40\x0d\xfb\xff\xa2\xc3\x7c\x3d\x39\x84\xdc\x09\x22\x64\x4f\x12\xd9\xba\xaa\xf6\xe3\xbd\x56\xdd\x91\x25\x6a\x14\x9c\x89\x34\x8e\x31\xdf\xee\x15\x7e\x2f\x39\x81\x15\x2a\x28\x95\x66\x51\xf5\xfd\x83\xc5\xfe\x15\x07\xcf\xf7\x08\xee\x1d\x8e\xb6\xc5\x52\xcc\x8c\x5a\x93\x66\xc5\xd8\x79\x38\x46\xd6\xa7\x88\x37\xc9\x2e\xe3\xd2\xa5\x7b\x4b\x3a\xdc\xa1\xdc\x9e\x29\xf1\x8c\x8a\x99\x16\x47\x8d\xd4\x78\x8b\xf6\x1c\xe9\x71\x54\x1b\x69\xa8\x4a\x93\x37\xe5\xb2\x2c\x4f\x0c\x92\xab\xa0\x73\x32\x72\x59\xd3\xf0\x2d\x8d\xed\xca\x37\x16\x19\x9e\xdb\x1c\xab\x17\x49\xc3\x0f\x37\xdc\x88\xb1\xb4\xd4\x42\xcb\x58\x5e\x6a\x52\x0b\x15\x10\x0a\xb0\x04\xe7\xf8\x58\x32\x16\x01\xa6\xcd\x01\xb2\xc2\x69\x24\x35\x38\x6f\x30\x6a\xae\x1b\xb4\x71\xaa\xad\x1d\xa0\xd6\x20\x2d\x8b\x3c\xc6\x82\x62\x27\x34\x6d\x15\x84\x7b\x43\xb1\x35\x78\xa6\x24\x77\x28\xc1\x6e\xfc\xe9\x48\x74\xf4\x15\xe3\xe1\x84\x42\x88\x40\x7a\x26\x49\x3b\x48\xb1\xa4\x19\x8e\x0c\xa7\xb5\x01\x6c\x0c\x97\x61\x8a\xc2\x32\xd8\x8c\x44\x69\x24\xbf\x65\x1d\x74\xd6\xe5\x44\xef\xec\x48\x5e\xb7\x8a\xa3\x29\x8e\x41\x64\xce\x1f\x88\xdc\x00\x47\x4b\x40\x98\x6e\xd1\x0d\x8e\x48\x98\x63\x5c\x21\xb1\x4c\x05\x0a\x58\x98\xc5\x6d\x4f\x0a\x77\x53\x4f\x8b\xc4\x44\x1f\xb2\xdf\x8d\x3b\xea\x9f\xfe\xf6\xf2\xc5\xff\x5d\x7f\xfe\x9f\xfb\x67\x8f\xff\xf3\xe9\x69\xd1\xfe\xb3\xc7\xfd\x3c\xf8\x3f\x71\x94\x82\x23\xd1\x72\x00\xb7\x42\x99\x6c\xc0\x60\x7b\x0f\x79\xea\xa8\x53\x4b\x56\x31\xfa\x0b\x52\x9f\x96\xdb\xcd\x2f\xd7\x67\xcd\x04\x19\x85\xfe\xdb\x02\x9a\x59\x03\xad\x63\x3c\xea\xff\x2e\x18\xfd\x00\xd9\xe2\x56\x60\x59\x93\xb9\xb6\xb2\x3e\x3c\x2c\xab\x0f\xa7\xb2\x89\x43\xc7\xf6\xd5\xce\x2e\xad\xa6\xa9\xed\xa6\xc6\x5a\xb4\xa6\x67\xdf\x8c\x26\x7b\x50\x5a\x91\x08\x2e\x6d\xd4\x3a\xc1\x9d\xf2\xdb\xde\x1e\xb2\x2c\x6c\xa5\x64\xc9\x16\xb4\x90\xaa\x4a\xb7\x0c\xde\x13\xc3\x2a\x9a\x11\x9b\x7a\x1b\x3d\x95\x97\x37\x31\x6b\x69\x7e\x34\xc0\x67\x1f\x66\x19\x49\xef\xf1\x25\xf5\xac\x0e\xea\x0a\x28\x8d\x4d\x7e\xd9\x57\x4b\x49\xe5\xc6\xb3\x25\xfd\xe6\x57\x42\x25\xac\xcd\xcf\x36\x74\x8e\xca\x24\x47\xe7\x80\xa8\x92\x72\xbd\x3d\x84\x2d\x65\xe2\x82\x1a\x9c\xc4\x44\x92\x1b\x10\x79\x8a\xc4\x4a\x2f\x60\x51\x04\x81\xaa\xf0\xa3\x95\x27\xd7\x12\x7b\xa3\x96\x03\x45\x96\xc1\x8a\x07\xc9\xb2\xb0\x95\x52\x8c\xef\x48\x9c\xc6\x7e\x94\xca\xc2\x0e\x07\x12\x44\xa9\x20\x37\xf0\xae\x0f\x49\xa3\x96\x9d\x4b\x42\x7b\x70\x59\x14\xee\xe0\xb2\x0f\x49\xa3\x96\x4b\x97\xbf\x00\x5d\x4b\x4f\xfc\xbb\x2b\xee\x92\xb9\x17\xb5\xaa\xb8\x0b\x97\x17\x9b\x43\xfd\xd6\xc2\xb2\xc2\x2e\x29\xcf\xfd\x87\x4a\x55\xda\x25\x63\x1f\x5a\x65\x69\x2b\x2d\x3d\x67\xe9\x41\xae\x5e\xc1\x6e\x2b\xd4\xdb\x3e\xa8\xd3\x26\xd2\x48\x92\x24\xca\x61\x86\x8f\x8c\xbb\xf2\x8e\x91\xdf\x1f\x06\x19\x33\xf3\x03\x4d\xba\xcd\xe2\x2d\xfb\x69\xe9\x16\x15\x13\xd5\x56\x85\x4e\x3c\x5b\x8a\xbf\x25\x72\x83\xee\x5e\x20\x22\xf2\xc8\xaa\x7b\xdb\x8e\xe4\x29\x58\xca\x38\xb7\x3f\x2e\x59\xb8\xbd\xa8\x16\x16\xf7\xdb\x79\x51\x9f\x5a\xb4\x8d\x87\x3a\x6e\xbc\x3e\xc5\xb4\xcd\x58\xf9\xf5\x3c\xb9\x6f\x49\xaf\x57\xc1\xfa\x1c\x5d\x6d\x88\x8a\x8b\xd3\x28\xcc\xb7\xef\x10\x8a\x4a\x74\xa9\x4a\xa7\x62\xbf\x0d\x76\x23\x6f\x59\xd9\x31\xee\x40\x11\xfb\x28\xec\x8d\x22\x1c\x13\x5a\x64\x94\x23\x16\x60\xbb\xd2\x7c\xa0\x98\xb2\xe5\x6e\xbc\x54\x33\xe0\x3e\xb9\x52\x17\xdb\xb7\x1b\xc8\x12\x20\x8c\x23\xca\x64\x7e\x78\xa3\x62\x5b\x75\x56\xd9\x9e\x2a\x91\x27\xb0\x70\x34\x1f\x90\x89\xb5\x86\x73\x7e\x71\xda\x1e\xfb\x3a\x72\xdc\x5e\x79\x88\xcb\x74\x79\xd9\x64\xe4\xd4\xc2\x9e\xce\xb1\xfe\x85\x5a\xc0\xe9\x0c\x34\x3d\xd0\x43\xce\xa1\x36\x39\xd5\xa1\x4e\xf5\xf8\xb1\xa9\x23\x08\x75\x84\xac\x53\x6c\x3a\xc5\xa6\x53\x6c\x3a\xc5\xa6\x7f\xc5\xd8\xf4\x51\xfd\xff\x25\x4e\xfa\x33\x05\xbe\x9d\x60\xd2\x04\x93\x6a\x5f\x33\x9b\x98\x50\xd2\xe1\x50\x52\xc6\xcc\xdb\x38\x91\xdb\xe6\xaa\xa2\x8f\xa1\x6a\xa6\xd4\xc6\x56\xd6\x8c\x40\x02\x68\x48\xe8\x1a\xe1\x9a\xd9\x2e\xb7\x05\xc3\x34\xda\x2a\xbb\xcd\x12\x36\x98\x22\x50\x4c\xa1\x1b\xc5\xd5\x84\xf0\xbe\x24\x84\xf7\x2f\x22\x37\xef\x94\xd7\x9f\xa0\xde\x04\xf5\x26\xa8\x37\x41\x3d\x64\x40\x3d\xe5\xf2\xde\x60\x89\x27\xb4\x37\xa1\xbd\xda\xd7\xd2\x2c\x26\xc0\x37\x01\x3e\x1b\xef\x5f\x06\xe0\x6b\x7c\x5c\x91\x08\x26\x10\x38\x81\xc0\x09\x04\x76\x4a\x3d\x81\xc0\xbf\x12\x08\x4c\xb0\xdc\x7c\x99\x00\xd0\x75\x70\xb4\xf8\x5a\x7c\xea\xde\x3e\x39\x08\x30\x5a\x27\x35\xed\xb4\x65\xad\x69\x74\x10\x88\x79\xe2\x30\x52\x19\xd6\x04\x21\xa7\x95\xd5\x0e\x03\xf8\xda\x20\xd7\x84\xb4\x26\xa4\x35\x21\xad\x09\x69\x21\x03\x69\x51\x46\xff\xff\x18\x9b\x54\xed\x87\x47\x06\x9d\x4e\x73\x6e\x9a\xb3\xa9\xce\x83\x5e\x4b\xc6\x71\x20\x45\xd7\x72\xf5\x40\x72\x0e\x34\x6c\xf4\x6c\xf3\xba\x5e\x4b\x97\x0e\x52\xb8\xbe\x8b\x79\xa0\x10\x86\xa1\x75\xb0\x6f\xec\xc8\xf4\x3d\x4d\x7b\x86\xc2\x02\x31\x12\x51\xbf\x07\x94\xad\x10\xd6\x2e\x79\xcf\xe9\x1c\xf5\x1e\x31\x23\x5c\x18\xfb\x9c\xfb\x70\xe0\x62\xbd\xf7\xb5\x94\xcf\xf3\xf6\xfa\xc5\x4e\x9c\x85\x76\x1d\xae\x37\xbc\xde\xa3\x41\xcb\x29\xd0\x5e\x70\x67\x50\x93\x6d\x98\xa8\xd3\x67\x0f\x68\xb1\xeb\x38\x47\x07\x10\x1b\xd2\xe2\x18\x68\x6d\x40\xbb\xa3\x40\xba\x21\xf2\x8e\x81\xfb\xf6\x92\x77\x2f\x70\xe8\xdb\xb2\x36\xbf\x30\x91\xc5\x21\xe7\x45\xcc\x34\x0c\x48\x8e\xd0\xf2\x9b\x7c\x3c\xbd\x1c\x04\x3e\x07\xe8\x7c\x2f\x84\x7a\x48\x4d\x1f\xba\xe1\x76\x45\x7b\x60\xe0\x01\xca\xee\x04\xca\x31\xbe\x73\x5f\xa3\x70\x0c\xad\x1f\xa5\xf5\x76\xd5\xbb\xd2\x7e\xfb\x30\x90\xcf\xfa\x67\x7a\xe6\xc3\x37\x42\x19\xe2\xc9\x9c\x61\x4c\xe7\xd1\x77\x55\x86\x6e\x8f\x7b\x85\x42\x33\xa3\xaa\x57\xae\xfd\xd5\xcc\x9c\x56\x68\xe2\xde\x0e\xa8\x2c\xa9\xb0\x7d\xf0\x54\x2d\x80\xf2\x48\x39\x3d\x98\x1a\x6d\x0b\x9d\xba\x53\xfb\xce\xf8\xd1\x7e\xbb\x60\x4f\x06\xf5\xce\xda\xab\xeb\xca\xcb\xd5\xac\x20\xda\x72\x3b\xa2\x4b\x38\xd7\xb5\x89\xbe\x42\xd9\xb9\x73\xc4\x0c\x6d\xb7\xd9\xf8\x8d\xbd\x3e\x9c\xf5\x53\x68\x48\x14\x36\x8f\x09\xc5\x92\xf1\x21\xd1\x09\x07\x1c\xbe\xa7\x91\xf3\x6a\xc8\xc1\x57\xb0\xdd\xc5\xc6\x1d\xad\x76\x1d\xa8\x82\x0e\x4c\x38\xfe\xa5\x8c\xc5\x0a\x40\x5d\xa1\xbb\x98\xd1\xfb\x74\x61\xed\x1a\x98\xaf\x3c\x8c\x1e\xe3\xc2\x92\x29\x74\x3e\x99\xd0\xf9\x41\x50\xd0\x38\x4b\x57\x7e\x5b\x7a\x0e\xe6\xce\x4e\xd7\x19\x35\x57\xbb\x3c\x3c\xd2\x5e\x4f\x4b\x4c\xf7\x0f\x4d\x2b\x91\x5d\x94\xa6\x95\xc8\x69\x25\x72\x5a\x89\x7c\xb8\x95\xc8\x07\x80\x8c\xda\x9c\x64\x7b\xb7\x71\xdf\x57\x12\x4b\x9a\x1f\x72\x0c\x13\x03\xad\x3c\xd5\x4e\xde\x8e\x57\x13\x6d\x34\x86\xcf\x97\xe6\xa4\x68\xc4\xb0\xf6\xc9\xc2\xeb\x8d\x0b\xd7\xcd\xfe\xba\xa6\xf5\x30\xeb\x30\x33\xbe\xc7\x56\x27\xab\x08\xd9\x6d\xbb\x09\xee\x7c\x2d\xcf\xee\x87\x38\xac\xc8\xdd\x90\x9a\x58\x4a\x4e\x96\xa9\x79\x79\xf3\xde\x20\xf0\x96\xe3\x24\x19\xeb\xba\xf2\x53\x19\xab\x12\xaf\x47\xb3\xa0\x3e\xef\x9b\x8d\x6d\x6d\x7b\xde\x3b\x3b\x1a\xc0\x3f\x95\x7e\xed\x78\xfb\x76\xb8\xaf\xb3\xdd\xc5\xeb\x95\xed\x5a\x62\x41\x82\xb3\x54\x6e\x80\x4a\x92\x6f\x36\xbd\x34\xae\xde\x6f\xa4\xc0\xbc\x08\xe3\x84\xfc\x1d\xb6\xe3\xd0\x62\x38\x95\x9b\x57\xe7\x71\x12\x91\x80\xc8\x31\x69\x5e\x60\x21\x6e\x19\x0f\xc7\xa4\x79\x96\x28\x3e\x47\x54\x65\x41\x36\x08\x40\x88\x1f\x58\x08\x56\xaa\xd5\xbf\xaf\xad\x96\xd7\xd6\xcf\x87\xf5\x34\x0f\x71\x93\x6e\x26\xed\x98\x5b\x9f\x4f\xcf\x95\x34\xc6\xd7\x11\xfa\xb0\x81\x22\x1a\xdb\xdf\x8e\xdc\xc3\xb9\xf8\xdd\x5d\x3c\x74\xe6\xea\xb7\x8b\xbf\xf5\x6e\xb3\x46\x2e\x64\xf4\xab\x3c\x4e\xcf\x36\x1d\xfe\xfa\xb8\x36\xba\x8a\xd8\xad\xf6\xc6\x41\x2a\x37\x8c\x17\x0f\xda\xfe\xda\xe7\x65\xbc\x71\x2c\x36\x57\x8a\x47\x12\x4c\xf1\xbd\x77\x6b\xa4\x50\x7e\x77\x7b\x22\x60\x89\xef\xcd\xf5\xb9\x0c\x97\x79\x0d\x2b\x35\x43\xcb\x3d\x24\xf1\x78\xfc\xf8\xcb\x1f\x15\x06\xe2\x78\xd8\x51\x21\xd9\x1f\xf0\xf5\x8f\x86\xa4\x50\xfa\xb1\x47\x43\xa5\xdd\x69\x14\xe8\xa3\xc0\x86\x91\xa7\x81\x50\xb4\x7c\xc0\x81\x80\x77\x7a\x9f\xc6\xc2\xa9\x8c\x05\x33\xb0\x3b\x31\xa4\xf4\xd7\x1b\x26\x55\x97\x7c\x65\xf8\x69\x1a\x84\x8e\x41\x78\xd9\xec\xc5\x11\x16\x1e\x74\x91\xf5\x56\xf5\x57\x49\x47\x5c\x92\xa9\x1e\x99\x36\xf4\xdb\xb1\x0e\xd3\x78\x02\xb0\x9b\x25\xcb\xe9\xe9\x1d\x0d\x44\x01\x42\x08\x91\x64\xd9\xdd\x37\x08\x17\xef\xf9\xe5\x0f\xbd\x46\x91\xf5\xf9\x89\x92\x37\xdd\x89\x59\x44\x1f\x9c\xee\x34\x1e\xbe\x47\x83\x32\x72\x8e\x37\xdf\xac\x69\x38\xef\x75\xb0\xda\xdb\xac\x83\x94\x2f\x39\xa6\x62\x05\x1c\x25\x9c\x49\x16\xb0\xa8\x3c\xc7\x7e\x76\x71\x3e\x6f\xb5\x24\xe7\xe8\xb7\xb9\xc7\x6c\x43\x92\xee\x21\xd4\x17\xa1\x7f\xba\x35\xfe\xae\x39\xbc\xde\xba\x69\xd9\x8e\xe1\x62\xde\x64\x7d\x16\x88\x1b\xed\x29\x11\xfd\x4f\xa9\xff\x99\x90\xc4\xf6\xf4\xf9\x6e\xe9\x28\x23\xd7\xca\xe5\xee\xee\x9f\x63\xb1\x5b\xfb\x10\xd7\x2f\x1d\xf2\xe3\xbf\xb9\xb5\x6f\xa4\x6d\x7d\x25\x79\xfb\x24\x31\xea\x56\xbe\x5d\x53\xcd\x2d\x36\xa3\x6d\xdf\xab\x1c\xb8\x6d\x6f\xc0\x98\xa7\xdd\xaa\x86\x8c\x1d\x39\xa3\x9d\x70\x2b\x9b\x68\xd9\xfd\x33\xfe\xa9\xb6\x4a\x2e\x63\x0f\xcf\x68\x27\xd9\x4c\xb9\x46\x6d\xcb\xbe\xa1\xa8\xd6\x5f\xc6\xd6\x9f\xf1\x4f\xf4\xd4\xb4\x78\xd0\xd6\xf4\x13\x3c\x3b\xac\xd0\xdc\x90\x34\xda\xc9\xb4\x9a\x1a\x8d\xbd\x93\x87\xd4\xe2\x21\x1b\xb3\x2b\xd1\xbe\xe7\x69\xd4\x53\x67\xd5\x40\xa0\xe3\x19\x3f\x6d\x1a\xbc\x0e\x86\x3c\x10\xb4\x3d\x2a\xcd\x78\x32\xe6\xab\xbd\x36\xc9\xf4\x3a\x58\xae\xc3\xf4\x47\xea\xbf\xfb\x47\xff\x0d\x00\x00\xff\xff\xd2\x32\x5a\x28\x38\x9d\x00\x00") - -func v2SchemaJsonBytes() ([]byte, error) { - return bindataRead( - _v2SchemaJson, - "v2/schema.json", - ) -} - -func v2SchemaJson() (*asset, error) { - bytes, err := v2SchemaJsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "v2/schema.json", size: 40248, mode: os.FileMode(0640), modTime: time.Unix(1568964748, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xab, 0x88, 0x5e, 0xf, 0xbf, 0x17, 0x74, 0x0, 0xb2, 0x5a, 0x7f, 0xbc, 0x58, 0xcd, 0xc, 0x25, 0x73, 0xd5, 0x29, 0x1c, 0x7a, 0xd0, 0xce, 0x79, 0xd4, 0x89, 0x31, 0x27, 0x90, 0xf2, 0xff, 0xe6}} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "jsonschema-draft-04.json": jsonschemaDraft04Json, - - "v2/schema.json": v2SchemaJson, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "jsonschema-draft-04.json": {jsonschemaDraft04Json, map[string]*bintree{}}, - "v2": {nil, map[string]*bintree{ - "schema.json": {v2SchemaJson, map[string]*bintree{}}, - }}, -}} - -// RestoreAsset restores an asset under the given directory. -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) -} - -// RestoreAssets restores an asset under the given directory recursively. -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) -} diff --git a/vendor/github.com/go-openapi/spec/cache.go b/vendor/github.com/go-openapi/spec/cache.go index 122993b44b4..06495d2c3d3 100644 --- a/vendor/github.com/go-openapi/spec/cache.go +++ b/vendor/github.com/go-openapi/spec/cache.go @@ -1,40 +1,28 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec import ( + "maps" "sync" ) -// ResolutionCache a cache for resolving urls +// ResolutionCache a cache for resolving urls. type ResolutionCache interface { - Get(string) (interface{}, bool) - Set(string, interface{}) + Get(uri string) (any, bool) + Set(uri string, data any) } type simpleCache struct { lock sync.RWMutex - store map[string]interface{} + store map[string]any } -func (s *simpleCache) ShallowClone() ResolutionCache { - store := make(map[string]interface{}, len(s.store)) +func (s *simpleCache) ShallowClone() ResolutionCache { //nolint:ireturn // returns the public interface type by design + store := make(map[string]any, len(s.store)) s.lock.RLock() - for k, v := range s.store { - store[k] = v - } + maps.Copy(store, s.store) s.lock.RUnlock() return &simpleCache{ @@ -42,8 +30,8 @@ func (s *simpleCache) ShallowClone() ResolutionCache { } } -// Get retrieves a cached URI -func (s *simpleCache) Get(uri string) (interface{}, bool) { +// Get retrieves a cached URI. +func (s *simpleCache) Get(uri string) (any, bool) { s.lock.RLock() v, ok := s.store[uri] @@ -51,8 +39,8 @@ func (s *simpleCache) Get(uri string) (interface{}, bool) { return v, ok } -// Set caches a URI -func (s *simpleCache) Set(uri string, data interface{}) { +// Set caches a URI. +func (s *simpleCache) Set(uri string, data any) { s.lock.Lock() s.store[uri] = data s.lock.Unlock() @@ -68,8 +56,8 @@ var ( // // All subsequent utilizations of this cache are produced from a shallow // clone of this initial version. - resCache *simpleCache - onceCache sync.Once + resCache *simpleCache //nolint:gochecknoglobals // package-level lazy cache for $ref resolution + onceCache sync.Once //nolint:gochecknoglobals // guards lazy init of resCache _ ResolutionCache = &simpleCache{} ) @@ -80,13 +68,13 @@ func initResolutionCache() { } func defaultResolutionCache() *simpleCache { - return &simpleCache{store: map[string]interface{}{ + return &simpleCache{store: map[string]any{ "http://swagger.io/v2/schema.json": MustLoadSwagger20Schema(), "http://json-schema.org/draft-04/schema": MustLoadJSONSchemaDraft04(), }} } -func cacheOrDefault(cache ResolutionCache) ResolutionCache { +func cacheOrDefault(cache ResolutionCache) ResolutionCache { //nolint:ireturn // returns the public interface type by design onceCache.Do(initResolutionCache) if cache != nil { diff --git a/vendor/github.com/go-openapi/spec/contact_info.go b/vendor/github.com/go-openapi/spec/contact_info.go index 2f7bb219b56..46fada5dff1 100644 --- a/vendor/github.com/go-openapi/spec/contact_info.go +++ b/vendor/github.com/go-openapi/spec/contact_info.go @@ -1,23 +1,12 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec import ( "encoding/json" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) // ContactInfo contact information for the exposed API. @@ -28,14 +17,14 @@ type ContactInfo struct { VendorExtensible } -// ContactInfoProps hold the properties of a ContactInfo object +// ContactInfoProps hold the properties of a ContactInfo object. type ContactInfoProps struct { Name string `json:"name,omitempty"` URL string `json:"url,omitempty"` Email string `json:"email,omitempty"` } -// UnmarshalJSON hydrates ContactInfo from json +// UnmarshalJSON hydrates ContactInfo from json. func (c *ContactInfo) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &c.ContactInfoProps); err != nil { return err @@ -43,7 +32,7 @@ func (c *ContactInfo) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &c.VendorExtensible) } -// MarshalJSON produces ContactInfo as json +// MarshalJSON produces ContactInfo as json. func (c ContactInfo) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(c.ContactInfoProps) if err != nil { @@ -53,5 +42,5 @@ func (c ContactInfo) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2), nil + return jsonutils.ConcatJSON(b1, b2), nil } diff --git a/vendor/github.com/go-openapi/spec/debug.go b/vendor/github.com/go-openapi/spec/debug.go index fc889f6d0b0..fa52b0c7f77 100644 --- a/vendor/github.com/go-openapi/spec/debug.go +++ b/vendor/github.com/go-openapi/spec/debug.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -25,14 +14,12 @@ import ( // Debug is true when the SWAGGER_DEBUG env var is not empty. // // It enables a more verbose logging of this package. -var Debug = os.Getenv("SWAGGER_DEBUG") != "" +var Debug = os.Getenv("SWAGGER_DEBUG") != "" //nolint:gochecknoglobals // public toggle for debug logging -var ( - // specLogger is a debug logger for this package - specLogger *log.Logger -) +// specLogger is a debug logger for this package. +var specLogger *log.Logger //nolint:gochecknoglobals // package-level debug logger -func init() { +func init() { //nolint:gochecknoinits // initializes debug logger at package load debugOptions() } @@ -40,7 +27,7 @@ func debugOptions() { specLogger = log.New(os.Stdout, "spec:", log.LstdFlags) } -func debugLog(msg string, args ...interface{}) { +func debugLog(msg string, args ...any) { // A private, trivial trace logger, based on go-openapi/spec/expander.go:debugLog() if Debug { _, file1, pos1, _ := runtime.Caller(1) diff --git a/vendor/github.com/go-openapi/spec/doc.go b/vendor/github.com/go-openapi/spec/doc.go new file mode 100644 index 00000000000..8b589781a6d --- /dev/null +++ b/vendor/github.com/go-openapi/spec/doc.go @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package spec exposes an object model for OpenAPIv2 specifications (swagger). +// +// The exposed data structures know how to serialize to and deserialize from JSON. +// +// # Security +// +// Resolving and expanding "$ref" pointers loads documents through a pluggable loader (see +// [ExpandOptions.PathLoader] and [ExpandOptions.PathLoaderWithOptions]). By default, that +// loader is NOT sandboxed, so a specification obtained from an untrusted source can abuse it: +// +// - A local "$ref" such as "file:///etc/passwd" or a relative "../../secret.json" is read +// straight off disk. A malicious specification can therefore read any file the process can +// access (arbitrary file read / path traversal, CWE-22). +// - A remote "$ref" such as "http://169.254.169.254/..." is fetched with no restriction. A +// malicious specification can therefore probe or reach internal addresses (SSRF, CWE-918). +// +// Do NOT expand or resolve an untrusted specification with the default options. To process +// untrusted specifications safely, inject a confined loader: +// +// - Recommended: use the restricted loaders from github.com/go-openapi/loads, for example +// loads.SpecRestricted(path, root) or loads.SetRestrictedLoaders(root). They confine local +// reads to root and route remote fetches through a client that rejects loopback, private and +// link-local addresses, and the confinement applies to every "$ref" resolved during +// expansion. +// - Or directly: set [ExpandOptions.PathLoaderWithOptions] to a loader built with +// github.com/go-openapi/swag/loading options such as loading.WithRoot (to confine local +// reads to a directory) and loading.WithHTTPClient (to restrict remote fetches). A "$ref" +// that resolves outside root is then rejected, including one reached through a "file://" +// URI or a "../" traversal. +// +// Expanding an untrusted specification also has a resource-exhaustion vector ("$ref" +// amplification); see [ExpandOptions.MaxExpansionNodes], which is bounded by default. +package spec diff --git a/vendor/github.com/go-openapi/spec/embed.go b/vendor/github.com/go-openapi/spec/embed.go new file mode 100644 index 00000000000..0d0b69996cc --- /dev/null +++ b/vendor/github.com/go-openapi/spec/embed.go @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package spec + +import ( + "embed" + "path" +) + +//go:embed schemas/*.json schemas/*/*.json +var assets embed.FS + +func jsonschemaDraft04JSONBytes() ([]byte, error) { + return assets.ReadFile(path.Join("schemas", "jsonschema-draft-04.json")) +} + +func v2SchemaJSONBytes() ([]byte, error) { + return assets.ReadFile(path.Join("schemas", "v2", "schema.json")) +} diff --git a/vendor/github.com/go-openapi/spec/errors.go b/vendor/github.com/go-openapi/spec/errors.go index 6992c7ba730..740b773c2c5 100644 --- a/vendor/github.com/go-openapi/spec/errors.go +++ b/vendor/github.com/go-openapi/spec/errors.go @@ -1,19 +1,32 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package spec import "errors" -// Error codes +// Error codes. var ( - // ErrUnknownTypeForReference indicates that a resolved reference was found in an unsupported container type + // ErrUnknownTypeForReference indicates that a resolved reference was found in an unsupported container type. ErrUnknownTypeForReference = errors.New("unknown type for the resolved reference") - // ErrResolveRefNeedsAPointer indicates that a $ref target must be a valid JSON pointer + // ErrResolveRefNeedsAPointer indicates that a $ref target must be a valid JSON pointer. ErrResolveRefNeedsAPointer = errors.New("resolve ref: target needs to be a pointer") // ErrDerefUnsupportedType indicates that a resolved reference was found in an unsupported container type. - // At the moment, $ref are supported only inside: schemas, parameters, responses, path items + // At the moment, $ref are supported only inside: schemas, parameters, responses, path items. ErrDerefUnsupportedType = errors.New("deref: unsupported type") - // ErrExpandUnsupportedType indicates that $ref expansion is attempted on some invalid type + // ErrExpandUnsupportedType indicates that $ref expansion is attempted on some invalid type. ErrExpandUnsupportedType = errors.New("expand: unsupported type. Input should be of type *Parameter or *Response") + + // ErrExpandTooManyNodes indicates that $ref expansion exceeded the maximum number of schema nodes + // allowed for a single expansion (see ExpandOptions.MaxExpansionNodes). + // + // This is a safeguard against maliciously crafted specifications that expand to an exponential + // number of nodes from a small input (a $ref amplification / "billion laughs" style attack). + ErrExpandTooManyNodes = errors.New("expand: too many schema nodes: expansion budget exceeded (see ExpandOptions.MaxExpansionNodes)") + + // ErrSpec is an error raised by the spec package. + ErrSpec = errors.New("spec error") ) diff --git a/vendor/github.com/go-openapi/spec/expander.go b/vendor/github.com/go-openapi/spec/expander.go index d4ea889d44d..00eb5b53a8c 100644 --- a/vendor/github.com/go-openapi/spec/expander.go +++ b/vendor/github.com/go-openapi/spec/expander.go @@ -1,24 +1,28 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec import ( "encoding/json" "fmt" + + "github.com/go-openapi/swag/loading" ) +const smallPrealloc = 10 + +// DefaultMaxExpansionNodes is the default upper bound on the number of schema nodes +// expanded during a single ExpandSpec / ExpandSchema* call. +// +// It guards against maliciously crafted specifications whose $ref graph expands to an +// exponential number of nodes from a few kilobytes of input. For reference, expanding the +// full Kubernetes API specification (the largest real-world spec we test against) visits +// roughly 47,000 nodes, so this default leaves ample headroom for legitimate documents. +// +// See ExpandOptions.MaxExpansionNodes to tune or disable this budget. +const DefaultMaxExpansionNodes = 500_000 + // ExpandOptions provides options for the spec expander. // // RelativeBase is the path to the root document. This can be a remote URL or a path to a local file. @@ -26,14 +30,59 @@ import ( // If left empty, the root document is assumed to be located in the current working directory: // all relative $ref's will be resolved from there. // -// PathLoader injects a document loading method. By default, this resolves to the function provided by the SpecLoader package variable. +// PathLoader injects a document loading method. By default, this resolves to the function provided by the PathLoader package variable. +// +// PathLoaderWithOptions is an alternative document loader that accepts [loading.Option] values, matching the +// signature used by the go-openapi/swag/loading and go-openapi/loads loaders. When set, it takes precedence over +// PathLoader. This lets a caller inject an options-aware (e.g. path-confined) loader without an adapter closure. // +// Security: the default loader is not sandboxed. When expanding an untrusted specification, inject a confined +// loader (for example one built with loading.WithRoot) — see the package "Security" section. type ExpandOptions struct { RelativeBase string // the path to the root document to expand. This is a file, not a directory SkipSchemas bool // do not expand schemas, just paths, parameters and responses ContinueOnError bool // continue expanding even after and error is found PathLoader func(string) (json.RawMessage, error) `json:"-"` // the document loading method that takes a path as input and yields a json document AbsoluteCircularRef bool // circular $ref remaining after expansion remain absolute URLs + + // PathLoaderWithOptions injects a document loading method that accepts loading options. + // + // It has the same role as PathLoader but matches the option-aware loader signature exposed by + // github.com/go-openapi/swag/loading (and github.com/go-openapi/loads), so such a loader can be + // injected directly, without wrapping it in an adapter closure. + // + // When set, PathLoaderWithOptions takes precedence over PathLoader. The provided loader is expected + // to carry its own loading options (for example a path confinement built with loading.WithRoot); + // the expander itself invokes it without adding options. + PathLoaderWithOptions func(string, ...loading.Option) (json.RawMessage, error) `json:"-"` + + // MaxExpansionNodes caps the number of schema nodes expanded during a single expansion call, + // as a safeguard against $ref amplification attacks (see ErrExpandTooManyNodes). + // + // The value is interpreted as follows: + // + // 0 (the zero value): use DefaultMaxExpansionNodes. Every caller is protected by default. + // <0: no limit (unbounded expansion). Use only with fully trusted specifications. + // >0: cap the expansion at this number of nodes. + // + // When the budget is exceeded, expansion stops and ErrExpandTooManyNodes is returned. + // Because this is a resource-exhaustion safeguard, the error is always returned, even when + // ContinueOnError is set. + MaxExpansionNodes int +} + +// maxExpansionNodes resolves the tri-state MaxExpansionNodes option into an effective budget. +// +// A returned value of 0 means "unbounded". +func (o *ExpandOptions) maxExpansionNodes() int { + switch { + case o.MaxExpansionNodes == 0: + return DefaultMaxExpansionNodes + case o.MaxExpansionNodes < 0: + return 0 // unbounded + default: + return o.MaxExpansionNodes + } } func optionsOrDefault(opts *ExpandOptions) *ExpandOptions { @@ -48,7 +97,11 @@ func optionsOrDefault(opts *ExpandOptions) *ExpandOptions { return &ExpandOptions{} } -// ExpandSpec expands the references in a swagger spec +// ExpandSpec expands the references in a swagger spec. +// +// Security: with default options the document loader is not sandboxed, so a "$ref" in an +// untrusted spec can read local files or reach internal addresses. See the package "Security" +// section before expanding untrusted input. func ExpandSpec(spec *Swagger, options *ExpandOptions) error { options = optionsOrDefault(options) resolver := defaultSchemaLoader(spec, options, nil, nil) @@ -57,8 +110,8 @@ func ExpandSpec(spec *Swagger, options *ExpandOptions) error { if !options.SkipSchemas { for key, definition := range spec.Definitions { - parentRefs := make([]string, 0, 10) - parentRefs = append(parentRefs, fmt.Sprintf("#/definitions/%s", key)) + parentRefs := make([]string, 0, smallPrealloc) + parentRefs = append(parentRefs, "#/definitions/"+key) def, err := expandSchema(definition, parentRefs, resolver, specBasePath) if resolver.shouldStopOnError(err) { @@ -102,16 +155,22 @@ func ExpandSpec(spec *Swagger, options *ExpandOptions) error { const rootBase = ".root" // baseForRoot loads in the cache the root document and produces a fake ".root" base path entry -// for further $ref resolution -// -// Setting the cache is optional and this parameter may safely be left to nil. -func baseForRoot(root interface{}, cache ResolutionCache) string { +// for further $ref resolution. +func baseForRoot(root any, cache ResolutionCache) string { + // cache the root document to resolve $ref's + normalizedBase := normalizeBase(rootBase) + if root == nil { - return "" + // ensure that we never leave a nil root: always cache the root base pseudo-document + cachedRoot, found := cache.Get(normalizedBase) + if found && cachedRoot != nil { + // the cache is already preloaded with a root + return normalizedBase + } + + root = map[string]any{} } - // cache the root document to resolve $ref's - normalizedBase := normalizeBase(rootBase) cache.Set(normalizedBase, root) return normalizedBase @@ -125,25 +184,50 @@ func baseForRoot(root interface{}, cache ResolutionCache) string { // (use ExpandSchemaWithBasePath to resolve external references). // // Setting the cache is optional and this parameter may safely be left to nil. -func ExpandSchema(schema *Schema, root interface{}, cache ResolutionCache) error { +// +// ExpandSchema uses the package default document loader, which is not sandboxed. To expand a +// schema whose $ref may derive from untrusted input, use [ExpandSchemaWithOptions] with a confined +// loader — see the package "Security" section. +func ExpandSchema(schema *Schema, root any, cache ResolutionCache) error { + return ExpandSchemaWithOptions(schema, root, cache, nil) +} + +// ExpandSchemaWithOptions expands the refs in the schema object with reference to the root object, +// honoring the provided expand options. It is the option-aware form of [ExpandSchema]. +// +// In particular, set opts.PathLoaderWithOptions (or opts.PathLoader) to inject a confined document +// loader when expanding a schema whose $ref may derive from an untrusted source (see the package +// "Security" section). opts.ContinueOnError, opts.AbsoluteCircularRef and opts.MaxExpansionNodes +// are honored as well. +// +// The base path is always derived from root (as with [ExpandSchema]), so opts.RelativeBase and +// opts.SkipSchemas are ignored. Passing nil opts is equivalent to [ExpandSchema]. +// +// Setting the cache is optional and this parameter may safely be left to nil. +func ExpandSchemaWithOptions(schema *Schema, root any, cache ResolutionCache, opts *ExpandOptions) error { cache = cacheOrDefault(cache) if root == nil { root = schema } - opts := &ExpandOptions{ - // when a root is specified, cache the root as an in-memory document for $ref retrieval - RelativeBase: baseForRoot(root, cache), - SkipSchemas: false, - ContinueOnError: false, + effective := ExpandOptions{} + if opts != nil { + effective = *opts // preserve caller options (loader, ContinueOnError, budget, ...) } + // when a root is specified, cache the root as an in-memory document for $ref retrieval + effective.RelativeBase = baseForRoot(root, cache) + effective.SkipSchemas = false - return ExpandSchemaWithBasePath(schema, cache, opts) + return ExpandSchemaWithBasePath(schema, cache, &effective) } // ExpandSchemaWithBasePath expands the refs in the schema object, base path configured through expand options. // // Setting the cache is optional and this parameter may safely be left to nil. +// +// Security: with default options the document loader is not sandboxed, so a "$ref" in an +// untrusted schema can read local files or reach internal addresses. See the package "Security" +// section before expanding untrusted input. func ExpandSchemaWithBasePath(schema *Schema, cache ResolutionCache, opts *ExpandOptions) error { if schema == nil { return nil @@ -155,7 +239,7 @@ func ExpandSchemaWithBasePath(schema *Schema, cache ResolutionCache, opts *Expan resolver := defaultSchemaLoader(nil, opts, cache, nil) - parentRefs := make([]string, 0, 10) + parentRefs := make([]string, 0, smallPrealloc) s, err := expandSchema(*schema, parentRefs, resolver, opts.RelativeBase) if err != nil { return err @@ -194,7 +278,12 @@ func expandItems(target Schema, parentRefs []string, resolver *schemaLoader, bas return &target, nil } +//nolint:gocognit,gocyclo,cyclop // complex but well-tested $ref expansion logic; refactoring deferred to dedicated PR func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) { + if err := resolver.context.countNode(); err != nil { + return &target, err + } + if target.Ref.String() == "" && target.Ref.IsRoot() { newRef := normalizeRef(&target.Ref, basePath) target.Ref = *newRef @@ -208,7 +297,19 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba } if target.Ref.String() != "" { - return expandSchemaRef(target, parentRefs, resolver, basePath) + if !resolver.options.SkipSchemas { + return expandSchemaRef(target, parentRefs, resolver, basePath) + } + + // when "expand" with SkipSchema, we just rebase the existing $ref without replacing + // the full schema. + rebasedRef, err := NewRef(normalizeURI(target.Ref.String(), basePath)) + if err != nil { + return nil, err + } + target.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID) + + return &target, nil } for k := range target.Definitions { @@ -369,7 +470,7 @@ func expandPathItem(pathItem *PathItem, resolver *schemaLoader, basePath string) return nil } - parentRefs := make([]string, 0, 10) + parentRefs := make([]string, 0, smallPrealloc) if err := resolver.deref(pathItem, parentRefs, basePath); resolver.shouldStopOnError(err) { return err } @@ -444,56 +545,76 @@ func expandOperation(op *Operation, resolver *schemaLoader, basePath string) err // (use ExpandResponse to resolve external references). // // Setting the cache is optional and this parameter may safely be left to nil. -func ExpandResponseWithRoot(response *Response, root interface{}, cache ResolutionCache) error { - cache = cacheOrDefault(cache) - opts := &ExpandOptions{ - RelativeBase: baseForRoot(root, cache), - } - resolver := defaultSchemaLoader(root, opts, cache, nil) - - return expandParameterOrResponse(response, resolver, opts.RelativeBase) +func ExpandResponseWithRoot(response *Response, root any, cache ResolutionCache) error { + return ExpandResponseWithOptions(response, root, cache, nil) } // ExpandResponse expands a response based on a basepath // -// All refs inside response will be resolved relative to basePath +// All refs inside response will be resolved relative to basePath. func ExpandResponse(response *Response, basePath string) error { - opts := optionsOrDefault(&ExpandOptions{ - RelativeBase: basePath, - }) - resolver := defaultSchemaLoader(nil, opts, nil, nil) + return ExpandResponseWithOptions(response, nil, nil, &ExpandOptions{RelativeBase: basePath}) +} - return expandParameterOrResponse(response, resolver, opts.RelativeBase) +// ExpandResponseWithOptions expands a response, honoring the provided expand options. +// +// It is the option-aware form of [ExpandResponse] and [ExpandResponseWithRoot]. When root is +// non-nil, refs resolve against the in-memory root document; otherwise they resolve relative to +// opts.RelativeBase. +// +// Set opts.PathLoaderWithOptions (or opts.PathLoader) to inject a confined document loader when +// the response's $ref may derive from an untrusted source — see the package "Security" section. +// +// Setting the cache is optional and this parameter may safely be left to nil. +func ExpandResponseWithOptions(response *Response, root any, cache ResolutionCache, opts *ExpandOptions) error { + return expandRefableWithOptions(response, root, cache, opts) } // ExpandParameterWithRoot expands a parameter based on a root document, not a fetchable document. // // Notice that it is impossible to reference a json schema in a different document other than root // (use ExpandParameter to resolve external references). -func ExpandParameterWithRoot(parameter *Parameter, root interface{}, cache ResolutionCache) error { - cache = cacheOrDefault(cache) - - opts := &ExpandOptions{ - RelativeBase: baseForRoot(root, cache), - } - resolver := defaultSchemaLoader(root, opts, cache, nil) - - return expandParameterOrResponse(parameter, resolver, opts.RelativeBase) +func ExpandParameterWithRoot(parameter *Parameter, root any, cache ResolutionCache) error { + return ExpandParameterWithOptions(parameter, root, cache, nil) } // ExpandParameter expands a parameter based on a basepath. // This is the exported version of expandParameter -// all refs inside parameter will be resolved relative to basePath +// all refs inside parameter will be resolved relative to basePath. func ExpandParameter(parameter *Parameter, basePath string) error { - opts := optionsOrDefault(&ExpandOptions{ - RelativeBase: basePath, - }) - resolver := defaultSchemaLoader(nil, opts, nil, nil) + return ExpandParameterWithOptions(parameter, nil, nil, &ExpandOptions{RelativeBase: basePath}) +} + +// ExpandParameterWithOptions expands a parameter, honoring the provided expand options. +// +// It is the option-aware form of [ExpandParameter] and [ExpandParameterWithRoot]. When root is +// non-nil, refs resolve against the in-memory root document; otherwise they resolve relative to +// opts.RelativeBase. +// +// Set opts.PathLoaderWithOptions (or opts.PathLoader) to inject a confined document loader when +// the parameter's $ref may derive from an untrusted source — see the package "Security" section. +// +// Setting the cache is optional and this parameter may safely be left to nil. +func ExpandParameterWithOptions(parameter *Parameter, root any, cache ResolutionCache, opts *ExpandOptions) error { + return expandRefableWithOptions(parameter, root, cache, opts) +} + +// expandRefableWithOptions is the shared implementation for the option-aware parameter/response +// expanders. When root is non-nil, refs resolve against the in-memory root (base derived from +// root); otherwise they resolve relative to opts.RelativeBase. opts carries the loader and other +// expand options. +func expandRefableWithOptions(input any, root any, cache ResolutionCache, opts *ExpandOptions) error { + cache = cacheOrDefault(cache) + effective := optionsOrDefault(opts) // clones and normalizes RelativeBase; preserves the loader + if root != nil { + effective.RelativeBase = baseForRoot(root, cache) + } + resolver := defaultSchemaLoader(root, effective, cache, nil) - return expandParameterOrResponse(parameter, resolver, opts.RelativeBase) + return expandParameterOrResponse(input, resolver, effective.RelativeBase) } -func getRefAndSchema(input interface{}) (*Ref, *Schema, error) { +func getRefAndSchema(input any) (*Ref, *Schema, error) { var ( ref *Ref sch *Schema @@ -519,22 +640,29 @@ func getRefAndSchema(input interface{}) (*Ref, *Schema, error) { return ref, sch, nil } -func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePath string) error { - ref, _, err := getRefAndSchema(input) +func expandParameterOrResponse(input any, resolver *schemaLoader, basePath string) error { + ref, sch, err := getRefAndSchema(input) if err != nil { return err } - if ref == nil { + if ref == nil && sch == nil { // nothing to do return nil } - parentRefs := make([]string, 0, 10) - if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) { - return err + parentRefs := make([]string, 0, smallPrealloc) + if ref != nil { + // dereference this $ref + if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) { + return err + } + + ref, sch, _ = getRefAndSchema(input) + if ref == nil { + ref = &Ref{} // empty ref + } } - ref, sch, _ := getRefAndSchema(input) if ref.String() != "" { transitiveResolver := resolver.transitiveResolver(basePath, *ref) basePath = resolver.updateBasePath(transitiveResolver, basePath) @@ -546,47 +674,39 @@ func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePa if ref != nil { *ref = Ref{} } + return nil } - if sch.Ref.String() != "" { + if sch.Ref.String() != "" { //nolint:nestif // intertwined ref rebasing and circularity check rebasedRef, ern := NewRef(normalizeURI(sch.Ref.String(), basePath)) if ern != nil { return ern } - switch { - case resolver.isCircular(&rebasedRef, basePath, parentRefs...): + if resolver.isCircular(&rebasedRef, basePath, parentRefs...) { // this is a circular $ref: stop expansion if !resolver.options.AbsoluteCircularRef { sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID) } else { sch.Ref = rebasedRef } - case !resolver.options.SkipSchemas: - // schema expanded to a $ref in another root - sch.Ref = rebasedRef - debugLog("rebased to: %s", sch.Ref.String()) - default: - // skip schema expansion but rebase $ref to schema - sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID) } } + // $ref expansion or rebasing is performed by expandSchema below if ref != nil { *ref = Ref{} } // expand schema - if !resolver.options.SkipSchemas { - s, err := expandSchema(*sch, parentRefs, resolver, basePath) - if resolver.shouldStopOnError(err) { - return err - } - if s == nil { - // guard for when continuing on error - return nil - } + // yes, we do it even if options.SkipSchema is true: we have to go down that rabbit hole and rebase nested $ref) + s, err := expandSchema(*sch, parentRefs, resolver, basePath) + if resolver.shouldStopOnError(err) { + return err + } + + if s != nil { // guard for when continuing on error *sch = *s } diff --git a/vendor/github.com/go-openapi/spec/external_docs.go b/vendor/github.com/go-openapi/spec/external_docs.go index 88add91b2b8..17b8efbf100 100644 --- a/vendor/github.com/go-openapi/spec/external_docs.go +++ b/vendor/github.com/go-openapi/spec/external_docs.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec diff --git a/vendor/github.com/go-openapi/spec/header.go b/vendor/github.com/go-openapi/spec/header.go index 9dfd17b185f..f656e0789a1 100644 --- a/vendor/github.com/go-openapi/spec/header.go +++ b/vendor/github.com/go-openapi/spec/header.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -19,14 +8,14 @@ import ( "strings" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) const ( jsonArray = "array" ) -// HeaderProps describes a response header +// HeaderProps describes a response header. type HeaderProps struct { Description string `json:"description,omitempty"` } @@ -41,25 +30,25 @@ type Header struct { HeaderProps } -// ResponseHeader creates a new header instance for use in a response +// ResponseHeader creates a new header instance for use in a response. func ResponseHeader() *Header { return new(Header) } -// WithDescription sets the description on this response, allows for chaining +// WithDescription sets the description on this response, allows for chaining. func (h *Header) WithDescription(description string) *Header { h.Description = description return h } -// Typed a fluent builder method for the type of parameter +// Typed a fluent builder method for the type of parameter. func (h *Header) Typed(tpe, format string) *Header { h.Type = tpe h.Format = format return h } -// CollectionOf a fluent builder method for an array item +// CollectionOf a fluent builder method for an array item. func (h *Header) CollectionOf(items *Items, format string) *Header { h.Type = jsonArray h.Items = items @@ -67,87 +56,87 @@ func (h *Header) CollectionOf(items *Items, format string) *Header { return h } -// WithDefault sets the default value on this item -func (h *Header) WithDefault(defaultValue interface{}) *Header { +// WithDefault sets the default value on this item. +func (h *Header) WithDefault(defaultValue any) *Header { h.Default = defaultValue return h } -// WithMaxLength sets a max length value -func (h *Header) WithMaxLength(max int64) *Header { - h.MaxLength = &max +// WithMaxLength sets a max length value. +func (h *Header) WithMaxLength(maximum int64) *Header { + h.MaxLength = &maximum return h } -// WithMinLength sets a min length value -func (h *Header) WithMinLength(min int64) *Header { - h.MinLength = &min +// WithMinLength sets a min length value. +func (h *Header) WithMinLength(minimum int64) *Header { + h.MinLength = &minimum return h } -// WithPattern sets a pattern value +// WithPattern sets a pattern value. func (h *Header) WithPattern(pattern string) *Header { h.Pattern = pattern return h } -// WithMultipleOf sets a multiple of value +// WithMultipleOf sets a multiple of value. func (h *Header) WithMultipleOf(number float64) *Header { h.MultipleOf = &number return h } -// WithMaximum sets a maximum number value -func (h *Header) WithMaximum(max float64, exclusive bool) *Header { - h.Maximum = &max +// WithMaximum sets a maximum number value. +func (h *Header) WithMaximum(maximum float64, exclusive bool) *Header { + h.Maximum = &maximum h.ExclusiveMaximum = exclusive return h } -// WithMinimum sets a minimum number value -func (h *Header) WithMinimum(min float64, exclusive bool) *Header { - h.Minimum = &min +// WithMinimum sets a minimum number value. +func (h *Header) WithMinimum(minimum float64, exclusive bool) *Header { + h.Minimum = &minimum h.ExclusiveMinimum = exclusive return h } -// WithEnum sets a the enum values (replace) -func (h *Header) WithEnum(values ...interface{}) *Header { - h.Enum = append([]interface{}{}, values...) +// WithEnum sets a the enum values (replace). +func (h *Header) WithEnum(values ...any) *Header { + h.Enum = append([]any{}, values...) return h } -// WithMaxItems sets the max items +// WithMaxItems sets the max items. func (h *Header) WithMaxItems(size int64) *Header { h.MaxItems = &size return h } -// WithMinItems sets the min items +// WithMinItems sets the min items. func (h *Header) WithMinItems(size int64) *Header { h.MinItems = &size return h } -// UniqueValues dictates that this array can only have unique items +// UniqueValues dictates that this array can only have unique items. func (h *Header) UniqueValues() *Header { h.UniqueItems = true return h } -// AllowDuplicates this array can have duplicates +// AllowDuplicates this array can have duplicates. func (h *Header) AllowDuplicates() *Header { h.UniqueItems = false return h } -// WithValidations is a fluent method to set header validations +// WithValidations is a fluent method to set header validations. func (h *Header) WithValidations(val CommonValidations) *Header { h.SetValidations(SchemaValidations{CommonValidations: val}) return h } -// MarshalJSON marshal this to JSON +// MarshalJSON marshal this to JSON. func (h Header) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(h.CommonValidations) if err != nil { @@ -161,10 +150,14 @@ func (h Header) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2, b3), nil + b4, err := json.Marshal(h.VendorExtensible) + if err != nil { + return nil, err + } + return jsonutils.ConcatJSON(b1, b2, b3, b4), nil } -// UnmarshalJSON unmarshals this header from JSON +// UnmarshalJSON unmarshals this header from JSON. func (h *Header) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &h.CommonValidations); err != nil { return err @@ -178,8 +171,8 @@ func (h *Header) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &h.HeaderProps) } -// JSONLookup look up a value by the json property name -func (h Header) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (h Header) JSONLookup(token string) (any, error) { if ex, ok := h.Extensions[token]; ok { return &ex, nil } diff --git a/vendor/github.com/go-openapi/spec/info.go b/vendor/github.com/go-openapi/spec/info.go index c458b49b216..0ccfdcccd9e 100644 --- a/vendor/github.com/go-openapi/spec/info.go +++ b/vendor/github.com/go-openapi/spec/info.go @@ -1,37 +1,27 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec import ( "encoding/json" + "strconv" "strings" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) -// Extensions vendor specific extensions -type Extensions map[string]interface{} +// Extensions vendor specific extensions. +type Extensions map[string]any -// Add adds a value to these extensions -func (e Extensions) Add(key string, value interface{}) { +// Add adds a value to these extensions. +func (e Extensions) Add(key string, value any) { realKey := strings.ToLower(key) e[realKey] = value } -// GetString gets a string value from the extensions +// GetString gets a string value from the extensions. func (e Extensions) GetString(key string) (string, bool) { if v, ok := e[strings.ToLower(key)]; ok { str, ok := v.(string) @@ -40,7 +30,25 @@ func (e Extensions) GetString(key string) (string, bool) { return "", false } -// GetBool gets a string value from the extensions +// GetInt gets a int value from the extensions. +func (e Extensions) GetInt(key string) (int, bool) { + realKey := strings.ToLower(key) + + if v, ok := e.GetString(realKey); ok { + if r, err := strconv.Atoi(v); err == nil { + return r, true + } + } + + if v, ok := e[realKey]; ok { + if r, rOk := v.(float64); rOk { + return int(r), true + } + } + return -1, false +} + +// GetBool gets a string value from the extensions. func (e Extensions) GetBool(key string) (bool, bool) { if v, ok := e[strings.ToLower(key)]; ok { str, ok := v.(bool) @@ -49,10 +57,10 @@ func (e Extensions) GetBool(key string) (bool, bool) { return false, false } -// GetStringSlice gets a string value from the extensions +// GetStringSlice gets a string value from the extensions. func (e Extensions) GetStringSlice(key string) ([]string, bool) { if v, ok := e[strings.ToLower(key)]; ok { - arr, isSlice := v.([]interface{}) + arr, isSlice := v.([]any) if !isSlice { return nil, false } @@ -74,20 +82,20 @@ type VendorExtensible struct { Extensions Extensions } -// AddExtension adds an extension to this extensible object -func (v *VendorExtensible) AddExtension(key string, value interface{}) { +// AddExtension adds an extension to this extensible object. +func (v *VendorExtensible) AddExtension(key string, value any) { if value == nil { return } if v.Extensions == nil { - v.Extensions = make(map[string]interface{}) + v.Extensions = make(map[string]any) } v.Extensions.Add(key, value) } -// MarshalJSON marshals the extensions to json +// MarshalJSON marshals the extensions to json. func (v VendorExtensible) MarshalJSON() ([]byte, error) { - toser := make(map[string]interface{}) + toser := make(map[string]any) for k, v := range v.Extensions { lk := strings.ToLower(k) if strings.HasPrefix(lk, "x-") { @@ -97,9 +105,9 @@ func (v VendorExtensible) MarshalJSON() ([]byte, error) { return json.Marshal(toser) } -// UnmarshalJSON for this extensible object +// UnmarshalJSON for this extensible object. func (v *VendorExtensible) UnmarshalJSON(data []byte) error { - var d map[string]interface{} + var d map[string]any if err := json.Unmarshal(data, &d); err != nil { return err } @@ -107,7 +115,7 @@ func (v *VendorExtensible) UnmarshalJSON(data []byte) error { lk := strings.ToLower(k) if strings.HasPrefix(lk, "x-") { if v.Extensions == nil { - v.Extensions = map[string]interface{}{} + v.Extensions = map[string]any{} } v.Extensions[k] = vv } @@ -115,7 +123,7 @@ func (v *VendorExtensible) UnmarshalJSON(data []byte) error { return nil } -// InfoProps the properties for an info definition +// InfoProps the properties for an info definition. type InfoProps struct { Description string `json:"description,omitempty"` Title string `json:"title,omitempty"` @@ -134,8 +142,8 @@ type Info struct { InfoProps } -// JSONLookup look up a value by the json property name -func (i Info) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (i Info) JSONLookup(token string) (any, error) { if ex, ok := i.Extensions[token]; ok { return &ex, nil } @@ -143,7 +151,7 @@ func (i Info) JSONLookup(token string) (interface{}, error) { return r, err } -// MarshalJSON marshal this to JSON +// MarshalJSON marshal this to JSON. func (i Info) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(i.InfoProps) if err != nil { @@ -153,10 +161,10 @@ func (i Info) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2), nil + return jsonutils.ConcatJSON(b1, b2), nil } -// UnmarshalJSON marshal this from JSON +// UnmarshalJSON marshal this from JSON. func (i *Info) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &i.InfoProps); err != nil { return err diff --git a/vendor/github.com/go-openapi/spec/items.go b/vendor/github.com/go-openapi/spec/items.go index e2afb2133b9..daf5a4fd421 100644 --- a/vendor/github.com/go-openapi/spec/items.go +++ b/vendor/github.com/go-openapi/spec/items.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -19,25 +8,25 @@ import ( "strings" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) const ( jsonRef = "$ref" ) -// SimpleSchema describe swagger simple schemas for parameters and headers +// SimpleSchema describe swagger simple schemas for parameters and headers. type SimpleSchema struct { - Type string `json:"type,omitempty"` - Nullable bool `json:"nullable,omitempty"` - Format string `json:"format,omitempty"` - Items *Items `json:"items,omitempty"` - CollectionFormat string `json:"collectionFormat,omitempty"` - Default interface{} `json:"default,omitempty"` - Example interface{} `json:"example,omitempty"` + Type string `json:"type,omitempty"` + Nullable bool `json:"nullable,omitempty"` + Format string `json:"format,omitempty"` + Items *Items `json:"items,omitempty"` + CollectionFormat string `json:"collectionFormat,omitempty"` + Default any `json:"default,omitempty"` + Example any `json:"example,omitempty"` } -// TypeName return the type (or format) of a simple schema +// TypeName return the type (or format) of a simple schema. func (s *SimpleSchema) TypeName() string { if s.Format != "" { return s.Format @@ -45,7 +34,7 @@ func (s *SimpleSchema) TypeName() string { return s.Type } -// ItemsTypeName yields the type of items in a simple schema array +// ItemsTypeName yields the type of items in a simple schema array. func (s *SimpleSchema) ItemsTypeName() string { if s.Items == nil { return "" @@ -64,12 +53,12 @@ type Items struct { VendorExtensible } -// NewItems creates a new instance of items +// NewItems creates a new instance of items. func NewItems() *Items { return &Items{} } -// Typed a fluent builder method for the type of item +// Typed a fluent builder method for the type of item. func (i *Items) Typed(tpe, format string) *Items { i.Type = tpe i.Format = format @@ -82,7 +71,7 @@ func (i *Items) AsNullable() *Items { return i } -// CollectionOf a fluent builder method for an array item +// CollectionOf a fluent builder method for an array item. func (i *Items) CollectionOf(items *Items, format string) *Items { i.Type = jsonArray i.Items = items @@ -90,87 +79,87 @@ func (i *Items) CollectionOf(items *Items, format string) *Items { return i } -// WithDefault sets the default value on this item -func (i *Items) WithDefault(defaultValue interface{}) *Items { +// WithDefault sets the default value on this item. +func (i *Items) WithDefault(defaultValue any) *Items { i.Default = defaultValue return i } -// WithMaxLength sets a max length value -func (i *Items) WithMaxLength(max int64) *Items { - i.MaxLength = &max +// WithMaxLength sets a max length value. +func (i *Items) WithMaxLength(maximum int64) *Items { + i.MaxLength = &maximum return i } -// WithMinLength sets a min length value -func (i *Items) WithMinLength(min int64) *Items { - i.MinLength = &min +// WithMinLength sets a min length value. +func (i *Items) WithMinLength(minimum int64) *Items { + i.MinLength = &minimum return i } -// WithPattern sets a pattern value +// WithPattern sets a pattern value. func (i *Items) WithPattern(pattern string) *Items { i.Pattern = pattern return i } -// WithMultipleOf sets a multiple of value +// WithMultipleOf sets a multiple of value. func (i *Items) WithMultipleOf(number float64) *Items { i.MultipleOf = &number return i } -// WithMaximum sets a maximum number value -func (i *Items) WithMaximum(max float64, exclusive bool) *Items { - i.Maximum = &max +// WithMaximum sets a maximum number value. +func (i *Items) WithMaximum(maximum float64, exclusive bool) *Items { + i.Maximum = &maximum i.ExclusiveMaximum = exclusive return i } -// WithMinimum sets a minimum number value -func (i *Items) WithMinimum(min float64, exclusive bool) *Items { - i.Minimum = &min +// WithMinimum sets a minimum number value. +func (i *Items) WithMinimum(minimum float64, exclusive bool) *Items { + i.Minimum = &minimum i.ExclusiveMinimum = exclusive return i } -// WithEnum sets a the enum values (replace) -func (i *Items) WithEnum(values ...interface{}) *Items { - i.Enum = append([]interface{}{}, values...) +// WithEnum sets a the enum values (replace). +func (i *Items) WithEnum(values ...any) *Items { + i.Enum = append([]any{}, values...) return i } -// WithMaxItems sets the max items +// WithMaxItems sets the max items. func (i *Items) WithMaxItems(size int64) *Items { i.MaxItems = &size return i } -// WithMinItems sets the min items +// WithMinItems sets the min items. func (i *Items) WithMinItems(size int64) *Items { i.MinItems = &size return i } -// UniqueValues dictates that this array can only have unique items +// UniqueValues dictates that this array can only have unique items. func (i *Items) UniqueValues() *Items { i.UniqueItems = true return i } -// AllowDuplicates this array can have duplicates +// AllowDuplicates this array can have duplicates. func (i *Items) AllowDuplicates() *Items { i.UniqueItems = false return i } -// WithValidations is a fluent method to set Items validations +// WithValidations is a fluent method to set Items validations. func (i *Items) WithValidations(val CommonValidations) *Items { i.SetValidations(SchemaValidations{CommonValidations: val}) return i } -// UnmarshalJSON hydrates this items instance with the data from JSON +// UnmarshalJSON hydrates this items instance with the data from JSON. func (i *Items) UnmarshalJSON(data []byte) error { var validations CommonValidations if err := json.Unmarshal(data, &validations); err != nil { @@ -195,7 +184,7 @@ func (i *Items) UnmarshalJSON(data []byte) error { return nil } -// MarshalJSON converts this items object to JSON +// MarshalJSON converts this items object to JSON. func (i Items) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(i.CommonValidations) if err != nil { @@ -213,11 +202,11 @@ func (i Items) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b4, b3, b1, b2), nil + return jsonutils.ConcatJSON(b4, b3, b1, b2), nil } -// JSONLookup look up a value by the json property name -func (i Items) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (i Items) JSONLookup(token string) (any, error) { if token == jsonRef { return &i.Ref, nil } diff --git a/vendor/github.com/go-openapi/spec/license.go b/vendor/github.com/go-openapi/spec/license.go index b42f80368ec..8209f218b56 100644 --- a/vendor/github.com/go-openapi/spec/license.go +++ b/vendor/github.com/go-openapi/spec/license.go @@ -1,23 +1,12 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec import ( "encoding/json" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) // License information for the exposed API. @@ -28,13 +17,13 @@ type License struct { VendorExtensible } -// LicenseProps holds the properties of a License object +// LicenseProps holds the properties of a License object. type LicenseProps struct { Name string `json:"name,omitempty"` URL string `json:"url,omitempty"` } -// UnmarshalJSON hydrates License from json +// UnmarshalJSON hydrates License from json. func (l *License) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &l.LicenseProps); err != nil { return err @@ -42,7 +31,7 @@ func (l *License) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &l.VendorExtensible) } -// MarshalJSON produces License as json +// MarshalJSON produces License as json. func (l License) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(l.LicenseProps) if err != nil { @@ -52,5 +41,5 @@ func (l License) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2), nil + return jsonutils.ConcatJSON(b1, b2), nil } diff --git a/vendor/github.com/go-openapi/spec/normalizer.go b/vendor/github.com/go-openapi/spec/normalizer.go index d6c48397128..68252dc30b8 100644 --- a/vendor/github.com/go-openapi/spec/normalizer.go +++ b/vendor/github.com/go-openapi/spec/normalizer.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -40,7 +29,7 @@ const fileScheme = "file" // // The base path argument is assumed to be canonicalized (e.g. using normalizeBase()). func normalizeURI(refPath, base string) string { - refURL, err := url.Parse(refPath) + refURL, err := parseURL(refPath) if err != nil { specLogger.Printf("warning: invalid URI in $ref %q: %v", refPath, err) refURL, refPath = repairURI(refPath) @@ -58,7 +47,7 @@ func normalizeURI(refPath, base string) string { return refURL.String() } - baseURL, _ := url.Parse(base) + baseURL, _ := parseURL(base) if path.IsAbs(refURL.Path) { baseURL.Path = refURL.Path } else if refURL.Path != "" { @@ -84,7 +73,6 @@ func normalizeURI(refPath, base string) string { // There is a special case for schemas that are anchored with an "id": // in that case, the rebasing is performed // against the id only if this is an anchor for the initial root document. // All other intermediate "id"'s found along the way are ignored for the purpose of rebasing. -// func denormalizeRef(ref *Ref, originalRelativeBase, id string) Ref { debugLog("denormalizeRef called:\n$ref: %q\noriginal: %s\nroot ID:%s", ref.String(), originalRelativeBase, id) @@ -94,16 +82,16 @@ func denormalizeRef(ref *Ref, originalRelativeBase, id string) Ref { } if id != "" { - idBaseURL, err := url.Parse(id) + idBaseURL, err := parseURL(id) if err == nil { // if the schema id is not usable as a URI, ignore it - if ref, ok := rebase(ref, idBaseURL, true); ok { // rebase, but keep references to root unchaged (do not want $ref: "") + if ref, ok := rebase(ref, idBaseURL, true); ok { // rebase, but keep references to root unchanged (do not want $ref: "") // $ref relative to the ID of the schema in the root document return ref } } } - originalRelativeBaseURL, _ := url.Parse(originalRelativeBase) + originalRelativeBaseURL, _ := parseURL(originalRelativeBase) r, _ := rebase(ref, originalRelativeBaseURL, false) @@ -130,8 +118,8 @@ func rebase(ref *Ref, v *url.URL, notEqual bool) (Ref, bool) { newBase.Fragment = u.Fragment - if strings.HasPrefix(u.Path, docPath) { - newBase.Path = strings.TrimPrefix(u.Path, docPath) + if after, ok := strings.CutPrefix(u.Path, docPath); ok { + newBase.Path = after } else { newBase.Path = strings.TrimPrefix(u.Path, v.Path) } @@ -150,7 +138,7 @@ func rebase(ref *Ref, v *url.URL, notEqual bool) (Ref, bool) { return MustCreateRef(newBase.String()), true } -// normalizeRef canonicalize a Ref, using a canonical relativeBase as its absolute anchor +// normalizeRef canonicalize a Ref, using a canonical relativeBase as its absolute anchor. func normalizeRef(ref *Ref, relativeBase string) *Ref { r := MustCreateRef(normalizeURI(ref.String(), relativeBase)) return &r @@ -168,7 +156,7 @@ func normalizeRef(ref *Ref, relativeBase string) *Ref { // // See also: https://en.wikipedia.org/wiki/File_URI_scheme func normalizeBase(in string) string { - u, err := url.Parse(in) + u, err := parseURL(in) if err != nil { specLogger.Printf("warning: invalid URI in RelativeBase %q: %v", in, err) u, in = repairURI(in) diff --git a/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go b/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go index c8a06453474..0d55632349f 100644 --- a/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go +++ b/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go @@ -1,18 +1,7 @@ -// +build !windows +//go:build !windows -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -34,10 +23,10 @@ func absPath(in string) string { } func repairURI(in string) (*url.URL, string) { - u, _ := url.Parse("") + u, _ := parseURL("") debugLog("repaired URI: original: %q, repaired: %q", in, "") return u, "" } -func fixWindowsURI(u *url.URL, in string) { +func fixWindowsURI(_ *url.URL, _ string) { } diff --git a/vendor/github.com/go-openapi/spec/normalizer_windows.go b/vendor/github.com/go-openapi/spec/normalizer_windows.go index fe2d1ecd43e..61515c9a163 100644 --- a/vendor/github.com/go-openapi/spec/normalizer_windows.go +++ b/vendor/github.com/go-openapi/spec/normalizer_windows.go @@ -1,18 +1,7 @@ // -build windows -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -60,13 +49,13 @@ func repairURI(in string) (*url.URL, string) { const prefix = fileScheme + "://" if !strings.HasPrefix(in, prefix) { // giving up: resolve to empty path - u, _ := url.Parse("") + u, _ := parseURL("") return u, "" } // attempt the repair, stripping the scheme should be sufficient - u, _ := url.Parse(strings.TrimPrefix(in, prefix)) + u, _ := parseURL(strings.TrimPrefix(in, prefix)) debugLog("repaired URI: original: %q, repaired: %q", in, u.String()) return u, u.String() diff --git a/vendor/github.com/go-openapi/spec/operation.go b/vendor/github.com/go-openapi/spec/operation.go index 995ce6acb17..cd70d2547ce 100644 --- a/vendor/github.com/go-openapi/spec/operation.go +++ b/vendor/github.com/go-openapi/spec/operation.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -21,19 +10,19 @@ import ( "sort" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) -func init() { - gob.Register(map[string]interface{}{}) - gob.Register([]interface{}{}) +func init() { //nolint:gochecknoinits // registers gob types for Operation serialization + gob.Register(map[string]any{}) + gob.Register([]any{}) } // OperationProps describes an operation // // NOTES: // - schemes, when present must be from [http, https, ws, wss]: see validate -// - Security is handled as a special case: see MarshalJSON function +// - Security is handled as a special case: see MarshalJSON function. type OperationProps struct { Description string `json:"description,omitempty"` Consumes []string `json:"consumes,omitempty"` @@ -58,19 +47,22 @@ func (op OperationProps) MarshalJSON() ([]byte, error) { type Alias OperationProps if op.Security == nil { return json.Marshal(&struct { - Security []map[string][]string `json:"security,omitempty"` *Alias + + Security []map[string][]string `json:"security,omitempty"` }{ - Security: op.Security, Alias: (*Alias)(&op), + Security: op.Security, }) } + return json.Marshal(&struct { - Security []map[string][]string `json:"security"` *Alias + + Security []map[string][]string `json:"security"` }{ - Security: op.Security, Alias: (*Alias)(&op), + Security: op.Security, }) } @@ -82,7 +74,15 @@ type Operation struct { OperationProps } -// SuccessResponse gets a success response model +// NewOperation creates a new operation instance. +// It expects an ID as parameter but not passing an ID is also valid. +func NewOperation(id string) *Operation { + op := new(Operation) + op.ID = id + return op +} + +// SuccessResponse gets a success response model. func (o *Operation) SuccessResponse() (*Response, int, bool) { if o.Responses == nil { return nil, 0, false @@ -103,8 +103,8 @@ func (o *Operation) SuccessResponse() (*Response, int, bool) { return o.Responses.Default, 0, false } -// JSONLookup look up a value by the json property name -func (o Operation) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (o Operation) JSONLookup(token string) (any, error) { if ex, ok := o.Extensions[token]; ok { return &ex, nil } @@ -112,7 +112,7 @@ func (o Operation) JSONLookup(token string) (interface{}, error) { return r, err } -// UnmarshalJSON hydrates this items instance with the data from JSON +// UnmarshalJSON hydrates this items instance with the data from JSON. func (o *Operation) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &o.OperationProps); err != nil { return err @@ -120,7 +120,7 @@ func (o *Operation) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &o.VendorExtensible) } -// MarshalJSON converts this items object to JSON +// MarshalJSON converts this items object to JSON. func (o Operation) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(o.OperationProps) if err != nil { @@ -130,31 +130,23 @@ func (o Operation) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - concated := swag.ConcatJSON(b1, b2) + concated := jsonutils.ConcatJSON(b1, b2) return concated, nil } -// NewOperation creates a new operation instance. -// It expects an ID as parameter but not passing an ID is also valid. -func NewOperation(id string) *Operation { - op := new(Operation) - op.ID = id - return op -} - // WithID sets the ID property on this operation, allows for chaining. func (o *Operation) WithID(id string) *Operation { o.ID = id return o } -// WithDescription sets the description on this operation, allows for chaining +// WithDescription sets the description on this operation, allows for chaining. func (o *Operation) WithDescription(description string) *Operation { o.Description = description return o } -// WithSummary sets the summary on this operation, allows for chaining +// WithSummary sets the summary on this operation, allows for chaining. func (o *Operation) WithSummary(summary string) *Operation { o.Summary = summary return o @@ -178,38 +170,38 @@ func (o *Operation) WithExternalDocs(description, url string) *Operation { return o } -// Deprecate marks the operation as deprecated +// Deprecate marks the operation as deprecated. func (o *Operation) Deprecate() *Operation { o.Deprecated = true return o } -// Undeprecate marks the operation as not deprected +// Undeprecate marks the operation as not deprecated. func (o *Operation) Undeprecate() *Operation { o.Deprecated = false return o } -// WithConsumes adds media types for incoming body values +// WithConsumes adds media types for incoming body values. func (o *Operation) WithConsumes(mediaTypes ...string) *Operation { o.Consumes = append(o.Consumes, mediaTypes...) return o } -// WithProduces adds media types for outgoing body values +// WithProduces adds media types for outgoing body values. func (o *Operation) WithProduces(mediaTypes ...string) *Operation { o.Produces = append(o.Produces, mediaTypes...) return o } -// WithTags adds tags for this operation +// WithTags adds tags for this operation. func (o *Operation) WithTags(tags ...string) *Operation { o.Tags = append(o.Tags, tags...) return o } // AddParam adds a parameter to this operation, when a parameter for that location -// and with that name already exists it will be replaced +// and with that name already exists it will be replaced. func (o *Operation) AddParam(param *Parameter) *Operation { if param == nil { return o @@ -217,9 +209,12 @@ func (o *Operation) AddParam(param *Parameter) *Operation { for i, p := range o.Parameters { if p.Name == param.Name && p.In == param.In { - params := append(o.Parameters[:i], *param) + params := make([]Parameter, 0, len(o.Parameters)+1) + params = append(params, o.Parameters[:i]...) + params = append(params, *param) params = append(params, o.Parameters[i+1:]...) o.Parameters = params + return o } } @@ -228,7 +223,7 @@ func (o *Operation) AddParam(param *Parameter) *Operation { return o } -// RemoveParam removes a parameter from the operation +// RemoveParam removes a parameter from the operation. func (o *Operation) RemoveParam(name, in string) *Operation { for i, p := range o.Parameters { if p.Name == name && p.In == in { @@ -246,14 +241,14 @@ func (o *Operation) SecuredWith(name string, scopes ...string) *Operation { } // WithDefaultResponse adds a default response to the operation. -// Passing a nil value will remove the response +// Passing a nil value will remove the response. func (o *Operation) WithDefaultResponse(response *Response) *Operation { return o.RespondsWith(0, response) } // RespondsWith adds a status code response to the operation. // When the code is 0 the value of the response will be used as default response value. -// When the value of the response is nil it will be removed from the operation +// When the value of the response is nil it will be removed from the operation. func (o *Operation) RespondsWith(code int, response *Response) *Operation { if o.Responses == nil { o.Responses = new(Responses) @@ -284,7 +279,7 @@ type gobAlias struct { SecurityIsEmpty bool } -// GobEncode provides a safe gob encoder for Operation, including empty security requirements +// GobEncode provides a safe gob encoder for Operation, including empty security requirements. func (o Operation) GobEncode() ([]byte, error) { raw := struct { Ext VendorExtensible @@ -298,7 +293,7 @@ func (o Operation) GobEncode() ([]byte, error) { return b.Bytes(), err } -// GobDecode provides a safe gob decoder for Operation, including empty security requirements +// GobDecode provides a safe gob decoder for Operation, including empty security requirements. func (o *Operation) GobDecode(b []byte) error { var raw struct { Ext VendorExtensible @@ -315,7 +310,7 @@ func (o *Operation) GobDecode(b []byte) error { return nil } -// GobEncode provides a safe gob encoder for Operation, including empty security requirements +// GobEncode provides a safe gob encoder for Operation, including empty security requirements. func (op OperationProps) GobEncode() ([]byte, error) { raw := gobAlias{ Alias: (*opsAlias)(&op), @@ -360,7 +355,7 @@ func (op OperationProps) GobEncode() ([]byte, error) { return b.Bytes(), err } -// GobDecode provides a safe gob decoder for Operation, including empty security requirements +// GobDecode provides a safe gob decoder for Operation, including empty security requirements. func (op *OperationProps) GobDecode(b []byte) error { var raw gobAlias diff --git a/vendor/github.com/go-openapi/spec/parameter.go b/vendor/github.com/go-openapi/spec/parameter.go index 2b2b89b67bf..516f5d95c56 100644 --- a/vendor/github.com/go-openapi/spec/parameter.go +++ b/vendor/github.com/go-openapi/spec/parameter.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -19,48 +8,54 @@ import ( "strings" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) -// QueryParam creates a query parameter +// QueryParam creates a query parameter. func QueryParam(name string) *Parameter { return &Parameter{ParamProps: ParamProps{Name: name, In: "query"}} } -// HeaderParam creates a header parameter, this is always required by default +// HeaderParam creates a header parameter, this is always required by default. func HeaderParam(name string) *Parameter { return &Parameter{ParamProps: ParamProps{Name: name, In: "header", Required: true}} } -// PathParam creates a path parameter, this is always required +// PathParam creates a path parameter, this is always required. func PathParam(name string) *Parameter { return &Parameter{ParamProps: ParamProps{Name: name, In: "path", Required: true}} } -// BodyParam creates a body parameter +// BodyParam creates a body parameter. func BodyParam(name string, schema *Schema) *Parameter { return &Parameter{ParamProps: ParamProps{Name: name, In: "body", Schema: schema}} } -// FormDataParam creates a body parameter +// FormDataParam creates a body parameter. func FormDataParam(name string) *Parameter { return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"}} } -// FileParam creates a body parameter +// FileParam creates a body parameter. func FileParam(name string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name, In: "formData"}, - SimpleSchema: SimpleSchema{Type: "file"}} + return &Parameter{ + ParamProps: ParamProps{Name: name, In: "formData"}, + SimpleSchema: SimpleSchema{Type: "file"}, + } } -// SimpleArrayParam creates a param for a simple array (string, int, date etc) +// SimpleArrayParam creates a param for a simple array (string, int, date etc). func SimpleArrayParam(name, tpe, fmt string) *Parameter { - return &Parameter{ParamProps: ParamProps{Name: name}, - SimpleSchema: SimpleSchema{Type: jsonArray, CollectionFormat: "csv", - Items: &Items{SimpleSchema: SimpleSchema{Type: tpe, Format: fmt}}}} + return &Parameter{ + ParamProps: ParamProps{Name: name}, + SimpleSchema: SimpleSchema{ + Type: jsonArray, CollectionFormat: "csv", + Items: &Items{SimpleSchema: SimpleSchema{Type: tpe, Format: fmt}}, + }, + } } -// ParamRef creates a parameter that's a json reference +// ParamRef creates a parameter that's a json reference. func ParamRef(uri string) *Parameter { p := new(Parameter) p.Ref = MustCreateRef(uri) @@ -71,7 +66,7 @@ func ParamRef(uri string) *Parameter { // // NOTE: // - Schema is defined when "in" == "body": see validate -// - AllowEmptyValue is allowed where "in" == "query" || "formData" +// - AllowEmptyValue is allowed where "in" == "query" || "formData". type ParamProps struct { Description string `json:"description,omitempty"` Name string `json:"name,omitempty"` @@ -84,27 +79,27 @@ type ParamProps struct { // Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn). // // There are five possible parameter types. -// * Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part -// of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`, -// the path parameter is `itemId`. -// * Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`. -// * Header - Custom headers that are expected as part of the request. -// * Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be -// _one_ body parameter. The name of the body parameter has no effect on the parameter itself and is used for -// documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist -// together for the same operation. -// * Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or -// `multipart/form-data` are used as the content type of the request (in Swagger's definition, -// the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used -// to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be -// declared together with a body parameter for the same operation. Form parameters have a different format based on -// the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4). -// * `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload. -// For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple -// parameters that are being transferred. -// * `multipart/form-data` - each parameter takes a section in the payload with an internal header. -// For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is -// `submit-name`. This type of form parameters is more commonly used for file transfers. +// - Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part +// of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`, +// the path parameter is `itemId`. +// - Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`. +// - Header - Custom headers that are expected as part of the request. +// - Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be +// _one_ body parameter. The name of the body parameter has no effect on the parameter itself and is used for +// documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist +// together for the same operation. +// - Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or +// `multipart/form-data` are used as the content type of the request (in Swagger's definition, +// the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used +// to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be +// declared together with a body parameter for the same operation. Form parameters have a different format based on +// the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4). +// - `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload. +// For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple +// parameters that are being transferred. +// - `multipart/form-data` - each parameter takes a section in the payload with an internal header. +// For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is +// `submit-name`. This type of form parameters is more commonly used for file transfers. // // For more information: http://goo.gl/8us55a#parameterObject type Parameter struct { @@ -115,8 +110,8 @@ type Parameter struct { ParamProps } -// JSONLookup look up a value by the json property name -func (p Parameter) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (p Parameter) JSONLookup(token string) (any, error) { if ex, ok := p.Extensions[token]; ok { return &ex, nil } @@ -142,32 +137,32 @@ func (p Parameter) JSONLookup(token string) (interface{}, error) { return r, err } -// WithDescription a fluent builder method for the description of the parameter +// WithDescription a fluent builder method for the description of the parameter. func (p *Parameter) WithDescription(description string) *Parameter { p.Description = description return p } -// Named a fluent builder method to override the name of the parameter +// Named a fluent builder method to override the name of the parameter. func (p *Parameter) Named(name string) *Parameter { p.Name = name return p } -// WithLocation a fluent builder method to override the location of the parameter +// WithLocation a fluent builder method to override the location of the parameter. func (p *Parameter) WithLocation(in string) *Parameter { p.In = in return p } -// Typed a fluent builder method for the type of the parameter value +// Typed a fluent builder method for the type of the parameter value. func (p *Parameter) Typed(tpe, format string) *Parameter { p.Type = tpe p.Format = format return p } -// CollectionOf a fluent builder method for an array parameter +// CollectionOf a fluent builder method for an array parameter. func (p *Parameter) CollectionOf(items *Items, format string) *Parameter { p.Type = jsonArray p.Items = items @@ -175,32 +170,32 @@ func (p *Parameter) CollectionOf(items *Items, format string) *Parameter { return p } -// WithDefault sets the default value on this parameter -func (p *Parameter) WithDefault(defaultValue interface{}) *Parameter { +// WithDefault sets the default value on this parameter. +func (p *Parameter) WithDefault(defaultValue any) *Parameter { p.AsOptional() // with default implies optional p.Default = defaultValue return p } -// AllowsEmptyValues flags this parameter as being ok with empty values +// AllowsEmptyValues flags this parameter as being ok with empty values. func (p *Parameter) AllowsEmptyValues() *Parameter { p.AllowEmptyValue = true return p } -// NoEmptyValues flags this parameter as not liking empty values +// NoEmptyValues flags this parameter as not liking empty values. func (p *Parameter) NoEmptyValues() *Parameter { p.AllowEmptyValue = false return p } -// AsOptional flags this parameter as optional +// AsOptional flags this parameter as optional. func (p *Parameter) AsOptional() *Parameter { p.Required = false return p } -// AsRequired flags this parameter as required +// AsRequired flags this parameter as required. func (p *Parameter) AsRequired() *Parameter { if p.Default != nil { // with a default required makes no sense return p @@ -209,81 +204,81 @@ func (p *Parameter) AsRequired() *Parameter { return p } -// WithMaxLength sets a max length value -func (p *Parameter) WithMaxLength(max int64) *Parameter { - p.MaxLength = &max +// WithMaxLength sets a max length value. +func (p *Parameter) WithMaxLength(maximum int64) *Parameter { + p.MaxLength = &maximum return p } -// WithMinLength sets a min length value -func (p *Parameter) WithMinLength(min int64) *Parameter { - p.MinLength = &min +// WithMinLength sets a min length value. +func (p *Parameter) WithMinLength(minimum int64) *Parameter { + p.MinLength = &minimum return p } -// WithPattern sets a pattern value +// WithPattern sets a pattern value. func (p *Parameter) WithPattern(pattern string) *Parameter { p.Pattern = pattern return p } -// WithMultipleOf sets a multiple of value +// WithMultipleOf sets a multiple of value. func (p *Parameter) WithMultipleOf(number float64) *Parameter { p.MultipleOf = &number return p } -// WithMaximum sets a maximum number value -func (p *Parameter) WithMaximum(max float64, exclusive bool) *Parameter { - p.Maximum = &max +// WithMaximum sets a maximum number value. +func (p *Parameter) WithMaximum(maximum float64, exclusive bool) *Parameter { + p.Maximum = &maximum p.ExclusiveMaximum = exclusive return p } -// WithMinimum sets a minimum number value -func (p *Parameter) WithMinimum(min float64, exclusive bool) *Parameter { - p.Minimum = &min +// WithMinimum sets a minimum number value. +func (p *Parameter) WithMinimum(minimum float64, exclusive bool) *Parameter { + p.Minimum = &minimum p.ExclusiveMinimum = exclusive return p } -// WithEnum sets a the enum values (replace) -func (p *Parameter) WithEnum(values ...interface{}) *Parameter { - p.Enum = append([]interface{}{}, values...) +// WithEnum sets a the enum values (replace). +func (p *Parameter) WithEnum(values ...any) *Parameter { + p.Enum = append([]any{}, values...) return p } -// WithMaxItems sets the max items +// WithMaxItems sets the max items. func (p *Parameter) WithMaxItems(size int64) *Parameter { p.MaxItems = &size return p } -// WithMinItems sets the min items +// WithMinItems sets the min items. func (p *Parameter) WithMinItems(size int64) *Parameter { p.MinItems = &size return p } -// UniqueValues dictates that this array can only have unique items +// UniqueValues dictates that this array can only have unique items. func (p *Parameter) UniqueValues() *Parameter { p.UniqueItems = true return p } -// AllowDuplicates this array can have duplicates +// AllowDuplicates this array can have duplicates. func (p *Parameter) AllowDuplicates() *Parameter { p.UniqueItems = false return p } -// WithValidations is a fluent method to set parameter validations +// WithValidations is a fluent method to set parameter validations. func (p *Parameter) WithValidations(val CommonValidations) *Parameter { p.SetValidations(SchemaValidations{CommonValidations: val}) return p } -// UnmarshalJSON hydrates this items instance with the data from JSON +// UnmarshalJSON hydrates this items instance with the data from JSON. func (p *Parameter) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &p.CommonValidations); err != nil { return err @@ -300,7 +295,7 @@ func (p *Parameter) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &p.ParamProps) } -// MarshalJSON converts this items object to JSON +// MarshalJSON converts this items object to JSON. func (p Parameter) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(p.CommonValidations) if err != nil { @@ -322,5 +317,5 @@ func (p Parameter) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b3, b1, b2, b4, b5), nil + return jsonutils.ConcatJSON(b3, b1, b2, b4, b5), nil } diff --git a/vendor/github.com/go-openapi/spec/path_item.go b/vendor/github.com/go-openapi/spec/path_item.go index 68fc8e90144..4408ece4654 100644 --- a/vendor/github.com/go-openapi/spec/path_item.go +++ b/vendor/github.com/go-openapi/spec/path_item.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -18,10 +7,10 @@ import ( "encoding/json" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) -// PathItemProps the path item specific properties +// PathItemProps the path item specific properties. type PathItemProps struct { Get *Operation `json:"get,omitempty"` Put *Operation `json:"put,omitempty"` @@ -45,8 +34,8 @@ type PathItem struct { PathItemProps } -// JSONLookup look up a value by the json property name -func (p PathItem) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (p PathItem) JSONLookup(token string) (any, error) { if ex, ok := p.Extensions[token]; ok { return &ex, nil } @@ -57,7 +46,7 @@ func (p PathItem) JSONLookup(token string) (interface{}, error) { return r, err } -// UnmarshalJSON hydrates this items instance with the data from JSON +// UnmarshalJSON hydrates this items instance with the data from JSON. func (p *PathItem) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &p.Refable); err != nil { return err @@ -68,7 +57,7 @@ func (p *PathItem) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &p.PathItemProps) } -// MarshalJSON converts this items object to JSON +// MarshalJSON converts this items object to JSON. func (p PathItem) MarshalJSON() ([]byte, error) { b3, err := json.Marshal(p.Refable) if err != nil { @@ -82,6 +71,6 @@ func (p PathItem) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - concated := swag.ConcatJSON(b3, b4, b5) + concated := jsonutils.ConcatJSON(b3, b4, b5) return concated, nil } diff --git a/vendor/github.com/go-openapi/spec/paths.go b/vendor/github.com/go-openapi/spec/paths.go index 9dc82a2901d..5daf5a6709f 100644 --- a/vendor/github.com/go-openapi/spec/paths.go +++ b/vendor/github.com/go-openapi/spec/paths.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -19,7 +8,7 @@ import ( "fmt" "strings" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) // Paths holds the relative paths to the individual endpoints. @@ -30,21 +19,22 @@ import ( // For more information: http://goo.gl/8us55a#pathsObject type Paths struct { VendorExtensible + Paths map[string]PathItem `json:"-"` // custom serializer to flatten this, each entry must start with "/" } -// JSONLookup look up a value by the json property name -func (p Paths) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (p Paths) JSONLookup(token string) (any, error) { if pi, ok := p.Paths[token]; ok { return &pi, nil } if ex, ok := p.Extensions[token]; ok { return &ex, nil } - return nil, fmt.Errorf("object has no field %q", token) + return nil, fmt.Errorf("object has no field %q: %w", token, ErrSpec) } -// UnmarshalJSON hydrates this items instance with the data from JSON +// UnmarshalJSON hydrates this items instance with the data from JSON. func (p *Paths) UnmarshalJSON(data []byte) error { var res map[string]json.RawMessage if err := json.Unmarshal(data, &res); err != nil { @@ -53,9 +43,9 @@ func (p *Paths) UnmarshalJSON(data []byte) error { for k, v := range res { if strings.HasPrefix(strings.ToLower(k), "x-") { if p.Extensions == nil { - p.Extensions = make(map[string]interface{}) + p.Extensions = make(map[string]any) } - var d interface{} + var d any if err := json.Unmarshal(v, &d); err != nil { return err } @@ -75,7 +65,7 @@ func (p *Paths) UnmarshalJSON(data []byte) error { return nil } -// MarshalJSON converts this items object to JSON +// MarshalJSON converts this items object to JSON. func (p Paths) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(p.VendorExtensible) if err != nil { @@ -92,6 +82,6 @@ func (p Paths) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - concated := swag.ConcatJSON(b1, b2) + concated := jsonutils.ConcatJSON(b1, b2) return concated, nil } diff --git a/vendor/github.com/go-openapi/spec/properties.go b/vendor/github.com/go-openapi/spec/properties.go index 2af13787ab1..b8e97271e19 100644 --- a/vendor/github.com/go-openapi/spec/properties.go +++ b/vendor/github.com/go-openapi/spec/properties.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package spec import ( @@ -7,10 +10,11 @@ import ( "sort" ) -// OrderSchemaItem holds a named schema (e.g. from a property of an object) +// OrderSchemaItem holds a named schema (e.g. from a property of an object). type OrderSchemaItem struct { - Name string Schema + + Name string } // OrderSchemaItems is a sortable slice of named schemas. @@ -21,30 +25,35 @@ type OrderSchemaItems []OrderSchemaItem // of the OrderSchemaItems slice, keeping the original order of the slice. func (items OrderSchemaItems) MarshalJSON() ([]byte, error) { buf := bytes.NewBuffer(nil) - buf.WriteString("{") - for i := range items { - if i > 0 { - buf.WriteString(",") - } - buf.WriteString("\"") - buf.WriteString(items[i].Name) - buf.WriteString("\":") - bs, err := json.Marshal(&items[i].Schema) - if err != nil { + buf.WriteByte('{') + + if len(items) == 0 { + buf.WriteByte('}') + + return buf.Bytes(), nil + } + + if err := items.marshalJSONItem(items[0], buf); err != nil { + return nil, err + } + + for _, item := range items[1:] { + buf.WriteByte(',') + if err := items.marshalJSONItem(item, buf); err != nil { return nil, err } - buf.Write(bs) } - buf.WriteString("}") + buf.WriteByte('}') + return buf.Bytes(), nil } func (items OrderSchemaItems) Len() int { return len(items) } func (items OrderSchemaItems) Swap(i, j int) { items[i], items[j] = items[j], items[i] } func (items OrderSchemaItems) Less(i, j int) (ret bool) { - ii, oki := items[i].Extensions.GetString("x-order") - ij, okj := items[j].Extensions.GetString("x-order") - if oki { + ii, oki := items[i].Extensions.GetInt("x-order") + ij, okj := items[j].Extensions.GetInt("x-order") + if oki { //nolint:nestif // nested recover logic for safe type comparison if okj { defer func() { if err := recover(); err != nil { @@ -56,7 +65,7 @@ func (items OrderSchemaItems) Less(i, j int) (ret bool) { ret = reflect.ValueOf(ii).String() < reflect.ValueOf(ij).String() } }() - return reflect.ValueOf(ii).Int() < reflect.ValueOf(ij).Int() + return ii < ij } return true } else if okj { @@ -65,11 +74,27 @@ func (items OrderSchemaItems) Less(i, j int) (ret bool) { return items[i].Name < items[j].Name } +func (items OrderSchemaItems) marshalJSONItem(item OrderSchemaItem, output *bytes.Buffer) error { + nameJSON, err := json.Marshal(item.Name) + if err != nil { + return err + } + output.Write(nameJSON) + output.WriteByte(':') + schemaJSON, err := json.Marshal(&item.Schema) + if err != nil { + return err + } + output.Write(schemaJSON) + + return nil +} + // SchemaProperties is a map representing the properties of a Schema object. // It knows how to transform its keys into an ordered slice. type SchemaProperties map[string]Schema -// ToOrderedSchemaItems transforms the map of properties into a sortable slice +// ToOrderedSchemaItems transforms the map of properties into a sortable slice. func (properties SchemaProperties) ToOrderedSchemaItems() OrderSchemaItems { items := make(OrderSchemaItems, 0, len(properties)) for k, v := range properties { diff --git a/vendor/github.com/go-openapi/spec/ref.go b/vendor/github.com/go-openapi/spec/ref.go index b0ef9bd9c9b..d1a7ab9b94b 100644 --- a/vendor/github.com/go-openapi/spec/ref.go +++ b/vendor/github.com/go-openapi/spec/ref.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -18,34 +7,50 @@ import ( "bytes" "encoding/gob" "encoding/json" - "net/http" "os" "path/filepath" "github.com/go-openapi/jsonreference" ) -// Refable is a struct for things that accept a $ref property +// Refable is a struct for things that accept a $ref property. type Refable struct { Ref Ref } -// MarshalJSON marshals the ref to json +// MarshalJSON marshals the ref to json. func (r Refable) MarshalJSON() ([]byte, error) { return r.Ref.MarshalJSON() } -// UnmarshalJSON unmarshalss the ref from json +// UnmarshalJSON unmarshals the ref from json. func (r *Refable) UnmarshalJSON(d []byte) error { return json.Unmarshal(d, &r.Ref) } -// Ref represents a json reference that is potentially resolved +// Ref represents a json reference that is potentially resolved. type Ref struct { jsonreference.Ref } -// RemoteURI gets the remote uri part of the ref +// NewRef creates a new instance of a ref object +// returns an error when the reference uri is an invalid uri. +func NewRef(refURI string) (Ref, error) { + ref, err := jsonreference.New(refURI) + if err != nil { + return Ref{}, err + } + + return Ref{Ref: ref}, nil +} + +// MustCreateRef creates a ref object but panics when refURI is invalid. +// Use the NewRef method for a version that returns an error. +func MustCreateRef(refURI string) Ref { + return Ref{Ref: jsonreference.MustCreateRef(refURI)} +} + +// RemoteURI gets the remote uri part of the ref. func (r *Ref) RemoteURI() string { if r.String() == "" { return "" @@ -56,7 +61,15 @@ func (r *Ref) RemoteURI() string { return u.String() } -// IsValidURI returns true when the url the ref points to can be found +// IsValidURI returns true when the ref points to a valid URI. +// +// For an absolute URL, it only checks that the reference is a well-formed URI. It deliberately +// does NOT perform a network request to verify that the remote target is reachable: doing so +// would make validation depend on network availability and expose callers to denial-of-service +// and SSRF when processing untrusted specifications. Resolving and fetching remote references is +// the responsibility of the expander, through its configurable (and confinable) document loader. +// +// For a local file reference, it checks that the file exists. func (r *Ref) IsValidURI(basepaths ...string) bool { if r.String() == "" { return true @@ -68,17 +81,11 @@ func (r *Ref) IsValidURI(basepaths ...string) bool { } if r.HasFullURL { - //nolint:noctx,gosec - rr, err := http.Get(v) - if err != nil { - return false - } - defer rr.Body.Close() - - return rr.StatusCode/100 == 2 + // a well-formed absolute URL is a valid URI; remote reachability is not checked here (see above). + return true } - if !(r.HasFileScheme || r.HasFullFilePath || r.HasURLPathOnly) { + if !r.HasFileScheme && !r.HasFullFilePath && !r.HasURLPathOnly { return false } @@ -105,7 +112,7 @@ func (r *Ref) IsValidURI(basepaths ...string) bool { } // Inherits creates a new reference from a parent and a child -// If the child cannot inherit from the parent, an error is returned +// If the child cannot inherit from the parent, an error is returned. func (r *Ref) Inherits(child Ref) (*Ref, error) { ref, err := r.Ref.Inherits(child.Ref) if err != nil { @@ -114,23 +121,7 @@ func (r *Ref) Inherits(child Ref) (*Ref, error) { return &Ref{Ref: *ref}, nil } -// NewRef creates a new instance of a ref object -// returns an error when the reference uri is an invalid uri -func NewRef(refURI string) (Ref, error) { - ref, err := jsonreference.New(refURI) - if err != nil { - return Ref{}, err - } - return Ref{Ref: ref}, nil -} - -// MustCreateRef creates a ref object but panics when refURI is invalid. -// Use the NewRef method for a version that returns an error. -func MustCreateRef(refURI string) Ref { - return Ref{Ref: jsonreference.MustCreateRef(refURI)} -} - -// MarshalJSON marshals this ref into a JSON object +// MarshalJSON marshals this ref into a JSON object. func (r Ref) MarshalJSON() ([]byte, error) { str := r.String() if str == "" { @@ -139,20 +130,20 @@ func (r Ref) MarshalJSON() ([]byte, error) { } return []byte("{}"), nil } - v := map[string]interface{}{"$ref": str} + v := map[string]any{"$ref": str} return json.Marshal(v) } -// UnmarshalJSON unmarshals this ref from a JSON object +// UnmarshalJSON unmarshals this ref from a JSON object. func (r *Ref) UnmarshalJSON(d []byte) error { - var v map[string]interface{} + var v map[string]any if err := json.Unmarshal(d, &v); err != nil { return err } return r.fromMap(v) } -// GobEncode provides a safe gob encoder for Ref +// GobEncode provides a safe gob encoder for Ref. func (r Ref) GobEncode() ([]byte, error) { var b bytes.Buffer raw, err := r.MarshalJSON() @@ -163,7 +154,7 @@ func (r Ref) GobEncode() ([]byte, error) { return b.Bytes(), err } -// GobDecode provides a safe gob decoder for Ref +// GobDecode provides a safe gob decoder for Ref. func (r *Ref) GobDecode(b []byte) error { var raw []byte buf := bytes.NewBuffer(b) @@ -174,7 +165,7 @@ func (r *Ref) GobDecode(b []byte) error { return json.Unmarshal(raw, r) } -func (r *Ref) fromMap(v map[string]interface{}) error { +func (r *Ref) fromMap(v map[string]any) error { if v == nil { return nil } diff --git a/vendor/github.com/go-openapi/spec/resolver.go b/vendor/github.com/go-openapi/spec/resolver.go index 47d1ee13fc7..1bf90c86828 100644 --- a/vendor/github.com/go-openapi/spec/resolver.go +++ b/vendor/github.com/go-openapi/spec/resolver.go @@ -1,12 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package spec import ( "fmt" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) -func resolveAnyWithBase(root interface{}, ref *Ref, result interface{}, options *ExpandOptions) error { +func resolveAnyWithBase(root any, ref *Ref, result any, options *ExpandOptions) error { options = optionsOrDefault(options) resolver := defaultSchemaLoader(root, options, nil, nil) @@ -17,8 +20,8 @@ func resolveAnyWithBase(root interface{}, ref *Ref, result interface{}, options return nil } -// ResolveRefWithBase resolves a reference against a context root with preservation of base path -func ResolveRefWithBase(root interface{}, ref *Ref, options *ExpandOptions) (*Schema, error) { +// ResolveRefWithBase resolves a reference against a context root with preservation of base path. +func ResolveRefWithBase(root any, ref *Ref, options *ExpandOptions) (*Schema, error) { result := new(Schema) if err := resolveAnyWithBase(root, ref, result, options); err != nil { @@ -31,8 +34,8 @@ func ResolveRefWithBase(root interface{}, ref *Ref, options *ExpandOptions) (*Sc // ResolveRef resolves a reference for a schema against a context root // ref is guaranteed to be in root (no need to go to external files) // -// ResolveRef is ONLY called from the code generation module -func ResolveRef(root interface{}, ref *Ref) (*Schema, error) { +// ResolveRef is ONLY called from the code generation module. +func ResolveRef(root any, ref *Ref) (*Schema, error) { res, _, err := ref.GetPointer().Get(root) if err != nil { return nil, err @@ -43,9 +46,9 @@ func ResolveRef(root interface{}, ref *Ref) (*Schema, error) { return &sch, nil case *Schema: return sch, nil - case map[string]interface{}: + case map[string]any: newSch := new(Schema) - if err = swag.DynamicJSONToStruct(sch, newSch); err != nil { + if err = jsonutils.FromDynamicJSON(sch, newSch); err != nil { return nil, err } return newSch, nil @@ -54,8 +57,8 @@ func ResolveRef(root interface{}, ref *Ref) (*Schema, error) { } } -// ResolveParameterWithBase resolves a parameter reference against a context root and base path -func ResolveParameterWithBase(root interface{}, ref Ref, options *ExpandOptions) (*Parameter, error) { +// ResolveParameterWithBase resolves a parameter reference against a context root and base path. +func ResolveParameterWithBase(root any, ref Ref, options *ExpandOptions) (*Parameter, error) { result := new(Parameter) if err := resolveAnyWithBase(root, &ref, result, options); err != nil { @@ -65,13 +68,13 @@ func ResolveParameterWithBase(root interface{}, ref Ref, options *ExpandOptions) return result, nil } -// ResolveParameter resolves a parameter reference against a context root -func ResolveParameter(root interface{}, ref Ref) (*Parameter, error) { +// ResolveParameter resolves a parameter reference against a context root. +func ResolveParameter(root any, ref Ref) (*Parameter, error) { return ResolveParameterWithBase(root, ref, nil) } -// ResolveResponseWithBase resolves response a reference against a context root and base path -func ResolveResponseWithBase(root interface{}, ref Ref, options *ExpandOptions) (*Response, error) { +// ResolveResponseWithBase resolves response a reference against a context root and base path. +func ResolveResponseWithBase(root any, ref Ref, options *ExpandOptions) (*Response, error) { result := new(Response) err := resolveAnyWithBase(root, &ref, result, options) @@ -82,13 +85,13 @@ func ResolveResponseWithBase(root interface{}, ref Ref, options *ExpandOptions) return result, nil } -// ResolveResponse resolves response a reference against a context root -func ResolveResponse(root interface{}, ref Ref) (*Response, error) { +// ResolveResponse resolves response a reference against a context root. +func ResolveResponse(root any, ref Ref) (*Response, error) { return ResolveResponseWithBase(root, ref, nil) } -// ResolvePathItemWithBase resolves response a path item against a context root and base path -func ResolvePathItemWithBase(root interface{}, ref Ref, options *ExpandOptions) (*PathItem, error) { +// ResolvePathItemWithBase resolves response a path item against a context root and base path. +func ResolvePathItemWithBase(root any, ref Ref, options *ExpandOptions) (*PathItem, error) { result := new(PathItem) if err := resolveAnyWithBase(root, &ref, result, options); err != nil { @@ -100,16 +103,16 @@ func ResolvePathItemWithBase(root interface{}, ref Ref, options *ExpandOptions) // ResolvePathItem resolves response a path item against a context root and base path // -// Deprecated: use ResolvePathItemWithBase instead -func ResolvePathItem(root interface{}, ref Ref, options *ExpandOptions) (*PathItem, error) { +// Deprecated: use ResolvePathItemWithBase instead. +func ResolvePathItem(root any, ref Ref, options *ExpandOptions) (*PathItem, error) { return ResolvePathItemWithBase(root, ref, options) } // ResolveItemsWithBase resolves parameter items reference against a context root and base path. // -// NOTE: stricly speaking, this construct is not supported by Swagger 2.0. +// NOTE: strictly speaking, this construct is not supported by Swagger 2.0. // Similarly, $ref are forbidden in response headers. -func ResolveItemsWithBase(root interface{}, ref Ref, options *ExpandOptions) (*Items, error) { +func ResolveItemsWithBase(root any, ref Ref, options *ExpandOptions) (*Items, error) { result := new(Items) if err := resolveAnyWithBase(root, &ref, result, options); err != nil { @@ -121,7 +124,7 @@ func ResolveItemsWithBase(root interface{}, ref Ref, options *ExpandOptions) (*I // ResolveItems resolves parameter items reference against a context root and base path. // -// Deprecated: use ResolveItemsWithBase instead -func ResolveItems(root interface{}, ref Ref, options *ExpandOptions) (*Items, error) { +// Deprecated: use ResolveItemsWithBase instead. +func ResolveItems(root any, ref Ref, options *ExpandOptions) (*Items, error) { return ResolveItemsWithBase(root, ref, options) } diff --git a/vendor/github.com/go-openapi/spec/response.go b/vendor/github.com/go-openapi/spec/response.go index 0340b60d845..4bb6a2bcd24 100644 --- a/vendor/github.com/go-openapi/spec/response.go +++ b/vendor/github.com/go-openapi/spec/response.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -18,15 +7,15 @@ import ( "encoding/json" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) -// ResponseProps properties specific to a response +// ResponseProps properties specific to a response. type ResponseProps struct { - Description string `json:"description"` - Schema *Schema `json:"schema,omitempty"` - Headers map[string]Header `json:"headers,omitempty"` - Examples map[string]interface{} `json:"examples,omitempty"` + Description string `json:"description"` + Schema *Schema `json:"schema,omitempty"` + Headers map[string]Header `json:"headers,omitempty"` + Examples map[string]any `json:"examples,omitempty"` } // Response describes a single response from an API Operation. @@ -38,8 +27,20 @@ type Response struct { VendorExtensible } -// JSONLookup look up a value by the json property name -func (r Response) JSONLookup(token string) (interface{}, error) { +// NewResponse creates a new response instance. +func NewResponse() *Response { + return new(Response) +} + +// ResponseRef creates a response as a json reference. +func ResponseRef(url string) *Response { + resp := NewResponse() + resp.Ref = MustCreateRef(url) + return resp +} + +// JSONLookup look up a value by the json property name. +func (r Response) JSONLookup(token string) (any, error) { if ex, ok := r.Extensions[token]; ok { return &ex, nil } @@ -50,7 +51,7 @@ func (r Response) JSONLookup(token string) (interface{}, error) { return ptr, err } -// UnmarshalJSON hydrates this items instance with the data from JSON +// UnmarshalJSON hydrates this items instance with the data from JSON. func (r *Response) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &r.ResponseProps); err != nil { return err @@ -61,7 +62,7 @@ func (r *Response) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, &r.VendorExtensible) } -// MarshalJSON converts this items object to JSON +// MarshalJSON converts this items object to JSON. func (r Response) MarshalJSON() ([]byte, error) { var ( b1 []byte @@ -74,14 +75,14 @@ func (r Response) MarshalJSON() ([]byte, error) { } else { // when there is $ref inside the schema, description should be omitempty-ied b1, err = json.Marshal(struct { - Description string `json:"description,omitempty"` - Schema *Schema `json:"schema,omitempty"` - Headers map[string]Header `json:"headers,omitempty"` - Examples map[string]interface{} `json:"examples,omitempty"` + Description string `json:"description,omitempty"` + Schema *Schema `json:"schema,omitempty"` + Headers map[string]Header `json:"headers,omitempty"` + Examples map[string]any `json:"examples,omitempty"` }{ - Description: r.ResponseProps.Description, - Schema: r.ResponseProps.Schema, - Examples: r.ResponseProps.Examples, + Description: r.Description, + Schema: r.Schema, + Examples: r.Examples, }) } if err != nil { @@ -96,35 +97,23 @@ func (r Response) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2, b3), nil -} - -// NewResponse creates a new response instance -func NewResponse() *Response { - return new(Response) -} - -// ResponseRef creates a response as a json reference -func ResponseRef(url string) *Response { - resp := NewResponse() - resp.Ref = MustCreateRef(url) - return resp + return jsonutils.ConcatJSON(b1, b2, b3), nil } -// WithDescription sets the description on this response, allows for chaining +// WithDescription sets the description on this response, allows for chaining. func (r *Response) WithDescription(description string) *Response { r.Description = description return r } // WithSchema sets the schema on this response, allows for chaining. -// Passing a nil argument removes the schema from this response +// Passing a nil argument removes the schema from this response. func (r *Response) WithSchema(schema *Schema) *Response { r.Schema = schema return r } -// AddHeader adds a header to this response +// AddHeader adds a header to this response. func (r *Response) AddHeader(name string, header *Header) *Response { if header == nil { return r.RemoveHeader(name) @@ -136,16 +125,16 @@ func (r *Response) AddHeader(name string, header *Header) *Response { return r } -// RemoveHeader removes a header from this response +// RemoveHeader removes a header from this response. func (r *Response) RemoveHeader(name string) *Response { delete(r.Headers, name) return r } -// AddExample adds an example to this response -func (r *Response) AddExample(mediaType string, example interface{}) *Response { +// AddExample adds an example to this response. +func (r *Response) AddExample(mediaType string, example any) *Response { if r.Examples == nil { - r.Examples = make(map[string]interface{}) + r.Examples = make(map[string]any) } r.Examples[mediaType] = example return r diff --git a/vendor/github.com/go-openapi/spec/responses.go b/vendor/github.com/go-openapi/spec/responses.go index 4efb6f868bd..fb369e4a6b0 100644 --- a/vendor/github.com/go-openapi/spec/responses.go +++ b/vendor/github.com/go-openapi/spec/responses.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -19,8 +8,9 @@ import ( "fmt" "reflect" "strconv" + "strings" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) // Responses is a container for the expected responses of an operation. @@ -41,8 +31,8 @@ type Responses struct { ResponsesProps } -// JSONLookup implements an interface to customize json pointer lookup -func (r Responses) JSONLookup(token string) (interface{}, error) { +// JSONLookup implements an interface to customize json pointer lookup. +func (r Responses) JSONLookup(token string) (any, error) { if token == "default" { return r.Default, nil } @@ -54,14 +44,15 @@ func (r Responses) JSONLookup(token string) (interface{}, error) { return scr, nil } } - return nil, fmt.Errorf("object has no field %q", token) + return nil, fmt.Errorf("object has no field %q: %w", token, ErrSpec) } -// UnmarshalJSON hydrates this items instance with the data from JSON +// UnmarshalJSON hydrates this items instance with the data from JSON. func (r *Responses) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &r.ResponsesProps); err != nil { return err } + if err := json.Unmarshal(data, &r.VendorExtensible); err != nil { return err } @@ -71,7 +62,7 @@ func (r *Responses) UnmarshalJSON(data []byte) error { return nil } -// MarshalJSON converts this items object to JSON +// MarshalJSON converts this items object to JSON. func (r Responses) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(r.ResponsesProps) if err != nil { @@ -81,7 +72,7 @@ func (r Responses) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - concated := swag.ConcatJSON(b1, b2) + concated := jsonutils.ConcatJSON(b1, b2) return concated, nil } @@ -93,7 +84,7 @@ type ResponsesProps struct { StatusCodeResponses map[int]Response } -// MarshalJSON marshals responses as JSON +// MarshalJSON marshals responses as JSON. func (r ResponsesProps) MarshalJSON() ([]byte, error) { toser := map[string]Response{} if r.Default != nil { @@ -105,22 +96,33 @@ func (r ResponsesProps) MarshalJSON() ([]byte, error) { return json.Marshal(toser) } -// UnmarshalJSON unmarshals responses from JSON +// UnmarshalJSON unmarshals responses from JSON. func (r *ResponsesProps) UnmarshalJSON(data []byte) error { - var res map[string]Response + var res map[string]json.RawMessage if err := json.Unmarshal(data, &res); err != nil { - return nil + return err } + if v, ok := res["default"]; ok { - r.Default = &v + var defaultRes Response + if err := json.Unmarshal(v, &defaultRes); err != nil { + return err + } + r.Default = &defaultRes delete(res, "default") } for k, v := range res { - if nk, err := strconv.Atoi(k); err == nil { - if r.StatusCodeResponses == nil { - r.StatusCodeResponses = map[int]Response{} + if !strings.HasPrefix(k, "x-") { + var statusCodeResp Response + if err := json.Unmarshal(v, &statusCodeResp); err != nil { + return err + } + if nk, err := strconv.Atoi(k); err == nil { + if r.StatusCodeResponses == nil { + r.StatusCodeResponses = map[int]Response{} + } + r.StatusCodeResponses[nk] = statusCodeResp } - r.StatusCodeResponses[nk] = v } } return nil diff --git a/vendor/github.com/go-openapi/spec/schema.go b/vendor/github.com/go-openapi/spec/schema.go index a8d0f737a7a..c71a2e5c5ab 100644 --- a/vendor/github.com/go-openapi/spec/schema.go +++ b/vendor/github.com/go-openapi/spec/schema.go @@ -1,109 +1,100 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec import ( "encoding/json" "fmt" - "net/url" "strings" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/jsonpointer/jsonname" + "github.com/go-openapi/swag/jsonutils" ) -// BooleanProperty creates a boolean property +// BooleanProperty creates a boolean property. func BooleanProperty() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"boolean"}}} } -// BoolProperty creates a boolean property +// BoolProperty creates a boolean property. func BoolProperty() *Schema { return BooleanProperty() } -// StringProperty creates a string property +// StringProperty creates a string property. func StringProperty() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}} } -// CharProperty creates a string property +// CharProperty creates a string property. func CharProperty() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}} } -// Float64Property creates a float64/double property +// Float64Property creates a float64/double property. func Float64Property() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "double"}} } -// Float32Property creates a float32/float property +// Float32Property creates a float32/float property. func Float32Property() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "float"}} } -// Int8Property creates an int8 property +// Int8Property creates an int8 property. func Int8Property() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int8"}} } -// Int16Property creates an int16 property +// Int16Property creates an int16 property. func Int16Property() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int16"}} } -// Int32Property creates an int32 property +// Int32Property creates an int32 property. func Int32Property() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int32"}} } -// Int64Property creates an int64 property +// Int64Property creates an int64 property. func Int64Property() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int64"}} } -// StrFmtProperty creates a property for the named string format +// StrFmtProperty creates a property for the named string format. func StrFmtProperty(format string) *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: format}} } -// DateProperty creates a date property +// DateProperty creates a date property. func DateProperty() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date"}} } -// DateTimeProperty creates a date time property +// DateTimeProperty creates a date time property. func DateTimeProperty() *Schema { return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date-time"}} } -// MapProperty creates a map property +// MapProperty creates a map property. func MapProperty(property *Schema) *Schema { - return &Schema{SchemaProps: SchemaProps{Type: []string{"object"}, - AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}}} + return &Schema{SchemaProps: SchemaProps{ + Type: []string{"object"}, + AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}, + }} } -// RefProperty creates a ref property +// RefProperty creates a ref property. func RefProperty(name string) *Schema { return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}} } -// RefSchema creates a ref property +// RefSchema creates a ref property. func RefSchema(name string) *Schema { return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}} } -// ArrayProperty creates an array property +// ArrayProperty creates an array property. func ArrayProperty(items *Schema) *Schema { if items == nil { return &Schema{SchemaProps: SchemaProps{Type: []string{"array"}}} @@ -111,41 +102,41 @@ func ArrayProperty(items *Schema) *Schema { return &Schema{SchemaProps: SchemaProps{Items: &SchemaOrArray{Schema: items}, Type: []string{"array"}}} } -// ComposedSchema creates a schema with allOf +// ComposedSchema creates a schema with allOf. func ComposedSchema(schemas ...Schema) *Schema { s := new(Schema) s.AllOf = schemas return s } -// SchemaURL represents a schema url +// SchemaURL represents a schema url. type SchemaURL string -// MarshalJSON marshal this to JSON +// MarshalJSON marshal this to JSON. func (r SchemaURL) MarshalJSON() ([]byte, error) { if r == "" { return []byte("{}"), nil } - v := map[string]interface{}{"$schema": string(r)} + v := map[string]any{"$schema": string(r)} return json.Marshal(v) } -// UnmarshalJSON unmarshal this from JSON +// UnmarshalJSON unmarshal this from JSON. func (r *SchemaURL) UnmarshalJSON(data []byte) error { - var v map[string]interface{} + var v map[string]any if err := json.Unmarshal(data, &v); err != nil { return err } return r.fromMap(v) } -func (r *SchemaURL) fromMap(v map[string]interface{}) error { +func (r *SchemaURL) fromMap(v map[string]any) error { if v == nil { return nil } if vv, ok := v["$schema"]; ok { if str, ok := vv.(string); ok { - u, err := url.Parse(str) + u, err := parseURL(str) if err != nil { return err } @@ -156,7 +147,7 @@ func (r *SchemaURL) fromMap(v map[string]interface{}) error { return nil } -// SchemaProps describes a JSON schema (draft 4) +// SchemaProps describes a JSON schema (draft 4). type SchemaProps struct { ID string `json:"id,omitempty"` Ref Ref `json:"-"` @@ -166,7 +157,7 @@ type SchemaProps struct { Nullable bool `json:"nullable,omitempty"` Format string `json:"format,omitempty"` Title string `json:"title,omitempty"` - Default interface{} `json:"default,omitempty"` + Default any `json:"default,omitempty"` Maximum *float64 `json:"maximum,omitempty"` ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"` Minimum *float64 `json:"minimum,omitempty"` @@ -178,7 +169,7 @@ type SchemaProps struct { MinItems *int64 `json:"minItems,omitempty"` UniqueItems bool `json:"uniqueItems,omitempty"` MultipleOf *float64 `json:"multipleOf,omitempty"` - Enum []interface{} `json:"enum,omitempty"` + Enum []any `json:"enum,omitempty"` MaxProperties *int64 `json:"maxProperties,omitempty"` MinProperties *int64 `json:"minProperties,omitempty"` Required []string `json:"required,omitempty"` @@ -195,13 +186,13 @@ type SchemaProps struct { Definitions Definitions `json:"definitions,omitempty"` } -// SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4) +// SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4). type SwaggerSchemaProps struct { Discriminator string `json:"discriminator,omitempty"` ReadOnly bool `json:"readOnly,omitempty"` XML *XMLObject `json:"xml,omitempty"` ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` - Example interface{} `json:"example,omitempty"` + Example any `json:"example,omitempty"` } // Schema the schema object allows the definition of input and output data types. @@ -215,11 +206,12 @@ type Schema struct { VendorExtensible SchemaProps SwaggerSchemaProps - ExtraProps map[string]interface{} `json:"-"` + + ExtraProps map[string]any `json:"-"` } -// JSONLookup implements an interface to customize json pointer lookup -func (s Schema) JSONLookup(token string) (interface{}, error) { +// JSONLookup implements an interface to customize json pointer lookup. +func (s Schema) JSONLookup(token string) (any, error) { if ex, ok := s.Extensions[token]; ok { return &ex, nil } @@ -236,31 +228,31 @@ func (s Schema) JSONLookup(token string) (interface{}, error) { return r, err } -// WithID sets the id for this schema, allows for chaining +// WithID sets the id for this schema, allows for chaining. func (s *Schema) WithID(id string) *Schema { s.ID = id return s } -// WithTitle sets the title for this schema, allows for chaining +// WithTitle sets the title for this schema, allows for chaining. func (s *Schema) WithTitle(title string) *Schema { s.Title = title return s } -// WithDescription sets the description for this schema, allows for chaining +// WithDescription sets the description for this schema, allows for chaining. func (s *Schema) WithDescription(description string) *Schema { s.Description = description return s } -// WithProperties sets the properties for this schema +// WithProperties sets the properties for this schema. func (s *Schema) WithProperties(schemas map[string]Schema) *Schema { s.Properties = schemas return s } -// SetProperty sets a property on this schema +// SetProperty sets a property on this schema. func (s *Schema) SetProperty(name string, schema Schema) *Schema { if s.Properties == nil { s.Properties = make(map[string]Schema) @@ -269,32 +261,32 @@ func (s *Schema) SetProperty(name string, schema Schema) *Schema { return s } -// WithAllOf sets the all of property +// WithAllOf sets the all of property. func (s *Schema) WithAllOf(schemas ...Schema) *Schema { s.AllOf = schemas return s } -// WithMaxProperties sets the max number of properties an object can have -func (s *Schema) WithMaxProperties(max int64) *Schema { - s.MaxProperties = &max +// WithMaxProperties sets the max number of properties an object can have. +func (s *Schema) WithMaxProperties(maximum int64) *Schema { + s.MaxProperties = &maximum return s } -// WithMinProperties sets the min number of properties an object must have -func (s *Schema) WithMinProperties(min int64) *Schema { - s.MinProperties = &min +// WithMinProperties sets the min number of properties an object must have. +func (s *Schema) WithMinProperties(minimum int64) *Schema { + s.MinProperties = &minimum return s } -// Typed sets the type of this schema for a single value item +// Typed sets the type of this schema for a single value item. func (s *Schema) Typed(tpe, format string) *Schema { s.Type = []string{tpe} s.Format = format return s } -// AddType adds a type with potential format to the types for this schema +// AddType adds a type with potential format to the types for this schema. func (s *Schema) AddType(tpe, format string) *Schema { s.Type = append(s.Type, tpe) if format != "" { @@ -309,125 +301,125 @@ func (s *Schema) AsNullable() *Schema { return s } -// CollectionOf a fluent builder method for an array parameter +// CollectionOf a fluent builder method for an array parameter. func (s *Schema) CollectionOf(items Schema) *Schema { s.Type = []string{jsonArray} s.Items = &SchemaOrArray{Schema: &items} return s } -// WithDefault sets the default value on this parameter -func (s *Schema) WithDefault(defaultValue interface{}) *Schema { +// WithDefault sets the default value on this parameter. +func (s *Schema) WithDefault(defaultValue any) *Schema { s.Default = defaultValue return s } -// WithRequired flags this parameter as required +// WithRequired flags this parameter as required. func (s *Schema) WithRequired(items ...string) *Schema { s.Required = items return s } -// AddRequired adds field names to the required properties array +// AddRequired adds field names to the required properties array. func (s *Schema) AddRequired(items ...string) *Schema { s.Required = append(s.Required, items...) return s } -// WithMaxLength sets a max length value -func (s *Schema) WithMaxLength(max int64) *Schema { - s.MaxLength = &max +// WithMaxLength sets a max length value. +func (s *Schema) WithMaxLength(maximum int64) *Schema { + s.MaxLength = &maximum return s } -// WithMinLength sets a min length value -func (s *Schema) WithMinLength(min int64) *Schema { - s.MinLength = &min +// WithMinLength sets a min length value. +func (s *Schema) WithMinLength(minimum int64) *Schema { + s.MinLength = &minimum return s } -// WithPattern sets a pattern value +// WithPattern sets a pattern value. func (s *Schema) WithPattern(pattern string) *Schema { s.Pattern = pattern return s } -// WithMultipleOf sets a multiple of value +// WithMultipleOf sets a multiple of value. func (s *Schema) WithMultipleOf(number float64) *Schema { s.MultipleOf = &number return s } -// WithMaximum sets a maximum number value -func (s *Schema) WithMaximum(max float64, exclusive bool) *Schema { - s.Maximum = &max +// WithMaximum sets a maximum number value. +func (s *Schema) WithMaximum(maximum float64, exclusive bool) *Schema { + s.Maximum = &maximum s.ExclusiveMaximum = exclusive return s } -// WithMinimum sets a minimum number value -func (s *Schema) WithMinimum(min float64, exclusive bool) *Schema { - s.Minimum = &min +// WithMinimum sets a minimum number value. +func (s *Schema) WithMinimum(minimum float64, exclusive bool) *Schema { + s.Minimum = &minimum s.ExclusiveMinimum = exclusive return s } -// WithEnum sets a the enum values (replace) -func (s *Schema) WithEnum(values ...interface{}) *Schema { - s.Enum = append([]interface{}{}, values...) +// WithEnum sets a the enum values (replace). +func (s *Schema) WithEnum(values ...any) *Schema { + s.Enum = append([]any{}, values...) return s } -// WithMaxItems sets the max items +// WithMaxItems sets the max items. func (s *Schema) WithMaxItems(size int64) *Schema { s.MaxItems = &size return s } -// WithMinItems sets the min items +// WithMinItems sets the min items. func (s *Schema) WithMinItems(size int64) *Schema { s.MinItems = &size return s } -// UniqueValues dictates that this array can only have unique items +// UniqueValues dictates that this array can only have unique items. func (s *Schema) UniqueValues() *Schema { s.UniqueItems = true return s } -// AllowDuplicates this array can have duplicates +// AllowDuplicates this array can have duplicates. func (s *Schema) AllowDuplicates() *Schema { s.UniqueItems = false return s } -// AddToAllOf adds a schema to the allOf property +// AddToAllOf adds a schema to the allOf property. func (s *Schema) AddToAllOf(schemas ...Schema) *Schema { s.AllOf = append(s.AllOf, schemas...) return s } -// WithDiscriminator sets the name of the discriminator field +// WithDiscriminator sets the name of the discriminator field. func (s *Schema) WithDiscriminator(discriminator string) *Schema { s.Discriminator = discriminator return s } -// AsReadOnly flags this schema as readonly +// AsReadOnly flags this schema as readonly. func (s *Schema) AsReadOnly() *Schema { s.ReadOnly = true return s } -// AsWritable flags this schema as writeable (not read-only) +// AsWritable flags this schema as writeable (not read-only). func (s *Schema) AsWritable() *Schema { s.ReadOnly = false return s } -// WithExample sets the example for this schema -func (s *Schema) WithExample(example interface{}) *Schema { +// WithExample sets the example for this schema. +func (s *Schema) WithExample(example any) *Schema { s.Example = example return s } @@ -450,7 +442,7 @@ func (s *Schema) WithExternalDocs(description, url string) *Schema { return s } -// WithXMLName sets the xml name for the object +// WithXMLName sets the xml name for the object. func (s *Schema) WithXMLName(name string) *Schema { if s.XML == nil { s.XML = new(XMLObject) @@ -459,7 +451,7 @@ func (s *Schema) WithXMLName(name string) *Schema { return s } -// WithXMLNamespace sets the xml namespace for the object +// WithXMLNamespace sets the xml namespace for the object. func (s *Schema) WithXMLNamespace(namespace string) *Schema { if s.XML == nil { s.XML = new(XMLObject) @@ -468,7 +460,7 @@ func (s *Schema) WithXMLNamespace(namespace string) *Schema { return s } -// WithXMLPrefix sets the xml prefix for the object +// WithXMLPrefix sets the xml prefix for the object. func (s *Schema) WithXMLPrefix(prefix string) *Schema { if s.XML == nil { s.XML = new(XMLObject) @@ -477,7 +469,7 @@ func (s *Schema) WithXMLPrefix(prefix string) *Schema { return s } -// AsXMLAttribute flags this object as xml attribute +// AsXMLAttribute flags this object as xml attribute. func (s *Schema) AsXMLAttribute() *Schema { if s.XML == nil { s.XML = new(XMLObject) @@ -486,7 +478,7 @@ func (s *Schema) AsXMLAttribute() *Schema { return s } -// AsXMLElement flags this object as an xml node +// AsXMLElement flags this object as an xml node. func (s *Schema) AsXMLElement() *Schema { if s.XML == nil { s.XML = new(XMLObject) @@ -495,7 +487,7 @@ func (s *Schema) AsXMLElement() *Schema { return s } -// AsWrappedXML flags this object as wrapped, this is mostly useful for array types +// AsWrappedXML flags this object as wrapped, this is mostly useful for array types. func (s *Schema) AsWrappedXML() *Schema { if s.XML == nil { s.XML = new(XMLObject) @@ -504,7 +496,7 @@ func (s *Schema) AsWrappedXML() *Schema { return s } -// AsUnwrappedXML flags this object as an xml node +// AsUnwrappedXML flags this object as an xml node. func (s *Schema) AsUnwrappedXML() *Schema { if s.XML == nil { s.XML = new(XMLObject) @@ -534,13 +526,13 @@ func (s *Schema) SetValidations(val SchemaValidations) { s.PatternProperties = val.PatternProperties } -// WithValidations is a fluent method to set schema validations +// WithValidations is a fluent method to set schema validations. func (s *Schema) WithValidations(val SchemaValidations) *Schema { s.SetValidations(val) return s } -// Validations returns a clone of the validations for this schema +// Validations returns a clone of the validations for this schema. func (s Schema) Validations() SchemaValidations { return SchemaValidations{ CommonValidations: CommonValidations{ @@ -563,40 +555,40 @@ func (s Schema) Validations() SchemaValidations { } } -// MarshalJSON marshal this to JSON +// MarshalJSON marshal this to JSON. func (s Schema) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(s.SchemaProps) if err != nil { - return nil, fmt.Errorf("schema props %v", err) + return nil, fmt.Errorf("schema props %w: %w", err, ErrSpec) } b2, err := json.Marshal(s.VendorExtensible) if err != nil { - return nil, fmt.Errorf("vendor props %v", err) + return nil, fmt.Errorf("vendor props %w: %w", err, ErrSpec) } b3, err := s.Ref.MarshalJSON() if err != nil { - return nil, fmt.Errorf("ref prop %v", err) + return nil, fmt.Errorf("ref prop %w: %w", err, ErrSpec) } b4, err := s.Schema.MarshalJSON() if err != nil { - return nil, fmt.Errorf("schema prop %v", err) + return nil, fmt.Errorf("schema prop %w: %w", err, ErrSpec) } b5, err := json.Marshal(s.SwaggerSchemaProps) if err != nil { - return nil, fmt.Errorf("common validations %v", err) + return nil, fmt.Errorf("common validations %w: %w", err, ErrSpec) } var b6 []byte if s.ExtraProps != nil { jj, err := json.Marshal(s.ExtraProps) if err != nil { - return nil, fmt.Errorf("extra props %v", err) + return nil, fmt.Errorf("extra props %w: %w", err, ErrSpec) } b6 = jj } - return swag.ConcatJSON(b1, b2, b3, b4, b5, b6), nil + return jsonutils.ConcatJSON(b1, b2, b3, b4, b5, b6), nil } -// UnmarshalJSON marshal this from JSON +// UnmarshalJSON marshal this from JSON. func (s *Schema) UnmarshalJSON(data []byte) error { props := struct { SchemaProps @@ -611,7 +603,7 @@ func (s *Schema) UnmarshalJSON(data []byte) error { SwaggerSchemaProps: props.SwaggerSchemaProps, } - var d map[string]interface{} + var d map[string]any if err := json.Unmarshal(data, &d); err != nil { return err } @@ -621,7 +613,7 @@ func (s *Schema) UnmarshalJSON(data []byte) error { delete(d, "$ref") delete(d, "$schema") - for _, pn := range swag.DefaultJSONNameProvider.GetJSONNames(s) { + for _, pn := range jsonname.DefaultJSONNameProvider.GetJSONNames(s) { delete(d, pn) } @@ -629,13 +621,13 @@ func (s *Schema) UnmarshalJSON(data []byte) error { lk := strings.ToLower(k) if strings.HasPrefix(lk, "x-") { if sch.Extensions == nil { - sch.Extensions = map[string]interface{}{} + sch.Extensions = map[string]any{} } sch.Extensions[k] = vv continue } if sch.ExtraProps == nil { - sch.ExtraProps = map[string]interface{}{} + sch.ExtraProps = map[string]any{} } sch.ExtraProps[k] = vv } diff --git a/vendor/github.com/go-openapi/spec/schema_loader.go b/vendor/github.com/go-openapi/spec/schema_loader.go index b81175afdf4..491ed020fd1 100644 --- a/vendor/github.com/go-openapi/spec/schema_loader.go +++ b/vendor/github.com/go-openapi/spec/schema_loader.go @@ -1,28 +1,20 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec import ( "encoding/json" + "errors" "fmt" "log" "net/url" "reflect" "strings" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" + "github.com/go-openapi/swag/loading" + "github.com/go-openapi/swag/stringutils" ) // PathLoader is a function to use when loading remote refs. @@ -33,8 +25,8 @@ import ( // NOTE: if you are using the go-openapi/loads package, it will override // this value with its own default (a loader to retrieve YAML documents as // well as JSON ones). -var PathLoader = func(pth string) (json.RawMessage, error) { - data, err := swag.LoadFromFileOrHTTP(pth) +var PathLoader = func(pth string) (json.RawMessage, error) { //nolint:gochecknoglobals // package-level default loader, overridable by go-openapi/loads + data, err := loading.LoadFromFileOrHTTP(pth) if err != nil { return nil, err } @@ -52,33 +44,68 @@ type resolverContext struct { basePath string loadDoc func(string) (json.RawMessage, error) rootID string + + // nodes counts the schema nodes expanded so far, capped by maxNodes to guard against + // $ref amplification. maxNodes == 0 means unbounded. Shared, single-threaded: no locking needed. + nodes int + maxNodes int } func newResolverContext(options *ExpandOptions) *resolverContext { expandOptions := optionsOrDefault(options) - // path loader may be overridden by options + // path loader may be overridden by options. An option-aware loader takes precedence over a + // plain one, which in turn takes precedence over the package-level default. var loader func(string) (json.RawMessage, error) - if expandOptions.PathLoader == nil { - loader = PathLoader - } else { + switch { + case expandOptions.PathLoaderWithOptions != nil: + withOptions := expandOptions.PathLoaderWithOptions + loader = func(pth string) (json.RawMessage, error) { + // the injected loader carries its own loading options: none are added here. + return withOptions(pth) + } + case expandOptions.PathLoader != nil: loader = expandOptions.PathLoader + default: + loader = PathLoader } return &resolverContext{ circulars: make(map[string]bool), basePath: expandOptions.RelativeBase, // keep the root base path in context loadDoc: loader, + maxNodes: expandOptions.maxExpansionNodes(), } } +// countNode accounts for one expanded schema node and reports whether the expansion budget +// has been exceeded. A maxNodes of 0 disables the budget (unbounded expansion). +func (c *resolverContext) countNode() error { + c.nodes++ + if c.maxNodes > 0 && c.nodes > c.maxNodes { + return ErrExpandTooManyNodes + } + return nil +} + type schemaLoader struct { - root interface{} + root any options *ExpandOptions cache ResolutionCache context *resolverContext } +// Resolve resolves a reference against basePath and stores the result in target. +// +// Resolve is not in charge of following references: it only resolves ref by following its URL. +// +// If the schema the ref is referring to holds nested refs, Resolve doesn't resolve them. +// +// If basePath is an empty string, ref is resolved against the root schema stored in the schemaLoader struct. +func (r *schemaLoader) Resolve(ref *Ref, target any, basePath string) error { + return r.resolveRef(ref, target, basePath) +} + func (r *schemaLoader) transitiveResolver(basePath string, ref Ref) *schemaLoader { if ref.IsRoot() || ref.HasFragmentOnly { return r @@ -113,9 +140,9 @@ func (r *schemaLoader) updateBasePath(transitive *schemaLoader, basePath string) return basePath } -func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string) error { +func (r *schemaLoader) resolveRef(ref *Ref, target any, basePath string) error { tgt := reflect.ValueOf(target) - if tgt.Kind() != reflect.Ptr { + if tgt.Kind() != reflect.Pointer { return ErrResolveRefNeedsAPointer } @@ -124,8 +151,8 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string) } var ( - res interface{} - data interface{} + res any + data any err error ) @@ -134,7 +161,7 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string) root := r.root if (ref.IsRoot() || ref.HasFragmentOnly) && root == nil && basePath != "" { if baseRef, erb := NewRef(basePath); erb == nil { - root, _, _, _ = r.load(baseRef.GetURL()) + root, _ = r.load(baseRef.GetURL()) } } @@ -142,7 +169,7 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string) data = root } else { baseRef := normalizeRef(ref, basePath) - data, _, _, err = r.load(baseRef.GetURL()) + data, err = r.load(baseRef.GetURL()) if err != nil { return err } @@ -155,43 +182,35 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string) return err } } - return swag.DynamicJSONToStruct(res, target) + return jsonutils.FromDynamicJSON(res, target) } -func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error) { +func (r *schemaLoader) load(refURL *url.URL) (any, error) { debugLog("loading schema from url: %s", refURL) toFetch := *refURL toFetch.Fragment = "" - var err error pth := toFetch.String() normalized := normalizeBase(pth) debugLog("loading doc from: %s", normalized) - unescaped, err := url.PathUnescape(normalized) - if err != nil { - return nil, url.URL{}, false, err - } - - u := url.URL{Path: unescaped} - - data, fromCache := r.cache.Get(u.RequestURI()) + data, fromCache := r.cache.Get(normalized) if fromCache { - return data, toFetch, fromCache, nil + return data, nil } b, err := r.context.loadDoc(normalized) if err != nil { - return nil, url.URL{}, false, err + return nil, err } - var doc interface{} + var doc any if err := json.Unmarshal(b, &doc); err != nil { - return nil, url.URL{}, false, err + return nil, err } r.cache.Set(normalized, doc) - return doc, toFetch, fromCache, nil + return doc, nil } // isCircular detects cycles in sequences of $ref. @@ -204,25 +223,14 @@ func (r *schemaLoader) isCircular(ref *Ref, basePath string, parentRefs ...strin foundCycle = true return } - foundCycle = swag.ContainsStrings(parentRefs, normalizedRef) // normalized windows url's are lower cased + foundCycle = stringutils.ContainsStrings(parentRefs, normalizedRef) // normalized windows url's are lower cased if foundCycle { r.context.circulars[normalizedRef] = true } return } -// Resolve resolves a reference against basePath and stores the result in target. -// -// Resolve is not in charge of following references: it only resolves ref by following its URL. -// -// If the schema the ref is referring to holds nested refs, Resolve doesn't resolve them. -// -// If basePath is an empty string, ref is resolved against the root schema stored in the schemaLoader struct -func (r *schemaLoader) Resolve(ref *Ref, target interface{}, basePath string) error { - return r.resolveRef(ref, target, basePath) -} - -func (r *schemaLoader) deref(input interface{}, parentRefs []string, basePath string) error { +func (r *schemaLoader) deref(input any, parentRefs []string, basePath string) error { var ref *Ref switch refable := input.(type) { case *Schema: @@ -263,18 +271,26 @@ func (r *schemaLoader) deref(input interface{}, parentRefs []string, basePath st } func (r *schemaLoader) shouldStopOnError(err error) bool { - if err != nil && !r.options.ContinueOnError { + if err == nil { + return false + } + + if errors.Is(err, ErrExpandTooManyNodes) { + // a blown expansion budget is a hard, document-level failure: it is a safeguard against + // resource exhaustion and is never suppressed by ContinueOnError. return true } - if err != nil { - log.Println(err) + if !r.options.ContinueOnError { + return true } + log.Println(err) + return false } -func (r *schemaLoader) setSchemaID(target interface{}, id, basePath string) (string, string) { +func (r *schemaLoader) setSchemaID(target any, id, basePath string) (string, string) { debugLog("schema has ID: %s", id) // handling the case when id is a folder @@ -306,11 +322,11 @@ func (r *schemaLoader) setSchemaID(target interface{}, id, basePath string) (str } func defaultSchemaLoader( - root interface{}, + root any, expandOptions *ExpandOptions, cache ResolutionCache, - context *resolverContext) *schemaLoader { - + context *resolverContext, +) *schemaLoader { if expandOptions == nil { expandOptions = &ExpandOptions{} } diff --git a/vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json b/vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json new file mode 100644 index 00000000000..bcbb84743e3 --- /dev/null +++ b/vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json @@ -0,0 +1,149 @@ +{ + "id": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "positiveInteger": { + "type": "integer", + "minimum": 0 + }, + "positiveIntegerDefault0": { + "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] + }, + "simpleTypes": { + "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1, + "uniqueItems": true + } + }, + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "$schema": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": {}, + "multipleOf": { + "type": "number", + "minimum": 0, + "exclusiveMinimum": true + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "boolean", + "default": false + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "boolean", + "default": false + }, + "maxLength": { "$ref": "#/definitions/positiveInteger" }, + "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { + "anyOf": [ + { "type": "boolean" }, + { "$ref": "#" } + ], + "default": {} + }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": {} + }, + "maxItems": { "$ref": "#/definitions/positiveInteger" }, + "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "maxProperties": { "$ref": "#/definitions/positiveInteger" }, + "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { + "anyOf": [ + { "type": "boolean" }, + { "$ref": "#" } + ], + "default": {} + }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "enum": { + "type": "array", + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "dependencies": { + "exclusiveMaximum": [ "maximum" ], + "exclusiveMinimum": [ "minimum" ] + }, + "default": {} +} diff --git a/vendor/github.com/go-openapi/spec/schemas/v2/schema.json b/vendor/github.com/go-openapi/spec/schemas/v2/schema.json new file mode 100644 index 00000000000..ebe10ed32d6 --- /dev/null +++ b/vendor/github.com/go-openapi/spec/schemas/v2/schema.json @@ -0,0 +1,1607 @@ +{ + "title": "A JSON Schema for Swagger 2.0 API.", + "id": "http://swagger.io/v2/schema.json#", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "required": [ + "swagger", + "info", + "paths" + ], + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "swagger": { + "type": "string", + "enum": [ + "2.0" + ], + "description": "The Swagger version of this document." + }, + "info": { + "$ref": "#/definitions/info" + }, + "host": { + "type": "string", + "pattern": "^[^{}/ :\\\\]+(?::\\d+)?$", + "description": "The host (name or ip) of the API. Example: 'swagger.io'" + }, + "basePath": { + "type": "string", + "pattern": "^/", + "description": "The base path to the API. Example: '/api'." + }, + "schemes": { + "$ref": "#/definitions/schemesList" + }, + "consumes": { + "description": "A list of MIME types accepted by the API.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "produces": { + "description": "A list of MIME types the API can produce.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "paths": { + "$ref": "#/definitions/paths" + }, + "definitions": { + "$ref": "#/definitions/definitions" + }, + "parameters": { + "$ref": "#/definitions/parameterDefinitions" + }, + "responses": { + "$ref": "#/definitions/responseDefinitions" + }, + "security": { + "$ref": "#/definitions/security" + }, + "securityDefinitions": { + "$ref": "#/definitions/securityDefinitions" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/tag" + }, + "uniqueItems": true + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + } + }, + "definitions": { + "info": { + "type": "object", + "description": "General information about the API.", + "required": [ + "version", + "title" + ], + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "title": { + "type": "string", + "description": "A unique and precise title of the API." + }, + "version": { + "type": "string", + "description": "A semantic version number of the API." + }, + "description": { + "type": "string", + "description": "A longer description of the API. Should be different from the title. GitHub Flavored Markdown is allowed." + }, + "termsOfService": { + "type": "string", + "description": "The terms of service for the API." + }, + "contact": { + "$ref": "#/definitions/contact" + }, + "license": { + "$ref": "#/definitions/license" + } + } + }, + "contact": { + "type": "object", + "description": "Contact information for the owners of the API.", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "The identifying name of the contact person/organization." + }, + "url": { + "type": "string", + "description": "The URL pointing to the contact information.", + "format": "uri" + }, + "email": { + "type": "string", + "description": "The email address of the contact person/organization.", + "format": "email" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "license": { + "type": "object", + "required": [ + "name" + ], + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "The name of the license type. It's encouraged to use an OSI compatible license." + }, + "url": { + "type": "string", + "description": "The URL pointing to the license.", + "format": "uri" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "paths": { + "type": "object", + "description": "Relative paths to the individual endpoints. They must be relative to the 'basePath'.", + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + }, + "^/": { + "$ref": "#/definitions/pathItem" + } + }, + "additionalProperties": false + }, + "definitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema" + }, + "description": "One or more JSON objects describing the schemas being consumed and produced by the API." + }, + "parameterDefinitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/parameter" + }, + "description": "One or more JSON representations for parameters" + }, + "responseDefinitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/response" + }, + "description": "One or more JSON representations for responses" + }, + "externalDocs": { + "type": "object", + "additionalProperties": false, + "description": "information about external documentation", + "required": [ + "url" + ], + "properties": { + "description": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "examples": { + "type": "object", + "additionalProperties": true + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the HTTP message." + }, + "operation": { + "type": "object", + "required": [ + "responses" + ], + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "summary": { + "type": "string", + "description": "A brief summary of the operation." + }, + "description": { + "type": "string", + "description": "A longer description of the operation, GitHub Flavored Markdown is allowed." + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + }, + "operationId": { + "type": "string", + "description": "A unique identifier of the operation." + }, + "produces": { + "description": "A list of MIME types the API can produce.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "consumes": { + "description": "A list of MIME types the API can consume.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "parameters": { + "$ref": "#/definitions/parametersList" + }, + "responses": { + "$ref": "#/definitions/responses" + }, + "schemes": { + "$ref": "#/definitions/schemesList" + }, + "deprecated": { + "type": "boolean", + "default": false + }, + "security": { + "$ref": "#/definitions/security" + } + } + }, + "pathItem": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "$ref": { + "type": "string" + }, + "get": { + "$ref": "#/definitions/operation" + }, + "put": { + "$ref": "#/definitions/operation" + }, + "post": { + "$ref": "#/definitions/operation" + }, + "delete": { + "$ref": "#/definitions/operation" + }, + "options": { + "$ref": "#/definitions/operation" + }, + "head": { + "$ref": "#/definitions/operation" + }, + "patch": { + "$ref": "#/definitions/operation" + }, + "parameters": { + "$ref": "#/definitions/parametersList" + } + } + }, + "responses": { + "type": "object", + "description": "Response objects names can either be any valid HTTP status code or 'default'.", + "minProperties": 1, + "additionalProperties": false, + "patternProperties": { + "^([0-9]{3})$|^(default)$": { + "$ref": "#/definitions/responseValue" + }, + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "not": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + } + }, + "responseValue": { + "oneOf": [ + { + "$ref": "#/definitions/response" + }, + { + "$ref": "#/definitions/jsonReference" + } + ] + }, + "response": { + "type": "object", + "required": [ + "description" + ], + "properties": { + "description": { + "type": "string" + }, + "schema": { + "oneOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/fileSchema" + } + ] + }, + "headers": { + "$ref": "#/definitions/headers" + }, + "examples": { + "$ref": "#/definitions/examples" + } + }, + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "headers": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/header" + } + }, + "header": { + "type": "object", + "additionalProperties": false, + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "integer", + "boolean", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "vendorExtension": { + "description": "Any property starting with x- is valid.", + "additionalProperties": true, + "additionalItems": true + }, + "bodyParameter": { + "type": "object", + "required": [ + "name", + "in", + "schema" + ], + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "body" + ] + }, + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "schema": { + "$ref": "#/definitions/schema" + } + }, + "additionalProperties": false + }, + "headerParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "header" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "queryParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "query" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "allowEmptyValue": { + "type": "boolean", + "default": false, + "description": "allows sending a parameter by name only or with an empty value." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormatWithMulti" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "formDataParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "formData" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "allowEmptyValue": { + "type": "boolean", + "default": false, + "description": "allows sending a parameter by name only or with an empty value." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array", + "file" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormatWithMulti" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "pathParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "required": [ + "required" + ], + "properties": { + "required": { + "type": "boolean", + "enum": [ + true + ], + "description": "Determines whether or not this parameter is required or optional." + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "path" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "nonBodyParameter": { + "type": "object", + "required": [ + "name", + "in", + "type" + ], + "oneOf": [ + { + "$ref": "#/definitions/headerParameterSubSchema" + }, + { + "$ref": "#/definitions/formDataParameterSubSchema" + }, + { + "$ref": "#/definitions/queryParameterSubSchema" + }, + { + "$ref": "#/definitions/pathParameterSubSchema" + } + ] + }, + "parameter": { + "oneOf": [ + { + "$ref": "#/definitions/bodyParameter" + }, + { + "$ref": "#/definitions/nonBodyParameter" + } + ] + }, + "schema": { + "type": "object", + "description": "A deterministic version of a JSON Schema object.", + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "$ref": { + "type": "string" + }, + "format": { + "type": "string" + }, + "title": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/title" + }, + "description": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/description" + }, + "default": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/default" + }, + "multipleOf": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" + }, + "maximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" + }, + "exclusiveMaximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" + }, + "minimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" + }, + "exclusiveMinimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" + }, + "maxLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "pattern": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" + }, + "maxItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "uniqueItems": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" + }, + "maxProperties": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minProperties": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "required": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" + }, + "enum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" + }, + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "type": "boolean" + } + ], + "default": {} + }, + "type": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/type" + }, + "items": { + "anyOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + } + ], + "default": {} + }, + "allOf": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + }, + "properties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema" + }, + "default": {} + }, + "discriminator": { + "type": "string" + }, + "readOnly": { + "type": "boolean", + "default": false + }, + "xml": { + "$ref": "#/definitions/xml" + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + }, + "example": {} + }, + "additionalProperties": false + }, + "fileSchema": { + "type": "object", + "description": "A deterministic version of a JSON Schema object.", + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "required": [ + "type" + ], + "properties": { + "format": { + "type": "string" + }, + "title": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/title" + }, + "description": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/description" + }, + "default": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/default" + }, + "required": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" + }, + "type": { + "type": "string", + "enum": [ + "file" + ] + }, + "readOnly": { + "type": "boolean", + "default": false + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + }, + "example": {} + }, + "additionalProperties": false + }, + "primitivesItems": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "integer", + "boolean", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "security": { + "type": "array", + "items": { + "$ref": "#/definitions/securityRequirement" + }, + "uniqueItems": true + }, + "securityRequirement": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "xml": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "prefix": { + "type": "string" + }, + "attribute": { + "type": "boolean", + "default": false + }, + "wrapped": { + "type": "boolean", + "default": false + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "tag": { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "securityDefinitions": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/basicAuthenticationSecurity" + }, + { + "$ref": "#/definitions/apiKeySecurity" + }, + { + "$ref": "#/definitions/oauth2ImplicitSecurity" + }, + { + "$ref": "#/definitions/oauth2PasswordSecurity" + }, + { + "$ref": "#/definitions/oauth2ApplicationSecurity" + }, + { + "$ref": "#/definitions/oauth2AccessCodeSecurity" + } + ] + } + }, + "basicAuthenticationSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "basic" + ] + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "apiKeySecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "name", + "in" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "apiKey" + ] + }, + "name": { + "type": "string" + }, + "in": { + "type": "string", + "enum": [ + "header", + "query" + ] + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2ImplicitSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "authorizationUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "implicit" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "authorizationUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2PasswordSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "tokenUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "password" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2ApplicationSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "tokenUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "application" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2AccessCodeSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "authorizationUrl", + "tokenUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "accessCode" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "authorizationUrl": { + "type": "string", + "format": "uri" + }, + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2Scopes": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "mediaTypeList": { + "type": "array", + "items": { + "$ref": "#/definitions/mimeType" + }, + "uniqueItems": true + }, + "parametersList": { + "type": "array", + "description": "The parameters needed to send a valid API call.", + "additionalItems": false, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/parameter" + }, + { + "$ref": "#/definitions/jsonReference" + } + ] + }, + "uniqueItems": true + }, + "schemesList": { + "type": "array", + "description": "The transfer protocol of the API.", + "items": { + "type": "string", + "enum": [ + "http", + "https", + "ws", + "wss" + ] + }, + "uniqueItems": true + }, + "collectionFormat": { + "type": "string", + "enum": [ + "csv", + "ssv", + "tsv", + "pipes" + ], + "default": "csv" + }, + "collectionFormatWithMulti": { + "type": "string", + "enum": [ + "csv", + "ssv", + "tsv", + "pipes", + "multi" + ], + "default": "csv" + }, + "title": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/title" + }, + "description": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/description" + }, + "default": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/default" + }, + "multipleOf": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" + }, + "maximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" + }, + "exclusiveMaximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" + }, + "minimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" + }, + "exclusiveMinimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" + }, + "maxLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "pattern": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" + }, + "maxItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "uniqueItems": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" + }, + "enum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" + }, + "jsonReference": { + "type": "object", + "required": [ + "$ref" + ], + "additionalProperties": false, + "properties": { + "$ref": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/spec/security_scheme.go b/vendor/github.com/go-openapi/spec/security_scheme.go index 9d0bdae9081..6d9019e749c 100644 --- a/vendor/github.com/go-openapi/spec/security_scheme.go +++ b/vendor/github.com/go-openapi/spec/security_scheme.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -18,7 +7,7 @@ import ( "encoding/json" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) const ( @@ -31,17 +20,17 @@ const ( accessCode = "accessCode" ) -// BasicAuth creates a basic auth security scheme +// BasicAuth creates a basic auth security scheme. func BasicAuth() *SecurityScheme { return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{Type: basic}} } -// APIKeyAuth creates an api key auth security scheme +// APIKeyAuth creates an api key auth security scheme. func APIKeyAuth(fieldName, valueSource string) *SecurityScheme { return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{Type: apiKey, Name: fieldName, In: valueSource}} } -// OAuth2Implicit creates an implicit flow oauth2 security scheme +// OAuth2Implicit creates an implicit flow oauth2 security scheme. func OAuth2Implicit(authorizationURL string) *SecurityScheme { return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ Type: oauth2, @@ -50,7 +39,7 @@ func OAuth2Implicit(authorizationURL string) *SecurityScheme { }} } -// OAuth2Password creates a password flow oauth2 security scheme +// OAuth2Password creates a password flow oauth2 security scheme. func OAuth2Password(tokenURL string) *SecurityScheme { return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ Type: oauth2, @@ -59,7 +48,7 @@ func OAuth2Password(tokenURL string) *SecurityScheme { }} } -// OAuth2Application creates an application flow oauth2 security scheme +// OAuth2Application creates an application flow oauth2 security scheme. func OAuth2Application(tokenURL string) *SecurityScheme { return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ Type: oauth2, @@ -68,7 +57,7 @@ func OAuth2Application(tokenURL string) *SecurityScheme { }} } -// OAuth2AccessToken creates an access token flow oauth2 security scheme +// OAuth2AccessToken creates an access token flow oauth2 security scheme. func OAuth2AccessToken(authorizationURL, tokenURL string) *SecurityScheme { return &SecurityScheme{SecuritySchemeProps: SecuritySchemeProps{ Type: oauth2, @@ -78,7 +67,7 @@ func OAuth2AccessToken(authorizationURL, tokenURL string) *SecurityScheme { }} } -// SecuritySchemeProps describes a swagger security scheme in the securityDefinitions section +// SecuritySchemeProps describes a swagger security scheme in the securityDefinitions section. type SecuritySchemeProps struct { Description string `json:"description,omitempty"` Type string `json:"type"` @@ -90,7 +79,7 @@ type SecuritySchemeProps struct { Scopes map[string]string `json:"scopes,omitempty"` // oauth2 } -// AddScope adds a scope to this security scheme +// AddScope adds a scope to this security scheme. func (s *SecuritySchemeProps) AddScope(scope, description string) { if s.Scopes == nil { s.Scopes = make(map[string]string) @@ -108,8 +97,8 @@ type SecurityScheme struct { SecuritySchemeProps } -// JSONLookup implements an interface to customize json pointer lookup -func (s SecurityScheme) JSONLookup(token string) (interface{}, error) { +// JSONLookup implements an interface to customize json pointer lookup. +func (s SecurityScheme) JSONLookup(token string) (any, error) { if ex, ok := s.Extensions[token]; ok { return &ex, nil } @@ -118,7 +107,7 @@ func (s SecurityScheme) JSONLookup(token string) (interface{}, error) { return r, err } -// MarshalJSON marshal this to JSON +// MarshalJSON marshal this to JSON. func (s SecurityScheme) MarshalJSON() ([]byte, error) { var ( b1 []byte @@ -158,10 +147,10 @@ func (s SecurityScheme) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2), nil + return jsonutils.ConcatJSON(b1, b2), nil } -// UnmarshalJSON marshal this from JSON +// UnmarshalJSON marshal this from JSON. func (s *SecurityScheme) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &s.SecuritySchemeProps); err != nil { return err diff --git a/vendor/github.com/go-openapi/spec/spec.go b/vendor/github.com/go-openapi/spec/spec.go index 7d38b6e6251..4eba04b2d1a 100644 --- a/vendor/github.com/go-openapi/spec/spec.go +++ b/vendor/github.com/go-openapi/spec/spec.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -24,13 +13,13 @@ import ( //go:generate perl -pi -e s,Json,JSON,g bindata.go const ( - // SwaggerSchemaURL the url for the swagger 2.0 schema to validate specs + // SwaggerSchemaURL the url for the swagger 2.0 schema to validate specs. SwaggerSchemaURL = "http://swagger.io/v2/schema.json#" - // JSONSchemaURL the url for the json schema schema + // JSONSchemaURL the url for the json schema. JSONSchemaURL = "http://json-schema.org/draft-04/schema#" ) -// MustLoadJSONSchemaDraft04 panics when Swagger20Schema returns an error +// MustLoadJSONSchemaDraft04 panics when Swagger20Schema returns an error. func MustLoadJSONSchemaDraft04() *Schema { d, e := JSONSchemaDraft04() if e != nil { @@ -39,9 +28,9 @@ func MustLoadJSONSchemaDraft04() *Schema { return d } -// JSONSchemaDraft04 loads the json schema document for json shema draft04 +// JSONSchemaDraft04 loads the json schema document for json schema draft04. func JSONSchemaDraft04() (*Schema, error) { - b, err := Asset("jsonschema-draft-04.json") + b, err := jsonschemaDraft04JSONBytes() if err != nil { return nil, err } @@ -53,7 +42,7 @@ func JSONSchemaDraft04() (*Schema, error) { return schema, nil } -// MustLoadSwagger20Schema panics when Swagger20Schema returns an error +// MustLoadSwagger20Schema panics when Swagger20Schema returns an error. func MustLoadSwagger20Schema() *Schema { d, e := Swagger20Schema() if e != nil { @@ -62,10 +51,9 @@ func MustLoadSwagger20Schema() *Schema { return d } -// Swagger20Schema loads the swagger 2.0 schema from the embedded assets +// Swagger20Schema loads the swagger 2.0 schema from the embedded assets. func Swagger20Schema() (*Schema, error) { - - b, err := Asset("v2/schema.json") + b, err := v2SchemaJSONBytes() if err != nil { return nil, err } diff --git a/vendor/github.com/go-openapi/spec/swagger.go b/vendor/github.com/go-openapi/spec/swagger.go index 44722ffd5ad..dbe32db8a33 100644 --- a/vendor/github.com/go-openapi/spec/swagger.go +++ b/vendor/github.com/go-openapi/spec/swagger.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -19,10 +8,11 @@ import ( "encoding/gob" "encoding/json" "fmt" + "slices" "strconv" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) // Swagger this is the root document object for the API specification. @@ -35,8 +25,8 @@ type Swagger struct { SwaggerProps } -// JSONLookup look up a value by the json property name -func (s Swagger) JSONLookup(token string) (interface{}, error) { +// JSONLookup look up a value by the json property name. +func (s Swagger) JSONLookup(token string) (any, error) { if ex, ok := s.Extensions[token]; ok { return &ex, nil } @@ -44,7 +34,7 @@ func (s Swagger) JSONLookup(token string) (interface{}, error) { return r, err } -// MarshalJSON marshals this swagger structure to json +// MarshalJSON marshals this swagger structure to json. func (s Swagger) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(s.SwaggerProps) if err != nil { @@ -54,10 +44,10 @@ func (s Swagger) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2), nil + return jsonutils.ConcatJSON(b1, b2), nil } -// UnmarshalJSON unmarshals a swagger spec from json +// UnmarshalJSON unmarshals a swagger spec from json. func (s *Swagger) UnmarshalJSON(data []byte) error { var sw Swagger if err := json.Unmarshal(data, &sw.SwaggerProps); err != nil { @@ -70,7 +60,7 @@ func (s *Swagger) UnmarshalJSON(data []byte) error { return nil } -// GobEncode provides a safe gob encoder for Swagger, including extensions +// GobEncode provides a safe gob encoder for Swagger, including extensions. func (s Swagger) GobEncode() ([]byte, error) { var b bytes.Buffer raw := struct { @@ -84,7 +74,7 @@ func (s Swagger) GobEncode() ([]byte, error) { return b.Bytes(), err } -// GobDecode provides a safe gob decoder for Swagger, including extensions +// GobDecode provides a safe gob decoder for Swagger, including extensions. func (s *Swagger) GobDecode(b []byte) error { var raw struct { Props SwaggerProps @@ -105,7 +95,7 @@ func (s *Swagger) GobDecode(b []byte) error { // NOTE: validation rules // - the scheme, when present must be from [http, https, ws, wss] // - BasePath must start with a leading "/" -// - Paths is required +// - Paths is required. type SwaggerProps struct { ID string `json:"id,omitempty"` Consumes []string `json:"consumes,omitempty"` @@ -136,7 +126,7 @@ type gobSwaggerPropsAlias struct { SecurityIsEmpty bool } -// GobEncode provides a safe gob encoder for SwaggerProps, including empty security requirements +// GobEncode provides a safe gob encoder for SwaggerProps, including empty security requirements. func (o SwaggerProps) GobEncode() ([]byte, error) { raw := gobSwaggerPropsAlias{ Alias: (*swaggerPropsAlias)(&o), @@ -181,7 +171,7 @@ func (o SwaggerProps) GobEncode() ([]byte, error) { return b.Bytes(), err } -// GobDecode provides a safe gob decoder for SwaggerProps, including empty security requirements +// GobDecode provides a safe gob decoder for SwaggerProps, including empty security requirements. func (o *SwaggerProps) GobDecode(b []byte) error { var raw gobSwaggerPropsAlias @@ -217,17 +207,17 @@ func (o *SwaggerProps) GobDecode(b []byte) error { return nil } -// Dependencies represent a dependencies property +// Dependencies represent a dependencies property. type Dependencies map[string]SchemaOrStringArray -// SchemaOrBool represents a schema or boolean value, is biased towards true for the boolean property +// SchemaOrBool represents a schema or boolean value, is biased towards true for the boolean property. type SchemaOrBool struct { Allows bool Schema *Schema } -// JSONLookup implements an interface to customize json pointer lookup -func (s SchemaOrBool) JSONLookup(token string) (interface{}, error) { +// JSONLookup implements an interface to customize json pointer lookup. +func (s SchemaOrBool) JSONLookup(token string) (any, error) { if token == "allows" { return s.Allows, nil } @@ -235,10 +225,12 @@ func (s SchemaOrBool) JSONLookup(token string) (interface{}, error) { return r, err } -var jsTrue = []byte("true") -var jsFalse = []byte("false") +var ( + jsTrue = []byte("true") //nolint:gochecknoglobals // constant-like byte slices for JSON marshaling + jsFalse = []byte("false") //nolint:gochecknoglobals // constant-like byte slices for JSON marshaling +) -// MarshalJSON convert this object to JSON +// MarshalJSON convert this object to JSON. func (s SchemaOrBool) MarshalJSON() ([]byte, error) { if s.Schema != nil { return json.Marshal(s.Schema) @@ -250,10 +242,10 @@ func (s SchemaOrBool) MarshalJSON() ([]byte, error) { return jsTrue, nil } -// UnmarshalJSON converts this bool or schema object from a JSON structure +// UnmarshalJSON converts this bool or schema object from a JSON structure. func (s *SchemaOrBool) UnmarshalJSON(data []byte) error { var nw SchemaOrBool - if len(data) >= 4 { + if len(data) > 0 { if data[0] == '{' { var sch Schema if err := json.Unmarshal(data, &sch); err != nil { @@ -261,25 +253,25 @@ func (s *SchemaOrBool) UnmarshalJSON(data []byte) error { } nw.Schema = &sch } - nw.Allows = !(data[0] == 'f' && data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e') + nw.Allows = !bytes.Equal(data, []byte("false")) } *s = nw return nil } -// SchemaOrStringArray represents a schema or a string array +// SchemaOrStringArray represents a schema or a string array. type SchemaOrStringArray struct { Schema *Schema Property []string } -// JSONLookup implements an interface to customize json pointer lookup -func (s SchemaOrStringArray) JSONLookup(token string) (interface{}, error) { +// JSONLookup implements an interface to customize json pointer lookup. +func (s SchemaOrStringArray) JSONLookup(token string) (any, error) { r, _, err := jsonpointer.GetForToken(s.Schema, token) return r, err } -// MarshalJSON converts this schema object or array into JSON structure +// MarshalJSON converts this schema object or array into JSON structure. func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) { if len(s.Property) > 0 { return json.Marshal(s.Property) @@ -290,7 +282,7 @@ func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) { return []byte("null"), nil } -// UnmarshalJSON converts this schema object or array from a JSON structure +// UnmarshalJSON converts this schema object or array from a JSON structure. func (s *SchemaOrStringArray) UnmarshalJSON(data []byte) error { var first byte if len(data) > 1 { @@ -328,21 +320,16 @@ type Definitions map[string]Schema type SecurityDefinitions map[string]*SecurityScheme // StringOrArray represents a value that can either be a string -// or an array of strings. Mainly here for serialization purposes +// or an array of strings. Mainly here for serialization purposes. type StringOrArray []string -// Contains returns true when the value is contained in the slice +// Contains returns true when the value is contained in the slice. func (s StringOrArray) Contains(value string) bool { - for _, str := range s { - if str == value { - return true - } - } - return false + return slices.Contains(s, value) } -// JSONLookup implements an interface to customize json pointer lookup -func (s SchemaOrArray) JSONLookup(token string) (interface{}, error) { +// JSONLookup implements an interface to customize json pointer lookup. +func (s SchemaOrArray) JSONLookup(token string) (any, error) { if _, err := strconv.Atoi(token); err == nil { r, _, err := jsonpointer.GetForToken(s.Schemas, token) return r, err @@ -351,7 +338,7 @@ func (s SchemaOrArray) JSONLookup(token string) (interface{}, error) { return r, err } -// UnmarshalJSON unmarshals this string or array object from a JSON array or JSON string +// UnmarshalJSON unmarshals this string or array object from a JSON array or JSON string. func (s *StringOrArray) UnmarshalJSON(data []byte) error { var first byte if len(data) > 1 { @@ -367,7 +354,7 @@ func (s *StringOrArray) UnmarshalJSON(data []byte) error { return nil } - var single interface{} + var single any if err := json.Unmarshal(data, &single); err != nil { return err } @@ -379,11 +366,11 @@ func (s *StringOrArray) UnmarshalJSON(data []byte) error { *s = StringOrArray([]string{v}) return nil default: - return fmt.Errorf("only string or array is allowed, not %T", single) + return fmt.Errorf("only string or array is allowed, not %T: %w", single, ErrSpec) } } -// MarshalJSON converts this string or array to a JSON array or JSON string +// MarshalJSON converts this string or array to a JSON array or JSON string. func (s StringOrArray) MarshalJSON() ([]byte, error) { if len(s) == 1 { return json.Marshal([]string(s)[0]) @@ -392,13 +379,13 @@ func (s StringOrArray) MarshalJSON() ([]byte, error) { } // SchemaOrArray represents a value that can either be a Schema -// or an array of Schema. Mainly here for serialization purposes +// or an array of Schema. Mainly here for serialization purposes. type SchemaOrArray struct { Schema *Schema Schemas []Schema } -// Len returns the number of schemas in this property +// Len returns the number of schemas in this property. func (s SchemaOrArray) Len() int { if s.Schema != nil { return 1 @@ -406,7 +393,7 @@ func (s SchemaOrArray) Len() int { return len(s.Schemas) } -// ContainsType returns true when one of the schemas is of the specified type +// ContainsType returns true when one of the schemas is of the specified type. func (s *SchemaOrArray) ContainsType(name string) bool { if s.Schema != nil { return s.Schema.Type != nil && s.Schema.Type.Contains(name) @@ -414,7 +401,7 @@ func (s *SchemaOrArray) ContainsType(name string) bool { return false } -// MarshalJSON converts this schema object or array into JSON structure +// MarshalJSON converts this schema object or array into JSON structure. func (s SchemaOrArray) MarshalJSON() ([]byte, error) { if len(s.Schemas) > 0 { return json.Marshal(s.Schemas) @@ -422,7 +409,7 @@ func (s SchemaOrArray) MarshalJSON() ([]byte, error) { return json.Marshal(s.Schema) } -// UnmarshalJSON converts this schema object or array from a JSON structure +// UnmarshalJSON converts this schema object or array from a JSON structure. func (s *SchemaOrArray) UnmarshalJSON(data []byte) error { var nw SchemaOrArray var first byte diff --git a/vendor/github.com/go-openapi/spec/tag.go b/vendor/github.com/go-openapi/spec/tag.go index faa3d3de1eb..af3fb0a4e89 100644 --- a/vendor/github.com/go-openapi/spec/tag.go +++ b/vendor/github.com/go-openapi/spec/tag.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -18,21 +7,16 @@ import ( "encoding/json" "github.com/go-openapi/jsonpointer" - "github.com/go-openapi/swag" + "github.com/go-openapi/swag/jsonutils" ) -// TagProps describe a tag entry in the top level tags section of a swagger spec +// TagProps describe a tag entry in the top level tags section of a swagger spec. type TagProps struct { Description string `json:"description,omitempty"` Name string `json:"name,omitempty"` ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"` } -// NewTag creates a new tag -func NewTag(name, description string, externalDocs *ExternalDocumentation) Tag { - return Tag{TagProps: TagProps{Description: description, Name: name, ExternalDocs: externalDocs}} -} - // Tag allows adding meta data to a single tag that is used by the // [Operation Object](http://goo.gl/8us55a#operationObject). // It is not mandatory to have a Tag Object per tag used there. @@ -43,8 +27,13 @@ type Tag struct { TagProps } -// JSONLookup implements an interface to customize json pointer lookup -func (t Tag) JSONLookup(token string) (interface{}, error) { +// NewTag creates a new tag. +func NewTag(name, description string, externalDocs *ExternalDocumentation) Tag { + return Tag{TagProps: TagProps{Description: description, Name: name, ExternalDocs: externalDocs}} +} + +// JSONLookup implements an interface to customize json pointer lookup. +func (t Tag) JSONLookup(token string) (any, error) { if ex, ok := t.Extensions[token]; ok { return &ex, nil } @@ -53,7 +42,7 @@ func (t Tag) JSONLookup(token string) (interface{}, error) { return r, err } -// MarshalJSON marshal this to JSON +// MarshalJSON marshal this to JSON. func (t Tag) MarshalJSON() ([]byte, error) { b1, err := json.Marshal(t.TagProps) if err != nil { @@ -63,10 +52,10 @@ func (t Tag) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return swag.ConcatJSON(b1, b2), nil + return jsonutils.ConcatJSON(b1, b2), nil } -// UnmarshalJSON marshal this from JSON +// UnmarshalJSON marshal this from JSON. func (t *Tag) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &t.TagProps); err != nil { return err diff --git a/vendor/github.com/go-openapi/spec/url_go19.go b/vendor/github.com/go-openapi/spec/url_go19.go new file mode 100644 index 00000000000..8d0c81acd68 --- /dev/null +++ b/vendor/github.com/go-openapi/spec/url_go19.go @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package spec + +import "net/url" + +func parseURL(s string) (*url.URL, error) { + u, err := url.Parse(s) + if err == nil { + u.OmitHost = false + } + return u, err +} diff --git a/vendor/github.com/go-openapi/spec/validations.go b/vendor/github.com/go-openapi/spec/validations.go index 6360a8ea774..a82c2ffe138 100644 --- a/vendor/github.com/go-openapi/spec/validations.go +++ b/vendor/github.com/go-openapi/spec/validations.go @@ -1,19 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package spec -// CommonValidations describe common JSON-schema validations +// CommonValidations describe common JSON-schema validations. type CommonValidations struct { - Maximum *float64 `json:"maximum,omitempty"` - ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"` - Minimum *float64 `json:"minimum,omitempty"` - ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"` - MaxLength *int64 `json:"maxLength,omitempty"` - MinLength *int64 `json:"minLength,omitempty"` - Pattern string `json:"pattern,omitempty"` - MaxItems *int64 `json:"maxItems,omitempty"` - MinItems *int64 `json:"minItems,omitempty"` - UniqueItems bool `json:"uniqueItems,omitempty"` - MultipleOf *float64 `json:"multipleOf,omitempty"` - Enum []interface{} `json:"enum,omitempty"` + Maximum *float64 `json:"maximum,omitempty"` + ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"` + Minimum *float64 `json:"minimum,omitempty"` + ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"` + MaxLength *int64 `json:"maxLength,omitempty"` + MinLength *int64 `json:"minLength,omitempty"` + Pattern string `json:"pattern,omitempty"` + MaxItems *int64 `json:"maxItems,omitempty"` + MinItems *int64 `json:"minItems,omitempty"` + UniqueItems bool `json:"uniqueItems,omitempty"` + MultipleOf *float64 `json:"multipleOf,omitempty"` + Enum []any `json:"enum,omitempty"` } // SetValidations defines all validations for a simple schema. @@ -37,12 +40,12 @@ func (v *CommonValidations) SetValidations(val SchemaValidations) { type clearedValidation struct { Validation string - Value interface{} + Value any } type clearedValidations []clearedValidation -func (c clearedValidations) apply(cbs []func(string, interface{})) { +func (c clearedValidations) apply(cbs []func(string, any)) { for _, cb := range cbs { for _, cleared := range c { cb(cleared.Validation, cleared.Value) @@ -53,8 +56,9 @@ func (c clearedValidations) apply(cbs []func(string, interface{})) { // ClearNumberValidations clears all number validations. // // Some callbacks may be set by the caller to capture changed values. -func (v *CommonValidations) ClearNumberValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 5) +func (v *CommonValidations) ClearNumberValidations(cbs ...func(string, any)) { + const maxNumberValidations = 5 + done := make(clearedValidations, 0, maxNumberValidations) defer func() { done.apply(cbs) }() @@ -84,8 +88,9 @@ func (v *CommonValidations) ClearNumberValidations(cbs ...func(string, interface // ClearStringValidations clears all string validations. // // Some callbacks may be set by the caller to capture changed values. -func (v *CommonValidations) ClearStringValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 3) +func (v *CommonValidations) ClearStringValidations(cbs ...func(string, any)) { + const maxStringValidations = 3 + done := make(clearedValidations, 0, maxStringValidations) defer func() { done.apply(cbs) }() @@ -107,8 +112,9 @@ func (v *CommonValidations) ClearStringValidations(cbs ...func(string, interface // ClearArrayValidations clears all array validations. // // Some callbacks may be set by the caller to capture changed values. -func (v *CommonValidations) ClearArrayValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 3) +func (v *CommonValidations) ClearArrayValidations(cbs ...func(string, any)) { + const maxArrayValidations = 3 + done := make(clearedValidations, 0, maxArrayValidations) defer func() { done.apply(cbs) }() @@ -137,22 +143,22 @@ func (v CommonValidations) Validations() SchemaValidations { } } -// HasNumberValidations indicates if the validations are for numbers or integers +// HasNumberValidations indicates if the validations are for numbers or integers. func (v CommonValidations) HasNumberValidations() bool { return v.Maximum != nil || v.Minimum != nil || v.MultipleOf != nil } -// HasStringValidations indicates if the validations are for strings +// HasStringValidations indicates if the validations are for strings. func (v CommonValidations) HasStringValidations() bool { return v.MaxLength != nil || v.MinLength != nil || v.Pattern != "" } -// HasArrayValidations indicates if the validations are for arrays +// HasArrayValidations indicates if the validations are for arrays. func (v CommonValidations) HasArrayValidations() bool { return v.MaxItems != nil || v.MinItems != nil || v.UniqueItems } -// HasEnum indicates if the validation includes some enum constraint +// HasEnum indicates if the validation includes some enum constraint. func (v CommonValidations) HasEnum() bool { return len(v.Enum) > 0 } @@ -160,7 +166,7 @@ func (v CommonValidations) HasEnum() bool { // SchemaValidations describes the validation properties of a schema // // NOTE: at this moment, this is not embedded in SchemaProps because this would induce a breaking change -// in the exported members: all initializers using litterals would fail. +// in the exported members: all initializers using literals would fail. type SchemaValidations struct { CommonValidations @@ -169,12 +175,12 @@ type SchemaValidations struct { MinProperties *int64 `json:"minProperties,omitempty"` } -// HasObjectValidations indicates if the validations are for objects +// HasObjectValidations indicates if the validations are for objects. func (v SchemaValidations) HasObjectValidations() bool { return v.MaxProperties != nil || v.MinProperties != nil || v.PatternProperties != nil } -// SetValidations for schema validations +// SetValidations for schema validations. func (v *SchemaValidations) SetValidations(val SchemaValidations) { v.CommonValidations.SetValidations(val) v.PatternProperties = val.PatternProperties @@ -182,7 +188,7 @@ func (v *SchemaValidations) SetValidations(val SchemaValidations) { v.MinProperties = val.MinProperties } -// Validations for a schema +// Validations for a schema. func (v SchemaValidations) Validations() SchemaValidations { val := v.CommonValidations.Validations() val.PatternProperties = v.PatternProperties @@ -194,8 +200,9 @@ func (v SchemaValidations) Validations() SchemaValidations { // ClearObjectValidations returns a clone of the validations with all object validations cleared. // // Some callbacks may be set by the caller to capture changed values. -func (v *SchemaValidations) ClearObjectValidations(cbs ...func(string, interface{})) { - done := make(clearedValidations, 0, 3) +func (v *SchemaValidations) ClearObjectValidations(cbs ...func(string, any)) { + const maxObjectValidations = 3 + done := make(clearedValidations, 0, maxObjectValidations) defer func() { done.apply(cbs) }() diff --git a/vendor/github.com/go-openapi/spec/xml_object.go b/vendor/github.com/go-openapi/spec/xml_object.go index 945a46703d5..07f7ef8ccd7 100644 --- a/vendor/github.com/go-openapi/spec/xml_object.go +++ b/vendor/github.com/go-openapi/spec/xml_object.go @@ -1,16 +1,5 @@ -// Copyright 2015 go-swagger maintainers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package spec @@ -25,43 +14,43 @@ type XMLObject struct { Wrapped bool `json:"wrapped,omitempty"` } -// WithName sets the xml name for the object +// WithName sets the xml name for the object. func (x *XMLObject) WithName(name string) *XMLObject { x.Name = name return x } -// WithNamespace sets the xml namespace for the object +// WithNamespace sets the xml namespace for the object. func (x *XMLObject) WithNamespace(namespace string) *XMLObject { x.Namespace = namespace return x } -// WithPrefix sets the xml prefix for the object +// WithPrefix sets the xml prefix for the object. func (x *XMLObject) WithPrefix(prefix string) *XMLObject { x.Prefix = prefix return x } -// AsAttribute flags this object as xml attribute +// AsAttribute flags this object as xml attribute. func (x *XMLObject) AsAttribute() *XMLObject { x.Attribute = true return x } -// AsElement flags this object as an xml node +// AsElement flags this object as an xml node. func (x *XMLObject) AsElement() *XMLObject { x.Attribute = false return x } -// AsWrapped flags this object as wrapped, this is mostly useful for array types +// AsWrapped flags this object as wrapped, this is mostly useful for array types. func (x *XMLObject) AsWrapped() *XMLObject { x.Wrapped = true return x } -// AsUnwrapped flags this object as an xml node +// AsUnwrapped flags this object as an xml node. func (x *XMLObject) AsUnwrapped() *XMLObject { x.Wrapped = false return x diff --git a/vendor/github.com/go-openapi/strfmt/.gitignore b/vendor/github.com/go-openapi/strfmt/.gitignore index bbdffea78a0..20c4e0fa048 100644 --- a/vendor/github.com/go-openapi/strfmt/.gitignore +++ b/vendor/github.com/go-openapi/strfmt/.gitignore @@ -4,3 +4,4 @@ .env .mcp.json go.work.sum +.worktrees diff --git a/vendor/github.com/go-openapi/strfmt/.golangci.yml b/vendor/github.com/go-openapi/strfmt/.golangci.yml index 8a3b3bff7c4..31480c7138a 100644 --- a/vendor/github.com/go-openapi/strfmt/.golangci.yml +++ b/vendor/github.com/go-openapi/strfmt/.golangci.yml @@ -6,6 +6,8 @@ linters: - depguard - funlen - gomoddirectives + - gomodguard + - gomodguard_v2 - godox - exhaustruct - nlreturn diff --git a/vendor/github.com/go-openapi/strfmt/CONTRIBUTORS.md b/vendor/github.com/go-openapi/strfmt/CONTRIBUTORS.md index 4aa4fcb54fc..fa17ff3111c 100644 --- a/vendor/github.com/go-openapi/strfmt/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/strfmt/CONTRIBUTORS.md @@ -4,12 +4,12 @@ | Total Contributors | Total Contributions | | --- | --- | -| 40 | 239 | +| 41 | 243 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | | @casualjim | 88 | | -| @fredbi | 71 | | +| @fredbi | 74 | | | @youyuanwu | 13 | | | @jlambatl | 9 | | | @GlenDC | 5 | | @@ -26,6 +26,7 @@ | @bg451 | 2 | | | @aleksandr-vin | 2 | | | @ujjwalsh | 1 | | +| @patchwright | 1 | | | @kenjones-cisco | 1 | | | @jwalter1-quest | 1 | | | @ccoVeille | 1 | | diff --git a/vendor/github.com/go-openapi/strfmt/README.md b/vendor/github.com/go-openapi/strfmt/README.md index 4afef43733d..15ee0e5826d 100644 --- a/vendor/github.com/go-openapi/strfmt/README.md +++ b/vendor/github.com/go-openapi/strfmt/README.md @@ -67,7 +67,7 @@ It also provides convenient extensions to go-openapi users. - [x] go-openapi custom format extensions - bsonobjectid (BSON objectID) - creditcard - - duration (e.g. "3 weeks", "1ms") + - duration (e.g. "3 weeks", "1ms") (aka "duration-human") - hexcolor (e.g. "#FFFFFF") - isbn, isbn10, isbn13 - mac (e.g "01:02:03:04:05:06") @@ -76,11 +76,26 @@ It also provides convenient extensions to go-openapi users. - uuid, uuid3, uuid4, uuid5, uuid7 - cidr (e.g. "192.0.2.1/24", "2001:db8:a0b:12f0::1/32") - ulid (e.g. "00000PP9HGSBSSDZ1JTEXBJ0PW", [spec](https://github.com/ulid/spec)) +- [x] JSON-schema draft 2020 formats + - duration-iso8601 B(e.g. "P2W") > NOTE: as the name stands for, this package is intended to support string formatting only. > It does not provide validation for numerical values with swagger format extension for JSON types "number" or > "integer" (e.g. float, double, int32...). +## Durations + +We have 2 very different definitions of the "duration" format: the "human-readable" duration that used to be just "duration", +and the new "duration-iso8601". There is no "dual" parser that accepts both formats: types are specialized. + +To clarify the situation, a new alias for the duration format is introduced "duration-human" (e.g. "1 ms"), as opposed to +"duration-iso8601". + +The `Default` format registry wires "duration-human" as the default mapping for "duration" +(preexisting behavior, no breaking change - aligned with Swagger 2.0 which did not define "duration"). + +A new `JSONSchema2020` registry wires "duration-iso8601" as the default mapping for "duration". + ### Type conversion All types defined here are stringers and may be converted to strings with `.String()`. @@ -104,6 +119,7 @@ List of defined types: - Date - DateTime - Duration +- DurationISO8601 and `ISODuration[P ISODurationPolicy]` (for optional behavior) - Email - HexColor - Hostname diff --git a/vendor/github.com/go-openapi/strfmt/bson.go b/vendor/github.com/go-openapi/strfmt/bson.go index 16a83f64086..b0c05d83bcc 100644 --- a/vendor/github.com/go-openapi/strfmt/bson.go +++ b/vendor/github.com/go-openapi/strfmt/bson.go @@ -10,11 +10,6 @@ import ( "fmt" ) -func init() { //nolint:gochecknoinits // registers bsonobjectid format in the default registry - var id ObjectId - Default.Add("bsonobjectid", &id, IsBSONObjectID) -} - // IsBSONObjectID returns true when the string is a valid BSON [ObjectId]. func IsBSONObjectID(str string) bool { _, err := objectIDFromHex(str) diff --git a/vendor/github.com/go-openapi/strfmt/country.go b/vendor/github.com/go-openapi/strfmt/country.go new file mode 100644 index 00000000000..39aeb3d7861 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/country.go @@ -0,0 +1,173 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package strfmt + +import ( + "database/sql/driver" + "encoding/json" + "fmt" + + "github.com/go-openapi/strfmt/internal/countries" +) + +// Country represents an ISO 3166 country alpha-3 or alpha-2 code as a string format. +// +// swagger:strfmt country. +type Country struct { + countries.Country + + l int +} + +const ( + alpha2Len = 2 + alpha3Len = 3 +) + +// IsCountry checks if a string is a valid ISO 3166 country format. +func IsCountry(str string) bool { + _, err := ParseCountry(str) + + return err == nil +} + +// ParseCountry parses a string that represents a valid [Country]. +func ParseCountry(str string) (Country, error) { + l := len(str) + switch l { + case alpha3Len: + c, ok := countries.CountriesISO3[str] + if !ok { + return Country{}, fmt.Errorf("unrecognized strfmt.Country %q: %w", str, ErrFormat) + } + + return Country{Country: c, l: alpha3Len}, nil + case alpha2Len: + c, ok := countries.CountriesISO2[str] + if !ok { + return Country{}, fmt.Errorf("unrecognized strfmt.Country %q: %w", str, ErrFormat) + } + + return Country{Country: c, l: alpha2Len}, nil + default: + return Country{}, fmt.Errorf("invalid length for strfmt.Country in: %q: %w", str, ErrFormat) + } +} + +// MarshalText returns this instance into text. +func (u Country) MarshalText() ([]byte, error) { + return []byte(u.String()), nil +} + +// UnmarshalText hydrates this instance from text. +func (u *Country) UnmarshalText(data []byte) error { // validation is performed later on + c, err := ParseCountry(string(data)) + if err != nil { + return err + } + + *u = c + + return nil +} + +// Scan read a value from a database driver. +func (u *Country) Scan(raw any) error { + switch v := raw.(type) { + case []byte: + c, err := ParseCountry(string(v)) + if err != nil { + return err + } + *u = c + case string: + c, err := ParseCountry(v) + if err != nil { + return err + } + *u = c + default: + return fmt.Errorf("cannot sql.Scan() strfmt.Country from: %#v: %w", v, ErrFormat) + } + + return nil +} + +// Value converts a value to a database driver value. +func (u Country) Value() (driver.Value, error) { + return driver.Value(u.String()), nil +} + +func (u Country) String() string { + switch u.l { + case alpha3Len: + return u.ISOAlpha3 + case alpha2Len: + return u.ISOAlpha2 + default: + return "" + } +} + +// MarshalJSON returns the [Country] as JSON. +func (u Country) MarshalJSON() ([]byte, error) { + return json.Marshal(u.String()) +} + +// UnmarshalJSON sets the [Country] from JSON. +func (u *Country) UnmarshalJSON(data []byte) error { + if string(data) == jsonNull { + return nil + } + var ustr string + if err := json.Unmarshal(data, &ustr); err != nil { + return err + } + + c, err := ParseCountry(ustr) + if err != nil { + return err + } + + *u = c + + return nil +} + +// DeepCopyInto copies the receiver and writes its value into out. +func (u *Country) DeepCopyInto(out *Country) { + *out = *u +} + +// DeepCopy copies the receiver into a new [Country]. +func (u *Country) DeepCopy() *Country { + if u == nil { + return nil + } + + out := new(Country) + u.DeepCopyInto(out) + + return out +} + +// GobEncode implements the gob.GobEncoder interface. +func (u Country) GobEncode() ([]byte, error) { + return u.MarshalText() +} + +// GobDecode implements the gob.GobDecoder interface. +func (u *Country) GobDecode(data []byte) error { + return u.UnmarshalText(data) +} + +// MarshalBinary implements the encoding.[encoding.BinaryMarshaler] interface. +func (u Country) MarshalBinary() ([]byte, error) { + return u.MarshalText() +} + +// UnmarshalBinary implements the encoding.[encoding.BinaryUnmarshaler] interface. +func (u *Country) UnmarshalBinary(data []byte) error { + return u.UnmarshalText(data) +} diff --git a/vendor/github.com/go-openapi/strfmt/currency.go b/vendor/github.com/go-openapi/strfmt/currency.go new file mode 100644 index 00000000000..7af115663f2 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/currency.go @@ -0,0 +1,146 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package strfmt + +import ( + "database/sql/driver" + "encoding/json" + "fmt" + + "golang.org/x/text/currency" +) + +// Currency represents an ISO 4217 currency alpha-3 code as a string format. +// +// # Implementation +// +// golang.org/x/text/currency +// +// swagger:strfmt currency. +type Currency struct { + currency.Unit +} + +// IsCurrency checks if a string is a valid currency format. +func IsCurrency(str string) bool { + _, err := ParseCurrency(str) + + return err == nil +} + +// ParseCurrency parses a string that represents a valid [Currency]. +func ParseCurrency(str string) (Currency, error) { + cur, err := currency.ParseISO(str) + + return Currency{Unit: cur}, err +} + +// MarshalText returns this instance into text. +func (u Currency) MarshalText() ([]byte, error) { + return []byte(u.Unit.String()), nil +} + +// UnmarshalText hydrates this instance from text. +func (u *Currency) UnmarshalText(data []byte) error { // validation is performed later on + cur, err := ParseCurrency(string(data)) + if err != nil { + return err + } + *u = cur + + return nil +} + +// Scan read a value from a database driver. +func (u *Currency) Scan(raw any) error { + switch v := raw.(type) { + case []byte: + cur, err := ParseCurrency(string(v)) + if err != nil { + return err + } + *u = cur + case string: + cur, err := ParseCurrency(v) + if err != nil { + return err + } + *u = cur + default: + return fmt.Errorf("cannot sql.Scan() strfmt.Currency from: %#v: %w", v, ErrFormat) + } + + return nil +} + +// Value converts a value to a database driver value. +func (u Currency) Value() (driver.Value, error) { + return driver.Value(u.String()), nil +} + +func (u Currency) String() string { + return u.Unit.String() +} + +// MarshalJSON returns the [Currency] as JSON. +func (u Currency) MarshalJSON() ([]byte, error) { + return json.Marshal(u.String()) +} + +// UnmarshalJSON sets the [Currency] from JSON. +func (u *Currency) UnmarshalJSON(data []byte) error { + if string(data) == jsonNull { + return nil + } + var ustr string + if err := json.Unmarshal(data, &ustr); err != nil { + return err + } + + cur, err := ParseCurrency(ustr) + if err != nil { + return err + } + + *u = cur + + return nil +} + +// DeepCopyInto copies the receiver and writes its value into out. +func (u *Currency) DeepCopyInto(out *Currency) { + *out = *u +} + +// DeepCopy copies the receiver into a new [Currency]. +func (u *Currency) DeepCopy() *Currency { + if u == nil { + return nil + } + + out := new(Currency) + u.DeepCopyInto(out) + + return out +} + +// GobEncode implements the gob.GobEncoder interface. +func (u Currency) GobEncode() ([]byte, error) { + return u.MarshalText() +} + +// GobDecode implements the gob.GobDecoder interface. +func (u *Currency) GobDecode(data []byte) error { + return u.UnmarshalText(data) +} + +// MarshalBinary implements the encoding.[encoding.BinaryMarshaler] interface. +func (u Currency) MarshalBinary() ([]byte, error) { + return u.MarshalText() +} + +// UnmarshalBinary implements the encoding.[encoding.BinaryUnmarshaler] interface. +func (u *Currency) UnmarshalBinary(data []byte) error { + return u.UnmarshalText(data) +} diff --git a/vendor/github.com/go-openapi/strfmt/date.go b/vendor/github.com/go-openapi/strfmt/date.go index 59ee1f11216..6d0e8a01ac8 100644 --- a/vendor/github.com/go-openapi/strfmt/date.go +++ b/vendor/github.com/go-openapi/strfmt/date.go @@ -10,11 +10,6 @@ import ( "time" ) -func init() { //nolint:gochecknoinits // registers date format in the default registry - d := Date{} - Default.Add("date", &d, IsDate) -} - // IsDate returns true when the string is a valid date. func IsDate(str string) bool { _, err := time.Parse(RFC3339FullDate, str) diff --git a/vendor/github.com/go-openapi/strfmt/default.go b/vendor/github.com/go-openapi/strfmt/default.go index 725cc0e1a60..bcc57e6fad3 100644 --- a/vendor/github.com/go-openapi/strfmt/default.go +++ b/vendor/github.com/go-openapi/strfmt/default.go @@ -32,22 +32,22 @@ const ( ) const ( - // UUIDPattern Regex for [UUID] that allows uppercase + // UUIDPattern Regex for [UUID] that allows uppercase. // // Deprecated: [strfmt] no longer uses regular expressions to validate UUIDs. UUIDPattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{32}$)` - // UUID3Pattern Regex for [UUID3] that allows uppercase + // UUID3Pattern Regex for [UUID3] that allows uppercase. // // Deprecated: [strfmt] no longer uses regular expressions to validate UUIDs. UUID3Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{12}3[0-9a-f]{3}?[0-9a-f]{16}$)` - // UUID4Pattern Regex for [UUID4] that allows uppercase + // UUID4Pattern Regex for [UUID4] that allows uppercase. // // Deprecated: [strfmt] no longer uses regular expressions to validate UUIDs. UUID4Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$)` - // UUID5Pattern Regex for [UUID]5 that allows uppercase + // UUID5Pattern Regex for [UUID]5 that allows uppercase. // // Deprecated: [strfmt] no longer uses regular expressions to validate UUIDs. UUID5Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}5[0-9a-f]{3}[89ab][0-9a-f]{15}$)` @@ -88,8 +88,8 @@ var ( // IsHostname returns true when the string is a valid hostname. // -// It follows the rules detailed at https://url.spec.whatwg.org/#concept-host-parser -// and implemented by most modern web browsers. +// It follows the rules detailed at https://url.spec.whatwg.org/#concept-host-parser and implemented by most modern web +// browsers. // // It supports IDNA rules regarding internationalized names with unicode. // @@ -142,13 +142,13 @@ func IsHostname(str string) bool { return true } -// domainEndsAsNumber determines if a domain name ends with a decimal, octal or hex digit, -// accounting for a possible trailing dot (the last part being empty in that case). +// domainEndsAsNumber determines if a domain name ends with a decimal, octal or hex digit, accounting for a possible +// trailing dot (the last part being empty in that case). // // It returns the last non-trailing dot part and if that part consists only of (dec/hex/oct) digits. func domainEndsAsNumber(parts []string) (lastPart string, lastIndex int, ok bool) { - // NOTE: using ParseUint(x, 0, 32) is not an option, as the IPv4 format supported why WHATWG - // doesn't support notations such as "0b1001" (binary digits) or "0o666" (alternate notation for octal digits). + // NOTE: using ParseUint(x, 0, 32) is not an option, as the IPv4 format supported why WHATWG doesn't support notations + // such as "0b1001" (binary digits) or "0o666" (alternate notation for octal digits). lastIndex = len(parts) - 1 lastPart = parts[lastIndex] if len(lastPart) == 0 { @@ -233,8 +233,9 @@ func isValidIPv6(str string) bool { // "0o07.2.3.4" func isValidIPv4(parts []string) bool { // NOTE: using ParseUint(x, 0, 32) is not an option, even though it would simplify this code a lot. - // The IPv4 format supported why WHATWG doesn't support notations such as "0b1001" (binary digits) - // or "0o666" (alternate notation for octal digits). + // + // The IPv4 format supported why WHATWG doesn't support notations such as "0b1001" (binary digits) or "0o666" + // (alternate notation for octal digits). const ( maxPartsInIPv4 = 4 maxDigitsInPart = 11 // max size of a 4-bytes hex or octal digit @@ -376,101 +377,22 @@ func IsEmail(str string) bool { return e == nil && addr.Address != "" } -func init() { //nolint:gochecknoinits // registers all default string formats in the registry - // register formats in the default registry: - // - byte - // - creditcard - // - email - // - hexcolor - // - hostname - // - ipv4 - // - ipv6 - // - cidr - // - isbn - // - isbn10 - // - isbn13 - // - mac - // - password - // - rgbcolor - // - ssn - // - uri - // - uuid - // - uuid3 - // - uuid4 - // - uuid5 - // - uuid7 - u := URI("") - Default.Add("uri", &u, isRequestURI) - - eml := Email("") - Default.Add("email", &eml, IsEmail) - - hn := Hostname("") - Default.Add("hostname", &hn, IsHostname) - - ip4 := IPv4("") - Default.Add("ipv4", &ip4, isIPv4) - - ip6 := IPv6("") - Default.Add("ipv6", &ip6, isIPv6) - - cidr := CIDR("") - Default.Add("cidr", &cidr, isCIDR) - - mac := MAC("") - Default.Add("mac", &mac, isMAC) - - uid := UUID("") - Default.Add("uuid", &uid, IsUUID) - - uid3 := UUID3("") - Default.Add("uuid3", &uid3, IsUUID3) - - uid4 := UUID4("") - Default.Add("uuid4", &uid4, IsUUID4) - - uid5 := UUID5("") - Default.Add("uuid5", &uid5, IsUUID5) - - uid7 := UUID7("") - Default.Add("uuid7", &uid7, IsUUID7) - - isbn := ISBN("") - Default.Add("isbn", &isbn, func(str string) bool { return isISBN10(str) || isISBN13(str) }) - - isbn10 := ISBN10("") - Default.Add("isbn10", &isbn10, isISBN10) - - isbn13 := ISBN13("") - Default.Add("isbn13", &isbn13, isISBN13) - - cc := CreditCard("") - Default.Add("creditcard", &cc, isCreditCard) - - ssn := SSN("") - Default.Add("ssn", &ssn, isSSN) - - hc := HexColor("") - Default.Add("hexcolor", &hc, isHexcolor) - - rc := RGBColor("") - Default.Add("rgbcolor", &rc, isRGBcolor) - - b64 := Base64([]byte(nil)) - Default.Add("byte", &b64, isBase64) - - pw := Password("") - Default.Add("password", &pw, func(_ string) bool { return true }) -} +// base64Encoding is the canonical alphabet for the [Base64] format. +// +// OpenAPI `format: byte` means standard base64 (RFC 4648 §4, the `+/` alphabet), not base64url. +// This is the single seam every [Base64] path encodes and decodes through, so a future URL-safe variant only swaps the +// encoding here. +// See go-openapi/strfmt#87. +var base64Encoding = base64.StdEncoding //nolint:gochecknoglobals // canonical alphabet seam for the Base64 format -// Base64 represents a base64 encoded string, using URLEncoding alphabet. +// Base64 represents a base64 encoded string, using the standard RFC 4648 alphabet. // // swagger:strfmt byte. type Base64 []byte // MarshalText turns this instance into text. func (b Base64) MarshalText() ([]byte, error) { - enc := base64.URLEncoding + enc := base64Encoding src := []byte(b) buf := make([]byte, enc.EncodedLen(len(src))) enc.Encode(buf, src) @@ -479,7 +401,7 @@ func (b Base64) MarshalText() ([]byte, error) { // UnmarshalText hydrates this instance from text. func (b *Base64) UnmarshalText(data []byte) error { // validation is performed later on - enc := base64.URLEncoding + enc := base64Encoding dbuf := make([]byte, enc.DecodedLen(len(data))) n, err := enc.Decode(dbuf, data) @@ -495,14 +417,14 @@ func (b *Base64) UnmarshalText(data []byte) error { // validation is performed l func (b *Base64) Scan(raw any) error { switch v := raw.(type) { case []byte: - dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(v))) - n, err := base64.StdEncoding.Decode(dbuf, v) + dbuf := make([]byte, base64Encoding.DecodedLen(len(v))) + n, err := base64Encoding.Decode(dbuf, v) if err != nil { return err } *b = dbuf[:n] case string: - vv, err := base64.StdEncoding.DecodeString(v) + vv, err := base64Encoding.DecodeString(v) if err != nil { return err } @@ -520,7 +442,7 @@ func (b Base64) Value() (driver.Value, error) { } func (b Base64) String() string { - return base64.StdEncoding.EncodeToString([]byte(b)) + return base64Encoding.EncodeToString([]byte(b)) } // MarshalJSON returns the Base64 as JSON. @@ -534,7 +456,7 @@ func (b *Base64) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &b64str); err != nil { return err } - vb, err := base64.StdEncoding.DecodeString(b64str) + vb, err := base64Encoding.DecodeString(b64str) if err != nil { return err } @@ -1040,7 +962,7 @@ func (u *MAC) DeepCopy() *MAC { return out } -// UUID represents a [uuid] string format +// UUID represents a [uuid] string format. // // swagger:strfmt uuid. type UUID string @@ -1905,6 +1827,7 @@ func (r *RGBColor) DeepCopy() *RGBColor { } // Password represents a password. +// // This has no validations and is mainly used as a marker for UI components. // // swagger:strfmt password. @@ -1978,11 +1901,10 @@ func (r *Password) DeepCopy() *Password { } func isRequestURI(rawurl string) bool { - // url.ParseRequestURI assumes the input contains no "#fragment" - // (RFC 3986 §3.5). A URI with a fragment and an empty path, such as - // "https://host#@frag", is therefore misread as userinfo and rejected - // as "invalid userinfo". Strip the fragment first so the absolute - // request URI validates, matching url.Parse's RFC 3986 handling. + // url.ParseRequestURI assumes the input contains no "#fragment" (RFC 3986 §3.5). + // A URI with a fragment and an empty path, such as "https://host#@frag", is therefore misread as userinfo and rejected + // as "invalid userinfo". + // Strip the fragment first so the absolute request URI validates, matching url.Parse's RFC 3986 handling. if i := strings.IndexByte(rawurl, '#'); i >= 0 { rawurl = rawurl[:i] } @@ -2009,19 +1931,20 @@ func isCIDR(str string) bool { } // isMAC checks if a string is valid MAC address. +// // Possible MAC formats: -// 01:23:45:67:89:ab -// 01:23:45:67:89:ab:cd:ef -// 01-23-45-67-89-ab -// 01-23-45-67-89-ab-cd-ef -// 0123.4567.89ab -// 0123.4567.89ab.cdef. +// - 01:23:45:67:89:ab +// - 01:23:45:67:89:ab:cd:ef +// - 01-23-45-67-89-ab +// - 01-23-45-67-89-ab-cd-ef +// - 0123.4567.89ab 0123.4567.89ab.cdef func isMAC(str string) bool { _, err := net.ParseMAC(str) return err == nil } // isISBN checks if the string is an ISBN (version 10 or 13). +// // If version value is not equal to 10 or 13, it will be checks both variants. func isISBN(str string, version int) bool { sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "") @@ -2120,7 +2043,7 @@ func isRGBcolor(str string) bool { // isBase64 checks if a string is base64 encoded. func isBase64(str string) bool { - _, err := base64.StdEncoding.DecodeString(str) + _, err := base64Encoding.DecodeString(str) return err == nil } diff --git a/vendor/github.com/go-openapi/strfmt/duration.go b/vendor/github.com/go-openapi/strfmt/duration.go index f2ab7ff8348..fc4de0d14c2 100644 --- a/vendor/github.com/go-openapi/strfmt/duration.go +++ b/vendor/github.com/go-openapi/strfmt/duration.go @@ -12,11 +12,6 @@ import ( "unicode" ) -func init() { //nolint:gochecknoinits // registers duration format in the default registry - d := Duration(0) - Default.Add("duration", &d, IsDuration) -} - const ( hoursInDay = 24 daysInWeek = 7 @@ -174,6 +169,9 @@ func ParseDuration(s string) (time.Duration, error) { scale float64 = 1 // value = v + f/scale ) s = strings.TrimLeftFunc(s, unicode.IsSpace) + if s == "" { + break + } // The next character must be 0-9.] if s[0] != '.' && ('0' > s[0] || s[0] > '9') { diff --git a/vendor/github.com/go-openapi/strfmt/duration_iso8601.go b/vendor/github.com/go-openapi/strfmt/duration_iso8601.go new file mode 100644 index 00000000000..9fded035ae2 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/duration_iso8601.go @@ -0,0 +1,583 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package strfmt + +import ( + "database/sql/driver" + "encoding/json" + "fmt" + "math" + "strconv" + "strings" + "time" +) + +// ISO 8601 duration unit lengths, expressed in nanoseconds. +// +// Calendar units are collapsed to fixed lengths (a year is 365 days, a month is 30 days): a [time.Duration] cannot +// carry calendar context, so this conversion is inherently lossy and not calendar-correct. +// It matches the historical behaviour of ISO duration libraries in this space. +const ( + isoSecond = uint64(time.Second) + isoMinute = uint64(time.Minute) + isoHour = uint64(time.Hour) + isoDay = 24 * isoHour + isoWeek = 7 * isoDay + isoMonth = 30 * isoDay + isoYear = 365 * isoDay + + // maxDurationMagnitude is 1<<63: the magnitude of [math.MinInt64], and one more than [math.MaxInt64]. + // + // A parsed magnitude may reach exactly this value only for a negative duration (yielding [math.MinInt64]). + maxDurationMagnitude = uint64(1) << 63 +) + +// Base-10 parsing / formatting constants (decimalBase lives in default.go). +const ( + // decimalAccMax bounds a uint64 accumulator so that acc*decimalBase + 9 cannot overflow. + decimalAccMax = (math.MaxUint64 - (decimalBase - 1)) / decimalBase + // nanoDigits is the number of fractional digits in one whole second (nanosecond precision). + nanoDigits = 9 +) + +// ISODuration is an ISO 8601 / RFC 3339 duration (e.g. "P1Y2M3DT4H5M6S", "P2W"). +// +// The type parameter P selects the parsing policy at compile time (see [ISODurationPolicy]). +// Every instantiation is a distinct type that round-trips through JSON, text, SQL and BSON. +// Use the [DurationISO8601] alias for the strict, spec-compliant default. +// +// Like [time.Duration], it stores a nanosecond count; the largest representable duration is approximately 290 years. +// Calendar units are collapsed to fixed lengths (year = 365 days, month = 30 days), which is lossy by nature. +// +// This generic type carries no swagger:strfmt annotation: go-swagger binds a concrete format name to the +// [DurationISO8601] alias, not to a generic declaration. +type ISODuration[P ISODurationPolicy] time.Duration + +// DurationISO8601 is the strict, spec-compliant ISO 8601 duration: the JSON Schema draft 2020 "duration" format +// (RFC 3339 Appendix A). +// +// It binds to the explicit, unambiguous "duration-iso8601" handle. Plain "duration" is a context-dependent +// default resolved by the registry ([Default] → human, [JSONSchema2020Registry] → ISO), not by this static type. +// +// swagger:strfmt duration-iso8601. +type DurationISO8601 = ISODuration[DurationStrict] + +// ParseISO8601Duration parses an ISO 8601 / RFC 3339 duration string. +// +// With no options it enforces the strict RFC 3339 Appendix A grammar. +// Options relax individual rules for programmatic callers. +func ParseISO8601Duration(s string, opts ...ISODurationOption) (time.Duration, error) { + cfg := DurationStrict{}.isoDurationConfig() + for _, o := range opts { + o(&cfg) + } + return parseISO8601Duration(s, cfg) +} + +// --- Format / encoding methods --- + +// String renders the duration in canonical ISO 8601 form. +// +// Unlike [ISODuration.MarshalText], String is a best-effort display form: it always renders the true value (lossless), +// even under a strict policy that could not serialize it (e.g. a sign or sub-second precision). +func (d ISODuration[P]) String() string { return isoFormat(time.Duration(d)) } + +// MarshalText implements [encoding.TextMarshaler], applying the policy P: a strict policy errors on a value it cannot +// represent (see [isoEmit]). +func (d ISODuration[P]) MarshalText() ([]byte, error) { + var p P + s, err := isoEmit(time.Duration(d), p.isoDurationConfig()) + if err != nil { + return nil, err + } + return []byte(s), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], applying the policy P. +func (d *ISODuration[P]) UnmarshalText(text []byte) error { + var p P + dd, err := parseISO8601Duration(string(text), p.isoDurationConfig()) + if err != nil { + return err + } + *d = ISODuration[P](dd) + return nil +} + +// MarshalJSON returns the duration as a JSON string, applying the policy P. +func (d ISODuration[P]) MarshalJSON() ([]byte, error) { + var p P + s, err := isoEmit(time.Duration(d), p.isoDurationConfig()) + if err != nil { + return nil, err + } + return json.Marshal(s) +} + +// UnmarshalJSON sets the duration from a JSON string, applying the policy P. +func (d *ISODuration[P]) UnmarshalJSON(data []byte) error { + if string(data) == jsonNull { + return nil + } + var str string + if err := json.Unmarshal(data, &str); err != nil { + return err + } + var p P + dd, err := parseISO8601Duration(str, p.isoDurationConfig()) + if err != nil { + return err + } + *d = ISODuration[P](dd) + return nil +} + +// Scan reads a duration (nanoseconds) from a database driver value. +func (d *ISODuration[P]) Scan(raw any) error { + switch v := raw.(type) { + case int64: + *d = ISODuration[P](v) + case float64: + *d = ISODuration[P](int64(v)) + case nil: + *d = ISODuration[P](0) + default: + return fmt.Errorf("cannot sql.Scan() strfmt.ISODuration from: %#v: %w", v, ErrFormat) + } + return nil +} + +// Value writes the duration as a nanosecond count. +func (d ISODuration[P]) Value() (driver.Value, error) { + return driver.Value(int64(d)), nil +} + +// Equal reports whether two durations are equal. +func (d ISODuration[P]) Equal(other ISODuration[P]) bool { return d == other } + +// DeepCopyInto copies the receiver into out. +func (d *ISODuration[P]) DeepCopyInto(out *ISODuration[P]) { *out = *d } + +// DeepCopy copies the receiver into a new value. +func (d *ISODuration[P]) DeepCopy() *ISODuration[P] { + if d == nil { + return nil + } + out := new(ISODuration[P]) + d.DeepCopyInto(out) + return out +} + +// IsDurationISO8601 returns true if the string is a valid strict ISO 8601 duration. +func IsDurationISO8601(s string) bool { + _, err := parseISO8601Duration(s, DurationStrict{}.isoDurationConfig()) + return err == nil +} + +func isoDurationError(input, msg string) error { + return fmt.Errorf("invalid ISO 8601 duration %q: %s: %w", input, msg, ErrFormat) +} + +// section positions used to enforce component ordering (strictly increasing). +// +//nolint:gochecknoglobals,mnd // immutable ordinal lookup tables; the integers are sequence positions, not magic constants +var ( + isoDatePos = map[byte]int{'Y': 1, 'M': 2, 'W': 3, 'D': 4} + isoTimePos = map[byte]int{'H': 1, 'M': 2, 'S': 3} +) + +// isoDateSlot maps the year/month/day designators to contiguous slots for the strict anchoring (gap) check. +// +// 'W' is deliberately excluded: in strict mode it is exclusive, so it never coexists with Y/M/D. +func isoDateSlot(des byte) (int, bool) { + switch des { + case 'Y': + return 0, true + case 'M': + return 1, true + case 'D': + return 2, true //nolint:mnd // contiguous slot index (Y=0, M=1, D=2), not a magic constant + default: + return 0, false + } +} + +//nolint:gocognit,gocyclo,cyclop // a single-pass grammar scanner; the branches mirror the ABNF. +func parseISO8601Duration(input string, cfg isoDurationConfig) (time.Duration, error) { + s := input + if cfg.allowSpace { + s = strings.TrimSpace(s) + } + + neg := false + if cfg.allowSign && s != "" && (s[0] == '+' || s[0] == '-') { + neg = s[0] == '-' + s = s[1:] + } + + if s == "" || s[0] != 'P' { + return 0, isoDurationError(input, `must start with "P"`) + } + s = s[1:] + if s == "" { + return 0, isoDurationError(input, "no components after P") + } + + var ( + total uint64 + inTime bool + seenAny bool + weekSeen bool + fractionUsed bool + lastDatePos int + lastTimePos int + datePresent [3]bool // Y, M, D — for the anchoring (gap) check + timePresent [3]bool // H, M, S + ) + + for s != "" { + c := s[0] + + if c == 'T' { + if inTime { + return 0, isoDurationError(input, `duplicate "T" separator`) + } + if weekSeen && !cfg.weekCombinable { + return 0, isoDurationError(input, `"W" cannot be combined with other components`) + } + inTime = true + s = s[1:] + if s == "" { + return 0, isoDurationError(input, `no components after "T"`) + } + continue + } + + // A fraction, if any, must be on the least significant component: nothing may follow it. + if fractionUsed { + return 0, isoDurationError(input, "a fraction is only allowed on the least significant component") + } + + // Scan the integer part (ASCII digits only). + i := 0 + for i < len(s) && s[i] >= '0' && s[i] <= '9' { + i++ + } + if i == 0 { + return 0, isoDurationError(input, fmt.Sprintf("expected a digit, got %q", s[0])) + } + intPart := s[:i] + + // Optional decimal fraction. + var fracPart string + hasFrac := false + if i < len(s) && (s[i] == '.' || s[i] == ',') { + if !cfg.allowFraction { + return 0, isoDurationError(input, "decimal fraction is not allowed") + } + hasFrac = true + j := i + 1 + for j < len(s) && s[j] >= '0' && s[j] <= '9' { + j++ + } + fracPart = s[i+1 : j] + i = j + } + + if i >= len(s) { + return 0, isoDurationError(input, "value without a unit designator") + } + des := s[i] + s = s[i+1:] + + unit, err := isoResolveUnit(input, des, inTime, cfg, + &lastDatePos, &lastTimePos, &weekSeen, seenAny, &datePresent, &timePresent) + if err != nil { + return 0, err + } + seenAny = true + if hasFrac { + fractionUsed = true + } + + val, err := isoScaleValue(input, intPart, fracPart, unit) + if err != nil { + return 0, err + } + + // Accumulate with the stdlib overflow discipline: the magnitude may reach 1<<63 only for a negative duration. + if total > maxDurationMagnitude-val { + return 0, isoDurationError(input, "value out of range") + } + total += val + } + + if inTime && !timePresent[0] && !timePresent[1] && !timePresent[2] { + return 0, isoDurationError(input, `no components after "T"`) + } + if !seenAny { + return 0, isoDurationError(input, "no components") + } + + // Strict anchoring: the present Y/M/D and H/M/S components must each form a contiguous run (e.g. P1Y2D and PT1H2S are + // rejected). + if !cfg.relaxAnchoring { + if err := isoCheckContiguous(input, datePresent, "date"); err != nil { + return 0, err + } + if err := isoCheckContiguous(input, timePresent, "time"); err != nil { + return 0, err + } + } + + if total > maxDurationMagnitude-1 { + if neg && total == maxDurationMagnitude { + return math.MinInt64, nil + } + return 0, isoDurationError(input, "value out of range") + } + if neg { + return -time.Duration(total), nil + } + return time.Duration(total), nil +} + +// isoResolveUnit validates a designator in context (section, ordering, week +// exclusivity) and returns its unit length in nanoseconds. +func isoResolveUnit( + input string, des byte, inTime bool, cfg isoDurationConfig, + lastDatePos, lastTimePos *int, weekSeen *bool, seenAny bool, + datePresent, timePresent *[3]bool, +) (uint64, error) { + if inTime { + pos, ok := isoTimePos[des] + if !ok { + return 0, isoDurationError(input, fmt.Sprintf("%q is not a valid time-section designator", des)) + } + if pos <= *lastTimePos { + return 0, isoDurationError(input, fmt.Sprintf("designator %q is out of order", des)) + } + *lastTimePos = pos + timePresent[pos-1] = true + switch des { + case 'H': + return isoHour, nil + case 'M': + return isoMinute, nil + default: // 'S' + return isoSecond, nil + } + } + + pos, ok := isoDatePos[des] + if !ok { + return 0, isoDurationError(input, fmt.Sprintf("%q is not a valid date-section designator", des)) + } + if pos <= *lastDatePos { + return 0, isoDurationError(input, fmt.Sprintf("designator %q is out of order", des)) + } + + if des == 'W' { + if !cfg.weekCombinable && seenAny { + return 0, isoDurationError(input, `"W" cannot be combined with other components`) + } + *lastDatePos = pos + *weekSeen = true + return isoWeek, nil + } + + if *weekSeen && !cfg.weekCombinable { + return 0, isoDurationError(input, `"W" cannot be combined with other components`) + } + *lastDatePos = pos + if slot, ok := isoDateSlot(des); ok { + datePresent[slot] = true + } + switch des { + case 'Y': + return isoYear, nil + case 'M': + return isoMonth, nil + default: // 'D' + return isoDay, nil + } +} + +// isoCheckContiguous rejects gaps in a section's component chain. +func isoCheckContiguous(input string, present [3]bool, section string) error { + first, last := -1, -1 + for i, p := range present { + if p { + if first < 0 { + first = i + } + last = i + } + } + if first < 0 { + return nil + } + for i := first; i <= last; i++ { + if !present[i] { + return isoDurationError(input, "non-contiguous "+section+" components (a gap in the unit chain)") + } + } + return nil +} + +// isoScaleValue converts an integer (and optional fractional) component to nanoseconds, checking every overflow +// boundary. +func isoScaleValue(input, intPart, fracPart string, unit uint64) (uint64, error) { + v, ok := isoParseUint(intPart) + if !ok { + return 0, isoDurationError(input, "value out of range") + } + // Bound v*unit to the duration magnitude *before* multiplying, so the later fractional addition cannot wrap a uint64. + if v > maxDurationMagnitude/unit { + return 0, isoDurationError(input, "value out of range") + } + val := v * unit + + if fracPart != "" { + f, scale := isoParseFraction(fracPart) + if f > 0 { + // float64 is accurate enough for a sub-unit fraction (matches the standard library technique); the magnitude stays + // below the uint64 ceiling because val <= 1<<63 and the addend is < unit. + val += uint64(float64(f) * (float64(unit) / float64(scale))) + if val > maxDurationMagnitude { + return 0, isoDurationError(input, "value out of range") + } + } + } + + return val, nil +} + +// isoParseUint parses digits into a uint64, reporting overflow. +func isoParseUint(s string) (uint64, bool) { + var v uint64 + for i := range len(s) { + if v > decimalAccMax { + return 0, false + } + v = v*decimalBase + uint64(s[i]-'0') + } + + return v, true +} + +// isoParseFraction parses fractional digits into (value, scale=10^len), capping precision at 18 digits so the value +// stays exact in the subsequent float maths. +func isoParseFraction(s string) (uint64, uint64) { + const maxFracDigits = 18 + if len(s) > maxFracDigits { + s = s[:maxFracDigits] + } + var f, scale uint64 = 0, 1 + for i := range len(s) { + f = f*decimalBase + uint64(s[i]-'0') + scale *= decimalBase + } + + return f, scale +} + +// isoFormat renders a duration in canonical ISO 8601 form (P[n]DT[n]H[n]M[n]S). +// +// Intermediate zero time components are emitted when needed to keep the output contiguous (e.g. 1h5s → "PT1H0M5S"), +// so the structure is always syntactically valid ISO 8601. Years, months and weeks are not reconstructed (a +// [time.Duration] does not carry calendar context); a fractional second is emitted losslessly, and a negative duration +// is prefixed with "-". +func isoFormat(d time.Duration) string { + if d == 0 { + return "PT0S" + } + neg := d < 0 + var u uint64 + if neg { + u = uint64(-d) + } else { + u = uint64(d) + } + + days := u / isoDay + u %= isoDay + hours := u / isoHour + u %= isoHour + minutes := u / isoMinute + u %= isoMinute + seconds := u / isoSecond + frac := u % isoSecond + + var b strings.Builder + if neg { + b.WriteByte('-') + } + + b.WriteByte('P') + if days > 0 { + b.WriteString(strconv.FormatUint(days, decimalBase)) + b.WriteByte('D') + } + isoWriteTimeSection(&b, hours, minutes, seconds, frac) + + return b.String() +} + +// isoWriteTimeSection appends the "T…" part of a canonical ISO 8601 duration, emitting a zero-minute filler when it +// must bridge hours and seconds so the output stays contiguous (e.g. 1h5s → "T1H0M5S"). +func isoWriteTimeSection(b *strings.Builder, hours, minutes, seconds, frac uint64) { + hasH := hours > 0 + hasM := minutes > 0 + hasS := seconds > 0 || frac > 0 + if !hasH && !hasM && !hasS { + return + } + + b.WriteByte('T') + if hasH { + b.WriteString(strconv.FormatUint(hours, decimalBase)) + b.WriteByte('H') + } + + // Emit minutes if non-zero, or as a zero filler bridging hours and seconds. + if hasM || (hasH && hasS) { + b.WriteString(strconv.FormatUint(minutes, decimalBase)) + b.WriteByte('M') + } + + if hasS { + b.WriteString(strconv.FormatUint(seconds, decimalBase)) + if frac > 0 { + b.WriteByte('.') + b.WriteString(isoFormatFraction(frac)) + } + b.WriteByte('S') + } +} + +// isoEmit renders d under the given policy. +// +// A policy that forbids a feature the value requires (a sign, or sub-second precision) cannot represent it, and returns +// an error rather than emitting output a matching parser would reject. +func isoEmit(d time.Duration, cfg isoDurationConfig) (string, error) { + if !cfg.allowSign && d < 0 { + return "", fmt.Errorf("a negative duration cannot be represented under this ISO 8601 policy: %w", ErrFormat) + } + + if !cfg.allowFraction && d%time.Second != 0 { + return "", fmt.Errorf("sub-second precision cannot be represented under this ISO 8601 policy: %w", ErrFormat) + } + + return isoFormat(d), nil +} + +// isoFormatFraction renders a nanosecond remainder (0..1e9) as its 9-digit fractional part with trailing zeros trimmed. +func isoFormatFraction(frac uint64) string { + s := strconv.FormatUint(frac, decimalBase) + if len(s) < nanoDigits { + s = strings.Repeat("0", nanoDigits-len(s)) + s + } + return strings.TrimRight(s, "0") +} diff --git a/vendor/github.com/go-openapi/strfmt/duration_iso8601_options.go b/vendor/github.com/go-openapi/strfmt/duration_iso8601_options.go new file mode 100644 index 00000000000..4f90a5c5a5a --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/duration_iso8601_options.go @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package strfmt + +// ISODurationPolicy is a compile-time policy selecting the parsing behaviour of an [ISODuration]. +// +// It is a phantom type parameter: a zero-size value whose single method yields the parser configuration. +// See [DurationStrict] and [DurationLenient]. +type ISODurationPolicy interface { + isoDurationConfig() isoDurationConfig +} + +// isoDurationConfig holds the leniency knobs of the ISO 8601 duration parser. +// +// The zero value is the strict RFC 3339 Appendix A grammar (the JSON Schema "duration" format): every field false. +type isoDurationConfig struct { + allowFraction bool // accept a decimal fraction on the least significant component + allowSign bool // accept a leading '+' or '-' + allowSpace bool // tolerate surrounding whitespace + weekCombinable bool // allow the 'W' designator to combine with other components + relaxAnchoring bool // allow gaps in the component chain (e.g. P1Y2D, PT1H2S) +} + +// DurationStrict is the strict RFC 3339 Appendix A policy. +// +// This is the grammar that the JSON Schema "duration" format is defined against (draft 2020): +// no fraction, no sign, no whitespace, strict ordering and anchoring, and an exclusive 'W' designator. +type DurationStrict struct{} + +func (DurationStrict) isoDurationConfig() isoDurationConfig { return isoDurationConfig{} } + +// DurationLenient relaxes every strictness knob. +// +// It accepts a decimal fraction on the least significant component, a leading sign, surrounding whitespace, +// component chains with gaps (e.g. P1Y2D), and a 'W' designator combined with other components. +// +// It remains ordered (P2D1Y is still rejected). +type DurationLenient struct{} + +func (DurationLenient) isoDurationConfig() isoDurationConfig { + return isoDurationConfig{ + allowFraction: true, + allowSign: true, + allowSpace: true, + weekCombinable: true, + relaxAnchoring: true, + } +} + +// ISODurationOption relaxes the strict parser on the explicit [ParseISO8601Duration] path, for programmatic callers. +// +// It has no effect on the registry / struct-field decode path, which is governed by the type's policy. +type ISODurationOption func(*isoDurationConfig) + +// WithISOFractions accepts a decimal fraction on the least significant component. +func WithISOFractions() ISODurationOption { + return func(c *isoDurationConfig) { c.allowFraction = true } +} + +// WithISOSign accepts a leading '+' or '-'. +func WithISOSign() ISODurationOption { return func(c *isoDurationConfig) { c.allowSign = true } } + +// WithISOSpace tolerates surrounding whitespace. +func WithISOSpace() ISODurationOption { return func(c *isoDurationConfig) { c.allowSpace = true } } + +// WithISOWeekCombinable allows the 'W' designator to combine with other components. +func WithISOWeekCombinable() ISODurationOption { + return func(c *isoDurationConfig) { c.weekCombinable = true } +} + +// WithISORelaxedAnchoring allows gaps in the component chain (e.g. P1Y2D, PT1H2S). +func WithISORelaxedAnchoring() ISODurationOption { + return func(c *isoDurationConfig) { c.relaxAnchoring = true } +} + +// WithISOLenient relaxes every strictness knob (see [DurationLenient]). +func WithISOLenient() ISODurationOption { + return func(c *isoDurationConfig) { *c = DurationLenient{}.isoDurationConfig() } +} diff --git a/vendor/github.com/go-openapi/strfmt/format.go b/vendor/github.com/go-openapi/strfmt/format.go index e494dd7b83d..09c37542546 100644 --- a/vendor/github.com/go-openapi/strfmt/format.go +++ b/vendor/github.com/go-openapi/strfmt/format.go @@ -10,15 +10,11 @@ import ( "slices" "strings" "sync" - "time" "github.com/go-openapi/errors" "github.com/go-viper/mapstructure/v2" ) -// Default is the default formats registry. -var Default = NewSeededFormats(nil, nil) //nolint:gochecknoglobals // package-level default registry, by design - // Validator represents a validator for a string format. type Validator func(string) bool @@ -48,11 +44,28 @@ type knownFormat struct { } // NameNormalizer is a function that normalizes a format name. +// +// The default duration format corresponds to "duration-human". type NameNormalizer func(string) string +var dashReplacer = strings.NewReplacer("-", "") //nolint:gochecknoglobals // it's okay to use a global private replacer + // DefaultNameNormalizer removes all dashes. func DefaultNameNormalizer(name string) string { - return strings.ReplaceAll(name, "-", "") + if name == "duration" { + name = "duration-human" + } + + return dashReplacer.Replace(name) +} + +// JSONSchema2020Normalizer is like [NameNormalizer] but adopts "duration-iso8601" as the default "duration" format. +func JSONSchema2020Normalizer(name string) string { + if name == "duration" { + name = "duration-iso8601" + } + + return dashReplacer.Replace(name) } type defaultFormats struct { @@ -63,6 +76,11 @@ type defaultFormats struct { } // MapStructureHookFunc is a decode hook function for mapstructure. +// +// A registered format is decoded by delegating to the destination type's own +// [encoding.TextUnmarshaler], so the mapstructure path is identical to the JSON +// and [defaultFormats.Parse] paths. New formats are picked up automatically as +// soon as they are registered — no per-type wiring here. func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { //nolint:ireturn // returns interface required by mapstructure return func(from reflect.Type, to reflect.Type, obj any) (any, error) { if from.Kind() != reflect.String { @@ -74,85 +92,25 @@ func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { // } for _, v := range f.data { - tpe, _ := f.GetType(v.Name) - if to == tpe { - return decodeFormatFromString(v.Name, data) + if to != v.Type { + continue } - } - return data, nil - } -} -// decodeFormatFromString decodes a string into the appropriate format type by name. -func decodeFormatFromString(name, data string) (any, error) { //nolint:gocyclo,cyclop // flat switch over format names, no real complexity - switch name { - case "date": - d, err := time.ParseInLocation(RFC3339FullDate, data, DefaultTimeLocation) - if err != nil { - return nil, err - } - return Date(d), nil - case "datetime": - if len(data) == 0 { - return nil, fmt.Errorf("empty string is an invalid datetime format: %w", ErrFormat) - } - return ParseDateTime(data) - case "duration": - dur, err := ParseDuration(data) - if err != nil { - return nil, err - } - return Duration(dur), nil - case "uri": - return URI(data), nil - case "email": - return Email(data), nil - case "uuid": - return UUID(data), nil - case "uuid3": - return UUID3(data), nil - case "uuid4": - return UUID4(data), nil - case "uuid5": - return UUID5(data), nil - case "uuid7": - return UUID7(data), nil - case "hostname": - return Hostname(data), nil - case "ipv4": - return IPv4(data), nil - case "ipv6": - return IPv6(data), nil - case "cidr": - return CIDR(data), nil - case "mac": - return MAC(data), nil - case "isbn": - return ISBN(data), nil - case "isbn10": - return ISBN10(data), nil - case "isbn13": - return ISBN13(data), nil - case "creditcard": - return CreditCard(data), nil - case "ssn": - return SSN(data), nil - case "hexcolor": - return HexColor(data), nil - case "rgbcolor": - return RGBColor(data), nil - case "byte": - return Base64(data), nil - case "password": - return Password(data), nil - case "ulid": - ulid, err := ParseULID(data) - if err != nil { - return nil, err + // reflect.New yields an addressable *T so the (pointer-receiver) + // TextUnmarshaler can hydrate it; we hand back the dereferenced + // value to match the destination field's (value) type. + nw := reflect.New(v.Type).Interface() + dec, isText := nw.(encoding.TextUnmarshaler) + if !isText { + return nil, errors.InvalidTypeName(v.Name) + } + if err := dec.UnmarshalText([]byte(data)); err != nil { + return nil, err + } + return reflect.ValueOf(nw).Elem().Interface(), nil } - return ulid, nil - default: - return nil, errors.InvalidTypeName(name) + + return data, nil } } diff --git a/vendor/github.com/go-openapi/strfmt/internal/countries/countries.go b/vendor/github.com/go-openapi/strfmt/internal/countries/countries.go new file mode 100644 index 00000000000..7f13c0cfe35 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/internal/countries/countries.go @@ -0,0 +1,512 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by gen.go; DO NOT EDIT. + +package countries + +// CountriesISO3 indexes ISO3166 countries by their alpha-3 code. +var CountriesISO3 = map[string]Country{ + "ABW": {Name: "Aruba", ISOAlpha3: "ABW", ISOAlpha2: "AW", Code: "533"}, + "AFG": {Name: "Afghanistan", ISOAlpha3: "AFG", ISOAlpha2: "AF", Code: "004"}, + "AGO": {Name: "Angola", ISOAlpha3: "AGO", ISOAlpha2: "AO", Code: "024"}, + "AIA": {Name: "Anguilla", ISOAlpha3: "AIA", ISOAlpha2: "AI", Code: "660"}, + "ALA": {Name: "Åland Islands", ISOAlpha3: "ALA", ISOAlpha2: "AX", Code: "248"}, + "ALB": {Name: "Albania", ISOAlpha3: "ALB", ISOAlpha2: "AL", Code: "008"}, + "AND": {Name: "Andorra", ISOAlpha3: "AND", ISOAlpha2: "AD", Code: "020"}, + "ARE": {Name: "United Arab Emirates", ISOAlpha3: "ARE", ISOAlpha2: "AE", Code: "784"}, + "ARG": {Name: "Argentina", ISOAlpha3: "ARG", ISOAlpha2: "AR", Code: "032"}, + "ARM": {Name: "Armenia", ISOAlpha3: "ARM", ISOAlpha2: "AM", Code: "051"}, + "ASM": {Name: "American Samoa", ISOAlpha3: "ASM", ISOAlpha2: "AS", Code: "016"}, + "ATA": {Name: "Antarctica", ISOAlpha3: "ATA", ISOAlpha2: "AQ", Code: "010"}, + "ATF": {Name: "French Southern Territories", ISOAlpha3: "ATF", ISOAlpha2: "TF", Code: "260"}, + "ATG": {Name: "Antigua and Barbuda", ISOAlpha3: "ATG", ISOAlpha2: "AG", Code: "028"}, + "AUS": {Name: "Australia", ISOAlpha3: "AUS", ISOAlpha2: "AU", Code: "036"}, + "AUT": {Name: "Austria", ISOAlpha3: "AUT", ISOAlpha2: "AT", Code: "040"}, + "AZE": {Name: "Azerbaijan", ISOAlpha3: "AZE", ISOAlpha2: "AZ", Code: "031"}, + "BDI": {Name: "Burundi", ISOAlpha3: "BDI", ISOAlpha2: "BI", Code: "108"}, + "BEL": {Name: "Belgium", ISOAlpha3: "BEL", ISOAlpha2: "BE", Code: "056"}, + "BEN": {Name: "Benin", ISOAlpha3: "BEN", ISOAlpha2: "BJ", Code: "204"}, + "BES": {Name: "Bonaire, Sint Eustatius and Saba", ISOAlpha3: "BES", ISOAlpha2: "BQ", Code: "535"}, + "BFA": {Name: "Burkina Faso", ISOAlpha3: "BFA", ISOAlpha2: "BF", Code: "854"}, + "BGD": {Name: "Bangladesh", ISOAlpha3: "BGD", ISOAlpha2: "BD", Code: "050"}, + "BGR": {Name: "Bulgaria", ISOAlpha3: "BGR", ISOAlpha2: "BG", Code: "100"}, + "BHR": {Name: "Bahrain", ISOAlpha3: "BHR", ISOAlpha2: "BH", Code: "048"}, + "BHS": {Name: "Bahamas", ISOAlpha3: "BHS", ISOAlpha2: "BS", Code: "044"}, + "BIH": {Name: "Bosnia and Herzegovina", ISOAlpha3: "BIH", ISOAlpha2: "BA", Code: "070"}, + "BLM": {Name: "Saint Barthélemy", ISOAlpha3: "BLM", ISOAlpha2: "BL", Code: "652"}, + "BLR": {Name: "Belarus", ISOAlpha3: "BLR", ISOAlpha2: "BY", Code: "112"}, + "BLZ": {Name: "Belize", ISOAlpha3: "BLZ", ISOAlpha2: "BZ", Code: "084"}, + "BMU": {Name: "Bermuda", ISOAlpha3: "BMU", ISOAlpha2: "BM", Code: "060"}, + "BOL": {Name: "Bolivia (Plurinational State of)", ISOAlpha3: "BOL", ISOAlpha2: "BO", Code: "068"}, + "BRA": {Name: "Brazil", ISOAlpha3: "BRA", ISOAlpha2: "BR", Code: "076"}, + "BRB": {Name: "Barbados", ISOAlpha3: "BRB", ISOAlpha2: "BB", Code: "052"}, + "BRN": {Name: "Brunei Darussalam", ISOAlpha3: "BRN", ISOAlpha2: "BN", Code: "096"}, + "BTN": {Name: "Bhutan", ISOAlpha3: "BTN", ISOAlpha2: "BT", Code: "064"}, + "BVT": {Name: "Bouvet Island", ISOAlpha3: "BVT", ISOAlpha2: "BV", Code: "074"}, + "BWA": {Name: "Botswana", ISOAlpha3: "BWA", ISOAlpha2: "BW", Code: "072"}, + "CAF": {Name: "Central African Republic", ISOAlpha3: "CAF", ISOAlpha2: "CF", Code: "140"}, + "CAN": {Name: "Canada", ISOAlpha3: "CAN", ISOAlpha2: "CA", Code: "124"}, + "CCK": {Name: "Cocos (Keeling) Islands", ISOAlpha3: "CCK", ISOAlpha2: "CC", Code: "166"}, + "CHE": {Name: "Switzerland", ISOAlpha3: "CHE", ISOAlpha2: "CH", Code: "756"}, + "CHL": {Name: "Chile", ISOAlpha3: "CHL", ISOAlpha2: "CL", Code: "152"}, + "CHN": {Name: "China", ISOAlpha3: "CHN", ISOAlpha2: "CN", Code: "156"}, + "CIV": {Name: "Côte d'Ivoire", ISOAlpha3: "CIV", ISOAlpha2: "CI", Code: "384"}, + "CMR": {Name: "Cameroon", ISOAlpha3: "CMR", ISOAlpha2: "CM", Code: "120"}, + "COD": {Name: "Congo, Democratic Republic of the", ISOAlpha3: "COD", ISOAlpha2: "CD", Code: "180"}, + "COG": {Name: "Congo", ISOAlpha3: "COG", ISOAlpha2: "CG", Code: "178"}, + "COK": {Name: "Cook Islands", ISOAlpha3: "COK", ISOAlpha2: "CK", Code: "184"}, + "COL": {Name: "Colombia", ISOAlpha3: "COL", ISOAlpha2: "CO", Code: "170"}, + "COM": {Name: "Comoros", ISOAlpha3: "COM", ISOAlpha2: "KM", Code: "174"}, + "CPV": {Name: "Cabo Verde", ISOAlpha3: "CPV", ISOAlpha2: "CV", Code: "132"}, + "CRI": {Name: "Costa Rica", ISOAlpha3: "CRI", ISOAlpha2: "CR", Code: "188"}, + "CUB": {Name: "Cuba", ISOAlpha3: "CUB", ISOAlpha2: "CU", Code: "192"}, + "CUW": {Name: "Curaçao", ISOAlpha3: "CUW", ISOAlpha2: "CW", Code: "531"}, + "CXR": {Name: "Christmas Island", ISOAlpha3: "CXR", ISOAlpha2: "CX", Code: "162"}, + "CYM": {Name: "Cayman Islands", ISOAlpha3: "CYM", ISOAlpha2: "KY", Code: "136"}, + "CYP": {Name: "Cyprus", ISOAlpha3: "CYP", ISOAlpha2: "CY", Code: "196"}, + "CZE": {Name: "Czechia", ISOAlpha3: "CZE", ISOAlpha2: "CZ", Code: "203"}, + "DEU": {Name: "Germany", ISOAlpha3: "DEU", ISOAlpha2: "DE", Code: "276"}, + "DJI": {Name: "Djibouti", ISOAlpha3: "DJI", ISOAlpha2: "DJ", Code: "262"}, + "DMA": {Name: "Dominica", ISOAlpha3: "DMA", ISOAlpha2: "DM", Code: "212"}, + "DNK": {Name: "Denmark", ISOAlpha3: "DNK", ISOAlpha2: "DK", Code: "208"}, + "DOM": {Name: "Dominican Republic", ISOAlpha3: "DOM", ISOAlpha2: "DO", Code: "214"}, + "DZA": {Name: "Algeria", ISOAlpha3: "DZA", ISOAlpha2: "DZ", Code: "012"}, + "ECU": {Name: "Ecuador", ISOAlpha3: "ECU", ISOAlpha2: "EC", Code: "218"}, + "EGY": {Name: "Egypt", ISOAlpha3: "EGY", ISOAlpha2: "EG", Code: "818"}, + "ERI": {Name: "Eritrea", ISOAlpha3: "ERI", ISOAlpha2: "ER", Code: "232"}, + "ESH": {Name: "Western Sahara", ISOAlpha3: "ESH", ISOAlpha2: "EH", Code: "732"}, + "ESP": {Name: "Spain", ISOAlpha3: "ESP", ISOAlpha2: "ES", Code: "724"}, + "EST": {Name: "Estonia", ISOAlpha3: "EST", ISOAlpha2: "EE", Code: "233"}, + "ETH": {Name: "Ethiopia", ISOAlpha3: "ETH", ISOAlpha2: "ET", Code: "231"}, + "FIN": {Name: "Finland", ISOAlpha3: "FIN", ISOAlpha2: "FI", Code: "246"}, + "FJI": {Name: "Fiji", ISOAlpha3: "FJI", ISOAlpha2: "FJ", Code: "242"}, + "FLK": {Name: "Falkland Islands (Malvinas)", ISOAlpha3: "FLK", ISOAlpha2: "FK", Code: "238"}, + "FRA": {Name: "France", ISOAlpha3: "FRA", ISOAlpha2: "FR", Code: "250"}, + "FRO": {Name: "Faroe Islands", ISOAlpha3: "FRO", ISOAlpha2: "FO", Code: "234"}, + "FSM": {Name: "Micronesia (Federated States of)", ISOAlpha3: "FSM", ISOAlpha2: "FM", Code: "583"}, + "GAB": {Name: "Gabon", ISOAlpha3: "GAB", ISOAlpha2: "GA", Code: "266"}, + "GBR": {Name: "United Kingdom of Great Britain and Northern Ireland", ISOAlpha3: "GBR", ISOAlpha2: "GB", Code: "826"}, + "GEO": {Name: "Georgia", ISOAlpha3: "GEO", ISOAlpha2: "GE", Code: "268"}, + "GGY": {Name: "Guernsey", ISOAlpha3: "GGY", ISOAlpha2: "GG", Code: "831"}, + "GHA": {Name: "Ghana", ISOAlpha3: "GHA", ISOAlpha2: "GH", Code: "288"}, + "GIB": {Name: "Gibraltar", ISOAlpha3: "GIB", ISOAlpha2: "GI", Code: "292"}, + "GIN": {Name: "Guinea", ISOAlpha3: "GIN", ISOAlpha2: "GN", Code: "324"}, + "GLP": {Name: "Guadeloupe", ISOAlpha3: "GLP", ISOAlpha2: "GP", Code: "312"}, + "GMB": {Name: "Gambia", ISOAlpha3: "GMB", ISOAlpha2: "GM", Code: "270"}, + "GNB": {Name: "Guinea-Bissau", ISOAlpha3: "GNB", ISOAlpha2: "GW", Code: "624"}, + "GNQ": {Name: "Equatorial Guinea", ISOAlpha3: "GNQ", ISOAlpha2: "GQ", Code: "226"}, + "GRC": {Name: "Greece", ISOAlpha3: "GRC", ISOAlpha2: "GR", Code: "300"}, + "GRD": {Name: "Grenada", ISOAlpha3: "GRD", ISOAlpha2: "GD", Code: "308"}, + "GRL": {Name: "Greenland", ISOAlpha3: "GRL", ISOAlpha2: "GL", Code: "304"}, + "GTM": {Name: "Guatemala", ISOAlpha3: "GTM", ISOAlpha2: "GT", Code: "320"}, + "GUF": {Name: "French Guiana", ISOAlpha3: "GUF", ISOAlpha2: "GF", Code: "254"}, + "GUM": {Name: "Guam", ISOAlpha3: "GUM", ISOAlpha2: "GU", Code: "316"}, + "GUY": {Name: "Guyana", ISOAlpha3: "GUY", ISOAlpha2: "GY", Code: "328"}, + "HKG": {Name: "Hong Kong", ISOAlpha3: "HKG", ISOAlpha2: "HK", Code: "344"}, + "HMD": {Name: "Heard Island and McDonald Islands", ISOAlpha3: "HMD", ISOAlpha2: "HM", Code: "334"}, + "HND": {Name: "Honduras", ISOAlpha3: "HND", ISOAlpha2: "HN", Code: "340"}, + "HRV": {Name: "Croatia", ISOAlpha3: "HRV", ISOAlpha2: "HR", Code: "191"}, + "HTI": {Name: "Haiti", ISOAlpha3: "HTI", ISOAlpha2: "HT", Code: "332"}, + "HUN": {Name: "Hungary", ISOAlpha3: "HUN", ISOAlpha2: "HU", Code: "348"}, + "IDN": {Name: "Indonesia", ISOAlpha3: "IDN", ISOAlpha2: "ID", Code: "360"}, + "IMN": {Name: "Isle of Man", ISOAlpha3: "IMN", ISOAlpha2: "IM", Code: "833"}, + "IND": {Name: "India", ISOAlpha3: "IND", ISOAlpha2: "IN", Code: "356"}, + "IOT": {Name: "British Indian Ocean Territory", ISOAlpha3: "IOT", ISOAlpha2: "IO", Code: "086"}, + "IRL": {Name: "Ireland", ISOAlpha3: "IRL", ISOAlpha2: "IE", Code: "372"}, + "IRN": {Name: "Iran (Islamic Republic of)", ISOAlpha3: "IRN", ISOAlpha2: "IR", Code: "364"}, + "IRQ": {Name: "Iraq", ISOAlpha3: "IRQ", ISOAlpha2: "IQ", Code: "368"}, + "ISL": {Name: "Iceland", ISOAlpha3: "ISL", ISOAlpha2: "IS", Code: "352"}, + "ISR": {Name: "Israel", ISOAlpha3: "ISR", ISOAlpha2: "IL", Code: "376"}, + "ITA": {Name: "Italy", ISOAlpha3: "ITA", ISOAlpha2: "IT", Code: "380"}, + "JAM": {Name: "Jamaica", ISOAlpha3: "JAM", ISOAlpha2: "JM", Code: "388"}, + "JEY": {Name: "Jersey", ISOAlpha3: "JEY", ISOAlpha2: "JE", Code: "832"}, + "JOR": {Name: "Jordan", ISOAlpha3: "JOR", ISOAlpha2: "JO", Code: "400"}, + "JPN": {Name: "Japan", ISOAlpha3: "JPN", ISOAlpha2: "JP", Code: "392"}, + "KAZ": {Name: "Kazakhstan", ISOAlpha3: "KAZ", ISOAlpha2: "KZ", Code: "398"}, + "KEN": {Name: "Kenya", ISOAlpha3: "KEN", ISOAlpha2: "KE", Code: "404"}, + "KGZ": {Name: "Kyrgyzstan", ISOAlpha3: "KGZ", ISOAlpha2: "KG", Code: "417"}, + "KHM": {Name: "Cambodia", ISOAlpha3: "KHM", ISOAlpha2: "KH", Code: "116"}, + "KIR": {Name: "Kiribati", ISOAlpha3: "KIR", ISOAlpha2: "KI", Code: "296"}, + "KNA": {Name: "Saint Kitts and Nevis", ISOAlpha3: "KNA", ISOAlpha2: "KN", Code: "659"}, + "KOR": {Name: "Korea, Republic of", ISOAlpha3: "KOR", ISOAlpha2: "KR", Code: "410"}, + "KWT": {Name: "Kuwait", ISOAlpha3: "KWT", ISOAlpha2: "KW", Code: "414"}, + "LAO": {Name: "Lao People's Democratic Republic", ISOAlpha3: "LAO", ISOAlpha2: "LA", Code: "418"}, + "LBN": {Name: "Lebanon", ISOAlpha3: "LBN", ISOAlpha2: "LB", Code: "422"}, + "LBR": {Name: "Liberia", ISOAlpha3: "LBR", ISOAlpha2: "LR", Code: "430"}, + "LBY": {Name: "Libya", ISOAlpha3: "LBY", ISOAlpha2: "LY", Code: "434"}, + "LCA": {Name: "Saint Lucia", ISOAlpha3: "LCA", ISOAlpha2: "LC", Code: "662"}, + "LIE": {Name: "Liechtenstein", ISOAlpha3: "LIE", ISOAlpha2: "LI", Code: "438"}, + "LKA": {Name: "Sri Lanka", ISOAlpha3: "LKA", ISOAlpha2: "LK", Code: "144"}, + "LSO": {Name: "Lesotho", ISOAlpha3: "LSO", ISOAlpha2: "LS", Code: "426"}, + "LTU": {Name: "Lithuania", ISOAlpha3: "LTU", ISOAlpha2: "LT", Code: "440"}, + "LUX": {Name: "Luxembourg", ISOAlpha3: "LUX", ISOAlpha2: "LU", Code: "442"}, + "LVA": {Name: "Latvia", ISOAlpha3: "LVA", ISOAlpha2: "LV", Code: "428"}, + "MAC": {Name: "Macao", ISOAlpha3: "MAC", ISOAlpha2: "MO", Code: "446"}, + "MAF": {Name: "Saint Martin (French part)", ISOAlpha3: "MAF", ISOAlpha2: "MF", Code: "663"}, + "MAR": {Name: "Morocco", ISOAlpha3: "MAR", ISOAlpha2: "MA", Code: "504"}, + "MCO": {Name: "Monaco", ISOAlpha3: "MCO", ISOAlpha2: "MC", Code: "492"}, + "MDA": {Name: "Moldova, Republic of", ISOAlpha3: "MDA", ISOAlpha2: "MD", Code: "498"}, + "MDG": {Name: "Madagascar", ISOAlpha3: "MDG", ISOAlpha2: "MG", Code: "450"}, + "MDV": {Name: "Maldives", ISOAlpha3: "MDV", ISOAlpha2: "MV", Code: "462"}, + "MEX": {Name: "Mexico", ISOAlpha3: "MEX", ISOAlpha2: "MX", Code: "484"}, + "MHL": {Name: "Marshall Islands", ISOAlpha3: "MHL", ISOAlpha2: "MH", Code: "584"}, + "MKD": {Name: "North Macedonia", ISOAlpha3: "MKD", ISOAlpha2: "MK", Code: "807"}, + "MLI": {Name: "Mali", ISOAlpha3: "MLI", ISOAlpha2: "ML", Code: "466"}, + "MLT": {Name: "Malta", ISOAlpha3: "MLT", ISOAlpha2: "MT", Code: "470"}, + "MMR": {Name: "Myanmar", ISOAlpha3: "MMR", ISOAlpha2: "MM", Code: "104"}, + "MNE": {Name: "Montenegro", ISOAlpha3: "MNE", ISOAlpha2: "ME", Code: "499"}, + "MNG": {Name: "Mongolia", ISOAlpha3: "MNG", ISOAlpha2: "MN", Code: "496"}, + "MNP": {Name: "Northern Mariana Islands", ISOAlpha3: "MNP", ISOAlpha2: "MP", Code: "580"}, + "MOZ": {Name: "Mozambique", ISOAlpha3: "MOZ", ISOAlpha2: "MZ", Code: "508"}, + "MRT": {Name: "Mauritania", ISOAlpha3: "MRT", ISOAlpha2: "MR", Code: "478"}, + "MSR": {Name: "Montserrat", ISOAlpha3: "MSR", ISOAlpha2: "MS", Code: "500"}, + "MTQ": {Name: "Martinique", ISOAlpha3: "MTQ", ISOAlpha2: "MQ", Code: "474"}, + "MUS": {Name: "Mauritius", ISOAlpha3: "MUS", ISOAlpha2: "MU", Code: "480"}, + "MWI": {Name: "Malawi", ISOAlpha3: "MWI", ISOAlpha2: "MW", Code: "454"}, + "MYS": {Name: "Malaysia", ISOAlpha3: "MYS", ISOAlpha2: "MY", Code: "458"}, + "MYT": {Name: "Mayotte", ISOAlpha3: "MYT", ISOAlpha2: "YT", Code: "175"}, + "NAM": {Name: "Namibia", ISOAlpha3: "NAM", ISOAlpha2: "NA", Code: "516"}, + "NCL": {Name: "New Caledonia", ISOAlpha3: "NCL", ISOAlpha2: "NC", Code: "540"}, + "NER": {Name: "Niger", ISOAlpha3: "NER", ISOAlpha2: "NE", Code: "562"}, + "NFK": {Name: "Norfolk Island", ISOAlpha3: "NFK", ISOAlpha2: "NF", Code: "574"}, + "NGA": {Name: "Nigeria", ISOAlpha3: "NGA", ISOAlpha2: "NG", Code: "566"}, + "NIC": {Name: "Nicaragua", ISOAlpha3: "NIC", ISOAlpha2: "NI", Code: "558"}, + "NIU": {Name: "Niue", ISOAlpha3: "NIU", ISOAlpha2: "NU", Code: "570"}, + "NLD": {Name: "Netherlands", ISOAlpha3: "NLD", ISOAlpha2: "NL", Code: "528"}, + "NOR": {Name: "Norway", ISOAlpha3: "NOR", ISOAlpha2: "NO", Code: "578"}, + "NPL": {Name: "Nepal", ISOAlpha3: "NPL", ISOAlpha2: "NP", Code: "524"}, + "NRU": {Name: "Nauru", ISOAlpha3: "NRU", ISOAlpha2: "NR", Code: "520"}, + "NZL": {Name: "New Zealand", ISOAlpha3: "NZL", ISOAlpha2: "NZ", Code: "554"}, + "OMN": {Name: "Oman", ISOAlpha3: "OMN", ISOAlpha2: "OM", Code: "512"}, + "PAK": {Name: "Pakistan", ISOAlpha3: "PAK", ISOAlpha2: "PK", Code: "586"}, + "PAN": {Name: "Panama", ISOAlpha3: "PAN", ISOAlpha2: "PA", Code: "591"}, + "PCN": {Name: "Pitcairn", ISOAlpha3: "PCN", ISOAlpha2: "PN", Code: "612"}, + "PER": {Name: "Peru", ISOAlpha3: "PER", ISOAlpha2: "PE", Code: "604"}, + "PHL": {Name: "Philippines", ISOAlpha3: "PHL", ISOAlpha2: "PH", Code: "608"}, + "PLW": {Name: "Palau", ISOAlpha3: "PLW", ISOAlpha2: "PW", Code: "585"}, + "PNG": {Name: "Papua New Guinea", ISOAlpha3: "PNG", ISOAlpha2: "PG", Code: "598"}, + "POL": {Name: "Poland", ISOAlpha3: "POL", ISOAlpha2: "PL", Code: "616"}, + "PRI": {Name: "Puerto Rico", ISOAlpha3: "PRI", ISOAlpha2: "PR", Code: "630"}, + "PRK": {Name: "Korea (Democratic People's Republic of)", ISOAlpha3: "PRK", ISOAlpha2: "KP", Code: "408"}, + "PRT": {Name: "Portugal", ISOAlpha3: "PRT", ISOAlpha2: "PT", Code: "620"}, + "PRY": {Name: "Paraguay", ISOAlpha3: "PRY", ISOAlpha2: "PY", Code: "600"}, + "PSE": {Name: "Palestine, State of", ISOAlpha3: "PSE", ISOAlpha2: "PS", Code: "275"}, + "PYF": {Name: "French Polynesia", ISOAlpha3: "PYF", ISOAlpha2: "PF", Code: "258"}, + "QAT": {Name: "Qatar", ISOAlpha3: "QAT", ISOAlpha2: "QA", Code: "634"}, + "REU": {Name: "Réunion", ISOAlpha3: "REU", ISOAlpha2: "RE", Code: "638"}, + "ROU": {Name: "Romania", ISOAlpha3: "ROU", ISOAlpha2: "RO", Code: "642"}, + "RUS": {Name: "Russian Federation", ISOAlpha3: "RUS", ISOAlpha2: "RU", Code: "643"}, + "RWA": {Name: "Rwanda", ISOAlpha3: "RWA", ISOAlpha2: "RW", Code: "646"}, + "SAU": {Name: "Saudi Arabia", ISOAlpha3: "SAU", ISOAlpha2: "SA", Code: "682"}, + "SDN": {Name: "Sudan", ISOAlpha3: "SDN", ISOAlpha2: "SD", Code: "729"}, + "SEN": {Name: "Senegal", ISOAlpha3: "SEN", ISOAlpha2: "SN", Code: "686"}, + "SGP": {Name: "Singapore", ISOAlpha3: "SGP", ISOAlpha2: "SG", Code: "702"}, + "SGS": {Name: "South Georgia and the South Sandwich Islands", ISOAlpha3: "SGS", ISOAlpha2: "GS", Code: "239"}, + "SHN": {Name: "Saint Helena, Ascension and Tristan da Cunha", ISOAlpha3: "SHN", ISOAlpha2: "SH", Code: "654"}, + "SJM": {Name: "Svalbard and Jan Mayen", ISOAlpha3: "SJM", ISOAlpha2: "SJ", Code: "744"}, + "SLB": {Name: "Solomon Islands", ISOAlpha3: "SLB", ISOAlpha2: "SB", Code: "090"}, + "SLE": {Name: "Sierra Leone", ISOAlpha3: "SLE", ISOAlpha2: "SL", Code: "694"}, + "SLV": {Name: "El Salvador", ISOAlpha3: "SLV", ISOAlpha2: "SV", Code: "222"}, + "SMR": {Name: "San Marino", ISOAlpha3: "SMR", ISOAlpha2: "SM", Code: "674"}, + "SOM": {Name: "Somalia", ISOAlpha3: "SOM", ISOAlpha2: "SO", Code: "706"}, + "SPM": {Name: "Saint Pierre and Miquelon", ISOAlpha3: "SPM", ISOAlpha2: "PM", Code: "666"}, + "SRB": {Name: "Serbia", ISOAlpha3: "SRB", ISOAlpha2: "RS", Code: "688"}, + "SSD": {Name: "South Sudan", ISOAlpha3: "SSD", ISOAlpha2: "SS", Code: "728"}, + "STP": {Name: "Sao Tome and Principe", ISOAlpha3: "STP", ISOAlpha2: "ST", Code: "678"}, + "SUR": {Name: "Suriname", ISOAlpha3: "SUR", ISOAlpha2: "SR", Code: "740"}, + "SVK": {Name: "Slovakia", ISOAlpha3: "SVK", ISOAlpha2: "SK", Code: "703"}, + "SVN": {Name: "Slovenia", ISOAlpha3: "SVN", ISOAlpha2: "SI", Code: "705"}, + "SWE": {Name: "Sweden", ISOAlpha3: "SWE", ISOAlpha2: "SE", Code: "752"}, + "SWZ": {Name: "Eswatini", ISOAlpha3: "SWZ", ISOAlpha2: "SZ", Code: "748"}, + "SXM": {Name: "Sint Maarten (Dutch part)", ISOAlpha3: "SXM", ISOAlpha2: "SX", Code: "534"}, + "SYC": {Name: "Seychelles", ISOAlpha3: "SYC", ISOAlpha2: "SC", Code: "690"}, + "SYR": {Name: "Syrian Arab Republic", ISOAlpha3: "SYR", ISOAlpha2: "SY", Code: "760"}, + "TCA": {Name: "Turks and Caicos Islands", ISOAlpha3: "TCA", ISOAlpha2: "TC", Code: "796"}, + "TCD": {Name: "Chad", ISOAlpha3: "TCD", ISOAlpha2: "TD", Code: "148"}, + "TGO": {Name: "Togo", ISOAlpha3: "TGO", ISOAlpha2: "TG", Code: "768"}, + "THA": {Name: "Thailand", ISOAlpha3: "THA", ISOAlpha2: "TH", Code: "764"}, + "TJK": {Name: "Tajikistan", ISOAlpha3: "TJK", ISOAlpha2: "TJ", Code: "762"}, + "TKL": {Name: "Tokelau", ISOAlpha3: "TKL", ISOAlpha2: "TK", Code: "772"}, + "TKM": {Name: "Turkmenistan", ISOAlpha3: "TKM", ISOAlpha2: "TM", Code: "795"}, + "TLS": {Name: "Timor-Leste", ISOAlpha3: "TLS", ISOAlpha2: "TL", Code: "626"}, + "TON": {Name: "Tonga", ISOAlpha3: "TON", ISOAlpha2: "TO", Code: "776"}, + "TTO": {Name: "Trinidad and Tobago", ISOAlpha3: "TTO", ISOAlpha2: "TT", Code: "780"}, + "TUN": {Name: "Tunisia", ISOAlpha3: "TUN", ISOAlpha2: "TN", Code: "788"}, + "TUR": {Name: "Turkey", ISOAlpha3: "TUR", ISOAlpha2: "TR", Code: "792"}, + "TUV": {Name: "Tuvalu", ISOAlpha3: "TUV", ISOAlpha2: "TV", Code: "798"}, + "TWN": {Name: "Taiwan, Province of China", ISOAlpha3: "TWN", ISOAlpha2: "TW", Code: "158"}, + "TZA": {Name: "Tanzania, United Republic of", ISOAlpha3: "TZA", ISOAlpha2: "TZ", Code: "834"}, + "UGA": {Name: "Uganda", ISOAlpha3: "UGA", ISOAlpha2: "UG", Code: "800"}, + "UKR": {Name: "Ukraine", ISOAlpha3: "UKR", ISOAlpha2: "UA", Code: "804"}, + "UMI": {Name: "United States Minor Outlying Islands", ISOAlpha3: "UMI", ISOAlpha2: "UM", Code: "581"}, + "URY": {Name: "Uruguay", ISOAlpha3: "URY", ISOAlpha2: "UY", Code: "858"}, + "USA": {Name: "United States of America", ISOAlpha3: "USA", ISOAlpha2: "US", Code: "840"}, + "UZB": {Name: "Uzbekistan", ISOAlpha3: "UZB", ISOAlpha2: "UZ", Code: "860"}, + "VAT": {Name: "Holy See", ISOAlpha3: "VAT", ISOAlpha2: "VA", Code: "336"}, + "VCT": {Name: "Saint Vincent and the Grenadines", ISOAlpha3: "VCT", ISOAlpha2: "VC", Code: "670"}, + "VEN": {Name: "Venezuela (Bolivarian Republic of)", ISOAlpha3: "VEN", ISOAlpha2: "VE", Code: "862"}, + "VGB": {Name: "Virgin Islands (British)", ISOAlpha3: "VGB", ISOAlpha2: "VG", Code: "092"}, + "VIR": {Name: "Virgin Islands (U.S.)", ISOAlpha3: "VIR", ISOAlpha2: "VI", Code: "850"}, + "VNM": {Name: "Viet Nam", ISOAlpha3: "VNM", ISOAlpha2: "VN", Code: "704"}, + "VUT": {Name: "Vanuatu", ISOAlpha3: "VUT", ISOAlpha2: "VU", Code: "548"}, + "WLF": {Name: "Wallis and Futuna", ISOAlpha3: "WLF", ISOAlpha2: "WF", Code: "876"}, + "WSM": {Name: "Samoa", ISOAlpha3: "WSM", ISOAlpha2: "WS", Code: "882"}, + "YEM": {Name: "Yemen", ISOAlpha3: "YEM", ISOAlpha2: "YE", Code: "887"}, + "ZAF": {Name: "South Africa", ISOAlpha3: "ZAF", ISOAlpha2: "ZA", Code: "710"}, + "ZMB": {Name: "Zambia", ISOAlpha3: "ZMB", ISOAlpha2: "ZM", Code: "894"}, + "ZWE": {Name: "Zimbabwe", ISOAlpha3: "ZWE", ISOAlpha2: "ZW", Code: "716"}, +} + +// CountriesISO2 indexes ISO3166 countries by their alpha-2 code. +var CountriesISO2 = map[string]Country{ + "AD": {Name: "Andorra", ISOAlpha3: "AND", ISOAlpha2: "AD", Code: "020"}, + "AE": {Name: "United Arab Emirates", ISOAlpha3: "ARE", ISOAlpha2: "AE", Code: "784"}, + "AF": {Name: "Afghanistan", ISOAlpha3: "AFG", ISOAlpha2: "AF", Code: "004"}, + "AG": {Name: "Antigua and Barbuda", ISOAlpha3: "ATG", ISOAlpha2: "AG", Code: "028"}, + "AI": {Name: "Anguilla", ISOAlpha3: "AIA", ISOAlpha2: "AI", Code: "660"}, + "AL": {Name: "Albania", ISOAlpha3: "ALB", ISOAlpha2: "AL", Code: "008"}, + "AM": {Name: "Armenia", ISOAlpha3: "ARM", ISOAlpha2: "AM", Code: "051"}, + "AO": {Name: "Angola", ISOAlpha3: "AGO", ISOAlpha2: "AO", Code: "024"}, + "AQ": {Name: "Antarctica", ISOAlpha3: "ATA", ISOAlpha2: "AQ", Code: "010"}, + "AR": {Name: "Argentina", ISOAlpha3: "ARG", ISOAlpha2: "AR", Code: "032"}, + "AS": {Name: "American Samoa", ISOAlpha3: "ASM", ISOAlpha2: "AS", Code: "016"}, + "AT": {Name: "Austria", ISOAlpha3: "AUT", ISOAlpha2: "AT", Code: "040"}, + "AU": {Name: "Australia", ISOAlpha3: "AUS", ISOAlpha2: "AU", Code: "036"}, + "AW": {Name: "Aruba", ISOAlpha3: "ABW", ISOAlpha2: "AW", Code: "533"}, + "AX": {Name: "Åland Islands", ISOAlpha3: "ALA", ISOAlpha2: "AX", Code: "248"}, + "AZ": {Name: "Azerbaijan", ISOAlpha3: "AZE", ISOAlpha2: "AZ", Code: "031"}, + "BA": {Name: "Bosnia and Herzegovina", ISOAlpha3: "BIH", ISOAlpha2: "BA", Code: "070"}, + "BB": {Name: "Barbados", ISOAlpha3: "BRB", ISOAlpha2: "BB", Code: "052"}, + "BD": {Name: "Bangladesh", ISOAlpha3: "BGD", ISOAlpha2: "BD", Code: "050"}, + "BE": {Name: "Belgium", ISOAlpha3: "BEL", ISOAlpha2: "BE", Code: "056"}, + "BF": {Name: "Burkina Faso", ISOAlpha3: "BFA", ISOAlpha2: "BF", Code: "854"}, + "BG": {Name: "Bulgaria", ISOAlpha3: "BGR", ISOAlpha2: "BG", Code: "100"}, + "BH": {Name: "Bahrain", ISOAlpha3: "BHR", ISOAlpha2: "BH", Code: "048"}, + "BI": {Name: "Burundi", ISOAlpha3: "BDI", ISOAlpha2: "BI", Code: "108"}, + "BJ": {Name: "Benin", ISOAlpha3: "BEN", ISOAlpha2: "BJ", Code: "204"}, + "BL": {Name: "Saint Barthélemy", ISOAlpha3: "BLM", ISOAlpha2: "BL", Code: "652"}, + "BM": {Name: "Bermuda", ISOAlpha3: "BMU", ISOAlpha2: "BM", Code: "060"}, + "BN": {Name: "Brunei Darussalam", ISOAlpha3: "BRN", ISOAlpha2: "BN", Code: "096"}, + "BO": {Name: "Bolivia (Plurinational State of)", ISOAlpha3: "BOL", ISOAlpha2: "BO", Code: "068"}, + "BQ": {Name: "Bonaire, Sint Eustatius and Saba", ISOAlpha3: "BES", ISOAlpha2: "BQ", Code: "535"}, + "BR": {Name: "Brazil", ISOAlpha3: "BRA", ISOAlpha2: "BR", Code: "076"}, + "BS": {Name: "Bahamas", ISOAlpha3: "BHS", ISOAlpha2: "BS", Code: "044"}, + "BT": {Name: "Bhutan", ISOAlpha3: "BTN", ISOAlpha2: "BT", Code: "064"}, + "BV": {Name: "Bouvet Island", ISOAlpha3: "BVT", ISOAlpha2: "BV", Code: "074"}, + "BW": {Name: "Botswana", ISOAlpha3: "BWA", ISOAlpha2: "BW", Code: "072"}, + "BY": {Name: "Belarus", ISOAlpha3: "BLR", ISOAlpha2: "BY", Code: "112"}, + "BZ": {Name: "Belize", ISOAlpha3: "BLZ", ISOAlpha2: "BZ", Code: "084"}, + "CA": {Name: "Canada", ISOAlpha3: "CAN", ISOAlpha2: "CA", Code: "124"}, + "CC": {Name: "Cocos (Keeling) Islands", ISOAlpha3: "CCK", ISOAlpha2: "CC", Code: "166"}, + "CD": {Name: "Congo, Democratic Republic of the", ISOAlpha3: "COD", ISOAlpha2: "CD", Code: "180"}, + "CF": {Name: "Central African Republic", ISOAlpha3: "CAF", ISOAlpha2: "CF", Code: "140"}, + "CG": {Name: "Congo", ISOAlpha3: "COG", ISOAlpha2: "CG", Code: "178"}, + "CH": {Name: "Switzerland", ISOAlpha3: "CHE", ISOAlpha2: "CH", Code: "756"}, + "CI": {Name: "Côte d'Ivoire", ISOAlpha3: "CIV", ISOAlpha2: "CI", Code: "384"}, + "CK": {Name: "Cook Islands", ISOAlpha3: "COK", ISOAlpha2: "CK", Code: "184"}, + "CL": {Name: "Chile", ISOAlpha3: "CHL", ISOAlpha2: "CL", Code: "152"}, + "CM": {Name: "Cameroon", ISOAlpha3: "CMR", ISOAlpha2: "CM", Code: "120"}, + "CN": {Name: "China", ISOAlpha3: "CHN", ISOAlpha2: "CN", Code: "156"}, + "CO": {Name: "Colombia", ISOAlpha3: "COL", ISOAlpha2: "CO", Code: "170"}, + "CR": {Name: "Costa Rica", ISOAlpha3: "CRI", ISOAlpha2: "CR", Code: "188"}, + "CU": {Name: "Cuba", ISOAlpha3: "CUB", ISOAlpha2: "CU", Code: "192"}, + "CV": {Name: "Cabo Verde", ISOAlpha3: "CPV", ISOAlpha2: "CV", Code: "132"}, + "CW": {Name: "Curaçao", ISOAlpha3: "CUW", ISOAlpha2: "CW", Code: "531"}, + "CX": {Name: "Christmas Island", ISOAlpha3: "CXR", ISOAlpha2: "CX", Code: "162"}, + "CY": {Name: "Cyprus", ISOAlpha3: "CYP", ISOAlpha2: "CY", Code: "196"}, + "CZ": {Name: "Czechia", ISOAlpha3: "CZE", ISOAlpha2: "CZ", Code: "203"}, + "DE": {Name: "Germany", ISOAlpha3: "DEU", ISOAlpha2: "DE", Code: "276"}, + "DJ": {Name: "Djibouti", ISOAlpha3: "DJI", ISOAlpha2: "DJ", Code: "262"}, + "DK": {Name: "Denmark", ISOAlpha3: "DNK", ISOAlpha2: "DK", Code: "208"}, + "DM": {Name: "Dominica", ISOAlpha3: "DMA", ISOAlpha2: "DM", Code: "212"}, + "DO": {Name: "Dominican Republic", ISOAlpha3: "DOM", ISOAlpha2: "DO", Code: "214"}, + "DZ": {Name: "Algeria", ISOAlpha3: "DZA", ISOAlpha2: "DZ", Code: "012"}, + "EC": {Name: "Ecuador", ISOAlpha3: "ECU", ISOAlpha2: "EC", Code: "218"}, + "EE": {Name: "Estonia", ISOAlpha3: "EST", ISOAlpha2: "EE", Code: "233"}, + "EG": {Name: "Egypt", ISOAlpha3: "EGY", ISOAlpha2: "EG", Code: "818"}, + "EH": {Name: "Western Sahara", ISOAlpha3: "ESH", ISOAlpha2: "EH", Code: "732"}, + "ER": {Name: "Eritrea", ISOAlpha3: "ERI", ISOAlpha2: "ER", Code: "232"}, + "ES": {Name: "Spain", ISOAlpha3: "ESP", ISOAlpha2: "ES", Code: "724"}, + "ET": {Name: "Ethiopia", ISOAlpha3: "ETH", ISOAlpha2: "ET", Code: "231"}, + "FI": {Name: "Finland", ISOAlpha3: "FIN", ISOAlpha2: "FI", Code: "246"}, + "FJ": {Name: "Fiji", ISOAlpha3: "FJI", ISOAlpha2: "FJ", Code: "242"}, + "FK": {Name: "Falkland Islands (Malvinas)", ISOAlpha3: "FLK", ISOAlpha2: "FK", Code: "238"}, + "FM": {Name: "Micronesia (Federated States of)", ISOAlpha3: "FSM", ISOAlpha2: "FM", Code: "583"}, + "FO": {Name: "Faroe Islands", ISOAlpha3: "FRO", ISOAlpha2: "FO", Code: "234"}, + "FR": {Name: "France", ISOAlpha3: "FRA", ISOAlpha2: "FR", Code: "250"}, + "GA": {Name: "Gabon", ISOAlpha3: "GAB", ISOAlpha2: "GA", Code: "266"}, + "GB": {Name: "United Kingdom of Great Britain and Northern Ireland", ISOAlpha3: "GBR", ISOAlpha2: "GB", Code: "826"}, + "GD": {Name: "Grenada", ISOAlpha3: "GRD", ISOAlpha2: "GD", Code: "308"}, + "GE": {Name: "Georgia", ISOAlpha3: "GEO", ISOAlpha2: "GE", Code: "268"}, + "GF": {Name: "French Guiana", ISOAlpha3: "GUF", ISOAlpha2: "GF", Code: "254"}, + "GG": {Name: "Guernsey", ISOAlpha3: "GGY", ISOAlpha2: "GG", Code: "831"}, + "GH": {Name: "Ghana", ISOAlpha3: "GHA", ISOAlpha2: "GH", Code: "288"}, + "GI": {Name: "Gibraltar", ISOAlpha3: "GIB", ISOAlpha2: "GI", Code: "292"}, + "GL": {Name: "Greenland", ISOAlpha3: "GRL", ISOAlpha2: "GL", Code: "304"}, + "GM": {Name: "Gambia", ISOAlpha3: "GMB", ISOAlpha2: "GM", Code: "270"}, + "GN": {Name: "Guinea", ISOAlpha3: "GIN", ISOAlpha2: "GN", Code: "324"}, + "GP": {Name: "Guadeloupe", ISOAlpha3: "GLP", ISOAlpha2: "GP", Code: "312"}, + "GQ": {Name: "Equatorial Guinea", ISOAlpha3: "GNQ", ISOAlpha2: "GQ", Code: "226"}, + "GR": {Name: "Greece", ISOAlpha3: "GRC", ISOAlpha2: "GR", Code: "300"}, + "GS": {Name: "South Georgia and the South Sandwich Islands", ISOAlpha3: "SGS", ISOAlpha2: "GS", Code: "239"}, + "GT": {Name: "Guatemala", ISOAlpha3: "GTM", ISOAlpha2: "GT", Code: "320"}, + "GU": {Name: "Guam", ISOAlpha3: "GUM", ISOAlpha2: "GU", Code: "316"}, + "GW": {Name: "Guinea-Bissau", ISOAlpha3: "GNB", ISOAlpha2: "GW", Code: "624"}, + "GY": {Name: "Guyana", ISOAlpha3: "GUY", ISOAlpha2: "GY", Code: "328"}, + "HK": {Name: "Hong Kong", ISOAlpha3: "HKG", ISOAlpha2: "HK", Code: "344"}, + "HM": {Name: "Heard Island and McDonald Islands", ISOAlpha3: "HMD", ISOAlpha2: "HM", Code: "334"}, + "HN": {Name: "Honduras", ISOAlpha3: "HND", ISOAlpha2: "HN", Code: "340"}, + "HR": {Name: "Croatia", ISOAlpha3: "HRV", ISOAlpha2: "HR", Code: "191"}, + "HT": {Name: "Haiti", ISOAlpha3: "HTI", ISOAlpha2: "HT", Code: "332"}, + "HU": {Name: "Hungary", ISOAlpha3: "HUN", ISOAlpha2: "HU", Code: "348"}, + "ID": {Name: "Indonesia", ISOAlpha3: "IDN", ISOAlpha2: "ID", Code: "360"}, + "IE": {Name: "Ireland", ISOAlpha3: "IRL", ISOAlpha2: "IE", Code: "372"}, + "IL": {Name: "Israel", ISOAlpha3: "ISR", ISOAlpha2: "IL", Code: "376"}, + "IM": {Name: "Isle of Man", ISOAlpha3: "IMN", ISOAlpha2: "IM", Code: "833"}, + "IN": {Name: "India", ISOAlpha3: "IND", ISOAlpha2: "IN", Code: "356"}, + "IO": {Name: "British Indian Ocean Territory", ISOAlpha3: "IOT", ISOAlpha2: "IO", Code: "086"}, + "IQ": {Name: "Iraq", ISOAlpha3: "IRQ", ISOAlpha2: "IQ", Code: "368"}, + "IR": {Name: "Iran (Islamic Republic of)", ISOAlpha3: "IRN", ISOAlpha2: "IR", Code: "364"}, + "IS": {Name: "Iceland", ISOAlpha3: "ISL", ISOAlpha2: "IS", Code: "352"}, + "IT": {Name: "Italy", ISOAlpha3: "ITA", ISOAlpha2: "IT", Code: "380"}, + "JE": {Name: "Jersey", ISOAlpha3: "JEY", ISOAlpha2: "JE", Code: "832"}, + "JM": {Name: "Jamaica", ISOAlpha3: "JAM", ISOAlpha2: "JM", Code: "388"}, + "JO": {Name: "Jordan", ISOAlpha3: "JOR", ISOAlpha2: "JO", Code: "400"}, + "JP": {Name: "Japan", ISOAlpha3: "JPN", ISOAlpha2: "JP", Code: "392"}, + "KE": {Name: "Kenya", ISOAlpha3: "KEN", ISOAlpha2: "KE", Code: "404"}, + "KG": {Name: "Kyrgyzstan", ISOAlpha3: "KGZ", ISOAlpha2: "KG", Code: "417"}, + "KH": {Name: "Cambodia", ISOAlpha3: "KHM", ISOAlpha2: "KH", Code: "116"}, + "KI": {Name: "Kiribati", ISOAlpha3: "KIR", ISOAlpha2: "KI", Code: "296"}, + "KM": {Name: "Comoros", ISOAlpha3: "COM", ISOAlpha2: "KM", Code: "174"}, + "KN": {Name: "Saint Kitts and Nevis", ISOAlpha3: "KNA", ISOAlpha2: "KN", Code: "659"}, + "KP": {Name: "Korea (Democratic People's Republic of)", ISOAlpha3: "PRK", ISOAlpha2: "KP", Code: "408"}, + "KR": {Name: "Korea, Republic of", ISOAlpha3: "KOR", ISOAlpha2: "KR", Code: "410"}, + "KW": {Name: "Kuwait", ISOAlpha3: "KWT", ISOAlpha2: "KW", Code: "414"}, + "KY": {Name: "Cayman Islands", ISOAlpha3: "CYM", ISOAlpha2: "KY", Code: "136"}, + "KZ": {Name: "Kazakhstan", ISOAlpha3: "KAZ", ISOAlpha2: "KZ", Code: "398"}, + "LA": {Name: "Lao People's Democratic Republic", ISOAlpha3: "LAO", ISOAlpha2: "LA", Code: "418"}, + "LB": {Name: "Lebanon", ISOAlpha3: "LBN", ISOAlpha2: "LB", Code: "422"}, + "LC": {Name: "Saint Lucia", ISOAlpha3: "LCA", ISOAlpha2: "LC", Code: "662"}, + "LI": {Name: "Liechtenstein", ISOAlpha3: "LIE", ISOAlpha2: "LI", Code: "438"}, + "LK": {Name: "Sri Lanka", ISOAlpha3: "LKA", ISOAlpha2: "LK", Code: "144"}, + "LR": {Name: "Liberia", ISOAlpha3: "LBR", ISOAlpha2: "LR", Code: "430"}, + "LS": {Name: "Lesotho", ISOAlpha3: "LSO", ISOAlpha2: "LS", Code: "426"}, + "LT": {Name: "Lithuania", ISOAlpha3: "LTU", ISOAlpha2: "LT", Code: "440"}, + "LU": {Name: "Luxembourg", ISOAlpha3: "LUX", ISOAlpha2: "LU", Code: "442"}, + "LV": {Name: "Latvia", ISOAlpha3: "LVA", ISOAlpha2: "LV", Code: "428"}, + "LY": {Name: "Libya", ISOAlpha3: "LBY", ISOAlpha2: "LY", Code: "434"}, + "MA": {Name: "Morocco", ISOAlpha3: "MAR", ISOAlpha2: "MA", Code: "504"}, + "MC": {Name: "Monaco", ISOAlpha3: "MCO", ISOAlpha2: "MC", Code: "492"}, + "MD": {Name: "Moldova, Republic of", ISOAlpha3: "MDA", ISOAlpha2: "MD", Code: "498"}, + "ME": {Name: "Montenegro", ISOAlpha3: "MNE", ISOAlpha2: "ME", Code: "499"}, + "MF": {Name: "Saint Martin (French part)", ISOAlpha3: "MAF", ISOAlpha2: "MF", Code: "663"}, + "MG": {Name: "Madagascar", ISOAlpha3: "MDG", ISOAlpha2: "MG", Code: "450"}, + "MH": {Name: "Marshall Islands", ISOAlpha3: "MHL", ISOAlpha2: "MH", Code: "584"}, + "MK": {Name: "North Macedonia", ISOAlpha3: "MKD", ISOAlpha2: "MK", Code: "807"}, + "ML": {Name: "Mali", ISOAlpha3: "MLI", ISOAlpha2: "ML", Code: "466"}, + "MM": {Name: "Myanmar", ISOAlpha3: "MMR", ISOAlpha2: "MM", Code: "104"}, + "MN": {Name: "Mongolia", ISOAlpha3: "MNG", ISOAlpha2: "MN", Code: "496"}, + "MO": {Name: "Macao", ISOAlpha3: "MAC", ISOAlpha2: "MO", Code: "446"}, + "MP": {Name: "Northern Mariana Islands", ISOAlpha3: "MNP", ISOAlpha2: "MP", Code: "580"}, + "MQ": {Name: "Martinique", ISOAlpha3: "MTQ", ISOAlpha2: "MQ", Code: "474"}, + "MR": {Name: "Mauritania", ISOAlpha3: "MRT", ISOAlpha2: "MR", Code: "478"}, + "MS": {Name: "Montserrat", ISOAlpha3: "MSR", ISOAlpha2: "MS", Code: "500"}, + "MT": {Name: "Malta", ISOAlpha3: "MLT", ISOAlpha2: "MT", Code: "470"}, + "MU": {Name: "Mauritius", ISOAlpha3: "MUS", ISOAlpha2: "MU", Code: "480"}, + "MV": {Name: "Maldives", ISOAlpha3: "MDV", ISOAlpha2: "MV", Code: "462"}, + "MW": {Name: "Malawi", ISOAlpha3: "MWI", ISOAlpha2: "MW", Code: "454"}, + "MX": {Name: "Mexico", ISOAlpha3: "MEX", ISOAlpha2: "MX", Code: "484"}, + "MY": {Name: "Malaysia", ISOAlpha3: "MYS", ISOAlpha2: "MY", Code: "458"}, + "MZ": {Name: "Mozambique", ISOAlpha3: "MOZ", ISOAlpha2: "MZ", Code: "508"}, + "NA": {Name: "Namibia", ISOAlpha3: "NAM", ISOAlpha2: "NA", Code: "516"}, + "NC": {Name: "New Caledonia", ISOAlpha3: "NCL", ISOAlpha2: "NC", Code: "540"}, + "NE": {Name: "Niger", ISOAlpha3: "NER", ISOAlpha2: "NE", Code: "562"}, + "NF": {Name: "Norfolk Island", ISOAlpha3: "NFK", ISOAlpha2: "NF", Code: "574"}, + "NG": {Name: "Nigeria", ISOAlpha3: "NGA", ISOAlpha2: "NG", Code: "566"}, + "NI": {Name: "Nicaragua", ISOAlpha3: "NIC", ISOAlpha2: "NI", Code: "558"}, + "NL": {Name: "Netherlands", ISOAlpha3: "NLD", ISOAlpha2: "NL", Code: "528"}, + "NO": {Name: "Norway", ISOAlpha3: "NOR", ISOAlpha2: "NO", Code: "578"}, + "NP": {Name: "Nepal", ISOAlpha3: "NPL", ISOAlpha2: "NP", Code: "524"}, + "NR": {Name: "Nauru", ISOAlpha3: "NRU", ISOAlpha2: "NR", Code: "520"}, + "NU": {Name: "Niue", ISOAlpha3: "NIU", ISOAlpha2: "NU", Code: "570"}, + "NZ": {Name: "New Zealand", ISOAlpha3: "NZL", ISOAlpha2: "NZ", Code: "554"}, + "OM": {Name: "Oman", ISOAlpha3: "OMN", ISOAlpha2: "OM", Code: "512"}, + "PA": {Name: "Panama", ISOAlpha3: "PAN", ISOAlpha2: "PA", Code: "591"}, + "PE": {Name: "Peru", ISOAlpha3: "PER", ISOAlpha2: "PE", Code: "604"}, + "PF": {Name: "French Polynesia", ISOAlpha3: "PYF", ISOAlpha2: "PF", Code: "258"}, + "PG": {Name: "Papua New Guinea", ISOAlpha3: "PNG", ISOAlpha2: "PG", Code: "598"}, + "PH": {Name: "Philippines", ISOAlpha3: "PHL", ISOAlpha2: "PH", Code: "608"}, + "PK": {Name: "Pakistan", ISOAlpha3: "PAK", ISOAlpha2: "PK", Code: "586"}, + "PL": {Name: "Poland", ISOAlpha3: "POL", ISOAlpha2: "PL", Code: "616"}, + "PM": {Name: "Saint Pierre and Miquelon", ISOAlpha3: "SPM", ISOAlpha2: "PM", Code: "666"}, + "PN": {Name: "Pitcairn", ISOAlpha3: "PCN", ISOAlpha2: "PN", Code: "612"}, + "PR": {Name: "Puerto Rico", ISOAlpha3: "PRI", ISOAlpha2: "PR", Code: "630"}, + "PS": {Name: "Palestine, State of", ISOAlpha3: "PSE", ISOAlpha2: "PS", Code: "275"}, + "PT": {Name: "Portugal", ISOAlpha3: "PRT", ISOAlpha2: "PT", Code: "620"}, + "PW": {Name: "Palau", ISOAlpha3: "PLW", ISOAlpha2: "PW", Code: "585"}, + "PY": {Name: "Paraguay", ISOAlpha3: "PRY", ISOAlpha2: "PY", Code: "600"}, + "QA": {Name: "Qatar", ISOAlpha3: "QAT", ISOAlpha2: "QA", Code: "634"}, + "RE": {Name: "Réunion", ISOAlpha3: "REU", ISOAlpha2: "RE", Code: "638"}, + "RO": {Name: "Romania", ISOAlpha3: "ROU", ISOAlpha2: "RO", Code: "642"}, + "RS": {Name: "Serbia", ISOAlpha3: "SRB", ISOAlpha2: "RS", Code: "688"}, + "RU": {Name: "Russian Federation", ISOAlpha3: "RUS", ISOAlpha2: "RU", Code: "643"}, + "RW": {Name: "Rwanda", ISOAlpha3: "RWA", ISOAlpha2: "RW", Code: "646"}, + "SA": {Name: "Saudi Arabia", ISOAlpha3: "SAU", ISOAlpha2: "SA", Code: "682"}, + "SB": {Name: "Solomon Islands", ISOAlpha3: "SLB", ISOAlpha2: "SB", Code: "090"}, + "SC": {Name: "Seychelles", ISOAlpha3: "SYC", ISOAlpha2: "SC", Code: "690"}, + "SD": {Name: "Sudan", ISOAlpha3: "SDN", ISOAlpha2: "SD", Code: "729"}, + "SE": {Name: "Sweden", ISOAlpha3: "SWE", ISOAlpha2: "SE", Code: "752"}, + "SG": {Name: "Singapore", ISOAlpha3: "SGP", ISOAlpha2: "SG", Code: "702"}, + "SH": {Name: "Saint Helena, Ascension and Tristan da Cunha", ISOAlpha3: "SHN", ISOAlpha2: "SH", Code: "654"}, + "SI": {Name: "Slovenia", ISOAlpha3: "SVN", ISOAlpha2: "SI", Code: "705"}, + "SJ": {Name: "Svalbard and Jan Mayen", ISOAlpha3: "SJM", ISOAlpha2: "SJ", Code: "744"}, + "SK": {Name: "Slovakia", ISOAlpha3: "SVK", ISOAlpha2: "SK", Code: "703"}, + "SL": {Name: "Sierra Leone", ISOAlpha3: "SLE", ISOAlpha2: "SL", Code: "694"}, + "SM": {Name: "San Marino", ISOAlpha3: "SMR", ISOAlpha2: "SM", Code: "674"}, + "SN": {Name: "Senegal", ISOAlpha3: "SEN", ISOAlpha2: "SN", Code: "686"}, + "SO": {Name: "Somalia", ISOAlpha3: "SOM", ISOAlpha2: "SO", Code: "706"}, + "SR": {Name: "Suriname", ISOAlpha3: "SUR", ISOAlpha2: "SR", Code: "740"}, + "SS": {Name: "South Sudan", ISOAlpha3: "SSD", ISOAlpha2: "SS", Code: "728"}, + "ST": {Name: "Sao Tome and Principe", ISOAlpha3: "STP", ISOAlpha2: "ST", Code: "678"}, + "SV": {Name: "El Salvador", ISOAlpha3: "SLV", ISOAlpha2: "SV", Code: "222"}, + "SX": {Name: "Sint Maarten (Dutch part)", ISOAlpha3: "SXM", ISOAlpha2: "SX", Code: "534"}, + "SY": {Name: "Syrian Arab Republic", ISOAlpha3: "SYR", ISOAlpha2: "SY", Code: "760"}, + "SZ": {Name: "Eswatini", ISOAlpha3: "SWZ", ISOAlpha2: "SZ", Code: "748"}, + "TC": {Name: "Turks and Caicos Islands", ISOAlpha3: "TCA", ISOAlpha2: "TC", Code: "796"}, + "TD": {Name: "Chad", ISOAlpha3: "TCD", ISOAlpha2: "TD", Code: "148"}, + "TF": {Name: "French Southern Territories", ISOAlpha3: "ATF", ISOAlpha2: "TF", Code: "260"}, + "TG": {Name: "Togo", ISOAlpha3: "TGO", ISOAlpha2: "TG", Code: "768"}, + "TH": {Name: "Thailand", ISOAlpha3: "THA", ISOAlpha2: "TH", Code: "764"}, + "TJ": {Name: "Tajikistan", ISOAlpha3: "TJK", ISOAlpha2: "TJ", Code: "762"}, + "TK": {Name: "Tokelau", ISOAlpha3: "TKL", ISOAlpha2: "TK", Code: "772"}, + "TL": {Name: "Timor-Leste", ISOAlpha3: "TLS", ISOAlpha2: "TL", Code: "626"}, + "TM": {Name: "Turkmenistan", ISOAlpha3: "TKM", ISOAlpha2: "TM", Code: "795"}, + "TN": {Name: "Tunisia", ISOAlpha3: "TUN", ISOAlpha2: "TN", Code: "788"}, + "TO": {Name: "Tonga", ISOAlpha3: "TON", ISOAlpha2: "TO", Code: "776"}, + "TR": {Name: "Turkey", ISOAlpha3: "TUR", ISOAlpha2: "TR", Code: "792"}, + "TT": {Name: "Trinidad and Tobago", ISOAlpha3: "TTO", ISOAlpha2: "TT", Code: "780"}, + "TV": {Name: "Tuvalu", ISOAlpha3: "TUV", ISOAlpha2: "TV", Code: "798"}, + "TW": {Name: "Taiwan, Province of China", ISOAlpha3: "TWN", ISOAlpha2: "TW", Code: "158"}, + "TZ": {Name: "Tanzania, United Republic of", ISOAlpha3: "TZA", ISOAlpha2: "TZ", Code: "834"}, + "UA": {Name: "Ukraine", ISOAlpha3: "UKR", ISOAlpha2: "UA", Code: "804"}, + "UG": {Name: "Uganda", ISOAlpha3: "UGA", ISOAlpha2: "UG", Code: "800"}, + "UM": {Name: "United States Minor Outlying Islands", ISOAlpha3: "UMI", ISOAlpha2: "UM", Code: "581"}, + "US": {Name: "United States of America", ISOAlpha3: "USA", ISOAlpha2: "US", Code: "840"}, + "UY": {Name: "Uruguay", ISOAlpha3: "URY", ISOAlpha2: "UY", Code: "858"}, + "UZ": {Name: "Uzbekistan", ISOAlpha3: "UZB", ISOAlpha2: "UZ", Code: "860"}, + "VA": {Name: "Holy See", ISOAlpha3: "VAT", ISOAlpha2: "VA", Code: "336"}, + "VC": {Name: "Saint Vincent and the Grenadines", ISOAlpha3: "VCT", ISOAlpha2: "VC", Code: "670"}, + "VE": {Name: "Venezuela (Bolivarian Republic of)", ISOAlpha3: "VEN", ISOAlpha2: "VE", Code: "862"}, + "VG": {Name: "Virgin Islands (British)", ISOAlpha3: "VGB", ISOAlpha2: "VG", Code: "092"}, + "VI": {Name: "Virgin Islands (U.S.)", ISOAlpha3: "VIR", ISOAlpha2: "VI", Code: "850"}, + "VN": {Name: "Viet Nam", ISOAlpha3: "VNM", ISOAlpha2: "VN", Code: "704"}, + "VU": {Name: "Vanuatu", ISOAlpha3: "VUT", ISOAlpha2: "VU", Code: "548"}, + "WF": {Name: "Wallis and Futuna", ISOAlpha3: "WLF", ISOAlpha2: "WF", Code: "876"}, + "WS": {Name: "Samoa", ISOAlpha3: "WSM", ISOAlpha2: "WS", Code: "882"}, + "YE": {Name: "Yemen", ISOAlpha3: "YEM", ISOAlpha2: "YE", Code: "887"}, + "YT": {Name: "Mayotte", ISOAlpha3: "MYT", ISOAlpha2: "YT", Code: "175"}, + "ZA": {Name: "South Africa", ISOAlpha3: "ZAF", ISOAlpha2: "ZA", Code: "710"}, + "ZM": {Name: "Zambia", ISOAlpha3: "ZMB", ISOAlpha2: "ZM", Code: "894"}, + "ZW": {Name: "Zimbabwe", ISOAlpha3: "ZWE", ISOAlpha2: "ZW", Code: "716"}, +} diff --git a/vendor/github.com/go-openapi/strfmt/internal/countries/country.go b/vendor/github.com/go-openapi/strfmt/internal/countries/country.go new file mode 100644 index 00000000000..774051430eb --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/internal/countries/country.go @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +//go:generate go run gen.go -- countries.go +package countries + +// Country identifies a country with its english name, and ISO3166 codes. +// +//nolint:tagliatelle // JSON tags mirror the iso3166.json source keys (alpha-3, alpha-2, country-code); renaming them breaks the embedded-JSON unmarshal. +type Country struct { + Name string `json:"name"` + ISOAlpha3 string `json:"alpha-3"` + ISOAlpha2 string `json:"alpha-2"` + Code string `json:"country-code"` +} diff --git a/vendor/github.com/go-openapi/strfmt/internal/countries/iso3166.json b/vendor/github.com/go-openapi/strfmt/internal/countries/iso3166.json new file mode 100644 index 00000000000..b2c0b5c5017 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/internal/countries/iso3166.json @@ -0,0 +1,251 @@ +[ +{"name":"Afghanistan","alpha-2":"AF","alpha-3":"AFG","country-code":"004","iso_3166-2":"ISO 3166-2:AF","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Åland Islands","alpha-2":"AX","alpha-3":"ALA","country-code":"248","iso_3166-2":"ISO 3166-2:AX","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Albania","alpha-2":"AL","alpha-3":"ALB","country-code":"008","iso_3166-2":"ISO 3166-2:AL","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Algeria","alpha-2":"DZ","alpha-3":"DZA","country-code":"012","iso_3166-2":"ISO 3166-2:DZ","region":"Africa","sub-region":"Northern Africa","intermediate-region":"","region-code":"002","sub-region-code":"015","intermediate-region-code":""}, +{"name":"American Samoa","alpha-2":"AS","alpha-3":"ASM","country-code":"016","iso_3166-2":"ISO 3166-2:AS","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Andorra","alpha-2":"AD","alpha-3":"AND","country-code":"020","iso_3166-2":"ISO 3166-2:AD","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Angola","alpha-2":"AO","alpha-3":"AGO","country-code":"024","iso_3166-2":"ISO 3166-2:AO","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Anguilla","alpha-2":"AI","alpha-3":"AIA","country-code":"660","iso_3166-2":"ISO 3166-2:AI","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Antarctica","alpha-2":"AQ","alpha-3":"ATA","country-code":"010","iso_3166-2":"ISO 3166-2:AQ","region":"","sub-region":"","intermediate-region":"","region-code":"","sub-region-code":"","intermediate-region-code":""}, +{"name":"Antigua and Barbuda","alpha-2":"AG","alpha-3":"ATG","country-code":"028","iso_3166-2":"ISO 3166-2:AG","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Argentina","alpha-2":"AR","alpha-3":"ARG","country-code":"032","iso_3166-2":"ISO 3166-2:AR","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Armenia","alpha-2":"AM","alpha-3":"ARM","country-code":"051","iso_3166-2":"ISO 3166-2:AM","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Aruba","alpha-2":"AW","alpha-3":"ABW","country-code":"533","iso_3166-2":"ISO 3166-2:AW","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Australia","alpha-2":"AU","alpha-3":"AUS","country-code":"036","iso_3166-2":"ISO 3166-2:AU","region":"Oceania","sub-region":"Australia and New Zealand","intermediate-region":"","region-code":"009","sub-region-code":"053","intermediate-region-code":""}, +{"name":"Austria","alpha-2":"AT","alpha-3":"AUT","country-code":"040","iso_3166-2":"ISO 3166-2:AT","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"Azerbaijan","alpha-2":"AZ","alpha-3":"AZE","country-code":"031","iso_3166-2":"ISO 3166-2:AZ","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Bahamas","alpha-2":"BS","alpha-3":"BHS","country-code":"044","iso_3166-2":"ISO 3166-2:BS","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Bahrain","alpha-2":"BH","alpha-3":"BHR","country-code":"048","iso_3166-2":"ISO 3166-2:BH","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Bangladesh","alpha-2":"BD","alpha-3":"BGD","country-code":"050","iso_3166-2":"ISO 3166-2:BD","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Barbados","alpha-2":"BB","alpha-3":"BRB","country-code":"052","iso_3166-2":"ISO 3166-2:BB","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Belarus","alpha-2":"BY","alpha-3":"BLR","country-code":"112","iso_3166-2":"ISO 3166-2:BY","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Belgium","alpha-2":"BE","alpha-3":"BEL","country-code":"056","iso_3166-2":"ISO 3166-2:BE","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"Belize","alpha-2":"BZ","alpha-3":"BLZ","country-code":"084","iso_3166-2":"ISO 3166-2:BZ","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Benin","alpha-2":"BJ","alpha-3":"BEN","country-code":"204","iso_3166-2":"ISO 3166-2:BJ","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Bermuda","alpha-2":"BM","alpha-3":"BMU","country-code":"060","iso_3166-2":"ISO 3166-2:BM","region":"Americas","sub-region":"Northern America","intermediate-region":"","region-code":"019","sub-region-code":"021","intermediate-region-code":""}, +{"name":"Bhutan","alpha-2":"BT","alpha-3":"BTN","country-code":"064","iso_3166-2":"ISO 3166-2:BT","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Bolivia (Plurinational State of)","alpha-2":"BO","alpha-3":"BOL","country-code":"068","iso_3166-2":"ISO 3166-2:BO","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Bonaire, Sint Eustatius and Saba","alpha-2":"BQ","alpha-3":"BES","country-code":"535","iso_3166-2":"ISO 3166-2:BQ","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Bosnia and Herzegovina","alpha-2":"BA","alpha-3":"BIH","country-code":"070","iso_3166-2":"ISO 3166-2:BA","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Botswana","alpha-2":"BW","alpha-3":"BWA","country-code":"072","iso_3166-2":"ISO 3166-2:BW","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Southern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"018"}, +{"name":"Bouvet Island","alpha-2":"BV","alpha-3":"BVT","country-code":"074","iso_3166-2":"ISO 3166-2:BV","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Brazil","alpha-2":"BR","alpha-3":"BRA","country-code":"076","iso_3166-2":"ISO 3166-2:BR","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"British Indian Ocean Territory","alpha-2":"IO","alpha-3":"IOT","country-code":"086","iso_3166-2":"ISO 3166-2:IO","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Brunei Darussalam","alpha-2":"BN","alpha-3":"BRN","country-code":"096","iso_3166-2":"ISO 3166-2:BN","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Bulgaria","alpha-2":"BG","alpha-3":"BGR","country-code":"100","iso_3166-2":"ISO 3166-2:BG","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Burkina Faso","alpha-2":"BF","alpha-3":"BFA","country-code":"854","iso_3166-2":"ISO 3166-2:BF","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Burundi","alpha-2":"BI","alpha-3":"BDI","country-code":"108","iso_3166-2":"ISO 3166-2:BI","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Cabo Verde","alpha-2":"CV","alpha-3":"CPV","country-code":"132","iso_3166-2":"ISO 3166-2:CV","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Cambodia","alpha-2":"KH","alpha-3":"KHM","country-code":"116","iso_3166-2":"ISO 3166-2:KH","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Cameroon","alpha-2":"CM","alpha-3":"CMR","country-code":"120","iso_3166-2":"ISO 3166-2:CM","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Canada","alpha-2":"CA","alpha-3":"CAN","country-code":"124","iso_3166-2":"ISO 3166-2:CA","region":"Americas","sub-region":"Northern America","intermediate-region":"","region-code":"019","sub-region-code":"021","intermediate-region-code":""}, +{"name":"Cayman Islands","alpha-2":"KY","alpha-3":"CYM","country-code":"136","iso_3166-2":"ISO 3166-2:KY","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Central African Republic","alpha-2":"CF","alpha-3":"CAF","country-code":"140","iso_3166-2":"ISO 3166-2:CF","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Chad","alpha-2":"TD","alpha-3":"TCD","country-code":"148","iso_3166-2":"ISO 3166-2:TD","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Chile","alpha-2":"CL","alpha-3":"CHL","country-code":"152","iso_3166-2":"ISO 3166-2:CL","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"China","alpha-2":"CN","alpha-3":"CHN","country-code":"156","iso_3166-2":"ISO 3166-2:CN","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Christmas Island","alpha-2":"CX","alpha-3":"CXR","country-code":"162","iso_3166-2":"ISO 3166-2:CX","region":"Oceania","sub-region":"Australia and New Zealand","intermediate-region":"","region-code":"009","sub-region-code":"053","intermediate-region-code":""}, +{"name":"Cocos (Keeling) Islands","alpha-2":"CC","alpha-3":"CCK","country-code":"166","iso_3166-2":"ISO 3166-2:CC","region":"Oceania","sub-region":"Australia and New Zealand","intermediate-region":"","region-code":"009","sub-region-code":"053","intermediate-region-code":""}, +{"name":"Colombia","alpha-2":"CO","alpha-3":"COL","country-code":"170","iso_3166-2":"ISO 3166-2:CO","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Comoros","alpha-2":"KM","alpha-3":"COM","country-code":"174","iso_3166-2":"ISO 3166-2:KM","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Congo","alpha-2":"CG","alpha-3":"COG","country-code":"178","iso_3166-2":"ISO 3166-2:CG","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Congo, Democratic Republic of the","alpha-2":"CD","alpha-3":"COD","country-code":"180","iso_3166-2":"ISO 3166-2:CD","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Cook Islands","alpha-2":"CK","alpha-3":"COK","country-code":"184","iso_3166-2":"ISO 3166-2:CK","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Costa Rica","alpha-2":"CR","alpha-3":"CRI","country-code":"188","iso_3166-2":"ISO 3166-2:CR","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Côte d'Ivoire","alpha-2":"CI","alpha-3":"CIV","country-code":"384","iso_3166-2":"ISO 3166-2:CI","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Croatia","alpha-2":"HR","alpha-3":"HRV","country-code":"191","iso_3166-2":"ISO 3166-2:HR","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Cuba","alpha-2":"CU","alpha-3":"CUB","country-code":"192","iso_3166-2":"ISO 3166-2:CU","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Curaçao","alpha-2":"CW","alpha-3":"CUW","country-code":"531","iso_3166-2":"ISO 3166-2:CW","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Cyprus","alpha-2":"CY","alpha-3":"CYP","country-code":"196","iso_3166-2":"ISO 3166-2:CY","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Czechia","alpha-2":"CZ","alpha-3":"CZE","country-code":"203","iso_3166-2":"ISO 3166-2:CZ","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Denmark","alpha-2":"DK","alpha-3":"DNK","country-code":"208","iso_3166-2":"ISO 3166-2:DK","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Djibouti","alpha-2":"DJ","alpha-3":"DJI","country-code":"262","iso_3166-2":"ISO 3166-2:DJ","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Dominica","alpha-2":"DM","alpha-3":"DMA","country-code":"212","iso_3166-2":"ISO 3166-2:DM","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Dominican Republic","alpha-2":"DO","alpha-3":"DOM","country-code":"214","iso_3166-2":"ISO 3166-2:DO","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Ecuador","alpha-2":"EC","alpha-3":"ECU","country-code":"218","iso_3166-2":"ISO 3166-2:EC","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Egypt","alpha-2":"EG","alpha-3":"EGY","country-code":"818","iso_3166-2":"ISO 3166-2:EG","region":"Africa","sub-region":"Northern Africa","intermediate-region":"","region-code":"002","sub-region-code":"015","intermediate-region-code":""}, +{"name":"El Salvador","alpha-2":"SV","alpha-3":"SLV","country-code":"222","iso_3166-2":"ISO 3166-2:SV","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Equatorial Guinea","alpha-2":"GQ","alpha-3":"GNQ","country-code":"226","iso_3166-2":"ISO 3166-2:GQ","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Eritrea","alpha-2":"ER","alpha-3":"ERI","country-code":"232","iso_3166-2":"ISO 3166-2:ER","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Estonia","alpha-2":"EE","alpha-3":"EST","country-code":"233","iso_3166-2":"ISO 3166-2:EE","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Eswatini","alpha-2":"SZ","alpha-3":"SWZ","country-code":"748","iso_3166-2":"ISO 3166-2:SZ","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Southern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"018"}, +{"name":"Ethiopia","alpha-2":"ET","alpha-3":"ETH","country-code":"231","iso_3166-2":"ISO 3166-2:ET","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Falkland Islands (Malvinas)","alpha-2":"FK","alpha-3":"FLK","country-code":"238","iso_3166-2":"ISO 3166-2:FK","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Faroe Islands","alpha-2":"FO","alpha-3":"FRO","country-code":"234","iso_3166-2":"ISO 3166-2:FO","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Fiji","alpha-2":"FJ","alpha-3":"FJI","country-code":"242","iso_3166-2":"ISO 3166-2:FJ","region":"Oceania","sub-region":"Melanesia","intermediate-region":"","region-code":"009","sub-region-code":"054","intermediate-region-code":""}, +{"name":"Finland","alpha-2":"FI","alpha-3":"FIN","country-code":"246","iso_3166-2":"ISO 3166-2:FI","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"France","alpha-2":"FR","alpha-3":"FRA","country-code":"250","iso_3166-2":"ISO 3166-2:FR","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"French Guiana","alpha-2":"GF","alpha-3":"GUF","country-code":"254","iso_3166-2":"ISO 3166-2:GF","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"French Polynesia","alpha-2":"PF","alpha-3":"PYF","country-code":"258","iso_3166-2":"ISO 3166-2:PF","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"French Southern Territories","alpha-2":"TF","alpha-3":"ATF","country-code":"260","iso_3166-2":"ISO 3166-2:TF","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Gabon","alpha-2":"GA","alpha-3":"GAB","country-code":"266","iso_3166-2":"ISO 3166-2:GA","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Gambia","alpha-2":"GM","alpha-3":"GMB","country-code":"270","iso_3166-2":"ISO 3166-2:GM","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Georgia","alpha-2":"GE","alpha-3":"GEO","country-code":"268","iso_3166-2":"ISO 3166-2:GE","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Germany","alpha-2":"DE","alpha-3":"DEU","country-code":"276","iso_3166-2":"ISO 3166-2:DE","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"Ghana","alpha-2":"GH","alpha-3":"GHA","country-code":"288","iso_3166-2":"ISO 3166-2:GH","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Gibraltar","alpha-2":"GI","alpha-3":"GIB","country-code":"292","iso_3166-2":"ISO 3166-2:GI","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Greece","alpha-2":"GR","alpha-3":"GRC","country-code":"300","iso_3166-2":"ISO 3166-2:GR","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Greenland","alpha-2":"GL","alpha-3":"GRL","country-code":"304","iso_3166-2":"ISO 3166-2:GL","region":"Americas","sub-region":"Northern America","intermediate-region":"","region-code":"019","sub-region-code":"021","intermediate-region-code":""}, +{"name":"Grenada","alpha-2":"GD","alpha-3":"GRD","country-code":"308","iso_3166-2":"ISO 3166-2:GD","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Guadeloupe","alpha-2":"GP","alpha-3":"GLP","country-code":"312","iso_3166-2":"ISO 3166-2:GP","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Guam","alpha-2":"GU","alpha-3":"GUM","country-code":"316","iso_3166-2":"ISO 3166-2:GU","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Guatemala","alpha-2":"GT","alpha-3":"GTM","country-code":"320","iso_3166-2":"ISO 3166-2:GT","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Guernsey","alpha-2":"GG","alpha-3":"GGY","country-code":"831","iso_3166-2":"ISO 3166-2:GG","region":"Europe","sub-region":"Northern Europe","intermediate-region":"Channel Islands","region-code":"150","sub-region-code":"154","intermediate-region-code":"830"}, +{"name":"Guinea","alpha-2":"GN","alpha-3":"GIN","country-code":"324","iso_3166-2":"ISO 3166-2:GN","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Guinea-Bissau","alpha-2":"GW","alpha-3":"GNB","country-code":"624","iso_3166-2":"ISO 3166-2:GW","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Guyana","alpha-2":"GY","alpha-3":"GUY","country-code":"328","iso_3166-2":"ISO 3166-2:GY","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Haiti","alpha-2":"HT","alpha-3":"HTI","country-code":"332","iso_3166-2":"ISO 3166-2:HT","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Heard Island and McDonald Islands","alpha-2":"HM","alpha-3":"HMD","country-code":"334","iso_3166-2":"ISO 3166-2:HM","region":"Oceania","sub-region":"Australia and New Zealand","intermediate-region":"","region-code":"009","sub-region-code":"053","intermediate-region-code":""}, +{"name":"Holy See","alpha-2":"VA","alpha-3":"VAT","country-code":"336","iso_3166-2":"ISO 3166-2:VA","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Honduras","alpha-2":"HN","alpha-3":"HND","country-code":"340","iso_3166-2":"ISO 3166-2:HN","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Hong Kong","alpha-2":"HK","alpha-3":"HKG","country-code":"344","iso_3166-2":"ISO 3166-2:HK","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Hungary","alpha-2":"HU","alpha-3":"HUN","country-code":"348","iso_3166-2":"ISO 3166-2:HU","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Iceland","alpha-2":"IS","alpha-3":"ISL","country-code":"352","iso_3166-2":"ISO 3166-2:IS","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"India","alpha-2":"IN","alpha-3":"IND","country-code":"356","iso_3166-2":"ISO 3166-2:IN","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Indonesia","alpha-2":"ID","alpha-3":"IDN","country-code":"360","iso_3166-2":"ISO 3166-2:ID","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Iran (Islamic Republic of)","alpha-2":"IR","alpha-3":"IRN","country-code":"364","iso_3166-2":"ISO 3166-2:IR","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Iraq","alpha-2":"IQ","alpha-3":"IRQ","country-code":"368","iso_3166-2":"ISO 3166-2:IQ","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Ireland","alpha-2":"IE","alpha-3":"IRL","country-code":"372","iso_3166-2":"ISO 3166-2:IE","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Isle of Man","alpha-2":"IM","alpha-3":"IMN","country-code":"833","iso_3166-2":"ISO 3166-2:IM","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Israel","alpha-2":"IL","alpha-3":"ISR","country-code":"376","iso_3166-2":"ISO 3166-2:IL","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Italy","alpha-2":"IT","alpha-3":"ITA","country-code":"380","iso_3166-2":"ISO 3166-2:IT","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Jamaica","alpha-2":"JM","alpha-3":"JAM","country-code":"388","iso_3166-2":"ISO 3166-2:JM","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Japan","alpha-2":"JP","alpha-3":"JPN","country-code":"392","iso_3166-2":"ISO 3166-2:JP","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Jersey","alpha-2":"JE","alpha-3":"JEY","country-code":"832","iso_3166-2":"ISO 3166-2:JE","region":"Europe","sub-region":"Northern Europe","intermediate-region":"Channel Islands","region-code":"150","sub-region-code":"154","intermediate-region-code":"830"}, +{"name":"Jordan","alpha-2":"JO","alpha-3":"JOR","country-code":"400","iso_3166-2":"ISO 3166-2:JO","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Kazakhstan","alpha-2":"KZ","alpha-3":"KAZ","country-code":"398","iso_3166-2":"ISO 3166-2:KZ","region":"Asia","sub-region":"Central Asia","intermediate-region":"","region-code":"142","sub-region-code":"143","intermediate-region-code":""}, +{"name":"Kenya","alpha-2":"KE","alpha-3":"KEN","country-code":"404","iso_3166-2":"ISO 3166-2:KE","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Kiribati","alpha-2":"KI","alpha-3":"KIR","country-code":"296","iso_3166-2":"ISO 3166-2:KI","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Korea (Democratic People's Republic of)","alpha-2":"KP","alpha-3":"PRK","country-code":"408","iso_3166-2":"ISO 3166-2:KP","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Korea, Republic of","alpha-2":"KR","alpha-3":"KOR","country-code":"410","iso_3166-2":"ISO 3166-2:KR","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Kuwait","alpha-2":"KW","alpha-3":"KWT","country-code":"414","iso_3166-2":"ISO 3166-2:KW","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Kyrgyzstan","alpha-2":"KG","alpha-3":"KGZ","country-code":"417","iso_3166-2":"ISO 3166-2:KG","region":"Asia","sub-region":"Central Asia","intermediate-region":"","region-code":"142","sub-region-code":"143","intermediate-region-code":""}, +{"name":"Lao People's Democratic Republic","alpha-2":"LA","alpha-3":"LAO","country-code":"418","iso_3166-2":"ISO 3166-2:LA","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Latvia","alpha-2":"LV","alpha-3":"LVA","country-code":"428","iso_3166-2":"ISO 3166-2:LV","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Lebanon","alpha-2":"LB","alpha-3":"LBN","country-code":"422","iso_3166-2":"ISO 3166-2:LB","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Lesotho","alpha-2":"LS","alpha-3":"LSO","country-code":"426","iso_3166-2":"ISO 3166-2:LS","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Southern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"018"}, +{"name":"Liberia","alpha-2":"LR","alpha-3":"LBR","country-code":"430","iso_3166-2":"ISO 3166-2:LR","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Libya","alpha-2":"LY","alpha-3":"LBY","country-code":"434","iso_3166-2":"ISO 3166-2:LY","region":"Africa","sub-region":"Northern Africa","intermediate-region":"","region-code":"002","sub-region-code":"015","intermediate-region-code":""}, +{"name":"Liechtenstein","alpha-2":"LI","alpha-3":"LIE","country-code":"438","iso_3166-2":"ISO 3166-2:LI","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"Lithuania","alpha-2":"LT","alpha-3":"LTU","country-code":"440","iso_3166-2":"ISO 3166-2:LT","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Luxembourg","alpha-2":"LU","alpha-3":"LUX","country-code":"442","iso_3166-2":"ISO 3166-2:LU","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"Macao","alpha-2":"MO","alpha-3":"MAC","country-code":"446","iso_3166-2":"ISO 3166-2:MO","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Madagascar","alpha-2":"MG","alpha-3":"MDG","country-code":"450","iso_3166-2":"ISO 3166-2:MG","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Malawi","alpha-2":"MW","alpha-3":"MWI","country-code":"454","iso_3166-2":"ISO 3166-2:MW","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Malaysia","alpha-2":"MY","alpha-3":"MYS","country-code":"458","iso_3166-2":"ISO 3166-2:MY","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Maldives","alpha-2":"MV","alpha-3":"MDV","country-code":"462","iso_3166-2":"ISO 3166-2:MV","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Mali","alpha-2":"ML","alpha-3":"MLI","country-code":"466","iso_3166-2":"ISO 3166-2:ML","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Malta","alpha-2":"MT","alpha-3":"MLT","country-code":"470","iso_3166-2":"ISO 3166-2:MT","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Marshall Islands","alpha-2":"MH","alpha-3":"MHL","country-code":"584","iso_3166-2":"ISO 3166-2:MH","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Martinique","alpha-2":"MQ","alpha-3":"MTQ","country-code":"474","iso_3166-2":"ISO 3166-2:MQ","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Mauritania","alpha-2":"MR","alpha-3":"MRT","country-code":"478","iso_3166-2":"ISO 3166-2:MR","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Mauritius","alpha-2":"MU","alpha-3":"MUS","country-code":"480","iso_3166-2":"ISO 3166-2:MU","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Mayotte","alpha-2":"YT","alpha-3":"MYT","country-code":"175","iso_3166-2":"ISO 3166-2:YT","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Mexico","alpha-2":"MX","alpha-3":"MEX","country-code":"484","iso_3166-2":"ISO 3166-2:MX","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Micronesia (Federated States of)","alpha-2":"FM","alpha-3":"FSM","country-code":"583","iso_3166-2":"ISO 3166-2:FM","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Moldova, Republic of","alpha-2":"MD","alpha-3":"MDA","country-code":"498","iso_3166-2":"ISO 3166-2:MD","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Monaco","alpha-2":"MC","alpha-3":"MCO","country-code":"492","iso_3166-2":"ISO 3166-2:MC","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"Mongolia","alpha-2":"MN","alpha-3":"MNG","country-code":"496","iso_3166-2":"ISO 3166-2:MN","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Montenegro","alpha-2":"ME","alpha-3":"MNE","country-code":"499","iso_3166-2":"ISO 3166-2:ME","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Montserrat","alpha-2":"MS","alpha-3":"MSR","country-code":"500","iso_3166-2":"ISO 3166-2:MS","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Morocco","alpha-2":"MA","alpha-3":"MAR","country-code":"504","iso_3166-2":"ISO 3166-2:MA","region":"Africa","sub-region":"Northern Africa","intermediate-region":"","region-code":"002","sub-region-code":"015","intermediate-region-code":""}, +{"name":"Mozambique","alpha-2":"MZ","alpha-3":"MOZ","country-code":"508","iso_3166-2":"ISO 3166-2:MZ","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Myanmar","alpha-2":"MM","alpha-3":"MMR","country-code":"104","iso_3166-2":"ISO 3166-2:MM","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Namibia","alpha-2":"NA","alpha-3":"NAM","country-code":"516","iso_3166-2":"ISO 3166-2:NA","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Southern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"018"}, +{"name":"Nauru","alpha-2":"NR","alpha-3":"NRU","country-code":"520","iso_3166-2":"ISO 3166-2:NR","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Nepal","alpha-2":"NP","alpha-3":"NPL","country-code":"524","iso_3166-2":"ISO 3166-2:NP","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Netherlands","alpha-2":"NL","alpha-3":"NLD","country-code":"528","iso_3166-2":"ISO 3166-2:NL","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"New Caledonia","alpha-2":"NC","alpha-3":"NCL","country-code":"540","iso_3166-2":"ISO 3166-2:NC","region":"Oceania","sub-region":"Melanesia","intermediate-region":"","region-code":"009","sub-region-code":"054","intermediate-region-code":""}, +{"name":"New Zealand","alpha-2":"NZ","alpha-3":"NZL","country-code":"554","iso_3166-2":"ISO 3166-2:NZ","region":"Oceania","sub-region":"Australia and New Zealand","intermediate-region":"","region-code":"009","sub-region-code":"053","intermediate-region-code":""}, +{"name":"Nicaragua","alpha-2":"NI","alpha-3":"NIC","country-code":"558","iso_3166-2":"ISO 3166-2:NI","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Niger","alpha-2":"NE","alpha-3":"NER","country-code":"562","iso_3166-2":"ISO 3166-2:NE","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Nigeria","alpha-2":"NG","alpha-3":"NGA","country-code":"566","iso_3166-2":"ISO 3166-2:NG","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Niue","alpha-2":"NU","alpha-3":"NIU","country-code":"570","iso_3166-2":"ISO 3166-2:NU","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Norfolk Island","alpha-2":"NF","alpha-3":"NFK","country-code":"574","iso_3166-2":"ISO 3166-2:NF","region":"Oceania","sub-region":"Australia and New Zealand","intermediate-region":"","region-code":"009","sub-region-code":"053","intermediate-region-code":""}, +{"name":"North Macedonia","alpha-2":"MK","alpha-3":"MKD","country-code":"807","iso_3166-2":"ISO 3166-2:MK","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Northern Mariana Islands","alpha-2":"MP","alpha-3":"MNP","country-code":"580","iso_3166-2":"ISO 3166-2:MP","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Norway","alpha-2":"NO","alpha-3":"NOR","country-code":"578","iso_3166-2":"ISO 3166-2:NO","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Oman","alpha-2":"OM","alpha-3":"OMN","country-code":"512","iso_3166-2":"ISO 3166-2:OM","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Pakistan","alpha-2":"PK","alpha-3":"PAK","country-code":"586","iso_3166-2":"ISO 3166-2:PK","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Palau","alpha-2":"PW","alpha-3":"PLW","country-code":"585","iso_3166-2":"ISO 3166-2:PW","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Palestine, State of","alpha-2":"PS","alpha-3":"PSE","country-code":"275","iso_3166-2":"ISO 3166-2:PS","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Panama","alpha-2":"PA","alpha-3":"PAN","country-code":"591","iso_3166-2":"ISO 3166-2:PA","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Central America","region-code":"019","sub-region-code":"419","intermediate-region-code":"013"}, +{"name":"Papua New Guinea","alpha-2":"PG","alpha-3":"PNG","country-code":"598","iso_3166-2":"ISO 3166-2:PG","region":"Oceania","sub-region":"Melanesia","intermediate-region":"","region-code":"009","sub-region-code":"054","intermediate-region-code":""}, +{"name":"Paraguay","alpha-2":"PY","alpha-3":"PRY","country-code":"600","iso_3166-2":"ISO 3166-2:PY","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Peru","alpha-2":"PE","alpha-3":"PER","country-code":"604","iso_3166-2":"ISO 3166-2:PE","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Philippines","alpha-2":"PH","alpha-3":"PHL","country-code":"608","iso_3166-2":"ISO 3166-2:PH","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Pitcairn","alpha-2":"PN","alpha-3":"PCN","country-code":"612","iso_3166-2":"ISO 3166-2:PN","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Poland","alpha-2":"PL","alpha-3":"POL","country-code":"616","iso_3166-2":"ISO 3166-2:PL","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Portugal","alpha-2":"PT","alpha-3":"PRT","country-code":"620","iso_3166-2":"ISO 3166-2:PT","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Puerto Rico","alpha-2":"PR","alpha-3":"PRI","country-code":"630","iso_3166-2":"ISO 3166-2:PR","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Qatar","alpha-2":"QA","alpha-3":"QAT","country-code":"634","iso_3166-2":"ISO 3166-2:QA","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Réunion","alpha-2":"RE","alpha-3":"REU","country-code":"638","iso_3166-2":"ISO 3166-2:RE","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Romania","alpha-2":"RO","alpha-3":"ROU","country-code":"642","iso_3166-2":"ISO 3166-2:RO","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Russian Federation","alpha-2":"RU","alpha-3":"RUS","country-code":"643","iso_3166-2":"ISO 3166-2:RU","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Rwanda","alpha-2":"RW","alpha-3":"RWA","country-code":"646","iso_3166-2":"ISO 3166-2:RW","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Saint Barthélemy","alpha-2":"BL","alpha-3":"BLM","country-code":"652","iso_3166-2":"ISO 3166-2:BL","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Saint Helena, Ascension and Tristan da Cunha","alpha-2":"SH","alpha-3":"SHN","country-code":"654","iso_3166-2":"ISO 3166-2:SH","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Saint Kitts and Nevis","alpha-2":"KN","alpha-3":"KNA","country-code":"659","iso_3166-2":"ISO 3166-2:KN","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Saint Lucia","alpha-2":"LC","alpha-3":"LCA","country-code":"662","iso_3166-2":"ISO 3166-2:LC","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Saint Martin (French part)","alpha-2":"MF","alpha-3":"MAF","country-code":"663","iso_3166-2":"ISO 3166-2:MF","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Saint Pierre and Miquelon","alpha-2":"PM","alpha-3":"SPM","country-code":"666","iso_3166-2":"ISO 3166-2:PM","region":"Americas","sub-region":"Northern America","intermediate-region":"","region-code":"019","sub-region-code":"021","intermediate-region-code":""}, +{"name":"Saint Vincent and the Grenadines","alpha-2":"VC","alpha-3":"VCT","country-code":"670","iso_3166-2":"ISO 3166-2:VC","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Samoa","alpha-2":"WS","alpha-3":"WSM","country-code":"882","iso_3166-2":"ISO 3166-2:WS","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"San Marino","alpha-2":"SM","alpha-3":"SMR","country-code":"674","iso_3166-2":"ISO 3166-2:SM","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Sao Tome and Principe","alpha-2":"ST","alpha-3":"STP","country-code":"678","iso_3166-2":"ISO 3166-2:ST","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Middle Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"017"}, +{"name":"Saudi Arabia","alpha-2":"SA","alpha-3":"SAU","country-code":"682","iso_3166-2":"ISO 3166-2:SA","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Senegal","alpha-2":"SN","alpha-3":"SEN","country-code":"686","iso_3166-2":"ISO 3166-2:SN","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Serbia","alpha-2":"RS","alpha-3":"SRB","country-code":"688","iso_3166-2":"ISO 3166-2:RS","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Seychelles","alpha-2":"SC","alpha-3":"SYC","country-code":"690","iso_3166-2":"ISO 3166-2:SC","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Sierra Leone","alpha-2":"SL","alpha-3":"SLE","country-code":"694","iso_3166-2":"ISO 3166-2:SL","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Singapore","alpha-2":"SG","alpha-3":"SGP","country-code":"702","iso_3166-2":"ISO 3166-2:SG","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Sint Maarten (Dutch part)","alpha-2":"SX","alpha-3":"SXM","country-code":"534","iso_3166-2":"ISO 3166-2:SX","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Slovakia","alpha-2":"SK","alpha-3":"SVK","country-code":"703","iso_3166-2":"ISO 3166-2:SK","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"Slovenia","alpha-2":"SI","alpha-3":"SVN","country-code":"705","iso_3166-2":"ISO 3166-2:SI","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Solomon Islands","alpha-2":"SB","alpha-3":"SLB","country-code":"090","iso_3166-2":"ISO 3166-2:SB","region":"Oceania","sub-region":"Melanesia","intermediate-region":"","region-code":"009","sub-region-code":"054","intermediate-region-code":""}, +{"name":"Somalia","alpha-2":"SO","alpha-3":"SOM","country-code":"706","iso_3166-2":"ISO 3166-2:SO","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"South Africa","alpha-2":"ZA","alpha-3":"ZAF","country-code":"710","iso_3166-2":"ISO 3166-2:ZA","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Southern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"018"}, +{"name":"South Georgia and the South Sandwich Islands","alpha-2":"GS","alpha-3":"SGS","country-code":"239","iso_3166-2":"ISO 3166-2:GS","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"South Sudan","alpha-2":"SS","alpha-3":"SSD","country-code":"728","iso_3166-2":"ISO 3166-2:SS","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Spain","alpha-2":"ES","alpha-3":"ESP","country-code":"724","iso_3166-2":"ISO 3166-2:ES","region":"Europe","sub-region":"Southern Europe","intermediate-region":"","region-code":"150","sub-region-code":"039","intermediate-region-code":""}, +{"name":"Sri Lanka","alpha-2":"LK","alpha-3":"LKA","country-code":"144","iso_3166-2":"ISO 3166-2:LK","region":"Asia","sub-region":"Southern Asia","intermediate-region":"","region-code":"142","sub-region-code":"034","intermediate-region-code":""}, +{"name":"Sudan","alpha-2":"SD","alpha-3":"SDN","country-code":"729","iso_3166-2":"ISO 3166-2:SD","region":"Africa","sub-region":"Northern Africa","intermediate-region":"","region-code":"002","sub-region-code":"015","intermediate-region-code":""}, +{"name":"Suriname","alpha-2":"SR","alpha-3":"SUR","country-code":"740","iso_3166-2":"ISO 3166-2:SR","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Svalbard and Jan Mayen","alpha-2":"SJ","alpha-3":"SJM","country-code":"744","iso_3166-2":"ISO 3166-2:SJ","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Sweden","alpha-2":"SE","alpha-3":"SWE","country-code":"752","iso_3166-2":"ISO 3166-2:SE","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"Switzerland","alpha-2":"CH","alpha-3":"CHE","country-code":"756","iso_3166-2":"ISO 3166-2:CH","region":"Europe","sub-region":"Western Europe","intermediate-region":"","region-code":"150","sub-region-code":"155","intermediate-region-code":""}, +{"name":"Syrian Arab Republic","alpha-2":"SY","alpha-3":"SYR","country-code":"760","iso_3166-2":"ISO 3166-2:SY","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Taiwan, Province of China","alpha-2":"TW","alpha-3":"TWN","country-code":"158","iso_3166-2":"ISO 3166-2:TW","region":"Asia","sub-region":"Eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"030","intermediate-region-code":""}, +{"name":"Tajikistan","alpha-2":"TJ","alpha-3":"TJK","country-code":"762","iso_3166-2":"ISO 3166-2:TJ","region":"Asia","sub-region":"Central Asia","intermediate-region":"","region-code":"142","sub-region-code":"143","intermediate-region-code":""}, +{"name":"Tanzania, United Republic of","alpha-2":"TZ","alpha-3":"TZA","country-code":"834","iso_3166-2":"ISO 3166-2:TZ","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Thailand","alpha-2":"TH","alpha-3":"THA","country-code":"764","iso_3166-2":"ISO 3166-2:TH","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Timor-Leste","alpha-2":"TL","alpha-3":"TLS","country-code":"626","iso_3166-2":"ISO 3166-2:TL","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Togo","alpha-2":"TG","alpha-3":"TGO","country-code":"768","iso_3166-2":"ISO 3166-2:TG","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Western Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"011"}, +{"name":"Tokelau","alpha-2":"TK","alpha-3":"TKL","country-code":"772","iso_3166-2":"ISO 3166-2:TK","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Tonga","alpha-2":"TO","alpha-3":"TON","country-code":"776","iso_3166-2":"ISO 3166-2:TO","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Trinidad and Tobago","alpha-2":"TT","alpha-3":"TTO","country-code":"780","iso_3166-2":"ISO 3166-2:TT","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Tunisia","alpha-2":"TN","alpha-3":"TUN","country-code":"788","iso_3166-2":"ISO 3166-2:TN","region":"Africa","sub-region":"Northern Africa","intermediate-region":"","region-code":"002","sub-region-code":"015","intermediate-region-code":""}, +{"name":"Turkey","alpha-2":"TR","alpha-3":"TUR","country-code":"792","iso_3166-2":"ISO 3166-2:TR","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Turkmenistan","alpha-2":"TM","alpha-3":"TKM","country-code":"795","iso_3166-2":"ISO 3166-2:TM","region":"Asia","sub-region":"Central Asia","intermediate-region":"","region-code":"142","sub-region-code":"143","intermediate-region-code":""}, +{"name":"Turks and Caicos Islands","alpha-2":"TC","alpha-3":"TCA","country-code":"796","iso_3166-2":"ISO 3166-2:TC","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Tuvalu","alpha-2":"TV","alpha-3":"TUV","country-code":"798","iso_3166-2":"ISO 3166-2:TV","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Uganda","alpha-2":"UG","alpha-3":"UGA","country-code":"800","iso_3166-2":"ISO 3166-2:UG","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Ukraine","alpha-2":"UA","alpha-3":"UKR","country-code":"804","iso_3166-2":"ISO 3166-2:UA","region":"Europe","sub-region":"Eastern Europe","intermediate-region":"","region-code":"150","sub-region-code":"151","intermediate-region-code":""}, +{"name":"United Arab Emirates","alpha-2":"AE","alpha-3":"ARE","country-code":"784","iso_3166-2":"ISO 3166-2:AE","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"United Kingdom of Great Britain and Northern Ireland","alpha-2":"GB","alpha-3":"GBR","country-code":"826","iso_3166-2":"ISO 3166-2:GB","region":"Europe","sub-region":"Northern Europe","intermediate-region":"","region-code":"150","sub-region-code":"154","intermediate-region-code":""}, +{"name":"United States of America","alpha-2":"US","alpha-3":"USA","country-code":"840","iso_3166-2":"ISO 3166-2:US","region":"Americas","sub-region":"Northern America","intermediate-region":"","region-code":"019","sub-region-code":"021","intermediate-region-code":""}, +{"name":"United States Minor Outlying Islands","alpha-2":"UM","alpha-3":"UMI","country-code":"581","iso_3166-2":"ISO 3166-2:UM","region":"Oceania","sub-region":"Micronesia","intermediate-region":"","region-code":"009","sub-region-code":"057","intermediate-region-code":""}, +{"name":"Uruguay","alpha-2":"UY","alpha-3":"URY","country-code":"858","iso_3166-2":"ISO 3166-2:UY","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Uzbekistan","alpha-2":"UZ","alpha-3":"UZB","country-code":"860","iso_3166-2":"ISO 3166-2:UZ","region":"Asia","sub-region":"Central Asia","intermediate-region":"","region-code":"142","sub-region-code":"143","intermediate-region-code":""}, +{"name":"Vanuatu","alpha-2":"VU","alpha-3":"VUT","country-code":"548","iso_3166-2":"ISO 3166-2:VU","region":"Oceania","sub-region":"Melanesia","intermediate-region":"","region-code":"009","sub-region-code":"054","intermediate-region-code":""}, +{"name":"Venezuela (Bolivarian Republic of)","alpha-2":"VE","alpha-3":"VEN","country-code":"862","iso_3166-2":"ISO 3166-2:VE","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"South America","region-code":"019","sub-region-code":"419","intermediate-region-code":"005"}, +{"name":"Viet Nam","alpha-2":"VN","alpha-3":"VNM","country-code":"704","iso_3166-2":"ISO 3166-2:VN","region":"Asia","sub-region":"South-eastern Asia","intermediate-region":"","region-code":"142","sub-region-code":"035","intermediate-region-code":""}, +{"name":"Virgin Islands (British)","alpha-2":"VG","alpha-3":"VGB","country-code":"092","iso_3166-2":"ISO 3166-2:VG","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Virgin Islands (U.S.)","alpha-2":"VI","alpha-3":"VIR","country-code":"850","iso_3166-2":"ISO 3166-2:VI","region":"Americas","sub-region":"Latin America and the Caribbean","intermediate-region":"Caribbean","region-code":"019","sub-region-code":"419","intermediate-region-code":"029"}, +{"name":"Wallis and Futuna","alpha-2":"WF","alpha-3":"WLF","country-code":"876","iso_3166-2":"ISO 3166-2:WF","region":"Oceania","sub-region":"Polynesia","intermediate-region":"","region-code":"009","sub-region-code":"061","intermediate-region-code":""}, +{"name":"Western Sahara","alpha-2":"EH","alpha-3":"ESH","country-code":"732","iso_3166-2":"ISO 3166-2:EH","region":"Africa","sub-region":"Northern Africa","intermediate-region":"","region-code":"002","sub-region-code":"015","intermediate-region-code":""}, +{"name":"Yemen","alpha-2":"YE","alpha-3":"YEM","country-code":"887","iso_3166-2":"ISO 3166-2:YE","region":"Asia","sub-region":"Western Asia","intermediate-region":"","region-code":"142","sub-region-code":"145","intermediate-region-code":""}, +{"name":"Zambia","alpha-2":"ZM","alpha-3":"ZMB","country-code":"894","iso_3166-2":"ISO 3166-2:ZM","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"}, +{"name":"Zimbabwe","alpha-2":"ZW","alpha-3":"ZWE","country-code":"716","iso_3166-2":"ISO 3166-2:ZW","region":"Africa","sub-region":"Sub-Saharan Africa","intermediate-region":"Eastern Africa","region-code":"002","sub-region-code":"202","intermediate-region-code":"014"} +] diff --git a/vendor/github.com/go-openapi/strfmt/mongo.go b/vendor/github.com/go-openapi/strfmt/mongo.go index be904ffa5de..15bfbed192f 100644 --- a/vendor/github.com/go-openapi/strfmt/mongo.go +++ b/vendor/github.com/go-openapi/strfmt/mongo.go @@ -4,7 +4,6 @@ package strfmt import ( - "encoding/base64" "encoding/binary" "fmt" "time" @@ -41,6 +40,8 @@ var ( _ bsonUnmarshaler = &Base64{} _ bsonMarshaler = Duration(0) _ bsonUnmarshaler = (*Duration)(nil) + _ bsonMarshaler = DurationISO8601(0) + _ bsonUnmarshaler = (*DurationISO8601)(nil) _ bsonMarshaler = DateTime{} _ bsonUnmarshaler = &DateTime{} _ bsonMarshaler = ULID{} @@ -92,6 +93,10 @@ var ( _ bsonValueUnmarshaler = &DateTime{} _ bsonValueMarshaler = ObjectId{} _ bsonValueUnmarshaler = &ObjectId{} + _ bsonMarshaler = Currency{} + _ bsonUnmarshaler = (*Currency)(nil) + _ bsonMarshaler = Country{} + _ bsonUnmarshaler = (*Country)(nil) ) const ( @@ -140,7 +145,7 @@ func (b *Base64) UnmarshalBSON(data []byte) error { return fmt.Errorf("couldn't unmarshal bson bytes as base64: %w", ErrFormat) } - vb, err := base64.StdEncoding.DecodeString(s) + vb, err := base64Encoding.DecodeString(s) if err != nil { return err } @@ -171,6 +176,38 @@ func (d *Duration) UnmarshalBSON(data []byte) error { return nil } +// MarshalBSON renders the [ISODuration] as a BSON document. +// +// BSON is a storage boundary (like SQL): the value is emitted losslessly with [ISODuration.String], regardless of the +// policy P — a strict policy that could not serialize a sign or sub-second precision on the interchange path must still +// be persistable. +func (d ISODuration[P]) MarshalBSON() ([]byte, error) { + return bsonlite.C.MarshalDoc(d.String()) +} + +// UnmarshalBSON reads an [ISODuration] from a BSON document. +// +// The stored value is our own canonical output, so it is parsed leniently: BSON is trusted storage, not external +// interchange, and must round-trip whatever [ISODuration.MarshalBSON] emitted even under a strict policy P. +func (d *ISODuration[P]) UnmarshalBSON(data []byte) error { + v, err := bsonlite.C.UnmarshalDoc(data) + if err != nil { + return err + } + + s, ok := v.(string) + if !ok { + return fmt.Errorf("couldn't unmarshal bson bytes value as ISODuration: %w", ErrFormat) + } + + rd, err := parseISO8601Duration(s, DurationLenient{}.isoDurationConfig()) + if err != nil { + return err + } + *d = ISODuration[P](rd) + return nil +} + // MarshalBSON renders the [DateTime] as a BSON document. func (t DateTime) MarshalBSON() ([]byte, error) { tNorm := NormalizeTimeForMarshal(time.Time(t)) @@ -599,3 +636,47 @@ func (id *ObjectId) UnmarshalBSONValue(_ byte, data []byte) error { *id = ObjectId(oid) return nil } + +// MarshalBSON document from this value. +func (u Currency) MarshalBSON() ([]byte, error) { + return bsonlite.C.MarshalDoc(u.String()) +} + +// UnmarshalBSON document into this value. +func (u *Currency) UnmarshalBSON(data []byte) error { + s, err := unmarshalBSONString(data, "Currency") + if err != nil { + return err + } + + cur, err := ParseCurrency(s) + if err != nil { + return err + } + + *u = cur + + return nil +} + +// MarshalBSON document from this value. +func (u Country) MarshalBSON() ([]byte, error) { + return bsonlite.C.MarshalDoc(u.String()) +} + +// UnmarshalBSON document into this value. +func (u *Country) UnmarshalBSON(data []byte) error { + s, err := unmarshalBSONString(data, "Country") + if err != nil { + return err + } + + cur, err := ParseCountry(s) + if err != nil { + return err + } + + *u = cur + + return nil +} diff --git a/vendor/github.com/go-openapi/strfmt/register.go b/vendor/github.com/go-openapi/strfmt/register.go new file mode 100644 index 00000000000..4a4c185b53a --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/register.go @@ -0,0 +1,138 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package strfmt + +// Default is the default formats registry. +// +// NOTE: format "duration" is wire by default onto "duration-human". +var Default Registry //nolint:gochecknoglobals // package-level default registry, by design + +// JSONSchema2020Registry is the format registry with JSONSchema draft 2020 formats (e.g. duration is an iso8601 duration). +var JSONSchema2020Registry Registry //nolint:gochecknoglobals // package-level default registry, by design + +func init() { //nolint:gochecknoinits // registers all default string formats in the registry + // register formats in the default registry: + // - byte + // - creditcard + // - email + // - hexcolor + // - hostname + // - ipv4 + // - ipv6 + // - cidr + // - isbn + // - isbn10 + // - isbn13 + // - mac + // - password + // - rgbcolor + // - ssn + // - uri + // - uuid + // - uuid3 + // - uuid4 + // - uuid5 + // - uuid7 + // - ulid + // - date, date-time + // - duration, duration-human, duration-iso8601 + // - objectid + // - currency, country + Default = NewSeededFormats(nil, nil) + + u := URI("") + Default.Add("uri", &u, isRequestURI) + + eml := Email("") + Default.Add("email", &eml, IsEmail) + + hn := Hostname("") + Default.Add("hostname", &hn, IsHostname) + + ip4 := IPv4("") + Default.Add("ipv4", &ip4, isIPv4) + + ip6 := IPv6("") + Default.Add("ipv6", &ip6, isIPv6) + + cidr := CIDR("") + Default.Add("cidr", &cidr, isCIDR) + + mac := MAC("") + Default.Add("mac", &mac, isMAC) + + uid := UUID("") + Default.Add("uuid", &uid, IsUUID) + + uid3 := UUID3("") + Default.Add("uuid3", &uid3, IsUUID3) + + uid4 := UUID4("") + Default.Add("uuid4", &uid4, IsUUID4) + + uid5 := UUID5("") + Default.Add("uuid5", &uid5, IsUUID5) + + uid7 := UUID7("") + Default.Add("uuid7", &uid7, IsUUID7) + + isbn := ISBN("") + Default.Add("isbn", &isbn, func(str string) bool { return isISBN10(str) || isISBN13(str) }) + + isbn10 := ISBN10("") + Default.Add("isbn10", &isbn10, isISBN10) + + isbn13 := ISBN13("") + Default.Add("isbn13", &isbn13, isISBN13) + + cc := CreditCard("") + Default.Add("creditcard", &cc, isCreditCard) + + ssn := SSN("") + Default.Add("ssn", &ssn, isSSN) + + hc := HexColor("") + Default.Add("hexcolor", &hc, isHexcolor) + + rc := RGBColor("") + Default.Add("rgbcolor", &rc, isRGBcolor) + + b64 := Base64([]byte(nil)) + Default.Add("byte", &b64, isBase64) + + pw := Password("") + Default.Add("password", &pw, func(_ string) bool { return true }) + + d := Date{} + Default.Add("date", &d, IsDate) + + dt := DateTime{} + Default.Add("datetime", &dt, IsDateTime) + + du := Duration(0) + Default.Add("duration", &du, IsDuration) + Default.Add("duration-human", &du, IsDuration) + + di := DurationISO8601(0) + Default.Add("duration-iso8601", &di, IsDurationISO8601) + + var id ObjectId + Default.Add("bsonobjectid", &id, IsBSONObjectID) + + ulid := ULID{} + Default.Add("ulid", &ulid, IsULID) + + cur := Currency{} + Default.Add("currency", &cur, IsCurrency) + + co := Country{} + Default.Add("country", &co, IsCountry) + + def, ok := Default.(*defaultFormats) + if !ok { + panic("internal error: can't initialize") + } + + JSONSchema2020Registry = NewSeededFormats(def.data, JSONSchema2020Normalizer) +} diff --git a/vendor/github.com/go-openapi/strfmt/time.go b/vendor/github.com/go-openapi/strfmt/time.go index 1fde8c6b119..94e409e0637 100644 --- a/vendor/github.com/go-openapi/strfmt/time.go +++ b/vendor/github.com/go-openapi/strfmt/time.go @@ -17,11 +17,6 @@ import ( // Unix 0 for an EST timezone is not equivalent to a UTC timezone. var UnixZero = time.Unix(0, 0).UTC() //nolint:gochecknoglobals // package-level sentinel value for unix epoch -func init() { //nolint:gochecknoinits // registers datetime format in the default registry - dt := DateTime{} - Default.Add("datetime", &dt, IsDateTime) -} - // IsDateTime returns true when the string is a valid date-time. // // JSON datetime format consist of a date and a time separated by a "T", e.g. 2012-04-23T18:25:43.511Z. diff --git a/vendor/github.com/go-openapi/strfmt/ulid.go b/vendor/github.com/go-openapi/strfmt/ulid.go index f05d22c5187..38809adba42 100644 --- a/vendor/github.com/go-openapi/strfmt/ulid.go +++ b/vendor/github.com/go-openapi/strfmt/ulid.go @@ -69,11 +69,6 @@ var ( ULIDValueOverrideFunc = ULIDValueDefaultFunc ) -func init() { //nolint:gochecknoinits // registers ulid format in the default registry - ulid := ULID{} - Default.Add("ulid", &ulid, IsULID) -} - // IsULID checks if provided string is [ULID] format // Be noticed that this function considers overflowed [ULID] as non-[ulid]. // For more details see https://github.com/[ulid]/spec diff --git a/vendor/github.com/go-openapi/swag/.gitignore b/vendor/github.com/go-openapi/swag/.gitignore index 1680db44c01..3ceb596fa2a 100644 --- a/vendor/github.com/go-openapi/swag/.gitignore +++ b/vendor/github.com/go-openapi/swag/.gitignore @@ -4,3 +4,4 @@ Godeps .idea *.out .mcp.json +.worktrees diff --git a/vendor/github.com/go-openapi/swag/.golangci.yml b/vendor/github.com/go-openapi/swag/.golangci.yml index 126264a6b89..099c0a78c63 100644 --- a/vendor/github.com/go-openapi/swag/.golangci.yml +++ b/vendor/github.com/go-openapi/swag/.golangci.yml @@ -14,7 +14,10 @@ linters: - gocognit - godot - godox + - goconst - gomoddirectives + - gomodguard + - gomodguard_v2 - gosmopolitan - inamedparam - intrange diff --git a/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md b/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md index 286878acff9..0f0711cd5f4 100644 --- a/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md @@ -4,11 +4,11 @@ | Total Contributors | Total Contributions | | --- | --- | -| 24 | 242 | +| 24 | 251 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | -| @fredbi | 112 | | +| @fredbi | 121 | | | @casualjim | 98 | | | @alexandear | 4 | | | @orisano | 3 | | diff --git a/vendor/github.com/go-openapi/swag/README.md b/vendor/github.com/go-openapi/swag/README.md index 64f66710397..c6c2d21e944 100644 --- a/vendor/github.com/go-openapi/swag/README.md +++ b/vendor/github.com/go-openapi/swag/README.md @@ -34,12 +34,9 @@ You may also use it standalone for your projects. * **2025-12-19** : new community chat on discord * a new discord community channel is available to be notified of changes and support users - * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] -Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] - ## Status API is stable. @@ -70,11 +67,12 @@ Child modules will continue to evolve and some new ones may be added in the futu | `cmdutils` | utilities to work with CLIs || | `conv` | type conversion utilities | convert between values and pointers for any types
convert from string to builtin types (wraps `strconv`)
require `./typeutils` (test dependency)
| | `fileutils` | file utilities | | -| `jsonname` | JSON utilities | infer JSON names from `go` properties
| +| `jsonname` | JSON utilities (deprecated) | infer JSON names from `go` properties
use `github.com/go-openapi/jsonpointer/jsonname` instead | | `jsonutils` | JSON utilities | fast json concatenation
read and write JSON from and to dynamic `go` data structures
~require `github.com/mailru/easyjson`~
| | `loading` | file loading | load from file or http
require `./yamlutils`
| | `mangling` | safe name generation | name mangling for `go`
| | `netutils` | networking utilities | host, port from address
| +| `pools` | utilities to work with sync.Pools | | | `stringutils` | `string` utilities | search in slice (with case-insensitive)
split/join query parameters as arrays
| | `typeutils` | `go` types utilities | check the zero value for any type
safe check for a nil value
| | `yamlutils` | YAML utilities | converting YAML to JSON
loading YAML into a dynamic YAML document
maintaining the original order of keys in YAML objects
require `./jsonutils`
~require `github.com/mailru/easyjson`~
require `go.yaml.in/yaml/v3`
| @@ -171,9 +169,9 @@ on top of which it has been built. ## Other documentation * [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines](.github/CONTRIBUTING.md) -* [Maintainers documentation](docs/MAINTAINERS.md) -* [Code style](docs/STYLE.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] ## Cutting a new release @@ -208,9 +206,6 @@ Maintainers can cut a new release by either: [doc-url]: https://goswagger.io/go-openapi [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/swag [godoc-url]: http://pkg.go.dev/github.com/go-openapi/swag -[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png -[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM -[slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue [discord-url]: https://discord.gg/FfnFYaC3k5 @@ -222,3 +217,7 @@ Maintainers can cut a new release by either: [goversion-url]: https://github.com/go-openapi/swag/blob/master/go.mod [top-badge]: https://img.shields.io/github/languages/top/go-openapi/swag [commits-badge]: https://img.shields.io/github/commits-since/go-openapi/swag/latest + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/swag/conv/format.go b/vendor/github.com/go-openapi/swag/conv/format.go index 5b87b8e146b..e14e5bfcfb9 100644 --- a/vendor/github.com/go-openapi/swag/conv/format.go +++ b/vendor/github.com/go-openapi/swag/conv/format.go @@ -7,14 +7,16 @@ import ( "strconv" ) +const baseDecimal = 10 + // FormatInteger turns an integer type into a string. func FormatInteger[T Signed](value T) string { - return strconv.FormatInt(int64(value), 10) + return strconv.FormatInt(int64(value), baseDecimal) } // FormatUinteger turns an unsigned integer type into a string. func FormatUinteger[T Unsigned](value T) string { - return strconv.FormatUint(uint64(value), 10) + return strconv.FormatUint(uint64(value), baseDecimal) } // FormatFloat turns a floating point numerical value into a string. @@ -26,3 +28,23 @@ func FormatFloat[T Float](value T) string { func FormatBool(value bool) string { return strconv.FormatBool(value) } + +// AppendInteger appends the decimal representation of an integer to a slice of bytes. +func AppendInteger[T Signed](dst []byte, value T) []byte { + return strconv.AppendInt(dst, int64(value), baseDecimal) +} + +// AppendUinteger appends the decimal representation of an unsigned integer to a slice of bytes. +func AppendUinteger[T Unsigned](dst []byte, value T) []byte { + return strconv.AppendUint(dst, uint64(value), baseDecimal) +} + +// AppendFloat appends the decimal representation of a floating point number to a slice of bytes. +func AppendFloat[T Float](dst []byte, value T) []byte { + return strconv.AppendFloat(dst, float64(value), 'g', -1, bitsize(value)) +} + +// AppendBool appends the text representation of a boolean to a slice of bytes. +func AppendBool(dst []byte, value bool) []byte { + return strconv.AppendBool(dst, value) +} diff --git a/vendor/github.com/go-openapi/swag/go.work b/vendor/github.com/go-openapi/swag/go.work index 8537cb2a76a..f1dddc436e7 100644 --- a/vendor/github.com/go-openapi/swag/go.work +++ b/vendor/github.com/go-openapi/swag/go.work @@ -12,6 +12,7 @@ use ( ./loading ./mangling ./netutils + ./pools ./stringutils ./typeutils ./yamlutils diff --git a/vendor/github.com/go-openapi/swag/jsonname_iface.go b/vendor/github.com/go-openapi/swag/jsonname_iface.go index 303a007f6f4..443560caad4 100644 --- a/vendor/github.com/go-openapi/swag/jsonname_iface.go +++ b/vendor/github.com/go-openapi/swag/jsonname_iface.go @@ -4,21 +4,21 @@ package swag import ( - "github.com/go-openapi/swag/jsonname" + "github.com/go-openapi/jsonpointer/jsonname" ) // DefaultJSONNameProvider is the default cache for types // -// Deprecated: use [jsonname.DefaultJSONNameProvider] instead. +// Deprecated: use [github.com/go-openapi/jsonpointer/jsonname.DefaultJSONNameProvider] instead. var DefaultJSONNameProvider = jsonname.DefaultJSONNameProvider // NameProvider represents an object capable of translating from go property names // to json property names. // -// Deprecated: use [jsonname.NameProvider] instead. +// Deprecated: use [github.com/go-openapi/jsonpointer/jsonname.NameProvider] instead. type NameProvider = jsonname.NameProvider // NewNameProvider creates a new name provider // -// Deprecated: use [jsonname.NewNameProvider] instead. +// Deprecated: use [github.com/go-openapi/jsonpointer/jsonname.NewNameProvider] instead. func NewNameProvider() *NameProvider { return jsonname.NewNameProvider() } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go index 0213ff5c29f..94185f79c10 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go @@ -5,6 +5,7 @@ package json import ( stdjson "encoding/json" + "fmt" "github.com/go-openapi/swag/jsonutils/adapters/ifaces" "github.com/go-openapi/swag/typeutils" @@ -24,11 +25,16 @@ var ErrStdlib jsonError = "error from the JSON adapter stdlib" var _ ifaces.Adapter = &Adapter{} type Adapter struct { + options } // NewAdapter yields an [ifaces.Adapter] using the standard library. -func NewAdapter() *Adapter { - return &Adapter{} +func NewAdapter(opts ...Option) *Adapter { + var o options + + return &Adapter{ + options: buildOptions(o, opts), + } } func (a *Adapter) Marshal(value any) ([]byte, error) { @@ -40,45 +46,18 @@ func (a *Adapter) Unmarshal(data []byte, value any) error { } func (a *Adapter) OrderedMarshal(value ifaces.Ordered) ([]byte, error) { - w := poolOfWriters.Borrow() - defer func() { - poolOfWriters.Redeem(w) - }() - - if typeutils.IsNil(value) { - w.RawString("null") - - return w.BuildBytes() - } - - w.RawByte('{') - first := true - for k, v := range value.OrderedItems() { - if first { - first = false - } else { - w.RawByte(',') - } + w, redeem := poolOfWriters.BorrowWithRedeem() + defer redeem() + w.setBuf() - w.String(k) - w.RawByte(':') - - switch val := v.(type) { - case ifaces.Ordered: - w.Raw(a.OrderedMarshal(val)) - default: - w.Raw(stdjson.Marshal(v)) - } - } - - w.RawByte('}') + a.orderedMarshal(w, value, 1) return w.BuildBytes() } func (a *Adapter) OrderedUnmarshal(data []byte, value ifaces.SetOrdered) error { var m MapSlice - if err := m.OrderedUnmarshalJSON(data); err != nil { + if err := m.orderedUnmarshalJSON(data, a.maxDepth()); err != nil { return err } @@ -112,4 +91,43 @@ func (a *Adapter) Redeem() { } func (a *Adapter) Reset() { + a.options = options{} +} + +// orderedMarshal writes value to w, tracking the container nesting depth to guard +// against stack overflow on deeply nested structures. +func (a *Adapter) orderedMarshal(w *jwriter, value ifaces.Ordered, depth int) { + if typeutils.IsNil(value) { + w.RawString("null") + + return + } + + if maxDepth := a.maxDepth(); depth > maxDepth { + w.SetErr(fmt.Errorf("maximum nesting depth of %d exceeded: %w", maxDepth, ErrStdlib)) + + return + } + + w.RawByte('{') + first := true + for k, v := range value.OrderedItems() { + if first { + first = false + } else { + w.RawByte(',') + } + + w.String(k) + w.RawByte(':') + + switch val := v.(type) { + case ifaces.Ordered: + a.orderedMarshal(w, val, depth+1) + default: + w.Raw(stdjson.Marshal(v)) + } + } + + w.RawByte('}') } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go index b5aa1c7972e..ac81cbc75fa 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go @@ -54,7 +54,7 @@ func (t token) Delim() byte { return 0 } - return byte(r) + return byte(r) //nolint:gosec // delimiter runes are single byte } type tokenKind uint8 @@ -91,6 +91,13 @@ type jlexer struct { // current token next token // started bool + + // depth tracks the current JSON container nesting level, and maxDepth caps it + // to guard against stack-overflow on adversarially deep documents. The standard + // library's streaming [encoding/json.Decoder.Token] API (used here) does not + // enforce the max-depth guard that [encoding/json.Unmarshal] provides, so we do. + depth int + maxDepth int } type bytesReader struct { @@ -130,7 +137,8 @@ var _ io.Reader = &bytesReader{} func newLexer(data []byte) *jlexer { l := &jlexer{ // current: undefToken, - next: undefToken, + next: undefToken, + maxDepth: defaultMaxNestingDepth, } l.buf = &bytesReader{ buf: data, @@ -143,7 +151,11 @@ func newLexer(data []byte) *jlexer { func (l *jlexer) Reset() { l.err = nil l.next = undefToken - // leave l.dec and l.buf alone, since they are replaced at every Borrow + l.depth = 0 + l.maxDepth = defaultMaxNestingDepth + l.dec = nil + // leave l.buf alone, since they are replaced at every Borrow + l.buf = nil } func (l *jlexer) Error() error { @@ -228,6 +240,21 @@ func (l *jlexer) Delim(c byte) { if tok.Delim() != c { l.err = fmt.Errorf("expected delimiter '%q' but got '%q': %w", c, tok.Delim(), ErrStdlib) + + return + } + + // Track container nesting depth centrally: every '{' or '[' opens a level and + // every '}' or ']' closes one. This guards the mutually-recursive unmarshal + // routines (unmarshalObject/unmarshalArray/asInterface) against stack overflow. + switch c { + case '{', '[': + l.depth++ + if l.maxDepth > 0 && l.depth > l.maxDepth { + l.err = fmt.Errorf("maximum nesting depth of %d exceeded: %w", l.maxDepth, ErrStdlib) + } + case '}', ']': + l.depth-- } } @@ -318,3 +345,12 @@ func (l *jlexer) fetchToken() token { return token{Token: jtok} } + +func (l *jlexer) setBuf(data []byte) func() { + rdr, redeemBuf := poolOfReaders.BorrowWithRedeem() + l.buf = rdr + l.buf.buf = data + l.dec = stdjson.NewDecoder(l.buf) // cannot pool, not exposed by the encoding/json API + + return redeemBuf +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/options.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/options.go new file mode 100644 index 00000000000..f114f1f1a1a --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/options.go @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +// defaultMaxNestingDepth is the default maximum number of nested JSON containers +// ('{' or '[') that the ordered-JSON marshaler and unmarshaler will process before +// returning an error. +// +// It mirrors the limit enforced by the standard library's [encoding/json] decoder +// (see encoding/json's internal maxNestingDepth), which this adapter would otherwise +// not benefit from since it drives [encoding/json.Decoder.Token] directly. +const defaultMaxNestingDepth = 10000 + +// Option selects options for the stdlib adapter. +type Option func(o options) options + +type options struct { + maxNestingDepth int +} + +func buildOptions(o options, opts []Option) options { + for _, apply := range opts { + o = apply(o) + } + + return o +} + +// maxDepth returns the configured maximum nesting depth, or the default when unset. +func (o options) maxDepth() int { + if o.maxNestingDepth <= 0 { + return defaultMaxNestingDepth + } + + return o.maxNestingDepth +} + +// WithMaxNestingDepth sets the maximum number of nested JSON containers accepted +// when marshaling or unmarshaling ordered JSON. +// +// A value <= 0 selects the default (10,000). +// +// This guards against stack-overflow crashes on deeply nested (possibly adversarial) +// JSON documents or in-memory structures. +func WithMaxNestingDepth(depth int) Option { + return func(o options) options { + o.maxNestingDepth = depth + + return o + } +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go index 54deef406f3..a5a8f4b6317 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go @@ -70,12 +70,11 @@ func (s MapSlice) MarshalJSON() ([]byte, error) { } func (s MapSlice) OrderedMarshalJSON() ([]byte, error) { - w := poolOfWriters.Borrow() - defer func() { - poolOfWriters.Redeem(w) - }() + w, redeem := poolOfWriters.BorrowWithRedeem() + defer redeem() + w.setBuf() - s.marshalObject(w) + s.marshalObject(w, 1) return w.BuildBytes() // this clones data, so it's okay to redeem the writer and its buffer } @@ -88,23 +87,38 @@ func (s *MapSlice) UnmarshalJSON(data []byte) error { } func (s *MapSlice) OrderedUnmarshalJSON(data []byte) error { - l := poolOfLexers.Borrow(data) - defer func() { - poolOfLexers.Redeem(l) - }() + return s.orderedUnmarshalJSON(data, defaultMaxNestingDepth) +} + +func (s *MapSlice) orderedUnmarshalJSON(data []byte, maxDepth int) error { + l, redeem := poolOfLexers.BorrowWithRedeem() + defer redeem() + + redeemBuf := l.setBuf(data) + defer redeemBuf() + + if maxDepth > 0 { + l.maxDepth = maxDepth + } s.unmarshalObject(l) return l.Error() } -func (s MapSlice) marshalObject(w *jwriter) { +func (s MapSlice) marshalObject(w *jwriter, depth int) { if s == nil { w.RawString("null") return } + if depth > defaultMaxNestingDepth { + w.SetErr(fmt.Errorf("maximum nesting depth of %d exceeded: %w", defaultMaxNestingDepth, ErrStdlib)) + + return + } + w.RawByte('{') if len(s) == 0 { @@ -113,11 +127,11 @@ func (s MapSlice) marshalObject(w *jwriter) { return } - s[0].marshalJSON(w) + s[0].marshalJSON(w, depth) for i := 1; i < len(s); i++ { w.RawByte(',') - s[i].marshalJSON(w) + s[i].marshalJSON(w, depth) } w.RawByte('}') @@ -162,9 +176,18 @@ type MapItem struct { Value any } -func (s MapItem) marshalJSON(w *jwriter) { +func (s MapItem) marshalJSON(w *jwriter, depth int) { w.String(s.Key) w.RawByte(':') + + // Recurse internally for nested ordered maps so the depth guard is not lost across + // the stdjson.Marshal boundary (which would reset it and re-enable stack overflow). + if nested, ok := s.Value.(MapSlice); ok { + nested.marshalObject(w, depth+1) + + return + } + w.Raw(stdjson.Marshal(s.Value)) } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go index 709b97c3046..2f06b88e808 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go @@ -4,118 +4,15 @@ package json import ( - "encoding/json" - "sync" - "github.com/go-openapi/swag/jsonutils/adapters/ifaces" + "github.com/go-openapi/swag/pools" ) -type adaptersPool struct { - sync.Pool -} - -func (p *adaptersPool) Borrow() *Adapter { - return p.Get().(*Adapter) -} - -func (p *adaptersPool) BorrowIface() ifaces.Adapter { - return p.Get().(*Adapter) -} - -func (p *adaptersPool) Redeem(a *Adapter) { - p.Put(a) -} - -type writersPool struct { - sync.Pool -} - -func (p *writersPool) Borrow() *jwriter { - ptr := p.Get() - - jw := ptr.(*jwriter) - jw.Reset() - - return jw -} - -func (p *writersPool) Redeem(w *jwriter) { - p.Put(w) -} - -type lexersPool struct { - sync.Pool -} - -func (p *lexersPool) Borrow(data []byte) *jlexer { - ptr := p.Get() - - l := ptr.(*jlexer) - l.buf = poolOfReaders.Borrow(data) - l.dec = json.NewDecoder(l.buf) // cannot pool, not exposed by the encoding/json API - l.Reset() - - return l -} - -func (p *lexersPool) Redeem(l *jlexer) { - l.dec = nil - discard := l.buf - l.buf = nil - poolOfReaders.Redeem(discard) - p.Put(l) -} - -type readersPool struct { - sync.Pool -} - -func (p *readersPool) Borrow(data []byte) *bytesReader { - ptr := p.Get() - - b := ptr.(*bytesReader) - b.Reset() - b.buf = data - - return b -} - -func (p *readersPool) Redeem(b *bytesReader) { - p.Put(b) -} - var ( - poolOfAdapters = &adaptersPool{ - Pool: sync.Pool{ - New: func() any { - return NewAdapter() - }, - }, - } - - poolOfWriters = &writersPool{ - Pool: sync.Pool{ - New: func() any { - return newJWriter() - }, - }, - } - - poolOfLexers = &lexersPool{ - Pool: sync.Pool{ - New: func() any { - return newLexer(nil) - }, - }, - } - - poolOfReaders = &readersPool{ - Pool: sync.Pool{ - New: func() any { - return &bytesReader{} - }, - }, - } + poolOfAdapters = pools.New[Adapter]() + poolOfWriters = pools.NewRedeemable[jwriter]() + poolOfLexers = pools.NewRedeemable[jlexer]() + poolOfReaders = pools.NewRedeemable[bytesReader]() ) // BorrowAdapter borrows an [Adapter] from the pool, recycling already allocated instances. @@ -124,10 +21,12 @@ func BorrowAdapter() *Adapter { } // BorrowAdapterIface borrows a stdlib [Adapter] and converts it directly -// to [ifaces.Adapter]. This is useful to avoid further allocations when -// translating the concrete type into an interface. +// to [ifaces.Adapter]. +// +// This is useful to avoid further allocations when translating the concrete type into +// an interface. func BorrowAdapterIface() ifaces.Adapter { - return poolOfAdapters.BorrowIface() + return poolOfAdapters.Borrow() } // RedeemAdapter redeems an [Adapter] to the pool, so it may be recycled. diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go index fc8818694ea..0dec85425ba 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go @@ -10,14 +10,22 @@ import ( "github.com/go-openapi/swag/jsonutils/adapters/ifaces" ) -func Register(dispatcher ifaces.Registrar) { +func Register(dispatcher ifaces.Registrar, opts ...Option) { t := reflect.TypeOf(Adapter{}) + var o options + o = buildOptions(o, opts) + dispatcher.RegisterFor( ifaces.RegistryEntry{ - Who: fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()), - What: ifaces.AllCapabilities, - Constructor: BorrowAdapterIface, - Support: support, + Who: fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()), + What: ifaces.AllCapabilities, + Constructor: func() ifaces.Adapter { + a := BorrowAdapter() + a.options = o + + return a + }, + Support: support, }) } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go index dc2325c1a30..c84e02cd838 100644 --- a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go @@ -14,17 +14,21 @@ type jwriter struct { err error } -func newJWriter() *jwriter { - buf := make([]byte, 0, sensibleBufferSize) - - return &jwriter{buf: bytes.NewBuffer(buf)} -} - func (w *jwriter) Reset() { - w.buf.Reset() + if w.buf != nil { + w.buf.Reset() + } w.err = nil } +// SetErr records the first error encountered while building the JSON output. +func (w *jwriter) SetErr(err error) { + if w.err != nil { + return + } + w.err = err +} + func (w *jwriter) RawString(s string) { if w.err != nil { return @@ -73,3 +77,12 @@ func (w *jwriter) BuildBytes() ([]byte, error) { return bytes.Clone(w.buf.Bytes()), nil } + +func (w *jwriter) setBuf() { + if w.buf != nil { + return + } + + buf := make([]byte, 0, sensibleBufferSize) + w.buf = bytes.NewBuffer(buf) +} diff --git a/vendor/github.com/go-openapi/swag/loading/doc.go b/vendor/github.com/go-openapi/swag/loading/doc.go index 8cf7bcb8b9d..112c49968b8 100644 --- a/vendor/github.com/go-openapi/swag/loading/doc.go +++ b/vendor/github.com/go-openapi/swag/loading/doc.go @@ -2,4 +2,28 @@ // SPDX-License-Identifier: Apache-2.0 // Package loading provides tools to load a file from http or from a local file system. +// +// # Security +// +// By default, the local loader reads any path the process can access, including absolute +// paths and "file://" URIs (for example "file:///etc/passwd"). Applications that pass +// untrusted input to [LoadFromFileOrHTTP], [JSONDoc] (or to downstream consumers such as +// go-openapi/loads) must confine local loading to a trusted directory. +// +// Use [WithRoot] to do so: it resolves every requested path relative to a chosen directory +// and rejects anything that escapes it, including via symlink. It is built on [os.Root] +// and is therefore safer than passing an [os.DirFS] to [WithFS], which does not block +// symlink escapes. +// +// Remote loading uses a standard [net/http] client. +// By default it follows redirects and performs no destination filtering — exactly like [net/http.DefaultClient]. +// +// A caller-controlled URL may therefore reach internal services or cloud metadata endpoints +// (server-side request forgery). +// +// This package does not, and should not, embed a network policy: +// when the URL may derive from untrusted input, supply a restricted client with +// [WithHTTPClient] whose transport rejects unwanted destinations at dial time — which also +// covers redirects and DNS rebinding. +// See the example on [LoadFromFileOrHTTP]. package loading diff --git a/vendor/github.com/go-openapi/swag/loading/loading.go b/vendor/github.com/go-openapi/swag/loading/loading.go index 269fb74d167..b06450c64df 100644 --- a/vendor/github.com/go-openapi/swag/loading/loading.go +++ b/vendor/github.com/go-openapi/swag/loading/loading.go @@ -17,7 +17,11 @@ import ( "strings" ) -// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in +// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in. +// +// Security: by default a local path is read with no confinement, so a caller-controlled path +// (including a "file://" URI or an absolute path) may read any file the process can access. +// When the path may derive from untrusted input, confine local loading with [WithRoot]. func LoadFromFileOrHTTP(pth string, opts ...Option) ([]byte, error) { o := optionsWithDefaults(opts) return LoadStrategy(pth, o.ReadFileFunc(), loadHTTPBytes(opts...), opts...)(pth) @@ -54,11 +58,14 @@ func LoadFromFileOrHTTP(pth string, opts ...Option) ([]byte, error) { // - `file:///c:/folder/file` becomes `C:\folder\file` // - `file://c:/folder/file` is tolerated (without leading `/`) and becomes `c:\folder\file` func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts ...Option) func(string) ([]byte, error) { - if strings.HasPrefix(pth, "http") { + if hasHTTPScheme(pth) { return remote } o := optionsWithDefaults(opts) _, isEmbedFS := o.fs.(embed.FS) + // any loader backed by an fs.FS or an os.Root consumes forward-slash paths on every + // platform, so it must not go through the windows-native file:// preprocessing below. + isFSBacked := o.fs != nil || o.root != "" return func(p string) ([]byte, error) { upth, err := url.PathUnescape(p) @@ -67,14 +74,22 @@ func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts . } cpth, hasPrefix := strings.CutPrefix(upth, "file://") - if !hasPrefix || isEmbedFS || runtime.GOOS != "windows" { + if !hasPrefix || isFSBacked || runtime.GOOS != "windows" { // crude processing: trim the file:// prefix. This leaves full URIs with a host with a (mostly) unexpected result // regular file path provided: just normalize slashes if isEmbedFS { - // on windows, we need to slash the path if FS is an embed FS. + // embed.FS always uses "/" as separator, even on windows, and rejects leading "./" or "/". return local(strings.TrimLeft(filepath.ToSlash(cpth), "./")) // remove invalid leading characters for embed FS } + if isFSBacked { + // other fs.FS (e.g. os.DirFS) and os.Root loaders also use "/" on every platform. + // Path confinement is enforced by the loader, not here: the os.Root loader rebases + // absolute in-root paths and rejects escaping paths ("..", out-of-root absolute, + // escaping symlinks); an fs.FS loader rejects what its file system does not allow. + return local(filepath.ToSlash(cpth)) + } + return local(filepath.FromSlash(cpth)) } @@ -113,6 +128,21 @@ func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts . } } +// hasHTTPScheme reports whether pth is an absolute URL with an http or https scheme, +// selecting the remote loader. The comparison is case-insensitive, as URL schemes are. +// +// Requiring the "://" separator (rather than a bare "http" prefix) avoids misrouting a +// local file whose name merely starts with "http" (e.g. "httpbin.json") to the remote loader. +func hasHTTPScheme(pth string) bool { + for _, scheme := range [...]string{"http://", "https://"} { + if len(pth) >= len(scheme) && strings.EqualFold(pth[:len(scheme)], scheme) { + return true + } + } + + return false +} + func loadHTTPBytes(opts ...Option) func(path string) ([]byte, error) { o := optionsWithDefaults(opts) diff --git a/vendor/github.com/go-openapi/swag/loading/options.go b/vendor/github.com/go-openapi/swag/loading/options.go index 6674ac69e62..539987547d1 100644 --- a/vendor/github.com/go-openapi/swag/loading/options.go +++ b/vendor/github.com/go-openapi/swag/loading/options.go @@ -4,9 +4,12 @@ package loading import ( + "errors" "io/fs" "net/http" "os" + "path/filepath" + "runtime" "time" ) @@ -23,7 +26,8 @@ type ( } fileOptions struct { - fs fs.ReadFileFS + fs fs.ReadFileFS + root string // when non-empty, local reads are confined to this directory via os.Root } options struct { @@ -33,6 +37,28 @@ type ( ) func (fo fileOptions) ReadFileFunc() func(string) ([]byte, error) { + if fo.root != "" { + root := fo.root + + return func(name string) ([]byte, error) { + // os.Root only accepts paths relative to the root, but callers (and this package's + // own file:// handling) routinely produce absolute paths. Rebase an absolute path + // onto the root before handing it to os.Root. + rel, err := rootRelative(root, name) + if err != nil { + return nil, errors.Join(err, ErrLoader) + } + + r, err := os.OpenRoot(root) + if err != nil { + return nil, errors.Join(err, ErrLoader) + } + defer func() { _ = r.Close() }() + + return r.ReadFile(rel) + } + } + if fo.fs == nil { return os.ReadFile } @@ -40,6 +66,61 @@ func (fo fileOptions) ReadFileFunc() func(string) ([]byte, error) { return fo.fs.ReadFile } +// rootRelative expresses name as a path relative to root, so that it can be resolved by os.Root. +// +// A relative name is returned unchanged: os.Root confines it directly (including "../" traversal +// and symlink escapes, which it rejects at open time). +// +// An absolute name is rebased onto root. If it cannot be expressed relative to root — for +// example because it lives on a different volume on Windows — filepath.Rel returns an error, +// which is propagated so the read is rejected rather than silently escaping the root. An +// absolute path that lexically escapes root yields a "../" prefix here and is then rejected by +// os.Root. +func rootRelative(root, name string) (string, error) { + osName := toOSPath(name) + if !filepath.IsAbs(osName) { + return name, nil + } + + absRoot, err := filepath.Abs(toOSPath(root)) + if err != nil { + return "", err + } + + return filepath.Rel(absRoot, osName) +} + +// toOSPath converts a slash-separated path to an OS-native path. +// +// On Windows it additionally normalizes the "/C:/dir" form — a leading separator before a drive +// letter — that file URIs and URL-style path normalization (as performed by +// github.com/go-openapi/spec) produce. Without this, filepath.IsAbs does not recognize such a +// path as absolute and os.Root rejects an otherwise in-root target. This mirrors the file:// +// drive-letter handling in LoadStrategy, which the os.Root loader bypasses. +func toOSPath(p string) string { + p = filepath.FromSlash(p) + if runtime.GOOS == "windows" { + p = stripLeadingDriveSlash(p) + } + + return p +} + +// stripLeadingDriveSlash removes a leading separator that precedes a Windows drive letter, +// turning "\C:\dir" (from a "/C:/dir" URL path) into "C:\dir". Any other path is returned +// unchanged. It is pure (no OS dependency) so that its logic can be tested on any platform. +func stripLeadingDriveSlash(p string) string { + if len(p) >= 3 && (p[0] == '/' || p[0] == '\\') && p[2] == ':' && isASCIILetter(p[1]) { + return p[1:] + } + + return p +} + +func isASCIILetter(b byte) bool { + return ('a' <= b && b <= 'z') || ('A' <= b && b <= 'Z') +} + // WithTimeout sets a timeout for the remote file loader. // // The default timeout is 30s. @@ -87,8 +168,15 @@ func WithHTTPClient(client *http.Client) Option { // By default, the file system is the one provided by the os package. // // For example, this may be set to consume from an embedded file system, or a rooted FS. +// +// WithFS and [WithRoot] are mutually exclusive: the last one applied wins. +// +// Security note: a file system built from [os.DirFS] confines paths but does NOT protect +// against symlinks that escape the root. To load from a directory derived from untrusted +// input, prefer [WithRoot], which is symlink-escape resistant. func WithFS(filesystem fs.FS) Option { return func(o *options) { + o.root = "" // last-wins vs WithRoot if rfs, ok := filesystem.(fs.ReadFileFS); ok { o.fs = rfs @@ -98,6 +186,30 @@ func WithFS(filesystem fs.FS) Option { } } +// WithRoot confines local file loading to dir. +// +// Every requested path is resolved within dir. A relative path is resolved against dir; an +// absolute path is rebased onto dir (so a caller that normalizes references to absolute paths, +// such as github.com/go-openapi/spec, still resolves correctly). Any path that would escape dir +// — through ".." traversal, an absolute path pointing outside dir, or a symlink pointing outside +// dir — is rejected. This is built on [os.Root] and is therefore resistant to the symlink +// escapes that a plain [os.DirFS] does not prevent. +// +// WithRoot is the recommended option when loading specs from a location derived from +// untrusted input. It applies to local loading only and has no effect on remote +// (http/https) loading. WithRoot and [WithFS] are mutually exclusive: the last one applied +// wins. +// +// Note: [os.Root] confines path resolution but does not, by itself, protect against +// traversal of mount/bind boundaries, /proc special files, or device files. Point WithRoot +// at a directory that holds only the documents you intend to expose. +func WithRoot(dir string) Option { + return func(o *options) { + o.root = dir + o.fs = nil // last-wins vs WithFS + } +} + type readFileFS struct { fs.FS } diff --git a/vendor/github.com/go-openapi/swag/loading_iface.go b/vendor/github.com/go-openapi/swag/loading_iface.go index 27ec3fb8c37..78dadfccdf4 100644 --- a/vendor/github.com/go-openapi/swag/loading_iface.go +++ b/vendor/github.com/go-openapi/swag/loading_iface.go @@ -80,11 +80,13 @@ func YAMLData(path string) (any, error) { // loadingOptionsWithDefaults bridges deprecated default settings that use package-level variables, // with the recommended use of loading.Option. func loadingOptionsWithDefaults(opts []loading.Option) []loading.Option { - o := []loading.Option{ + const defaultOptions = 3 + o := make([]loading.Option, 0, defaultOptions+len(opts)) + o = append(o, []loading.Option{ loading.WithTimeout(LoadHTTPTimeout), loading.WithBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword), loading.WithCustomHeaders(LoadHTTPCustomHeaders), - } + }...) o = append(o, opts...) return o diff --git a/vendor/github.com/go-openapi/swag/pools/LICENSE b/vendor/github.com/go-openapi/swag/pools/LICENSE new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/go-openapi/swag/pools/README.md b/vendor/github.com/go-openapi/swag/pools/README.md new file mode 100644 index 00000000000..1966461cb54 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/README.md @@ -0,0 +1 @@ +# pools diff --git a/vendor/github.com/go-openapi/swag/pools/debug.go b/vendor/github.com/go-openapi/swag/pools/debug.go new file mode 100644 index 00000000000..94415e989e4 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/debug.go @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +// TB is the subset of [testing.TB] used by [AssertNoLeaks]. +// +// It is satisfied by *[testing.T] and *[testing.B]. +// +// A local interface is used (rather than importing "testing") so that the +// release build does not pull the testing package — and its flags — into +// production binaries. +type TB interface { + Helper() + Errorf(format string, args ...any) + Logf(format string, args ...any) +} diff --git a/vendor/github.com/go-openapi/swag/pools/debug_off.go b/vendor/github.com/go-openapi/swag/pools/debug_off.go new file mode 100644 index 00000000000..9163d6d60e4 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/debug_off.go @@ -0,0 +1,51 @@ +//go:build !poolsdebug + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +// This is the release implementation of the pool instrumentation: it does +// nothing. +// +// tracker is an empty struct, so it adds no field to the pool types and its +// methods inline away to nothing. +// +// Build with -tags poolsdebug to get the instrumented variant (see +// debug_on.go). + +// debugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug tag). +const debugBuild = false + +// DebugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug build tag). +// +// It lets a test that must run in both modes skip the parts that are invalid +// under instrumentation — e.g. an allocation-count assertion, since the +// instrumented build allocates a per-borrow tracker. +const DebugBuild = debugBuild + +type tracker[T any] struct{} + +func (tracker[T]) register() {} + +func (tracker[T]) onBorrow(*T) {} + +func (tracker[T]) onRedeem(*T) {} + +func (tracker[T]) borrowRedeemer(_ *T, cached func()) func() { return cached } + +// AssertNoLeaks reports whether every borrowed object has been redeemed across +// all pools. +// +// It is only meaningful in the instrumented build (-tags poolsdebug). +// +// In a release build it is a no-op that always reports true, so the same test +// can run in both modes. +func AssertNoLeaks(TB) bool { return true } + +// ResetTracking clears all recorded borrow/redeem tracking. +// +// This is a no-op in a release build. +func ResetTracking() {} diff --git a/vendor/github.com/go-openapi/swag/pools/debug_on.go b/vendor/github.com/go-openapi/swag/pools/debug_on.go new file mode 100644 index 00000000000..64ccc57d38f --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/debug_on.go @@ -0,0 +1,237 @@ +//go:build poolsdebug + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +import ( + "fmt" + "runtime" + "sync" +) + +// This is the instrumented implementation of the pool tracking, enabled with +// -tags poolsdebug. +// +// Each pool carries a tracker that records, per recycled pointer, whether it is +// currently borrowed or redeemed, together with the call sites of the last +// borrow and redeem. +// It panics loudly (with those call sites) when it detects misuse: +// +// - a double redeem (the same object returned to the pool twice — corrupts sync.Pool); +// - for the redeemable pools, a redeem of a stale borrow (the slot was re-borrowed since — the +// ABA case the production atomic guard cannot catch), thanks to a per-borrow generation; +// - a redeem of an object the pool never handed out; +// - a borrow of an object still checked out (a symptom of an earlier double-Put). +// +// Borrowed-but-never-redeemed objects (leaks) are reported by [AssertNoLeaks]. + +// debugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug tag). +const debugBuild = true + +// DebugBuild reports whether the pool instrumentation is compiled in (the +// poolsdebug build tag). +// +// See the release-build doc for usage. +const DebugBuild = debugBuild + +type trackStatus uint8 + +const ( + trackBorrowed trackStatus = iota + 1 + trackRedeemed +) + +type trackEntry struct { + status trackStatus + gen uint64 // identifies the current borrow, to detect a redeem racing a re-borrow (ABA) + borrowedAt string + redeemedAt string +} + +type tracker[T any] struct { + mu sync.Mutex + entries map[*T]*trackEntry + nextGen uint64 +} + +func (t *tracker[T]) register() { + t.mu.Lock() + if t.entries == nil { + t.entries = make(map[*T]*trackEntry) + } + t.mu.Unlock() + + registerLeakChecker(t) +} + +// markBorrow records a borrow of ptr and returns its generation. +// +// Caller must hold no lock. +func (t *tracker[T]) markBorrow(ptr *T, site string) uint64 { + t.mu.Lock() + defer t.mu.Unlock() + + e := t.entries[ptr] + if e == nil { + e = &trackEntry{} + t.entries[ptr] = e + } else if e.status == trackBorrowed { + panic(fmt.Sprintf( + "pools: borrow of an object still checked out (borrowed at %s); "+ + "this usually means it was redeemed twice earlier", e.borrowedAt)) + } + + t.nextGen++ + e.status = trackBorrowed + e.gen = t.nextGen + e.borrowedAt = site + + return t.nextGen +} + +// markRedeem validates and records a redeem of ptr. gen is the borrow +// generation the caller is redeeming, or 0 to skip the ABA check (plain +// Pool[T], which has no per-borrow token). +func (t *tracker[T]) markRedeem(ptr *T, gen uint64, site string) { + t.mu.Lock() + defer t.mu.Unlock() + + e := t.entries[ptr] + switch { + case e == nil: + panic("pools: redeem of an object this pool never handed out") + case e.status != trackBorrowed: + panic(fmt.Sprintf("pools: double redeem (first redeemed at %s)", e.redeemedAt)) + case gen != 0 && e.gen != gen: + panic(fmt.Sprintf( + "pools: redeem of a stale borrow (the slot was re-borrowed at %s since this borrow); "+ + "a redeem is racing a re-borrow of the same slot (ABA)", e.borrowedAt)) + } + + e.status = trackRedeemed + e.redeemedAt = site +} + +const stackOffset = 3 + +func (t *tracker[T]) onBorrow(ptr *T) { + t.markBorrow(ptr, caller(stackOffset)) +} + +func (t *tracker[T]) onRedeem(ptr *T) { + t.markRedeem(ptr, 0, caller(stackOffset)) +} + +// borrowRedeemer records the borrow and returns a generation-stamped redeemer +// that validates the redeem (catching double-redeem and ABA) before delegating +// to the cached redeemer. +func (t *tracker[T]) borrowRedeemer(ptr *T, cached func()) func() { + gen := t.markBorrow(ptr, caller(stackOffset)) + + return func() { + t.markRedeem(ptr, gen, caller(stackOffset-1)) + cached() + } +} + +func (t *tracker[T]) checkLeaks(tb TB) bool { + t.mu.Lock() + defer t.mu.Unlock() + + ok := true + for _, e := range t.entries { + if e.status != trackRedeemed { + tb.Logf("pools: object borrowed but never redeemed (borrowed at %s)", e.borrowedAt) + ok = false + } + } + + return ok +} + +func (t *tracker[T]) resetTracking() { + t.mu.Lock() + t.entries = make(map[*T]*trackEntry) + t.nextGen = 0 + t.mu.Unlock() +} + +// leakChecker is the build-erased view of a tracker that the global registry +// holds, so trackers of different element types can be checked uniformly. +type leakChecker interface { + checkLeaks(tb TB) bool + resetTracking() +} + +var ( + registryMu sync.Mutex + registry []leakChecker +) + +func registerLeakChecker(c leakChecker) { + registryMu.Lock() + registry = append(registry, c) + registryMu.Unlock() +} + +// AssertNoLeaks reports whether every borrowed object has been redeemed across +// all pools created so far. +// +// It logs the borrow call site of each leaked object and fails tb when any are +// found. +// +// Typical use, with [ResetTracking] to isolate the test from earlier ones: +// +// func TestX(t *testing.T) { +// pools.ResetTracking() +// t.Cleanup(func() { pools.AssertNoLeaks(t) }) +// // ... exercise code that borrows/redeems ... +// } +func AssertNoLeaks(tb TB) bool { + tb.Helper() + registryMu.Lock() + defer registryMu.Unlock() + + ok := true + for _, c := range registry { + if !c.checkLeaks(tb) { + ok = false + } + } + if !ok { + tb.Errorf("pools: leaked pooled objects detected (borrowed but never redeemed)") + } + + return ok +} + +// ResetTracking clears all recorded borrow/redeem tracking across every pool. +// +// Call it at the start of a test so leaks from earlier tests are not attributed +// to it. +func ResetTracking() { + registryMu.Lock() + defer registryMu.Unlock() + + for _, c := range registry { + c.resetTracking() + } +} + +// caller returns "file:line" of the frame skip levels above caller itself. +func caller(skip int) string { + pc, _, _, ok := runtime.Caller(skip) + if !ok { + return "unknown" + } + fn := runtime.FuncForPC(pc) + if fn == nil { + return "unknown" + } + file, line := fn.FileLine(pc) + + return fmt.Sprintf("%s:%d", file, line) +} diff --git a/vendor/github.com/go-openapi/swag/pools/doc.go b/vendor/github.com/go-openapi/swag/pools/doc.go new file mode 100644 index 00000000000..395c24d29a6 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/doc.go @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package pools provide utilities to recycle allocated objects. +// +// This package provides: +// +// - a generic [Pool] type that wraps [sync.Pool], +// - a [PoolRedeemable] variant that hands out a cached redeem closure, +// - a [PoolSlice] for recycling slices without juggling pointers. +// +// # Debug build +// +// Building with the "poolsdebug" tag (go test -tags poolsdebug ./...) turns on +// instrumentation that tracks every borrow and redeem and panics on misuse: +// +// - double redeem (including the A -> B -> A case for the redeemable pools), +// - redeem of a foreign object, +// - borrow of an object still checked out +// +// It reports the offending call sites. +// +// [AssertNoLeaks] then reports any object borrowed but never redeemed. +// +// The instrumentation is a no-op with zero overhead when the tag is absent. +package pools diff --git a/vendor/github.com/go-openapi/swag/pools/pools.go b/vendor/github.com/go-openapi/swag/pools/pools.go new file mode 100644 index 00000000000..d78ea5790a3 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/pools/pools.go @@ -0,0 +1,410 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package pools + +import ( + "iter" + "slices" + "sync" + "sync/atomic" +) + +// Resettable is an interface for types that want to recycle a clean instance +// from a [Pool]. +// +// When T (or rather *T) implements [Resettable], the pool calls Reset on an +// instance both when it is redeemed and when it is borrowed: +// +// - on redeem, so that no references held by the instance are retained while it sits idle in the +// pool (which would pin a reference graph alive across a GC cycle); +// - on borrow, so that the next borrower receives a clean object regardless of how the instance +// reached the pool. +// +// Reset must be safe to call more than once on the same instance (it runs at +// least twice per cycle). +type Resettable interface { + Reset() +} + +// resetIfResettable calls Reset on v when *T implements [Resettable]. +func resetIfResettable[T any](v *T) { + if r, ok := any(v).(Resettable); ok { + r.Reset() + } +} + +// borrow state of a [redeemable] wrapper, used to detect double-redeem. +const ( + stateIdle uint32 = iota // sitting in the pool (or freshly created), not checked out + stateBorrowed // checked out by a borrower +) + +type redeemable[T any] struct { + inner *T + redeemer func() + // state guards against a double-redeem (the same wrapper Put into the pool + // twice, which would let one object be handed to two borrowers). + // + // It is set to stateBorrowed on borrow and atomically flipped back to + // stateIdle on redeem; a redeem that finds it already idle panics. + state atomic.Uint32 +} + +// redeemPanic is the message raised when a slot is redeemed while already idle. +const redeemPanic = "pools: " + + "double redeem detected (object already returned to the pool); " + + "a borrowed object must be redeemed exactly once" + +// Pool wraps a [sync.Pool] to make it available for any type. +// +// T must be the value type of the pooled object (e.g. Pool[bytes.Buffer]): +// [Pool.Borrow] returns a *T. Using a pointer type as T (e.g. +// Pool[*bytes.Buffer]) would yield a **T and is almost certainly a mistake. +type Pool[T any] struct { + pool sync.Pool + tracker tracker[T] // empty (zero-cost) unless built with the poolsdebug tag +} + +// PoolRedeemable wraps a [sync.Pool] to make it available for any type. +// +// It differs from [Pool] in the way objects are redeemed to the pool: borrowing +// also yields a cached redeem closure, so no closure is allocated at redeem +// time. +type PoolRedeemable[T any] struct { + pool sync.Pool + tracker tracker[redeemable[T]] // empty (zero-cost) unless built with the poolsdebug tag +} + +// New builds a new [Pool] to recycle allocations of type T explicitly using +// [Pool.Redeem] and the allocated pointer. +// +// Freshly allocated instances of type T are set to their zero value; like +// recycled instances they are reset (if [Resettable]) when borrowed, so +// [Pool.Borrow] always yields a clean object. +func New[T any]() *Pool[T] { + p := &Pool[T]{} + p.pool = sync.Pool{ + New: func() any { + return new(T) + }, + } + p.tracker.register() + + return p +} + +// NewRedeemable builds a new redeemable [Pool] to recycle allocations of type +// T, and use the inner redeemer to relinquish objects to the pool. +func NewRedeemable[T any]() *PoolRedeemable[T] { + p := &PoolRedeemable[T]{} + p.pool = sync.Pool{ + New: func() any { + r := &redeemable[T]{inner: new(T)} + r.redeemer = func() { + if !r.state.CompareAndSwap(stateBorrowed, stateIdle) { + panic(redeemPanic) + } + resetIfResettable(r.inner) + p.pool.Put(r) + } + + return r + }, + } + p.tracker.register() + + return p +} + +// Borrow an instance from the pool. +// +// If the type implements [Resettable], the returned instance is reset before +// being handed out, so it is always clean. +func (p *Pool[T]) Borrow() *T { + target := p.pool.Get().(*T) + resetIfResettable(target) + p.tracker.onBorrow(target) + + return target +} + +// Redeem a borrowed instance to the pool. +// +// A nil pointer is ignored (it would otherwise corrupt the pool: a typed-nil +// boxed into an interface is not the nil interface that [sync.Pool.Put] skips). +// +// The instance is reset (if it implements [Resettable]) before being returned +// to the pool. +// After calling Redeem, the caller must drop its reference to ptr: continuing +// to use it is a use-after-redeem bug. +// +// Unlike [PoolRedeemable], this plain pool holds no per-object state, so it +// cannot detect a double-redeem of the same pointer (which corrupts the pool). +// +// Prefer [PoolRedeemable] when you want that guard, or the debug build for full +// tracking. +func (p *Pool[T]) Redeem(ptr *T) { + if ptr == nil { + return + } + p.tracker.onRedeem(ptr) + resetIfResettable(ptr) + p.pool.Put(ptr) +} + +// BorrowWithRedeem borrows an instance from the pool and provides the +// corresponding redeem function. +// +// This is useful for instance to use with defer. +// +// The instance is reset (if it implements [Resettable]) both when borrowed and +// when the returned redeem closure is called. +// After calling the redeem closure, the caller must drop its reference to the +// returned instance. +// +// Calling the redeem closure more than once panics (see [redeemable.state]): a +// borrowed instance must be redeemed exactly once. +func (p *PoolRedeemable[T]) BorrowWithRedeem() (*T, func()) { + container := p.pool.Get().(*redeemable[T]) + container.state.Store(stateBorrowed) + resetIfResettable(container.inner) + + // In release builds borrowRedeemer returns container.redeemer unchanged (zero + // cost). + // Under the poolsdebug tag it returns a generation-stamped wrapper that tracks + // the borrow and detects double-redeem (incl. + // + // ABA), foreign-redeem and leaks. + return container.inner, p.tracker.borrowRedeemer(container, container.redeemer) +} + +// Slice is a struct that wraps a slice []T. +// +// This is useful to borrow and redeem slices from a pool, without having to +// constantly manipulate pointers to the slice. +// +// The wrapper holds the authoritative slice header. +// +// Its mutating methods ([Slice.Append], [Slice.Concat], [Slice.Grow]) return +// the current backing slice for convenience, so it reads as an idiomatic []T. +// +// But the returned slice is only a snapshot of the wrapper's state at that +// moment: if you keep it and grow it yourself with the builtin append and it +// reallocates, the new backing array lives only in your local copy and is NOT +// tracked by the wrapper — it will not be recycled when the wrapper is +// redeemed (and a later borrower would get the old, smaller array). +// +// Rule of thumb: it is fine to read or pass the returned []T to a consumer; but +// if you plan to grow the slice, keep calling the wrapper's methods so the +// growth is tracked and recycled. +type Slice[T any] struct { + length int + inner []T +} + +// Slice returns the inner slice. +// +// Treat the result as a read-only view (for ranging or passing to a consumer), +// valid until the next mutation or redeem. +// To grow or append, use the wrapper methods so the new backing array is +// tracked and recycled (see [Slice]). +func (s *Slice[T]) Slice() []T { + return s.inner +} + +// Grow the inner slice so it can accommodate at least size more elements +// without reallocating, and return the current backing slice. +// +// Growth is tracked by the wrapper, so the enlarged backing array is recycled +// on redeem. +// See [Slice] for the caveat about growing the returned slice yourself. +func (s *Slice[T]) Grow(size int) []T { + s.inner = slices.Grow(s.inner, size) + + return s.inner +} + +func (s *Slice[T]) Len() int { + return len(s.inner) +} + +func (s *Slice[T]) Cap() int { + return cap(s.inner) +} + +// Append elements to the inner slice and return the current backing slice. +// +// This should be preferred to the append builtin if you plan that the slice will +// grow and you want the newly allocated space to be tracked and recycled. +// See [Slice] for the caveat about growing the returned slice yourself. +func (s *Slice[T]) Append(elems ...T) []T { + s.inner = append(s.inner, elems...) + + return s.inner +} + +// Concat another slice to the inner slice and return the current backing slice. +// +// Unlike [slices.Concat], this reuses the inner slice's capacity instead of +// always allocating a fresh backing array. +// See [Slice] for the caveat about growing the returned slice yourself. +func (s *Slice[T]) Concat(slice []T) []T { + s.inner = append(s.inner, slice...) + + return s.inner +} + +// IndexedElems iterates over the inner slice. +func (s *Slice[T]) IndexedElems() iter.Seq2[int, T] { + return func(yield func(int, T) bool) { + for i, elem := range s.inner { + if !yield(i, elem) { + return + } + } + } +} + +// Reset the inner slice to its configured initial length, keeping allocated +// capacity. +// +// All elements are zeroed, so the pool never retains stale element references +// (which would keep a referenced graph alive for slices of pointers) and so a +// [WithLength] slice is handed out clean rather than carrying data from a +// previous borrower. +func (s *Slice[T]) Reset() { + clear(s.inner) + if s.length > cap(s.inner) { + s.inner = slices.Grow(s.inner[:0], s.length) + } + s.inner = s.inner[:s.length] +} + +// Clip removes unused capacity from the inner slice. +func (s *Slice[T]) Clip() { + s.inner = slices.Clip(s.inner) +} + +// resetWithCapacity discards the current backing array and replaces it with a +// fresh one of the configured length and the given capacity. +// +// It is used by a capacity-capped pool to stop recycling an oversized backing +// array (the old array is left for the GC). +func (s *Slice[T]) resetWithCapacity(capacity int) { + s.inner = make([]T, s.length, max(s.length, capacity)) +} + +// PoolSlice is a pool of [Slice[T]]. +// +// [PoolSlice.BorrowWithRedeem] will return an empty inner slice by default. +// This default may be altered using [WithMinimumCapacity]. +// +// Use [PoolSlice.BorrowWithSizeAndRedeem] or [Slice.Grow] to grow the capacity +// of the inner slice. +type PoolSlice[T any] struct { + // redeemable is held as an unexported field rather than embedded, so the + // underlying [PoolRedeemable] and its [sync.Pool] are not part of PoolSlice's + // public surface. + redeemable *PoolRedeemable[Slice[T]] +} + +// PoolSliceOption alters the default settings to allocate new pooled slices +type PoolSliceOption func(*poolSliceOptions) + +type poolSliceOptions struct { + minCapacity int + length int + maxCapacity int +} + +func WithMinimumCapacity(size int) PoolSliceOption { + return func(o *poolSliceOptions) { + o.minCapacity = size + } +} + +// WithMaxCapacity bounds the capacity of recycled slices. +// +// When a borrowed slice has grown past size at redeem time, its (oversized) +// backing array is discarded and replaced with a fresh one sized to the minimum +// capacity, instead of being recycled. +// +// This stops the pool from accumulating large backing arrays after an +// occasional large request, keeping the steady-state memory bounded. +// +// The trade-off: a workload that genuinely needs slices larger than size will +// reallocate on every cycle. +// Set size from the high-water mark you actually expect, not below it. +// A size of 0 (the default) means no cap: grown slices are recycled as-is. +func WithMaxCapacity(size int) PoolSliceOption { + return func(o *poolSliceOptions) { + o.maxCapacity = size + } +} + +// WithLength ensures that the borrowed slices have a fixed given initial +// length. +// +// By default, the borrowed slices are reset to length 0. +func WithLength(size int) PoolSliceOption { + return func(o *poolSliceOptions) { + o.length = size + } +} + +// NewPoolSlice builds a pool to recycle slices of type []T. +func NewPoolSlice[T any](opts ...PoolSliceOption) *PoolSlice[T] { + var o poolSliceOptions + for _, apply := range opts { + apply(&o) + } + + rp := &PoolRedeemable[Slice[T]]{} + rp.pool = sync.Pool{ + New: func() any { + s := &redeemable[Slice[T]]{ + inner: &Slice[T]{ + length: o.length, + inner: make([]T, o.length, max(o.length, o.minCapacity)), + }, + } + + s.redeemer = func() { + if !s.state.CompareAndSwap(stateBorrowed, stateIdle) { + panic(redeemPanic) + } + if o.maxCapacity > 0 && s.inner.Cap() > o.maxCapacity { + s.inner.resetWithCapacity(o.minCapacity) + } else { + s.inner.Reset() + } + rp.pool.Put(s) + } + + return s + }, + } + rp.tracker.register() + + return &PoolSlice[T]{redeemable: rp} +} + +// BorrowWithRedeem returns the slice wrapper and the redeem closure to +// relinquish the allocated wrapper. +// +// The wrapper is reset (elements zeroed, length restored) both on borrow and +// when the redeem closure is called. +// Calling the redeem closure more than once panics. +func (p *PoolSlice[T]) BorrowWithRedeem() (*Slice[T], func()) { + return p.redeemable.BorrowWithRedeem() +} + +// BorrowWithSizeAndRedeem borrows a slice []T from the pool and ensures that +// its capacity is at least the provided size. +func (p *PoolSlice[T]) BorrowWithSizeAndRedeem(size int) (*Slice[T], func()) { + s, redeem := p.BorrowWithRedeem() + s.Grow(size) + + return s, redeem +} diff --git a/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go b/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go index 3daf68dbba0..24d951f8de0 100644 --- a/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go +++ b/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go @@ -123,7 +123,7 @@ func (s YAMLMapSlice) MarshalYAML() (any, error) { var nodes []*yaml.Node for _, item := range s { - nn, err := json2yaml(item.Value) + nn, err := json2yaml(item.Value, 1) if err != nil { return nil, err } @@ -153,6 +153,17 @@ func (s YAMLMapSlice) MarshalYAML() (any, error) { // // It implements [yaml.Unmarshaler]. func (s *YAMLMapSlice) UnmarshalYAML(node *yaml.Node) error { + return s.unmarshalYAML(newYAMLWalker(), node, 0) +} + +// unmarshalYAML builds the slice from a [yaml.Node], tracking the recursion depth (against +// stack-overflow) and threading the [yamlWalker] so anchor/alias expansion stays bounded +// across the whole document. +func (s *YAMLMapSlice) unmarshalYAML(w *yamlWalker, node *yaml.Node, depth int) error { + if depth > defaultMaxNestingDepth { + return errMaxNestingDepth + } + if typeutils.IsNil(*s) { // allow to unmarshal with a simple var declaration (nil slice) *s = YAMLMapSlice{} @@ -167,13 +178,17 @@ func (s *YAMLMapSlice) UnmarshalYAML(node *yaml.Node) error { m = m[:0] for i := 0; i < len(node.Content); i += 2 { + if err := w.account(); err != nil { // account the key node + return err + } + var nmi YAMLMapItem k, err := yamlStringScalarC(node.Content[i]) if err != nil { return fmt.Errorf("unable to decode YAML map key: %w: %w", err, ErrYAML) } nmi.Key = k - v, err := yamlNode(node.Content[i+1]) + v, err := w.node(node.Content[i+1], depth+1) if err != nil { return fmt.Errorf("unable to process YAML map value for key %q: %w: %w", k, err, ErrYAML) } @@ -186,7 +201,11 @@ func (s *YAMLMapSlice) UnmarshalYAML(node *yaml.Node) error { return nil } -func json2yaml(item any) (*yaml.Node, error) { +func json2yaml(item any, depth int) (*yaml.Node, error) { + if depth > defaultMaxNestingDepth { + return nil, errMaxNestingDepth + } + if typeutils.IsNil(item) { return &yaml.Node{ Kind: yaml.ScalarNode, @@ -196,7 +215,7 @@ func json2yaml(item any) (*yaml.Node, error) { switch val := item.(type) { case ifaces.Ordered: - return orderedYAML(val) + return orderedYAML(val, depth) case map[string]any: var n yaml.Node @@ -209,7 +228,7 @@ func json2yaml(item any) (*yaml.Node, error) { for _, k := range keys { v := val[k] - childNode, err := json2yaml(v) + childNode, err := json2yaml(v, depth+1) if err != nil { return nil, err } @@ -225,7 +244,7 @@ func json2yaml(item any) (*yaml.Node, error) { var n yaml.Node n.Kind = yaml.SequenceNode for i := range val { - childNode, err := json2yaml(val[i]) + childNode, err := json2yaml(val[i], depth+1) if err != nil { return nil, err } @@ -297,11 +316,11 @@ func uintegerNode[T conv.Unsigned](val T) (*yaml.Node, error) { }, nil } -func orderedYAML[T ifaces.Ordered](val T) (*yaml.Node, error) { +func orderedYAML[T ifaces.Ordered](val T, depth int) (*yaml.Node, error) { var n yaml.Node n.Kind = yaml.MappingNode for key, value := range val.OrderedItems() { - childNode, err := json2yaml(value) + childNode, err := json2yaml(value, depth+1) if err != nil { return nil, err } diff --git a/vendor/github.com/go-openapi/swag/yamlutils/yaml.go b/vendor/github.com/go-openapi/swag/yamlutils/yaml.go index e3aff3c2fde..d4b5335f6f2 100644 --- a/vendor/github.com/go-openapi/swag/yamlutils/yaml.go +++ b/vendor/github.com/go-openapi/swag/yamlutils/yaml.go @@ -12,13 +12,99 @@ import ( yaml "go.yaml.in/yaml/v3" ) +// defaultMaxNestingDepth caps the recursion depth of the YAML<->JSON transforms to +// guard against stack-overflow on deeply nested (possibly adversarial) input. +// +// It matches the limit enforced by go.yaml.in/yaml/v3's own parser and by +// encoding/json's decoder. +const defaultMaxNestingDepth = 10000 + +// Bounds on YAML anchor/alias expansion. +// +// go.yaml.in/yaml/v3 enforces these when decoding into Go values, but that guard is +// coupled to the library's own tree walk: when we decode into a low-level [yaml.Node] +// (to preserve key order) and expand aliases ourselves in [yamlWalker.node], we bypass +// it. We therefore reproduce it here, with the same constants and ratio schedule as the +// library's decoder (see go.yaml.in/yaml/v3 decode.go, "excessive aliasing"). +const ( + aliasCountThreshold = 100 + decodeCountThreshold = 1000 + + // 400,000 decode operations is ~500kb of dense object declarations, or + // ~5kb of dense object declarations with 10000% alias expansion. + aliasRatioRangeLow = 400000 + // 4,000,000 decode operations is ~5MB of dense object declarations. + aliasRatioRangeHigh = 4000000 + aliasRatioRange = float64(aliasRatioRangeHigh - aliasRatioRangeLow) + + // tolerated share of alias-driven decodes: from aliasRatioSmall (small/medium documents) + // down to aliasRatioLarge (very large ones), interpolated with slope aliasRatioSlope. + aliasRatioSmall = 0.99 + aliasRatioLarge = 0.10 + aliasRatioSlope = aliasRatioSmall - aliasRatioLarge +) + +var ( + // errMaxNestingDepth is returned when a document nests deeper than [defaultMaxNestingDepth]. + errMaxNestingDepth = fmt.Errorf("maximum nesting depth of %d exceeded: %w", defaultMaxNestingDepth, ErrYAML) + + // errExcessiveAliasing is returned when anchor/alias expansion is disproportionate to the + // size of the document, i.e. an "alias bomb". + errExcessiveAliasing = fmt.Errorf("document contains excessive aliasing: %w", ErrYAML) +) + +// allowedAliasRatio scales the tolerated share of alias-driven decode operations from 99% +// for small-to-medium documents down to 10% for very large ones, mirroring go.yaml.in/yaml/v3. +func allowedAliasRatio(decodeCount int) float64 { + switch { + case decodeCount <= aliasRatioRangeLow: + return aliasRatioSmall + case decodeCount >= aliasRatioRangeHigh: + return aliasRatioLarge + default: + return aliasRatioSmall - aliasRatioSlope*(float64(decodeCount-aliasRatioRangeLow)/aliasRatioRange) + } +} + +// yamlWalker carries the state needed to bound a single YAML-tree traversal: +// anchor/alias expansion accounting and cycle detection. +// +// A fresh walker is created per top-level conversion; it is threaded (not copied) through +// the whole recursive walk so its counters accumulate across the entire document. +type yamlWalker struct { + decodeCount int + aliasCount int + aliasDepth int + aliases map[*yaml.Node]bool // anchors currently being expanded, for cycle detection +} + +func newYAMLWalker() *yamlWalker { + return &yamlWalker{aliases: make(map[*yaml.Node]bool)} +} + +// account records one processed node and fails if alias expansion has become excessive. +func (w *yamlWalker) account() error { + w.decodeCount++ + if w.aliasDepth > 0 { + w.aliasCount++ + } + + if w.aliasCount > aliasCountThreshold && + w.decodeCount > decodeCountThreshold && + float64(w.aliasCount)/float64(w.decodeCount) > allowedAliasRatio(w.decodeCount) { + return errExcessiveAliasing + } + + return nil +} + // YAMLToJSON converts a YAML document into JSON bytes. // // Note: a YAML document is the output from a [yaml.Marshaler], e.g a pointer to a [yaml.Node]. // // [YAMLToJSON] is typically called after [BytesToYAMLDoc]. func YAMLToJSON(value any) (json.RawMessage, error) { - jm, err := transformData(value) + jm, err := transformData(value, 0) if err != nil { return nil, err } @@ -44,46 +130,73 @@ func BytesToYAMLDoc(data []byte) (any, error) { return &document, nil } -func yamlNode(root *yaml.Node) (any, error) { +func (w *yamlWalker) node(root *yaml.Node, depth int) (any, error) { + if depth > defaultMaxNestingDepth { + return nil, errMaxNestingDepth + } + if err := w.account(); err != nil { + return nil, err + } + switch root.Kind { case yaml.DocumentNode: - return yamlDocument(root) + return w.document(root, depth) case yaml.SequenceNode: - return yamlSequence(root) + return w.sequence(root, depth) case yaml.MappingNode: - return yamlMapping(root) + return w.mapping(root, depth) case yaml.ScalarNode: return yamlScalar(root) case yaml.AliasNode: - return yamlNode(root.Alias) + return w.alias(root, depth) default: return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML) } } -func yamlDocument(node *yaml.Node) (any, error) { +// alias resolves an anchor reference, expanding the anchored subtree. It detects cycles +// (an anchor whose expansion transitively references itself) and accounts the expansion +// against the alias-bomb budget via [yamlWalker.aliasDepth]. +func (w *yamlWalker) alias(node *yaml.Node, depth int) (any, error) { + if node.Alias == nil { + return nil, fmt.Errorf("invalid YAML alias node %q: %w", node.Value, ErrYAML) + } + if w.aliases[node.Alias] { + return nil, fmt.Errorf("anchor %q contains itself: %w", node.Value, ErrYAML) + } + + w.aliases[node.Alias] = true + w.aliasDepth++ + out, err := w.node(node.Alias, depth+1) + w.aliasDepth-- + delete(w.aliases, node.Alias) + + return out, err +} + +func (w *yamlWalker) document(node *yaml.Node, depth int) (any, error) { if len(node.Content) != 1 { return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML) } - return yamlNode(node.Content[0]) + return w.node(node.Content[0], depth+1) } -func yamlMapping(node *yaml.Node) (any, error) { +func (w *yamlWalker) mapping(node *yaml.Node, depth int) (any, error) { const sensibleAllocDivider = 2 // nodes concatenate (key,value) sequences m := make(YAMLMapSlice, len(node.Content)/sensibleAllocDivider) - if err := m.UnmarshalYAML(node); err != nil { + if err := m.unmarshalYAML(w, node, depth); err != nil { return nil, err } return m, nil } -func yamlSequence(node *yaml.Node) (any, error) { +func (w *yamlWalker) sequence(node *yaml.Node, depth int) (any, error) { s := make([]any, 0) for i := range len(node.Content) { - v, err := yamlNode(node.Content[i]) + v, err := w.node(node.Content[i], depth+1) if err != nil { return nil, fmt.Errorf("unable to decode YAML sequence value: %w: %w", err, ErrYAML) } @@ -174,12 +287,16 @@ func format(t any) (string, error) { } } -func transformData(input any) (out any, err error) { +func transformData(input any, depth int) (out any, err error) { + if depth > defaultMaxNestingDepth { + return nil, errMaxNestingDepth + } + switch in := input.(type) { case yaml.Node: - return yamlNode(&in) + return newYAMLWalker().node(&in, depth) case *yaml.Node: - return yamlNode(in) + return newYAMLWalker().node(in, depth) case map[any]any: o := make(YAMLMapSlice, 0, len(in)) for ke, va := range in { @@ -188,7 +305,7 @@ func transformData(input any) (out any, err error) { return nil, err } - v, ert := transformData(va) + v, ert := transformData(va, depth+1) if ert != nil { return nil, ert } @@ -200,7 +317,7 @@ func transformData(input any) (out any, err error) { len1 := len(in) o := make([]any, len1) for i := range len1 { - o[i], err = transformData(in[i]) + o[i], err = transformData(in[i], depth+1) if err != nil { return nil, err } diff --git a/vendor/github.com/go-openapi/validate/CONTRIBUTORS.md b/vendor/github.com/go-openapi/validate/CONTRIBUTORS.md index 7b79b765dc3..40d877a1175 100644 --- a/vendor/github.com/go-openapi/validate/CONTRIBUTORS.md +++ b/vendor/github.com/go-openapi/validate/CONTRIBUTORS.md @@ -4,12 +4,12 @@ | Total Contributors | Total Contributions | | --- | --- | -| 31 | 295 | +| 31 | 310 | | Username | All Time Contribution Count | All Commits | | --- | --- | --- | | @casualjim | 169 | | -| @fredbi | 58 | | +| @fredbi | 73 | | | @sttts | 11 | | | @youyuanwu | 9 | | | @keramix | 8 | | @@ -40,4 +40,4 @@ | @dadgar | 1 | | | @elakito | 1 | | - _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_ + _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/validate/README.md b/vendor/github.com/go-openapi/validate/README.md index fec42b7c6ed..b814a2ef126 100644 --- a/vendor/github.com/go-openapi/validate/README.md +++ b/vendor/github.com/go-openapi/validate/README.md @@ -18,12 +18,9 @@ A validator for OpenAPI v2 specifications and JSON schema draft 4. * **2025-12-19** : new community chat on discord * a new discord community channel is available to be notified of changes and support users - * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] -Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] - ## Status API is stable. @@ -75,9 +72,9 @@ This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). ## Other documentation * [All-time contributors](./CONTRIBUTORS.md) -* [Contributing guidelines](.github/CONTRIBUTING.md) -* [Maintainers documentation](docs/MAINTAINERS.md) -* [Code style](docs/STYLE.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] ## Cutting a new release @@ -108,11 +105,8 @@ Maintainers can cut a new release by either: [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/validate [godoc-url]: http://pkg.go.dev/github.com/go-openapi/validate -[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png -[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM -[slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue -[discord-url]: https://discord.gg/twZ9BwT3 +[discord-url]: https://discord.gg/FfnFYaC3k5 [license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg @@ -122,3 +116,7 @@ Maintainers can cut a new release by either: [goversion-url]: https://github.com/go-openapi/validate/blob/master/go.mod [top-badge]: https://img.shields.io/github/languages/top/go-openapi/validate [commits-badge]: https://img.shields.io/github/commits-since/go-openapi/validate/latest + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/validate/helpers.go b/vendor/github.com/go-openapi/validate/helpers.go index 8a1a2312830..7cc254e02ea 100644 --- a/vendor/github.com/go-openapi/validate/helpers.go +++ b/vendor/github.com/go-openapi/validate/helpers.go @@ -242,9 +242,9 @@ func (h *paramHelper) resolveParam(path, method, operationID string, param *spec res := new(Result) isRef := param.Ref.String() != "" if s.spec.SpecFilePath() == "" { - err = spec.ExpandParameterWithRoot(param, s.spec.Spec(), nil) + err = spec.ExpandParameterWithOptions(param, s.spec.Spec(), nil, s.schemaOptions.expandOptions("")) } else { - err = spec.ExpandParameter(param, s.spec.SpecFilePath()) + err = spec.ExpandParameterWithOptions(param, nil, nil, s.schemaOptions.expandOptions(s.spec.SpecFilePath())) } if err != nil { // Safeguard // NOTE: we may enter here when the whole parameter is an unresolved $ref @@ -295,9 +295,9 @@ func (r *responseHelper) expandResponseRef( res := new(Result) if s.spec.SpecFilePath() == "" { // there is no physical document to resolve $ref in response - err = spec.ExpandResponseWithRoot(response, s.spec.Spec(), nil) + err = spec.ExpandResponseWithOptions(response, s.spec.Spec(), nil, s.schemaOptions.expandOptions("")) } else { - err = spec.ExpandResponse(response, s.spec.SpecFilePath()) + err = spec.ExpandResponseWithOptions(response, nil, nil, s.schemaOptions.expandOptions(s.spec.SpecFilePath())) } if err != nil { // Safeguard // NOTE: we may enter here when the whole response is an unresolved $ref. diff --git a/vendor/github.com/go-openapi/validate/schema.go b/vendor/github.com/go-openapi/validate/schema.go index b72a47bc331..706b7f5ef67 100644 --- a/vendor/github.com/go-openapi/validate/schema.go +++ b/vendor/github.com/go-openapi/validate/schema.go @@ -63,18 +63,18 @@ func newSchemaValidator(schema *spec.Schema, rootSchema any, root string, format rootSchema = schema } + if opts == nil { + opts = new(SchemaValidatorOptions) + } + if schema.ID != "" || schema.Ref.String() != "" || schema.Ref.IsRoot() { - err := spec.ExpandSchema(schema, rootSchema, nil) + err := spec.ExpandSchemaWithOptions(schema, rootSchema, nil, opts.expandOptions("")) if err != nil { msg := invalidSchemaProvidedMsg(err).Error() panic(msg) } } - if opts == nil { - opts = new(SchemaValidatorOptions) - } - var s *SchemaValidator if opts.recycleValidators { s = pools.poolOfSchemaValidators.BorrowValidator() diff --git a/vendor/github.com/go-openapi/validate/schema_option.go b/vendor/github.com/go-openapi/validate/schema_option.go index 3e1b882ed38..3ca489c0f54 100644 --- a/vendor/github.com/go-openapi/validate/schema_option.go +++ b/vendor/github.com/go-openapi/validate/schema_option.go @@ -3,6 +3,13 @@ package validate +import ( + "encoding/json" + + "github.com/go-openapi/spec" + "github.com/go-openapi/swag/loading" +) + // SchemaValidatorOptions defines optional rules for schema validation. type SchemaValidatorOptions struct { EnableObjectArrayTypeCheck bool @@ -10,6 +17,7 @@ type SchemaValidatorOptions struct { recycleValidators bool recycleResult bool skipSchemataResult bool + pathLoaderWithOptions func(string, ...loading.Option) (json.RawMessage, error) } // Option sets optional rules for schema validation. @@ -60,6 +68,23 @@ func WithSkipSchemataResult(enable bool) Option { } } +// WithPathLoader injects the document loader used to resolve remote and relative $ref while +// validating a schema or specification. It matches the option-aware loader signature of +// github.com/go-openapi/swag/loading (and go-openapi/loads). +// +// This lets validation resolve references through a caller-provided loader instead of the spec +// package's global default. The loader may carry any loading options — a custom HTTP client or +// timeout, authentication or custom headers, an embedded or rooted file system, and so on. +// +// One important use is confining loading of untrusted input: build the loader with loading.WithRoot +// (to confine local reads) and loading.WithHTTPClient (to restrict remote fetches), or use a +// restricted loader from go-openapi/loads. Left unset, the spec package default loader is used. +func WithPathLoader(loader func(string, ...loading.Option) (json.RawMessage, error)) Option { + return func(svo *SchemaValidatorOptions) { + svo.pathLoaderWithOptions = loader + } +} + // Options returns the current set of options. func (svo SchemaValidatorOptions) Options() []Option { return []Option{ @@ -68,5 +93,17 @@ func (svo SchemaValidatorOptions) Options() []Option { WithRecycleValidators(svo.recycleValidators), withRecycleResults(svo.recycleResult), WithSkipSchemataResult(svo.skipSchemataResult), + WithPathLoader(svo.pathLoaderWithOptions), + } +} + +// expandOptions builds the spec expand options for schema/$ref expansion during validation, +// carrying the injected loader (when set) so resolution can be confined. relativeBase is used for +// base-path-relative resolution; it is ignored by [spec.ExpandSchemaWithOptions], which derives the +// base from the root. +func (svo *SchemaValidatorOptions) expandOptions(relativeBase string) *spec.ExpandOptions { + return &spec.ExpandOptions{ + RelativeBase: relativeBase, + PathLoaderWithOptions: svo.pathLoaderWithOptions, } } diff --git a/vendor/github.com/go-openapi/validate/spec.go b/vendor/github.com/go-openapi/validate/spec.go index b85432f92b1..d6a61eae29c 100644 --- a/vendor/github.com/go-openapi/validate/spec.go +++ b/vendor/github.com/go-openapi/validate/spec.go @@ -25,6 +25,9 @@ import ( // // Returns an error flattening in a single standard error, all validation messages. // +// Options are forwarded to the underlying [SpecValidator]; in particular [WithPathLoader] injects a +// confined document loader for validating a specification from an untrusted source. +// // - Proposal for enhancement: $ref should not have siblings // - Proposal for enhancement: make sure documentation reflects all checks and warnings // - Proposal for enhancement: check on discriminators @@ -35,8 +38,8 @@ import ( // - Proposal for enhancement: check on required properties to support anyOf, allOf, oneOf // // NOTE: SecurityScopes are maps: no need to check uniqueness. -func Spec(doc *loads.Document, formats strfmt.Registry) error { - errs, _ /*warns*/ := NewSpecValidator(doc.Schema(), formats).Validate(doc) +func Spec(doc *loads.Document, formats strfmt.Registry, options ...Option) error { + errs, _ /*warns*/ := NewSpecValidator(doc.Schema(), formats, options...).Validate(doc) if errs.HasErrors() { return errors.CompositeValidationError(errs.Errors...) } @@ -55,14 +58,20 @@ type SpecValidator struct { } // NewSpecValidator creates a new swagger spec validator instance. -func NewSpecValidator(schema *spec.Schema, formats strfmt.Registry) *SpecValidator { - // schema options that apply to all called validators +// +// Options apply to the schema validators used internally. In particular, [WithPathLoader] injects +// the document loader used to resolve $ref while validating the specification — set a confined +// loader when validating a specification from an untrusted source (see the package "Security" +// notes on [WithPathLoader]). +func NewSpecValidator(schema *spec.Schema, formats strfmt.Registry, options ...Option) *SpecValidator { + // schema options that apply to all called validators: built-in defaults first, then + // caller-supplied options (which may add a loader or override a default). schemaOptions := new(SchemaValidatorOptions) - for _, o := range []Option{ + for _, o := range append([]Option{ SwaggerSchema(true), WithRecycleValidators(true), // withRecycleResults(true), - } { + }, options...) { o(schemaOptions) } @@ -146,7 +155,8 @@ func (s *SpecValidator) Validate(data any) (*Result, *Result) { errs.Merge(s.validateNonEmptyPathParamNames()) // errs.Merge(s.validateRefNoSibling()) // warning only - errs.Merge(s.validateReferenced()) // warning only + errs.Merge(s.validateReferenced()) // warning only + errs.Merge(s.validateDubiousRefs()) // warning only return errs, warnings } @@ -251,7 +261,7 @@ func (s *SpecValidator) validateDuplicatePropertyNames() *Result { func (s *SpecValidator) resolveRef(ref *spec.Ref) (*spec.Schema, error) { if s.spec.SpecFilePath() != "" { - return spec.ResolveRefWithBase(s.spec.Spec(), ref, &spec.ExpandOptions{RelativeBase: s.spec.SpecFilePath()}) + return spec.ResolveRefWithBase(s.spec.Spec(), ref, s.schemaOptions.expandOptions(s.spec.SpecFilePath())) } // NOTE: it looks like with the new spec resolver, this code is now unrecheable return spec.ResolveRef(s.spec.Spec(), ref) @@ -553,8 +563,12 @@ DEFINITIONS: if schema.Required != nil { // Safeguard for _, pn := range schema.Required { red := s.validateRequiredProperties(pn, d, &schema) //#nosec + // NOTE: capture validity before merging: Merge may redeem `red` to the + // pool (wantsRedeemOnMerge), after which reading it races with a concurrent + // BorrowResult().cleared() in another goroutine sharing the global pool. + isValid := red.IsValid() res.Merge(red) - if !red.IsValid() && !s.Options.ContinueOnErrors { + if !isValid && !s.Options.ContinueOnErrors { break DEFINITIONS // there is an error, let's stop that bleeding } } @@ -784,7 +798,10 @@ func (s *SpecValidator) validateReferencesValid() *Result { // NOTE: with default settings, loads.Document.Expanded() // stops on first error. Anyhow, the expand option to continue // on errors fails to report errors at all. - exp, err := s.spec.Expanded() + // + // Pass the injected loader (if any) so whole-spec expansion is confined too. When no loader + // is set, this is a no-op: loads falls back to the document's own loader. + exp, err := s.spec.Expanded(s.schemaOptions.expandOptions("")) if err != nil { res.AddErrors(unresolvedReferencesMsg(err)) } diff --git a/vendor/github.com/go-openapi/validate/spec_messages.go b/vendor/github.com/go-openapi/validate/spec_messages.go index 42ce3602852..eeb8a869518 100644 --- a/vendor/github.com/go-openapi/validate/spec_messages.go +++ b/vendor/github.com/go-openapi/validate/spec_messages.go @@ -177,6 +177,18 @@ const ( // UnusedResponseWarning ... UnusedResponseWarning = "response %q is not used anywhere" + // DubiousAbsoluteRefWarning flags a $ref pointing to an absolute local file location that escapes the + // spec's base path. Absolute local references are legitimate when they stay beneath the base path + // (flattening/expansion introduces such anchors for cyclical $refs), but an absolute reference that + // escapes the base path - or a file:// reference in a spec with no known base - may indicate an + // unsafe or adversarial spec. + DubiousAbsoluteRefWarning = "$ref %q points to an absolute or local file location that escapes the spec's base path: this may be unsafe with adversarial specs" + + // DubiousMultipleHostsWarning flags a spec whose remote $refs resolve to several distinct hosts. + // A single consistent remote host is common and legitimate; references spread across multiple hosts + // may indicate an unsafe or adversarial spec. + DubiousMultipleHostsWarning = "$ref values point to %d distinct remote hosts (%s): a spec referencing multiple hosts may be unsafe" + InvalidObject = "expected an object in %q.%s" ) @@ -404,3 +416,11 @@ func someParametersBrokenMsg(path, method, operationID string) errors.Error { func refShouldNotHaveSiblingsMsg(path, operationID string) errors.Error { return errors.New(errors.CompositeErrorCode, RefShouldNotHaveSiblingsWarning, operationID, path) } + +func dubiousAbsoluteRefMsg(ref string) errors.Error { + return errors.New(errors.CompositeErrorCode, DubiousAbsoluteRefWarning, ref) +} + +func dubiousMultipleHostsMsg(count int, hosts string) errors.Error { + return errors.New(errors.CompositeErrorCode, DubiousMultipleHostsWarning, count, hosts) +} diff --git a/vendor/github.com/go-openapi/validate/spec_ref_warnings.go b/vendor/github.com/go-openapi/validate/spec_ref_warnings.go new file mode 100644 index 00000000000..49c72314c94 --- /dev/null +++ b/vendor/github.com/go-openapi/validate/spec_ref_warnings.go @@ -0,0 +1,209 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package validate + +import ( + "net/url" + "path" + "sort" + "strings" + + "github.com/go-openapi/spec" +) + +// minDistinctHostsToWarn is the number of distinct remote hosts among $refs at or above which +// Rule 2 emits a host-spread warning. A single consistent remote host is legitimate. +const minDistinctHostsToWarn = 2 + +// validateDubiousRefs emits warnings (never errors) when $ref locations match patterns +// that may indicate an unsafe or adversarial spec. It inspects refs as authored, on the +// UNEXPANDED spec, so it must run before expansion flattens them away. +// +// Two rules are applied over s.analyzer.AllRefs(): +// +// - Rule 1 (absolute local escape): a $ref pointing to an absolute local file location +// (file:// scheme, a Unix absolute path, or a Windows drive path such as C:\) is dubious +// UNLESS it stays beneath the spec's base path. Absolute refs beneath the base are +// legitimate: flattening/expansion in go-openapi/spec and analysis introduces absolute +// anchors to resolve cyclical $refs. Relative and fragment-only refs are always exempt. +// +// - Rule 2 (host spread): when remote (http/https, or protocol-relative) refs resolve to +// two or more distinct hosts, a single aggregate warning lists them. A single consistent +// remote host is common and legitimate, so it is not flagged. +// +// All findings are warnings: they do not affect validity (see Result.IsValid). +func (s *SpecValidator) validateDubiousRefs() *Result { + res := pools.poolOfResults.BorrowResult() + + baseDir, hasBase := s.localBaseDir() + + remoteHosts := make(map[string]struct{}) + for _, r := range s.analyzer.AllRefs() { + u := r.GetURL() + if u == nil { // Safeguard: a valid spec always yields parseable refs + continue + } + + // Rule 1: absolute local reference escaping the base path. + if refPath, isLocalAbs := absoluteLocalRefPath(r, u); isLocalAbs { + if !hasBase || !isBeneathBase(refPath, baseDir) { + res.AddWarnings(dubiousAbsoluteRefMsg(r.String())) + } + continue + } + + // Rule 2: gather remote hosts (http/https and protocol-relative //host/...). + if host := remoteRefHost(u); host != "" { + remoteHosts[host] = struct{}{} + } + } + + if len(remoteHosts) >= minDistinctHostsToWarn { + hosts := make([]string, 0, len(remoteHosts)) + for h := range remoteHosts { + hosts = append(hosts, h) + } + sort.Strings(hosts) + res.AddWarnings(dubiousMultipleHostsMsg(len(hosts), strings.Join(hosts, ", "))) + } + + return res +} + +// absoluteLocalRefPath reports whether r is an absolute LOCAL file reference and, if so, +// returns the cleaned path it points to (without scheme/fragment, drive letter lower-cased). +// +// Classification order matters (see the empirical jsonreference flag behavior): +// - file:// scheme is local, including UNC file://host/share (inherently dubious). +// - a non-empty Host with no file scheme means remote (http/https or protocol-relative +// //host/path) - NOT local; handled by Rule 2. This must be checked before the Unix +// branch, because protocol-relative refs also set HasFullFilePath. +// - len(u.Scheme) == 1 is a Windows drive path (C:\ or C:/), whose drive+path land in +// Scheme/Opaque/Path rather than Path. Checked before the Unix branch because C:/x also +// sets HasFullFilePath, and reconstructed from the authored ref string to keep the drive. +// - !r.HasFullURL && r.HasFullFilePath is a plain Unix absolute path (/abs/models.json). +// +// Relative (./x.json) and fragment-only (#/definitions/X) refs return false. +func absoluteLocalRefPath(r spec.Ref, u *url.URL) (string, bool) { + switch { + case r.HasFileScheme: + return fileRefPath(u), true + case u.Host != "": + // Remote (http/https) or protocol-relative //host/path: handled by Rule 2. + return "", false + case len(u.Scheme) == 1: + // Windows drive letter: reconstruct from the authored ref string. + return cleanRefPath(r.String()), true + case !r.HasFullURL && r.HasFullFilePath: + return cleanRefPath(u.Path), true + default: + return "", false + } +} + +// remoteRefHost returns the host of a remote reference (http/https), or of a protocol-relative +// reference (//host/path). It returns "" for local and fragment-only refs. file:// hosts (UNC) +// are deliberately excluded: those are handled as local-absolute refs by Rule 1. +func remoteRefHost(u *url.URL) string { + switch u.Scheme { + case "http", "https": + return u.Host + case "": + // Protocol-relative //host/path: empty scheme but a host is present. + return u.Host + default: + return "" + } +} + +// localBaseDir returns the directory of the spec file, slash-normalized, when the spec was +// loaded from a local path. It returns ok=false when the base is unknown (in-memory spec) or +// remote (http/https), in which case absolute-local refs cannot be proven beneath a base and +// are treated as dubious. +func (s *SpecValidator) localBaseDir() (string, bool) { + specPath := s.spec.SpecFilePath() + if specPath == "" { + return "", false + } + + // Strip a file:// scheme if present; reject remote bases. + if u, err := url.Parse(specPath); err == nil && u.Scheme != "" { + switch { + case u.Scheme == "file": + specPath = u.Path + case len(u.Scheme) == 1: // Windows drive letter, treat as local + // keep specPath as-is (authored path) + default: // http, https, ... : no local base + return "", false + } + } + + return path.Dir(cleanRefPath(specPath)), true +} + +// isBeneathBase reports whether the cleaned target path is located within baseDir, i.e. it does +// not escape baseDir via "..". Comparison is purely lexical on cleaned paths, which is sufficient +// (and cross-platform safe) for a non-fatal warning. Both sides are expected to already be +// cleanRefPath-normalized (slashes, drive-letter case). +func isBeneathBase(target, baseDir string) bool { + if baseDir == "" { + return false + } + if target == baseDir { + return true + } + if !strings.HasSuffix(baseDir, "/") { + baseDir += "/" + } + return strings.HasPrefix(target, baseDir) +} + +// fileRefPath extracts the local path a file:// reference points to, accounting for the way +// Windows file URLs parse: +// - file:///abs/x -> /abs/x (empty host) +// - file:///C:/dir/x -> /c:/dir/x (empty host; drive sits in the path) +// - file://D:/a/x -> d:/a/x (drive letter lands in Host, rejoin it) +// - file://host/share -> /host/share/x (real UNC host kept visible so it cannot match a +// local base and stays flagged as dubious) +func fileRefPath(u *url.URL) string { + switch { + case u.Host == "": + return cleanRefPath(u.Path) + case isDriveHost(u.Host): + // Windows path authored as file://D:/... : the drive landed in Host (e.g. "d:"). + return cleanRefPath(u.Host + u.Path) + default: + // Real remote/UNC host: keep it in the path so it never matches a local base. + return cleanRefPath("//" + u.Host + u.Path) + } +} + +// isDriveHost reports whether a URL host is actually a Windows drive letter (e.g. "d:"), which +// happens when a Windows path is authored as a two-slash file URL: file://D:/path. +func isDriveHost(host string) bool { + h := strings.TrimSuffix(host, ":") + if len(h) != 1 { + return false + } + c := h[0] + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') +} + +// cleanRefPath normalizes a ref or base path for lexical comparison: backslashes to forward +// slashes, path.Clean, and a lower-cased leading Windows drive letter (matching the behavior of +// go-openapi/spec's normalizer). Plain Unix paths are unaffected, preserving case-sensitivity. +func cleanRefPath(p string) string { + p = path.Clean(strings.ReplaceAll(p, `\`, `/`)) + switch { + case len(p) >= 2 && p[1] == ':': + // drive-letter form: C:/dir -> c:/dir + p = strings.ToLower(p[:1]) + p[1:] + case len(p) >= 3 && p[0] == '/' && p[2] == ':': + // slash-prefixed drive form from canonical file:// URLs: /C:/dir -> c:/dir. + // The leading slash is dropped so this matches the base path derived from + // SpecFilePath (which has no leading slash), and the bare-drive form. + p = strings.ToLower(p[1:2]) + p[2:] + } + return p +} diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index fb023f2cf21..0e9f170d012 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -27,6 +27,18 @@ Use the links above for more information on each. # changelog +* Jul 1st, 2026 [1.19.0](https://github.com/klauspost/compress/releases/tag/v1.19.0) + * zstd: Add true concurrent stream encodingin https://github.com/klauspost/compress/pull/1136 + * zstd: arm64 decoder asm by @lizthegrey in https://github.com/klauspost/compress/pull/1160 + * flate: Add inflate checkpoints in https://github.com/klauspost/compress/pull/1154 + * zstd: avoid unused BuildDict encoder allocation by @snissn in https://github.com/klauspost/compress/pull/1147 + * snappy/s2: Limit length of varint in `decodedLen` by @eustas in https://github.com/klauspost/compress/pull/1148 + * gzhttp: match qvalue parameter case-insensitively (RFC 7231) by @z9z in https://github.com/klauspost/compress/pull/1149 + * zip: add NameDecoder callback for legacy encoding rewrite by @SAY-5 in https://github.com/klauspost/compress/pull/1150 + * huff0: Allow building tables from histogram in https://github.com/klauspost/compress/pull/1155 + * huff0: Allow building table from oversized histogram in https://github.com/klauspost/compress/pull/1156 + * s2sx: Clean symlink targets in https://github.com/klauspost/compress/pull/1163 + * Feb 9th, 2026 [1.18.4](https://github.com/klauspost/compress/releases/tag/v1.18.4) * gzhttp: Add zstandard to server handler wrapper https://github.com/klauspost/compress/pull/1121 * zstd: Add ResetWithOptions to encoder/decoder https://github.com/klauspost/compress/pull/1122 diff --git a/vendor/github.com/klauspost/compress/flate/dict_decoder.go b/vendor/github.com/klauspost/compress/flate/dict_decoder.go index cb855abc4ba..37861cf6afb 100644 --- a/vendor/github.com/klauspost/compress/flate/dict_decoder.go +++ b/vendor/github.com/klauspost/compress/flate/dict_decoder.go @@ -28,9 +28,10 @@ type dictDecoder struct { hist []byte // Sliding window history // Invariant: 0 <= rdPos <= wrPos <= len(hist) - wrPos int // Current output position in buffer - rdPos int // Have emitted hist[:rdPos] already - full bool // Has a full window length been written yet? + wrPos int // Current output position in buffer + rdPos int // Have emitted hist[:rdPos] already + flushed int64 // Total bytes returned by readFlush since init + full bool // Has a full window length been written yet? } // init initializes dictDecoder to have a sliding window dictionary of the given @@ -167,11 +168,22 @@ loop: return dstPos - dstBase } +// appendWindow appends the current sliding window (up to len(hist) most recent +// bytes, oldest first) to dst. +func (dd *dictDecoder) appendWindow(dst []byte) []byte { + if dd.full { + dst = append(dst, dd.hist[dd.wrPos:]...) + return append(dst, dd.hist[:dd.wrPos]...) + } + return append(dst, dd.hist[:dd.wrPos]...) +} + // readFlush returns a slice of the historical buffer that is ready to be // emitted to the user. The data returned by readFlush must be fully consumed // before calling any other dictDecoder methods. func (dd *dictDecoder) readFlush() []byte { toRead := dd.hist[dd.rdPos:dd.wrPos] + dd.flushed += int64(len(toRead)) dd.rdPos = dd.wrPos if dd.wrPos == len(dd.hist) { dd.wrPos, dd.rdPos = 0, 0 @@ -179,3 +191,9 @@ func (dd *dictDecoder) readFlush() []byte { } return toRead } + +// decoded reports the total number of bytes written into the dictionary since +// init (i.e. excluding any preset dict bytes). +func (dd *dictDecoder) decoded() int64 { + return dd.flushed + int64(dd.wrPos-dd.rdPos) +} diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go index 6e90126db03..39dd683b2dd 100644 --- a/vendor/github.com/klauspost/compress/flate/inflate.go +++ b/vendor/github.com/klauspost/compress/flate/inflate.go @@ -342,6 +342,11 @@ type decompressor struct { final bool flushMode flushMode + cb func(InflateCheckpoint) + cp InflateCheckpoint + hasCP bool // WithResumeFrom was supplied + uncOffset int64 // baseline uncompressed offset (from a resume checkpoint) + cpBuf []byte } func (f *decompressor) nextBlock() { @@ -676,6 +681,18 @@ func (f *decompressor) finishBlock() { f.toRead = f.dict.readFlush() } + if f.cb != nil { + bitPos := f.roffset*8 - int64(f.nb) + f.cpBuf = f.dict.appendWindow(f.cpBuf[:0]) + f.cb(InflateCheckpoint{ + UncompressedOffset: f.uncOffset + f.dict.decoded(), + CompressedOffset: bitPos / 8, + Final: f.final, + BitOffset: uint8(bitPos & 7), + Window: f.cpBuf, + }) + } + f.step = nextBlock } @@ -806,6 +823,45 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error { return nil } +// ResetCP will adjust the input to the provided checkpoint. +// It is assumed the input stream is forwarded to cp.CompressedOffset. +func (f *decompressor) ResetCP(r io.Reader, cp InflateCheckpoint) error { + *f = decompressor{ + r: makeReader(r), + bits: f.bits, + codebits: f.codebits, + h1: f.h1, + h2: f.h2, + dict: f.dict, + step: nextBlock, + cpBuf: f.cpBuf, + } + return f.applyCP(cp) +} + +// applyCP seeds the decompressor state from a resume checkpoint: +// loads the sliding window, sets the absolute compressed/uncompressed +// offsets, and skips cp.BitOffset bits into the first input byte so +// the next decode aligns with the start of a deflate block. +func (f *decompressor) applyCP(cp InflateCheckpoint) error { + f.dict.init(maxMatchOffset, cp.Window) + f.roffset = cp.CompressedOffset + f.uncOffset = cp.UncompressedOffset + f.final = cp.Final + f.b = 0 + f.nb = 0 + if cp.BitOffset > 0 { + c, err := f.r.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b = uint32(c) >> cp.BitOffset + f.nb = 8 - uint(cp.BitOffset) + } + return nil +} + type ReaderOpt func(*decompressor) // WithPartialBlock tells decompressor to return after each block, @@ -823,6 +879,36 @@ func WithDict(dict []byte) ReaderOpt { } } +// InflateCheckpoint provides a resumable checkpoint for inflate. +type InflateCheckpoint struct { + UncompressedOffset int64 // Byte offset in the decompressed stream + CompressedOffset int64 // Byte offset in the compressed stream + Final bool // True if this is the final block + BitOffset uint8 // 0-7 bits + Window []byte // 32KB sliding window dictionary +} + +// WithEobCallback will call the provided function after each block +// with the current gzip checkpoint. +// After returning the provided window can no longer be referenced. +// The callback will not be triggered after a block is marked "final". +// The callback is not retained after Reset. +func WithEobCallback(cb func(InflateCheckpoint)) ReaderOpt { + return func(f *decompressor) { + f.cb = cb + } +} + +// WithResumeFrom will adjust the input to the provided checkpoint. +// It is assumed the input stream is forwarded to the provided offset. +// The checkpoint is removed when Reset is called. +func WithResumeFrom(cp InflateCheckpoint) ReaderOpt { + return func(f *decompressor) { + f.cp = cp + f.hasCP = true + } +} + // NewReaderOpts returns new reader with provided options func NewReaderOpts(r io.Reader, opts ...ReaderOpt) io.ReadCloser { fixedHuffmanDecoderInit() @@ -838,6 +924,12 @@ func NewReaderOpts(r io.Reader, opts ...ReaderOpt) io.ReadCloser { opt(&f) } + if f.hasCP { + if err := f.applyCP(f.cp); err != nil { + f.err = err + } + } + return &f } diff --git a/vendor/github.com/klauspost/compress/flate/inflate_gen.go b/vendor/github.com/klauspost/compress/flate/inflate_gen.go index 2b2f993f753..e80f1965609 100644 --- a/vendor/github.com/klauspost/compress/flate/inflate_gen.go +++ b/vendor/github.com/klauspost/compress/flate/inflate_gen.go @@ -10,6 +10,15 @@ import ( "strings" ) +func peekBufio(fr *bufio.Reader) ([]byte, error) { + if fr.Buffered() == 0 { + if _, err := fr.Peek(1); err != nil && fr.Buffered() == 0 { + return nil, err + } + } + return fr.Peek(fr.Buffered()) +} + // Decode a single Huffman block from f. // hl and hd are the Huffman states for the lit/length values // and the distance values, respectively. If hd == nil, using the @@ -527,6 +536,8 @@ func (f *decompressor) huffmanBufioReader() { // but is smart enough to keep local variables in registers, so use nb and b, // inline call to moreBits and reassign b,nb back to f on return. fnb, fb, dict := f.nb, f.b, &f.dict + pbuf, _ := fr.Peek(fr.Buffered()) + pos := 0 switch f.stepState { case stateInit: @@ -548,12 +559,19 @@ readLiteral: n := uint(f.hl.maxRead) for { for fnb < n { - c, err := fr.ReadByte() - if err != nil { - f.b, f.nb = fb, fnb - f.err = noEOF(err) - return + if pos >= len(pbuf) { + fr.Discard(pos) + var err error + pbuf, err = peekBufio(fr) + pos = 0 + if len(pbuf) == 0 { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } } + c := pbuf[pos] + pos++ f.roffset++ fb |= uint32(c) << (fnb & regSizeMaskUint32) fnb += 8 @@ -566,6 +584,7 @@ readLiteral: } if n <= fnb { if n == 0 { + fr.Discard(pos) f.b, f.nb = fb, fnb if debugDecode { fmt.Println("huffsym: n==0") @@ -586,6 +605,7 @@ readLiteral: case v < 256: dict.writeByte(byte(v)) if dict.availWrite() == 0 { + fr.Discard(pos) f.toRead = dict.readFlush() f.step = huffmanBufioReader f.stepState = stateInit @@ -594,6 +614,7 @@ readLiteral: } goto readLiteral case v == 256: + fr.Discard(pos) f.b, f.nb = fb, fnb f.finishBlock() return @@ -605,15 +626,22 @@ readLiteral: length = int(val.length) + 3 n := uint(val.extra) for fnb < n { - c, err := fr.ReadByte() - if err != nil { - f.b, f.nb = fb, fnb - if debugDecode { - fmt.Println("morebits n>0:", err) + if pos >= len(pbuf) { + fr.Discard(pos) + var err error + pbuf, err = peekBufio(fr) + pos = 0 + if len(pbuf) == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return } - f.err = err - return } + c := pbuf[pos] + pos++ f.roffset++ fb |= uint32(c) << (fnb & regSizeMaskUint32) fnb += 8 @@ -622,6 +650,7 @@ readLiteral: fb >>= n & regSizeMaskUint32 fnb -= n default: + fr.Discard(pos) if debugDecode { fmt.Println(v, ">= maxNumLit") } @@ -633,15 +662,22 @@ readLiteral: var dist uint32 if f.hd == nil { for fnb < 5 { - c, err := fr.ReadByte() - if err != nil { - f.b, f.nb = fb, fnb - if debugDecode { - fmt.Println("morebits f.nb<5:", err) + if pos >= len(pbuf) { + fr.Discard(pos) + var err error + pbuf, err = peekBufio(fr) + pos = 0 + if len(pbuf) == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return } - f.err = err - return } + c := pbuf[pos] + pos++ f.roffset++ fb |= uint32(c) << (fnb & regSizeMaskUint32) fnb += 8 @@ -660,12 +696,19 @@ readLiteral: // inline call to moreBits and reassign b,nb back to f on return. for { for fnb < n { - c, err := fr.ReadByte() - if err != nil { - f.b, f.nb = fb, fnb - f.err = noEOF(err) - return + if pos >= len(pbuf) { + fr.Discard(pos) + var err error + pbuf, err = peekBufio(fr) + pos = 0 + if len(pbuf) == 0 { + f.b, f.nb = fb, fnb + f.err = noEOF(err) + return + } } + c := pbuf[pos] + pos++ f.roffset++ fb |= uint32(c) << (fnb & regSizeMaskUint32) fnb += 8 @@ -678,6 +721,7 @@ readLiteral: } if n <= fnb { if n == 0 { + fr.Discard(pos) f.b, f.nb = fb, fnb if debugDecode { fmt.Println("huffsym: n==0") @@ -701,15 +745,22 @@ readLiteral: // have 1 bit in bottom of dist, need nb more. extra := (dist & 1) << (nb & regSizeMaskUint32) for fnb < nb { - c, err := fr.ReadByte() - if err != nil { - f.b, f.nb = fb, fnb - if debugDecode { - fmt.Println("morebits f.nb= len(pbuf) { + fr.Discard(pos) + var err error + pbuf, err = peekBufio(fr) + pos = 0 + if len(pbuf) == 0 { + f.b, f.nb = fb, fnb + if debugDecode { + fmt.Println("morebits f.nb uint32(dict.histSize()) { + fr.Discard(pos) f.b, f.nb = fb, fnb if debugDecode { fmt.Println("dist > dict.histSize():", dist, dict.histSize()) @@ -752,6 +805,7 @@ copyHistory: f.copyLen -= cnt if dict.availWrite() == 0 || f.copyLen > 0 { + fr.Discard(pos) f.toRead = dict.readFlush() f.step = huffmanBufioReader // We need to continue this work f.stepState = stateDict diff --git a/vendor/github.com/klauspost/compress/gzhttp/compress.go b/vendor/github.com/klauspost/compress/gzhttp/compress.go index 0f84b28ec83..da5048ef240 100644 --- a/vendor/github.com/klauspost/compress/gzhttp/compress.go +++ b/vendor/github.com/klauspost/compress/gzhttp/compress.go @@ -1158,8 +1158,8 @@ func parseCoding(s string) (coding string, qvalue float64, err error) { if n == 0 { coding = strings.ToLower(part) - } else if after, ok := strings.CutPrefix(part, "q="); ok { - qvalue, err = strconv.ParseFloat(after, 64) + } else if len(part) >= 2 && strings.EqualFold(part[:2], "q=") { + qvalue, err = strconv.ParseFloat(part[2:], 64) if qvalue < 0.0 { qvalue = 0.0 diff --git a/vendor/github.com/klauspost/compress/huff0/build_table.go b/vendor/github.com/klauspost/compress/huff0/build_table.go new file mode 100644 index 00000000000..e3757c87e0f --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/build_table.go @@ -0,0 +1,168 @@ +package huff0 + +import "errors" + +// BuildCTable builds a Huffman compression table from a precomputed symbol +// histogram and installs it as the previous (reuse) table on s. +// +// After this call: +// - EstimateSize/CanUseTable can probe the table against other histograms. +// - Compress1X/Compress4X with Reuse = ReusePolicyMust will encode without +// emitting a new table header. +// - TransferCTable can hand the table to a sibling Scratch. +// +// count[i] is the number of occurrences of symbol i. The histogram must have +// at least 2 distinct non-zero symbols; ErrUseRLE is returned for a single +// symbol and an error is returned for an empty histogram. +func (s *Scratch) BuildCTable(count *[256]uint32) error { + if s == nil { + return errors.New("huff0: BuildCTable on nil Scratch") + } + if count == nil { + return errors.New("huff0: nil count passed to BuildCTable") + } + var err error + s, err = s.prepare(nil) + if err != nil { + return err + } + s.count = *count + var total, maxCount int + var symLen uint16 + for i, v := range s.count { + total += int(v) + if int(v) > maxCount { + maxCount = int(v) + } + if v != 0 { + symLen = uint16(i) + 1 + } + } + if total == 0 { + return errors.New("huff0: empty histogram") + } + if symLen < 2 || maxCount == total { + return ErrUseRLE + } + // huff0's internal rank table assumes total ≤ BlockSizeMax (it uses + // highBit32(count+1) + 1 as a rank index into a fixed-size array). + // Histograms summed across multiple blocks can exceed that; scale the + // counts down preserving the distribution. Non-zero entries round up so + // rare symbols stay representable. + if total > BlockSizeMax { + shift := uint(0) + for total>>shift > BlockSizeMax { + shift++ + } + round := uint32(1<> shift + if scaled == 0 { + scaled = 1 + } + s.count[i] = scaled + newTotal += int(scaled) + if int(scaled) > newMax { + newMax = int(scaled) + } + } + total = newTotal + maxCount = newMax + if maxCount == total { + return ErrUseRLE + } + } + s.symbolLen = symLen + s.maxCount = maxCount + s.srcLen = total + if err := s.buildCTable(); err != nil { + return err + } + if cap(s.prevTable) < len(s.cTable) { + s.prevTable = make(cTable, 0, maxSymbolValue+1) + } + s.prevTable = s.prevTable[:len(s.cTable)] + copy(s.prevTable, s.cTable) + s.prevTableLog = s.actualTableLog + // Force the next Compress* to recount from real input. + s.clearCount = true + s.maxCount = 0 + return nil +} + +// EstimateSize returns an estimated compressed payload size in bytes for the +// supplied histogram using the table currently stored in prevTable. It returns +// -1 when the table cannot encode every non-zero symbol of hist (i.e. when +// CanUseTable would return false). The estimate excludes the table header. +func (s *Scratch) EstimateSize(hist *[256]uint32) int { + if s == nil || hist == nil || len(s.prevTable) == 0 { + return -1 + } + pt := s.prevTable + nbBits := uint32(7) + for i, v := range hist { + if v == 0 { + continue + } + if i >= len(pt) || pt[i].nBits == 0 { + return -1 + } + nbBits += uint32(pt[i].nBits) * v + } + return int(nbBits >> 3) +} + +// CanUseTable reports whether the table in prevTable can encode every +// non-zero symbol present in hist. +func (s *Scratch) CanUseTable(hist *[256]uint32) bool { + if s == nil || hist == nil || len(s.prevTable) == 0 { + return false + } + pt := s.prevTable + for i, v := range hist { + if v == 0 { + continue + } + if i >= len(pt) || pt[i].nBits == 0 { + return false + } + } + return true +} + +// AppendTable serializes the table currently stored in prevTable (e.g. as +// installed by BuildCTable or carried over from a previous Compress call) +// into a self-delimiting zstd-style header and appends it to dst. The +// returned slice can be parsed back by ReadTable. +func (s *Scratch) AppendTable(dst []byte) ([]byte, error) { + if s == nil || len(s.prevTable) == 0 { + return dst, errors.New("huff0: AppendTable with empty table") + } + // cTable.write reads s.actualTableLog, s.symbolLen, s.huffWeight, s.fse + // and writes into s.Out. Save/restore Out so we don't disturb in-flight + // compression buffers. + saveOut := s.Out + saveTL := s.actualTableLog + saveSL := s.symbolLen + if s.fse == nil { + // Lazily init in case AppendTable is called on a fresh Scratch. + if _, err := s.prepare(nil); err != nil { + return dst, err + } + saveOut = s.Out + } + s.Out = s.Out[:0] + s.actualTableLog = s.prevTableLog + s.symbolLen = uint16(len(s.prevTable)) + if err := s.prevTable.write(s); err != nil { + s.Out, s.actualTableLog, s.symbolLen = saveOut, saveTL, saveSL + return dst, err + } + dst = append(dst, s.Out...) + s.Out, s.actualTableLog, s.symbolLen = saveOut, saveTL, saveSL + return dst, nil +} diff --git a/vendor/github.com/klauspost/compress/internal/snapref/decode.go b/vendor/github.com/klauspost/compress/internal/snapref/decode.go index a2c82fcd226..584b7574b20 100644 --- a/vendor/github.com/klauspost/compress/internal/snapref/decode.go +++ b/vendor/github.com/klauspost/compress/internal/snapref/decode.go @@ -31,7 +31,7 @@ func DecodedLen(src []byte) (int, error) { // that the length header occupied. func decodedLen(src []byte) (blockLen, headerLen int, err error) { v, n := binary.Uvarint(src) - if n <= 0 || v > 0xffffffff { + if n <= 0 || n > 5 || v > 0xffffffff { return 0, 0, ErrCorrupt } diff --git a/vendor/github.com/klauspost/compress/s2/decode.go b/vendor/github.com/klauspost/compress/s2/decode.go index 264ffd0a9b4..17abb515a59 100644 --- a/vendor/github.com/klauspost/compress/s2/decode.go +++ b/vendor/github.com/klauspost/compress/s2/decode.go @@ -35,7 +35,7 @@ func DecodedLen(src []byte) (int, error) { // that the length header occupied. func decodedLen(src []byte) (blockLen, headerLen int, err error) { v, n := binary.Uvarint(src) - if n <= 0 || v > 0xffffffff { + if n <= 0 || n > 5 || v > 0xffffffff { return 0, 0, ErrCorrupt } diff --git a/vendor/github.com/klauspost/compress/s2/encode_all.go b/vendor/github.com/klauspost/compress/s2/encode_all.go index 9d12c44f38a..794ec8a6874 100644 --- a/vendor/github.com/klauspost/compress/s2/encode_all.go +++ b/vendor/github.com/klauspost/compress/s2/encode_all.go @@ -981,7 +981,7 @@ searchDict: cv = load64(src, s) continue } - } else if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { + } else if repeat > 0 && uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) { base := s + checkRep // Extend back for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; { diff --git a/vendor/github.com/klauspost/compress/s2/hashtable_pool.go b/vendor/github.com/klauspost/compress/s2/hashtable_pool.go index bc7cabd5c5c..ec972132b57 100644 --- a/vendor/github.com/klauspost/compress/s2/hashtable_pool.go +++ b/vendor/github.com/klauspost/compress/s2/hashtable_pool.go @@ -25,7 +25,7 @@ type betterTables struct { sTable [betterShortTableSize]uint32 } -var betterTablePool = sync.Pool{New: func() interface{} { return &betterTables{} }} +var betterTablePool = sync.Pool{New: func() any { return &betterTables{} }} // betterSnappyTables holds better-snappy compression hash tables. type betterSnappyTables struct { @@ -33,7 +33,7 @@ type betterSnappyTables struct { sTable [betterShortTableSize]uint32 } -var betterSnappyTablePool = sync.Pool{New: func() interface{} { return &betterSnappyTables{} }} +var betterSnappyTablePool = sync.Pool{New: func() any { return &betterSnappyTables{} }} // bestTables holds best compression hash tables. type bestTables struct { @@ -41,7 +41,7 @@ type bestTables struct { sTable [bestShortTableSize]uint64 } -var bestTablePool = sync.Pool{New: func() interface{} { return &bestTables{} }} +var bestTablePool = sync.Pool{New: func() any { return &bestTables{} }} // getBetterTables gets a zeroed betterTables from the pool. func getBetterTables() *betterTables { diff --git a/vendor/github.com/klauspost/compress/s2/reader.go b/vendor/github.com/klauspost/compress/s2/reader.go index 4d01c4190cc..17443e2c146 100644 --- a/vendor/github.com/klauspost/compress/s2/reader.go +++ b/vendor/github.com/klauspost/compress/s2/reader.go @@ -216,13 +216,18 @@ func (r *Reader) skippable(tmp []byte, n int, allowEOF bool, id uint8) (ok bool) return r.err == nil } if rs, ok := r.r.(io.ReadSeeker); ok { - _, err := rs.Seek(int64(n), io.SeekCurrent) - if err == nil { - return true - } - if err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { - r.err = ErrCorrupt - return false + if cur, err := rs.Seek(0, io.SeekCurrent); err == nil { + if end, err := rs.Seek(0, io.SeekEnd); err == nil { + if cur+int64(n) <= end { + if _, err := rs.Seek(cur+int64(n), io.SeekStart); err == nil { + return true + } + } + if _, err := rs.Seek(cur, io.SeekStart); err != nil { + r.err = ErrCorrupt + return false + } + } } } for n > 0 { diff --git a/vendor/github.com/klauspost/compress/snappy/decode_strict.go b/vendor/github.com/klauspost/compress/snappy/decode_strict.go new file mode 100644 index 00000000000..6c28bcbbbc9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/snappy/decode_strict.go @@ -0,0 +1,130 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snappy + +import "encoding/binary" + +// DecodeStrict returns the decoded form of src, like Decode. +// +// Unlike Decode, which delegates to the s2 decoder and accepts the s2 +// "repeat last offset" extension (a copy whose encoded offset is 0), +// DecodeStrict uses a strict standard-Snappy block decoder. Offset 0 is not +// valid in the standard Snappy block format, so such a copy is rejected with +// ErrCorrupt. This makes DecodeStrict match github.com/golang/snappy and the +// C++ reference decoder, at the cost of being slower than Decode. +// +// The returned slice may be a sub-slice of dst if dst was large enough to +// hold the entire decoded block. Otherwise, a newly allocated slice will be +// returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// DecodeStrict handles the Snappy block format, not the Snappy stream format. +func DecodeStrict(dst, src []byte) ([]byte, error) { + v, n := binary.Uvarint(src) + if n <= 0 || n > 5 || v > 0xffffffff { + return nil, ErrCorrupt + } + const wordSize = 32 << (^uint(0) >> 32 & 1) + if wordSize == 32 && v > 0x7fffffff { + return nil, ErrTooLarge + } + dLen := int(v) + if dLen <= cap(dst) { + dst = dst[:dLen] + } else { + dst = make([]byte, dLen) + } + if decodeStrict(dst, src[n:]) != 0 { + return nil, ErrCorrupt + } + return dst, nil +} + +func decodeStrict(dst, src []byte) int { + var d, s, offset, length int + for s < len(src) { + switch src[s] & 0x03 { + case 0x00: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + s += 2 + if uint(s) > uint(len(src)) { + return 1 + } + x = uint32(src[s-1]) + case x == 61: + s += 3 + if uint(s) > uint(len(src)) { + return 1 + } + x = uint32(src[s-2]) | uint32(src[s-1])<<8 + case x == 62: + s += 4 + if uint(s) > uint(len(src)) { + return 1 + } + x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + case x == 63: + s += 5 + if uint(s) > uint(len(src)) { + return 1 + } + x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + } + length = int(x) + 1 + if length <= 0 || length > len(dst)-d || length > len(src)-s { + return 1 + } + copy(dst[d:], src[s:s+length]) + d += length + s += length + continue + case 0x01: + s += 2 + if uint(s) > uint(len(src)) { + return 1 + } + length = 4 + int(src[s-2])>>2&0x7 + offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + case 0x02: + s += 3 + if uint(s) > uint(len(src)) { + return 1 + } + length = 1 + int(src[s-3])>>2 + offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + case 0x03: + s += 5 + if uint(s) > uint(len(src)) { + return 1 + } + length = 1 + int(src[s-5])>>2 + offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + } + if offset <= 0 || d < offset || length > len(dst)-d { + return 1 + } + if offset >= length { + copy(dst[d:d+length], dst[d-offset:]) + d += length + continue + } + a := dst[d : d+length] + b := dst[d-offset:] + b = b[:len(a)] + for i := range a { + a[i] = b[i] + } + d += length + } + if d != len(dst) { + return 1 + } + return 0 +} diff --git a/vendor/github.com/klauspost/compress/zstd/README.md b/vendor/github.com/klauspost/compress/zstd/README.md index c11d7fa28e3..a5aeeaed06f 100644 --- a/vendor/github.com/klauspost/compress/zstd/README.md +++ b/vendor/github.com/klauspost/compress/zstd/README.md @@ -75,14 +75,47 @@ The above is fine for big encodes. However, whenever possible try to *reuse* the To reuse the encoder, you can use the `Reset(io.Writer)` function to change to another output. This will allow the encoder to reuse all resources and avoid wasteful allocations. -Currently stream encoding has 'light' concurrency, meaning up to 2 goroutines can be working on part -of a stream. This is independent of the `WithEncoderConcurrency(n)`, but that is likely to change +By default, stream encoding has 'light' concurrency, meaning up to 2 goroutines can be working on part +of a stream. This is independent of the `WithEncoderConcurrency(n)`, but that is likely to change in the future. So if you want to limit concurrency for future updates, specify the concurrency you would like. If you would like stream encoding to be done without spawning async goroutines, use `WithEncoderConcurrency(1)` which will compress input as each block is completed, blocking on writes until each has completed. +#### Parallel Stream Compression + +For maximum throughput on large streams, use `WithConcurrentBlocks(true)` together with +`WithEncoderConcurrency(n)` where n is the number of CPU cores you want to use. +This splits the input into large sections (jobs) that are compressed simultaneously by multiple goroutines, +similar to how the C zstd library does multithreaded compression. + +```Go +enc, err := zstd.NewWriter(out, + zstd.WithEncoderLevel(zstd.SpeedDefault), + zstd.WithEncoderConcurrency(runtime.GOMAXPROCS(0)), + zstd.WithConcurrentBlocks(true), +) +``` + +Each non-first job receives an overlap prefix from the previous job for match context, +so compression ratio is only marginally affected. Output is flushed in order, +producing a valid single-frame zstd stream. + +Benchmark on 1.8GB GOB stream (AMD Ryzen 9 9950X): + +| Level | 1 thread | 4 threads | 16 threads | 1T ratio | 16T ratio | +|---------|:----------:|:------------------:|:-------------------:|:--------:|:---------:| +| fastest | 783 MB/s | 2950 MB/s (3.8×) | 6939 MB/s (8.9×) | 12.24% | 12.26% | +| default | 728 MB/s | 2533 MB/s (3.5×) | 5340 MB/s (7.3×) | 10.67% | 10.68% | +| better | 434 MB/s | 1105 MB/s (2.5×) | 2206 MB/s (5.1×) | 9.14% | 9.21% | +| best | 129 MB/s | 367 MB/s (2.8×) | 884 MB/s (6.8×) | 8.48% | 8.63% | + +Notes: +* Not compatible with dictionary encoding. +* `Flush()` dispatches the current partial job, so latency-sensitive callers can force output. +* `EncodeAll` is unaffected — it uses its own concurrency via the encoder pool. + You can specify your desired compression level using `WithEncoderLevel()` option. Currently only pre-defined compression settings can be specified. diff --git a/vendor/github.com/klauspost/compress/zstd/dict.go b/vendor/github.com/klauspost/compress/zstd/dict.go index 2ffbfdf379e..4f1c4938cd3 100644 --- a/vendor/github.com/klauspost/compress/zstd/dict.go +++ b/vendor/github.com/klauspost/compress/zstd/dict.go @@ -230,7 +230,7 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { } block := blockEnc{lowMem: false} block.init() - enc := encoder(&bestFastEncoder{fastBase: fastBase{maxMatchOff: int32(maxMatchLen), bufferReset: math.MaxInt32 - int32(maxMatchLen*2), lowMem: false}}) + var enc encoder if o.Level != 0 { eOpts := encoderOptions{ level: o.Level, @@ -242,6 +242,7 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { enc = eOpts.encoder() } else { o.Level = SpeedBestCompression + enc = encoder(&bestFastEncoder{fastBase: fastBase{maxMatchOff: int32(maxMatchLen), bufferReset: math.MaxInt32 - int32(maxMatchLen*2), lowMem: false}}) } var ( remain [256]int diff --git a/vendor/github.com/klauspost/compress/zstd/enc_base.go b/vendor/github.com/klauspost/compress/zstd/enc_base.go index c4de134a7a4..c4fea575d6b 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_base.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_base.go @@ -128,6 +128,34 @@ func (e *fastBase) matchlen(s, t int32, src []byte) int32 { return int32(matchLen(src[s:], src[t:])) } +// resetBasePrefix resets the encoder state and loads prefix as initial history. +// This is used for parallel job encoding where non-first jobs need overlap context. +// Rep offsets are set to defaults [1,4,8] (invalidated, matching C behavior). +func (e *fastBase) resetBasePrefix(prefix []byte) { + if e.blk == nil { + e.blk = &blockEnc{lowMem: e.lowMem} + e.blk.init() + } else { + e.blk.reset(nil) + } + e.blk.initNewEncode() + if e.crc == nil { + e.crc = xxhash.New() + } else { + e.crc.Reset() + } + e.blk.dictLitEnc = nil + e.ensureHist(len(prefix) + maxCompressedBlockSize) + // Bump cur so old table entries fall outside the window. + // When cur >= bufferReset, leave it; the first Encode call + // will shift/clear tables, preserving valid prefix entries. + if e.cur < e.bufferReset { + e.cur += e.maxMatchOff + int32(len(e.hist)) + } + e.hist = e.hist[:0] + e.hist = append(e.hist, prefix...) +} + // Reset the encoding table. func (e *fastBase) resetBase(d *dict, singleBlock bool) { if e.blk == nil { diff --git a/vendor/github.com/klauspost/compress/zstd/enc_best.go b/vendor/github.com/klauspost/compress/zstd/enc_best.go index 851799322bd..c71382dde65 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_best.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_best.go @@ -551,3 +551,18 @@ func (e *bestFastEncoder) Reset(d *dict, singleBlock bool) { // Reset table to initial state copy(e.table[:], e.dictTable) } + +func (e *bestFastEncoder) ResetPrefix(prefix []byte) { + e.resetBasePrefix(prefix) + if len(prefix) < 8 { + return + } + end := e.cur + int32(len(prefix)) - 8 + for i := e.cur; i < end; i++ { + cv := load6432(prefix, i-e.cur) + h := hashLen(cv, bestLongTableBits, bestLongLen) + e.longTable[h] = prevEntry{offset: i, prev: e.longTable[h].offset} + h0 := hashLen(cv, bestShortTableBits, bestShortLen) + e.table[h0] = prevEntry{offset: i, prev: e.table[h0].offset} + } +} diff --git a/vendor/github.com/klauspost/compress/zstd/enc_better.go b/vendor/github.com/klauspost/compress/zstd/enc_better.go index 3305f09248c..523d57f3ad6 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_better.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_better.go @@ -1096,6 +1096,20 @@ func (e *betterFastEncoder) Reset(d *dict, singleBlock bool) { } } +func (e *betterFastEncoder) ResetPrefix(prefix []byte) { + e.resetBasePrefix(prefix) + if len(prefix) < 8 { + return + } + end := e.cur + int32(len(prefix)) - 8 + for i := e.cur; i < end; i += 2 { + cv := load6432(prefix, i-e.cur) + h := hashLen(cv, betterLongTableBits, betterLongLen) + e.longTable[h] = prevEntry{offset: i, prev: e.longTable[h].offset} + e.table[hashLen(cv>>8, betterShortTableBits, betterShortLen)] = tableEntry{val: uint32(cv >> 8), offset: i + 1} + } +} + // ResetDict will reset and set a dictionary if not nil func (e *betterFastEncoderDict) Reset(d *dict, singleBlock bool) { e.resetBase(d, singleBlock) @@ -1229,6 +1243,10 @@ func (e *betterFastEncoderDict) Reset(d *dict, singleBlock bool) { e.allDirty = false } +func (e *betterFastEncoderDict) ResetPrefix([]byte) { + panic("ResetPrefix not supported for dict encoders") +} + func (e *betterFastEncoderDict) markLongShardDirty(entryNum uint32) { e.longTableShardDirty[entryNum/betterLongTableShardSize] = true } diff --git a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go index 2fb6da112bc..712ba7ab582 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go @@ -1037,6 +1037,18 @@ func (e *doubleFastEncoder) Reset(d *dict, singleBlock bool) { } } +func (e *doubleFastEncoder) ResetPrefix(prefix []byte) { + e.fastEncoder.ResetPrefix(prefix) + if len(prefix) < 8 { + return + } + end := e.cur + int32(len(prefix)) - 8 + for i := e.cur + 1; i < end; i += 2 { + cv := load6432(prefix, i-e.cur) + e.longTable[hashLen(cv, dFastLongTableBits, dFastLongLen)] = tableEntry{val: uint32(cv), offset: i} + } +} + // ResetDict will reset and set a dictionary if not nil func (e *doubleFastEncoderDict) Reset(d *dict, singleBlock bool) { allDirty := e.allDirty @@ -1102,6 +1114,10 @@ func (e *doubleFastEncoderDict) Reset(d *dict, singleBlock bool) { } } +func (e *doubleFastEncoderDict) ResetPrefix([]byte) { + panic("ResetPrefix not supported for dict encoders") +} + func (e *doubleFastEncoderDict) markLongShardDirty(entryNum uint32) { e.longTableShardDirty[entryNum/dLongTableShardSize] = true } diff --git a/vendor/github.com/klauspost/compress/zstd/enc_fast.go b/vendor/github.com/klauspost/compress/zstd/enc_fast.go index 5e104f1a482..06045e24630 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_fast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_fast.go @@ -797,6 +797,19 @@ func (e *fastEncoder) Reset(d *dict, singleBlock bool) { } } +func (e *fastEncoder) ResetPrefix(prefix []byte) { + e.resetBasePrefix(prefix) + if len(prefix) < 8 { + return + } + end := e.cur + int32(len(prefix)) - 8 + // Index every 4th + for i := e.cur + 1; i < end; i += 4 { + cv := load6432(prefix, i-e.cur) + e.table[hashLen(cv, tableBits, tableFastHashLen)] = tableEntry{val: uint32(cv), offset: i} + } +} + // ResetDict will reset and set a dictionary if not nil func (e *fastEncoderDict) Reset(d *dict, singleBlock bool) { e.resetBase(d, singleBlock) @@ -866,6 +879,10 @@ func (e *fastEncoderDict) Reset(d *dict, singleBlock bool) { e.allDirty = false } +func (e *fastEncoderDict) ResetPrefix([]byte) { + panic("ResetPrefix not supported for dict encoders") +} + func (e *fastEncoderDict) markAllShardsDirty() { e.allDirty = true } diff --git a/vendor/github.com/klauspost/compress/zstd/enc_jobs.go b/vendor/github.com/klauspost/compress/zstd/enc_jobs.go new file mode 100644 index 00000000000..95ce67ac05a --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/enc_jobs.go @@ -0,0 +1,352 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "fmt" + rdebug "runtime/debug" + "sync" +) + +type encJob struct { + prefix []byte // overlap from previous job (nil for first) + input []byte // job's own input data (swapped from filling) + last bool // last block of last job gets last=true + output []byte // compressed blocks (filled by worker) + err error // encoding error + done chan struct{} // closed when complete +} + +type jobState struct { + jobSize int + overlapSize int + filling []byte // accumulates input up to jobSize + nextPrefix []byte // overlap prefix prepared for the next dispatched job + + jobSeq int // next job sequence number + + jobCh chan *encJob // dispatch to workers + resultCh chan *encJob // ordered results to flusher + + workerWg sync.WaitGroup + flusherWg sync.WaitGroup + + mu sync.Mutex + flushedSeq int // last flushed sequence number + cond *sync.Cond + + flusherErr error + started bool + + inputPool sync.Pool // *[]byte buffers of jobSize cap + outputPool sync.Pool // *[]byte buffers for compressed output + overlapPool sync.Pool // *[]byte buffers for overlap prefixes +} + +func (e *Encoder) startJobWorkers() { + js := &e.state.jobs + n := e.o.concurrent + js.jobCh = make(chan *encJob, n) + js.resultCh = make(chan *encJob, n) + js.flushedSeq = 0 + js.cond = sync.NewCond(&js.mu) + + // Workers borrow encoders from the shared e.encoders pool per-job. + // Ensure the pool is initialized before any worker tries to borrow. + e.init.Do(e.initialize) + + for range n { + js.workerWg.Add(1) + go e.jobWorker() + } + js.flusherWg.Add(1) + go e.jobFlusher() + js.started = true +} + +func (e *Encoder) jobWorker() { + js := &e.state.jobs + defer js.workerWg.Done() + for job := range js.jobCh { + enc := <-e.encoders + e.compressJob(enc, job) + e.encoders <- enc + close(job.done) + } +} + +func (e *Encoder) compressJob(enc encoder, job *encJob) { + defer func() { + if r := recover(); r != nil { + job.err = fmt.Errorf("panic in parallel job: %v", r) + rdebug.PrintStack() + } + }() + + if len(job.prefix) > 0 { + enc.ResetPrefix(job.prefix) + } else { + enc.Reset(nil, false) + } + + data := job.input + if len(data) == 0 && job.last { + blk := enc.Block() + blk.reset(nil) + blk.last = true + blk.encodeRaw(nil) + job.output = append(job.output, blk.output...) + return + } + + blk := enc.Block() + for len(data) > 0 { + todo := data + if len(todo) > e.o.blockSize { + todo = todo[:e.o.blockSize] + } + data = data[len(todo):] + + blk.pushOffsets() + enc.Encode(blk, todo) + blk.last = len(data) == 0 && job.last + + err := blk.encode(todo, e.o.noEntropy, !e.o.allLitEntropy) + if err != nil { + job.err = err + return + } + job.output = append(job.output, blk.output...) + blk.reset(nil) + } +} + +func (js *jobState) getInputBuf(size int) []byte { + if v := js.inputPool.Get(); v != nil { + bp := v.(*[]byte) + b := *bp + if cap(b) >= size { + return b[:0] + } + } + return make([]byte, 0, size) +} + +func (js *jobState) putInputBuf(b []byte) { + if cap(b) > 0 { + b = b[:0] + js.inputPool.Put(&b) + } +} + +func (js *jobState) getOutputBuf(size int) []byte { + if v := js.outputPool.Get(); v != nil { + bp := v.(*[]byte) + b := *bp + if cap(b) >= size { + return b[:0] + } + } + return make([]byte, 0, size) +} + +func (js *jobState) putOutputBuf(b []byte) { + if cap(b) > 0 { + b = b[:0] + js.outputPool.Put(&b) + } +} + +func (js *jobState) getOverlapBuf(size int) []byte { + if v := js.overlapPool.Get(); v != nil { + bp := v.(*[]byte) + b := *bp + if cap(b) >= size { + return b[:size] + } + } + return make([]byte, size) +} + +func (js *jobState) putOverlapBuf(b []byte) { + if cap(b) > 0 { + b = b[:0] + js.overlapPool.Put(&b) + } +} + +func (e *Encoder) jobFlusher() { + js := &e.state.jobs + defer js.flusherWg.Done() + for job := range js.resultCh { + <-job.done + // Worker has fully exited compressJob, so the prefix is no longer + // in use. Return it to the pool regardless of outcome. + if job.prefix != nil { + js.putOverlapBuf(job.prefix) + job.prefix = nil + } + if job.err != nil { + js.mu.Lock() + js.flusherErr = job.err + js.cond.Broadcast() + js.mu.Unlock() + for range js.resultCh { + } + return + } + if len(job.output) > 0 { + _, err := e.state.w.Write(job.output) + if err != nil { + js.mu.Lock() + js.flusherErr = err + js.cond.Broadcast() + js.mu.Unlock() + for range js.resultCh { + } + return + } + e.state.nWritten += int64(len(job.output)) + } + // Return buffers to pools. + js.putInputBuf(job.input) + js.putOutputBuf(job.output) + job.input = nil + job.output = nil + + js.mu.Lock() + js.flushedSeq++ + js.cond.Broadcast() + js.mu.Unlock() + } +} + +func (e *Encoder) shutdownJobWorkers() { + js := &e.state.jobs + if !js.started { + return + } + close(js.jobCh) + js.workerWg.Wait() + close(js.resultCh) + js.flusherWg.Wait() + js.started = false +} + +// waitAllJobs blocks until all dispatched jobs have been flushed. +func (e *Encoder) waitAllJobs() { + js := &e.state.jobs + if !js.started { + return + } + js.mu.Lock() + for js.flushedSeq < js.jobSeq && js.flusherErr == nil { + js.cond.Wait() + } + js.mu.Unlock() +} + +func (e *Encoder) dispatchJob(final bool) error { + s := &e.state + js := &s.jobs + + js.mu.Lock() + fErr := js.flusherErr + js.mu.Unlock() + if fErr != nil { + return fErr + } + + if !s.headerWritten { + // Single-block optimization: fall through to encodeAll path. + if final && len(js.filling) > 0 && len(js.filling) <= e.o.blockSize { + s.current = e.encodeAll(s.encoder, js.filling, s.current[:0]) + var n2 int + n2, s.err = s.w.Write(s.current) + if s.err != nil { + return s.err + } + s.nWritten += int64(n2) + s.nInput += int64(len(js.filling)) + s.current = s.current[:0] + js.filling = js.filling[:0] + s.headerWritten = true + s.fullFrameWritten = true + s.eofWritten = true + return nil + } + if final && len(js.filling) == 0 && !e.o.fullZero { + s.headerWritten = true + s.fullFrameWritten = true + s.eofWritten = true + return nil + } + + var tmp [maxHeaderSize]byte + fh := frameHeader{ + ContentSize: uint64(s.frameContentSize), + WindowSize: uint32(s.encoder.WindowSize(s.frameContentSize)), + SingleSegment: false, + Checksum: e.o.crc, + DictID: 0, + } + dst := fh.appendTo(tmp[:0]) + var n2 int + n2, s.err = s.w.Write(dst) + if s.err != nil { + return s.err + } + s.nWritten += int64(n2) + s.headerWritten = true + } + + if len(js.filling) == 0 && !final { + return nil + } + + if !js.started { + e.startJobWorkers() + } + + // Estimate output size for pooled buffer. + outputEst := max(len(js.filling)/2, 512) + + job := &encJob{ + last: final, + done: make(chan struct{}), + output: js.getOutputBuf(outputEst), + } + + // Each job owns its prefix slice; the flusher returns it to the pool + // after <-job.done, so workers and dispatch never share a buffer. + if js.nextPrefix != nil { + job.prefix = js.nextPrefix + js.nextPrefix = nil + } + + // Build the next job's prefix from the tail of this job's input. + if !final && len(js.filling) > 0 { + overlapLen := min(js.overlapSize, len(js.filling)) + np := js.getOverlapBuf(overlapLen) + copy(np, js.filling[len(js.filling)-overlapLen:]) + js.nextPrefix = np + } + + // Swap filling buffer into job — zero-copy for the input data. + job.input = js.filling + js.filling = js.getInputBuf(js.jobSize) + + s.nInput += int64(len(job.input)) + js.jobSeq++ + + if final { + s.eofWritten = true + } + + js.resultCh <- job + js.jobCh <- job + + return nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/encoder.go b/vendor/github.com/klauspost/compress/zstd/encoder.go index 0f2a00a0033..6ee96d8730c 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder.go @@ -38,6 +38,7 @@ type encoder interface { WindowSize(size int64) int32 UseBlock(*blockEnc) Reset(d *dict, singleBlock bool) + ResetPrefix(prefix []byte) } type encoderState struct { @@ -60,6 +61,9 @@ type encoderState struct { wg sync.WaitGroup // This waitgroup indicates we have a block encoding/writing. wWg sync.WaitGroup + + // Parallel job state (used when concurrentBlocks is enabled). + jobs jobState } // NewWriter will create a new Zstandard encoder. @@ -74,6 +78,9 @@ func NewWriter(w io.Writer, opts ...EOption) (*Encoder, error) { return nil, err } } + if e.o.concurrentBlocks && (e.o.dict != nil || e.o.concurrent <= 1) { + e.o.concurrentBlocks = false + } if w != nil { e.Reset(w) } @@ -95,12 +102,31 @@ func (e *Encoder) initialize() { // as a new, independent stream. func (e *Encoder) Reset(w io.Writer) { s := &e.state + + if e.o.concurrentBlocks { + e.shutdownJobWorkers() + js := &s.jobs + js.jobSize = e.o.jobSize() + js.overlapSize = e.o.overlapSize() + // js.filling is allocated lazily on first Write/ReadFrom so callers + // that only use EncodeAll don't pay the (up to ~32 MB) jobSize cost. + js.filling = js.filling[:0] + if js.nextPrefix != nil { + js.putOverlapBuf(js.nextPrefix) + js.nextPrefix = nil + } + js.jobSeq = 0 + js.flushedSeq = 0 + js.flusherErr = nil + js.started = false + } + s.wg.Wait() s.wWg.Wait() if cap(s.filling) == 0 { s.filling = make([]byte, 0, e.o.blockSize) } - if e.o.concurrent > 1 { + if e.o.concurrent > 1 && !e.o.concurrentBlocks { if cap(s.current) == 0 { s.current = make([]byte, 0, e.o.blockSize) } @@ -145,6 +171,9 @@ func (e *Encoder) ResetWithOptions(w io.Writer, opts ...EOption) error { } } hasDict := e.o.dict != nil + if e.o.concurrentBlocks && hasDict { + e.o.concurrentBlocks = false + } if hadDict != hasDict { // Dict presence changed — encoder type must be recreated. e.state.encoder = nil @@ -176,6 +205,49 @@ func (e *Encoder) Write(p []byte) (n int, err error) { if s.eofWritten { return 0, ErrEncoderClosed } + if e.o.concurrentBlocks { + return e.writeJobs(p) + } + return e.writeBlocks(p) +} + +func (e *Encoder) writeJobs(p []byte) (n int, err error) { + s := &e.state + js := &s.jobs + jobSize := js.jobSize + if cap(js.filling) == 0 && len(p) > 0 { + js.filling = make([]byte, 0, jobSize) + } + for len(p) > 0 { + if len(p)+len(js.filling) < jobSize { + if e.o.crc { + _, _ = s.encoder.CRC().Write(p) + } + js.filling = append(js.filling, p...) + return n + len(p), nil + } + add := p + if len(p)+len(js.filling) > jobSize { + add = add[:jobSize-len(js.filling)] + } + if e.o.crc { + _, _ = s.encoder.CRC().Write(add) + } + js.filling = append(js.filling, add...) + p = p[len(add):] + n += len(add) + if len(js.filling) < jobSize { + return n, nil + } + if err := e.dispatchJob(false); err != nil { + return n, err + } + } + return n, nil +} + +func (e *Encoder) writeBlocks(p []byte) (n int, err error) { + s := &e.state for len(p) > 0 { if len(p)+len(s.filling) < e.o.blockSize { if e.o.crc { @@ -374,6 +446,10 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) { println("Using ReadFrom") } + if e.o.concurrentBlocks { + return e.readFromJobs(r) + } + // Flush any current writes. if len(e.state.filling) > 0 { if err := e.nextBlock(false); err != nil { @@ -387,7 +463,6 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) { if e.o.crc { _, _ = e.state.encoder.CRC().Write(src[:n2]) } - // src is now the unfilled part... src = src[n2:] n += int64(n2) switch err { @@ -420,15 +495,63 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) { } } +func (e *Encoder) readFromJobs(r io.Reader) (n int64, err error) { + js := &e.state.jobs + jobSize := js.jobSize + + // Flush any current filling. + if len(js.filling) > 0 { + if err := e.dispatchJob(false); err != nil { + return 0, err + } + } + + if cap(js.filling) < jobSize { + js.filling = make([]byte, 0, jobSize) + } + js.filling = js.filling[:jobSize] + src := js.filling + for { + n2, err := r.Read(src) + if e.o.crc { + _, _ = e.state.encoder.CRC().Write(src[:n2]) + } + src = src[n2:] + n += int64(n2) + switch err { + case io.EOF: + js.filling = js.filling[:len(js.filling)-len(src)] + return n, nil + case nil: + default: + e.state.err = err + return n, err + } + if len(src) > 0 { + continue + } + if err = e.dispatchJob(false); err != nil { + return n, err + } + if cap(js.filling) < jobSize { + js.filling = make([]byte, 0, jobSize) + } + js.filling = js.filling[:jobSize] + src = js.filling + } +} + // Flush will send the currently written data to output // and block until everything has been written. // This should only be used on rare occasions where pushing the currently queued data is critical. func (e *Encoder) Flush() error { s := &e.state + if e.o.concurrentBlocks { + return e.flushJobs() + } if len(s.filling) > 0 { err := e.nextBlock(false) if err != nil { - // Ignore Flush after Close. if errors.Is(s.err, ErrEncoderClosed) { return nil } @@ -438,7 +561,6 @@ func (e *Encoder) Flush() error { s.wg.Wait() s.wWg.Wait() if s.err != nil { - // Ignore Flush after Close. if errors.Is(s.err, ErrEncoderClosed) { return nil } @@ -447,6 +569,20 @@ func (e *Encoder) Flush() error { return s.writeErr } +func (e *Encoder) flushJobs() error { + js := &e.state.jobs + if len(js.filling) > 0 { + if err := e.dispatchJob(false); err != nil { + return err + } + } + e.waitAllJobs() + js.mu.Lock() + fErr := js.flusherErr + js.mu.Unlock() + return fErr +} + // Close will flush the final output and close the stream. // The function will block until everything has been written. // The Encoder can still be re-used after calling this. @@ -455,12 +591,16 @@ func (e *Encoder) Close() error { if s.encoder == nil { return nil } + if e.o.concurrentBlocks { + return e.closeJobs() + } if s.w == nil { if len(s.filling) == 0 && !s.headerWritten && !s.eofWritten && s.nInput == 0 { return nil } return errors.New("zstd: encoder has no writer") } + err := e.nextBlock(true) if err != nil { if errors.Is(s.err, ErrEncoderClosed) { @@ -511,6 +651,68 @@ func (e *Encoder) Close() error { return s.err } +func (e *Encoder) closeJobs() error { + s := &e.state + js := &s.jobs + + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } + + if s.w == nil { + if len(js.filling) == 0 && !s.headerWritten && !s.eofWritten && s.nInput == 0 { + return nil + } + return errors.New("zstd: encoder has no writer") + } + + if err := e.dispatchJob(true); err != nil { + e.shutdownJobWorkers() + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } + return err + } + + if s.frameContentSize > 0 && s.nInput != s.frameContentSize { + e.shutdownJobWorkers() + return fmt.Errorf("frame content size %d given, but %d bytes was written", s.frameContentSize, s.nInput) + } + + if s.fullFrameWritten { + e.shutdownJobWorkers() + s.err = ErrEncoderClosed + return nil + } + + e.shutdownJobWorkers() + if js.flusherErr != nil { + return js.flusherErr + } + + // Write CRC + if e.o.crc { + var tmp [4]byte + _, s.err = s.w.Write(s.encoder.AppendCRC(tmp[:0])) + s.nWritten += 4 + } + + // Add padding + if s.err == nil && e.o.pad > 0 { + add := calcSkippableFrame(s.nWritten, int64(e.o.pad)) + frame, err := skippableFrame(js.filling[:0], add, rand.Reader) + if err != nil { + return err + } + _, s.err = s.w.Write(frame) + } + if s.err == nil { + s.err = ErrEncoderClosed + return nil + } + return s.err +} + // EncodeAll will encode all input in src and append it to dst. // This function can be called concurrently, but each call will only run on a single goroutine. // If empty input is given, nothing is returned, unless WithZeroFrames is specified. diff --git a/vendor/github.com/klauspost/compress/zstd/encoder_options.go b/vendor/github.com/klauspost/compress/zstd/encoder_options.go index e217be0a17a..a8081496739 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder_options.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder_options.go @@ -14,22 +14,23 @@ type EOption func(*encoderOptions) error // options retains accumulated state of multiple options. type encoderOptions struct { - resetOpt bool - concurrent int - level EncoderLevel - single *bool - pad int - blockSize int - windowSize int - crc bool - fullZero bool - noEntropy bool - allLitEntropy bool - customWindow bool - customALEntropy bool - customBlockSize bool - lowMem bool - dict *dict + resetOpt bool + concurrent int + level EncoderLevel + single *bool + pad int + blockSize int + windowSize int + crc bool + fullZero bool + noEntropy bool + allLitEntropy bool + customWindow bool + customALEntropy bool + customBlockSize bool + lowMem bool + dict *dict + concurrentBlocks bool } func (o *encoderOptions) setDefault() { @@ -333,6 +334,42 @@ func WithLowerEncoderMem(b bool) EOption { } } +// WithConcurrentBlocks enables job-based parallel compression for streams. +// When enabled and concurrent > 1, input is split into large sections (jobs) +// that are compressed simultaneously by multiple goroutines. +// Each non-first job receives an overlap prefix from the previous job for match context. +// Output is flushed in order, producing a valid single-frame zstd stream. +// +// Currently disabled when used with dictionary encoding. +// Cannot be changed with ResetWithOptions. +func WithConcurrentBlocks(b bool) EOption { + return func(o *encoderOptions) error { + if o.resetOpt && b != o.concurrentBlocks { + return errors.New("WithConcurrentBlocks cannot be changed on Reset") + } + o.concurrentBlocks = b + return nil + } +} + +// jobSize returns the input section size per parallel job. +func (o *encoderOptions) jobSize() int { + s := max(o.windowSize*4, 512<<10) + return s +} + +// overlapSize returns the overlap prefix size for parallel jobs. +func (o *encoderOptions) overlapSize() int { + switch o.level { + case SpeedBestCompression: + return o.windowSize / 2 + case SpeedBetterCompression: + return o.windowSize / 4 + default: + return o.windowSize / 8 + } +} + // WithEncoderDict allows to register a dictionary that will be used for the encode. // // The slice dict must be in the [dictionary format] produced by diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s b/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s index bcde3986953..deeadc49eb0 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s @@ -1,4 +1,4 @@ -// Code generated by command: go run gen_fse.go -out ../fse_decoder_amd64.s -pkg=zstd. DO NOT EDIT. +// Code generated by command: go run gen_fse.go -out ../fse_decoder.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. //go:build !appengine && !noasm && gc && !noasm diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s b/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s new file mode 100644 index 00000000000..77ee3913f05 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s @@ -0,0 +1,153 @@ +// Code generated by command: go run gen_fse.go -out ../fse_decoder.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. +// EXPERIMENTAL arm64 output lowered from an amd64 avo program. + +//go:build arm64 && !appengine && !noasm && gc && !noasm + +// func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int +TEXT ·buildDtable_asm(SB), $0-24 + MOVD ctx+8(FP), R1 + MOVD s+0(FP), R6 + + // Load values + MOVBU 4098(R6), R2 + MOVD $0, R0 + MOVD $1, R16 + LSL R2, R16, R16 + ORR R16, R0, R0 + MOVD (R1), R3 + MOVD 16(R1), R5 + SUB $1, R0, R7 + MOVD 8(R1), R1 + MOVHU 4096(R6), R6 + + // End load values + // Init, lay down lowprob symbols + MOVD $0, R8 + JMP init_main_loop_condition + +init_main_loop: + ADD R8<<1, R1, R15 + MOVH (R15), R9 + AND $0xffff, R9, R15 + MOVD $-1, R16 + AND $0xffff, R16, R16 + CMP R16, R15 + BNE do_not_update_high_threshold + ADD R7<<3, R5, R15 + MOVB R8, 1(R15) + SUB $1, R7, R7 + MOVD $0x0000000000000001, R9 + +do_not_update_high_threshold: + ADD R8<<1, R3, R15 + MOVH R9, (R15) + ADD $1, R8, R8 + +init_main_loop_condition: + CMP R6, R8 + BLT init_main_loop + + // Spread symbols + // Calculate table step + MOVD R0, R8 + LSR $0x01, R8, R8 + MOVD R0, R9 + LSR $0x03, R9, R9 + ADD R9, R8, R8 + ADD $3, R8, R8 + + // Fill add bits values + SUB $1, R0, R9 + MOVD $0, R10 + MOVD $0, R11 + JMP spread_main_loop_condition + +spread_main_loop: + MOVD $0, R12 + ADD R11<<1, R1, R15 + MOVH (R15), R13 + JMP spread_inner_loop_condition + +spread_inner_loop: + ADD R10<<3, R5, R15 + MOVB R11, 1(R15) + +adjust_position: + ADD R8, R10, R10 + AND R9, R10, R10 + CMP R7, R10 + BGT adjust_position + ADD $1, R12, R12 + +spread_inner_loop_condition: + CMP R13, R12 + BLT spread_inner_loop + ADD $1, R11, R11 + +spread_main_loop_condition: + CMP R6, R11 + BLT spread_main_loop + TST R10, R10 + BEQ spread_check_ok + MOVD ctx+8(FP), R0 + MOVD R10, 24(R0) + MOVD $+1, R16 + MOVD R16, ret+16(FP) + RET + +spread_check_ok: + // Build Decoding table + MOVD $0, R6 + +build_table_main_table: + ADD R6<<3, R5, R15 + MOVBU 1(R15), R1 + ADD R1<<1, R3, R15 + MOVHU (R15), R7 + ADD $1, R7, R8 + ADD R1<<1, R3, R15 + MOVH R8, (R15) + MOVD R7, R8 + CLZ R8, R16 + MOVD $63, R8 + SUB R16, R8, R8 + MOVD R2, R1 + SUB R8, R1, R1 + LSL R1, R7, R7 + SUB R0, R7, R7 + ADD R6<<3, R5, R15 + MOVB R1, (R15) + ADD R6<<3, R5, R15 + MOVH R7, 2(R15) + CMP R0, R7 + BLE build_table_check1_ok + MOVD ctx+8(FP), R1 + MOVD R7, 24(R1) + MOVD R0, 32(R1) + MOVD $+2, R16 + MOVD R16, ret+16(FP) + RET + +build_table_check1_ok: + AND $0xff, R1, R15 + AND $0xff, R1, R16 + TST R16, R15 + BNE build_table_check2_ok + AND $0xffff, R7, R15 + AND $0xffff, R6, R16 + CMP R16, R15 + BNE build_table_check2_ok + MOVD ctx+8(FP), R0 + MOVD R7, 24(R0) + MOVD R6, 32(R0) + MOVD $+3, R16 + MOVD R16, ret+16(FP) + RET + +build_table_check2_ok: + ADD $1, R6, R6 + CMP R0, R6 + BLT build_table_main_table + MOVD $+0, R16 + MOVD R16, ret+16(FP) + RET diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go b/vendor/github.com/klauspost/compress/zstd/fse_decoder_asm.go similarity index 81% rename from vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go rename to vendor/github.com/klauspost/compress/zstd/fse_decoder_asm.go index b8c8607b5df..4ffc7e3c9fd 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_asm.go @@ -1,4 +1,4 @@ -//go:build amd64 && !appengine && !noasm && gc +//go:build (amd64 || arm64) && !appengine && !noasm && gc package zstd @@ -6,6 +6,10 @@ import ( "fmt" ) +// buildDtable_asm is generated by _generate/gen_fse.go and lowered to each +// architecture (amd64 by goasm, arm64 by the avo arm64 lowering printer). The +// Go side is identical across architectures, so it lives here. + type buildDtableAsmContext struct { // inputs stateTable *uint16 @@ -18,7 +22,7 @@ type buildDtableAsmContext struct { errParam2 uint64 } -// buildDtable_asm is an x86 assembly implementation of fseDecoder.buildDtable. +// buildDtable_asm is an assembly implementation of fseDecoder.buildDtable. // Function returns non-zero exit code on error. // //go:noescape diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go b/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go index 2138f8091a9..38fd2ccb2a9 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go @@ -1,4 +1,4 @@ -//go:build !amd64 || appengine || !gc || noasm +//go:build (!amd64 && !arm64) || appengine || !gc || noasm package zstd diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go index 18c3703ddc9..1281da885c5 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go @@ -3,321 +3,83 @@ package zstd import ( - "fmt" - "io" - "github.com/klauspost/compress/internal/cpuinfo" ) -type decodeSyncAsmContext struct { - llTable []decSymbol - mlTable []decSymbol - ofTable []decSymbol - llState uint64 - mlState uint64 - ofState uint64 - iteration int - litRemain int - out []byte - outPosition int - literals []byte - litPosition int - history []byte - windowSize int - ll int // set on error (not for all errors, please refer to _generate/gen.go) - ml int // set on error (not for all errors, please refer to _generate/gen.go) - mo int // set on error (not for all errors, please refer to _generate/gen.go) -} +// The shared decode/decodeSync/executeSimple wrappers and context structs live +// in seqdec_asm.go; this file only declares the amd64 asm routines and the +// dispatch helpers that pick the BMI2 / non-BMI2 (and 56-bit / safe) variant. -// sequenceDecs_decodeSync_amd64 implements the main loop of sequenceDecs.decodeSync in x86 asm. +// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm. // // Please refer to seqdec_generic.go for the reference implementation. // //go:noescape -func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int -// sequenceDecs_decodeSync_bmi2 implements the main loop of sequenceDecs.decodeSync in x86 asm with BMI2 extensions. +// sequenceDecs_decode_56_amd64 implements the main loop of sequenceDecs in x86 asm. // //go:noescape -func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int -// sequenceDecs_decodeSync_safe_amd64 does the same as above, but does not write more than output buffer. +// sequenceDecs_decode_bmi2 implements the main loop of sequenceDecs in x86 asm with BMI2 extensions. // //go:noescape -func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int -// sequenceDecs_decodeSync_safe_bmi2 does the same as above, but does not write more than output buffer. +// sequenceDecs_decode_56_bmi2 implements the main loop of sequenceDecs in x86 asm with BMI2 extensions. // //go:noescape -func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int - -// decode sequences from the stream with the provided history but without a dictionary. -func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { - if len(s.dict) > 0 { - return false, nil - } - if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSize { - return false, nil - } - - // FIXME: Using unsafe memory copies leads to rare, random crashes - // with fuzz testing. It is therefore disabled for now. - const useSafe = true - /* - useSafe := false - if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSizeAlloc { - useSafe = true - } - if s.maxSyncLen > 0 && cap(s.out)-len(s.out)-compressedBlockOverAlloc < int(s.maxSyncLen) { - useSafe = true - } - if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc { - useSafe = true - } - */ - - br := s.br - - maxBlockSize := min(s.windowSize, maxCompressedBlockSize) - - ctx := decodeSyncAsmContext{ - llTable: s.litLengths.fse.dt[:maxTablesize], - mlTable: s.matchLengths.fse.dt[:maxTablesize], - ofTable: s.offsets.fse.dt[:maxTablesize], - llState: uint64(s.litLengths.state.state), - mlState: uint64(s.matchLengths.state.state), - ofState: uint64(s.offsets.state.state), - iteration: s.nSeqs - 1, - litRemain: len(s.literals), - out: s.out, - outPosition: len(s.out), - literals: s.literals, - windowSize: s.windowSize, - history: hist, - } - - s.seqSize = 0 - startSize := len(s.out) +func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int - var errCode int +// decodeAsm runs the sequenceDecs decode loop, choosing the BMI2 / 56-bit variant. +func decodeAsm(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext, lte56bits bool) int { if cpuinfo.HasBMI2() { - if useSafe { - errCode = sequenceDecs_decodeSync_safe_bmi2(s, br, &ctx) - } else { - errCode = sequenceDecs_decodeSync_bmi2(s, br, &ctx) - } - } else { - if useSafe { - errCode = sequenceDecs_decodeSync_safe_amd64(s, br, &ctx) - } else { - errCode = sequenceDecs_decodeSync_amd64(s, br, &ctx) - } - } - switch errCode { - case noError: - break - - case errorMatchLenOfsMismatch: - return true, fmt.Errorf("zero matchoff and matchlen (%d) > 0", ctx.ml) - - case errorMatchLenTooBig: - return true, fmt.Errorf("match len (%d) bigger than max allowed length", ctx.ml) - - case errorMatchOffTooBig: - return true, fmt.Errorf("match offset (%d) bigger than current history (%d)", - ctx.mo, ctx.outPosition+len(hist)-startSize) - - case errorNotEnoughLiterals: - return true, fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", - ctx.ll, ctx.litRemain+ctx.ll) - - case errorOverread: - return true, io.ErrUnexpectedEOF - - case errorNotEnoughSpace: - size := ctx.outPosition + ctx.ll + ctx.ml - if debugDecoder { - println("msl:", s.maxSyncLen, "cap", cap(s.out), "bef:", startSize, "sz:", size-startSize, "mbs:", maxBlockSize, "outsz:", cap(s.out)-startSize) + if lte56bits { + return sequenceDecs_decode_56_bmi2(s, br, ctx) } - return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) - - default: - return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode) - } - - s.seqSize += ctx.litRemain - if s.seqSize > maxBlockSize { - return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + return sequenceDecs_decode_bmi2(s, br, ctx) } - err := br.close() - if err != nil { - printf("Closing sequences: %v, %+v\n", err, *br) - return true, err + if lte56bits { + return sequenceDecs_decode_56_amd64(s, br, ctx) } - - s.literals = s.literals[ctx.litPosition:] - t := ctx.outPosition - s.out = s.out[:t] - - // Add final literals - s.out = append(s.out, s.literals...) - if debugDecoder { - t += len(s.literals) - if t != len(s.out) { - panic(fmt.Errorf("length mismatch, want %d, got %d", len(s.out), t)) - } - } - - return true, nil + return sequenceDecs_decode_amd64(s, br, ctx) } -// -------------------------------------------------------------------------------- - -type decodeAsmContext struct { - llTable []decSymbol - mlTable []decSymbol - ofTable []decSymbol - llState uint64 - mlState uint64 - ofState uint64 - iteration int - seqs []seqVals - litRemain int -} - -const noError = 0 - -// error reported when mo == 0 && ml > 0 -const errorMatchLenOfsMismatch = 1 - -// error reported when ml > maxMatchLen -const errorMatchLenTooBig = 2 - -// error reported when mo > available history or mo > s.windowSize -const errorMatchOffTooBig = 3 - -// error reported when the sum of literal lengths exeeceds the literal buffer size -const errorNotEnoughLiterals = 4 - -// error reported when capacity of `out` is too small -const errorNotEnoughSpace = 5 - -// error reported when bits are overread. -const errorOverread = 6 - -// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm. +// sequenceDecs_decodeSync_amd64 implements the main loop of sequenceDecs.decodeSync in x86 asm. // // Please refer to seqdec_generic.go for the reference implementation. // //go:noescape -func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int -// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm. -// -// Please refer to seqdec_generic.go for the reference implementation. +// sequenceDecs_decodeSync_bmi2 implements the main loop of sequenceDecs.decodeSync in x86 asm with BMI2 extensions. // //go:noescape -func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int -// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions. +// sequenceDecs_decodeSync_safe_amd64 does the same as above, but does not write more than output buffer. // //go:noescape -func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int -// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions. +// sequenceDecs_decodeSync_safe_bmi2 does the same as above, but does not write more than output buffer. // //go:noescape -func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int - -// decode sequences from the stream without the provided history. -func (s *sequenceDecs) decode(seqs []seqVals) error { - br := s.br - - maxBlockSize := min(s.windowSize, maxCompressedBlockSize) - - ctx := decodeAsmContext{ - llTable: s.litLengths.fse.dt[:maxTablesize], - mlTable: s.matchLengths.fse.dt[:maxTablesize], - ofTable: s.offsets.fse.dt[:maxTablesize], - llState: uint64(s.litLengths.state.state), - mlState: uint64(s.matchLengths.state.state), - ofState: uint64(s.offsets.state.state), - seqs: seqs, - iteration: len(seqs) - 1, - litRemain: len(s.literals), - } - - if debugDecoder { - println("decode: decoding", len(seqs), "sequences", br.remain(), "bits remain on stream") - } +func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int - s.seqSize = 0 - lte56bits := s.maxBits+s.offsets.fse.actualTableLog+s.matchLengths.fse.actualTableLog+s.litLengths.fse.actualTableLog <= 56 - var errCode int +// decodeSyncAsm runs the decodeSync loop, choosing the BMI2 / safe variant. +func decodeSyncAsm(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext, safe bool) int { if cpuinfo.HasBMI2() { - if lte56bits { - errCode = sequenceDecs_decode_56_bmi2(s, br, &ctx) - } else { - errCode = sequenceDecs_decode_bmi2(s, br, &ctx) - } - } else { - if lte56bits { - errCode = sequenceDecs_decode_56_amd64(s, br, &ctx) - } else { - errCode = sequenceDecs_decode_amd64(s, br, &ctx) + if safe { + return sequenceDecs_decodeSync_safe_bmi2(s, br, ctx) } + return sequenceDecs_decodeSync_bmi2(s, br, ctx) } - if errCode != 0 { - i := len(seqs) - ctx.iteration - 1 - switch errCode { - case errorMatchLenOfsMismatch: - ml := ctx.seqs[i].ml - return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml) - - case errorMatchLenTooBig: - ml := ctx.seqs[i].ml - return fmt.Errorf("match len (%d) bigger than max allowed length", ml) - - case errorNotEnoughLiterals: - ll := ctx.seqs[i].ll - return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, ctx.litRemain+ll) - case errorOverread: - return io.ErrUnexpectedEOF - } - - return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode) + if safe { + return sequenceDecs_decodeSync_safe_amd64(s, br, ctx) } - - if ctx.litRemain < 0 { - return fmt.Errorf("literal count is too big: total available %d, total requested %d", - len(s.literals), len(s.literals)-ctx.litRemain) - } - - s.seqSize += ctx.litRemain - if s.seqSize > maxBlockSize { - return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) - } - if debugDecoder { - println("decode: ", br.remain(), "bits remain on stream. code:", errCode) - } - err := br.close() - if err != nil { - printf("Closing sequences: %v, %+v\n", err, *br) - } - return err -} - -// -------------------------------------------------------------------------------- - -type executeAsmContext struct { - seqs []seqVals - seqIndex int - out []byte - history []byte - literals []byte - outPosition int - litPosition int - windowSize int + return sequenceDecs_decodeSync_amd64(s, br, ctx) } // sequenceDecs_executeSimple_amd64 implements the main loop of sequenceDecs.executeSimple in x86 asm. @@ -334,54 +96,10 @@ func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool //go:noescape func sequenceDecs_executeSimple_safe_amd64(ctx *executeAsmContext) bool -// executeSimple handles cases when dictionary is not used. -func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error { - // Ensure we have enough output size... - if len(s.out)+s.seqSize+compressedBlockOverAlloc > cap(s.out) { - addBytes := s.seqSize + len(s.out) + compressedBlockOverAlloc - s.out = append(s.out, make([]byte, addBytes)...) - s.out = s.out[:len(s.out)-addBytes] - } - - if debugDecoder { - printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize) - } - - var t = len(s.out) - out := s.out[:t+s.seqSize] - - ctx := executeAsmContext{ - seqs: seqs, - seqIndex: 0, - out: out, - history: hist, - outPosition: t, - litPosition: 0, - literals: s.literals, - windowSize: s.windowSize, +// executeSimpleAsm runs the executeSimple loop, choosing the safe variant. +func executeSimpleAsm(ctx *executeAsmContext, safe bool) bool { + if safe { + return sequenceDecs_executeSimple_safe_amd64(ctx) } - var ok bool - if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc { - ok = sequenceDecs_executeSimple_safe_amd64(&ctx) - } else { - ok = sequenceDecs_executeSimple_amd64(&ctx) - } - if !ok { - return fmt.Errorf("match offset (%d) bigger than current history (%d)", - seqs[ctx.seqIndex].mo, ctx.outPosition+len(hist)) - } - s.literals = s.literals[ctx.litPosition:] - t = ctx.outPosition - - // Add final literals - copy(out[t:], s.literals) - if debugDecoder { - t += len(s.literals) - if t != len(out) { - panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize)) - } - } - s.out = out - - return nil + return sequenceDecs_executeSimple_amd64(ctx) } diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s index a708ca6d3d9..3fc381c7a7b 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s @@ -1,4 +1,4 @@ -// Code generated by command: go run gen.go -out ../seqdec_amd64.s -pkg=zstd. DO NOT EDIT. +// Code generated by command: go run gen.go -out ../seqdec.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. //go:build !appengine && !noasm && gc && !noasm diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.go b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.go new file mode 100644 index 00000000000..5ad262acff0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.go @@ -0,0 +1,70 @@ +//go:build arm64 && !appengine && !noasm && gc + +package zstd + +// The shared decode/decodeSync/executeSimple wrappers and context structs live +// in seqdec_asm.go; this file only declares the arm64 asm routines (generated +// by the avo arm64 lowering printer) and the dispatch helpers. arm64 has no +// BMI2, so each helper selects only between the 56-bit / safe variants. + +// sequenceDecs_decode_arm64 implements the main loop of sequenceDecs in arm64 asm. +// +// Please refer to seqdec_generic.go for the reference implementation. +// +//go:noescape +func sequenceDecs_decode_arm64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int + +// sequenceDecs_decode_56_arm64 implements the main loop of sequenceDecs in arm64 asm. +// +//go:noescape +func sequenceDecs_decode_56_arm64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int + +// decodeAsm runs the sequenceDecs decode loop, choosing the 56-bit variant. +func decodeAsm(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext, lte56bits bool) int { + if lte56bits { + return sequenceDecs_decode_56_arm64(s, br, ctx) + } + return sequenceDecs_decode_arm64(s, br, ctx) +} + +// sequenceDecs_decodeSync_arm64 implements the main loop of sequenceDecs.decodeSync in arm64 asm. +// +// Please refer to seqdec_generic.go for the reference implementation. +// +//go:noescape +func sequenceDecs_decodeSync_arm64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int + +// sequenceDecs_decodeSync_safe_arm64 does the same as above, but does not write more than output buffer. +// +//go:noescape +func sequenceDecs_decodeSync_safe_arm64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int + +// decodeSyncAsm runs the decodeSync loop, choosing the safe variant. +func decodeSyncAsm(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext, safe bool) int { + if safe { + return sequenceDecs_decodeSync_safe_arm64(s, br, ctx) + } + return sequenceDecs_decodeSync_arm64(s, br, ctx) +} + +// sequenceDecs_executeSimple_arm64 implements the main loop of sequenceDecs.executeSimple in arm64 asm. +// +// Returns false if a match offset is too big. +// +// Please refer to seqdec_generic.go for the reference implementation. +// +//go:noescape +func sequenceDecs_executeSimple_arm64(ctx *executeAsmContext) bool + +// Same as above, but with safe memcopies +// +//go:noescape +func sequenceDecs_executeSimple_safe_arm64(ctx *executeAsmContext) bool + +// executeSimpleAsm runs the executeSimple loop, choosing the safe variant. +func executeSimpleAsm(ctx *executeAsmContext, safe bool) bool { + if safe { + return sequenceDecs_executeSimple_safe_arm64(ctx) + } + return sequenceDecs_executeSimple_arm64(ctx) +} diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s new file mode 100644 index 00000000000..a468e5fc2ca --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s @@ -0,0 +1,2705 @@ +// Code generated by command: go run gen.go -out ../seqdec.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. +// EXPERIMENTAL arm64 output lowered from an amd64 avo program. + +//go:build arm64 && !appengine && !noasm && gc && !noasm + +// func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +// Requires: CMOV +TEXT ·sequenceDecs_decode_arm64(SB), $8-32 + MOVD br+8(FP), R1 + MOVD 24(R1), R2 + MOVBU 40(R1), R3 + MOVD (R1), R0 + MOVD 32(R1), R5 + ADD R5, R0, R0 + MOVD R0, (RSP) + MOVD ctx+16(FP), R0 + MOVD 72(R0), R6 + MOVD 80(R0), R7 + MOVD 88(R0), R8 + MOVD 104(R0), R9 + MOVD s+0(FP), R0 + MOVD 144(R0), R10 + MOVD 152(R0), R11 + MOVD 160(R0), R12 + +sequenceDecs_decode_amd64_main_loop: + MOVD (RSP), R13 + + // Fill bitreader to have enough for the offset and match length. + CMP $0x08, R5 + BLT sequenceDecs_decode_amd64_fill_byte_by_byte + MOVD R3, R0 + LSR $0x03, R0, R0 + SUB R0, R13, R13 + MOVD (R13), R2 + SUB R0, R5, R5 + AND $0x07, R3, R3 + JMP sequenceDecs_decode_amd64_fill_end + +sequenceDecs_decode_amd64_fill_byte_by_byte: + CMP $0x00, R5 + BLE sequenceDecs_decode_amd64_fill_check_overread + CMP $0x07, R3 + BLE sequenceDecs_decode_amd64_fill_end + LSL $0x08, R2, R2 + SUB $0x01, R13, R13 + SUB $0x01, R5, R5 + SUB $0x08, R3, R3 + MOVBU (R13), R0 + ORR R0, R2, R2 + JMP sequenceDecs_decode_amd64_fill_byte_by_byte + +sequenceDecs_decode_amd64_fill_check_overread: + CMP $0x40, R3 + BHI error_overread + +sequenceDecs_decode_amd64_fill_end: + // Update offset + MOVD R8, R0 + MOVD R3, R1 + MOVD R2, R14 + LSL R1, R14, R14 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decode_amd64_of_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decode_amd64_of_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decode_amd64_of_update_zero + NEG R1, R1 + LSR R1, R14, R14 + ADD R14, R0, R0 + +sequenceDecs_decode_amd64_of_update_zero: + MOVD R0, 16(R9) + + // Update match length + MOVD R7, R0 + MOVD R3, R1 + MOVD R2, R14 + LSL R1, R14, R14 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decode_amd64_ml_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decode_amd64_ml_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decode_amd64_ml_update_zero + NEG R1, R1 + LSR R1, R14, R14 + ADD R14, R0, R0 + +sequenceDecs_decode_amd64_ml_update_zero: + MOVD R0, 8(R9) + + // Fill bitreader to have enough for the remaining + CMP $0x08, R5 + BLT sequenceDecs_decode_amd64_fill_2_byte_by_byte + MOVD R3, R0 + LSR $0x03, R0, R0 + SUB R0, R13, R13 + MOVD (R13), R2 + SUB R0, R5, R5 + AND $0x07, R3, R3 + JMP sequenceDecs_decode_amd64_fill_2_end + +sequenceDecs_decode_amd64_fill_2_byte_by_byte: + CMP $0x00, R5 + BLE sequenceDecs_decode_amd64_fill_2_check_overread + CMP $0x07, R3 + BLE sequenceDecs_decode_amd64_fill_2_end + LSL $0x08, R2, R2 + SUB $0x01, R13, R13 + SUB $0x01, R5, R5 + SUB $0x08, R3, R3 + MOVBU (R13), R0 + ORR R0, R2, R2 + JMP sequenceDecs_decode_amd64_fill_2_byte_by_byte + +sequenceDecs_decode_amd64_fill_2_check_overread: + CMP $0x40, R3 + BHI error_overread + +sequenceDecs_decode_amd64_fill_2_end: + // Update literal length + MOVD R6, R0 + MOVD R3, R1 + MOVD R2, R14 + LSL R1, R14, R14 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decode_amd64_ll_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decode_amd64_ll_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decode_amd64_ll_update_zero + NEG R1, R1 + LSR R1, R14, R14 + ADD R14, R0, R0 + +sequenceDecs_decode_amd64_ll_update_zero: + MOVD R0, (R9) + + // Fill bitreader for state updates + MOVD R13, (RSP) + MOVD R8, R0 + LSR $0x08, R0, R0 + MOVBU R0, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decode_amd64_skip_update + + // Update Literal Length State + MOVBU R6, R13 + LSRW $0x10, R6, R6 + ADD R13, R3, R1 + MOVD R2, R14 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R14, R14 + MOVD $0x00000001, R4 + MOVB R13, R1 + LSLW R1, R4, R4 + SUBW $1, R4, R4 + AND R4, R14, R14 + ADD R14, R6, R6 + + // Load ctx.llTable + MOVD ctx+16(FP), R1 + MOVD (R1), R1 + ADD R6<<3, R1, R15 + MOVD (R15), R6 + + // Update Match Length State + MOVBU R7, R13 + LSRW $0x10, R7, R7 + ADD R13, R3, R1 + MOVD R2, R14 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R14, R14 + MOVD $0x00000001, R4 + MOVB R13, R1 + LSLW R1, R4, R4 + SUBW $1, R4, R4 + AND R4, R14, R14 + ADD R14, R7, R7 + + // Load ctx.mlTable + MOVD ctx+16(FP), R1 + MOVD 24(R1), R1 + ADD R7<<3, R1, R15 + MOVD (R15), R7 + + // Update Offset State + MOVBU R8, R13 + LSRW $0x10, R8, R8 + ADD R13, R3, R1 + MOVD R2, R14 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R14, R14 + MOVD $0x00000001, R4 + MOVB R13, R1 + LSLW R1, R4, R4 + SUBW $1, R4, R4 + AND R4, R14, R14 + ADD R14, R8, R8 + + // Load ctx.ofTable + MOVD ctx+16(FP), R1 + MOVD 48(R1), R1 + ADD R8<<3, R1, R15 + MOVD (R15), R8 + +sequenceDecs_decode_amd64_skip_update: + // Adjust offset + MOVD 16(R9), R1 + CMP $0x01, R0 + BLS sequenceDecs_decode_amd64_adjust_offsetB_1_or_0 + MOVD R11, R12 + MOVD R10, R11 + MOVD R1, R10 + JMP sequenceDecs_decode_amd64_after_adjust + +sequenceDecs_decode_amd64_adjust_offsetB_1_or_0: + MOVD (R9), R16 + CMP $0x00000000, R16 + BNE sequenceDecs_decode_amd64_adjust_offset_maybezero + ADD $1, R1, R1 + JMP sequenceDecs_decode_amd64_adjust_offset_nonzero + +sequenceDecs_decode_amd64_adjust_offset_maybezero: + TST R1, R1 + BNE sequenceDecs_decode_amd64_adjust_offset_nonzero + MOVD R10, R1 + JMP sequenceDecs_decode_amd64_after_adjust + +sequenceDecs_decode_amd64_adjust_offset_nonzero: + CMP $0x01, R1 + BLO sequenceDecs_decode_amd64_adjust_zero + BEQ sequenceDecs_decode_amd64_adjust_one + CMP $0x02, R1 + BHI sequenceDecs_decode_amd64_adjust_three + JMP sequenceDecs_decode_amd64_adjust_two + +sequenceDecs_decode_amd64_adjust_zero: + MOVD R10, R0 + JMP sequenceDecs_decode_amd64_adjust_test_temp_valid + +sequenceDecs_decode_amd64_adjust_one: + MOVD R11, R0 + JMP sequenceDecs_decode_amd64_adjust_test_temp_valid + +sequenceDecs_decode_amd64_adjust_two: + MOVD R12, R0 + JMP sequenceDecs_decode_amd64_adjust_test_temp_valid + +sequenceDecs_decode_amd64_adjust_three: + SUB $1, R10, R0 + +sequenceDecs_decode_amd64_adjust_test_temp_valid: + TST R0, R0 + BNE sequenceDecs_decode_amd64_adjust_temp_valid + MOVD $0x00000001, R0 + +sequenceDecs_decode_amd64_adjust_temp_valid: + CMP $0x01, R1 + CSEL NE, R11, R12, R12 + MOVD R10, R11 + MOVD R0, R10 + MOVD R0, R1 + +sequenceDecs_decode_amd64_after_adjust: + MOVD R1, 16(R9) + + // Check values + MOVD 8(R9), R0 + MOVD (R9), R13 + ADD R13, R0, R14 + MOVD s+0(FP), R4 + MOVD 256(R4), R16 + ADD R14, R16, R16 + MOVD R16, 256(R4) + MOVD ctx+16(FP), R14 + MOVD 128(R14), R16 + SUBS R13, R16, R16 + MOVD R16, 128(R14) + BMI error_not_enough_literals + CMP $0x00020002, R0 + BHI sequenceDecs_decode_amd64_error_match_len_too_big + TST R1, R1 + BNE sequenceDecs_decode_amd64_match_len_ofs_ok + TST R0, R0 + BNE sequenceDecs_decode_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decode_amd64_match_len_ofs_ok: + ADD $0x18, R9, R9 + MOVD ctx+16(FP), R0 + MOVD 96(R0), R16 + SUBS $1, R16, R16 + MOVD R16, 96(R0) + BPL sequenceDecs_decode_amd64_main_loop + MOVD s+0(FP), R0 + MOVD R10, 144(R0) + MOVD R11, 152(R0) + MOVD R12, 160(R0) + MOVD br+8(FP), R0 + MOVD R2, 24(R0) + MOVB R3, 40(R0) + MOVD R5, 32(R0) + + // Return success + MOVD $0x00000000, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decode_amd64_error_match_len_ofs_mismatch: + MOVD $0x00000001, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decode_amd64_error_match_len_too_big: + MOVD $0x00000002, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match offset too long error + MOVD $0x00000003, R16 + MOVD R16, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVD $0x00000004, R16 + MOVD R16, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVD $0x00000006, R16 + MOVD R16, ret+24(FP) + RET + +// func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +// Requires: CMOV +TEXT ·sequenceDecs_decode_56_arm64(SB), $8-32 + MOVD br+8(FP), R1 + MOVD 24(R1), R2 + MOVBU 40(R1), R3 + MOVD (R1), R0 + MOVD 32(R1), R5 + ADD R5, R0, R0 + MOVD R0, (RSP) + MOVD ctx+16(FP), R0 + MOVD 72(R0), R6 + MOVD 80(R0), R7 + MOVD 88(R0), R8 + MOVD 104(R0), R9 + MOVD s+0(FP), R0 + MOVD 144(R0), R10 + MOVD 152(R0), R11 + MOVD 160(R0), R12 + +sequenceDecs_decode_56_amd64_main_loop: + MOVD (RSP), R13 + + // Fill bitreader to have enough for the offset and match length. + CMP $0x08, R5 + BLT sequenceDecs_decode_56_amd64_fill_byte_by_byte + MOVD R3, R0 + LSR $0x03, R0, R0 + SUB R0, R13, R13 + MOVD (R13), R2 + SUB R0, R5, R5 + AND $0x07, R3, R3 + JMP sequenceDecs_decode_56_amd64_fill_end + +sequenceDecs_decode_56_amd64_fill_byte_by_byte: + CMP $0x00, R5 + BLE sequenceDecs_decode_56_amd64_fill_check_overread + CMP $0x07, R3 + BLE sequenceDecs_decode_56_amd64_fill_end + LSL $0x08, R2, R2 + SUB $0x01, R13, R13 + SUB $0x01, R5, R5 + SUB $0x08, R3, R3 + MOVBU (R13), R0 + ORR R0, R2, R2 + JMP sequenceDecs_decode_56_amd64_fill_byte_by_byte + +sequenceDecs_decode_56_amd64_fill_check_overread: + CMP $0x40, R3 + BHI error_overread + +sequenceDecs_decode_56_amd64_fill_end: + // Update offset + MOVD R8, R0 + MOVD R3, R1 + MOVD R2, R14 + LSL R1, R14, R14 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decode_56_amd64_of_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decode_56_amd64_of_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decode_56_amd64_of_update_zero + NEG R1, R1 + LSR R1, R14, R14 + ADD R14, R0, R0 + +sequenceDecs_decode_56_amd64_of_update_zero: + MOVD R0, 16(R9) + + // Update match length + MOVD R7, R0 + MOVD R3, R1 + MOVD R2, R14 + LSL R1, R14, R14 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decode_56_amd64_ml_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decode_56_amd64_ml_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decode_56_amd64_ml_update_zero + NEG R1, R1 + LSR R1, R14, R14 + ADD R14, R0, R0 + +sequenceDecs_decode_56_amd64_ml_update_zero: + MOVD R0, 8(R9) + + // Update literal length + MOVD R6, R0 + MOVD R3, R1 + MOVD R2, R14 + LSL R1, R14, R14 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decode_56_amd64_ll_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decode_56_amd64_ll_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decode_56_amd64_ll_update_zero + NEG R1, R1 + LSR R1, R14, R14 + ADD R14, R0, R0 + +sequenceDecs_decode_56_amd64_ll_update_zero: + MOVD R0, (R9) + + // Fill bitreader for state updates + MOVD R13, (RSP) + MOVD R8, R0 + LSR $0x08, R0, R0 + MOVBU R0, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decode_56_amd64_skip_update + + // Update Literal Length State + MOVBU R6, R13 + LSRW $0x10, R6, R6 + ADD R13, R3, R1 + MOVD R2, R14 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R14, R14 + MOVD $0x00000001, R4 + MOVB R13, R1 + LSLW R1, R4, R4 + SUBW $1, R4, R4 + AND R4, R14, R14 + ADD R14, R6, R6 + + // Load ctx.llTable + MOVD ctx+16(FP), R1 + MOVD (R1), R1 + ADD R6<<3, R1, R15 + MOVD (R15), R6 + + // Update Match Length State + MOVBU R7, R13 + LSRW $0x10, R7, R7 + ADD R13, R3, R1 + MOVD R2, R14 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R14, R14 + MOVD $0x00000001, R4 + MOVB R13, R1 + LSLW R1, R4, R4 + SUBW $1, R4, R4 + AND R4, R14, R14 + ADD R14, R7, R7 + + // Load ctx.mlTable + MOVD ctx+16(FP), R1 + MOVD 24(R1), R1 + ADD R7<<3, R1, R15 + MOVD (R15), R7 + + // Update Offset State + MOVBU R8, R13 + LSRW $0x10, R8, R8 + ADD R13, R3, R1 + MOVD R2, R14 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R14, R14 + MOVD $0x00000001, R4 + MOVB R13, R1 + LSLW R1, R4, R4 + SUBW $1, R4, R4 + AND R4, R14, R14 + ADD R14, R8, R8 + + // Load ctx.ofTable + MOVD ctx+16(FP), R1 + MOVD 48(R1), R1 + ADD R8<<3, R1, R15 + MOVD (R15), R8 + +sequenceDecs_decode_56_amd64_skip_update: + // Adjust offset + MOVD 16(R9), R1 + CMP $0x01, R0 + BLS sequenceDecs_decode_56_amd64_adjust_offsetB_1_or_0 + MOVD R11, R12 + MOVD R10, R11 + MOVD R1, R10 + JMP sequenceDecs_decode_56_amd64_after_adjust + +sequenceDecs_decode_56_amd64_adjust_offsetB_1_or_0: + MOVD (R9), R16 + CMP $0x00000000, R16 + BNE sequenceDecs_decode_56_amd64_adjust_offset_maybezero + ADD $1, R1, R1 + JMP sequenceDecs_decode_56_amd64_adjust_offset_nonzero + +sequenceDecs_decode_56_amd64_adjust_offset_maybezero: + TST R1, R1 + BNE sequenceDecs_decode_56_amd64_adjust_offset_nonzero + MOVD R10, R1 + JMP sequenceDecs_decode_56_amd64_after_adjust + +sequenceDecs_decode_56_amd64_adjust_offset_nonzero: + CMP $0x01, R1 + BLO sequenceDecs_decode_56_amd64_adjust_zero + BEQ sequenceDecs_decode_56_amd64_adjust_one + CMP $0x02, R1 + BHI sequenceDecs_decode_56_amd64_adjust_three + JMP sequenceDecs_decode_56_amd64_adjust_two + +sequenceDecs_decode_56_amd64_adjust_zero: + MOVD R10, R0 + JMP sequenceDecs_decode_56_amd64_adjust_test_temp_valid + +sequenceDecs_decode_56_amd64_adjust_one: + MOVD R11, R0 + JMP sequenceDecs_decode_56_amd64_adjust_test_temp_valid + +sequenceDecs_decode_56_amd64_adjust_two: + MOVD R12, R0 + JMP sequenceDecs_decode_56_amd64_adjust_test_temp_valid + +sequenceDecs_decode_56_amd64_adjust_three: + SUB $1, R10, R0 + +sequenceDecs_decode_56_amd64_adjust_test_temp_valid: + TST R0, R0 + BNE sequenceDecs_decode_56_amd64_adjust_temp_valid + MOVD $0x00000001, R0 + +sequenceDecs_decode_56_amd64_adjust_temp_valid: + CMP $0x01, R1 + CSEL NE, R11, R12, R12 + MOVD R10, R11 + MOVD R0, R10 + MOVD R0, R1 + +sequenceDecs_decode_56_amd64_after_adjust: + MOVD R1, 16(R9) + + // Check values + MOVD 8(R9), R0 + MOVD (R9), R13 + ADD R13, R0, R14 + MOVD s+0(FP), R4 + MOVD 256(R4), R16 + ADD R14, R16, R16 + MOVD R16, 256(R4) + MOVD ctx+16(FP), R14 + MOVD 128(R14), R16 + SUBS R13, R16, R16 + MOVD R16, 128(R14) + BMI error_not_enough_literals + CMP $0x00020002, R0 + BHI sequenceDecs_decode_56_amd64_error_match_len_too_big + TST R1, R1 + BNE sequenceDecs_decode_56_amd64_match_len_ofs_ok + TST R0, R0 + BNE sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decode_56_amd64_match_len_ofs_ok: + ADD $0x18, R9, R9 + MOVD ctx+16(FP), R0 + MOVD 96(R0), R16 + SUBS $1, R16, R16 + MOVD R16, 96(R0) + BPL sequenceDecs_decode_56_amd64_main_loop + MOVD s+0(FP), R0 + MOVD R10, 144(R0) + MOVD R11, 152(R0) + MOVD R12, 160(R0) + MOVD br+8(FP), R0 + MOVD R2, 24(R0) + MOVB R3, 40(R0) + MOVD R5, 32(R0) + + // Return success + MOVD $0x00000000, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch: + MOVD $0x00000001, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decode_56_amd64_error_match_len_too_big: + MOVD $0x00000002, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match offset too long error + MOVD $0x00000003, R16 + MOVD R16, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVD $0x00000004, R16 + MOVD R16, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVD $0x00000006, R16 + MOVD R16, ret+24(FP) + RET + +// skipped sequenceDecs_decode_bmi2 (generic twin preferred on arm64) + +// skipped sequenceDecs_decode_56_bmi2 (generic twin preferred on arm64) + +// func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool +// Requires: SSE +TEXT ·sequenceDecs_executeSimple_arm64(SB), $8-9 + MOVD ctx+0(FP), R9 + MOVD 8(R9), R1 + TST R1, R1 + BEQ empty_seqs + MOVD (R9), R0 + MOVD 24(R9), R2 + MOVD 32(R9), R3 + MOVD 80(R9), R5 + MOVD 104(R9), R6 + MOVD 120(R9), R7 + MOVD 56(R9), R8 + MOVD 64(R9), R9 + ADD R9, R8, R8 + + // seqsBase += 24 * seqIndex + ADD R2<<1, R2, R10 + LSL $0x03, R10, R10 + ADD R10, R0, R0 + + // outBase += outPosition + ADD R6, R3, R3 + +main_loop: + MOVD (R0), R10 + MOVD 16(R0), R11 + MOVD 8(R0), R12 + + // Copy literals + TST R10, R10 + BEQ check_offset + MOVD $0, R13 + +copy_1: + ADD R13, R5, R15 + VLD1 (R15), [V0.B16] + ADD R13, R3, R15 + VST1 [V0.B16], (R15) + ADD $0x10, R13, R13 + CMP R10, R13 + BLO copy_1 + ADD R10, R5, R5 + ADD R10, R3, R3 + ADD R10, R6, R6 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + ADD R9, R6, R10 + CMP R10, R11 + BGT error_match_off_too_big + CMP R7, R11 + BGT error_match_off_too_big + + // Copy match from history + MOVD R11, R10 + SUBS R6, R10, R10 + BLS copy_match + MOVD R8, R13 + SUB R10, R13, R13 + CMP R10, R12 + BGT copy_all_from_history + MOVD R12, R10 + SUBS $0x10, R10, R10 + BLO copy_4_small + +copy_4_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R10, R10 + BHS copy_4_loop + ADD R10, R13, R13 + ADD $16, R13, R13 + ADD R10, R3, R3 + ADD $16, R3, R3 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R3, R15 + VST1 [V0.B16], (R15) + JMP copy_4_end + +copy_4_small: + CMP $0x03, R12 + BEQ copy_4_move_3 + CMP $0x08, R12 + BLO copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVH (R13), R10 + MOVB 2(R13), R11 + MOVH R10, (R3) + MOVB R11, 2(R3) + ADD R12, R13, R13 + ADD R12, R3, R3 + JMP copy_4_end + +copy_4_move_4through7: + MOVWU (R13), R10 + ADD R12, R13, R15 + MOVWU -4(R15), R11 + MOVW R10, (R3) + ADD R12, R3, R15 + MOVW R11, -4(R15) + ADD R12, R13, R13 + ADD R12, R3, R3 + JMP copy_4_end + +copy_4_move_8through16: + MOVD (R13), R10 + ADD R12, R13, R15 + MOVD -8(R15), R11 + MOVD R10, (R3) + ADD R12, R3, R15 + MOVD R11, -8(R15) + ADD R12, R13, R13 + ADD R12, R3, R3 + +copy_4_end: + ADD R12, R6, R6 + ADD $0x18, R0, R0 + ADD $1, R2, R2 + CMP R1, R2 + BLO main_loop + JMP loop_finished + +copy_all_from_history: + MOVD R10, R14 + SUBS $0x10, R14, R14 + BLO copy_5_small + +copy_5_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R3, R3 + ADD $16, R3, R3 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R3, R15 + VST1 [V0.B16], (R15) + JMP copy_5_end + +copy_5_small: + CMP $0x03, R10 + BEQ copy_5_move_3 + BLO copy_5_move_1or2 + CMP $0x08, R10 + BLO copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R13), R14 + ADD R10, R13, R15 + MOVB -1(R15), R4 + MOVB R14, (R3) + ADD R10, R3, R15 + MOVB R4, -1(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end + +copy_5_move_3: + MOVH (R13), R14 + MOVB 2(R13), R4 + MOVH R14, (R3) + MOVB R4, 2(R3) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end + +copy_5_move_4through7: + MOVWU (R13), R14 + ADD R10, R13, R15 + MOVWU -4(R15), R4 + MOVW R14, (R3) + ADD R10, R3, R15 + MOVW R4, -4(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end + +copy_5_move_8through16: + MOVD (R13), R14 + ADD R10, R13, R15 + MOVD -8(R15), R4 + MOVD R14, (R3) + ADD R10, R3, R15 + MOVD R4, -8(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + +copy_5_end: + ADD R10, R6, R6 + SUB R10, R12, R12 + + // Copy match from the current buffer +copy_match: + MOVD R3, R10 + SUB R11, R10, R10 + + // ml <= mo + CMP R11, R12 + BHI copy_overlapping_match + + // Copy non-overlapping match + ADD R12, R6, R6 + MOVD R3, R11 + ADD R12, R3, R3 + +copy_2: + VLD1 (R10), [V0.B16] + VST1 [V0.B16], (R11) + ADD $0x10, R10, R10 + ADD $0x10, R11, R11 + SUBS $0x10, R12, R12 + BHI copy_2 + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADD R12, R6, R6 + +copy_slow_3: + MOVB (R10), R11 + MOVB R11, (R3) + ADD $1, R10, R10 + ADD $1, R3, R3 + SUBS $1, R12, R12 + BNE copy_slow_3 + +handle_loop: + ADD $0x18, R0, R0 + ADD $1, R2, R2 + CMP R1, R2 + BLO main_loop + +loop_finished: + // Return value + MOVD $0x01, R16 + MOVB R16, ret+8(FP) + + // Update the context + MOVD ctx+0(FP), R0 + MOVD R2, 24(R0) + MOVD R6, 104(R0) + MOVD 80(R0), R16 + SUB R16, R5, R5 + MOVD R5, 112(R0) + RET + +error_match_off_too_big: + // Return value + MOVD $0x00, R16 + MOVB R16, ret+8(FP) + + // Update the context + MOVD ctx+0(FP), R0 + MOVD R2, 24(R0) + MOVD R6, 104(R0) + MOVD 80(R0), R16 + SUB R16, R5, R5 + MOVD R5, 112(R0) + RET + +empty_seqs: + // Return value + MOVD $0x01, R16 + MOVB R16, ret+8(FP) + RET + +// func sequenceDecs_executeSimple_safe_amd64(ctx *executeAsmContext) bool +// Requires: SSE +TEXT ·sequenceDecs_executeSimple_safe_arm64(SB), $8-9 + MOVD ctx+0(FP), R9 + MOVD 8(R9), R1 + TST R1, R1 + BEQ empty_seqs + MOVD (R9), R0 + MOVD 24(R9), R2 + MOVD 32(R9), R3 + MOVD 80(R9), R5 + MOVD 104(R9), R6 + MOVD 120(R9), R7 + MOVD 56(R9), R8 + MOVD 64(R9), R9 + ADD R9, R8, R8 + + // seqsBase += 24 * seqIndex + ADD R2<<1, R2, R10 + LSL $0x03, R10, R10 + ADD R10, R0, R0 + + // outBase += outPosition + ADD R6, R3, R3 + +main_loop: + MOVD (R0), R10 + MOVD 16(R0), R11 + MOVD 8(R0), R12 + + // Copy literals + TST R10, R10 + BEQ check_offset + MOVD R10, R13 + SUBS $0x10, R13, R13 + BLO copy_1_small + +copy_1_loop: + VLD1 (R5), [V0.B16] + VST1 [V0.B16], (R3) + ADD $0x10, R5, R5 + ADD $0x10, R3, R3 + SUBS $0x10, R13, R13 + BHS copy_1_loop + ADD R13, R5, R5 + ADD $16, R5, R5 + ADD R13, R3, R3 + ADD $16, R3, R3 + ADD $-16, R5, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R3, R15 + VST1 [V0.B16], (R15) + JMP copy_1_end + +copy_1_small: + CMP $0x03, R10 + BEQ copy_1_move_3 + BLO copy_1_move_1or2 + CMP $0x08, R10 + BLO copy_1_move_4through7 + JMP copy_1_move_8through16 + +copy_1_move_1or2: + MOVB (R5), R13 + ADD R10, R5, R15 + MOVB -1(R15), R14 + MOVB R13, (R3) + ADD R10, R3, R15 + MOVB R14, -1(R15) + ADD R10, R5, R5 + ADD R10, R3, R3 + JMP copy_1_end + +copy_1_move_3: + MOVH (R5), R13 + MOVB 2(R5), R14 + MOVH R13, (R3) + MOVB R14, 2(R3) + ADD R10, R5, R5 + ADD R10, R3, R3 + JMP copy_1_end + +copy_1_move_4through7: + MOVWU (R5), R13 + ADD R10, R5, R15 + MOVWU -4(R15), R14 + MOVW R13, (R3) + ADD R10, R3, R15 + MOVW R14, -4(R15) + ADD R10, R5, R5 + ADD R10, R3, R3 + JMP copy_1_end + +copy_1_move_8through16: + MOVD (R5), R13 + ADD R10, R5, R15 + MOVD -8(R15), R14 + MOVD R13, (R3) + ADD R10, R3, R15 + MOVD R14, -8(R15) + ADD R10, R5, R5 + ADD R10, R3, R3 + +copy_1_end: + ADD R10, R6, R6 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + ADD R9, R6, R10 + CMP R10, R11 + BGT error_match_off_too_big + CMP R7, R11 + BGT error_match_off_too_big + + // Copy match from history + MOVD R11, R10 + SUBS R6, R10, R10 + BLS copy_match + MOVD R8, R13 + SUB R10, R13, R13 + CMP R10, R12 + BGT copy_all_from_history + MOVD R12, R10 + SUBS $0x10, R10, R10 + BLO copy_4_small + +copy_4_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R10, R10 + BHS copy_4_loop + ADD R10, R13, R13 + ADD $16, R13, R13 + ADD R10, R3, R3 + ADD $16, R3, R3 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R3, R15 + VST1 [V0.B16], (R15) + JMP copy_4_end + +copy_4_small: + CMP $0x03, R12 + BEQ copy_4_move_3 + CMP $0x08, R12 + BLO copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVH (R13), R10 + MOVB 2(R13), R11 + MOVH R10, (R3) + MOVB R11, 2(R3) + ADD R12, R13, R13 + ADD R12, R3, R3 + JMP copy_4_end + +copy_4_move_4through7: + MOVWU (R13), R10 + ADD R12, R13, R15 + MOVWU -4(R15), R11 + MOVW R10, (R3) + ADD R12, R3, R15 + MOVW R11, -4(R15) + ADD R12, R13, R13 + ADD R12, R3, R3 + JMP copy_4_end + +copy_4_move_8through16: + MOVD (R13), R10 + ADD R12, R13, R15 + MOVD -8(R15), R11 + MOVD R10, (R3) + ADD R12, R3, R15 + MOVD R11, -8(R15) + ADD R12, R13, R13 + ADD R12, R3, R3 + +copy_4_end: + ADD R12, R6, R6 + ADD $0x18, R0, R0 + ADD $1, R2, R2 + CMP R1, R2 + BLO main_loop + JMP loop_finished + +copy_all_from_history: + MOVD R10, R14 + SUBS $0x10, R14, R14 + BLO copy_5_small + +copy_5_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R3, R3 + ADD $16, R3, R3 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R3, R15 + VST1 [V0.B16], (R15) + JMP copy_5_end + +copy_5_small: + CMP $0x03, R10 + BEQ copy_5_move_3 + BLO copy_5_move_1or2 + CMP $0x08, R10 + BLO copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R13), R14 + ADD R10, R13, R15 + MOVB -1(R15), R4 + MOVB R14, (R3) + ADD R10, R3, R15 + MOVB R4, -1(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end + +copy_5_move_3: + MOVH (R13), R14 + MOVB 2(R13), R4 + MOVH R14, (R3) + MOVB R4, 2(R3) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end + +copy_5_move_4through7: + MOVWU (R13), R14 + ADD R10, R13, R15 + MOVWU -4(R15), R4 + MOVW R14, (R3) + ADD R10, R3, R15 + MOVW R4, -4(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end + +copy_5_move_8through16: + MOVD (R13), R14 + ADD R10, R13, R15 + MOVD -8(R15), R4 + MOVD R14, (R3) + ADD R10, R3, R15 + MOVD R4, -8(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + +copy_5_end: + ADD R10, R6, R6 + SUB R10, R12, R12 + + // Copy match from the current buffer +copy_match: + MOVD R3, R10 + SUB R11, R10, R10 + + // ml <= mo + CMP R11, R12 + BHI copy_overlapping_match + + // Copy non-overlapping match + ADD R12, R6, R6 + MOVD R12, R11 + SUBS $0x10, R11, R11 + BLO copy_2_small + +copy_2_loop: + VLD1 (R10), [V0.B16] + VST1 [V0.B16], (R3) + ADD $0x10, R10, R10 + ADD $0x10, R3, R3 + SUBS $0x10, R11, R11 + BHS copy_2_loop + ADD R11, R10, R10 + ADD $16, R10, R10 + ADD R11, R3, R3 + ADD $16, R3, R3 + ADD $-16, R10, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R3, R15 + VST1 [V0.B16], (R15) + JMP copy_2_end + +copy_2_small: + CMP $0x03, R12 + BEQ copy_2_move_3 + BLO copy_2_move_1or2 + CMP $0x08, R12 + BLO copy_2_move_4through7 + JMP copy_2_move_8through16 + +copy_2_move_1or2: + MOVB (R10), R11 + ADD R12, R10, R15 + MOVB -1(R15), R13 + MOVB R11, (R3) + ADD R12, R3, R15 + MOVB R13, -1(R15) + ADD R12, R10, R10 + ADD R12, R3, R3 + JMP copy_2_end + +copy_2_move_3: + MOVH (R10), R11 + MOVB 2(R10), R13 + MOVH R11, (R3) + MOVB R13, 2(R3) + ADD R12, R10, R10 + ADD R12, R3, R3 + JMP copy_2_end + +copy_2_move_4through7: + MOVWU (R10), R11 + ADD R12, R10, R15 + MOVWU -4(R15), R13 + MOVW R11, (R3) + ADD R12, R3, R15 + MOVW R13, -4(R15) + ADD R12, R10, R10 + ADD R12, R3, R3 + JMP copy_2_end + +copy_2_move_8through16: + MOVD (R10), R11 + ADD R12, R10, R15 + MOVD -8(R15), R13 + MOVD R11, (R3) + ADD R12, R3, R15 + MOVD R13, -8(R15) + ADD R12, R10, R10 + ADD R12, R3, R3 + +copy_2_end: + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADD R12, R6, R6 + +copy_slow_3: + MOVB (R10), R11 + MOVB R11, (R3) + ADD $1, R10, R10 + ADD $1, R3, R3 + SUBS $1, R12, R12 + BNE copy_slow_3 + +handle_loop: + ADD $0x18, R0, R0 + ADD $1, R2, R2 + CMP R1, R2 + BLO main_loop + +loop_finished: + // Return value + MOVD $0x01, R16 + MOVB R16, ret+8(FP) + + // Update the context + MOVD ctx+0(FP), R0 + MOVD R2, 24(R0) + MOVD R6, 104(R0) + MOVD 80(R0), R16 + SUB R16, R5, R5 + MOVD R5, 112(R0) + RET + +error_match_off_too_big: + // Return value + MOVD $0x00, R16 + MOVB R16, ret+8(FP) + + // Update the context + MOVD ctx+0(FP), R0 + MOVD R2, 24(R0) + MOVD R6, 104(R0) + MOVD 80(R0), R16 + SUB R16, R5, R5 + MOVD R5, 112(R0) + RET + +empty_seqs: + // Return value + MOVD $0x01, R16 + MOVB R16, ret+8(FP) + RET + +// func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +// Requires: CMOV, SSE +TEXT ·sequenceDecs_decodeSync_arm64(SB), $64-32 + MOVD br+8(FP), R1 + MOVD 24(R1), R2 + MOVBU 40(R1), R3 + MOVD (R1), R0 + MOVD 32(R1), R5 + ADD R5, R0, R0 + MOVD R0, (RSP) + MOVD ctx+16(FP), R0 + MOVD 72(R0), R6 + MOVD 80(R0), R7 + MOVD 88(R0), R8 + MOVD $0, R1 + MOVD R1, 8(RSP) + MOVD R1, 16(RSP) + MOVD R1, 24(RSP) + MOVD 112(R0), R9 + MOVD 128(R0), R1 + MOVD R1, 32(RSP) + MOVD 144(R0), R10 + MOVD 136(R0), R11 + MOVD 200(R0), R1 + MOVD R1, 56(RSP) + MOVD 176(R0), R1 + MOVD R1, 48(RSP) + MOVD 184(R0), R0 + MOVD R0, 40(RSP) + MOVD 40(RSP), R0 + MOVD 48(RSP), R16 + ADD R0, R16, R16 + MOVD R16, 48(RSP) + + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) + MOVD 32(RSP), R16 + ADD R9, R16, R16 + MOVD R16, 32(RSP) + + // outBase += outPosition + ADD R11, R9, R9 + +sequenceDecs_decodeSync_amd64_main_loop: + MOVD (RSP), R12 + + // Fill bitreader to have enough for the offset and match length. + CMP $0x08, R5 + BLT sequenceDecs_decodeSync_amd64_fill_byte_by_byte + MOVD R3, R0 + LSR $0x03, R0, R0 + SUB R0, R12, R12 + MOVD (R12), R2 + SUB R0, R5, R5 + AND $0x07, R3, R3 + JMP sequenceDecs_decodeSync_amd64_fill_end + +sequenceDecs_decodeSync_amd64_fill_byte_by_byte: + CMP $0x00, R5 + BLE sequenceDecs_decodeSync_amd64_fill_check_overread + CMP $0x07, R3 + BLE sequenceDecs_decodeSync_amd64_fill_end + LSL $0x08, R2, R2 + SUB $0x01, R12, R12 + SUB $0x01, R5, R5 + SUB $0x08, R3, R3 + MOVBU (R12), R0 + ORR R0, R2, R2 + JMP sequenceDecs_decodeSync_amd64_fill_byte_by_byte + +sequenceDecs_decodeSync_amd64_fill_check_overread: + CMP $0x40, R3 + BHI error_overread + +sequenceDecs_decodeSync_amd64_fill_end: + // Update offset + MOVD R8, R0 + MOVD R3, R1 + MOVD R2, R13 + LSL R1, R13, R13 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decodeSync_amd64_of_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decodeSync_amd64_of_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decodeSync_amd64_of_update_zero + NEG R1, R1 + LSR R1, R13, R13 + ADD R13, R0, R0 + +sequenceDecs_decodeSync_amd64_of_update_zero: + MOVD R0, 8(RSP) + + // Update match length + MOVD R7, R0 + MOVD R3, R1 + MOVD R2, R13 + LSL R1, R13, R13 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decodeSync_amd64_ml_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decodeSync_amd64_ml_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decodeSync_amd64_ml_update_zero + NEG R1, R1 + LSR R1, R13, R13 + ADD R13, R0, R0 + +sequenceDecs_decodeSync_amd64_ml_update_zero: + MOVD R0, 16(RSP) + + // Fill bitreader to have enough for the remaining + CMP $0x08, R5 + BLT sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte + MOVD R3, R0 + LSR $0x03, R0, R0 + SUB R0, R12, R12 + MOVD (R12), R2 + SUB R0, R5, R5 + AND $0x07, R3, R3 + JMP sequenceDecs_decodeSync_amd64_fill_2_end + +sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte: + CMP $0x00, R5 + BLE sequenceDecs_decodeSync_amd64_fill_2_check_overread + CMP $0x07, R3 + BLE sequenceDecs_decodeSync_amd64_fill_2_end + LSL $0x08, R2, R2 + SUB $0x01, R12, R12 + SUB $0x01, R5, R5 + SUB $0x08, R3, R3 + MOVBU (R12), R0 + ORR R0, R2, R2 + JMP sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte + +sequenceDecs_decodeSync_amd64_fill_2_check_overread: + CMP $0x40, R3 + BHI error_overread + +sequenceDecs_decodeSync_amd64_fill_2_end: + // Update literal length + MOVD R6, R0 + MOVD R3, R1 + MOVD R2, R13 + LSL R1, R13, R13 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decodeSync_amd64_ll_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decodeSync_amd64_ll_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decodeSync_amd64_ll_update_zero + NEG R1, R1 + LSR R1, R13, R13 + ADD R13, R0, R0 + +sequenceDecs_decodeSync_amd64_ll_update_zero: + MOVD R0, 24(RSP) + + // Fill bitreader for state updates + MOVD R12, (RSP) + MOVD R8, R0 + LSR $0x08, R0, R0 + MOVBU R0, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decodeSync_amd64_skip_update + + // Update Literal Length State + MOVBU R6, R12 + LSRW $0x10, R6, R6 + ADD R12, R3, R1 + MOVD R2, R13 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R13, R13 + MOVD $0x00000001, R14 + MOVB R12, R1 + LSLW R1, R14, R14 + SUBW $1, R14, R14 + AND R14, R13, R13 + ADD R13, R6, R6 + + // Load ctx.llTable + MOVD ctx+16(FP), R1 + MOVD (R1), R1 + ADD R6<<3, R1, R15 + MOVD (R15), R6 + + // Update Match Length State + MOVBU R7, R12 + LSRW $0x10, R7, R7 + ADD R12, R3, R1 + MOVD R2, R13 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R13, R13 + MOVD $0x00000001, R14 + MOVB R12, R1 + LSLW R1, R14, R14 + SUBW $1, R14, R14 + AND R14, R13, R13 + ADD R13, R7, R7 + + // Load ctx.mlTable + MOVD ctx+16(FP), R1 + MOVD 24(R1), R1 + ADD R7<<3, R1, R15 + MOVD (R15), R7 + + // Update Offset State + MOVBU R8, R12 + LSRW $0x10, R8, R8 + ADD R12, R3, R1 + MOVD R2, R13 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R13, R13 + MOVD $0x00000001, R14 + MOVB R12, R1 + LSLW R1, R14, R14 + SUBW $1, R14, R14 + AND R14, R13, R13 + ADD R13, R8, R8 + + // Load ctx.ofTable + MOVD ctx+16(FP), R1 + MOVD 48(R1), R1 + ADD R8<<3, R1, R15 + MOVD (R15), R8 + +sequenceDecs_decodeSync_amd64_skip_update: + // Adjust offset + MOVD s+0(FP), R1 + MOVD 8(RSP), R12 + CMP $0x01, R0 + BLS sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 + ADD $144, R1, R15 + VLD1 (R15), [V0.B16] + MOVD R12, 144(R1) + ADD $152, R1, R15 + VST1 [V0.B16], (R15) + JMP sequenceDecs_decodeSync_amd64_after_adjust + +sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0: + MOVD 24(RSP), R16 + CMP $0x00000000, R16 + BNE sequenceDecs_decodeSync_amd64_adjust_offset_maybezero + ADD $1, R12, R12 + JMP sequenceDecs_decodeSync_amd64_adjust_offset_nonzero + +sequenceDecs_decodeSync_amd64_adjust_offset_maybezero: + TST R12, R12 + BNE sequenceDecs_decodeSync_amd64_adjust_offset_nonzero + MOVD 144(R1), R12 + JMP sequenceDecs_decodeSync_amd64_after_adjust + +sequenceDecs_decodeSync_amd64_adjust_offset_nonzero: + MOVD R12, R0 + MOVD $0, R13 + MOVD $-1, R14 + CMP $0x03, R12 + CSEL EQ, R13, R0, R0 + CSEL EQ, R14, R13, R13 + ADD R0<<3, R1, R15 + MOVD 144(R15), R16 + ADDS R16, R13, R13 + BNE sequenceDecs_decodeSync_amd64_adjust_temp_valid + MOVD $0x00000001, R13 + +sequenceDecs_decodeSync_amd64_adjust_temp_valid: + CMP $0x01, R12 + BEQ sequenceDecs_decodeSync_amd64_adjust_skip + MOVD 152(R1), R0 + MOVD R0, 160(R1) + +sequenceDecs_decodeSync_amd64_adjust_skip: + MOVD 144(R1), R0 + MOVD R0, 152(R1) + MOVD R13, 144(R1) + MOVD R13, R12 + +sequenceDecs_decodeSync_amd64_after_adjust: + MOVD R12, 8(RSP) + + // Check values + MOVD 16(RSP), R0 + MOVD 24(RSP), R1 + ADD R1, R0, R13 + MOVD s+0(FP), R14 + MOVD 256(R14), R16 + ADD R13, R16, R16 + MOVD R16, 256(R14) + MOVD ctx+16(FP), R13 + MOVD 104(R13), R16 + SUBS R1, R16, R16 + MOVD R16, 104(R13) + BMI error_not_enough_literals + CMP $0x00020002, R0 + BHI sequenceDecs_decodeSync_amd64_error_match_len_too_big + TST R12, R12 + BNE sequenceDecs_decodeSync_amd64_match_len_ofs_ok + TST R0, R0 + BNE sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decodeSync_amd64_match_len_ofs_ok: + MOVD 24(RSP), R0 + MOVD 8(RSP), R1 + MOVD 16(RSP), R12 + + // Check if we have enough space in s.out + ADD R12, R0, R13 + ADD R9, R13, R13 + MOVD 32(RSP), R16 + CMP R16, R13 + BHI error_not_enough_space + + // Copy literals + TST R0, R0 + BEQ check_offset + MOVD $0, R13 + +copy_1: + ADD R13, R10, R15 + VLD1 (R15), [V0.B16] + ADD R13, R9, R15 + VST1 [V0.B16], (R15) + ADD $0x10, R13, R13 + CMP R0, R13 + BLO copy_1 + ADD R0, R10, R10 + ADD R0, R9, R9 + ADD R0, R11, R11 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + MOVD R11, R0 + MOVD 40(RSP), R16 + ADD R16, R0, R0 + CMP R0, R1 + BGT error_match_off_too_big + MOVD 56(RSP), R16 + CMP R16, R1 + BGT error_match_off_too_big + + // Copy match from history + MOVD R1, R0 + SUBS R11, R0, R0 + BLS copy_match + MOVD 48(RSP), R13 + SUB R0, R13, R13 + CMP R0, R12 + BGT copy_all_from_history + MOVD R12, R0 + SUBS $0x10, R0, R0 + BLO copy_4_small + +copy_4_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R0, R0 + BHS copy_4_loop + ADD R0, R13, R13 + ADD $16, R13, R13 + ADD R0, R9, R9 + ADD $16, R9, R9 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R9, R15 + VST1 [V0.B16], (R15) + JMP copy_4_end + +copy_4_small: + CMP $0x03, R12 + BEQ copy_4_move_3 + CMP $0x08, R12 + BLO copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVH (R13), R0 + MOVB 2(R13), R1 + MOVH R0, (R9) + MOVB R1, 2(R9) + ADD R12, R13, R13 + ADD R12, R9, R9 + JMP copy_4_end + +copy_4_move_4through7: + MOVWU (R13), R0 + ADD R12, R13, R15 + MOVWU -4(R15), R1 + MOVW R0, (R9) + ADD R12, R9, R15 + MOVW R1, -4(R15) + ADD R12, R13, R13 + ADD R12, R9, R9 + JMP copy_4_end + +copy_4_move_8through16: + MOVD (R13), R0 + ADD R12, R13, R15 + MOVD -8(R15), R1 + MOVD R0, (R9) + ADD R12, R9, R15 + MOVD R1, -8(R15) + ADD R12, R13, R13 + ADD R12, R9, R9 + +copy_4_end: + ADD R12, R11, R11 + JMP handle_loop + JMP loop_finished + +copy_all_from_history: + MOVD R0, R14 + SUBS $0x10, R14, R14 + BLO copy_5_small + +copy_5_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R9, R9 + ADD $16, R9, R9 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R9, R15 + VST1 [V0.B16], (R15) + JMP copy_5_end + +copy_5_small: + CMP $0x03, R0 + BEQ copy_5_move_3 + BLO copy_5_move_1or2 + CMP $0x08, R0 + BLO copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R13), R14 + ADD R0, R13, R15 + MOVB -1(R15), R4 + MOVB R14, (R9) + ADD R0, R9, R15 + MOVB R4, -1(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_5_end + +copy_5_move_3: + MOVH (R13), R14 + MOVB 2(R13), R4 + MOVH R14, (R9) + MOVB R4, 2(R9) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_5_end + +copy_5_move_4through7: + MOVWU (R13), R14 + ADD R0, R13, R15 + MOVWU -4(R15), R4 + MOVW R14, (R9) + ADD R0, R9, R15 + MOVW R4, -4(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_5_end + +copy_5_move_8through16: + MOVD (R13), R14 + ADD R0, R13, R15 + MOVD -8(R15), R4 + MOVD R14, (R9) + ADD R0, R9, R15 + MOVD R4, -8(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 + +copy_5_end: + ADD R0, R11, R11 + SUB R0, R12, R12 + + // Copy match from the current buffer +copy_match: + MOVD R9, R0 + SUB R1, R0, R0 + + // ml <= mo + CMP R1, R12 + BHI copy_overlapping_match + + // Copy non-overlapping match + ADD R12, R11, R11 + MOVD R9, R1 + ADD R12, R9, R9 + +copy_2: + VLD1 (R0), [V0.B16] + VST1 [V0.B16], (R1) + ADD $0x10, R0, R0 + ADD $0x10, R1, R1 + SUBS $0x10, R12, R12 + BHI copy_2 + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADD R12, R11, R11 + +copy_slow_3: + MOVB (R0), R1 + MOVB R1, (R9) + ADD $1, R0, R0 + ADD $1, R9, R9 + SUBS $1, R12, R12 + BNE copy_slow_3 + +handle_loop: + MOVD ctx+16(FP), R0 + MOVD 96(R0), R16 + SUBS $1, R16, R16 + MOVD R16, 96(R0) + BPL sequenceDecs_decodeSync_amd64_main_loop + +loop_finished: + MOVD br+8(FP), R0 + MOVD R2, 24(R0) + MOVB R3, 40(R0) + MOVD R5, 32(R0) + + // Update the context + MOVD ctx+16(FP), R0 + MOVD R11, 136(R0) + MOVD 144(R0), R1 + SUB R1, R10, R10 + MOVD R10, 168(R0) + + // Return success + MOVD $0x00000000, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: + MOVD 16(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 216(R1) + MOVD $0x00000001, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decodeSync_amd64_error_match_len_too_big: + MOVD ctx+16(FP), R0 + MOVD 16(RSP), R1 + MOVD R1, 216(R0) + MOVD $0x00000002, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match offset too long error +error_match_off_too_big: + MOVD ctx+16(FP), R0 + MOVD 8(RSP), R1 + MOVD R1, 224(R0) + MOVD R11, 136(R0) + MOVD $0x00000003, R16 + MOVD R16, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVD ctx+16(FP), R0 + MOVD 24(RSP), R1 + MOVD R1, 208(R0) + MOVD $0x00000004, R16 + MOVD R16, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVD $0x00000006, R16 + MOVD R16, ret+24(FP) + RET + + // Return with not enough output space error +error_not_enough_space: + MOVD ctx+16(FP), R0 + MOVD 24(RSP), R1 + MOVD R1, 208(R0) + MOVD 16(RSP), R1 + MOVD R1, 216(R0) + MOVD R11, 136(R0) + MOVD $0x00000005, R16 + MOVD R16, ret+24(FP) + RET + +// skipped sequenceDecs_decodeSync_bmi2 (generic twin preferred on arm64) + +// func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +// Requires: CMOV, SSE +TEXT ·sequenceDecs_decodeSync_safe_arm64(SB), $64-32 + MOVD br+8(FP), R1 + MOVD 24(R1), R2 + MOVBU 40(R1), R3 + MOVD (R1), R0 + MOVD 32(R1), R5 + ADD R5, R0, R0 + MOVD R0, (RSP) + MOVD ctx+16(FP), R0 + MOVD 72(R0), R6 + MOVD 80(R0), R7 + MOVD 88(R0), R8 + MOVD $0, R1 + MOVD R1, 8(RSP) + MOVD R1, 16(RSP) + MOVD R1, 24(RSP) + MOVD 112(R0), R9 + MOVD 128(R0), R1 + MOVD R1, 32(RSP) + MOVD 144(R0), R10 + MOVD 136(R0), R11 + MOVD 200(R0), R1 + MOVD R1, 56(RSP) + MOVD 176(R0), R1 + MOVD R1, 48(RSP) + MOVD 184(R0), R0 + MOVD R0, 40(RSP) + MOVD 40(RSP), R0 + MOVD 48(RSP), R16 + ADD R0, R16, R16 + MOVD R16, 48(RSP) + + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) + MOVD 32(RSP), R16 + ADD R9, R16, R16 + MOVD R16, 32(RSP) + + // outBase += outPosition + ADD R11, R9, R9 + +sequenceDecs_decodeSync_safe_amd64_main_loop: + MOVD (RSP), R12 + + // Fill bitreader to have enough for the offset and match length. + CMP $0x08, R5 + BLT sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte + MOVD R3, R0 + LSR $0x03, R0, R0 + SUB R0, R12, R12 + MOVD (R12), R2 + SUB R0, R5, R5 + AND $0x07, R3, R3 + JMP sequenceDecs_decodeSync_safe_amd64_fill_end + +sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte: + CMP $0x00, R5 + BLE sequenceDecs_decodeSync_safe_amd64_fill_check_overread + CMP $0x07, R3 + BLE sequenceDecs_decodeSync_safe_amd64_fill_end + LSL $0x08, R2, R2 + SUB $0x01, R12, R12 + SUB $0x01, R5, R5 + SUB $0x08, R3, R3 + MOVBU (R12), R0 + ORR R0, R2, R2 + JMP sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte + +sequenceDecs_decodeSync_safe_amd64_fill_check_overread: + CMP $0x40, R3 + BHI error_overread + +sequenceDecs_decodeSync_safe_amd64_fill_end: + // Update offset + MOVD R8, R0 + MOVD R3, R1 + MOVD R2, R13 + LSL R1, R13, R13 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decodeSync_safe_amd64_of_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decodeSync_safe_amd64_of_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decodeSync_safe_amd64_of_update_zero + NEG R1, R1 + LSR R1, R13, R13 + ADD R13, R0, R0 + +sequenceDecs_decodeSync_safe_amd64_of_update_zero: + MOVD R0, 8(RSP) + + // Update match length + MOVD R7, R0 + MOVD R3, R1 + MOVD R2, R13 + LSL R1, R13, R13 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decodeSync_safe_amd64_ml_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decodeSync_safe_amd64_ml_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decodeSync_safe_amd64_ml_update_zero + NEG R1, R1 + LSR R1, R13, R13 + ADD R13, R0, R0 + +sequenceDecs_decodeSync_safe_amd64_ml_update_zero: + MOVD R0, 16(RSP) + + // Fill bitreader to have enough for the remaining + CMP $0x08, R5 + BLT sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte + MOVD R3, R0 + LSR $0x03, R0, R0 + SUB R0, R12, R12 + MOVD (R12), R2 + SUB R0, R5, R5 + AND $0x07, R3, R3 + JMP sequenceDecs_decodeSync_safe_amd64_fill_2_end + +sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte: + CMP $0x00, R5 + BLE sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread + CMP $0x07, R3 + BLE sequenceDecs_decodeSync_safe_amd64_fill_2_end + LSL $0x08, R2, R2 + SUB $0x01, R12, R12 + SUB $0x01, R5, R5 + SUB $0x08, R3, R3 + MOVBU (R12), R0 + ORR R0, R2, R2 + JMP sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte + +sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread: + CMP $0x40, R3 + BHI error_overread + +sequenceDecs_decodeSync_safe_amd64_fill_2_end: + // Update literal length + MOVD R6, R0 + MOVD R3, R1 + MOVD R2, R13 + LSL R1, R13, R13 + UBFX $8, R0, $8, R1 + LSR $0x20, R0, R0 + TST R1, R1 + BEQ sequenceDecs_decodeSync_safe_amd64_ll_update_zero + ADD R1, R3, R3 + CMP $0x40, R3 + BHI sequenceDecs_decodeSync_safe_amd64_ll_update_zero + CMP $0x40, R1 + BHS sequenceDecs_decodeSync_safe_amd64_ll_update_zero + NEG R1, R1 + LSR R1, R13, R13 + ADD R13, R0, R0 + +sequenceDecs_decodeSync_safe_amd64_ll_update_zero: + MOVD R0, 24(RSP) + + // Fill bitreader for state updates + MOVD R12, (RSP) + MOVD R8, R0 + LSR $0x08, R0, R0 + MOVBU R0, R0 + MOVD ctx+16(FP), R1 + MOVD 96(R1), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decodeSync_safe_amd64_skip_update + + // Update Literal Length State + MOVBU R6, R12 + LSRW $0x10, R6, R6 + ADD R12, R3, R1 + MOVD R2, R13 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R13, R13 + MOVD $0x00000001, R14 + MOVB R12, R1 + LSLW R1, R14, R14 + SUBW $1, R14, R14 + AND R14, R13, R13 + ADD R13, R6, R6 + + // Load ctx.llTable + MOVD ctx+16(FP), R1 + MOVD (R1), R1 + ADD R6<<3, R1, R15 + MOVD (R15), R6 + + // Update Match Length State + MOVBU R7, R12 + LSRW $0x10, R7, R7 + ADD R12, R3, R1 + MOVD R2, R13 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R13, R13 + MOVD $0x00000001, R14 + MOVB R12, R1 + LSLW R1, R14, R14 + SUBW $1, R14, R14 + AND R14, R13, R13 + ADD R13, R7, R7 + + // Load ctx.mlTable + MOVD ctx+16(FP), R1 + MOVD 24(R1), R1 + ADD R7<<3, R1, R15 + MOVD (R15), R7 + + // Update Offset State + MOVBU R8, R12 + LSRW $0x10, R8, R8 + ADD R12, R3, R1 + MOVD R2, R13 + MOVD R1, R3 + NEG R1, R16 + ROR R16, R13, R13 + MOVD $0x00000001, R14 + MOVB R12, R1 + LSLW R1, R14, R14 + SUBW $1, R14, R14 + AND R14, R13, R13 + ADD R13, R8, R8 + + // Load ctx.ofTable + MOVD ctx+16(FP), R1 + MOVD 48(R1), R1 + ADD R8<<3, R1, R15 + MOVD (R15), R8 + +sequenceDecs_decodeSync_safe_amd64_skip_update: + // Adjust offset + MOVD s+0(FP), R1 + MOVD 8(RSP), R12 + CMP $0x01, R0 + BLS sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 + ADD $144, R1, R15 + VLD1 (R15), [V0.B16] + MOVD R12, 144(R1) + ADD $152, R1, R15 + VST1 [V0.B16], (R15) + JMP sequenceDecs_decodeSync_safe_amd64_after_adjust + +sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0: + MOVD 24(RSP), R16 + CMP $0x00000000, R16 + BNE sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero + ADD $1, R12, R12 + JMP sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero + +sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero: + TST R12, R12 + BNE sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero + MOVD 144(R1), R12 + JMP sequenceDecs_decodeSync_safe_amd64_after_adjust + +sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero: + MOVD R12, R0 + MOVD $0, R13 + MOVD $-1, R14 + CMP $0x03, R12 + CSEL EQ, R13, R0, R0 + CSEL EQ, R14, R13, R13 + ADD R0<<3, R1, R15 + MOVD 144(R15), R16 + ADDS R16, R13, R13 + BNE sequenceDecs_decodeSync_safe_amd64_adjust_temp_valid + MOVD $0x00000001, R13 + +sequenceDecs_decodeSync_safe_amd64_adjust_temp_valid: + CMP $0x01, R12 + BEQ sequenceDecs_decodeSync_safe_amd64_adjust_skip + MOVD 152(R1), R0 + MOVD R0, 160(R1) + +sequenceDecs_decodeSync_safe_amd64_adjust_skip: + MOVD 144(R1), R0 + MOVD R0, 152(R1) + MOVD R13, 144(R1) + MOVD R13, R12 + +sequenceDecs_decodeSync_safe_amd64_after_adjust: + MOVD R12, 8(RSP) + + // Check values + MOVD 16(RSP), R0 + MOVD 24(RSP), R1 + ADD R1, R0, R13 + MOVD s+0(FP), R14 + MOVD 256(R14), R16 + ADD R13, R16, R16 + MOVD R16, 256(R14) + MOVD ctx+16(FP), R13 + MOVD 104(R13), R16 + SUBS R1, R16, R16 + MOVD R16, 104(R13) + BMI error_not_enough_literals + CMP $0x00020002, R0 + BHI sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big + TST R12, R12 + BNE sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok + TST R0, R0 + BNE sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok: + MOVD 24(RSP), R0 + MOVD 8(RSP), R1 + MOVD 16(RSP), R12 + + // Check if we have enough space in s.out + ADD R12, R0, R13 + ADD R9, R13, R13 + MOVD 32(RSP), R16 + CMP R16, R13 + BHI error_not_enough_space + + // Copy literals + TST R0, R0 + BEQ check_offset + MOVD R0, R13 + SUBS $0x10, R13, R13 + BLO copy_1_small + +copy_1_loop: + VLD1 (R10), [V0.B16] + VST1 [V0.B16], (R9) + ADD $0x10, R10, R10 + ADD $0x10, R9, R9 + SUBS $0x10, R13, R13 + BHS copy_1_loop + ADD R13, R10, R10 + ADD $16, R10, R10 + ADD R13, R9, R9 + ADD $16, R9, R9 + ADD $-16, R10, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R9, R15 + VST1 [V0.B16], (R15) + JMP copy_1_end + +copy_1_small: + CMP $0x03, R0 + BEQ copy_1_move_3 + BLO copy_1_move_1or2 + CMP $0x08, R0 + BLO copy_1_move_4through7 + JMP copy_1_move_8through16 + +copy_1_move_1or2: + MOVB (R10), R13 + ADD R0, R10, R15 + MOVB -1(R15), R14 + MOVB R13, (R9) + ADD R0, R9, R15 + MOVB R14, -1(R15) + ADD R0, R10, R10 + ADD R0, R9, R9 + JMP copy_1_end + +copy_1_move_3: + MOVH (R10), R13 + MOVB 2(R10), R14 + MOVH R13, (R9) + MOVB R14, 2(R9) + ADD R0, R10, R10 + ADD R0, R9, R9 + JMP copy_1_end + +copy_1_move_4through7: + MOVWU (R10), R13 + ADD R0, R10, R15 + MOVWU -4(R15), R14 + MOVW R13, (R9) + ADD R0, R9, R15 + MOVW R14, -4(R15) + ADD R0, R10, R10 + ADD R0, R9, R9 + JMP copy_1_end + +copy_1_move_8through16: + MOVD (R10), R13 + ADD R0, R10, R15 + MOVD -8(R15), R14 + MOVD R13, (R9) + ADD R0, R9, R15 + MOVD R14, -8(R15) + ADD R0, R10, R10 + ADD R0, R9, R9 + +copy_1_end: + ADD R0, R11, R11 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + MOVD R11, R0 + MOVD 40(RSP), R16 + ADD R16, R0, R0 + CMP R0, R1 + BGT error_match_off_too_big + MOVD 56(RSP), R16 + CMP R16, R1 + BGT error_match_off_too_big + + // Copy match from history + MOVD R1, R0 + SUBS R11, R0, R0 + BLS copy_match + MOVD 48(RSP), R13 + SUB R0, R13, R13 + CMP R0, R12 + BGT copy_all_from_history + MOVD R12, R0 + SUBS $0x10, R0, R0 + BLO copy_4_small + +copy_4_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R0, R0 + BHS copy_4_loop + ADD R0, R13, R13 + ADD $16, R13, R13 + ADD R0, R9, R9 + ADD $16, R9, R9 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R9, R15 + VST1 [V0.B16], (R15) + JMP copy_4_end + +copy_4_small: + CMP $0x03, R12 + BEQ copy_4_move_3 + CMP $0x08, R12 + BLO copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVH (R13), R0 + MOVB 2(R13), R1 + MOVH R0, (R9) + MOVB R1, 2(R9) + ADD R12, R13, R13 + ADD R12, R9, R9 + JMP copy_4_end + +copy_4_move_4through7: + MOVWU (R13), R0 + ADD R12, R13, R15 + MOVWU -4(R15), R1 + MOVW R0, (R9) + ADD R12, R9, R15 + MOVW R1, -4(R15) + ADD R12, R13, R13 + ADD R12, R9, R9 + JMP copy_4_end + +copy_4_move_8through16: + MOVD (R13), R0 + ADD R12, R13, R15 + MOVD -8(R15), R1 + MOVD R0, (R9) + ADD R12, R9, R15 + MOVD R1, -8(R15) + ADD R12, R13, R13 + ADD R12, R9, R9 + +copy_4_end: + ADD R12, R11, R11 + JMP handle_loop + JMP loop_finished + +copy_all_from_history: + MOVD R0, R14 + SUBS $0x10, R14, R14 + BLO copy_5_small + +copy_5_loop: + VLD1 (R13), [V0.B16] + VST1 [V0.B16], (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R9, R9 + ADD $16, R9, R9 + ADD $-16, R13, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R9, R15 + VST1 [V0.B16], (R15) + JMP copy_5_end + +copy_5_small: + CMP $0x03, R0 + BEQ copy_5_move_3 + BLO copy_5_move_1or2 + CMP $0x08, R0 + BLO copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R13), R14 + ADD R0, R13, R15 + MOVB -1(R15), R4 + MOVB R14, (R9) + ADD R0, R9, R15 + MOVB R4, -1(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_5_end + +copy_5_move_3: + MOVH (R13), R14 + MOVB 2(R13), R4 + MOVH R14, (R9) + MOVB R4, 2(R9) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_5_end + +copy_5_move_4through7: + MOVWU (R13), R14 + ADD R0, R13, R15 + MOVWU -4(R15), R4 + MOVW R14, (R9) + ADD R0, R9, R15 + MOVW R4, -4(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_5_end + +copy_5_move_8through16: + MOVD (R13), R14 + ADD R0, R13, R15 + MOVD -8(R15), R4 + MOVD R14, (R9) + ADD R0, R9, R15 + MOVD R4, -8(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 + +copy_5_end: + ADD R0, R11, R11 + SUB R0, R12, R12 + + // Copy match from the current buffer +copy_match: + MOVD R9, R0 + SUB R1, R0, R0 + + // ml <= mo + CMP R1, R12 + BHI copy_overlapping_match + + // Copy non-overlapping match + ADD R12, R11, R11 + MOVD R12, R1 + SUBS $0x10, R1, R1 + BLO copy_2_small + +copy_2_loop: + VLD1 (R0), [V0.B16] + VST1 [V0.B16], (R9) + ADD $0x10, R0, R0 + ADD $0x10, R9, R9 + SUBS $0x10, R1, R1 + BHS copy_2_loop + ADD R1, R0, R0 + ADD $16, R0, R0 + ADD R1, R9, R9 + ADD $16, R9, R9 + ADD $-16, R0, R15 + VLD1 (R15), [V0.B16] + ADD $-16, R9, R15 + VST1 [V0.B16], (R15) + JMP copy_2_end + +copy_2_small: + CMP $0x03, R12 + BEQ copy_2_move_3 + BLO copy_2_move_1or2 + CMP $0x08, R12 + BLO copy_2_move_4through7 + JMP copy_2_move_8through16 + +copy_2_move_1or2: + MOVB (R0), R1 + ADD R12, R0, R15 + MOVB -1(R15), R13 + MOVB R1, (R9) + ADD R12, R9, R15 + MOVB R13, -1(R15) + ADD R12, R0, R0 + ADD R12, R9, R9 + JMP copy_2_end + +copy_2_move_3: + MOVH (R0), R1 + MOVB 2(R0), R13 + MOVH R1, (R9) + MOVB R13, 2(R9) + ADD R12, R0, R0 + ADD R12, R9, R9 + JMP copy_2_end + +copy_2_move_4through7: + MOVWU (R0), R1 + ADD R12, R0, R15 + MOVWU -4(R15), R13 + MOVW R1, (R9) + ADD R12, R9, R15 + MOVW R13, -4(R15) + ADD R12, R0, R0 + ADD R12, R9, R9 + JMP copy_2_end + +copy_2_move_8through16: + MOVD (R0), R1 + ADD R12, R0, R15 + MOVD -8(R15), R13 + MOVD R1, (R9) + ADD R12, R9, R15 + MOVD R13, -8(R15) + ADD R12, R0, R0 + ADD R12, R9, R9 + +copy_2_end: + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADD R12, R11, R11 + +copy_slow_3: + MOVB (R0), R1 + MOVB R1, (R9) + ADD $1, R0, R0 + ADD $1, R9, R9 + SUBS $1, R12, R12 + BNE copy_slow_3 + +handle_loop: + MOVD ctx+16(FP), R0 + MOVD 96(R0), R16 + SUBS $1, R16, R16 + MOVD R16, 96(R0) + BPL sequenceDecs_decodeSync_safe_amd64_main_loop + +loop_finished: + MOVD br+8(FP), R0 + MOVD R2, 24(R0) + MOVB R3, 40(R0) + MOVD R5, 32(R0) + + // Update the context + MOVD ctx+16(FP), R0 + MOVD R11, 136(R0) + MOVD 144(R0), R1 + SUB R1, R10, R10 + MOVD R10, 168(R0) + + // Return success + MOVD $0x00000000, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: + MOVD 16(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 216(R1) + MOVD $0x00000001, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: + MOVD ctx+16(FP), R0 + MOVD 16(RSP), R1 + MOVD R1, 216(R0) + MOVD $0x00000002, R16 + MOVD R16, ret+24(FP) + RET + + // Return with match offset too long error +error_match_off_too_big: + MOVD ctx+16(FP), R0 + MOVD 8(RSP), R1 + MOVD R1, 224(R0) + MOVD R11, 136(R0) + MOVD $0x00000003, R16 + MOVD R16, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVD ctx+16(FP), R0 + MOVD 24(RSP), R1 + MOVD R1, 208(R0) + MOVD $0x00000004, R16 + MOVD R16, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVD $0x00000006, R16 + MOVD R16, ret+24(FP) + RET + + // Return with not enough output space error +error_not_enough_space: + MOVD ctx+16(FP), R0 + MOVD 24(RSP), R1 + MOVD R1, 208(R0) + MOVD 16(RSP), R1 + MOVD R1, 216(R0) + MOVD R11, 136(R0) + MOVD $0x00000005, R16 + MOVD R16, ret+24(FP) + RET + +// skipped sequenceDecs_decodeSync_safe_bmi2 (generic twin preferred on arm64) diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go b/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go new file mode 100644 index 00000000000..55405f3914d --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go @@ -0,0 +1,289 @@ +//go:build (amd64 || arm64) && !appengine && !noasm && gc + +package zstd + +import ( + "fmt" + "io" +) + +// This file holds the parts of the assembly sequence decoder that are identical +// across architectures: the context structs exchanged with the asm, the error +// codes, and the decode/decodeSync/executeSimple wrappers. Each architecture +// supplies the small dispatch helpers (decodeAsm, decodeSyncAsm, +// executeSimpleAsm) that select the concrete asm routine — amd64 also chooses a +// BMI2 variant, arm64 has a single implementation. + +type decodeSyncAsmContext struct { + llTable []decSymbol + mlTable []decSymbol + ofTable []decSymbol + llState uint64 + mlState uint64 + ofState uint64 + iteration int + litRemain int + out []byte + outPosition int + literals []byte + litPosition int + history []byte + windowSize int + ll int // set on error (not for all errors, please refer to _generate/gen.go) + ml int // set on error (not for all errors, please refer to _generate/gen.go) + mo int // set on error (not for all errors, please refer to _generate/gen.go) +} + +type decodeAsmContext struct { + llTable []decSymbol + mlTable []decSymbol + ofTable []decSymbol + llState uint64 + mlState uint64 + ofState uint64 + iteration int + seqs []seqVals + litRemain int +} + +type executeAsmContext struct { + seqs []seqVals + seqIndex int + out []byte + history []byte + literals []byte + outPosition int + litPosition int + windowSize int +} + +const noError = 0 + +// error reported when mo == 0 && ml > 0 +const errorMatchLenOfsMismatch = 1 + +// error reported when ml > maxMatchLen +const errorMatchLenTooBig = 2 + +// error reported when mo > available history or mo > s.windowSize +const errorMatchOffTooBig = 3 + +// error reported when the sum of literal lengths exeeceds the literal buffer size +const errorNotEnoughLiterals = 4 + +// error reported when capacity of `out` is too small +const errorNotEnoughSpace = 5 + +// error reported when bits are overread. +const errorOverread = 6 + +// decode sequences from the stream with the provided history but without a dictionary. +func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { + if len(s.dict) > 0 { + return false, nil + } + if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSize { + return false, nil + } + + // FIXME: Using unsafe memory copies leads to rare, random crashes + // with fuzz testing. It is therefore disabled for now. + const useSafe = true + + br := s.br + + maxBlockSize := min(s.windowSize, maxCompressedBlockSize) + + ctx := decodeSyncAsmContext{ + llTable: s.litLengths.fse.dt[:maxTablesize], + mlTable: s.matchLengths.fse.dt[:maxTablesize], + ofTable: s.offsets.fse.dt[:maxTablesize], + llState: uint64(s.litLengths.state.state), + mlState: uint64(s.matchLengths.state.state), + ofState: uint64(s.offsets.state.state), + iteration: s.nSeqs - 1, + litRemain: len(s.literals), + out: s.out, + outPosition: len(s.out), + literals: s.literals, + windowSize: s.windowSize, + history: hist, + } + + s.seqSize = 0 + startSize := len(s.out) + + errCode := decodeSyncAsm(s, br, &ctx, useSafe) + switch errCode { + case noError: + break + + case errorMatchLenOfsMismatch: + return true, fmt.Errorf("zero matchoff and matchlen (%d) > 0", ctx.ml) + + case errorMatchLenTooBig: + return true, fmt.Errorf("match len (%d) bigger than max allowed length", ctx.ml) + + case errorMatchOffTooBig: + return true, fmt.Errorf("match offset (%d) bigger than current history (%d)", + ctx.mo, ctx.outPosition+len(hist)-startSize) + + case errorNotEnoughLiterals: + return true, fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", + ctx.ll, ctx.litRemain+ctx.ll) + + case errorOverread: + return true, io.ErrUnexpectedEOF + + case errorNotEnoughSpace: + size := ctx.outPosition + ctx.ll + ctx.ml + if debugDecoder { + println("msl:", s.maxSyncLen, "cap", cap(s.out), "bef:", startSize, "sz:", size-startSize, "mbs:", maxBlockSize, "outsz:", cap(s.out)-startSize) + } + return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + + default: + return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode) + } + + s.seqSize += ctx.litRemain + if s.seqSize > maxBlockSize { + return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + err := br.close() + if err != nil { + printf("Closing sequences: %v, %+v\n", err, *br) + return true, err + } + + s.literals = s.literals[ctx.litPosition:] + t := ctx.outPosition + s.out = s.out[:t] + + // Add final literals + s.out = append(s.out, s.literals...) + if debugDecoder { + t += len(s.literals) + if t != len(s.out) { + panic(fmt.Errorf("length mismatch, want %d, got %d", len(s.out), t)) + } + } + + return true, nil +} + +// decode sequences from the stream without the provided history. +func (s *sequenceDecs) decode(seqs []seqVals) error { + br := s.br + + maxBlockSize := min(s.windowSize, maxCompressedBlockSize) + + ctx := decodeAsmContext{ + llTable: s.litLengths.fse.dt[:maxTablesize], + mlTable: s.matchLengths.fse.dt[:maxTablesize], + ofTable: s.offsets.fse.dt[:maxTablesize], + llState: uint64(s.litLengths.state.state), + mlState: uint64(s.matchLengths.state.state), + ofState: uint64(s.offsets.state.state), + seqs: seqs, + iteration: len(seqs) - 1, + litRemain: len(s.literals), + } + + if debugDecoder { + println("decode: decoding", len(seqs), "sequences", br.remain(), "bits remain on stream") + } + + s.seqSize = 0 + lte56bits := s.maxBits+s.offsets.fse.actualTableLog+s.matchLengths.fse.actualTableLog+s.litLengths.fse.actualTableLog <= 56 + errCode := decodeAsm(s, br, &ctx, lte56bits) + if errCode != 0 { + i := len(seqs) - ctx.iteration - 1 + switch errCode { + case errorMatchLenOfsMismatch: + ml := ctx.seqs[i].ml + return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml) + + case errorMatchLenTooBig: + ml := ctx.seqs[i].ml + return fmt.Errorf("match len (%d) bigger than max allowed length", ml) + + case errorNotEnoughLiterals: + ll := ctx.seqs[i].ll + return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, ctx.litRemain+ll) + case errorOverread: + return io.ErrUnexpectedEOF + } + + return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode) + } + + if ctx.litRemain < 0 { + return fmt.Errorf("literal count is too big: total available %d, total requested %d", + len(s.literals), len(s.literals)-ctx.litRemain) + } + + s.seqSize += ctx.litRemain + if s.seqSize > maxBlockSize { + return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + if debugDecoder { + println("decode: ", br.remain(), "bits remain on stream. code:", errCode) + } + err := br.close() + if err != nil { + printf("Closing sequences: %v, %+v\n", err, *br) + } + return err +} + +// executeSimple handles cases when dictionary is not used. +func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error { + // Ensure we have enough output size... + if len(s.out)+s.seqSize+compressedBlockOverAlloc > cap(s.out) { + addBytes := s.seqSize + len(s.out) + compressedBlockOverAlloc + s.out = append(s.out, make([]byte, addBytes)...) + s.out = s.out[:len(s.out)-addBytes] + } + + if debugDecoder { + printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize) + } + + var t = len(s.out) + out := s.out[:t+s.seqSize] + + ctx := executeAsmContext{ + seqs: seqs, + seqIndex: 0, + out: out, + history: hist, + outPosition: t, + litPosition: 0, + literals: s.literals, + windowSize: s.windowSize, + } + // useSafe avoids overwriting the output buffer when the literals slice has + // not been allocated with the required over-allocation slack. + useSafe := cap(s.literals) < len(s.literals)+compressedBlockOverAlloc + + ok := executeSimpleAsm(&ctx, useSafe) + if !ok { + return fmt.Errorf("match offset (%d) bigger than current history (%d)", + seqs[ctx.seqIndex].mo, ctx.outPosition+len(hist)) + } + s.literals = s.literals[ctx.litPosition:] + t = ctx.outPosition + + // Add final literals + copy(out[t:], s.literals) + if debugDecoder { + t += len(s.literals) + if t != len(out) { + panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize)) + } + } + s.out = out + + return nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_generic.go b/vendor/github.com/klauspost/compress/zstd/seqdec_generic.go index 516cd9b0701..8a3db6ba22f 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_generic.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_generic.go @@ -1,4 +1,4 @@ -//go:build !amd64 || appengine || !gc || noasm +//go:build (!amd64 && !arm64) || appengine || !gc || noasm package zstd diff --git a/vendor/github.com/klauspost/compress/zstd/snappy.go b/vendor/github.com/klauspost/compress/zstd/snappy.go index 336c2889304..36c56f36d77 100644 --- a/vendor/github.com/klauspost/compress/zstd/snappy.go +++ b/vendor/github.com/klauspost/compress/zstd/snappy.go @@ -334,9 +334,10 @@ func decodeSnappy(blk *blockEnc, src []byte) error { return errUnsupportedLiteralLength } - //if length > snappyMaxBlockSize-d || uint32(length) > len(src)-s { - // return ErrSnappyCorrupt - //} + if length > len(src)-s { + println("length > len(src)-s", length, len(src)-s) + return ErrSnappyCorrupt + } blk.literals = append(blk.literals, src[s:s+length]...) //println(length, "litLen") diff --git a/vendor/github.com/mdlayher/socket/.golangci.yml b/vendor/github.com/mdlayher/socket/.golangci.yml new file mode 100644 index 00000000000..1f10166aabe --- /dev/null +++ b/vendor/github.com/mdlayher/socket/.golangci.yml @@ -0,0 +1,16 @@ +version: "2" +linters: + enable: + - misspell + - modernize + - revive + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling +formatters: + exclusions: + generated: lax diff --git a/vendor/github.com/mdlayher/socket/CHANGELOG.md b/vendor/github.com/mdlayher/socket/CHANGELOG.md index b83418532d0..b94818e7cad 100644 --- a/vendor/github.com/mdlayher/socket/CHANGELOG.md +++ b/vendor/github.com/mdlayher/socket/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## v0.5.2 + +- [Improvement]: Bump build to Go 1.23.0. Note this is required for the latest + Go extended library versions. + ## v0.5.1 - [Improvement]: revert `go.mod` to Go 1.20 to [resolve an issue around Go diff --git a/vendor/github.com/mdlayher/socket/accept4.go b/vendor/github.com/mdlayher/socket/accept4.go index e1016b2063d..48be812ed85 100644 --- a/vendor/github.com/mdlayher/socket/accept4.go +++ b/vendor/github.com/mdlayher/socket/accept4.go @@ -1,5 +1,4 @@ //go:build dragonfly || freebsd || illumos || linux -// +build dragonfly freebsd illumos linux package socket diff --git a/vendor/github.com/mdlayher/socket/conn.go b/vendor/github.com/mdlayher/socket/conn.go index 5be502f5a21..6057a2e0a82 100644 --- a/vendor/github.com/mdlayher/socket/conn.go +++ b/vendor/github.com/mdlayher/socket/conn.go @@ -120,7 +120,7 @@ func (c *Conn) ReadContext(ctx context.Context, b []byte) (int, error) { b = b[:maxRW] } - n, err := readT(c, ctx, "read", func(fd int) (int, error) { + n, err := readT(ctx, c, "read", func(fd int) (int, error) { return unix.Read(fd, b) }) if n == 0 && err == nil && c.facts.zeroReadIsEOF { @@ -142,12 +142,12 @@ func (c *Conn) WriteContext(ctx context.Context, b []byte) (int, error) { ) doErr := c.write(ctx, "write", func(fd int) error { - max := len(b) - if c.facts.isStream && max-nn > maxRW { - max = nn + maxRW + lenb := len(b) + if c.facts.isStream && lenb-nn > maxRW { + lenb = nn + maxRW } - n, err = unix.Write(fd, b[nn:max]) + n, err = unix.Write(fd, b[nn:lenb]) if n > 0 { nn += n } @@ -418,7 +418,7 @@ func (c *Conn) Accept(ctx context.Context, flags int) (*Conn, unix.Sockaddr, err sa unix.Sockaddr } - r, err := readT(c, ctx, sysAccept, func(fd int) (ret, error) { + r, err := readT(ctx, c, sysAccept, func(fd int) (ret, error) { // Either accept(2) or accept4(2) depending on the OS. nfd, sa, err := accept(fd, flags|socketFlags) return ret{nfd, sa}, err @@ -464,7 +464,7 @@ func (c *Conn) Connect(ctx context.Context, sa unix.Sockaddr) (unix.Sockaddr, er // have an explicit WaitWrite call like internal/poll does, so we have // to wait until the runtime calls the closure again to indicate we can // write. - progress uint32 + progress atomic.Uint32 // Capture closure sockaddr and error. rsa unix.Sockaddr @@ -472,7 +472,7 @@ func (c *Conn) Connect(ctx context.Context, sa unix.Sockaddr) (unix.Sockaddr, er ) doErr := c.write(ctx, op, func(fd int) error { - if atomic.AddUint32(&progress, 1) == 1 { + if progress.Add(1) == 1 { // First call: initiate connect. return unix.Connect(fd, sa) } @@ -569,7 +569,7 @@ func (c *Conn) Recvmsg(ctx context.Context, p, oob []byte, flags int) (int, int, from unix.Sockaddr } - r, err := readT(c, ctx, "recvmsg", func(fd int) (ret, error) { + r, err := readT(ctx, c, "recvmsg", func(fd int) (ret, error) { n, oobn, recvflags, from, err := unix.Recvmsg(fd, p, oob, flags) return ret{n, oobn, recvflags, from}, err }) @@ -587,7 +587,7 @@ func (c *Conn) Recvfrom(ctx context.Context, p []byte, flags int) (int, unix.Soc addr unix.Sockaddr } - out, err := readT(c, ctx, "recvfrom", func(fd int) (ret, error) { + out, err := readT(ctx, c, "recvfrom", func(fd int) (ret, error) { n, addr, err := unix.Recvfrom(fd, p, flags) return ret{n, addr}, err }) @@ -600,7 +600,7 @@ func (c *Conn) Recvfrom(ctx context.Context, p []byte, flags int) (int, unix.Soc // Sendmsg wraps sendmsg(2). func (c *Conn) Sendmsg(ctx context.Context, p, oob []byte, to unix.Sockaddr, flags int) (int, error) { - return writeT(c, ctx, "sendmsg", func(fd int) (int, error) { + return writeT(ctx, c, "sendmsg", func(fd int) (int, error) { return unix.SendmsgN(fd, p, oob, to, flags) }) } @@ -645,7 +645,7 @@ func (c *Conn) Shutdown(how int) error { // read wraps readT to execute a function and capture its error result. This is // a convenience wrapper for functions which don't return any extra values. func (c *Conn) read(ctx context.Context, op string, f func(fd int) error) error { - _, err := readT(c, ctx, op, func(fd int) (struct{}, error) { + _, err := readT(ctx, c, op, func(fd int) (struct{}, error) { return struct{}{}, f(fd) }) return err @@ -654,7 +654,7 @@ func (c *Conn) read(ctx context.Context, op string, f func(fd int) error) error // write executes f, a write function, against the associated file descriptor. // op is used to create an *os.SyscallError if the file descriptor is closed. func (c *Conn) write(ctx context.Context, op string, f func(fd int) error) error { - _, err := writeT(c, ctx, op, func(fd int) (struct{}, error) { + _, err := writeT(ctx, c, op, func(fd int) (struct{}, error) { return struct{}{}, f(fd) }) return err @@ -662,7 +662,7 @@ func (c *Conn) write(ctx context.Context, op string, f func(fd int) error) error // readT executes c.rc.Read for op using the input function, returning a newly // allocated result T. -func readT[T any](c *Conn, ctx context.Context, op string, f func(fd int) (T, error)) (T, error) { +func readT[T any](ctx context.Context, c *Conn, op string, f func(fd int) (T, error)) (T, error) { return rwT(c, rwContext[T]{ Context: ctx, Type: read, @@ -673,7 +673,7 @@ func readT[T any](c *Conn, ctx context.Context, op string, f func(fd int) (T, er // writeT executes c.rc.Write for op using the input function, returning a newly // allocated result T. -func writeT[T any](c *Conn, ctx context.Context, op string, f func(fd int) (T, error)) (T, error) { +func writeT[T any](ctx context.Context, c *Conn, op string, f func(fd int) (T, error)) (T, error) { return rwT(c, rwContext[T]{ Context: ctx, Type: write, @@ -771,9 +771,7 @@ func rwT[T any](c *Conn, rw rwContext[T]) (T, error) { // // TODO(mdlayher): is it possible to detect a background context vs a // context with possible future cancel? - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { select { case <-rw.Context.Done(): @@ -784,7 +782,7 @@ func rwT[T any](c *Conn, rw rwContext[T]) (T, error) { case <-doneC: // Nothing to do. } - }() + }) } var ( diff --git a/vendor/github.com/mdlayher/socket/conn_linux.go b/vendor/github.com/mdlayher/socket/conn_linux.go index 081194f327c..b1cdffbdc67 100644 --- a/vendor/github.com/mdlayher/socket/conn_linux.go +++ b/vendor/github.com/mdlayher/socket/conn_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package socket diff --git a/vendor/github.com/mdlayher/socket/netns_linux.go b/vendor/github.com/mdlayher/socket/netns_linux.go index b29115ad1cf..9f37b77029f 100644 --- a/vendor/github.com/mdlayher/socket/netns_linux.go +++ b/vendor/github.com/mdlayher/socket/netns_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package socket @@ -65,7 +64,7 @@ func withNetNS(fd int, fn func() (*Conn, error)) (*Conn, error) { // No more thread-local state manipulation; return the new Conn. runtime.UnlockOSThread() conn = c - return nil + return err }) if err := eg.Wait(); err != nil { diff --git a/vendor/github.com/mdlayher/socket/setbuffer_linux.go b/vendor/github.com/mdlayher/socket/setbuffer_linux.go index 0d4aa4417c1..ae631893a69 100644 --- a/vendor/github.com/mdlayher/socket/setbuffer_linux.go +++ b/vendor/github.com/mdlayher/socket/setbuffer_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package socket diff --git a/vendor/github.com/mdlayher/socket/typ_cloexec_nonblock.go b/vendor/github.com/mdlayher/socket/typ_cloexec_nonblock.go index 40e834310b7..f4a7e559b3c 100644 --- a/vendor/github.com/mdlayher/socket/typ_cloexec_nonblock.go +++ b/vendor/github.com/mdlayher/socket/typ_cloexec_nonblock.go @@ -1,5 +1,4 @@ //go:build !darwin -// +build !darwin package socket diff --git a/vendor/github.com/mdlayher/vsock/.golangci.yml b/vendor/github.com/mdlayher/vsock/.golangci.yml new file mode 100644 index 00000000000..7237e2714da --- /dev/null +++ b/vendor/github.com/mdlayher/vsock/.golangci.yml @@ -0,0 +1,21 @@ +version: "2" +linters: + enable: + # - errorlint + - misspell + - modernize + - revive + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - errcheck + path: _test.go +formatters: + exclusions: + generated: lax diff --git a/vendor/github.com/mdlayher/vsock/CHANGELOG.md b/vendor/github.com/mdlayher/vsock/CHANGELOG.md index c64a797bc22..aae74863511 100644 --- a/vendor/github.com/mdlayher/vsock/CHANGELOG.md +++ b/vendor/github.com/mdlayher/vsock/CHANGELOG.md @@ -1,10 +1,16 @@ # CHANGELOG -# v1.2.1 +## v1.3.0 + +- [Improvement]: Updated dependencies and now requires Go 1.25. (#63) +- [Improvement]: Update to use net.ErrClosed error (#57) +- [Tests]: Check for ENETUNREACH and ETIMEDOUT in tests (#54) + +## v1.2.1 - [Improvement]: updated dependencies, test with Go 1.20. -# v1.2.0 +## v1.2.0 **This is the first release of package vsock that only supports Go 1.18+. Users on older versions of Go must use v1.1.1.** diff --git a/vendor/github.com/mdlayher/vsock/conn_linux.go b/vendor/github.com/mdlayher/vsock/conn_linux.go index 6029d547e5f..46902d4fcaa 100644 --- a/vendor/github.com/mdlayher/vsock/conn_linux.go +++ b/vendor/github.com/mdlayher/vsock/conn_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package vsock diff --git a/vendor/github.com/mdlayher/vsock/fd_linux.go b/vendor/github.com/mdlayher/vsock/fd_linux.go index 531e53f928e..25c6e6761a5 100644 --- a/vendor/github.com/mdlayher/vsock/fd_linux.go +++ b/vendor/github.com/mdlayher/vsock/fd_linux.go @@ -31,6 +31,6 @@ func isErrno(err error, errno int) bool { } } -func panicf(format string, a ...interface{}) { +func panicf(format string, a ...any) { panic(fmt.Sprintf(format, a...)) } diff --git a/vendor/github.com/mdlayher/vsock/listener_linux.go b/vendor/github.com/mdlayher/vsock/listener_linux.go index 50fa1b7a49a..3416368f3fd 100644 --- a/vendor/github.com/mdlayher/vsock/listener_linux.go +++ b/vendor/github.com/mdlayher/vsock/listener_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package vsock diff --git a/vendor/github.com/mdlayher/vsock/vsock.go b/vendor/github.com/mdlayher/vsock/vsock.go index 78763936ae6..1cc05202e51 100644 --- a/vendor/github.com/mdlayher/vsock/vsock.go +++ b/vendor/github.com/mdlayher/vsock/vsock.go @@ -1,7 +1,6 @@ package vsock import ( - "errors" "fmt" "io" "net" @@ -403,7 +402,7 @@ func opError(op string, err error, local, remote net.Addr) error { // // To rectify the differences, net.TCPConn uses an error with this text // from internal/poll for the backing file already being closed. - err = errors.New("use of closed network connection") + err = net.ErrClosed default: // Nothing to do, return this directly. } diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md index 2a7d8c265bf..8dc2472360b 100644 --- a/vendor/github.com/miekg/dns/README.md +++ b/vendor/github.com/miekg/dns/README.md @@ -6,7 +6,12 @@ DNS version 2 is now available at , check it out if you want to help shape the next 15 years of the Go DNS package. -The version here will see no new features and less and less development. +The version here will see no new features and less and less development, and my time (if any) will be fully +devoted towards v2. + +**December 2025**: v2 should be (already) a good replacement, the coming months would be a good time to +migrate, see [this file describing the +differences](https://codeberg.org/miekg/dns/src/branch/main/README-diff-with-v1.md), to help you get started. # Alternative (more granular) approach to a DNS library @@ -62,7 +67,7 @@ A not-so-up-to-date-list-that-may-be-actually-current: - https://www.dnsperf.com/ - https://dnssectest.net/ - https://github.com/oif/apex -- https://github.com/jedisct1/dnscrypt-proxy +- https://github.com/jedisct1/dnscrypt-proxy (migrated to v2) - https://github.com/jedisct1/rpdns - https://github.com/xor-gate/sshfp - https://github.com/rs/dnstrace diff --git a/vendor/github.com/miekg/dns/client.go b/vendor/github.com/miekg/dns/client.go index 9549fa9232b..a0f96187b41 100644 --- a/vendor/github.com/miekg/dns/client.go +++ b/vendor/github.com/miekg/dns/client.go @@ -57,8 +57,8 @@ type Client struct { // Client.Dialer) or context.Context.Deadline (see ExchangeContext) Timeout time.Duration DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero - ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero - WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero + ReadTimeout time.Duration // net.Conn.SetReadDeadline value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero + WriteTimeout time.Duration // net.Conn.SetWriteDeadline value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero TsigSecret map[string]string // secret(s) for Tsig map[], zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations. @@ -92,6 +92,9 @@ func (c *Client) dialTimeout() time.Duration { } func (c *Client) readTimeout() time.Duration { + if c.Timeout != 0 { + return c.Timeout + } if c.ReadTimeout != 0 { return c.ReadTimeout } @@ -99,6 +102,9 @@ func (c *Client) readTimeout() time.Duration { } func (c *Client) writeTimeout() time.Duration { + if c.Timeout != 0 { + return c.Timeout + } if c.WriteTimeout != 0 { return c.WriteTimeout } diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go index edf18596199..382a8083875 100644 --- a/vendor/github.com/miekg/dns/msg.go +++ b/vendor/github.com/miekg/dns/msg.go @@ -338,11 +338,13 @@ loop: return off + 2, nil } + // Trailing root label if off < len(msg) { msg[off] = 0 + return off + 1, nil } - return off + 1, nil + return off, ErrBuf } // isRootLabel returns whether s or bs, from off to end, is the root diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go index 31957b2ea0d..f7c6525dd0f 100644 --- a/vendor/github.com/miekg/dns/scan.go +++ b/vendor/github.com/miekg/dns/scan.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/fs" + "math" "os" "path" "path/filepath" @@ -1231,7 +1232,7 @@ func typeToInt(token string) (uint16, bool) { // stringToTTL parses things like 2w, 2m, etc, and returns the time in seconds. func stringToTTL(token string) (uint32, bool) { - var s, i uint32 + var s, i uint for _, c := range token { switch c { case 's', 'S': @@ -1251,12 +1252,15 @@ func stringToTTL(token string) (uint32, bool) { i = 0 case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': i *= 10 - i += uint32(c) - '0' + i += uint(c) - '0' default: return 0, false } } - return s + i, true + if s+i > math.MaxUint32 { + return 0, false + } + return uint32(s + i), true } // Parse LOC records' [.][mM] into a diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go index c53a63d7c8b..33cb83e5ac8 100644 --- a/vendor/github.com/miekg/dns/version.go +++ b/vendor/github.com/miekg/dns/version.go @@ -3,7 +3,7 @@ package dns import "fmt" // Version is current version of this library. -var Version = v{1, 1, 69} +var Version = v{1, 1, 72} // v holds the version of this library. type v struct { diff --git a/vendor/github.com/oklog/ulid/v2/ulid.go b/vendor/github.com/oklog/ulid/v2/ulid.go index 77e9ddd6349..e07e1a68183 100644 --- a/vendor/github.com/oklog/ulid/v2/ulid.go +++ b/vendor/github.com/oklog/ulid/v2/ulid.go @@ -505,7 +505,16 @@ func (id *ULID) Scan(src interface{}) error { case string: return id.UnmarshalText([]byte(x)) case []byte: - return id.UnmarshalBinary(x) + // Drivers often return text/varchar columns as []byte. Accept both + // the 16-byte binary form and the 26-character text encoding. + switch len(x) { + case len(*id): + return id.UnmarshalBinary(x) + case EncodedSize: + return id.UnmarshalText(x) + default: + return ErrDataSize + } } return ErrScanValue diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/api.go b/vendor/github.com/prometheus/alertmanager/api/v2/api.go index 5088109333a..0207607b959 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/api.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/api.go @@ -29,6 +29,7 @@ import ( "github.com/go-openapi/analysis" "github.com/go-openapi/loads" "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/server-middleware/docui" "github.com/go-openapi/strfmt" "github.com/prometheus/client_golang/prometheus" prometheus_model "github.com/prometheus/common/model" @@ -126,7 +127,7 @@ func NewAPI( openAPI.Middleware = func(b middleware.Builder) http.Handler { // Manually create the context so that we can use the singleton swaggerSpecAnalysis. swaggerContext := middleware.NewRoutableContextWithAnalyzedSpec(swaggerSpec, swaggerSpecAnalysis, openAPI, nil) - return middleware.Spec("", swaggerSpec.Raw(), swaggerContext.RoutesHandler(b)) + return docui.ServeSpec(swaggerSpec.Raw(), swaggerContext.RoutesHandler(b), docui.WithSpecPath("/swagger.json")) } openAPI.AlertGetAlertsHandler = alert_ops.GetAlertsHandlerFunc(api.getAlertsHandler) @@ -511,9 +512,10 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams } ag := &open_api_models.AlertGroup{ - Receiver: &open_api_models.ReceiverReference{Name: &alertGroup.Receiver}, - Labels: ModelLabelSetToAPILabelSet(alertGroup.Labels), - Alerts: make([]*open_api_models.GettableAlert, 0, len(alertGroup.Alerts)), + Receiver: &open_api_models.ReceiverReference{Name: &alertGroup.Receiver}, + Labels: ModelLabelSetToAPILabelSet(alertGroup.Labels), + RouteLabels: ModelLabelSetToAPILabelSet(alertGroup.RouteLabels), + Alerts: make([]*open_api_models.GettableAlert, 0, len(alertGroup.Alerts)), } for _, alert := range alertGroup.Alerts { @@ -681,7 +683,20 @@ func (api *API) getSilencesHandler(params silence_ops.GetSilencesParams) middlew return silence_ops.NewGetSilencesBadRequest().WithPayload(err.Error()) } - psils, _, err := api.silences.Query(ctx) + // Build the state filter. Params are always non-nil (defaults to true) so + // we only add a state to the query when the caller has not excluded it. + var states []silence.SilenceState + if *params.Active { + states = append(states, silence.SilenceStateActive) + } + if *params.Expired { + states = append(states, silence.SilenceStateExpired) + } + if *params.Pending { + states = append(states, silence.SilenceStatePending) + } + + psils, _, err := api.silences.Query(ctx, silence.QState(states...)) if err != nil { logger.Error("Failed to get silences", "err", err) return silence_ops.NewGetSilencesInternalServerError().WithPayload(err.Error()) @@ -692,12 +707,12 @@ func (api *API) getSilencesHandler(params silence_ops.GetSilencesParams) middlew if !CheckSilenceMatchesFilterLabels(ps, matchers) { continue } - silence, err := GettableSilenceFromProto(ps) + sil, err := GettableSilenceFromProto(ps) if err != nil { logger.Error("Failed to unmarshal silence from proto", "err", err) return silence_ops.NewGetSilencesInternalServerError().WithPayload(err.Error()) } - sils = append(sils, &silence) + sils = append(sils, &sil) } SortSilences(sils) diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_parameters.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_parameters.go index 8e02101200c..166edf521e7 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_parameters.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_parameters.go @@ -76,12 +76,36 @@ GetSilencesParams contains all the parameters to send to the API endpoint */ type GetSilencesParams struct { + /* Active. + + Include active silences in results. If false, excludes active silences. + + Default: true + */ + Active *bool + + /* Expired. + + Include expired silences in results. If false, excludes expired silences. + + Default: true + */ + Expired *bool + /* Filter. A matcher expression to filter silences. For example `alertname="MyAlert"`. It can be repeated to apply multiple matchers. */ Filter []string + /* Pending. + + Include pending silences in results. If false, excludes pending silences. + + Default: true + */ + Pending *bool + timeout time.Duration Context context.Context HTTPClient *http.Client @@ -99,7 +123,24 @@ func (o *GetSilencesParams) WithDefaults() *GetSilencesParams { // // All values with no default are reset to their zero value. func (o *GetSilencesParams) SetDefaults() { - // no default values defined for this parameter + var ( + activeDefault = bool(true) + + expiredDefault = bool(true) + + pendingDefault = bool(true) + ) + + val := GetSilencesParams{ + Active: &activeDefault, + Expired: &expiredDefault, + Pending: &pendingDefault, + } + + val.timeout = o.timeout + val.Context = o.Context + val.HTTPClient = o.HTTPClient + *o = val } // WithTimeout adds the timeout to the get silences params @@ -135,6 +176,28 @@ func (o *GetSilencesParams) SetHTTPClient(client *http.Client) { o.HTTPClient = client } +// WithActive adds the active to the get silences params +func (o *GetSilencesParams) WithActive(active *bool) *GetSilencesParams { + o.SetActive(active) + return o +} + +// SetActive adds the active to the get silences params +func (o *GetSilencesParams) SetActive(active *bool) { + o.Active = active +} + +// WithExpired adds the expired to the get silences params +func (o *GetSilencesParams) WithExpired(expired *bool) *GetSilencesParams { + o.SetExpired(expired) + return o +} + +// SetExpired adds the expired to the get silences params +func (o *GetSilencesParams) SetExpired(expired *bool) { + o.Expired = expired +} + // WithFilter adds the filter to the get silences params func (o *GetSilencesParams) WithFilter(filter []string) *GetSilencesParams { o.SetFilter(filter) @@ -146,6 +209,17 @@ func (o *GetSilencesParams) SetFilter(filter []string) { o.Filter = filter } +// WithPending adds the pending to the get silences params +func (o *GetSilencesParams) WithPending(pending *bool) *GetSilencesParams { + o.SetPending(pending) + return o +} + +// SetPending adds the pending to the get silences params +func (o *GetSilencesParams) SetPending(pending *bool) { + o.Pending = pending +} + // WriteToRequest writes these params to a swagger request func (o *GetSilencesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { @@ -154,6 +228,40 @@ func (o *GetSilencesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.R } var res []error + if o.Active != nil { + + // query param active + var qrActive bool + + if o.Active != nil { + qrActive = *o.Active + } + qActive := swag.FormatBool(qrActive) + if qActive != "" { + + if err := r.SetQueryParam("active", qActive); err != nil { + return err + } + } + } + + if o.Expired != nil { + + // query param expired + var qrExpired bool + + if o.Expired != nil { + qrExpired = *o.Expired + } + qExpired := swag.FormatBool(qrExpired) + if qExpired != "" { + + if err := r.SetQueryParam("expired", qExpired); err != nil { + return err + } + } + } + if o.Filter != nil { // binding items for filter @@ -165,6 +273,23 @@ func (o *GetSilencesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.R } } + if o.Pending != nil { + + // query param pending + var qrPending bool + + if o.Pending != nil { + qrPending = *o.Pending + } + qPending := swag.FormatBool(qrPending) + if qPending != "" { + + if err := r.SetQueryParam("pending", qPending); err != nil { + return err + } + } + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/compat.go b/vendor/github.com/prometheus/alertmanager/api/v2/compat.go index cb5560af058..5db1a9cad11 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/compat.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/compat.go @@ -38,6 +38,7 @@ func GettableSilenceFromProto(s *silencepb.Silence) (open_api_models.GettableSil Silence: open_api_models.Silence{ StartsAt: &start, EndsAt: &end, + Matchers: open_api_models.Matchers{}, Comment: &s.Comment, CreatedBy: &s.CreatedBy, Annotations: s.Annotations, diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go index 6cad0ab2e4b..848df30c9d9 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go @@ -46,6 +46,10 @@ type AlertGroup struct { // receiver // Required: true Receiver *ReceiverReference `json:"receiver"` + + // route labels + // Required: true + RouteLabels LabelSet `json:"routeLabels"` } // Validate validates this alert group @@ -64,6 +68,10 @@ func (m *AlertGroup) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateRouteLabels(formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -149,6 +157,30 @@ func (m *AlertGroup) validateReceiver(formats strfmt.Registry) error { return nil } +func (m *AlertGroup) validateRouteLabels(formats strfmt.Registry) error { + + if err := validate.Required("routeLabels", "body", m.RouteLabels); err != nil { + return err + } + + if m.RouteLabels != nil { + if err := m.RouteLabels.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("routeLabels") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("routeLabels") + } + + return err + } + } + + return nil +} + // ContextValidate validate this alert group based on the context it is used func (m *AlertGroup) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error @@ -165,6 +197,10 @@ func (m *AlertGroup) ContextValidate(ctx context.Context, formats strfmt.Registr res = append(res, err) } + if err := m.contextValidateRouteLabels(ctx, formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -239,6 +275,24 @@ func (m *AlertGroup) contextValidateReceiver(ctx context.Context, formats strfmt return nil } +func (m *AlertGroup) contextValidateRouteLabels(ctx context.Context, formats strfmt.Registry) error { + + if err := m.RouteLabels.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("routeLabels") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("routeLabels") + } + + return err + } + + return nil +} + // MarshalBinary interface implementation func (m *AlertGroup) MarshalBinary() ([]byte, error) { if m == nil { diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml b/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml index 1ee47c30dc5..0b6e8644464 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml +++ b/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml @@ -70,6 +70,21 @@ paths: collectionFormat: multi items: type: string + - in: query + name: active + type: boolean + description: Include active silences in results. If false, excludes active silences. + default: true + - in: query + name: expired + type: boolean + description: Include expired silences in results. If false, excludes expired silences. + default: true + - in: query + name: pending + type: boolean + description: Include pending silences in results. If false, excludes pending silences. + default: true post: tags: - silence @@ -501,6 +516,8 @@ definitions: properties: labels: $ref: '#/definitions/labelSet' + routeLabels: + $ref: '#/definitions/labelSet' receiver: $ref: '#/definitions/receiverReference' alerts: @@ -509,6 +526,7 @@ definitions: $ref: '#/definitions/gettableAlert' required: - labels + - routeLabels - receiver - alerts alertStatus: diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go index 3e41640c95d..36725d260da 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go @@ -329,6 +329,27 @@ func init() { "description": "A matcher expression to filter silences. For example ` + "`" + `alertname=\"MyAlert\"` + "`" + `. It can be repeated to apply multiple matchers.", "name": "filter", "in": "query" + }, + { + "type": "boolean", + "default": true, + "description": "Include active silences in results. If false, excludes active silences.", + "name": "active", + "in": "query" + }, + { + "type": "boolean", + "default": true, + "description": "Include expired silences in results. If false, excludes expired silences.", + "name": "expired", + "in": "query" + }, + { + "type": "boolean", + "default": true, + "description": "Include pending silences in results. If false, excludes pending silences.", + "name": "pending", + "in": "query" } ], "responses": { @@ -425,6 +446,7 @@ func init() { "type": "object", "required": [ "labels", + "routeLabels", "receiver", "alerts" ], @@ -440,6 +462,9 @@ func init() { }, "receiver": { "$ref": "#/definitions/receiverReference" + }, + "routeLabels": { + "$ref": "#/definitions/labelSet" } } }, @@ -1225,6 +1250,27 @@ func init() { "description": "A matcher expression to filter silences. For example ` + "`" + `alertname=\"MyAlert\"` + "`" + `. It can be repeated to apply multiple matchers.", "name": "filter", "in": "query" + }, + { + "type": "boolean", + "default": true, + "description": "Include active silences in results. If false, excludes active silences.", + "name": "active", + "in": "query" + }, + { + "type": "boolean", + "default": true, + "description": "Include expired silences in results. If false, excludes expired silences.", + "name": "expired", + "in": "query" + }, + { + "type": "boolean", + "default": true, + "description": "Include pending silences in results. If false, excludes pending silences.", + "name": "pending", + "in": "query" } ], "responses": { @@ -1330,6 +1376,7 @@ func init() { "type": "object", "required": [ "labels", + "routeLabels", "receiver", "alerts" ], @@ -1345,6 +1392,9 @@ func init() { }, "receiver": { "$ref": "#/definitions/receiverReference" + }, + "routeLabels": { + "$ref": "#/definitions/labelSet" } } }, diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_parameters.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_parameters.go index 47374dd9a99..afb28f657c4 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_parameters.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_parameters.go @@ -26,14 +26,29 @@ import ( "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" ) // NewGetSilencesParams creates a new GetSilencesParams object -// -// There are no default values defined in the spec. +// with the default values initialized. func NewGetSilencesParams() GetSilencesParams { - return GetSilencesParams{} + var ( + // initialize parameters with default values + + activeDefault = bool(true) + expiredDefault = bool(true) + + pendingDefault = bool(true) + ) + + return GetSilencesParams{ + Active: &activeDefault, + + Expired: &expiredDefault, + + Pending: &pendingDefault, + } } // GetSilencesParams contains all the bound params for the get silences operation @@ -44,11 +59,29 @@ type GetSilencesParams struct { // HTTP Request Object HTTPRequest *http.Request `json:"-"` + /*Include active silences in results. If false, excludes active silences. + In: query + Default: true + */ + Active *bool + + /*Include expired silences in results. If false, excludes expired silences. + In: query + Default: true + */ + Expired *bool + /*A matcher expression to filter silences. For example `alertname="MyAlert"`. It can be repeated to apply multiple matchers. In: query Collection Format: multi */ Filter []string + + /*Include pending silences in results. If false, excludes pending silences. + In: query + Default: true + */ + Pending *bool } // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface @@ -61,16 +94,79 @@ func (o *GetSilencesParams) BindRequest(r *http.Request, route *middleware.Match o.HTTPRequest = r qs := runtime.Values(r.URL.Query()) + qActive, qhkActive, _ := qs.GetOK("active") + if err := o.bindActive(qActive, qhkActive, route.Formats); err != nil { + res = append(res, err) + } + + qExpired, qhkExpired, _ := qs.GetOK("expired") + if err := o.bindExpired(qExpired, qhkExpired, route.Formats); err != nil { + res = append(res, err) + } + qFilter, qhkFilter, _ := qs.GetOK("filter") if err := o.bindFilter(qFilter, qhkFilter, route.Formats); err != nil { res = append(res, err) } + + qPending, qhkPending, _ := qs.GetOK("pending") + if err := o.bindPending(qPending, qhkPending, route.Formats); err != nil { + res = append(res, err) + } if len(res) > 0 { return errors.CompositeValidationError(res...) } return nil } +// bindActive binds and validates parameter Active from query. +func (o *GetSilencesParams) bindActive(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetSilencesParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("active", "query", "bool", raw) + } + o.Active = &value + + return nil +} + +// bindExpired binds and validates parameter Expired from query. +func (o *GetSilencesParams) bindExpired(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetSilencesParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("expired", "query", "bool", raw) + } + o.Expired = &value + + return nil +} + // bindFilter binds and validates array parameter Filter from query. // // Arrays are parsed according to CollectionFormat: "multi" (defaults to "csv" when empty). @@ -92,3 +188,27 @@ func (o *GetSilencesParams) bindFilter(rawData []string, hasKey bool, formats st return nil } + +// bindPending binds and validates parameter Pending from query. +func (o *GetSilencesParams) bindPending(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetSilencesParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("pending", "query", "bool", raw) + } + o.Pending = &value + + return nil +} diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_urlbuilder.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_urlbuilder.go index a96c95bf4b8..49239bdbfb0 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_urlbuilder.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_urlbuilder.go @@ -29,7 +29,10 @@ import ( // GetSilencesURL generates an URL for the get silences operation type GetSilencesURL struct { - Filter []string + Active *bool + Expired *bool + Filter []string + Pending *bool _basePath string // avoid unkeyed usage @@ -65,6 +68,22 @@ func (o *GetSilencesURL) Build() (*url.URL, error) { qs := make(url.Values) + var activeQ string + if o.Active != nil { + activeQ = swag.FormatBool(*o.Active) + } + if activeQ != "" { + qs.Set("active", activeQ) + } + + var expiredQ string + if o.Expired != nil { + expiredQ = swag.FormatBool(*o.Expired) + } + if expiredQ != "" { + qs.Set("expired", expiredQ) + } + var filterIR []string for _, filterI := range o.Filter { filterIS := filterI @@ -79,6 +98,14 @@ func (o *GetSilencesURL) Build() (*url.URL, error) { qs.Add("filter", qsv) } + var pendingQ string + if o.Pending != nil { + pendingQ = swag.FormatBool(*o.Pending) + } + if pendingQ != "" { + qs.Set("pending", pendingQ) + } + _result.RawQuery = qs.Encode() return &_result, nil diff --git a/vendor/github.com/prometheus/alertmanager/config/common/url.go b/vendor/github.com/prometheus/alertmanager/config/common/url.go index dc20913b8b3..5a5fd10d277 100644 --- a/vendor/github.com/prometheus/alertmanager/config/common/url.go +++ b/vendor/github.com/prometheus/alertmanager/config/common/url.go @@ -152,8 +152,8 @@ func (s *SecretURL) UnmarshalJSON(data []byte) error { return nil } -// containsTemplating checks if the string contains template syntax. -func containsTemplating(s string) (bool, error) { +// ContainsTemplating checks if the string contains template syntax. +func ContainsTemplating(s string) (bool, error) { if !strings.Contains(s, "{{") { return false, nil } @@ -196,7 +196,7 @@ func (s *SecretTemplateURL) UnmarshalYAML(unmarshal func(any) error) error { } // Check if the URL contains template syntax - isTemplated, err := containsTemplating(urlStr) + isTemplated, err := ContainsTemplating(urlStr) if err != nil { return fmt.Errorf("invalid template syntax: %w", err) } diff --git a/vendor/github.com/prometheus/alertmanager/config/config.go b/vendor/github.com/prometheus/alertmanager/config/config.go index aeea0560a3c..d8232b21a96 100644 --- a/vendor/github.com/prometheus/alertmanager/config/config.go +++ b/vendor/github.com/prometheus/alertmanager/config/config.go @@ -37,6 +37,10 @@ import ( "github.com/prometheus/alertmanager/notify/jira" "github.com/prometheus/alertmanager/notify/mattermost" "github.com/prometheus/alertmanager/notify/msteams" + "github.com/prometheus/alertmanager/notify/msteamsv2" + "github.com/prometheus/alertmanager/notify/opsgenie" + "github.com/prometheus/alertmanager/notify/pagerduty" + "github.com/prometheus/alertmanager/notify/telegram" "github.com/prometheus/alertmanager/notify/webhook" "github.com/prometheus/alertmanager/timeinterval" "github.com/prometheus/alertmanager/tracing" @@ -476,7 +480,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(any) error) error { } for _, ogc := range rcv.OpsGenieConfigs { if ogc == nil { - ogc = &OpsGenieConfig{} + ogc = &opsgenie.OpsGenieConfig{} } ogc.HTTPConfig = cmp.Or(ogc.HTTPConfig, c.Global.HTTPConfig) ogc.APIURL = cmp.Or(ogc.APIURL, c.Global.OpsGenieAPIURL) @@ -590,7 +594,16 @@ func (c *Config) UnmarshalYAML(unmarshal func(any) error) error { if msteamsv2 == nil { return errors.New("missing msteamsv2 config") } - msteamsv2.HTTPConfig = cmp.Or(msteamsv2.HTTPConfig, c.Global.HTTPConfig) + if msteamsv2.HTTPConfig == nil { + // copy the global config so receiver-level mutations don't affect it + httpCfg := *c.Global.HTTPConfig + msteamsv2.HTTPConfig = &httpCfg + } else if msteamsv2.HTTPConfig.ProxyURL.URL == nil { + // receiver has a partial http_config but no proxy_url set, + // so inherit only the proxy_url from global, leaving any + // other proxy fields the receiver set (NoProxy, etc.) intact + msteamsv2.HTTPConfig.ProxyURL = c.Global.HTTPConfig.ProxyURL + } if msteamsv2.WebhookURL == nil && len(msteamsv2.WebhookURLFile) == 0 { return errors.New("no msteamsv2 webhook URL or URLFile provided") } @@ -890,6 +903,12 @@ type Route struct { GroupWait *model.Duration `yaml:"group_wait,omitempty" json:"group_wait,omitempty"` GroupInterval *model.Duration `yaml:"group_interval,omitempty" json:"group_interval,omitempty"` RepeatInterval *model.Duration `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty"` + + // Labels are attached to a route and inherited by child routes. + // Values may be Go templates rendered against the current alert group's + // data. Notification-specific fields such as .NotificationReason are + // not available; use notification templates for reason-dependent content. + Labels model.LabelSet `yaml:"labels,omitempty" json:"labels,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface for Route. @@ -905,6 +924,12 @@ func (r *Route) UnmarshalYAML(unmarshal func(any) error) error { } } + for k := range r.Labels { + if !compat.IsValidLabelName(k) { + return fmt.Errorf("invalid label name %q in route labels", k) + } + } + for _, l := range r.GroupByStr { if l == "..." { r.GroupByAll = true @@ -954,18 +979,18 @@ type Receiver struct { DiscordConfigs []*discord.DiscordConfig `yaml:"discord_configs,omitempty" json:"discord_configs,omitempty"` EmailConfigs []*EmailConfig `yaml:"email_configs,omitempty" json:"email_configs,omitempty"` IncidentioConfigs []*incidentio.IncidentioConfig `yaml:"incidentio_configs,omitempty" json:"incidentio_configs,omitempty"` - PagerdutyConfigs []*PagerdutyConfig `yaml:"pagerduty_configs,omitempty" json:"pagerduty_configs,omitempty"` + PagerdutyConfigs []*pagerduty.PagerdutyConfig `yaml:"pagerduty_configs,omitempty" json:"pagerduty_configs,omitempty"` SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty" json:"slack_configs,omitempty"` WebhookConfigs []*webhook.WebhookConfig `yaml:"webhook_configs,omitempty" json:"webhook_configs,omitempty"` - OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty" json:"opsgenie_configs,omitempty"` + OpsGenieConfigs []*opsgenie.OpsGenieConfig `yaml:"opsgenie_configs,omitempty" json:"opsgenie_configs,omitempty"` WechatConfigs []*WechatConfig `yaml:"wechat_configs,omitempty" json:"wechat_configs,omitempty"` PushoverConfigs []*PushoverConfig `yaml:"pushover_configs,omitempty" json:"pushover_configs,omitempty"` VictorOpsConfigs []*VictorOpsConfig `yaml:"victorops_configs,omitempty" json:"victorops_configs,omitempty"` SNSConfigs []*SNSConfig `yaml:"sns_configs,omitempty" json:"sns_configs,omitempty"` - TelegramConfigs []*TelegramConfig `yaml:"telegram_configs,omitempty" json:"telegram_configs,omitempty"` + TelegramConfigs []*telegram.TelegramConfig `yaml:"telegram_configs,omitempty" json:"telegram_configs,omitempty"` WebexConfigs []*WebexConfig `yaml:"webex_configs,omitempty" json:"webex_configs,omitempty"` MSTeamsConfigs []*msteams.MSTeamsConfig `yaml:"msteams_configs,omitempty" json:"msteams_configs,omitempty"` - MSTeamsV2Configs []*MSTeamsV2Config `yaml:"msteamsv2_configs,omitempty" json:"msteamsv2_configs,omitempty"` + MSTeamsV2Configs []*msteamsv2.MSTeamsV2Config `yaml:"msteamsv2_configs,omitempty" json:"msteamsv2_configs,omitempty"` JiraConfigs []*jira.JiraConfig `yaml:"jira_configs,omitempty" json:"jira_configs,omitempty"` RocketchatConfigs []*RocketchatConfig `yaml:"rocketchat_configs,omitempty" json:"rocketchat_configs,omitempty"` MattermostConfigs []*mattermost.MattermostConfig `yaml:"mattermost_configs,omitempty" json:"mattermost_configs,omitempty"` diff --git a/vendor/github.com/prometheus/alertmanager/config/notifiers.go b/vendor/github.com/prometheus/alertmanager/config/notifiers.go index 46626cb7a3c..a9052475d5b 100644 --- a/vendor/github.com/prometheus/alertmanager/config/notifiers.go +++ b/vendor/github.com/prometheus/alertmanager/config/notifiers.go @@ -19,7 +19,6 @@ import ( "net/textproto" "regexp" "slices" - "strings" "time" commoncfg "github.com/prometheus/common/config" @@ -51,24 +50,6 @@ var ( // DefaultEmailSubject defines the default Subject header of an Email. DefaultEmailSubject = `{{ template "email.default.subject" . }}` - // DefaultPagerdutyDetails defines the default values for PagerDuty details. - DefaultPagerdutyDetails = map[string]any{ - "firing": `{{ .Alerts.Firing | toJson }}`, - "resolved": `{{ .Alerts.Resolved | toJson }}`, - "num_firing": `{{ .Alerts.Firing | len }}`, - "num_resolved": `{{ .Alerts.Resolved | len }}`, - } - - // DefaultPagerdutyConfig defines default values for PagerDuty configurations. - DefaultPagerdutyConfig = PagerdutyConfig{ - NotifierConfig: amcommoncfg.NotifierConfig{ - VSendResolved: true, - }, - Description: `{{ template "pagerduty.default.description" .}}`, - Client: `{{ template "pagerduty.default.client" . }}`, - ClientURL: `{{ template "pagerduty.default.clientURL" . }}`, - } - // DefaultSlackConfig defines default values for Slack configurations. DefaultSlackConfig = SlackConfig{ NotifierConfig: amcommoncfg.NotifierConfig{ @@ -99,17 +80,6 @@ var ( TitleLink: `{{ template "rocketchat.default.titlelink" . }}`, } - // DefaultOpsGenieConfig defines default values for OpsGenie configurations. - DefaultOpsGenieConfig = OpsGenieConfig{ - NotifierConfig: amcommoncfg.NotifierConfig{ - VSendResolved: true, - }, - Message: `{{ template "opsgenie.default.message" . }}`, - Description: `{{ template "opsgenie.default.description" . }}`, - Source: `{{ template "opsgenie.default.source" . }}`, - // TODO: Add a details field with all the alerts. - } - // DefaultWechatConfig defines default values for wechat configurations. DefaultWechatConfig = WechatConfig{ NotifierConfig: amcommoncfg.NotifierConfig{ @@ -155,23 +125,6 @@ var ( Subject: `{{ template "sns.default.subject" . }}`, Message: `{{ template "sns.default.message" . }}`, } - - DefaultTelegramConfig = TelegramConfig{ - NotifierConfig: amcommoncfg.NotifierConfig{ - VSendResolved: true, - }, - DisableNotifications: false, - Message: `{{ template "telegram.default.message" . }}`, - ParseMode: "HTML", - } - - DefaultMSTeamsV2Config = MSTeamsV2Config{ - NotifierConfig: amcommoncfg.NotifierConfig{ - VSendResolved: true, - }, - Title: `{{ template "msteamsv2.default.title" . }}`, - Text: `{{ template "msteamsv2.default.text" . }}`, - } ) // WebexConfig configures notifications via Webex. @@ -273,76 +226,6 @@ func (c *EmailConfig) UnmarshalYAML(unmarshal func(any) error) error { return nil } -// PagerdutyConfig configures notifications via PagerDuty. -type PagerdutyConfig struct { - amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` - - HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` - - ServiceKey commoncfg.Secret `yaml:"service_key,omitempty" json:"service_key,omitempty"` - ServiceKeyFile string `yaml:"service_key_file,omitempty" json:"service_key_file,omitempty"` - RoutingKey commoncfg.Secret `yaml:"routing_key,omitempty" json:"routing_key,omitempty"` - RoutingKeyFile string `yaml:"routing_key_file,omitempty" json:"routing_key_file,omitempty"` - URL *amcommoncfg.URL `yaml:"url,omitempty" json:"url,omitempty"` - Client string `yaml:"client,omitempty" json:"client,omitempty"` - ClientURL string `yaml:"client_url,omitempty" json:"client_url,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Details map[string]any `yaml:"details,omitempty" json:"details,omitempty"` - Images []PagerdutyImage `yaml:"images,omitempty" json:"images,omitempty"` - Links []PagerdutyLink `yaml:"links,omitempty" json:"links,omitempty"` - Source string `yaml:"source,omitempty" json:"source,omitempty"` - Severity string `yaml:"severity,omitempty" json:"severity,omitempty"` - Class string `yaml:"class,omitempty" json:"class,omitempty"` - Component string `yaml:"component,omitempty" json:"component,omitempty"` - Group string `yaml:"group,omitempty" json:"group,omitempty"` - // Timeout is the maximum time allowed to invoke the pagerduty. Setting this to 0 - // does not impose a timeout. - Timeout time.Duration `yaml:"timeout" json:"timeout"` -} - -// PagerdutyLink is a link. -type PagerdutyLink struct { - Href string `yaml:"href,omitempty" json:"href,omitempty"` - Text string `yaml:"text,omitempty" json:"text,omitempty"` -} - -// PagerdutyImage is an image. -type PagerdutyImage struct { - Src string `yaml:"src,omitempty" json:"src,omitempty"` - Alt string `yaml:"alt,omitempty" json:"alt,omitempty"` - Href string `yaml:"href,omitempty" json:"href,omitempty"` -} - -// UnmarshalYAML implements the yaml.Unmarshaler interface. -func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(any) error) error { - *c = DefaultPagerdutyConfig - type plain PagerdutyConfig - if err := unmarshal((*plain)(c)); err != nil { - return err - } - if c.RoutingKey == "" && c.ServiceKey == "" && c.RoutingKeyFile == "" && c.ServiceKeyFile == "" { - return errors.New("missing service or routing key in PagerDuty config") - } - if len(c.RoutingKey) > 0 && len(c.RoutingKeyFile) > 0 { - return errors.New("at most one of routing_key & routing_key_file must be configured") - } - if len(c.ServiceKey) > 0 && len(c.ServiceKeyFile) > 0 { - return errors.New("at most one of service_key & service_key_file must be configured") - } - if c.Details == nil { - c.Details = make(map[string]any) - } - if c.Source == "" { - c.Source = c.Client - } - for k, v := range DefaultPagerdutyDetails { - if _, ok := c.Details[k]; !ok { - c.Details[k] = v - } - } - return nil -} - // SlackAction configures a single Slack action that is sent with each notification. // See https://api.slack.com/docs/message-attachments#action_fields and https://api.slack.com/docs/message-buttons // for more information. @@ -542,74 +425,6 @@ func (c *WechatConfig) UnmarshalYAML(unmarshal func(any) error) error { return nil } -// OpsGenieConfig configures notifications via OpsGenie. -type OpsGenieConfig struct { - amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` - - HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` - - APIKey commoncfg.Secret `yaml:"api_key,omitempty" json:"api_key,omitempty"` - APIKeyFile string `yaml:"api_key_file,omitempty" json:"api_key_file,omitempty"` - APIURL *amcommoncfg.URL `yaml:"api_url,omitempty" json:"api_url,omitempty"` - Message string `yaml:"message,omitempty" json:"message,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Source string `yaml:"source,omitempty" json:"source,omitempty"` - Details map[string]string `yaml:"details,omitempty" json:"details,omitempty"` - Entity string `yaml:"entity,omitempty" json:"entity,omitempty"` - Responders []OpsGenieConfigResponder `yaml:"responders,omitempty" json:"responders,omitempty"` - Actions string `yaml:"actions,omitempty" json:"actions,omitempty"` - Tags string `yaml:"tags,omitempty" json:"tags,omitempty"` - Note string `yaml:"note,omitempty" json:"note,omitempty"` - Priority string `yaml:"priority,omitempty" json:"priority,omitempty"` - UpdateAlerts bool `yaml:"update_alerts,omitempty" json:"update_alerts,omitempty"` -} - -const opsgenieValidTypesRe = `^(team|teams|user|escalation|schedule)$` - -var opsgenieTypeMatcher = regexp.MustCompile(opsgenieValidTypesRe) - -// UnmarshalYAML implements the yaml.Unmarshaler interface. -func (c *OpsGenieConfig) UnmarshalYAML(unmarshal func(any) error) error { - *c = DefaultOpsGenieConfig - type plain OpsGenieConfig - if err := unmarshal((*plain)(c)); err != nil { - return err - } - - if c.APIKey != "" && len(c.APIKeyFile) > 0 { - return errors.New("at most one of api_key & api_key_file must be configured") - } - - for _, r := range c.Responders { - if r.ID == "" && r.Username == "" && r.Name == "" { - return fmt.Errorf("opsGenieConfig responder %v has to have at least one of id, username or name specified", r) - } - - isTemplated, err := containsTemplating(r.Type) - if err != nil { - return fmt.Errorf("opsGenieConfig responder %v type contains invalid template syntax: %w", r, err) - } - if !isTemplated { - r.Type = strings.ToLower(r.Type) - if !opsgenieTypeMatcher.MatchString(r.Type) { - return fmt.Errorf("opsGenieConfig responder %v type does not match valid options %s", r, opsgenieValidTypesRe) - } - } - } - - return nil -} - -type OpsGenieConfigResponder struct { - // One of those 3 should be filled. - ID string `yaml:"id,omitempty" json:"id,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Username string `yaml:"username,omitempty" json:"username,omitempty"` - - // team, user, escalation, schedule etc. - Type string `yaml:"type,omitempty" json:"type,omitempty"` -} - // VictorOpsConfig configures notifications via VictorOps. type VictorOpsConfig struct { amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` @@ -746,76 +561,6 @@ func (c *SNSConfig) UnmarshalYAML(unmarshal func(any) error) error { return nil } -// TelegramConfig configures notifications via Telegram. -type TelegramConfig struct { - amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` - - HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` - - APIUrl *amcommoncfg.URL `yaml:"api_url" json:"api_url,omitempty"` - BotToken commoncfg.Secret `yaml:"bot_token,omitempty" json:"token,omitempty"` - BotTokenFile string `yaml:"bot_token_file,omitempty" json:"token_file,omitempty"` - ChatID int64 `yaml:"chat_id,omitempty" json:"chat,omitempty"` - ChatIDFile string `yaml:"chat_id_file,omitempty" json:"chat_file,omitempty"` - MessageThreadID int `yaml:"message_thread_id,omitempty" json:"message_thread_id,omitempty"` - Message string `yaml:"message,omitempty" json:"message,omitempty"` - DisableNotifications bool `yaml:"disable_notifications,omitempty" json:"disable_notifications,omitempty"` - ParseMode string `yaml:"parse_mode,omitempty" json:"parse_mode,omitempty"` -} - -// UnmarshalYAML implements the yaml.Unmarshaler interface. -func (c *TelegramConfig) UnmarshalYAML(unmarshal func(any) error) error { - *c = DefaultTelegramConfig - type plain TelegramConfig - if err := unmarshal((*plain)(c)); err != nil { - return err - } - if c.BotToken != "" && c.BotTokenFile != "" { - return errors.New("at most one of bot_token & bot_token_file must be configured") - } - if c.ChatID == 0 && c.ChatIDFile == "" { - return errors.New("missing chat_id or chat_id_file on telegram_config") - } - if c.ChatID != 0 && c.ChatIDFile != "" { - return errors.New("at most one of chat_id & chat_id_file must be configured") - } - if c.ParseMode != "" && - c.ParseMode != "Markdown" && - c.ParseMode != "MarkdownV2" && - c.ParseMode != "HTML" { - return errors.New("unknown parse_mode on telegram_config, must be Markdown, MarkdownV2, HTML or empty string") - } - return nil -} - -type MSTeamsV2Config struct { - amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` - HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` - WebhookURL *amcommoncfg.SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"` - WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"` - - Title string `yaml:"title,omitempty" json:"title,omitempty"` - Text string `yaml:"text,omitempty" json:"text,omitempty"` -} - -func (c *MSTeamsV2Config) UnmarshalYAML(unmarshal func(any) error) error { - *c = DefaultMSTeamsV2Config - type plain MSTeamsV2Config - if err := unmarshal((*plain)(c)); err != nil { - return err - } - - if c.WebhookURL == nil && c.WebhookURLFile == "" { - return errors.New("one of webhook_url or webhook_url_file must be configured") - } - - if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 { - return errors.New("at most one of webhook_url & webhook_url_file must be configured") - } - - return nil -} - type RocketchatAttachmentField struct { Short *bool `json:"short"` Title string `json:"title,omitempty"` diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go index fea22a215a8..47e45151d76 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go @@ -40,6 +40,7 @@ import ( "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/provider" "github.com/prometheus/alertmanager/store" + "github.com/prometheus/alertmanager/template" "github.com/prometheus/alertmanager/tracing" "github.com/prometheus/alertmanager/types" ) @@ -79,6 +80,7 @@ type Dispatcher struct { logger *slog.Logger recorder eventrecorder.Recorder + tmpl *template.Template startTimer *time.Timer state atomic.Int32 @@ -110,6 +112,7 @@ func NewDispatcher( logger *slog.Logger, recorder eventrecorder.Recorder, metrics *DispatcherMetrics, + tmpl *template.Template, ) *Dispatcher { if limits == nil { limits = nilLimits{} @@ -133,6 +136,7 @@ func NewDispatcher( recorder: recorder, metrics: metrics, limits: limits, + tmpl: tmpl, propagator: otel.GetTextMapPropagator(), } disp.state.Store(DispatcherStateUnknown) @@ -311,6 +315,7 @@ func (d *Dispatcher) LoadingDone() <-chan struct{} { type AlertGroup struct { Alerts alert.AlertSlice Labels model.LabelSet + RouteLabels model.LabelSet Receiver string GroupKey string RouteID string @@ -363,13 +368,6 @@ func (d *Dispatcher) Groups(ctx context.Context, routeFilter func(*Route) bool, // Process the snapshot without holding sync.Map locks for _, ag := range snapshot { - alertGroup := &AlertGroup{ - Labels: ag.labels, - Receiver: receiver, - GroupKey: ag.GroupKey(), - RouteID: ag.routeID, - } - alerts := ag.alerts.List() filteredAlerts := make([]*alert.Alert, 0, len(alerts)) for _, a := range alerts { @@ -393,6 +391,17 @@ func (d *Dispatcher) Groups(ctx context.Context, routeFilter func(*Route) bool, if len(filteredAlerts) == 0 { continue } + + // Compute RouteLabels() only now that the group will be returned: + // it may render templates on a cache miss, which is wasted work for + // groups filtered out above. + alertGroup := &AlertGroup{ + Labels: ag.labels, + RouteLabels: ag.RouteLabels(), + Receiver: receiver, + GroupKey: ag.GroupKey(), + RouteID: ag.routeID, + } alertGroup.Alerts = filteredAlerts alertGroup.AlertStatuses = make(map[model.Fingerprint]alert.AlertStatus, len(filteredAlerts)) for _, a := range filteredAlerts { @@ -478,7 +487,7 @@ func (d *Dispatcher) groupAlert(ctx context.Context, alert *alert.Alert, route * return } - ag := newAggrGroup(d.ctx, groupLabels, route, d.timeout, d.recorder, d.logger) + ag := newAggrGroup(d.ctx, groupLabels, route, d.timeout, d.recorder, d.logger, d.tmpl) // Insert the 1st alert in the group before starting the group's run() // function, to make sure that when the run() will be executed the 1st // alert is already there. @@ -613,6 +622,7 @@ type aggrGroup struct { alerts *store.Alerts marker marker.AlertMarker recorder eventrecorder.Recorder + tmpl *template.Template ctx context.Context cancel func() done chan struct{} @@ -620,6 +630,27 @@ type aggrGroup struct { timeout func(time.Duration) time.Duration running atomic.Bool flushIdx uint64 + + // routeLabels caches the route labels rendered against the group's current + // alerts, for the /api/v2/alerts/groups read path. It is rendered lazily and + // kept up to date with a generation counter rather than a lock, so that + // invalidation on the hot alert-ingestion path is a single atomic add. + // + // routeLabelsGen is bumped (by invalidateRouteLabels) whenever the alert set + // changes. Each cached render is tagged with the generation it was computed + // at; RouteLabels() treats the cache as valid only if its tag still equals + // the current generation. A render that races an invalidation is therefore + // tagged with a now-stale generation: it may be stored, but the next reader + // sees the mismatch and re-renders, so a stale value is never served. + routeLabels atomic.Pointer[renderedRouteLabels] + routeLabelsGen atomic.Uint64 +} + +// renderedRouteLabels is a cached route-label render tagged with the alert-set +// generation it was computed at. See aggrGroup.routeLabels. +type renderedRouteLabels struct { + gen uint64 + labels model.LabelSet } // newAggrGroup returns a new aggregation group. @@ -630,6 +661,7 @@ func newAggrGroup( to func(time.Duration) time.Duration, recorder eventrecorder.Recorder, logger *slog.Logger, + tmpl *template.Template, ) *aggrGroup { if to == nil { to = func(d time.Duration) time.Duration { return d } @@ -644,6 +676,7 @@ func newAggrGroup( alerts: store.NewAlerts(), marker: marker.NewAlertMarker(), recorder: recorder, + tmpl: tmpl, done: make(chan struct{}), flushIdx: 1, } @@ -674,6 +707,87 @@ func (ag *aggrGroup) String() string { return ag.GroupKey() } +// renderRouteLabels renders the route's labels as templates against the given +// alerts and the group's data. A route label value may be a template, so this +// allows it to reference group labels, other route labels, etc. +func (ag *aggrGroup) renderRouteLabels(alerts ...*alert.Alert) model.LabelSet { + // Nothing to render when the route has no labels (the common case) or there + // is no template engine. Skip building template data, which is O(n_alerts). + if len(ag.opts.Labels) == 0 || ag.tmpl == nil { + return model.LabelSet{} + } + + renderedRouteLabels := make(model.LabelSet, len(ag.opts.Labels)) + + // The notification reason is not available to route labels and is passed as ReasonUnknown. + data := ag.tmpl.Data(ag.opts.Receiver, ag.labels, ag.opts.Labels, notify.ReasonUnknown.String(), alerts...) + + logger := ag.logger.With("data", data) + + // Render every label through a single shared resolver so a label that + // cross-references another (via {{ routeLabels "x" }}) reuses the rendered + // value instead of re-rendering it per loop iteration. + render := ag.tmpl.RouteLabelRenderer(data) + for label, value := range ag.opts.Labels { + if rendered, err := render(string(label)); err == nil { + renderedRouteLabels[label] = model.LabelValue(rendered) + logger.Debug("rendered route label", "label", label, "value", rendered) + } else { + logger.Error("failed to render route label", "label", label, "value", string(value), "err", err) + } + } + + return renderedRouteLabels +} + +// RouteLabels returns the route labels rendered against the group's current +// alerts, caching the result. Both the read and the cache update are lock-free. +// The cache is invalidated by invalidateRouteLabels (a generation bump) after +// the alert set changes. +// +// Concurrent callers that all miss may render redundantly; that is acceptable +// because the only caller is the (cold) /alerts/groups API path. What must not +// happen — serving a render that predates an invalidation — is prevented by the +// generation tag. +func (ag *aggrGroup) RouteLabels() model.LabelSet { + // Load the cached value before the generation: if an invalidation happens + // between these two loads, we read the newer generation and treat the cache + // as a miss, which is safe. (Loading gen first could let us pair an old gen + // with a value cached for that gen and wrongly accept a stale render.) + cached := ag.routeLabels.Load() + gen := ag.routeLabelsGen.Load() + if cached != nil && cached.gen == gen { + return cached.labels + } + + alerts := ag.alerts.List() + + var labels model.LabelSet + if len(alerts) == 0 { + // Nothing to render against: e.g. all alerts resolved and deleted and + // the group is awaiting GC. Rendering route-label templates that + // reference .Alerts against an empty set would only log errors, and + // empty groups are excluded from the API response anyway. + labels = model.LabelSet{} + } else { + labels = ag.renderRouteLabels(alerts...) + } + + // Tag the render with the generation we observed before reading the alerts. + // If an invalidation raced this render, gen is already stale, so the next + // reader will see the mismatch and re-render rather than serve stale labels. + ag.routeLabels.Store(&renderedRouteLabels{gen: gen, labels: labels}) + return labels +} + +// invalidateRouteLabels marks the cached route labels stale. It must be called +// after the group's alert set has changed and the change is visible via +// ag.alerts, so that any render still in flight is tagged with a generation +// older than this one and will not be served. +func (ag *aggrGroup) invalidateRouteLabels() { + ag.routeLabelsGen.Add(1) +} + func (ag *aggrGroup) run(nf notifyFunc) { defer close(ag.done) defer ag.next.Stop() @@ -694,6 +808,7 @@ func (ag *aggrGroup) run(nf notifyFunc) { // Populate context with information needed along the pipeline. ctx = notify.WithGroupKey(ctx, ag.GroupKey()) ctx = notify.WithGroupLabels(ctx, ag.labels) + ctx = notify.WithRouteLabels(ctx, ag.opts.Labels) ctx = notify.WithReceiverName(ctx, ag.opts.Receiver) ctx = notify.WithRepeatInterval(ctx, ag.opts.RepeatInterval) ctx = notify.WithMuteTimeIntervals(ctx, ag.opts.MuteTimeIntervals) @@ -718,6 +833,10 @@ func (ag *aggrGroup) run(nf notifyFunc) { ) defer span.End() + // Render route labels against the batch of alerts that we are + // about to notify about. + ctx = notify.WithRouteLabels(ctx, ag.renderRouteLabels(alerts...)) + success := nf(ctx, alerts...) if !success { span.SetStatus(codes.Error, "notification failed") @@ -771,7 +890,11 @@ func (ag *aggrGroup) insert(ctx context.Context, alert *alert.Alert) bool { span.RecordError(err) ag.logger.Error(message, "err", err) } else { - ag.recorder.RecordEvent(ctx, notify.NewAlertGroupedEvent(ag.alertGroupInfo(), alert)) + ag.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + return notify.NewAlertGroupedEvent(ag.alertGroupInfo(), alert) + }) + // The alert set changed; the alert is already visible via ag.alerts. + ag.invalidateRouteLabels() } return true } @@ -822,6 +945,11 @@ func (ag *aggrGroup) flush(notify func(...*alert.Alert) bool) { if err := ag.alerts.DeleteIfNotModified(resolvedSlice, true); err != nil { ag.logger.Error("error on delete alerts", "err", err) } else { + if len(resolvedSlice) > 0 { + // The alert set changed; the deletion is already visible via + // ag.alerts. + ag.invalidateRouteLabels() + } // Delete markers for resolved alerts that are not in the store. for _, alert := range resolvedSlice { _, err := ag.alerts.Get(alert.Fingerprint()) @@ -839,7 +967,9 @@ func (ag *aggrGroup) recordResolvedEvents(resolved types.AlertSlice) { } groupInfo := ag.alertGroupInfo() for _, a := range resolved { - ag.recorder.RecordEvent(ag.ctx, notify.NewAlertResolvedEvent(groupInfo, a)) + ag.recorder.RecordEvent(ag.ctx, func() *eventrecorderpb.EventData { + return notify.NewAlertResolvedEvent(groupInfo, a) + }) } } diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/route.go b/vendor/github.com/prometheus/alertmanager/dispatch/route.go index 38b49524cae..6dcc9750e39 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/route.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/route.go @@ -16,6 +16,7 @@ package dispatch import ( "encoding/json" "fmt" + "maps" "sort" "strconv" "strings" @@ -36,6 +37,7 @@ var DefaultRouteOpts = RouteOpts{ GroupBy: map[model.LabelName]struct{}{}, GroupByAll: false, MuteTimeIntervals: []string{}, + Labels: model.LabelSet{}, } // A Route is a node that contains definitions of how to handle alerts. @@ -72,6 +74,15 @@ func newRoute(cr *config.Route, parent *Route, counter *int) *Route { opts = parent.RouteOpts } + // Merge parent route labels and cr.Labels into opts.Labels. Always merge + // into a fresh LabelSet so we never mutate the parent's map. + if len(cr.Labels) != 0 { + merged := model.LabelSet{} + maps.Copy(merged, opts.Labels) + maps.Copy(merged, cr.Labels) + opts.Labels = merged + } + if cr.Receiver != "" { opts.Receiver = cr.Receiver } @@ -249,6 +260,9 @@ type RouteOpts struct { // A list of time intervals for which the route is active. ActiveTimeIntervals []string + + // Merged labels from this route and all of its parent routes. + Labels model.LabelSet } func (ro *RouteOpts) String() string { diff --git a/vendor/github.com/prometheus/alertmanager/eventrecorder/config.go b/vendor/github.com/prometheus/alertmanager/eventrecorder/config.go index ff8ecf47f5b..622976c797a 100644 --- a/vendor/github.com/prometheus/alertmanager/eventrecorder/config.go +++ b/vendor/github.com/prometheus/alertmanager/eventrecorder/config.go @@ -23,12 +23,13 @@ type Config struct { FileOutputs []FileOutputConfig `yaml:"file_outputs,omitempty" json:"file_outputs,omitempty"` WebhookOutputs []WebhookOutputConfig `yaml:"webhook_outputs,omitempty" json:"webhook_outputs,omitempty"` KafkaOutputs []KafkaOutputConfig `yaml:"kafka_outputs,omitempty" json:"kafka_outputs,omitempty"` + StdoutOutputs []StdoutOutputConfig `yaml:"stdout_outputs,omitempty" json:"stdout_outputs,omitempty"` } // totalOutputs returns the number of configured outputs across all // destination kinds. func (c Config) totalOutputs() int { - return len(c.FileOutputs) + len(c.WebhookOutputs) + len(c.KafkaOutputs) + return len(c.FileOutputs) + len(c.WebhookOutputs) + len(c.KafkaOutputs) + len(c.StdoutOutputs) } // configEqual compares two Config values by their semantically @@ -38,7 +39,8 @@ func (c Config) totalOutputs() int { func configEqual(a, b Config) bool { if len(a.FileOutputs) != len(b.FileOutputs) || len(a.WebhookOutputs) != len(b.WebhookOutputs) || - len(a.KafkaOutputs) != len(b.KafkaOutputs) { + len(a.KafkaOutputs) != len(b.KafkaOutputs) || + len(a.StdoutOutputs) != len(b.StdoutOutputs) { return false } for i := range a.FileOutputs { @@ -56,5 +58,10 @@ func configEqual(a, b Config) bool { return false } } + for i := range a.StdoutOutputs { + if !a.StdoutOutputs[i].equal(b.StdoutOutputs[i]) { + return false + } + } return true } diff --git a/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.pb.go b/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.pb.go index fb508379795..f83b8cd0d27 100644 --- a/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.pb.go +++ b/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.pb.go @@ -1700,7 +1700,9 @@ type InhibitRule struct { TargetMatchers []*Matcher `protobuf:"bytes,2,rep,name=target_matchers,json=targetMatchers,proto3" json:"target_matchers,omitempty"` // Label names whose values must be equal between source and target // alerts for the inhibition to take effect. - EqualLabels []string `protobuf:"bytes,3,rep,name=equal_labels,json=equalLabels,proto3" json:"equal_labels,omitempty"` + EqualLabels []string `protobuf:"bytes,3,rep,name=equal_labels,json=equalLabels,proto3" json:"equal_labels,omitempty"` + // Name is the optional name of the inhibition rule. + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1756,6 +1758,13 @@ func (x *InhibitRule) GetEqualLabels() []string { return nil } +func (x *InhibitRule) GetName() string { + if x != nil { + return x.Name + } + return "" +} + // InhibitionMutedAlertEvent is emitted when one or more inhibition // rules suppress an alert. type InhibitionMutedAlertEvent struct { @@ -1938,11 +1947,12 @@ const file_eventrecorder_proto_rawDesc = "" + "\x16SilenceMutedAlertEvent\x122\n" + "\asilence\x18\x01 \x01(\v2\x18.eventrecorderpb.SilenceR\asilence\x12<\n" + "\vmuted_alert\x18\x02 \x01(\v2\x1b.eventrecorderpb.MutedAlertR\n" + - "mutedAlert\"\xb6\x01\n" + + "mutedAlert\"\xca\x01\n" + "\vInhibitRule\x12A\n" + "\x0fsource_matchers\x18\x01 \x03(\v2\x18.eventrecorderpb.MatcherR\x0esourceMatchers\x12A\n" + "\x0ftarget_matchers\x18\x02 \x03(\v2\x18.eventrecorderpb.MatcherR\x0etargetMatchers\x12!\n" + - "\fequal_labels\x18\x03 \x03(\tR\vequalLabels\"\xd5\x01\n" + + "\fequal_labels\x18\x03 \x03(\tR\vequalLabels\x12\x12\n" + + "\x04name\x18\x04 \x01(\tR\x04name\"\xd5\x01\n" + "\x19InhibitionMutedAlertEvent\x12A\n" + "\rinhibit_rules\x18\x01 \x03(\v2\x1c.eventrecorderpb.InhibitRuleR\finhibitRules\x12<\n" + "\vmuted_alert\x18\x02 \x01(\v2\x1b.eventrecorderpb.MutedAlertR\n" + diff --git a/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.proto b/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.proto index 3004b5e55cf..3de19298cd4 100644 --- a/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.proto +++ b/vendor/github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb/eventrecorder.proto @@ -373,6 +373,9 @@ message InhibitRule { // Label names whose values must be equal between source and target // alerts for the inhibition to take effect. repeated string equal_labels = 3; + + // Name is the optional name of the inhibition rule. + string name = 4; } // InhibitionMutedAlertEvent is emitted when one or more inhibition diff --git a/vendor/github.com/prometheus/alertmanager/eventrecorder/events.go b/vendor/github.com/prometheus/alertmanager/eventrecorder/events.go index 1eccba9eff9..4b5e5d58910 100644 --- a/vendor/github.com/prometheus/alertmanager/eventrecorder/events.go +++ b/vendor/github.com/prometheus/alertmanager/eventrecorder/events.go @@ -174,13 +174,14 @@ func SilenceAsProto(sil *silencepb.Silence) *eventrecorderpb.Silence { // InhibitRuleAsProto converts inhibit rule fields to an // eventrecorderpb.InhibitRule. It accepts the individual fields rather // than the InhibitRule struct to avoid an import cycle. -func InhibitRuleAsProto(sourceMatchers, targetMatchers labels.Matchers, equal map[model.LabelName]struct{}) *eventrecorderpb.InhibitRule { +func InhibitRuleAsProto(name string, sourceMatchers, targetMatchers labels.Matchers, equal map[model.LabelName]struct{}) *eventrecorderpb.InhibitRule { equalLabels := make([]string, 0, len(equal)) for label := range equal { equalLabels = append(equalLabels, string(label)) } slices.Sort(equalLabels) return &eventrecorderpb.InhibitRule{ + Name: name, SourceMatchers: MatchersAsProto(sourceMatchers), TargetMatchers: MatchersAsProto(targetMatchers), EqualLabels: equalLabels, diff --git a/vendor/github.com/prometheus/alertmanager/eventrecorder/recorder.go b/vendor/github.com/prometheus/alertmanager/eventrecorder/recorder.go index 49f978cddfe..7ce27ed218a 100644 --- a/vendor/github.com/prometheus/alertmanager/eventrecorder/recorder.go +++ b/vendor/github.com/prometheus/alertmanager/eventrecorder/recorder.go @@ -13,23 +13,12 @@ // Package eventrecorder provides a structured event recorder for // significant Alertmanager events. Events are serialized as JSON and -// fanned out to one or more configured destinations (JSONL file, -// webhook, kafka). +// fanned out to one or more configured destinations. // // RecordEvent never blocks the caller: events are serialized and // placed on a bounded in-memory queue. A background goroutine // drains the queue and sends to destinations. If the queue is full, // events are dropped and a metric is incremented. -// -// Package layout: -// -// - recorder.go Recorder core: types, write loop, fan-out. -// - metrics.go Prometheus metric definitions. -// - events.go Pure proto-conversion helpers and event constructors. -// - config.go Top-level Config: per-type output lists + equality. -// - file.go File output and its config. -// - webhook.go Webhook output and its config. -// - kafka.go Kafka output and its config. package eventrecorder import ( @@ -194,7 +183,7 @@ func buildOutputs(cfg Config, instance string, m *metrics, logger *slog.Logger) for _, wc := range cfg.WebhookOutputs { wo, err := NewWebhookOutput(wc, m.outputDrops, logger) if err != nil { - logger.Error("Failed to create webhook event recorder output", "url", wc.URL, "err", err) + logger.Error("Failed to create webhook event recorder output", "url", sanitizeSecretURL(wc.URL), "err", err) continue } outputs = append(outputs, wo) @@ -207,6 +196,9 @@ func buildOutputs(cfg Config, instance string, m *metrics, logger *slog.Logger) } outputs = append(outputs, ko) } + for range cfg.StdoutOutputs { + outputs = append(outputs, &StdoutOutput{}) + } return outputs } @@ -302,10 +294,16 @@ func (c *sharedRecorder) marshalAndSend(req writeRequest, outputs []Destination) // event is dropped (never blocks the caller). Recording only occurs // when the context has been decorated with WithEventRecording. // +// The event is supplied as a builder function rather than a value so +// that callers on hot read paths do not pay to construct an event +// (protobuf conversions, fingerprint slices, etc.) that would only be +// discarded when recording is disabled. The builder is invoked only +// after the recording gates pass, and exactly once. +// // The expensive protojson.Marshal call is deferred to the write-loop // goroutine so that the caller's hot path only pays for the proto // wrapping and a channel send. -func (r Recorder) RecordEvent(ctx context.Context, event *eventrecorderpb.EventData) { +func (r Recorder) RecordEvent(ctx context.Context, build func() *eventrecorderpb.EventData) { if r.core == nil || r.core.events == nil { return } @@ -313,6 +311,7 @@ func (r Recorder) RecordEvent(ctx context.Context, event *eventrecorderpb.EventD return } + event := build() eventType := extractEventType(event) wrappedEvent := &eventrecorderpb.Event{ diff --git a/vendor/github.com/prometheus/alertmanager/eventrecorder/stdout.go b/vendor/github.com/prometheus/alertmanager/eventrecorder/stdout.go new file mode 100644 index 00000000000..1b2652c4681 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/eventrecorder/stdout.go @@ -0,0 +1,58 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eventrecorder + +import ( + "os" + + "google.golang.org/protobuf/encoding/protojson" + + "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" +) + +// StdoutOutputConfig configures a stdout event recorder output. +// There are no required fields; the presence of an entry in +// stdout_outputs is sufficient to enable the output. +type StdoutOutputConfig struct{} + +// equal reports whether two stdout output configs are semantically equal. +// All StdoutOutputConfig values are identical since the type carries no fields. +func (c StdoutOutputConfig) equal(_ StdoutOutputConfig) bool { return true } + +// StdoutOutput writes events as newline-delimited JSON to os.Stdout. +// This is the recommended output for container deployments where stdout +// is captured by the runtime log driver (Docker, Kubernetes, etc.). +// +// Each event is serialized with protojson and followed by a newline so +// log collectors receive one self-contained JSON object per line. +type StdoutOutput struct{} + +// Name returns the stable identifier used in Prometheus metric labels. +func (s *StdoutOutput) Name() string { return "stdout" } + +// SendEvent serializes the event as a JSON line and writes it to stdout. +// It returns the byte count written (including the trailing newline) and +// any write error encountered. A serialization failure is wrapped in +// serializeError so the recorder attributes it to the correct metric. +func (s *StdoutOutput) SendEvent(event *eventrecorderpb.Event) (int, error) { + data, err := protojson.Marshal(event) + if err != nil { + return 0, &serializeError{err: err} + } + data = append(data, '\n') + return os.Stdout.Write(data) +} + +// Close is a no-op; os.Stdout is owned by the process, not by this output. +func (s *StdoutOutput) Close() error { return nil } diff --git a/vendor/github.com/prometheus/alertmanager/eventrecorder/webhook.go b/vendor/github.com/prometheus/alertmanager/eventrecorder/webhook.go index b2d4bc548a6..1a4972ae1bc 100644 --- a/vendor/github.com/prometheus/alertmanager/eventrecorder/webhook.go +++ b/vendor/github.com/prometheus/alertmanager/eventrecorder/webhook.go @@ -51,6 +51,14 @@ type WebhookOutputConfig struct { // 500ms). Successive attempts use exponential backoff (base * // 2^attempt). RetryBackoff model.Duration `yaml:"retry_backoff,omitempty" json:"retry_backoff,omitempty"` + // Batch enables sending events as JSON arrays instead of individual objects. + Batch bool `yaml:"batch,omitempty" json:"batch,omitempty"` + // BatchMaxEvents is the maximum number of events in one request (default 100). + BatchMaxEvents int `yaml:"batch_max_events,omitempty" json:"batch_max_events,omitempty"` + // BatchMaxBytes is the soft maximum encoded request size (default 1 MiB). + BatchMaxBytes int `yaml:"batch_max_bytes,omitempty" json:"batch_max_bytes,omitempty"` + // BatchFlushInterval is the maximum time an incomplete batch waits (default 100ms). + BatchFlushInterval model.Duration `yaml:"batch_flush_interval,omitempty" json:"batch_flush_interval,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface, validating @@ -72,6 +80,12 @@ func (c *WebhookOutputConfig) UnmarshalYAML(unmarshal func(any) error) error { if c.URL.Scheme == "" || c.URL.Host == "" { return errors.New("event_recorder webhook output requires an absolute http(s) url") } + if c.BatchMaxEvents < 0 || c.BatchMaxBytes < 0 || c.BatchFlushInterval < 0 { + return errors.New("event_recorder webhook batch settings cannot be negative") + } + if !c.Batch && (c.BatchMaxEvents != 0 || c.BatchMaxBytes != 0 || c.BatchFlushInterval != 0) { + return errors.New("event_recorder webhook batch settings require batch: true") + } return nil } @@ -100,6 +114,15 @@ func (c WebhookOutputConfig) equal(o WebhookOutputConfig) bool { if c.RetryBackoff != o.RetryBackoff { return false } + if c.Batch != o.Batch { + return false + } + if c.Batch && !httpBatchConfigsEqual( + newHTTPBatchConfig(c.BatchMaxEvents, c.BatchMaxBytes, c.BatchFlushInterval), + newHTTPBatchConfig(o.BatchMaxEvents, o.BatchMaxBytes, o.BatchFlushInterval), + ) { + return false + } return reflect.DeepEqual(c.HTTPConfig, o.HTTPConfig) } @@ -109,6 +132,9 @@ const ( defaultWebhookMaxRetries = 3 defaultWebhookRetryBackoff = 500 * time.Millisecond defaultWebhookMaxBackoff = 30 * time.Second + defaultHTTPBatchMaxEvents = 100 + defaultHTTPBatchMaxBytes = 1 << 20 + defaultHTTPBatchInterval = 100 * time.Millisecond webhookQueueSize = 1024 ) @@ -121,19 +147,58 @@ type WebhookOutput struct { client *http.Client url string name string + kind string + batch *httpBatchConfig maxRetries int retryBackoff time.Duration maxBackoff time.Duration logger *slog.Logger drops prometheus.Counter work chan []byte + batches chan []byte done chan struct{} cancel chan struct{} // closed after drain to abort remaining retries wg sync.WaitGroup } +type httpBatchConfig struct { + maxEvents int + maxBytes int + flushInterval time.Duration +} + // NewWebhookOutput creates a new webhook-based event recorder output. func NewWebhookOutput(cfg WebhookOutputConfig, dropsCounter *prometheus.CounterVec, logger *slog.Logger) (*WebhookOutput, error) { + var batch *httpBatchConfig + if cfg.Batch { + batch = newHTTPBatchConfig(cfg.BatchMaxEvents, cfg.BatchMaxBytes, cfg.BatchFlushInterval) + } + return newWebhookOutput(cfg, "webhook", batch, dropsCounter, logger) +} + +func newHTTPBatchConfig(maxEvents, maxBytes int, flushInterval model.Duration) *httpBatchConfig { + batch := &httpBatchConfig{ + maxEvents: defaultHTTPBatchMaxEvents, + maxBytes: defaultHTTPBatchMaxBytes, + flushInterval: defaultHTTPBatchInterval, + } + if maxEvents > 0 { + batch.maxEvents = maxEvents + } + if maxBytes > 0 { + batch.maxBytes = maxBytes + } + if flushInterval > 0 { + batch.flushInterval = time.Duration(flushInterval) + } + return batch +} + +func httpBatchConfigsEqual(a, b *httpBatchConfig) bool { + return *a == *b +} + +func newWebhookOutput(cfg WebhookOutputConfig, kind string, batch *httpBatchConfig, dropsCounter *prometheus.CounterVec, logger *slog.Logger) (*WebhookOutput, error) { httpCfg := commoncfg.DefaultHTTPClientConfig if cfg.HTTPConfig != nil { httpCfg = *cfg.HTTPConfig @@ -141,7 +206,7 @@ func NewWebhookOutput(cfg WebhookOutputConfig, dropsCounter *prometheus.CounterV client, err := commoncfg.NewClientFromConfig(httpCfg, "eventrecorder") if err != nil { - return nil, fmt.Errorf("creating HTTP client for event recorder webhook: %w", err) + return nil, fmt.Errorf("creating HTTP client for event recorder %s: %w", kind, err) } timeout := defaultWebhookTimeout @@ -166,23 +231,36 @@ func NewWebhookOutput(cfg WebhookOutputConfig, dropsCounter *prometheus.CounterV } urlStr := cfg.URL.String() + name := fmt.Sprintf("%s:%s", kind, sanitizeURL(urlStr)) wo := &WebhookOutput{ client: client, url: urlStr, - name: fmt.Sprintf("webhook:%s", sanitizeURL(urlStr)), + name: name, + kind: kind, + batch: batch, maxRetries: maxRetries, retryBackoff: retryBackoff, maxBackoff: defaultWebhookMaxBackoff, logger: logger, - drops: dropsCounter.WithLabelValues(fmt.Sprintf("webhook:%s", sanitizeURL(urlStr))), + drops: dropsCounter.WithLabelValues(name), work: make(chan []byte, webhookQueueSize), done: make(chan struct{}), cancel: make(chan struct{}), } - for range workers { + if batch != nil { wo.wg.Add(1) - go wo.worker() + wo.batches = make(chan []byte, workers) + go wo.batchLoop() + for range workers { + wo.wg.Add(1) + go wo.batchDeliveryWorker() + } + } else { + for range workers { + wo.wg.Add(1) + go wo.worker() + } } return wo, nil @@ -202,6 +280,13 @@ func sanitizeURL(raw string) string { return u.String() } +func sanitizeSecretURL(u *amcommoncfg.SecretURL) string { + if u == nil || u.URL == nil { + return "" + } + return sanitizeURL(u.String()) +} + // Name returns a stable identifier for this output. The URL is // sanitized to avoid leaking credentials. func (wo *WebhookOutput) Name() string { @@ -221,7 +306,7 @@ func (wo *WebhookOutput) SendEvent(event *eventrecorderpb.Event) (int, error) { case wo.work <- data: default: wo.drops.Inc() - wo.logger.Warn("Event recorder webhook queue full, dropping event", "output", wo.name) + wo.logger.Warn("Event recorder HTTP output queue full, dropping event", "output", wo.name) } return len(data), nil } @@ -246,13 +331,97 @@ func (wo *WebhookOutput) worker() { } } +func (wo *WebhookOutput) batchLoop() { + defer wo.wg.Done() + defer close(wo.batches) + + batch := make([][]byte, 0, min(wo.batch.maxEvents, webhookQueueSize)) + batchSize := 2 // Opening and closing brackets. + var timer *time.Timer + var timerC <-chan time.Time + + stopTimer := func() { + if timer != nil { + timer.Stop() + timer = nil + timerC = nil + } + } + flush := func() { + stopTimer() + if len(batch) == 0 { + return + } + wo.batches <- jsonArray(batch, batchSize) + batch = batch[:0] + batchSize = 2 + } + add := func(data []byte) { + additionalSize := len(data) + if len(batch) > 0 { + additionalSize++ // Comma separator. + } + if len(batch) > 0 && (len(batch) >= wo.batch.maxEvents || batchSize+additionalSize > wo.batch.maxBytes) { + flush() + additionalSize = len(data) + } + batch = append(batch, data) + batchSize += additionalSize + if len(batch) == 1 { + timer = time.NewTimer(wo.batch.flushInterval) + timerC = timer.C + } + if len(batch) >= wo.batch.maxEvents || batchSize >= wo.batch.maxBytes { + flush() + } + } + + for { + select { + case data := <-wo.work: + add(data) + case <-timerC: + flush() + case <-wo.done: + for { + select { + case data := <-wo.work: + add(data) + default: + flush() + return + } + } + } + } +} + +func (wo *WebhookOutput) batchDeliveryWorker() { + defer wo.wg.Done() + for data := range wo.batches { + wo.postWithRetry(data) + } +} + +func jsonArray(events [][]byte, size int) []byte { + data := make([]byte, 0, size) + data = append(data, '[') + for i, event := range events { + if i > 0 { + data = append(data, ',') + } + data = append(data, event...) + } + return append(data, ']') +} + func (wo *WebhookOutput) postWithRetry(data []byte) { for attempt := range wo.maxRetries { err := wo.post(data) if err == nil { return } - wo.logger.Warn("Event recorder webhook POST failed", "output", wo.name, "attempt", attempt+1, "err", err) + wo.logger.Warn("Event recorder HTTP output POST failed", "output", wo.name, "attempt", attempt+1, "err", err) if attempt < wo.maxRetries-1 { backoff := min(wo.retryBackoff< 0 { + return errors.New("at most one of webhook_url & webhook_url_file must be configured") + } + + return nil +} diff --git a/vendor/github.com/prometheus/alertmanager/notify/msteamsv2/msteamsv2.go b/vendor/github.com/prometheus/alertmanager/notify/msteamsv2/msteamsv2.go index dc87666238a..5602d503dcc 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/msteamsv2/msteamsv2.go +++ b/vendor/github.com/prometheus/alertmanager/notify/msteamsv2/msteamsv2.go @@ -29,7 +29,6 @@ import ( amcommoncfg "github.com/prometheus/alertmanager/config/common" - "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/notify" "github.com/prometheus/alertmanager/template" "github.com/prometheus/alertmanager/types" @@ -42,7 +41,7 @@ const ( ) type Notifier struct { - conf *config.MSTeamsV2Config + conf *MSTeamsV2Config tmpl *template.Template logger *slog.Logger client *http.Client @@ -86,7 +85,7 @@ type teamsMessage struct { } // New returns a new notifier that uses the Microsoft Teams Power Platform connector. -func New(c *config.MSTeamsV2Config, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *MSTeamsV2Config, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := notify.NewClientWithTracing(*c.HTTPConfig, "msteamsv2", httpOpts...) if err != nil { return nil, err diff --git a/vendor/github.com/prometheus/alertmanager/notify/opsgenie/config.go b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/config.go new file mode 100644 index 00000000000..03fd315a0ef --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/config.go @@ -0,0 +1,104 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package opsgenie + +import ( + "errors" + "fmt" + "regexp" + "strings" + + commoncfg "github.com/prometheus/common/config" + + amcommoncfg "github.com/prometheus/alertmanager/config/common" +) + +// DefaultOpsGenieConfig defines default values for OpsGenie configurations. +var DefaultOpsGenieConfig = OpsGenieConfig{ + NotifierConfig: amcommoncfg.NotifierConfig{ + VSendResolved: true, + }, + Message: `{{ template "opsgenie.default.message" . }}`, + Description: `{{ template "opsgenie.default.description" . }}`, + Source: `{{ template "opsgenie.default.source" . }}`, + // TODO: Add a details field with all the alerts. +} + +var opsgenieTypeMatcher = regexp.MustCompile(opsgenieValidTypesRe) + +// OpsGenieConfig configures notifications via OpsGenie. +type OpsGenieConfig struct { + amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` + + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + + APIKey commoncfg.Secret `yaml:"api_key,omitempty" json:"api_key,omitempty"` + APIKeyFile string `yaml:"api_key_file,omitempty" json:"api_key_file,omitempty"` + APIURL *amcommoncfg.URL `yaml:"api_url,omitempty" json:"api_url,omitempty"` + Message string `yaml:"message,omitempty" json:"message,omitempty"` + Description string `yaml:"description,omitempty" json:"description,omitempty"` + Source string `yaml:"source,omitempty" json:"source,omitempty"` + Details map[string]string `yaml:"details,omitempty" json:"details,omitempty"` + Entity string `yaml:"entity,omitempty" json:"entity,omitempty"` + Responders []OpsGenieConfigResponder `yaml:"responders,omitempty" json:"responders,omitempty"` + Actions string `yaml:"actions,omitempty" json:"actions,omitempty"` + Tags string `yaml:"tags,omitempty" json:"tags,omitempty"` + Note string `yaml:"note,omitempty" json:"note,omitempty"` + Priority string `yaml:"priority,omitempty" json:"priority,omitempty"` + UpdateAlerts bool `yaml:"update_alerts,omitempty" json:"update_alerts,omitempty"` +} + +const opsgenieValidTypesRe = `^(team|teams|user|escalation|schedule)$` + +// UnmarshalYAML implements the yaml.Unmarshaler interface. +func (c *OpsGenieConfig) UnmarshalYAML(unmarshal func(any) error) error { + *c = DefaultOpsGenieConfig + type plain OpsGenieConfig + if err := unmarshal((*plain)(c)); err != nil { + return err + } + + if c.APIKey != "" && len(c.APIKeyFile) > 0 { + return errors.New("at most one of api_key & api_key_file must be configured") + } + + for _, r := range c.Responders { + if r.ID == "" && r.Username == "" && r.Name == "" { + return fmt.Errorf("opsGenieConfig responder %v has to have at least one of id, username or name specified", r) + } + + isTemplated, err := amcommoncfg.ContainsTemplating(r.Type) + if err != nil { + return fmt.Errorf("opsGenieConfig responder %v type contains invalid template syntax: %w", r, err) + } + if !isTemplated { + r.Type = strings.ToLower(r.Type) + if !opsgenieTypeMatcher.MatchString(r.Type) { + return fmt.Errorf("opsGenieConfig responder %v type does not match valid options %s", r, opsgenieValidTypesRe) + } + } + } + + return nil +} + +type OpsGenieConfigResponder struct { + // One of those 3 should be filled. + ID string `yaml:"id,omitempty" json:"id,omitempty"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` + Username string `yaml:"username,omitempty" json:"username,omitempty"` + + // team, user, escalation, schedule etc. + Type string `yaml:"type,omitempty" json:"type,omitempty"` +} diff --git a/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go index a267b45e700..96a84894e60 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go +++ b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go @@ -27,7 +27,6 @@ import ( commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" - "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/notify" "github.com/prometheus/alertmanager/template" "github.com/prometheus/alertmanager/types" @@ -38,7 +37,7 @@ const maxMessageLenRunes = 130 // Notifier implements a Notifier for OpsGenie notifications. type Notifier struct { - conf *config.OpsGenieConfig + conf *OpsGenieConfig tmpl *template.Template logger *slog.Logger client *http.Client @@ -46,7 +45,7 @@ type Notifier struct { } // New returns a new OpsGenie notifier. -func New(c *config.OpsGenieConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *OpsGenieConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := notify.NewClientWithTracing(*c.HTTPConfig, "opsgenie", httpOpts...) if err != nil { return nil, err diff --git a/vendor/github.com/prometheus/alertmanager/notify/pagerduty/config.go b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/config.go new file mode 100644 index 00000000000..98ba23b4e5d --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/config.go @@ -0,0 +1,113 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pagerduty + +import ( + "errors" + "time" + + commoncfg "github.com/prometheus/common/config" + + amcommoncfg "github.com/prometheus/alertmanager/config/common" +) + +var ( + // DefaultPagerdutyDetails defines the default values for PagerDuty details. + DefaultPagerdutyDetails = map[string]any{ + "firing": `{{ .Alerts.Firing | toJson }}`, + "resolved": `{{ .Alerts.Resolved | toJson }}`, + "num_firing": `{{ .Alerts.Firing | len }}`, + "num_resolved": `{{ .Alerts.Resolved | len }}`, + } + + // DefaultPagerdutyConfig defines default values for PagerDuty configurations. + DefaultPagerdutyConfig = PagerdutyConfig{ + NotifierConfig: amcommoncfg.NotifierConfig{ + VSendResolved: true, + }, + Description: `{{ template "pagerduty.default.description" .}}`, + Client: `{{ template "pagerduty.default.client" . }}`, + ClientURL: `{{ template "pagerduty.default.clientURL" . }}`, + } +) + +// PagerdutyConfig configures notifications via PagerDuty. +type PagerdutyConfig struct { + amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` + + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + + ServiceKey commoncfg.Secret `yaml:"service_key,omitempty" json:"service_key,omitempty"` + ServiceKeyFile string `yaml:"service_key_file,omitempty" json:"service_key_file,omitempty"` + RoutingKey commoncfg.Secret `yaml:"routing_key,omitempty" json:"routing_key,omitempty"` + RoutingKeyFile string `yaml:"routing_key_file,omitempty" json:"routing_key_file,omitempty"` + URL *amcommoncfg.URL `yaml:"url,omitempty" json:"url,omitempty"` + Client string `yaml:"client,omitempty" json:"client,omitempty"` + ClientURL string `yaml:"client_url,omitempty" json:"client_url,omitempty"` + Description string `yaml:"description,omitempty" json:"description,omitempty"` + Details map[string]any `yaml:"details,omitempty" json:"details,omitempty"` + Images []PagerdutyImage `yaml:"images,omitempty" json:"images,omitempty"` + Links []PagerdutyLink `yaml:"links,omitempty" json:"links,omitempty"` + Source string `yaml:"source,omitempty" json:"source,omitempty"` + Severity string `yaml:"severity,omitempty" json:"severity,omitempty"` + Class string `yaml:"class,omitempty" json:"class,omitempty"` + Component string `yaml:"component,omitempty" json:"component,omitempty"` + Group string `yaml:"group,omitempty" json:"group,omitempty"` + // Timeout is the maximum time allowed to invoke the pagerduty. Setting this to 0 + // does not impose a timeout. + Timeout time.Duration `yaml:"timeout" json:"timeout"` +} + +// PagerdutyLink is a link. +type PagerdutyLink struct { + Href string `yaml:"href,omitempty" json:"href,omitempty"` + Text string `yaml:"text,omitempty" json:"text,omitempty"` +} + +// PagerdutyImage is an image. +type PagerdutyImage struct { + Src string `yaml:"src,omitempty" json:"src,omitempty"` + Alt string `yaml:"alt,omitempty" json:"alt,omitempty"` + Href string `yaml:"href,omitempty" json:"href,omitempty"` +} + +// UnmarshalYAML implements the yaml.Unmarshaler interface. +func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(any) error) error { + *c = DefaultPagerdutyConfig + type plain PagerdutyConfig + if err := unmarshal((*plain)(c)); err != nil { + return err + } + if c.RoutingKey == "" && c.ServiceKey == "" && c.RoutingKeyFile == "" && c.ServiceKeyFile == "" { + return errors.New("missing service or routing key in PagerDuty config") + } + if len(c.RoutingKey) > 0 && len(c.RoutingKeyFile) > 0 { + return errors.New("at most one of routing_key & routing_key_file must be configured") + } + if len(c.ServiceKey) > 0 && len(c.ServiceKeyFile) > 0 { + return errors.New("at most one of service_key & service_key_file must be configured") + } + if c.Details == nil { + c.Details = make(map[string]any) + } + if c.Source == "" { + c.Source = c.Client + } + for k, v := range DefaultPagerdutyDetails { + if _, ok := c.Details[k]; !ok { + c.Details[k] = v + } + } + return nil +} diff --git a/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go index 85327239923..7f9fa002d5f 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go +++ b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go @@ -29,7 +29,6 @@ import ( commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" - "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/notify" "github.com/prometheus/alertmanager/template" "github.com/prometheus/alertmanager/types" @@ -45,7 +44,7 @@ const ( // Notifier implements a Notifier for PagerDuty notifications. type Notifier struct { - conf *config.PagerdutyConfig + conf *PagerdutyConfig tmpl *template.Template logger *slog.Logger apiV1 string // for tests. @@ -54,7 +53,7 @@ type Notifier struct { } // New returns a new PagerDuty notifier. -func New(c *config.PagerdutyConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *PagerdutyConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := notify.NewClientWithTracing(*c.HTTPConfig, "pagerduty", httpOpts...) if err != nil { return nil, err diff --git a/vendor/github.com/prometheus/alertmanager/notify/retry_stage.go b/vendor/github.com/prometheus/alertmanager/notify/retry_stage.go index 7734ffe4f10..1fe08cd3854 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/retry_stage.go +++ b/vendor/github.com/prometheus/alertmanager/notify/retry_stage.go @@ -19,7 +19,7 @@ import ( "log/slog" "time" - "github.com/cenkalti/backoff/v4" + "github.com/cenkalti/backoff/v5" "github.com/prometheus/common/model" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -27,6 +27,7 @@ import ( "github.com/prometheus/alertmanager/alert" "github.com/prometheus/alertmanager/eventrecorder" + "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" ) // RetryStage notifies via passed integration with exponential backoff until it @@ -107,8 +108,9 @@ func (r RetryStage) exec(ctx context.Context, l *slog.Logger, alerts ...*alert.A sent = alerts } + // backoff/v5's ExponentialBackOff never returns Stop from NextBackOff, so + // the ticker retries indefinitely until the context is canceled. b := backoff.NewExponentialBackOff() - b.MaxElapsedTime = 0 // Always retry. tick := backoff.NewTicker(b) defer tick.Stop() @@ -178,7 +180,9 @@ func (r RetryStage) exec(ctx context.Context, l *slog.Logger, alerts ...*alert.A l.Info("Notify success") } - r.recorder.RecordEvent(ctx, NewNotificationEvent(ctx, sent, r.integration)) + r.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + return NewNotificationEvent(ctx, sent, r.integration) + }) return ctx, alerts, nil } case <-ctx.Done(): diff --git a/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go b/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go index 873e3328d1a..8cc6da5806a 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go +++ b/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go @@ -182,7 +182,16 @@ func (n *Notifier) createSNSClient(ctx context.Context, tmpl func(string) string return nil, fmt.Errorf("failed to load base config for STS: %w", err) } stsClient := sts.NewFromConfig(stsCfg) - stsProvider := stscreds.NewAssumeRoleProvider(stsClient, n.conf.Sigv4.RoleARN) + stsProvider := stscreds.NewAssumeRoleProvider( + stsClient, + n.conf.Sigv4.RoleARN, + // This adds an optional external_id configuration field that is passed to STS AssumeRole when role_arn is specified. + func(o *stscreds.AssumeRoleOptions) { + if n.conf.Sigv4.ExternalID != "" { + o.ExternalID = aws.String(n.conf.Sigv4.ExternalID) + } + }, + ) // Add the AssumeRole provider to the options for the SNS client config. snsCfgOpts = append(snsCfgOpts, awsconfig.WithCredentialsProvider(aws.NewCredentialsCache(stsProvider))) } diff --git a/vendor/github.com/prometheus/alertmanager/notify/telegram/config.go b/vendor/github.com/prometheus/alertmanager/notify/telegram/config.go new file mode 100644 index 00000000000..01fa674e259 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/notify/telegram/config.go @@ -0,0 +1,73 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package telegram + +import ( + "errors" + + commoncfg "github.com/prometheus/common/config" + + amcommoncfg "github.com/prometheus/alertmanager/config/common" +) + +var DefaultTelegramConfig = TelegramConfig{ + NotifierConfig: amcommoncfg.NotifierConfig{ + VSendResolved: true, + }, + DisableNotifications: false, + Message: `{{ template "telegram.default.message" . }}`, + ParseMode: "HTML", +} + +// TelegramConfig configures notifications via Telegram. +type TelegramConfig struct { + amcommoncfg.NotifierConfig `yaml:",inline" json:",inline"` + + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + + APIUrl *amcommoncfg.URL `yaml:"api_url" json:"api_url,omitempty"` + BotToken commoncfg.Secret `yaml:"bot_token,omitempty" json:"token,omitempty"` + BotTokenFile string `yaml:"bot_token_file,omitempty" json:"token_file,omitempty"` + ChatID int64 `yaml:"chat_id,omitempty" json:"chat,omitempty"` + ChatIDFile string `yaml:"chat_id_file,omitempty" json:"chat_file,omitempty"` + MessageThreadID int `yaml:"message_thread_id,omitempty" json:"message_thread_id,omitempty"` + Message string `yaml:"message,omitempty" json:"message,omitempty"` + DisableNotifications bool `yaml:"disable_notifications,omitempty" json:"disable_notifications,omitempty"` + ParseMode string `yaml:"parse_mode,omitempty" json:"parse_mode,omitempty"` +} + +// UnmarshalYAML implements the yaml.Unmarshaler interface. +func (c *TelegramConfig) UnmarshalYAML(unmarshal func(any) error) error { + *c = DefaultTelegramConfig + type plain TelegramConfig + if err := unmarshal((*plain)(c)); err != nil { + return err + } + if c.BotToken != "" && c.BotTokenFile != "" { + return errors.New("at most one of bot_token & bot_token_file must be configured") + } + if c.ChatID == 0 && c.ChatIDFile == "" { + return errors.New("missing chat_id or chat_id_file on telegram_config") + } + if c.ChatID != 0 && c.ChatIDFile != "" { + return errors.New("at most one of chat_id & chat_id_file must be configured") + } + if c.ParseMode != "" && + c.ParseMode != "Markdown" && + c.ParseMode != "MarkdownV2" && + c.ParseMode != "HTML" { + return errors.New("unknown parse_mode on telegram_config, must be Markdown, MarkdownV2, HTML or empty string") + } + return nil +} diff --git a/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go b/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go index 07bbedbbe8f..82919cf5f61 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go +++ b/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go @@ -25,7 +25,6 @@ import ( commoncfg "github.com/prometheus/common/config" "gopkg.in/telebot.v3" - "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/notify" "github.com/prometheus/alertmanager/template" "github.com/prometheus/alertmanager/types" @@ -36,7 +35,7 @@ const maxMessageLenRunes = 4096 // Notifier implements a Notifier for telegram notifications. type Notifier struct { - conf *config.TelegramConfig + conf *TelegramConfig tmpl *template.Template logger *slog.Logger client *telebot.Bot @@ -44,7 +43,7 @@ type Notifier struct { } // New returns a new Telegram notification handler. -func New(conf *config.TelegramConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(conf *TelegramConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { httpclient, err := notify.NewClientWithTracing(*conf.HTTPConfig, "telegram", httpOpts...) if err != nil { return nil, err diff --git a/vendor/github.com/prometheus/alertmanager/notify/util.go b/vendor/github.com/prometheus/alertmanager/notify/util.go index a99e2b067c7..fe4c9ea508f 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/util.go +++ b/vendor/github.com/prometheus/alertmanager/notify/util.go @@ -204,12 +204,18 @@ func GetTemplateData(ctx context.Context, tmpl *template.Template, alerts []*typ if !ok { l.Error("Missing group labels") } + // Route labels are optional (a route may have none, and some callers omit + // them); absence is not an error and a nil LabelSet is handled downstream. + routeLabels, _ := RouteLabels(ctx) notificationReason, ok := NotificationReason(ctx) if !ok { l.Error("Missing notification reason") notificationReason = ReasonUnknown } - return tmpl.Data(recv, groupLabels, notificationReason.String(), alerts...) + data := tmpl.Data(recv, groupLabels, routeLabels, notificationReason.String(), alerts...) + // Route labels are pre-rendered by the dispatcher; don't execute them again. + template.MarkRouteLabelsRendered(data) + return data } func readAll(r io.Reader) string { @@ -284,6 +290,8 @@ const ( ServerErrorReason ContextCanceledReason ContextDeadlineExceededReason + AuthErrorReason + RateLimitedReason ) func (s Reason) String() string { @@ -298,16 +306,34 @@ func (s Reason) String() string { return "contextCanceled" case ContextDeadlineExceededReason: return "contextDeadlineExceeded" + case AuthErrorReason: + return "authError" + case RateLimitedReason: + return "rateLimited" default: panic(fmt.Sprintf("unknown Reason: %d", s)) } } // possibleFailureReasonCategory is a list of possible failure reason. -var possibleFailureReasonCategory = []string{DefaultReason.String(), ClientErrorReason.String(), ServerErrorReason.String(), ContextCanceledReason.String(), ContextDeadlineExceededReason.String()} +var possibleFailureReasonCategory = []string{ + DefaultReason.String(), + ClientErrorReason.String(), + ServerErrorReason.String(), + ContextCanceledReason.String(), + ContextDeadlineExceededReason.String(), + AuthErrorReason.String(), + RateLimitedReason.String(), +} // GetFailureReasonFromStatusCode returns the reason for the failure based on the status code provided. func GetFailureReasonFromStatusCode(statusCode int) Reason { + switch statusCode { + case http.StatusUnauthorized, http.StatusForbidden: + return AuthErrorReason + case http.StatusTooManyRequests: + return RateLimitedReason + } if statusCode/100 == 4 { return ClientErrorReason } diff --git a/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go b/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go index 922ea543d5d..949bb614f85 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go +++ b/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go @@ -108,7 +108,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) shouldRetry, err := n.retrier.Check(resp.StatusCode, resp.Body) if err != nil { - return shouldRetry, err + return shouldRetry, notify.NewErrorWithReason(notify.GetFailureReasonFromStatusCode(resp.StatusCode), err) } return false, nil diff --git a/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go b/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go index d4e662804b1..7646eb9fdf1 100644 --- a/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go +++ b/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go @@ -29,6 +29,7 @@ import ( "go.opentelemetry.io/otel/trace" "github.com/prometheus/alertmanager/eventrecorder" + "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/featurecontrol" "github.com/prometheus/alertmanager/provider" "github.com/prometheus/alertmanager/store" @@ -347,7 +348,9 @@ func (a *Alerts) Put(ctx context.Context, alerts ...*types.Alert) error { a.callback.PostStore(alert, existing) if !existing { - a.recorder.RecordEvent(ctx, eventrecorder.NewAlertCreatedEvent(alert)) + a.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + return eventrecorder.NewAlertCreatedEvent(alert) + }) } metadata := map[string]string{} diff --git a/vendor/github.com/prometheus/alertmanager/silence/silence.go b/vendor/github.com/prometheus/alertmanager/silence/silence.go index d2fd4f10eed..c584901937c 100644 --- a/vendor/github.com/prometheus/alertmanager/silence/silence.go +++ b/vendor/github.com/prometheus/alertmanager/silence/silence.go @@ -32,7 +32,6 @@ import ( "sync" "time" - "github.com/coder/quartz" uuid "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -48,6 +47,7 @@ import ( "github.com/prometheus/alertmanager/alert" "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/eventrecorder" + "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/marker" "github.com/prometheus/alertmanager/matcher/compat" "github.com/prometheus/alertmanager/pkg/labels" @@ -285,9 +285,11 @@ func (s *Silencer) Mutes(ctx context.Context, lset model.LabelSet) bool { activeIDs = append(activeIDs, sil.Id) allIDs = append(allIDs, sil.Id) - s.recorder.RecordEvent(ctx, eventrecorder.NewSilenceMutedAlertEvent( - eventrecorder.SilenceAsProto(sil), fp, lset, - )) + s.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + return eventrecorder.NewSilenceMutedAlertEvent( + eventrecorder.SilenceAsProto(sil), fp, lset, + ) + }) default: // Do nothing, silence has expired in the meantime. } @@ -331,8 +333,6 @@ func (s *Silencer) PostGC(ff model.Fingerprints) { // Silences holds a silence state that can be modified, queried, and snapshot. type Silences struct { - clock quartz.Clock - logger *slog.Logger metrics *metrics retention time.Duration @@ -526,7 +526,6 @@ func New(o Options) (*Silences, error) { } s := &Silences{ - clock: quartz.NewReal(), mi: make(matcherIndex, 512), vi: make(versionIndex, 0, 512), logger: promslog.NewNopLogger(), @@ -567,7 +566,7 @@ func New(o Options) (*Silences, error) { } func (s *Silences) nowUTC() time.Time { - return s.clock.Now().UTC() + return time.Now().UTC() } // updateSizeMetrics updates the size metrics for state, matcher index, and version index. @@ -589,7 +588,7 @@ func (s *Silences) Maintenance(interval time.Duration, snapf string, stopc <-cha s.logger.Error("interval or stop signal are missing - not running maintenance") return } - t := s.clock.NewTicker(interval) + t := time.NewTicker(interval) defer t.Stop() var doMaintenance MaintenanceFunc @@ -627,7 +626,7 @@ func (s *Silences) Maintenance(interval time.Duration, snapf string, stopc <-cha s.metrics.maintenanceErrorsTotal.Inc() return err } - s.logger.Debug("Maintenance done", "duration", s.clock.Since(start), "size", size) + s.logger.Debug("Maintenance done", "duration", time.Since(start), "size", size) return nil } @@ -877,9 +876,11 @@ func (s *Silences) Set(ctx context.Context, sil *pb.Silence) error { return err } if changed { - s.recorder.RecordEvent(ctx, eventrecorder.NewSilenceUpdatedEvent( - eventrecorder.SilenceAsProto(sil), - )) + s.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + return eventrecorder.NewSilenceUpdatedEvent( + eventrecorder.SilenceAsProto(sil), + ) + }) } return nil } @@ -925,9 +926,11 @@ func (s *Silences) Set(ctx context.Context, sil *pb.Silence) error { return err } if added { - s.recorder.RecordEvent(ctx, eventrecorder.NewSilenceCreatedEvent( - eventrecorder.SilenceAsProto(sil), - )) + s.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + return eventrecorder.NewSilenceCreatedEvent( + eventrecorder.SilenceAsProto(sil), + ) + }) } return nil } @@ -1359,9 +1362,11 @@ func (s state) MarshalBinary() ([]byte, error) { var buf bytes.Buffer for _, e := range s { - if _, err := protodelim.MarshalTo(&buf, e); err != nil { + b, err := marshalMeshSilence(e) + if err != nil { return nil, err } + buf.Write(b) } return buf.Bytes(), nil } @@ -1392,7 +1397,9 @@ func decodeState(r io.Reader) (state, error) { // the first matcher set to the matchers field for backward compatibility with // older alertmanager versions. func prepareSilenceForMarshalling(sil *pb.Silence) { - if len(sil.MatcherSets) > 0 { + // The nil check is here because of rare cases where this function + // is called on a nil silence. It's up to the caller to decide if it's a bug + if sil != nil && len(sil.MatcherSets) > 0 { sil.Matchers = sil.MatcherSets[0].Matchers } } diff --git a/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go b/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go index c3454fb2936..4694f7989c2 100644 --- a/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go +++ b/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.pb.go @@ -271,9 +271,15 @@ type Silence struct { Annotations map[string]string `protobuf:"bytes,10,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Multiple matcher sets with OR logic between them. // At least one matcher set must match for the silence to apply. - MatcherSets []*MatcherSet `protobuf:"bytes,11,rep,name=matcher_sets,json=matcherSets,proto3" json:"matcher_sets,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + MatcherSets []*MatcherSet `protobuf:"bytes,11,rep,name=matcher_sets,json=matcherSets,proto3" json:"matcher_sets,omitempty"` + // Multiple receiver matcher sets with OR logic between them. + // Receiver matchers apply to the labels of receivers, not alerts. At + // least one set of receiver matchers must match for a silence to apply + // to alerts that are sent to that receiver. Unlike alert label matcher, + // a silence with no receiver matchers applies to ALL receivers. + ReceiverMatcherSets []*MatcherSet `protobuf:"bytes,12,rep,name=receiver_matcher_sets,json=receiverMatcherSets,proto3" json:"receiver_matcher_sets,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Silence) Reset() { @@ -376,6 +382,13 @@ func (x *Silence) GetMatcherSets() []*MatcherSet { return nil } +func (x *Silence) GetReceiverMatcherSets() []*MatcherSet { + if x != nil { + return x.ReceiverMatcherSets + } + return nil +} + // MeshSilence wraps a regular silence with an expiration timestamp // after which the silence may be garbage collected. type MeshSilence struct { @@ -452,7 +465,7 @@ const file_silence_proto_rawDesc = "" + "\ttimestamp\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\ttimestamp\"<\n" + "\n" + "MatcherSet\x12.\n" + - "\bmatchers\x18\x01 \x03(\v2\x12.silencepb.MatcherR\bmatchers\"\x9c\x04\n" + + "\bmatchers\x18\x01 \x03(\v2\x12.silencepb.MatcherR\bmatchers\"\xe7\x04\n" + "\aSilence\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" + "\bmatchers\x18\x02 \x03(\v2\x12.silencepb.MatcherR\bmatchers\x127\n" + @@ -466,7 +479,8 @@ const file_silence_proto_rawDesc = "" + "\acomment\x18\t \x01(\tR\acomment\x12E\n" + "\vannotations\x18\n" + " \x03(\v2#.silencepb.Silence.AnnotationsEntryR\vannotations\x128\n" + - "\fmatcher_sets\x18\v \x03(\v2\x15.silencepb.MatcherSetR\vmatcherSets\x1a>\n" + + "\fmatcher_sets\x18\v \x03(\v2\x15.silencepb.MatcherSetR\vmatcherSets\x12I\n" + + "\x15receiver_matcher_sets\x18\f \x03(\v2\x15.silencepb.MatcherSetR\x13receiverMatcherSets\x1a>\n" + "\x10AnnotationsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"v\n" + @@ -510,13 +524,14 @@ var file_silence_proto_depIdxs = []int32{ 2, // 7: silencepb.Silence.comments:type_name -> silencepb.Comment 6, // 8: silencepb.Silence.annotations:type_name -> silencepb.Silence.AnnotationsEntry 3, // 9: silencepb.Silence.matcher_sets:type_name -> silencepb.MatcherSet - 4, // 10: silencepb.MeshSilence.silence:type_name -> silencepb.Silence - 7, // 11: silencepb.MeshSilence.expires_at:type_name -> google.protobuf.Timestamp - 12, // [12:12] is the sub-list for method output_type - 12, // [12:12] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 3, // 10: silencepb.Silence.receiver_matcher_sets:type_name -> silencepb.MatcherSet + 4, // 11: silencepb.MeshSilence.silence:type_name -> silencepb.Silence + 7, // 12: silencepb.MeshSilence.expires_at:type_name -> google.protobuf.Timestamp + 13, // [13:13] is the sub-list for method output_type + 13, // [13:13] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_silence_proto_init() } diff --git a/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.proto b/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.proto index 658304e8d66..8769ae23339 100644 --- a/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.proto +++ b/vendor/github.com/prometheus/alertmanager/silence/silencepb/silence.proto @@ -68,6 +68,12 @@ message Silence { // Multiple matcher sets with OR logic between them. // At least one matcher set must match for the silence to apply. repeated MatcherSet matcher_sets = 11; + // Multiple receiver matcher sets with OR logic between them. + // Receiver matchers apply to the labels of receivers, not alerts. At + // least one set of receiver matchers must match for a silence to apply + // to alerts that are sent to that receiver. Unlike alert label matcher, + // a silence with no receiver matchers applies to ALL receivers. + repeated MatcherSet receiver_matcher_sets = 12; } // MeshSilence wraps a regular silence with an expiration timestamp diff --git a/vendor/github.com/prometheus/alertmanager/template/template.go b/vendor/github.com/prometheus/alertmanager/template/template.go index 73f1ac526ff..fea4bac2910 100644 --- a/vendor/github.com/prometheus/alertmanager/template/template.go +++ b/vendor/github.com/prometheus/alertmanager/template/template.go @@ -16,6 +16,7 @@ package template import ( "bytes" "embed" + "encoding/base64" "encoding/json" "fmt" tmplhtml "html/template" @@ -136,16 +137,114 @@ func (t *Template) FromGlob(path string) error { return nil } +// routeLabelsOf extracts the route labels from template data, which may be +// passed either by value or by pointer, along with whether those values are +// already rendered (and so must be returned verbatim rather than executed). +func routeLabelsOf(data any) (labels KV, rendered bool) { + switch d := data.(type) { + case *Data: + return d.RouteLabels, d.routeLabelsRendered + case Data: + return d.RouteLabels, d.routeLabelsRendered + default: + return nil, false + } +} + +// routeLabelResolver backs the routeLabels template function for a single +// top-level render. A route label value may itself be a template that +// references group labels, other route labels, etc., so resolving one can +// recurse. The resolver renders each label at most once (memo) and tracks which +// labels are currently being rendered (inProgress) so that a cyclic reference +// returns a descriptive error instead of recursing until the goroutine stack +// overflows (which is a fatal, unrecoverable runtime error in Go). +type routeLabelResolver struct { + raw KV // raw (possibly templated) label values + rendered bool // if true, raw values are already rendered; return verbatim + data any // data to render label values against + exec func(text string, data any, r *routeLabelResolver) (string, error) + memo map[string]string + inProgress map[string]struct{} + stack []string // labels currently being rendered, for the cycle error +} + +func newRouteLabelResolver(data any, exec func(string, any, *routeLabelResolver) (string, error)) *routeLabelResolver { + // memo and inProgress are allocated lazily on the first resolve() call, so a + // template that never references routeLabels (the common case) pays nothing. + labels, rendered := routeLabelsOf(data) + return &routeLabelResolver{ + raw: labels, + rendered: rendered, + data: data, + exec: exec, + } +} + +// resolve renders the named route label, recursing through any routeLabels +// references it contains. Unknown labels render to the empty string. If the +// values are already rendered, they are returned verbatim without a second +// execution. +func (r *routeLabelResolver) resolve(name string) (string, error) { + raw, ok := r.raw[name] + if !ok { + return "", nil + } + if r.rendered { + return raw, nil + } + if v, ok := r.memo[name]; ok { + return v, nil + } + if _, busy := r.inProgress[name]; busy { + cycle := strings.Join(append(append([]string{}, r.stack...), name), " -> ") + return "", fmt.Errorf("route label cycle detected: %s", cycle) + } + + if r.memo == nil { + r.memo = map[string]string{} + r.inProgress = map[string]struct{}{} + } + + r.inProgress[name] = struct{}{} + r.stack = append(r.stack, name) + v, err := r.exec(raw, r.data, r) + r.stack = r.stack[:len(r.stack)-1] + delete(r.inProgress, name) + if err != nil { + return "", err + } + + r.memo[name] = v + return v, nil +} + +// RouteLabelRenderer returns a function that renders a route label by name from +// data.RouteLabels. All returned renders share a single resolver, so each label +// — and any label it cross-references via {{ routeLabels "x" }} — is rendered at +// most once per call to RouteLabelRenderer (and cycles are still detected). +// It is used by the dispatch-time expansion of a group's route labels, where +// many labels are rendered against the same data and may reference each other. +func (t *Template) RouteLabelRenderer(data *Data) func(name string) (string, error) { + return newRouteLabelResolver(data, t.execText).resolve +} + // ExecuteTextString needs a meaningful doc comment (TODO(fabxc)). func (t *Template) ExecuteTextString(text string, data any) (string, error) { if text == "" { return "", nil } + return t.execText(text, data, newRouteLabelResolver(data, t.execText)) +} + +func (t *Template) execText(text string, data any, r *routeLabelResolver) (string, error) { tmpl, err := t.text.Clone() if err != nil { return "", err } - tmpl, err = tmpl.New("").Option("missingkey=zero").Parse(text) + + funcs := tmpltext.FuncMap{"routeLabels": r.resolve} + + tmpl, err = tmpl.New("").Option("missingkey=zero").Funcs(funcs).Parse(text) if err != nil { return "", err } @@ -159,11 +258,18 @@ func (t *Template) ExecuteHTMLString(html string, data any) (string, error) { if html == "" { return "", nil } + return t.execHTML(html, data, newRouteLabelResolver(data, t.execHTML)) +} + +func (t *Template) execHTML(html string, data any, r *routeLabelResolver) (string, error) { tmpl, err := t.html.Clone() if err != nil { return "", err } - tmpl, err = tmpl.New("").Option("missingkey=zero").Parse(html) + + funcs := tmplhtml.FuncMap{"routeLabels": r.resolve} + + tmpl, err = tmpl.New("").Option("missingkey=zero").Funcs(funcs).Parse(html) if err != nil { return "", err } @@ -203,6 +309,12 @@ var DefaultFuncs = FuncMap{ "stringSlice": func(s ...string) []string { return s }, + // routeLabels is a placeholder needed so templates referencing it parse + // successfully. It is replaced dynamically with the real implementation in + // ExecuteTextString and ExecuteHTMLString. + "routeLabels": func(name string) (string, error) { + return "", nil + }, // date returns the text representation of the time in the specified format. "date": func(fmt string, t time.Time) string { return t.Format(fmt) @@ -218,6 +330,15 @@ var DefaultFuncs = FuncMap{ "now": time.Now, "since": time.Since, "humanizeDuration": commonTemplates.HumanizeDuration, + // toDate parses s into a time.Time using the given layout, returning zero time on failure. + "toDate": func(layout, s string) time.Time { + t, _ := time.ParseInLocation(layout, s, time.UTC) + return t + }, + // mustToDate parses s into a time.Time using the given layout, returning an error on failure. + "mustToDate": func(layout, s string) (time.Time, error) { + return time.ParseInLocation(layout, s, time.UTC) + }, "toJson": func(v any) (string, error) { bytes, err := json.Marshal(v) if err != nil { @@ -225,6 +346,19 @@ var DefaultFuncs = FuncMap{ } return string(bytes), nil }, + // base64encode and base64decode use the URL-safe alphabet so the result + // can be embedded directly in a URL query parameter, e.g. to build a + // silence link for an external dashboard. + "base64encode": func(text string) string { + return base64.URLEncoding.EncodeToString([]byte(text)) + }, + "base64decode": func(text string) (string, error) { + decoded, err := base64.URLEncoding.DecodeString(text) + if err != nil { + return "", err + } + return string(decoded), nil + }, "list": func(args ...any) ([]any, error) { if args == nil { return []any{}, nil @@ -261,21 +395,21 @@ type Pair struct { type Pairs []Pair // Names returns a list of names of the pairs. -func (ps Pairs) Names() []string { +func (ps Pairs) Names() Strings { ns := make([]string, 0, len(ps)) for _, p := range ps { ns = append(ns, p.Name) } - return ns + return Strings(ns) } // Values returns a list of values of the pairs. -func (ps Pairs) Values() []string { +func (ps Pairs) Values() Strings { vs := make([]string, 0, len(ps)) for _, p := range ps { vs = append(vs, p.Value) } - return vs + return Strings(vs) } func (ps Pairs) String() string { @@ -291,6 +425,15 @@ func (ps Pairs) String() string { return b.String() } +// Strings is a list of strings exposed to templates. +type Strings []string + +// Join makes strings.Join accessible from templates, e.g. +// {{ .GroupLabels.Values.Join ":" }}. +func (s Strings) Join(sep string) string { + return strings.Join(s, sep) +} + // KV is a set of key/value string pairs. type KV map[string]string @@ -334,12 +477,12 @@ func (kv KV) Remove(keys []string) KV { } // Names returns the names of the label names in the LabelSet. -func (kv KV) Names() []string { +func (kv KV) Names() Strings { return kv.SortedPairs().Names() } // Values returns a list of the values in the LabelSet. -func (kv KV) Values() []string { +func (kv KV) Values() Strings { return kv.SortedPairs().Values() } @@ -361,8 +504,22 @@ type Data struct { GroupLabels KV `json:"groupLabels"` CommonLabels KV `json:"commonLabels"` CommonAnnotations KV `json:"commonAnnotations"` + RouteLabels KV `json:"routeLabels"` ExternalURL string `json:"externalURL"` + + // routeLabelsRendered: if true, routeLabels returns RouteLabels values + // verbatim instead of executing them as templates. Set via + // MarkRouteLabelsRendered. Unexported so it is not reachable from templates + // or serialized into JSON webhooks. + routeLabelsRendered bool +} + +// MarkRouteLabelsRendered marks d.RouteLabels as already-rendered, so the +// routeLabels template function returns the values verbatim rather than +// executing them a second time. +func MarkRouteLabelsRendered(d *Data) { + d.routeLabelsRendered = true } // Alert holds one alert for notification templates. @@ -402,7 +559,7 @@ func (as Alerts) Resolved() []Alert { } // Data assembles data for template expansion. -func (t *Template) Data(recv string, groupLabels model.LabelSet, notificationReason string, alerts ...*types.Alert) *Data { +func (t *Template) Data(recv string, groupLabels, routeLabels model.LabelSet, notificationReason string, alerts ...*types.Alert) *Data { typedAlerts := types.Alerts(alerts...) data := &Data{ @@ -413,6 +570,7 @@ func (t *Template) Data(recv string, groupLabels model.LabelSet, notificationRea GroupLabels: KV{}, CommonLabels: KV{}, CommonAnnotations: KV{}, + RouteLabels: KV{}, ExternalURL: t.ExternalURL.String(), } @@ -441,6 +599,10 @@ func (t *Template) Data(recv string, groupLabels model.LabelSet, notificationRea data.GroupLabels[string(k)] = string(v) } + for k, v := range routeLabels { + data.RouteLabels[string(k)] = string(v) + } + if len(alerts) >= 1 { var ( commonLabels = alerts[0].Labels.Clone() @@ -494,7 +656,12 @@ func DeepCopyWithTemplate(value any, tmplTextFunc TemplateFunc) (any, error) { // ignore error, thus the string is not an interface return parsed, ok } - return DeepCopyWithTemplate(inlineType, tmplTextFunc) + // inlineType holds structured data decoded from the rendered string. + // This is already final data, so only normalize it into JSON-compatible + // types. It must not be passed back through DeepCopyWithTemplate, because + // re-templating and re-parsing its leaf values would reinterpret strings + // that merely look like YAML (e.g. "value1:" becoming a map). See #5302. + return normalizeYAMLValue(inlineType), nil } return parsed, ok @@ -534,3 +701,39 @@ func DeepCopyWithTemplate(value any, tmplTextFunc TemplateFunc) (any, error) { return value, nil } } + +// normalizeYAMLValue recursively converts a value decoded by yaml.Unmarshal into +// JSON-compatible types: maps become map[string]any (non-string keys are dropped, +// mirroring DeepCopyWithTemplate) and slices/arrays become []any. Scalar leaves are +// returned unchanged, so values are never re-templated or re-parsed. This keeps a +// rendered JSON payload byte-for-byte faithful instead of reinterpreting string +// values that happen to be valid YAML (see #5302). +func normalizeYAMLValue(value any) any { + if value == nil { + return nil + } + + valueMeta := reflect.ValueOf(value) + switch valueMeta.Kind() { + case reflect.Array, reflect.Slice: + converted := make([]any, valueMeta.Len()) + for i := range converted { + converted[i] = normalizeYAMLValue(valueMeta.Index(i).Interface()) + } + return converted + + case reflect.Map: + converted := make(map[string]any, valueMeta.Len()) + for _, keyMeta := range valueMeta.MapKeys() { + strKey, isString := keyMeta.Interface().(string) + if !isString { + continue + } + converted[strKey] = normalizeYAMLValue(valueMeta.MapIndex(keyMeta).Interface()) + } + return converted + + default: + return value + } +} diff --git a/vendor/github.com/prometheus/alertmanager/tracing/tracing.go b/vendor/github.com/prometheus/alertmanager/tracing/tracing.go index 77a86842671..5ec7a2a6834 100644 --- a/vendor/github.com/prometheus/alertmanager/tracing/tracing.go +++ b/vendor/github.com/prometheus/alertmanager/tracing/tracing.go @@ -31,7 +31,7 @@ import ( "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.40.0" + semconv "go.opentelemetry.io/otel/semconv/v1.41.0" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace/noop" "google.golang.org/grpc/credentials" diff --git a/vendor/github.com/prometheus/client_golang/api/client.go b/vendor/github.com/prometheus/client_golang/api/client.go index 0e647b6756f..66844900d0c 100644 --- a/vendor/github.com/prometheus/client_golang/api/client.go +++ b/vendor/github.com/prometheus/client_golang/api/client.go @@ -27,13 +27,18 @@ import ( ) // DefaultRoundTripper is used if no RoundTripper is set in Config. +// refer https://github.com/golang/go/blob/master/src/net/http/transport.go#L46 var DefaultRoundTripper http.RoundTripper = &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).DialContext, - TLSHandshakeTimeout: 10 * time.Second, + ForceAttemptHTTP2: true, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, } // Config defines configuration parameters for a new client. @@ -136,21 +141,21 @@ func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response, } var body []byte - done := make(chan error, 1) + done := make(chan struct{}) + var readErr error go func() { + defer close(done) var buf bytes.Buffer - _, err := buf.ReadFrom(resp.Body) + _, readErr = buf.ReadFrom(resp.Body) body = buf.Bytes() - done <- err }() select { case <-ctx.Done(): resp.Body.Close() - <-done return resp, nil, ctx.Err() - case err = <-done: + case <-done: resp.Body.Close() - return resp, body, err + return resp, body, readErr } } diff --git a/vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go b/vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go index 8a72f9bfc7b..61094cb1ae2 100644 --- a/vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go +++ b/vendor/github.com/prometheus/client_golang/api/prometheus/v1/api.go @@ -380,7 +380,9 @@ const ( epBuildinfo = apiPrefix + "/status/buildinfo" epRuntimeinfo = apiPrefix + "/status/runtimeinfo" epTSDB = apiPrefix + "/status/tsdb" + epTSDBBlocks = apiPrefix + "/status/tsdb/blocks" epWalReplay = apiPrefix + "/status/walreplay" + epFormatQuery = apiPrefix + "/format_query" ) // AlertState models the state of an alert. @@ -475,7 +477,7 @@ type API interface { // Flags returns the flag values that Prometheus was launched with. Flags(ctx context.Context) (FlagsResult, error) // LabelNames returns the unique label names present in the block in sorted order by given time range and matchers. - LabelNames(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) ([]string, Warnings, error) + LabelNames(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) (model.LabelNames, Warnings, error) // LabelValues performs a query for the values of the given label, time range and matchers. LabelValues(ctx context.Context, label string, matches []string, startTime, endTime time.Time, opts ...Option) (model.LabelValues, Warnings, error) // Query performs a query for the given time. @@ -494,7 +496,7 @@ type API interface { // under the TSDB's data directory and returns the directory as response. Snapshot(ctx context.Context, skipHead bool) (SnapshotResult, error) // Rules returns a list of alerting and recording rules that are currently loaded. - Rules(ctx context.Context) (RulesResult, error) + Rules(ctx context.Context, matches []string) (RulesResult, error) // Targets returns an overview of the current state of the Prometheus target discovery. Targets(ctx context.Context) (TargetsResult, error) // TargetsMetadata returns metadata about metrics currently scraped by the target. @@ -503,8 +505,12 @@ type API interface { Metadata(ctx context.Context, metric, limit string) (map[string][]Metadata, error) // TSDB returns the cardinality statistics. TSDB(ctx context.Context, opts ...Option) (TSDBResult, error) + // TSDBBlocks returns the list of currently loaded TSDB blocks and their metadata. + TSDBBlocks(ctx context.Context) (TSDBBlocksResult, error) // WalReplay returns the current replay status of the wal. WalReplay(ctx context.Context) (WalReplayStatus, error) + // FormatQuery formats a PromQL expression in a prettified way. + FormatQuery(ctx context.Context, query string) (string, error) } // AlertsResult contains the result from querying the alerts endpoint. @@ -586,7 +592,7 @@ type RuleGroup struct { // default: // fmt.Printf("unknown rule type %s", v) // } -type Rules []interface{} +type Rules []any // AlertingRule models a alerting rule. type AlertingRule struct { @@ -666,7 +672,7 @@ type Metadata struct { // queryResult contains result data for a query. type queryResult struct { Type model.ValueType `json:"resultType"` - Result interface{} `json:"result"` + Result any `json:"result"` // The decoded value. v model.Value @@ -690,6 +696,40 @@ type TSDBHeadStats struct { MaxTime int `json:"maxTime"` } +// TSDBBlocksResult contains the results from querying the tsdb blocks endpoint. +type TSDBBlocksResult struct { + Status string `json:"status"` + Data TSDBBlocksData `json:"data"` +} + +// TSDBBlocksData contains the metadata for the tsdb blocks. +type TSDBBlocksData struct { + Blocks []TSDBBlocksBlockMetadata `json:"blocks"` +} + +// TSDBBlocksBlockMetadata contains the metadata for a single tsdb block. +type TSDBBlocksBlockMetadata struct { + Ulid string `json:"ulid"` + MinTime int64 `json:"minTime"` + MaxTime int64 `json:"maxTime"` + Stats TSDBBlocksStats `json:"stats"` + Compaction TSDBBlocksCompaction `json:"compaction"` + Version int `json:"version"` +} + +// TSDBBlocksStats contains block stats for a single tsdb block. +type TSDBBlocksStats struct { + NumSamples int `json:"numSamples"` + NumSeries int `json:"numSeries"` + NumChunks int `json:"numChunks"` +} + +// TSDBBlocksCompaction contains block compaction details for a single block. +type TSDBBlocksCompaction struct { + Level int `json:"level"` + Sources []string `json:"sources"` +} + // WalReplayStatus represents the wal replay status. type WalReplayStatus struct { Min int `json:"min"` @@ -1024,7 +1064,7 @@ func (h *httpAPI) Runtimeinfo(ctx context.Context) (RuntimeinfoResult, error) { return res, err } -func (h *httpAPI) LabelNames(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) ([]string, Warnings, error) { +func (h *httpAPI) LabelNames(ctx context.Context, matches []string, startTime, endTime time.Time, opts ...Option) (model.LabelNames, Warnings, error) { u := h.client.URL(epLabels, nil) q := addOptionalURLParams(u.Query(), opts) @@ -1042,7 +1082,7 @@ func (h *httpAPI) LabelNames(ctx context.Context, matches []string, startTime, e if err != nil { return nil, w, err } - var labelNames []string + var labelNames model.LabelNames err = json.Unmarshal(body, &labelNames) return labelNames, w, err } @@ -1235,8 +1275,15 @@ func (h *httpAPI) Snapshot(ctx context.Context, skipHead bool) (SnapshotResult, return res, err } -func (h *httpAPI) Rules(ctx context.Context) (RulesResult, error) { +func (h *httpAPI) Rules(ctx context.Context, matches []string) (RulesResult, error) { u := h.client.URL(epRules, nil) + q := u.Query() + + for _, m := range matches { + q.Add("match[]", m) + } + + u.RawQuery = q.Encode() req, err := http.NewRequest(http.MethodGet, u.String(), nil) if err != nil { @@ -1340,6 +1387,24 @@ func (h *httpAPI) TSDB(ctx context.Context, opts ...Option) (TSDBResult, error) return res, err } +func (h *httpAPI) TSDBBlocks(ctx context.Context) (TSDBBlocksResult, error) { + u := h.client.URL(epTSDBBlocks, nil) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return TSDBBlocksResult{}, err + } + + _, body, _, err := h.client.Do(ctx, req) + if err != nil { + return TSDBBlocksResult{}, err + } + + var res TSDBBlocksResult + err = json.Unmarshal(body, &res) + return res, err +} + func (h *httpAPI) WalReplay(ctx context.Context) (WalReplayStatus, error) { u := h.client.URL(epWalReplay, nil) @@ -1380,6 +1445,19 @@ func (h *httpAPI) QueryExemplars(ctx context.Context, query string, startTime, e return res, err } +func (h *httpAPI) FormatQuery(ctx context.Context, query string) (string, error) { + u := h.client.URL(epFormatQuery, nil) + q := u.Query() + q.Set("query", query) + + _, body, _, err := h.client.DoGetFallback(ctx, u, q) + if err != nil { + return "", err + } + + return string(body), nil +} + // Warnings is an array of non critical errors type Warnings []string @@ -1467,8 +1545,8 @@ func (h *apiClientImpl) Do(ctx context.Context, req *http.Request) (*http.Respon return resp, []byte(result.Data), result.Warnings, err } -// DoGetFallback will attempt to do the request as-is, and on a 405 or 501 it -// will fallback to a GET request. +// DoGetFallback will attempt to do the request as-is, and on a 403, 405, or +// 501 it will fallback to a GET request. func (h *apiClientImpl) DoGetFallback(ctx context.Context, u *url.URL, args url.Values) (*http.Response, []byte, Warnings, error) { encodedArgs := args.Encode() req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(encodedArgs)) @@ -1486,7 +1564,7 @@ func (h *apiClientImpl) DoGetFallback(ctx context.Context, u *url.URL, args url. req.Header["Idempotency-Key"] = nil resp, body, warnings, err := h.Do(ctx, req) - if resp != nil && (resp.StatusCode == http.StatusMethodNotAllowed || resp.StatusCode == http.StatusNotImplemented) { + if resp != nil && (resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusMethodNotAllowed || resp.StatusCode == http.StatusNotImplemented) { u.RawQuery = encodedArgs req, err = http.NewRequest(http.MethodGet, u.String(), nil) if err != nil { diff --git a/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go index 8547c8dfd18..820bf436aba 100644 --- a/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go +++ b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go @@ -90,7 +90,7 @@ loop: s = skipSpace(s[1:]) } } - return + return specs } func skipSpace(s string) (rest string) { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_go116.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_go116.go deleted file mode 100644 index effc57840ae..00000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_go116.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2021 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !go1.17 -// +build !go1.17 - -package collectors - -import "github.com/prometheus/client_golang/prometheus" - -// NewGoCollector returns a collector that exports metrics about the current Go -// process. This includes memory stats. To collect those, runtime.ReadMemStats -// is called. This requires to “stop the world”, which usually only happens for -// garbage collection (GC). Take the following implications into account when -// deciding whether to use the Go collector: -// -// 1. The performance impact of stopping the world is the more relevant the more -// frequently metrics are collected. However, with Go1.9 or later the -// stop-the-world time per metrics collection is very short (~25µs) so that the -// performance impact will only matter in rare cases. However, with older Go -// versions, the stop-the-world duration depends on the heap size and can be -// quite significant (~1.7 ms/GiB as per -// https://go-review.googlesource.com/c/go/+/34937). -// -// 2. During an ongoing GC, nothing else can stop the world. Therefore, if the -// metrics collection happens to coincide with GC, it will only complete after -// GC has finished. Usually, GC is fast enough to not cause problems. However, -// with a very large heap, GC might take multiple seconds, which is enough to -// cause scrape timeouts in common setups. To avoid this problem, the Go -// collector will use the memstats from a previous collection if -// runtime.ReadMemStats takes more than 1s. However, if there are no previously -// collected memstats, or their collection is more than 5m ago, the collection -// will block until runtime.ReadMemStats succeeds. -// -// NOTE: The problem is solved in Go 1.15, see -// https://github.com/golang/go/issues/19812 for the related Go issue. -func NewGoCollector() prometheus.Collector { - return prometheus.NewGoCollector() -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go index cc4ef1077e8..d29ade654fd 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go @@ -90,13 +90,13 @@ func WithGoCollectorMemStatsMetricsDisabled() func(options *internal.GoCollector // GoRuntimeMetricsRule allow enabling and configuring particular group of runtime/metrics. // TODO(bwplotka): Consider adding ability to adjust buckets. type GoRuntimeMetricsRule struct { - // Matcher represents RE2 expression will match the runtime/metrics from https://golang.bg/src/runtime/metrics/description.go + // Matcher represents RE2 expression will match the runtime/metrics from https://pkg.go.dev/runtime/metrics // Use `regexp.MustCompile` or `regexp.Compile` to create this field. Matcher *regexp.Regexp } // WithGoCollectorRuntimeMetrics allows enabling and configuring particular group of runtime/metrics. -// See the list of metrics https://golang.bg/src/runtime/metrics/description.go (pick the Go version you use there!). +// See the list of metrics https://pkg.go.dev/runtime/metrics (pick the Go version you use there!). // You can use this option in repeated manner, which will add new rules. The order of rules is important, the last rule // that matches particular metrics is applied. func WithGoCollectorRuntimeMetrics(rules ...GoRuntimeMetricsRule) func(options *internal.GoCollectorOptions) { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go index c96e187126f..0306b5878c3 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go @@ -15,15 +15,44 @@ package version import ( "fmt" + "maps" "github.com/prometheus/common/version" "github.com/prometheus/client_golang/prometheus" ) +type Option func(*options) + +type options struct { + extraConstLabels prometheus.Labels +} + +func WithExtraConstLabels(l prometheus.Labels) Option { + return func(o *options) { + o.extraConstLabels = l + } +} + // NewCollector returns a collector that exports metrics about current version // information. -func NewCollector(program string) prometheus.Collector { +func NewCollector(program string, opts ...Option) prometheus.Collector { + o := options{} + for _, opt := range opts { + opt(&o) + } + + constLabels := prometheus.Labels{ + "version": version.Version, + "revision": version.GetRevision(), + "branch": version.Branch, + "goversion": version.GoVersion, + "goos": version.GoOS, + "goarch": version.GoArch, + "tags": version.GetTags(), + } + maps.Copy(constLabels, o.extraConstLabels) + return prometheus.NewGaugeFunc( prometheus.GaugeOpts{ Namespace: program, @@ -32,15 +61,7 @@ func NewCollector(program string) prometheus.Collector { "A metric with a constant '1' value labeled by version, revision, branch, goversion from which %s was built, and the goos and goarch for the build.", program, ), - ConstLabels: prometheus.Labels{ - "version": version.Version, - "revision": version.GetRevision(), - "branch": version.Branch, - "goversion": version.GoVersion, - "goos": version.GoOS, - "goarch": version.GoArch, - "tags": version.GetTags(), - }, + ConstLabels: constLabels, }, func() float64 { return 1 }, ) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go index 4ce84e7a80e..7d963d3afb8 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/counter.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/counter.go @@ -85,11 +85,12 @@ type CounterVecOpts struct { // Both internal tracking values are added up in the Write method. This has to // be taken into account when it comes to precision and overflow behavior. func NewCounter(opts CounterOpts) Counter { - desc := NewDesc( + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - nil, + UnconstrainedLabels(nil), opts.ConstLabels, + WithUnit(opts.Unit), ) if opts.now == nil { opts.now = time.Now @@ -205,6 +206,7 @@ func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec { opts.Help, opts.VariableLabels, opts.ConstLabels, + WithUnit(opts.Unit), ) if opts.now == nil { opts.now = time.Now @@ -349,10 +351,11 @@ type CounterFunc interface { // // Check out the ExampleGaugeFunc examples for the similar GaugeFunc. func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc { - return newValueFunc(NewDesc( + return newValueFunc(V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - nil, + UnconstrainedLabels(nil), opts.ConstLabels, + WithUnit(opts.Unit), ), CounterValue, function) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go index 2331b8b4f3b..a3c92e7a4c1 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/desc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/desc.go @@ -47,6 +47,8 @@ type Desc struct { fqName string // help provides some helpful information about this metric. help string + // unit provides the unit of this metric. + unit string // constLabelPairs contains precalculated DTO label pairs based on // the constant labels. constLabelPairs []*dto.LabelPair @@ -66,6 +68,16 @@ type Desc struct { err error } +// DescOpt allows setting optional fields for NewDesc. +type DescOpt func(*Desc) + +// WithUnit sets the unit for a Desc. +func WithUnit(unit string) DescOpt { + return func(d *Desc) { + d.unit = unit + } +} + // NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc // and will be reported on registration time. variableLabels and constLabels can // be nil if no such labels should be set. fqName must not be empty. @@ -89,14 +101,17 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * // // For constLabels, the label values are constant. Therefore, they are fully // specified in the Desc. See the Collector example for a usage pattern. -func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels) *Desc { +func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels, opts ...DescOpt) *Desc { d := &Desc{ fqName: fqName, help: help, variableLabels: variableLabels.compile(), } - //nolint:staticcheck // TODO: Don't use deprecated model.NameValidationScheme. - if !model.NameValidationScheme.IsValidMetricName(fqName) { + + for _, opt := range opts { + opt(d) + } + if !model.UTF8Validation.IsValidMetricName(fqName) { d.err = fmt.Errorf("%q is not a valid metric name", fqName) return d } @@ -150,11 +165,13 @@ func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, const d.id = xxh.Sum64() // Sort labelNames so that order doesn't matter for the hash. sort.Strings(labelNames) - // Now hash together (in this order) the help string and the sorted + // Now hash together (in this order) the help string, the unit string and the sorted // label names. xxh.Reset() xxh.WriteString(help) xxh.Write(separatorByteSlice) + xxh.WriteString(d.unit) + xxh.Write(separatorByteSlice) for _, labelName := range labelNames { xxh.WriteString(labelName) xxh.Write(separatorByteSlice) @@ -182,6 +199,15 @@ func NewInvalidDesc(err error) *Desc { } } +// Err returns an error that occurred during construction, if any. +// +// Calling this method is optional. It can be used to detect construction +// errors early, before invoking other methods on the Desc. If an error is +// present, later operations may not behave as expected. +func (d *Desc) Err() error { + return d.err +} + func (d *Desc) String() string { lpStrings := make([]string, 0, len(d.constLabelPairs)) for _, lp := range d.constLabelPairs { @@ -202,9 +228,10 @@ func (d *Desc) String() string { } } return fmt.Sprintf( - "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: {%s}}", + "Desc{fqName: %q, help: %q, unit: %q, constLabels: {%s}, variableLabels: {%s}}", d.fqName, d.help, + d.unit, strings.Join(lpStrings, ","), strings.Join(vlStrings, ","), ) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go index de5a8562931..327746f4337 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go @@ -47,14 +47,14 @@ func (e *expvarCollector) Collect(ch chan<- Metric) { if expVar == nil { continue } - var v interface{} + var v any labels := make([]string, len(desc.variableLabels.names)) if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil { ch <- NewInvalidMetric(desc, err) continue } - var processValue func(v interface{}, i int) - processValue = func(v interface{}, i int) { + var processValue func(v any, i int) + processValue = func(v any, i int) { if i >= len(labels) { copiedLabels := append(make([]string, 0, len(labels)), labels...) switch v := v.(type) { @@ -72,7 +72,7 @@ func (e *expvarCollector) Collect(ch chan<- Metric) { ch <- m return } - vm, ok := v.(map[string]interface{}) + vm, ok := v.(map[string]any) if !ok { return } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go index dd2eac94067..41e54bf270a 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go @@ -76,11 +76,12 @@ type GaugeVecOpts struct { // scenarios for Gauges and Counters, where the former tends to be Set-heavy and // the latter Inc-heavy. func NewGauge(opts GaugeOpts) Gauge { - desc := NewDesc( + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - nil, + UnconstrainedLabels(nil), opts.ConstLabels, + WithUnit(opts.Unit), ) result := &gauge{desc: desc, labelPairs: desc.constLabelPairs} result.init(result) // Init self-collection. @@ -163,6 +164,7 @@ func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec { opts.Help, opts.VariableLabels, opts.ConstLabels, + WithUnit(opts.Unit), ) return &GaugeVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { @@ -302,10 +304,11 @@ type GaugeFunc interface { // value of 1. Example: // https://github.com/prometheus/common/blob/8558a5b7db3c84fa38b4766966059a7bd5bfa2ee/version/info.go#L36-L56 func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc { - return newValueFunc(NewDesc( + return newValueFunc(V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - nil, + UnconstrainedLabels(nil), opts.ConstLabels, + WithUnit(opts.Unit), ), GaugeValue, function) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go deleted file mode 100644 index 897a6e906b3..00000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2021 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !go1.17 -// +build !go1.17 - -package prometheus - -import ( - "runtime" - "sync" - "time" -) - -type goCollector struct { - base baseGoCollector - - // ms... are memstats related. - msLast *runtime.MemStats // Previously collected memstats. - msLastTimestamp time.Time - msMtx sync.Mutex // Protects msLast and msLastTimestamp. - msMetrics memStatsMetrics - msRead func(*runtime.MemStats) // For mocking in tests. - msMaxWait time.Duration // Wait time for fresh memstats. - msMaxAge time.Duration // Maximum allowed age of old memstats. -} - -// NewGoCollector is the obsolete version of collectors.NewGoCollector. -// See there for documentation. -// -// Deprecated: Use collectors.NewGoCollector instead. -func NewGoCollector() Collector { - msMetrics := goRuntimeMemStats() - msMetrics = append(msMetrics, struct { - desc *Desc - eval func(*runtime.MemStats) float64 - valType ValueType - }{ - // This metric is omitted in Go1.17+, see https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 - desc: NewDesc( - memstatNamespace("gc_cpu_fraction"), - "The fraction of this program's available CPU time used by the GC since the program started.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction }, - valType: GaugeValue, - }) - return &goCollector{ - base: newBaseGoCollector(), - msLast: &runtime.MemStats{}, - msRead: runtime.ReadMemStats, - msMaxWait: time.Second, - msMaxAge: 5 * time.Minute, - msMetrics: msMetrics, - } -} - -// Describe returns all descriptions of the collector. -func (c *goCollector) Describe(ch chan<- *Desc) { - c.base.Describe(ch) - for _, i := range c.msMetrics { - ch <- i.desc - } -} - -// Collect returns the current state of all metrics of the collector. -func (c *goCollector) Collect(ch chan<- Metric) { - var ( - ms = &runtime.MemStats{} - done = make(chan struct{}) - ) - // Start reading memstats first as it might take a while. - go func() { - c.msRead(ms) - c.msMtx.Lock() - c.msLast = ms - c.msLastTimestamp = time.Now() - c.msMtx.Unlock() - close(done) - }() - - // Collect base non-memory metrics. - c.base.Collect(ch) - - timer := time.NewTimer(c.msMaxWait) - select { - case <-done: // Our own ReadMemStats succeeded in time. Use it. - timer.Stop() // Important for high collection frequencies to not pile up timers. - c.msCollect(ch, ms) - return - case <-timer.C: // Time out, use last memstats if possible. Continue below. - } - c.msMtx.Lock() - if time.Since(c.msLastTimestamp) < c.msMaxAge { - // Last memstats are recent enough. Collect from them under the lock. - c.msCollect(ch, c.msLast) - c.msMtx.Unlock() - return - } - // If we are here, the last memstats are too old or don't exist. We have - // to wait until our own ReadMemStats finally completes. For that to - // happen, we have to release the lock. - c.msMtx.Unlock() - <-done - c.msCollect(ch, ms) -} - -func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) { - for _, i := range c.msMetrics { - ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms)) - } -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go index 6b8684731c9..1db1c4be09a 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go @@ -98,7 +98,7 @@ type goCollector struct { // snapshot is always produced by Collect. mu sync.Mutex - // Contains all samples that has to retrieved from runtime/metrics (not all of them will be exposed). + // Contains all samples that have to be retrieved from runtime/metrics (not all of them will be exposed). sampleBuf []metrics.Sample // sampleMap allows lookup for MemStats metrics and runtime/metrics histograms for exact sums. sampleMap map[string]*metrics.Sample @@ -210,16 +210,26 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { sampleBuf = append(sampleBuf, metrics.Sample{Name: d.Name}) sampleMap[d.Name] = &sampleBuf[len(sampleBuf)-1] + // Extract unit from the runtime/metrics name (e.g., "/gc/heap/allocs:bytes" -> "bytes") + // and sanitize to match Prometheus naming conventions (e.g., "cpu-seconds" -> "cpu_seconds") + var unit string + if idx := strings.IndexRune(d.Name, ':'); idx >= 0 { + unit = d.Name[idx+1:] + unit = strings.ReplaceAll(unit, "-", "_") + unit = strings.ReplaceAll(unit, "*", "_") + unit = strings.ReplaceAll(unit, "/", "_per_") + } + var m collectorMetric if d.Kind == metrics.KindFloat64Histogram { _, hasSum := opt.RuntimeMetricSumForHist[d.Name] - unit := d.Name[strings.IndexRune(d.Name, ':')+1:] m = newBatchHistogram( - NewDesc( + V2.NewDesc( BuildFQName(namespace, subsystem, name), help, + UnconstrainedLabels(nil), nil, - nil, + WithUnit(unit), ), internal.RuntimeMetricsBucketsForUnit(bucketsMap[d.Name], unit), hasSum, @@ -230,6 +240,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { Subsystem: subsystem, Name: name, Help: help, + Unit: unit, }, ) } else { @@ -238,6 +249,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { Subsystem: subsystem, Name: name, Help: help, + Unit: unit, }) } metricSet = append(metricSet, m) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index c453b754a7f..88bae3b32c2 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go @@ -378,6 +378,9 @@ type HistogramOpts struct { // string. Help string + // Unit provides the unit of this Histogram. + Unit string + // ConstLabels are used to attach fixed labels to this metric. Metrics // with the same fully-qualified name must have the same label names in // their ConstLabels. @@ -522,11 +525,12 @@ type HistogramVecOpts struct { // for each bucket. func NewHistogram(opts HistogramOpts) Histogram { return newHistogram( - NewDesc( + V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - nil, + UnconstrainedLabels(nil), opts.ConstLabels, + WithUnit(opts.Unit), ), opts, ) @@ -966,7 +970,7 @@ func (h *histogram) maybeReset( // We are using the possibly mocked h.now() rather than // time.Since(h.lastResetTime) to enable testing. if h.nativeHistogramMinResetDuration == 0 || // No reset configured. - h.resetScheduled || // Do not interefere if a reset is already scheduled. + h.resetScheduled || // Do not interfere if a reset is already scheduled. h.now().Sub(h.lastResetTime) < h.nativeHistogramMinResetDuration { return false } @@ -1053,8 +1057,8 @@ func (h *histogram) maybeWidenZeroBucket(hot, cold *histogramCounts) bool { atomic.StoreUint64(&cold.nativeHistogramZeroThresholdBits, math.Float64bits(newZeroThreshold)) // ...and then merge the newly deleted buckets into the wider zero // bucket. - mergeAndDeleteOrAddAndReset := func(hotBuckets, coldBuckets *sync.Map) func(k, v interface{}) bool { - return func(k, v interface{}) bool { + mergeAndDeleteOrAddAndReset := func(hotBuckets, coldBuckets *sync.Map) func(k, v any) bool { + return func(k, v any) bool { key := k.(int) bucket := v.(*int64) if key == smallestKey { @@ -1107,8 +1111,8 @@ func (h *histogram) doubleBucketWidth(hot, cold *histogramCounts) { // ...adjust the schema in the cold counts, too... atomic.StoreInt32(&cold.nativeHistogramSchema, coldSchema) // ...and then merge the cold buckets into the wider hot buckets. - merge := func(hotBuckets *sync.Map) func(k, v interface{}) bool { - return func(k, v interface{}) bool { + merge := func(hotBuckets *sync.Map) func(k, v any) bool { + return func(k, v any) bool { key := k.(int) bucket := v.(*int64) // Adjust key to match the bucket to merge into. @@ -1190,6 +1194,7 @@ func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec { opts.Help, opts.VariableLabels, opts.ConstLabels, + WithUnit(opts.Unit), ) return &HistogramVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { @@ -1476,7 +1481,7 @@ func pickSchema(bucketFactor float64) int32 { func makeBuckets(buckets *sync.Map) ([]*dto.BucketSpan, []int64) { var ii []int - buckets.Range(func(k, v interface{}) bool { + buckets.Range(func(k, v any) bool { ii = append(ii, k.(int)) return true }) @@ -1553,8 +1558,8 @@ func addToBucket(buckets *sync.Map, key int, increment int64) bool { // according to the buckets ranged through. It then resets all buckets ranged // through to 0 (but leaves them in place so that they don't need to get // recreated on the next scrape). -func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v interface{}) bool { - return func(k, v interface{}) bool { +func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v any) bool { + return func(k, v any) bool { bucket := v.(*int64) if addToBucket(hotBuckets, k.(int), atomic.LoadInt64(bucket)) { atomic.AddUint32(bucketNumber, 1) @@ -1565,7 +1570,7 @@ func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v interface } func deleteSyncMap(m *sync.Map) { - m.Range(func(k, v interface{}) bool { + m.Range(func(k, v any) bool { m.Delete(k) return true }) @@ -1573,7 +1578,7 @@ func deleteSyncMap(m *sync.Map) { func findSmallestKey(m *sync.Map) int { result := math.MaxInt32 - m.Range(func(k, v interface{}) bool { + m.Range(func(k, v any) bool { key := k.(int) if key < result { result = key diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go index 7bac0da33df..2db270f2166 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go @@ -78,7 +78,7 @@ type OpCode struct { // notion, pairing up elements that appear uniquely in each sequence. // That, and the method here, appear to yield more intuitive difference // reports than does diff. This method appears to be the least vulnerable -// to synching up on blocks of "junk lines", though (like blank lines in +// to syncing up on blocks of "junk lines", though (like blank lines in // ordinary text files, or maybe "

" lines in HTML files). That may be // because this is the only method of the 3 that has a *concept* of // "junk" . @@ -567,7 +567,7 @@ type UnifiedDiff struct { func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() - wf := func(format string, args ...interface{}) error { + wf := func(format string, args ...any) error { _, err := fmt.Fprintf(buf, format, args...) return err } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/labels.go b/vendor/github.com/prometheus/client_golang/prometheus/labels.go index 5fe8d3b4d29..a0285489a08 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/labels.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/labels.go @@ -184,6 +184,5 @@ func validateLabelValues(vals []string, expectedNumberOfValues int) error { } func checkLabelName(l string) bool { - //nolint:staticcheck // TODO: Don't use deprecated model.NameValidationScheme. - return model.NameValidationScheme.IsValidLabelName(l) && !strings.HasPrefix(l, reservedLabelPrefix) + return model.UTF8Validation.IsValidLabelName(l) && !strings.HasPrefix(l, reservedLabelPrefix) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go index 76e59f12880..c5cb90adf8f 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go @@ -81,6 +81,9 @@ type Opts struct { // string. Help string + // Unit provides the unit of this metric as per https://prometheus.io/docs/specs/om + Unit string + // ConstLabels are used to attach fixed labels to this metric. Metrics // with the same fully-qualified name must have the same label names in // their ConstLabels. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go index b32c95fa3fa..2b16298f406 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go @@ -72,7 +72,13 @@ func getOpenFileCount() (float64, error) { } func (c *processCollector) processCollect(ch chan<- Metric) { - if procs, err := unix.SysctlKinfoProcSlice("kern.proc.pid", os.Getpid()); err == nil { + pid, err := c.pidFn() + if err != nil { + c.reportError(ch, nil, err) + return + } + + if procs, err := unix.SysctlKinfoProcSlice("kern.proc.pid", pid); err == nil { if len(procs) == 1 { startTime := float64(procs[0].Proc.P_starttime.Nano() / 1e9) ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime) @@ -84,6 +90,11 @@ func (c *processCollector) processCollect(ch chan<- Metric) { c.reportError(ch, c.startTime, err) } + if pid != os.Getpid() { + c.reportError(ch, nil, fmt.Errorf("collecting metrics for pid %d is not supported on darwin: process metrics collection is limited to the current process (pid %d)", pid, os.Getpid())) + return + } + // The proc structure returned by kern.proc.pid above has an Rusage member, // but it is not filled in, so it needs to be fetched by getrusage(2). For // that call, the UTime, STime, and Maxrss members are filled out, but not diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go index fa474289ef8..c08dd05f031 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go @@ -30,6 +30,10 @@ var ( procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount") + + openProcess = windows.OpenProcess + closeHandle = windows.CloseHandle + getProcessTimes = windows.GetProcessTimes ) type processMemoryCounters struct { @@ -79,10 +83,21 @@ func getProcessHandleCount(handle windows.Handle) (uint32, error) { } func (c *processCollector) processCollect(ch chan<- Metric) { - h := windows.CurrentProcess() + pid, err := c.pidFn() + if err != nil { + c.reportError(ch, nil, err) + return + } + + h, err := openProcess(windows.PROCESS_QUERY_INFORMATION|windows.PROCESS_VM_READ, false, uint32(pid)) + if err != nil { + c.reportError(ch, nil, err) + return + } + defer closeHandle(h) var startTime, exitTime, kernelTime, userTime windows.Filetime - err := windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime) + err = getProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime) if err != nil { c.reportError(ch, nil, err) return diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index 763d99e3623..c28af5ce2ba 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -37,10 +37,12 @@ import ( "fmt" "io" "net/http" + "slices" "strconv" "sync" "time" + dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" "github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil" @@ -74,11 +76,118 @@ func defaultCompressionFormats() []Compression { } var gzipPool = sync.Pool{ - New: func() interface{} { + New: func() any { return gzip.NewWriter(nil) }, } +// coalescingGatherer wraps a TransactionalGatherer to deduplicate concurrent +// Gather calls. When a Gather is already in flight, new callers join the +// existing cycle and receive the same result once it completes. The underlying +// done function is called exactly once, when the last joined caller releases. +// +// This prevents goroutine pile-up when the scrape rate is faster than the +// time collectors need to produce metrics. +type coalescingGatherer struct { + g prometheus.TransactionalGatherer + mu sync.Mutex + cycle *gatherCycle +} + +// gatherCycle tracks a single in-flight Gather and all HTTP handlers sharing it. +type gatherCycle struct { + ready chan struct{} // closed when Gather completes; happens-before reads of mfs/err/done + mfs []*dto.MetricFamily // canonical result, set before ready is closed; callers get a slices.Clone, the element values stay shared and must not be mutated + err error // set before ready is closed + done func() // underlying done callback; set before ready is closed + refs int // number of handlers using this cycle; protected by coalescingGatherer.mu +} + +var _ prometheus.TransactionalGatherer = (*coalescingGatherer)(nil) // compile-time interface check + +// errGatherPanicked is returned to callers that joined an in-flight coalesced +// Gather whose underlying gatherer panicked. See the panic guard in Gather for +// why joiners receive this error instead of the panic itself. +var errGatherPanicked = errors.New("coalesced gather panicked") + +func (c *coalescingGatherer) Gather() ([]*dto.MetricFamily, func(), error) { + c.mu.Lock() + if cy := c.cycle; cy != nil { + // c.cycle is non-nil while Gather runs or handlers are still consuming its results. + cy.refs++ + c.mu.Unlock() + <-cy.ready + // Each caller gets its own slice header so it can filter or reorder + // without racing other callers sharing this cycle. The *dto.MetricFamily + // values remain shared and must not be mutated in place. + return slices.Clone(cy.mfs), c.releaseFunc(cy), cy.err + } + cy := &gatherCycle{ + ready: make(chan struct{}), + done: func() {}, + refs: 1, + } + c.cycle = cy + c.mu.Unlock() + + // Guard against a panic in c.g.Gather. The common case, a panicking + // Collector, never reaches here: Registry.Gather recovers Collector panics + // and returns them as an error. This guard only covers the rare case where + // the wrapped gatherer itself panics. + // + // We deliberately do not recover: the leader's panic propagates and is + // handled by net/http exactly as it would be without coalescing. We only + // set cy.err before closing cy.ready so joiners waiting on <-cy.ready fail + // with that error instead of silently returning an empty, successful + // response, and we clear c.cycle so the next Gather starts a fresh cycle. + // + // The leader never runs its own releaseFunc on this path, so its ref is + // not decremented; that is harmless because the cycle is detached (c.cycle + // = nil) and cy.done is still the no-op set at construction (c.g.Gather + // panicked before assigning a real done). If cy.done is ever made non-nil + // before c.g.Gather runs, this path would need to release it. + panicked := true + defer func() { + if panicked { + c.mu.Lock() + if c.cycle == cy { + c.cycle = nil + } + c.mu.Unlock() + cy.err = errGatherPanicked // set before close: happens-before joiners' reads + close(cy.ready) + } + }() + cy.mfs, cy.done, cy.err = c.g.Gather() + panicked = false + close(cy.ready) // happens-before joiners' reads of cy.mfs/err/done + + // Clone here too so cy.mfs stays the write-once canonical slice: joiners + // read it concurrently via slices.Clone, so the leader must not hand out + // (and potentially reorder) the same backing array. + return slices.Clone(cy.mfs), c.releaseFunc(cy), cy.err +} + +// releaseFunc returns the done callback for one caller sharing cy. +// When the last caller releases, the underlying done is invoked and the +// cycle is cleared so the next Gather starts fresh. +func (c *coalescingGatherer) releaseFunc(cy *gatherCycle) func() { + return func() { + c.mu.Lock() + cy.refs-- + if cy.refs > 0 { + c.mu.Unlock() + return + } + // Last caller. + if c.cycle == cy { + c.cycle = nil + } + c.mu.Unlock() + cy.done() // called outside the lock to avoid holding it during done + } +} + // Handler returns an http.Handler for the prometheus.DefaultGatherer, using // default HandlerOpts, i.e. it reports the first error as an HTTP error, it has // no error logging, and it applies compression if requested by the client. @@ -89,6 +198,10 @@ var gzipPool = sync.Pool{ // metrics used for instrumentation will be shared between them, providing // global scrape counts. // +// The handler supports filtering metrics by name using the `name[]` query parameter. +// Multiple metric names can be specified by providing the parameter multiple times. +// When no name[] parameters are provided, all metrics are returned. +// // This function is meant to cover the bulk of basic use cases. If you are doing // anything that requires more customization (including using a non-default // Gatherer, different instrumentation, and non-default HandlerOpts), use the @@ -105,6 +218,10 @@ func Handler() http.Handler { // Gatherers, with non-default HandlerOpts, and/or with custom (or no) // instrumentation. Use the InstrumentMetricHandler function to apply the same // kind of instrumentation as it is used by the Handler function. +// +// The handler supports filtering metrics by name using the `name[]` query parameter. +// Multiple metric names can be specified by providing the parameter multiple times. +// When no name[] parameters are provided, all metrics are returned. func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { return HandlerForTransactional(prometheus.ToTransactionalGatherer(reg), opts) } @@ -112,7 +229,15 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { // HandlerForTransactional is like HandlerFor, but it uses transactional gather, which // can safely change in-place returned *dto.MetricFamily before call to `Gather` and after // call to `done` of that `Gather`. +// +// The handler supports filtering metrics by name using the `name[]` query parameter. +// Multiple metric names can be specified by providing the parameter multiple times. +// When no name[] parameters are provided, all metrics are returned. func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerOpts) http.Handler { + if opts.CoalesceGather { + reg = &coalescingGatherer{g: reg} + } + var ( inFlightSem chan struct{} errCnt = prometheus.NewCounterVec( @@ -214,12 +339,14 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO rsp.Header().Set(contentEncodingHeader, encodingHeader) } - var enc expfmt.Encoder + var ( + enc expfmt.Encoder + encOpts []expfmt.EncoderOption + ) if opts.EnableOpenMetricsTextCreatedSamples { - enc = expfmt.NewEncoder(w, contentType, expfmt.WithCreatedLines()) - } else { - enc = expfmt.NewEncoder(w, contentType) + encOpts = append(encOpts, expfmt.WithCreatedLines()) } + enc = expfmt.NewEncoder(w, contentType, encOpts...) // handleError handles the error according to opts.ErrorHandling // and returns true if we have to abort after the handling. @@ -245,7 +372,24 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO return false } + // Build metric name filter set from query params (if any). The URL + // can be nil on hand-constructed requests. + var metricFilter map[string]struct{} + if req.URL != nil { + if metricNames := req.URL.Query()["name[]"]; len(metricNames) > 0 { + metricFilter = make(map[string]struct{}, len(metricNames)) + for _, name := range metricNames { + metricFilter[name] = struct{}{} + } + } + } + for _, mf := range mfs { + if metricFilter != nil { + if _, ok := metricFilter[mf.GetName()]; !ok { + continue + } + } if handleError(enc.Encode(mf)) { return } @@ -353,7 +497,7 @@ const ( // log.Logger from the standard library implements this interface, and it is // easy to implement by custom loggers, if they don't do so already anyway. type Logger interface { - Println(v ...interface{}) + Println(v ...any) } // HandlerOpts specifies options how to serve metrics via an http.Handler. The @@ -400,6 +544,40 @@ type HandlerOpts struct { // Service Unavailable and a suitable message in the body. If // MaxRequestsInFlight is 0 or negative, no limit is applied. MaxRequestsInFlight int + // CoalesceGather, if true, deduplicates concurrent Gather calls so that + // only one collection runs at a time. Additional requests that arrive + // while a Gather is in flight will receive the same result once it + // completes. This prevents goroutine pile-up when the scrape rate is + // faster than the time collectors need to produce metrics. + // + // When enabled, concurrent scrapers share a single metric snapshot per + // collection cycle. Each request receives its own copy of the returned + // slice, so filtering or reordering it (for example via name[] query + // parameters) is safe. The pointed-to MetricFamily values are still + // shared: the built-in handler only reads them, so this is safe in + // practice, but a custom TransactionalGatherer that mutates the returned + // families in place after Gather returns must not use this option. + // + // Because the snapshot is shared, a request that arrives while a cycle is + // in flight receives that cycle's result even though collection began + // before the request; two scrapers joined to one cycle observe the same + // timestamps rather than independently gathered data. + // + // Consider using CoalesceGather together with Timeout. Timeout bounds the + // client-facing response time and keeps at most one collection running at + // a time, but it does not cancel the underlying Gather: a joined request + // that times out still holds a MaxRequestsInFlight slot until the shared + // collection completes. + // + // Panic handling: a panicking Collector is already turned into an error by + // the registry, so joiners receive that error like any other. In the rare + // case where the wrapped gatherer itself panics, the panicking request's + // panic propagates as usual (handled by net/http), while requests that + // joined the same cycle receive an error rather than an empty response. + // + // NOTE: This option is experimental and may change or be removed in a + // future release. + CoalesceGather bool // If handling a request takes longer than Timeout, it is responded to // with 503 ServiceUnavailable and a suitable Message. No timeout is // applied if Timeout is 0 or negative. Note that with the current @@ -407,8 +585,9 @@ type HandlerOpts struct { // described above (and even that only if sending of the body hasn't // started yet), while the bulk work of gathering all the metrics keeps // running in the background (with the eventual result to be thrown - // away). Until the implementation is improved, it is recommended to - // implement a separate timeout in potentially slow Collectors. + // away). When CoalesceGather is enabled, only one such background Gather + // can be in flight at a time. It is also recommended to implement a + // separate timeout in potentially slow Collectors. Timeout time.Duration // If true, the experimental OpenMetrics encoding is added to the // possible options during content negotiation. Note that Prometheus @@ -460,7 +639,7 @@ func httpError(rsp http.ResponseWriter, err error) { // negotiateEncodingWriter reads the Accept-Encoding header from a request and // selects the right compression based on an allow-list of supported -// compressions. It returns a writer implementing the compression and an the +// compressions. It returns a writer implementing the compression and the // correct value that the caller can set in the response header. func negotiateEncodingWriter(r *http.Request, rw io.Writer, compressions []string) (_ io.Writer, encodingHeaderValue string, closeWriter func(), _ error) { if len(compressions) == 0 { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go index d3482c40ca7..0248579742a 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go @@ -75,10 +75,10 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou resp, err := next.RoundTrip(r) if err == nil { l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) - for label, resolve := range rtOpts.extraLabelsFromCtx { - l[label] = resolve(resp.Request.Context()) + for label, resolve := range rtOpts.extraLabelsFromRequest { + l[label] = resolve(resp.Request) } - addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r.Context())) + addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r)) } return resp, err } @@ -119,10 +119,10 @@ func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundT resp, err := next.RoundTrip(r) if err == nil { l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) - for label, resolve := range rtOpts.extraLabelsFromCtx { - l[label] = resolve(resp.Request.Context()) + for label, resolve := range rtOpts.extraLabelsFromRequest { + l[label] = resolve(resp.Request) } - observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r.Context())) + observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r)) } return resp, err } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go index 9332b0249a9..9dec091ac71 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go @@ -28,24 +28,36 @@ import ( // magicString is used for the hacky label test in checkLabels. Remove once fixed. const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa" -// observeWithExemplar is a wrapper for [prometheus.ExemplarAdder.ExemplarObserver], -// which falls back to [prometheus.Observer.Observe] if no labels are provided. +// observeWithExemplar records val on obs. If labels is non-nil and obs +// implements [prometheus.ExemplarObserver], the exemplar is attached via +// ObserveWithExemplar; otherwise the exemplar is dropped and the value is +// recorded with a plain [prometheus.Observer.Observe]. This mirrors the +// safe-cast pattern in [prometheus.Timer.ObserveDurationWithExemplar] and +// ensures we never panic when callers pass an ObserverVec backed by a +// summary, which cannot carry exemplars in the Prometheus exposition format. func observeWithExemplar(obs prometheus.Observer, val float64, labels map[string]string) { - if labels == nil { - obs.Observe(val) - return + if labels != nil { + if eo, ok := obs.(prometheus.ExemplarObserver); ok { + eo.ObserveWithExemplar(val, labels) + return + } } - obs.(prometheus.ExemplarObserver).ObserveWithExemplar(val, labels) + obs.Observe(val) } -// addWithExemplar is a wrapper for [prometheus.ExemplarAdder.AddWithExemplar], -// which falls back to [prometheus.Counter.Add] if no labels are provided. -func addWithExemplar(obs prometheus.Counter, val float64, labels map[string]string) { - if labels == nil { - obs.Add(val) - return +// addWithExemplar records val on c. If labels is non-nil and c implements +// [prometheus.ExemplarAdder], the exemplar is attached via AddWithExemplar; +// otherwise the exemplar is dropped and the value is recorded with a plain +// [prometheus.Counter.Add]. The safe-cast keeps the helper robust against +// custom Counter implementations that do not advertise exemplar support. +func addWithExemplar(c prometheus.Counter, val float64, labels map[string]string) { + if labels != nil { + if ea, ok := c.(prometheus.ExemplarAdder); ok { + ea.AddWithExemplar(val, labels) + return + } } - obs.(prometheus.ExemplarAdder).AddWithExemplar(val, labels) + c.Add(val) } // InstrumentHandlerInFlight is a middleware that wraps the provided @@ -97,10 +109,10 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op next.ServeHTTP(d, r) l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r)) } } @@ -108,10 +120,10 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op now := time.Now() next.ServeHTTP(w, r) l := labels(code, method, r.Method, 0, hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r)) } } @@ -147,10 +159,10 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, next.ServeHTTP(d, r) l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) + addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r)) } } @@ -158,10 +170,10 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, next.ServeHTTP(w, r) l := labels(code, method, r.Method, 0, hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) + addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r)) } } @@ -200,10 +212,10 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha now := time.Now() d := newDelegator(w, func(status int) { l := labels(code, method, r.Method, status, hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r)) }) next.ServeHTTP(d, r) } @@ -244,10 +256,10 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, size := computeApproximateRequestSize(r) l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) + observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r)) } } @@ -256,10 +268,10 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, size := computeApproximateRequestSize(r) l := labels(code, method, r.Method, 0, hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) + observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r)) } } @@ -296,10 +308,10 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler next.ServeHTTP(d, r) l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) - for label, resolve := range hOpts.extraLabelsFromCtx { - l[label] = resolve(r.Context()) + for label, resolve := range hOpts.extraLabelsFromRequest { + l[label] = resolve(r) } - observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r.Context())) + observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r)) }) } @@ -366,7 +378,7 @@ func checkLabels(c prometheus.Collector) (code, method bool) { panic("metric partitioned with non-supported labels") } } - return + return code, method } func isLabelCurried(c prometheus.Collector, label string) bool { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go index 5d4383aa14a..d4c0954f366 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go @@ -15,6 +15,7 @@ package promhttp import ( "context" + "net/http" "github.com/prometheus/client_golang/prometheus" ) @@ -24,28 +25,31 @@ type Option interface { apply(*options) } +// LabelValueFromRequest is used to compute the label value from request. +type LabelValueFromRequest func(request *http.Request) string + // LabelValueFromCtx are used to compute the label value from request context. // Context can be filled with values from request through middleware. type LabelValueFromCtx func(ctx context.Context) string // options store options for both a handler or round tripper. type options struct { - extraMethods []string - getExemplarFn func(requestCtx context.Context) prometheus.Labels - extraLabelsFromCtx map[string]LabelValueFromCtx + extraMethods []string + getExemplarFn func(req *http.Request) prometheus.Labels + extraLabelsFromRequest map[string]LabelValueFromRequest } func defaultOptions() *options { return &options{ - getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil }, - extraLabelsFromCtx: map[string]LabelValueFromCtx{}, + getExemplarFn: func(req *http.Request) prometheus.Labels { return nil }, + extraLabelsFromRequest: map[string]LabelValueFromRequest{}, } } func (o *options) emptyDynamicLabels() prometheus.Labels { labels := prometheus.Labels{} - for label := range o.extraLabelsFromCtx { + for label := range o.extraLabelsFromRequest { labels[label] = "" } @@ -66,19 +70,39 @@ func WithExtraMethods(methods ...string) Option { }) } -// WithExemplarFromContext allows to inject function that will get exemplar from context that will be put to counter and histogram metrics. +// WithExemplarFromRequest allows you to inject a function that will get exemplar from request that will be put to counter and histogram metrics. // If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but // metric will continue to observe/increment. -func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prometheus.Labels) Option { +func WithExemplarFromRequest(getExemplarFn func(req *http.Request) prometheus.Labels) Option { return optionApplyFunc(func(o *options) { o.getExemplarFn = getExemplarFn }) } +// WithExemplarFromContext allows you to inject a function that will get exemplar from context that will be put to counter and histogram metrics. +// If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but +// metric will continue to observe/increment. +func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prometheus.Labels) Option { + return optionApplyFunc(func(o *options) { + o.getExemplarFn = func(req *http.Request) prometheus.Labels { + return getExemplarFn(req.Context()) + } + }) +} + +// WithLabelFromRequest registers a label for dynamic resolution with access to the request. +func WithLabelFromRequest(name string, valueFn LabelValueFromRequest) Option { + return optionApplyFunc(func(o *options) { + o.extraLabelsFromRequest[name] = valueFn + }) +} + // WithLabelFromCtx registers a label for dynamic resolution with access to context. // See the example for ExampleInstrumentHandlerWithLabelResolver for example usage func WithLabelFromCtx(name string, valueFn LabelValueFromCtx) Option { return optionApplyFunc(func(o *options) { - o.extraLabelsFromCtx[name] = valueFn + o.extraLabelsFromRequest[name] = func(req *http.Request) string { + return valueFn(req.Context()) + } }) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/push/push.go b/vendor/github.com/prometheus/client_golang/prometheus/push/push.go index 1eb35ac9afa..c65b6a665ac 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/push/push.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/push/push.go @@ -182,8 +182,7 @@ func (p *Pusher) Error() error { // For convenience, this method returns a pointer to the Pusher itself. func (p *Pusher) Grouping(name, value string) *Pusher { if p.error == nil { - //nolint:staticcheck // TODO: Don't use deprecated model.NameValidationScheme. - if !model.NameValidationScheme.IsValidLabelName(name) { + if !model.UTF8Validation.IsValidLabelName(name) { p.error = fmt.Errorf("grouping label has invalid name: %s", name) return p } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go index c6fd2f58b74..ed0681c8b4e 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go @@ -214,6 +214,19 @@ func (err AlreadyRegisteredError) Error() string { // by a Gatherer to report multiple errors during MetricFamily gathering. type MultiError []error +// SafeMultiError is a thread-safe wrapper around MultiError using a mutex. +type SafeMultiError struct { + mu sync.Mutex + errs MultiError +} + +// Appends the provided error to the contained MultiError in a thread-safe way. +func (s *SafeMultiError) Append(err error) { + s.mu.Lock() + s.errs.Append(err) + s.mu.Unlock() +} + // Error formats the contained errors as a bullet point list, preceded by the // total number of errors. Note that this results in a multi-line string. func (errs MultiError) Error() string { @@ -408,6 +421,16 @@ func (r *Registry) MustRegister(cs ...Collector) { } } +// MustGather implements Gatherer. +// Wraps around Gather and panics if Gather fails for any reason. +func (r *Registry) MustGather() []*dto.MetricFamily { + mfs, err := r.Gather() + if err != nil { + panic(err) + } + return mfs +} + // Gather implements Gatherer. func (r *Registry) Gather() ([]*dto.MetricFamily, error) { r.mtx.RLock() @@ -423,7 +446,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { uncheckedMetricChan = make(chan Metric, capMetricChan) metricHashes = map[uint64]struct{}{} wg sync.WaitGroup - errs MultiError // The collected errors to return in the end. + safeErrs = &SafeMultiError{} // To collect errors in a threadsafe way registeredDescIDs map[uint64]struct{} // Only used for pedantic checks ) @@ -453,9 +476,9 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { for { select { case collector := <-checkedCollectors: - collector.Collect(checkedMetricChan) + safeErrs.Append((safeCollect(collector, checkedMetricChan))) case collector := <-uncheckedCollectors: - collector.Collect(uncheckedMetricChan) + safeErrs.Append(safeCollect(collector, uncheckedMetricChan)) default: return } @@ -499,7 +522,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { cmc = nil break } - errs.Append(processMetric( + safeErrs.Append(processMetric( metric, metricFamiliesByName, metricHashes, registeredDescIDs, @@ -509,7 +532,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { umc = nil break } - errs.Append(processMetric( + safeErrs.Append(processMetric( metric, metricFamiliesByName, metricHashes, nil, @@ -526,7 +549,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { cmc = nil break } - errs.Append(processMetric( + safeErrs.Append(processMetric( metric, metricFamiliesByName, metricHashes, registeredDescIDs, @@ -536,7 +559,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { umc = nil break } - errs.Append(processMetric( + safeErrs.Append(processMetric( metric, metricFamiliesByName, metricHashes, nil, @@ -556,7 +579,8 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { break } } - return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() + + return internal.NormalizeMetricFamilies(metricFamiliesByName), safeErrs.errs.MaybeUnwrap() } // Describe implements Collector. @@ -571,6 +595,24 @@ func (r *Registry) Describe(ch chan<- *Desc) { } } +// Helper wrapper around Collector.Collect. +// It tries to collect from the channel, recovers on panic and +// if it has recovered from a panic, then it sends an InvalidMetric into +// the channel with an InvalidDesc, and an error that includes a stack trace. +func safeCollect(c Collector, ch chan<- Metric) (err error) { + defer func() { + if r := recover(); r != nil { + buf := make([]byte, 64<<10) // 64 KB + n := runtime.Stack(buf, false) + err = fmt.Errorf("prometheus collector panic recovered: type=%T: error=%v\nstack trace=%s", c, r, buf[:n]) + ch <- NewInvalidMetric(NewInvalidDesc(err), err) + } + }() + c.Collect(ch) + + return err +} + // Collect implements Collector. func (r *Registry) Collect(ch chan<- Metric) { r.mtx.RLock() @@ -599,10 +641,12 @@ func WriteToTextfile(filename string, g Gatherer) error { mfs, err := g.Gather() if err != nil { + tmp.Close() return err } for _, mf := range mfs { if _, err := expfmt.MetricFamilyToText(tmp, mf); err != nil { + tmp.Close() return err } } @@ -685,6 +729,9 @@ func processMetric( metricFamily = &dto.MetricFamily{} metricFamily.Name = proto.String(desc.fqName) metricFamily.Help = proto.String(desc.help) + if desc.unit != "" { + metricFamily.Unit = proto.String(desc.unit) + } // TODO(beorn7): Simplify switch once Desc has type. switch { case dtoMetric.Gauge != nil: diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index ac5203c6faa..c12b8d13d4b 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go @@ -101,6 +101,9 @@ type SummaryOpts struct { // string. Help string + // Unit provides the unit of this Summary. + Unit string + // ConstLabels are used to attach fixed labels to this metric. Metrics // with the same fully-qualified name must have the same label names in // their ConstLabels. @@ -181,11 +184,12 @@ type SummaryVecOpts struct { // NewSummary creates a new Summary based on the provided SummaryOpts. func NewSummary(opts SummaryOpts) Summary { return newSummary( - NewDesc( + V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - nil, + UnconstrainedLabels(nil), opts.ConstLabels, + WithUnit(opts.Unit), ), opts, ) @@ -578,6 +582,7 @@ func (v2) NewSummaryVec(opts SummaryVecOpts) *SummaryVec { opts.Help, opts.VariableLabels, opts.ConstLabels, + WithUnit(opts.Unit), ) return &SummaryVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/timer.go b/vendor/github.com/prometheus/client_golang/prometheus/timer.go index 52344fef53f..c1318ffb51e 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/timer.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/timer.go @@ -37,10 +37,10 @@ type Timer struct { // or // // func TimeMeWithExemplar() { -// timer := NewTimer(myHistogram) -// defer timer.ObserveDurationWithExemplar(exemplar) -// // Do actual work. -// } +// timer := NewTimer(myHistogram) +// defer timer.ObserveDurationWithExemplar(exemplar) +// // Do actual work. +// } func NewTimer(o Observer) *Timer { return &Timer{ begin: time.Now(), @@ -66,7 +66,7 @@ func (t *Timer) ObserveDuration() time.Duration { // ObserveDurationWithExemplar is like ObserveDuration, but it will also // observe exemplar with the duration unless exemplar is nil or provided Observer can't -// be casted to ExemplarObserver. +// be cast to ExemplarObserver. func (t *Timer) ObserveDurationWithExemplar(exemplar Labels) time.Duration { d := time.Since(t.begin) eo, ok := t.observer.(ExemplarObserver) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go index 487b466563b..121d2a96390 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go @@ -193,9 +193,11 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) { // // Keeping the Metric for later use is possible (and should be considered if // performance is critical), but keep in mind that Reset, DeleteLabelValues and -// Delete can be used to delete the Metric from the MetricVec. In that case, the -// Metric will still exist, but it will not be exported anymore, even if a -// Metric with the same label values is created later. +// Delete can be used to delete the Metric from the MetricVec. In that case, if +// you have previously kept a reference to that Metric, the Metric object still +// exists and can be used, but it will not be exported anymore. If a Metric with +// the same label values is created later, updates to the old Metric reference +// will not be exported. // // An error is returned if the number of label values is not the same as the // number of variable labels in Desc (minus any curried labels). @@ -657,7 +659,7 @@ func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string { } var labelsPool = &sync.Pool{ - New: func() interface{} { + New: func() any { return make(Labels) }, } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go index 2ed1285068e..697f55558bd 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go @@ -230,6 +230,7 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc { return &Desc{ fqName: desc.fqName, help: desc.help, + unit: desc.unit, variableLabels: desc.variableLabels, constLabelPairs: desc.constLabelPairs, err: fmt.Errorf("attempted wrapping with already existing label name %q", ln), @@ -238,8 +239,8 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc { constLabels[ln] = lv } // NewDesc will do remaining validations. - newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) - // Propagate errors if there was any. This will override any errer + newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels, WithUnit(desc.unit)) + // Propagate errors if there was any. This will override any error // created by NewDesc above, i.e. earlier errors get precedence. if desc.err != nil { newDesc.err = desc.err diff --git a/vendor/github.com/prometheus/common/config/http_config.go b/vendor/github.com/prometheus/common/config/http_config.go index 88457375ff1..d633479c690 100644 --- a/vendor/github.com/prometheus/common/config/http_config.go +++ b/vendor/github.com/prometheus/common/config/http_config.go @@ -132,7 +132,7 @@ func (tv *TLSVersion) String() string { return s } } - return fmt.Sprintf("%d", tv) + return fmt.Sprintf("%d", *tv) } // BasicAuth contains basic HTTP authentication credentials. @@ -1178,10 +1178,8 @@ func originalRequestHost(req *http.Request) string { } // sensitiveHeadersOnRedirect lists the headers that must not be forwarded when -// following a redirect to a different host. The first four entries match the -// list stripped by makeHeadersCopier in net/http/client.go; we additionally -// strip the Proxy-* headers, which net/http does not, to avoid leaking proxy -// credentials to an untrusted host. +// following a redirect to a different host. The list matches the one stripped +// by makeHeadersCopier in net/http/client.go. var sensitiveHeadersOnRedirect = map[string]struct{}{ "Authorization": {}, // "Www-Authenticate" is the canonical form produced by diff --git a/vendor/github.com/prometheus/common/route/route.go b/vendor/github.com/prometheus/common/route/route.go index 18039fac0d5..b1f274c15d4 100644 --- a/vendor/github.com/prometheus/common/route/route.go +++ b/vendor/github.com/prometheus/common/route/route.go @@ -20,6 +20,11 @@ import ( "github.com/julienschmidt/httprouter" ) +// MethodQuery is the QUERY HTTP method. It is a safe, idempotent method that +// carries a request body, see https://datatracker.ietf.org/doc/rfc10008/. +// It is not yet part of net/http, so it is defined here. +const MethodQuery = "QUERY" + type param string // Param returns param p for the context, or the empty string when @@ -114,6 +119,11 @@ func (r *Router) Head(path string, h http.HandlerFunc) { r.rtr.HEAD(r.prefix+path, r.handle(path, h)) } +// Query registers a new QUERY route. +func (r *Router) Query(path string, h http.HandlerFunc) { + r.rtr.Handle(MethodQuery, r.prefix+path, r.handle(path, h)) +} + // Redirect takes an absolute path and sends an internal HTTP redirect for it, // prefixed by the router's path prefix. Note that this method does not include // functionality for handling relative paths or full URL redirects. diff --git a/vendor/github.com/prometheus/exporter-toolkit/web/cache.go b/vendor/github.com/prometheus/exporter-toolkit/web/cache.go index 252928eeaa5..b638afd9789 100644 --- a/vendor/github.com/prometheus/exporter-toolkit/web/cache.go +++ b/vendor/github.com/prometheus/exporter-toolkit/web/cache.go @@ -63,10 +63,7 @@ func (c *cache) makeRoom() { // the cache is on a long tail, we can save a lot of CPU // time by doing a whole bunch of deletions now and then // we won't have to do them again for a while. - numToDelete := len(c.cache) / 10 - if numToDelete < 1 { - numToDelete = 1 - } + numToDelete := max(len(c.cache)/10, 1) for deleted := 0; deleted <= numToDelete; deleted++ { // Go maps are "nondeterministic" not actually random, // so although we could just chop off the "front" of the diff --git a/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go b/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go index 240337ca77f..f863e9d8c38 100644 --- a/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go +++ b/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go @@ -12,7 +12,6 @@ // limitations under the License. //go:build !genassets -// +build !genassets //go:generate go run -tags genassets gen_assets.go diff --git a/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go b/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go index c760d88ca21..7245f741455 100644 --- a/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go +++ b/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go @@ -24,6 +24,7 @@ import ( "net/url" "os" "path/filepath" + "slices" "strconv" "strings" "time" @@ -38,6 +39,7 @@ import ( var ( errNoTLSConfig = errors.New("TLS config is not present") + ErrMissingFlag = errors.New("missing required flag configuration") ErrNoListeners = errors.New("no web listen address or systemd socket flag specified") ) @@ -65,9 +67,27 @@ type TLSConfig struct { } type FlagConfig struct { + // WebListenAddresses contains the listen addresses for the HTTP server. WebListenAddresses *[]string - WebSystemdSocket *bool - WebConfigFile *string + // WebSystemdSocket enables systemd socket activation listeners. + WebSystemdSocket *bool + // WebConfigFile points to the TLS and authentication configuration file. + WebConfigFile *string +} + +// checkFlags validates that the flag configuration contains the required +// listener and web config fields needed by the web package. +func (c *FlagConfig) checkFlags() error { + if c == nil { + return ErrMissingFlag + } + if c.WebConfigFile == nil { + return ErrMissingFlag + } + if c.WebSystemdSocket == nil && (c.WebListenAddresses == nil || len(*c.WebListenAddresses) == 0) { + return ErrNoListeners + } + return nil } // SetDirectory joins any relative file paths with dir. @@ -97,10 +117,8 @@ func (t *TLSConfig) VerifyPeerCertificate(rawCerts [][]byte, _ [][]*x509.Certifi } for _, sanValue := range sanValues { - for _, allowedSan := range t.ClientAllowedSans { - if sanValue == allowedSan { - return nil - } + if slices.Contains(t.ClientAllowedSans, sanValue) { + return nil } } @@ -291,8 +309,8 @@ func ServeMultiple(listeners []net.Listener, server *http.Server, flags *FlagCon // FlagConfig is true. // The FlagConfig is also passed on to ServeMultiple. func ListenAndServe(server *http.Server, flags *FlagConfig, logger *slog.Logger) error { - if flags.WebSystemdSocket == nil && (flags.WebListenAddresses == nil || len(*flags.WebListenAddresses) == 0) { - return ErrNoListeners + if err := flags.checkFlags(); err != nil { + return err } if flags.WebSystemdSocket != nil && *flags.WebSystemdSocket { @@ -440,7 +458,7 @@ func Validate(tlsConfigPath string) error { type Cipher uint16 -func (c *Cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (c *Cipher) UnmarshalYAML(unmarshal func(any) error) error { var s string err := unmarshal(&s) if err != nil { @@ -455,7 +473,7 @@ func (c *Cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { return errors.New("unknown cipher: " + s) } -func (c Cipher) MarshalYAML() (interface{}, error) { +func (c Cipher) MarshalYAML() (any, error) { return tls.CipherSuiteName((uint16)(c)), nil } @@ -468,7 +486,7 @@ var curves = map[string]Curve{ "X25519": (Curve)(tls.X25519), } -func (c *Curve) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (c *Curve) UnmarshalYAML(unmarshal func(any) error) error { var s string err := unmarshal(&s) if err != nil { @@ -481,7 +499,7 @@ func (c *Curve) UnmarshalYAML(unmarshal func(interface{}) error) error { return errors.New("unknown curve: " + s) } -func (c *Curve) MarshalYAML() (interface{}, error) { +func (c *Curve) MarshalYAML() (any, error) { for s, curveid := range curves { if *c == curveid { return s, nil @@ -499,7 +517,7 @@ var tlsVersions = map[string]TLSVersion{ "TLS10": (TLSVersion)(tls.VersionTLS10), } -func (tv *TLSVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (tv *TLSVersion) UnmarshalYAML(unmarshal func(any) error) error { var s string err := unmarshal(&s) if err != nil { @@ -512,7 +530,7 @@ func (tv *TLSVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { return errors.New("unknown TLS version: " + s) } -func (tv *TLSVersion) MarshalYAML() (interface{}, error) { +func (tv *TLSVersion) MarshalYAML() (any, error) { for s, v := range tlsVersions { if *tv == v { return s, nil diff --git a/vendor/github.com/prometheus/procfs/net_wireless.go b/vendor/github.com/prometheus/procfs/net_wireless.go index 69d07944516..f74dd3bed04 100644 --- a/vendor/github.com/prometheus/procfs/net_wireless.go +++ b/vendor/github.com/prometheus/procfs/net_wireless.go @@ -114,47 +114,47 @@ func parseWireless(r io.Reader) ([]*Wireless, error) { qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], ".")) if err != nil { - return nil, fmt.Errorf("%w: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err) + return nil, fmt.Errorf("%w: parse Quality:link as integer %q: %w", ErrFileParse, stats[1], err) } qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], ".")) if err != nil { - return nil, fmt.Errorf("%w: Quality:level as integer %q: %w", ErrFileParse, qlevel, err) + return nil, fmt.Errorf("%w: Quality:level as integer %q: %w", ErrFileParse, stats[2], err) } qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], ".")) if err != nil { - return nil, fmt.Errorf("%w: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err) + return nil, fmt.Errorf("%w: Quality:noise as integer %q: %w", ErrFileParse, stats[3], err) } dnwid, err := strconv.Atoi(stats[4]) if err != nil { - return nil, fmt.Errorf("%w: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err) + return nil, fmt.Errorf("%w: Discarded:nwid as integer %q: %w", ErrFileParse, stats[4], err) } dcrypt, err := strconv.Atoi(stats[5]) if err != nil { - return nil, fmt.Errorf("%w: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err) + return nil, fmt.Errorf("%w: Discarded:crypt as integer %q: %w", ErrFileParse, stats[5], err) } dfrag, err := strconv.Atoi(stats[6]) if err != nil { - return nil, fmt.Errorf("%w: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err) + return nil, fmt.Errorf("%w: Discarded:frag as integer %q: %w", ErrFileParse, stats[6], err) } dretry, err := strconv.Atoi(stats[7]) if err != nil { - return nil, fmt.Errorf("%w: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err) + return nil, fmt.Errorf("%w: Discarded:retry as integer %q: %w", ErrFileParse, stats[7], err) } dmisc, err := strconv.Atoi(stats[8]) if err != nil { - return nil, fmt.Errorf("%w: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err) + return nil, fmt.Errorf("%w: Discarded:misc as integer %q: %w", ErrFileParse, stats[8], err) } mbeacon, err := strconv.Atoi(stats[9]) if err != nil { - return nil, fmt.Errorf("%w: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err) + return nil, fmt.Errorf("%w: Missed:beacon as integer %q: %w", ErrFileParse, stats[9], err) } w := &Wireless{ diff --git a/vendor/github.com/prometheus/procfs/proc_cgroup.go b/vendor/github.com/prometheus/procfs/proc_cgroup.go index 535c08d6fc0..7e8a122978f 100644 --- a/vendor/github.com/prometheus/procfs/proc_cgroup.go +++ b/vendor/github.com/prometheus/procfs/proc_cgroup.go @@ -60,7 +60,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) { } cgroup.HierarchyID, err = strconv.Atoi(fields[0]) if err != nil { - return nil, fmt.Errorf("%w: hierarchy ID: %q", ErrFileParse, cgroup.HierarchyID) + return nil, fmt.Errorf("%w: hierarchy ID: %q", ErrFileParse, fields[0]) } if fields[1] != "" { ssNames := strings.Split(fields[1], ",") diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/atomic_maybe_work.go b/vendor/github.com/twmb/franz-go/pkg/kgo/atomic_maybe_work.go index 1cf93ad68ed..63c360fb96f 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/atomic_maybe_work.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/atomic_maybe_work.go @@ -61,6 +61,18 @@ func (l *workLoop) maybeFinish(again bool) bool { return again } +// hardFinish forces the loop back to unstarted, discarding any pending +// continue-work bump that a concurrent maybeBegin may have set. Unlike +// maybeFinish, it does not observe or preserve that bump, so work a racing +// pusher enqueued can be stranded with no worker running. +// +// This is safe only where the strand is moot or compensated. Most callers +// hardFinish because their session or client context just died, so any +// stranded work is being torn down anyway. The one transient caller is +// loopFetch hitting noConsumerSession: it compensates by reloading the +// session after hardFinish and re-triggering if a new one appeared (the +// race the comment there walks through). A new transient caller must do +// the same. func (l *workLoop) hardFinish() { l.state.Store(stateUnstarted) } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/broker.go b/vendor/github.com/twmb/franz-go/pkg/kgo/broker.go index 2386eb24ba6..8a7051aeb48 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/broker.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/broker.go @@ -36,6 +36,17 @@ var ctxPinReq = func() *string { v := "pin_req"; return &v }() type forceOpenReq struct{ kmsg.Request } +// reauthDrainReq is an internal sentinel pushed through the broker's request +// ring by a connection's handleResps worker as it exits with a sasl +// reauthentication pending. It runs handleReauthDrain on the broker worker +// goroutine: reauthenticate now that no reads are in flight, then replay the +// requests that parked while the pipeline drained. The embedded kmsg.Request +// is nil and never used; handleReq dispatches on the type before touching it. +type reauthDrainReq struct { + kmsg.Request + cxn *brokerCxn +} + type promisedReq struct { ctx context.Context req kmsg.Request @@ -137,10 +148,12 @@ type broker struct { addr string // net.JoinHostPort(meta.Host, meta.Port) meta BrokerMetadata - // versions tracks the first load of an ApiVersions. We store this - // after the first connect, which helps speed things up on future - // reconnects (across any of the three broker connections) because we - // will never look up API versions for this broker again. + // versions tracks the broker's last loaded ApiVersions. Every new + // connection re-issues ApiVersions and re-stores the result (see + // brokerCxn.init), but the stored value serves request version + // resolution across all five broker connections and client-level + // capability checks (supportsKeyVersion, supportsFeature) without + // opening a connection. versions atomic.Value // *brokerVersions // The cxn fields each manage a single tcp connection to one broker. @@ -222,6 +235,17 @@ func unknownSeedID(seedNum int) int32 { } func (cl *Client) newBroker(nodeID int32, host string, port int32, rack *string) *broker { + // Clone the Rack *string so the broker owns its own pointer. A + // user-issued cl.Request(MetadataRequest) is hijacked through + // fetchMetadata, which builds brokers from the response and then + // returns that same response to the user: a user writing *Rack + // through their response would race every internal deref of + // b.meta.Rack (brokerRacks, dups in RequestCachedMetadata, + // meta.equals on a later metadata update). + if rack != nil { + r := *rack + rack = &r + } return &broker{ cl: cl, @@ -243,14 +267,20 @@ func (b *broker) stopForever() { b.reqs.die() // no more pushing + // Snapshot the connections under reapMu but die outside of it: die + // runs the user's OnBrokerDisconnect hook, and a hook must not run + // under reapMu (a hook that waits on anything that itself needs + // reapMu, e.g. a concurrent request's loadConnection, would + // deadlock). b.dead is already set above and loadConnection re-checks + // it under reapMu before storing, so no new connection can be stored + // after this snapshot. b.reapMu.Lock() - defer b.reapMu.Unlock() + cxns := []*brokerCxn{b.cxnNormal, b.cxnProduce, b.cxnFetch, b.cxnGroup, b.cxnSlow} + b.reapMu.Unlock() - b.cxnNormal.die() - b.cxnProduce.die() - b.cxnFetch.die() - b.cxnGroup.die() - b.cxnSlow.die() + for _, cxn := range cxns { + cxn.die() + } } // do issues a request to the broker, eventually calling the response @@ -304,6 +334,11 @@ start: func (b *broker) handleReq(pr promisedReq) { req := pr.req + if r, ok := req.(*reauthDrainReq); ok { + b.handleReauthDrain(r.cxn) + pr.promise(nil, nil) // internal sentinel; the promise is a no-op + return + } var cxn *brokerCxn var retriedOnNewConnection bool start: @@ -400,17 +435,61 @@ start: } req.SetVersion(ourMax) - if !cxn.expiry.IsZero() && time.Now().After(cxn.expiry) { - // If we are after the reauth time, try to reauth. We - // can only have an expiry if we went the authenticate - // flow, so we know we are authenticating again. + if !cxn.expiry.IsZero() && time.Now().After(cxn.expiry) && !cxn.hasDiscard { + // If we are after the reauth time, reauthenticate, for KIP-368. + // We can only have an expiry if we went the authenticate flow, + // so we know we are authenticating again. // + // Reauthenticating reads the handshake and authenticate + // responses on this goroutine, so it requires that nothing + // else can be reading the connection: + // + // * If any response is in flight (resps is non-empty -- an + // element stays in the ring while handleResps processes + // it), handleResps is reading this connection and our read + // would race it byte-by-byte, interleaving the two + // responses' bytes between the two readers. We park this + // request (and every following request for this connection) + // so the pipeline drains -- under sustained pipelining the + // pipeline never goes empty on its own, so we must stop + // feeding it. Our expiry is deliberately pessimistic (2-5% + // early, 1s floor; see doSasl), so the in-flight responses + // are on a still-valid session and the drain (bounded by + // their read timeouts) fits the margin. handleResps pushes + // a reauthDrainReq as it exits; handleReauthDrain then + // reauthenticates and replays the parked requests in + // order. Only this connection parks: the broker worker + // keeps serving its other connections. The Java client + // similarly holds the channel's queued send while + // reauthenticating, and it too only begins with no write + // in progress. + // + // Ordering of the pending store vs the empty check below + // matters: we store before checking, and handleResps reads + // the flag after its final dropPeek. empty() and dropPeek + // both take the ring mutex, so if we observe a non-empty + // ring, our store happens-before the drain's flag read and + // a parked request can never miss its drain signal. + // + // * acks=0 produce connections run a discard goroutine that + // owns all reads forever (hasDiscard, checked above), so + // in-place reauth is never possible: loadConnection + // recreates expired discard connections instead, and a + // fresh connection authenticates in init. We can still get + // here if the connection's lifetime is shorter than our + // pessimism (the fresh connection is already "expired"); + // issuing the request on the just-authenticated connection + // is correct, and the next request picks up a new one. + cxn.reauthPending.Store(true) + if cxn.anyParked() || !cxn.resps.empty() { + cxn.park(pr) + return + } + cxn.reauthPending.Store(false) // Some implementations (AWS) occasionally fail for // unclear reasons (principals change, somehow). If // we receive SASL_AUTHENTICATION_FAILED, we retry // once on a new connection. See #249. - // - // For KIP-368. cxn.cl.cfg.logger.Log(LogLevelDebug, "sasl expiry limit reached, reauthenticating", "broker", logID(cxn.b.meta.NodeID)) if err := cxn.sasl(); err != nil { cxn.die() @@ -438,6 +517,20 @@ start: } if _, isForceOpen := req.(*forceOpenReq); isForceOpen { + // The connection is already fully open: loadConnection ran init + // (dial, ApiVersions, SASL). On an acks=0 produce connection the + // discard goroutine owns all reads (hasDiscard), so issuing a + // response-expecting request here would start a second reader + // (handleResps, via waitResp below) that races the discard read on + // the same socket -- the two io.ReadFulls split one byte stream, + // the same concurrent-reader hazard the expiry arm and + // loadConnection already avoid for reauthentication. The connection + // is warm; report success without probing it (init already proved + // the connection works end to end). + if cxn.hasDiscard { + pr.promise(nil, nil) + return + } // We issue ApiVersions with v0; we could try to bound the // version by going to the start above, but it really does // not matter much. @@ -565,12 +658,19 @@ func (b *broker) loadConnection(ctx context.Context, req kmsg.Request) (*brokerC pcxn = &b.cxnSlow } - // Do not reuse a connection that has been idle for longer than idle timeout. - // Kill it instead. - if *pcxn != nil && !(*pcxn).dead.Load() && (*pcxn).isIdleTimeout(b.cl.cfg.connIdleTimeout) { - // die() in a goroutine to avoid blocking - go (*pcxn).die() - reuse = false + // Do not reuse a connection that has been idle for longer than idle + // timeout; kill it instead. Same for an acks=0 produce connection + // whose sasl session expired: the discard goroutine owns all reads on + // it, so in-place reauthentication (which reads handshake responses) + // is impossible -- a fresh connection authenticates in init. + if *pcxn != nil && !(*pcxn).dead.Load() { + cxn := *pcxn + expired := cxn.hasDiscard && !cxn.expiry.IsZero() && time.Now().After(cxn.expiry) + if cxn.isIdleTimeout(b.cl.cfg.connIdleTimeout) || expired { + // die() in a goroutine to avoid blocking + go cxn.die() + reuse = false + } } if reuse && *pcxn != nil && !(*pcxn).dead.Load() { @@ -578,9 +678,13 @@ func (b *broker) loadConnection(ctx context.Context, req kmsg.Request) (*brokerC } var tries int - start := time.Now() doConnect: tries++ + // start, conn, and err are declared per attempt so that each attempt's + // deferred OnBrokerConnect hook reports that attempt's connection, + // error, and duration (a backward goto over := re-executes the + // declaration; prior attempts' defers keep their own variables). + start := time.Now() conn, err := b.connect(ctx) defer func() { since := time.Since(start) @@ -606,12 +710,10 @@ doConnect: // EventHubs does not handle v4 and resets the connection. We // retry twice. On the first and second attempt, we try our max // version possible (as should be allowed). On the third try, - // we downgrade to v0. - if er := (*errApiVersionsReset)(nil); errors.As(err, &er) { - if tries < 3 { - tries++ - goto doConnect - } + // we downgrade to v0 (see requestAPIVersions). + if er := (*errApiVersionsReset)(nil); errors.As(err, &er) && tries < 3 { + cxn.closeConn() + goto doConnect } b.cl.cfg.logger.Log(LogLevelDebug, "connection initialization failed", "addr", b.addr, "broker", logID(b.meta.NodeID), "err", err) cxn.closeConn() @@ -626,24 +728,28 @@ doConnect: } b.reapMu.Lock() - defer b.reapMu.Unlock() // If stopForever ran while we were connecting, the broker is - // dead and we must not store the connection. stopForever kills - // cxnProduce/etc under reapMu, but if the connection was nil at - // that time (we were mid-connect), stopForever's die() was a - // no-op. Without this check, the connection escapes destruction + // dead and we must not store the connection. stopForever reads + // cxnProduce/etc under reapMu before killing them, but if the + // connection was nil at that time (we were mid-connect), it was + // not seen. Without this check, the connection escapes destruction // and a produce request succeeds on a connection that will never // be reused, which -- combined with other connections from other // broker objects for the same nodeID -- breaks the single- // connection-per-broker ordering guarantee that Kafka requires // for idempotent produce. + // + // closeConn runs the user's OnBrokerDisconnect hook, so it runs + // after the unlock (see stopForever for why). if b.dead.Load() { + b.reapMu.Unlock() cxn.closeConn() return nil, errChosenBrokerDead } *pcxn = cxn + b.reapMu.Unlock() return cxn, nil } @@ -687,16 +793,20 @@ func (cl *Client) reapConnections(idleTimeout time.Duration) (total int) { } func (b *broker) reapConnections(idleTimeout time.Duration) (total int) { + // Snapshot under reapMu, evaluate and die outside: die runs the + // user's OnBrokerDisconnect hook, which must not run under reapMu + // (see stopForever). b.reapMu.Lock() - defer b.reapMu.Unlock() - - for _, cxn := range []*brokerCxn{ + cxns := []*brokerCxn{ b.cxnNormal, b.cxnProduce, b.cxnFetch, b.cxnGroup, b.cxnSlow, - } { + } + b.reapMu.Unlock() + + for _, cxn := range cxns { if cxn == nil || cxn.dead.Load() { continue } @@ -766,8 +876,75 @@ type brokerCxn struct { resps ring[promisedResp] // dead is an atomic so that a backed up resps cannot block cxn death. dead atomic.Bool - // closed in cloneConn; allows throttle waiting to quit + // closed in closeConn; allows throttle waiting to quit deadCh chan struct{} + // hasDiscard is set during init (before the connection is shared) if + // this is an acks=0 produce connection running the discard goroutine. + // The discard goroutine owns all reads on the connection, so sasl + // reauthentication can never happen in place; see handleReq and + // loadConnection. + hasDiscard bool + + // reauthPending is set by the broker worker when the sasl expiry has + // passed but responses are still in flight (handleResps owns reads, + // so reauthenticating would race it). While pending, requests for + // this connection park instead of being written, so the pipeline + // drains; handleResps pushes a reauthDrainReq as it exits to + // reauthenticate and replay them. See handleReq's expiry arm for the + // store/load ordering argument. + reauthPending atomic.Bool + + // parkMu guards parked/parkFailed. parked holds requests, in arrival + // order, that are waiting for a pending reauthentication; order + // matters for idempotent produce, whose sequence numbers were + // assigned at request build. die fails everything parked (and marks + // parkFailed) so a dead connection cannot strand requests. + parkMu xsync.Mutex + parked []promisedReq + parkFailed bool +} + +// park holds a request destined for this connection while a sasl +// reauthentication is pending; handleReauthDrain replays parked requests in +// order once the pipeline drains. If the connection already died (die fails +// everything parked), the request fails immediately with the same retryable +// error that ring-queued requests receive on broker death. +func (cxn *brokerCxn) park(pr promisedReq) { + cxn.parkMu.Lock() + if cxn.parkFailed { + cxn.parkMu.Unlock() + pr.promise(nil, errChosenBrokerDead) + return + } + cxn.parked = append(cxn.parked, pr) + n := len(cxn.parked) + cxn.parkMu.Unlock() + cxn.cl.cfg.logger.Log(LogLevelDebug, "sasl expiry limit reached but responses are in flight, parking request until the pipeline drains", "broker", logID(cxn.b.meta.NodeID), "parked_reqs", n) +} + +func (cxn *brokerCxn) anyParked() bool { + cxn.parkMu.Lock() + defer cxn.parkMu.Unlock() + return len(cxn.parked) > 0 +} + +func (cxn *brokerCxn) takeParked() []promisedReq { + cxn.parkMu.Lock() + defer cxn.parkMu.Unlock() + parked := cxn.parked + cxn.parked = nil + return parked +} + +func (cxn *brokerCxn) failParked() { + cxn.parkMu.Lock() + parked := cxn.parked + cxn.parked = nil + cxn.parkFailed = true + cxn.parkMu.Unlock() + for _, pr := range parked { + pr.promise(nil, errChosenBrokerDead) + } } func (cxn *brokerCxn) init(isProduceCxn bool, tries int) error { @@ -800,6 +977,7 @@ func (cxn *brokerCxn) init(isProduceCxn bool, tries int) error { } if isProduceCxn && cxn.cl.cfg.acks.val == 0 { + cxn.hasDiscard = true go cxn.discard() // see docs on discard for why we do this } return nil @@ -871,9 +1049,19 @@ start: cxn.cl.cfg.logger.Log(LogLevelDebug, "broker does not know our ApiVersions version, downgrading to version 0 and retrying", "broker", logID(cxn.b.meta.NodeID)) goto start case len(resp.ApiKeys) == 1 && resp.ApiKeys[0].ApiKey == 18: - maxVersion = resp.ApiKeys[0].MaxVersion - cxn.cl.cfg.logger.Log(LogLevelDebug, fmt.Sprintf("broker does not know our ApiVersions version but replied version %[1]d, downgrading to version %[1]d and retrying", maxVersion), "broker", logID(cxn.b.meta.NodeID)) - goto start + // KIP-511: the broker replies with the version we should + // retry with. Only accept a strictly lower, non-negative + // version: a real broker advertises less than what it + // just rejected, and accepting anything else would let a + // buggy/hostile broker keep us in this downgrade loop + // forever (the init path runs on no request context, so + // only client close would stop it). + if v := resp.ApiKeys[0].MaxVersion; v >= 0 && v < maxVersion { + maxVersion = v + cxn.cl.cfg.logger.Log(LogLevelDebug, fmt.Sprintf("broker does not know our ApiVersions version but replied version %[1]d, downgrading to version %[1]d and retrying", maxVersion), "broker", logID(cxn.b.meta.NodeID)) + goto start + } + return fmt.Errorf("broker replied with UNSUPPORTED_VERSION to our v%d ApiVersions request but advertised non-downgrade version %d", maxVersion, resp.ApiKeys[0].MaxVersion) default: // Should not hit this case, but we hope the broker replied with all keys } @@ -1055,6 +1243,16 @@ func (cxn *brokerCxn) doSasl(authenticate bool) error { } if lifetimeMillis > 0 { + // A hostile/buggy broker can reply with a lifetime so large + // that converting it to a time.Duration overflows, wrapping + // the expiry into the past and forcing a reauth before every + // request. Anything beyond a year never matters for a real + // connection; clamp. + const maxLifetimeMillis = 365 * 24 * int64(time.Hour/time.Millisecond) + if lifetimeMillis > maxLifetimeMillis { + lifetimeMillis = maxLifetimeMillis + } + // Lifetime is problematic. We need to be a bit pessimistic. // // We want a lowerbound: we use 1s (arbitrary), but if 1.1x our @@ -1093,6 +1291,14 @@ func (cxn *brokerCxn) doSasl(authenticate bool) error { "lifetime_pessimism", time.Duration(usePessimismMillis)*time.Millisecond, "reauthenticate_in", cxn.expiry.Sub(now), ) + } else { + // No (or zero) lifetime means the broker does not require + // reauthentication, KIP-368. If a previous authenticate on + // this connection set an expiry (reauth was enabled then, e.g. + // before a dynamic broker config change), clear it: keeping + // the old, already-passed expiry would re-run the full sasl + // flow before every subsequent request on this connection. + cxn.expiry = time.Time{} } return nil } @@ -1384,9 +1590,11 @@ func (cxn *brokerCxn) readResponse( return buf[4:], nil } -// closeConn is the one place we close broker connections. This is always done -// in either die, which is called when handleResps returns, or if init fails, -// which means we did not succeed enough to start handleResps. +// closeConn is the one place we close broker connections. It is reached via +// die (callable from anywhere once the connection is live: read/write errors, +// reaping, broker stoppage) or directly when the connection was never shared: +// init failure, the ApiVersions-reset retry, and loadConnection's dead-broker +// arm. func (cxn *brokerCxn) closeConn() { cxn.cl.cfg.hooks.each(func(h Hook) { if h, ok := h.(HookBrokerDisconnect); ok { @@ -1398,13 +1606,15 @@ func (cxn *brokerCxn) closeConn() { } // die kills a broker connection (which could be dead already) and replies to -// all requests awaiting responses appropriately. +// all requests awaiting responses appropriately, including requests parked +// for a pending reauthentication. func (cxn *brokerCxn) die() { if cxn == nil || cxn.dead.Swap(true) { return } cxn.closeConn() cxn.resps.die() + cxn.failParked() } // waitResp, called serially by a broker's handleReqs, manages handling a @@ -1529,7 +1739,7 @@ func (cxn *brokerCxn) discard() { } nread2, err = cxn.conn.Read(discard) nread += nread2 - size -= int32(nread2) // nread2 max is 128 + size -= int32(nread2) // nread2 max is len(discardBuf), 256 } }() @@ -1570,6 +1780,60 @@ start: if more { goto start } + + // The ring is empty and this worker is exiting: no read is in flight + // and none can start (only the broker worker pushes responses, and it + // parks requests for this connection while a reauth is pending). If a + // reauth is pending, signal the broker worker to perform it and + // replay the parked requests. If the broker is stopping, the failed + // push is fine: stopForever dies every connection, and die fails + // everything parked. + if cxn.reauthPending.Load() { + cxn.b.do(cxn.cl.ctx, &reauthDrainReq{cxn: cxn}, func(kmsg.Response, error) {}) + } +} + +// handleReauthDrain runs on the broker worker goroutine when a connection +// with a pending reauthentication has drained its in-flight responses (its +// handleResps worker pushed this sentinel as it exited). No reads can be in +// flight: handleResps exited, only this goroutine starts another (by writing +// a request), and every request for this connection since the expiry passed +// was parked. Reauthenticate and replay the parked requests in their +// original order -- order matters for idempotent produce, whose sequence +// numbers were assigned at request build. +func (b *broker) handleReauthDrain(cxn *brokerCxn) { + // A sentinel can be spurious: the quiet-connection reauth arm stores + // the pending flag and clears it just after, and a concurrently + // exiting handleResps can observe the transient true. That alone is + // a harmless no-op below -- but if the broker also hands out + // immediately-expiring lifetimes, a request queued behind this + // sentinel's push may have re-parked by now with a NEW response in + // flight (the inline arm's own request), so "drained" no longer + // holds. If anything is in flight, touch nothing: that response's + // handleResps exit re-signals (the parker stored the pending flag + // before observing the non-empty ring, so the exit cannot miss it) + // and the re-signal finds the connection actually quiet. + if !cxn.resps.empty() { + return + } + + // Take the parked requests before a possible die below: a failed + // reauth must not fail them, it replays them through the normal path, + // which builds a fresh connection with a fresh authentication -- the + // same recovery the in-place reauth arm provides via its + // retry-on-new-connection. (If the connection died earlier, die + // already failed everything parked and this take returns nil.) + parked := cxn.takeParked() + if cxn.reauthPending.Swap(false) && !cxn.dead.Load() { + cxn.cl.cfg.logger.Log(LogLevelDebug, "sasl expiry limit reached and responses have drained, reauthenticating", "broker", logID(cxn.b.meta.NodeID), "parked_reqs", len(parked)) + if err := cxn.sasl(); err != nil { + cxn.cl.cfg.logger.Log(LogLevelDebug, "sasl reauth failed, killing connection; any parked requests retry on a new connection", "broker", logID(cxn.b.meta.NodeID), "err", err) + cxn.die() + } + } + for _, pr := range parked { + b.handleReq(pr) + } } func (cxn *brokerCxn) handleResp(pr promisedResp) { @@ -1618,6 +1882,14 @@ func (cxn *brokerCxn) handleResp(pr promisedResp) { if readErr == nil { if throttleResponse, ok := pr.resp.(kmsg.ThrottleResponse); ok { millis, throttlesAfterResp := throttleResponse.Throttle() + // A throttle is honored in full with NO upper cap (KIP-219), + // matching Java's NetworkClient. millis <= 0 is ignored; a + // positive value - even a hostile near-MaxInt32 (~24.8 days) - + // delays the next write on this connection (writeRequest), which + // selects on the request ctx and client Close, so the wait is + // always interruptible and holds no lock. Capping it would break + // the quota mechanism; an absurd throttle is equivalent to a slow + // broker, which is always possible. Do not add a cap. if millis > 0 { if pr.resp.Key() == 0 { cxn.b.cl.metrics.observeTime(&cxn.b.cl.metrics.pThrottle, int64(millis)) diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/client.go b/vendor/github.com/twmb/franz-go/pkg/kgo/client.go index f82e59838b4..eaba2c3c45d 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/client.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/client.go @@ -100,7 +100,6 @@ type Client struct { topics map[string]cachedMetaTopic byID map[[16]byte]string // TopicID => topic name allAt time.Time // when last all-topics fetch completed - anyAt time.Time // when any cached metadata was last stored } } @@ -372,7 +371,7 @@ func (cl *Client) OptValues(opt any) []any { return []any{cfg.recordTimeout} case namefn(TransactionalID): if cfg.txnID != nil { - return []any{cfg.txnID, true} + return []any{*cfg.txnID, true} } return []any{"", false} case namefn(TransactionTimeout): @@ -462,6 +461,14 @@ func (cl *Client) OptValues(opt any) []any { return []any{true} case namefn(SessionTimeout): return []any{cfg.sessionTimeout} + case namefn(ShareGroup): + return []any{cfg.shareGroup} + case namefn(ShareAckCallback): + return []any{cfg.shareAckCallback} + case namefn(ShareMaxRecords): + return []any{cfg.shareMaxRecords} + case namefn(ShareMaxRecordsStrict): + return []any{cfg.shareMaxRecordsStrict} default: return nil @@ -681,7 +688,7 @@ func (cl *Client) Ping(ctx context.Context) error { // // For admin requests, this deletes the topic from the cached metadata map for // sharded requests. Metadata for sharded admin requests is only cached for -// MetadataMinAge anyway, but the map is not cleaned up one the metadata +// MetadataMinAge anyway, but the map is not cleaned up once the metadata // expires. This function ensures the map is purged. func (cl *Client) PurgeTopicsFromClient(topics ...string) { if len(topics) == 0 { @@ -935,7 +942,21 @@ func (cl *Client) supportsOffsetForLeaderEpoch() bool { // v1 introduces support for regex and requires the client to generate // the member ID, and fully stabilizes KIP-848. func (cl *Client) supportsKIP848v1() bool { - return cl.supportsKeyVersion(int16(kmsg.ConsumerGroupHeartbeat), 1) + if !cl.supportsKeyVersion(int16(kmsg.ConsumerGroupHeartbeat), 1) { + return false + } + // The 848 manage loop runs v1 semantics (client-generated member ID, + // regex subscriptions). If the user's MaxVersions caps the heartbeat + // below v1, the wire request would be v0 while we behave as v1: v0 + // has no SubscribedTopicRegex field at all, so a regex consumer's + // join would carry no subscription and silently consume nothing. + // Only opt in if the cap allows v1, mirroring supportsKIP890p2. + if mv := cl.cfg.maxVersions; mv != nil { + if v, ok := mv.LookupMaxKeyVersion(int16(kmsg.ConsumerGroupHeartbeat)); !ok || v < 1 { + return false + } + } + return true } // Called after the first metric observed, which is always after a response. @@ -964,7 +985,28 @@ func (cl *Client) supportsKeyVersion(key, version int16) bool { } func (cl *Client) supportsKIP890p2() bool { - return cl.supportsFeature("transaction.version", 2) + if !cl.supportsFeature("transaction.version", 2) { + return false + } + // The KIP-890 part 2 paths change what goes on the wire: produce v12+ + // skips AddPartitionsToTxn, TxnOffsetCommit v5+ skips AddOffsetsToTxn, + // and EndTxn v5+ bumps the producer epoch. A user MaxVersions cap + // below any of those keeps the OLD wire versions while skipping the + // explicit add requests, and the broker then rejects the produces + // with INVALID_TXN_STATE because the partitions were never added to + // the transaction. Only opt in if the cap allows the new versions. + if mv := cl.cfg.maxVersions; mv != nil { + if v, ok := mv.LookupMaxKeyVersion(int16(kmsg.Produce)); !ok || v < 12 { + return false + } + if v, ok := mv.LookupMaxKeyVersion(int16(kmsg.EndTxn)); !ok || v < 5 { + return false + } + if v, ok := mv.LookupMaxKeyVersion(int16(kmsg.TxnOffsetCommit)); !ok || v < 5 { + return false + } + } + return true } // Same as above. A cluster returns a max version for a feature only once the @@ -988,32 +1030,42 @@ func (cl *Client) supportsFeature(name string, version int16) bool { } // fetchBrokerMetadata issues a metadata request solely for broker information. +// +// Concurrent callers collapse onto one in-flight request. The request itself +// runs on the client context: if it ran on the initiating caller's context, +// that caller canceling would fail every collapsed waiter with the canceled +// error even though their own contexts are live (the same reasoning as +// doLoadCoordinators). Each caller's context governs only its own wait; an +// abandoned fetch still completes and updates broker state, which is fine. func (cl *Client) fetchBrokerMetadata(ctx context.Context) error { cl.fetchingBrokersMu.Lock() wait := cl.fetchingBrokers - if wait != nil { - cl.fetchingBrokersMu.Unlock() - <-wait.done - return wait.err + if wait == nil { + wait = &struct { + done chan struct{} + err error + }{done: make(chan struct{})} + cl.fetchingBrokers = wait + go func() { + defer func() { + cl.fetchingBrokersMu.Lock() + defer cl.fetchingBrokersMu.Unlock() + cl.fetchingBrokers = nil + close(wait.done) + }() + req := kmsg.NewPtrMetadataRequest() + req.Topics = []kmsg.MetadataRequestTopic{} + _, _, wait.err = cl.fetchMetadata(cl.ctx, req, true, nil) + }() } - wait = &struct { - done chan struct{} - err error - }{done: make(chan struct{})} - cl.fetchingBrokers = wait cl.fetchingBrokersMu.Unlock() - defer func() { - cl.fetchingBrokersMu.Lock() - defer cl.fetchingBrokersMu.Unlock() - cl.fetchingBrokers = nil - close(wait.done) - }() - - req := kmsg.NewPtrMetadataRequest() - req.Topics = []kmsg.MetadataRequestTopic{} - _, _, wait.err = cl.fetchMetadata(ctx, req, true, nil) - return wait.err + select { + case <-wait.done: + return wait.err + case <-ctx.Done(): + return ctx.Err() + } } func (cl *Client) fetchMetadataByName(ctx context.Context, all bool, topics []string, results map[string]cachedMetaTopic) (*broker, *kmsg.MetadataResponse, error) { @@ -1106,14 +1158,32 @@ func (cl *Client) updateMetadataBrokers(resp *kmsg.MetadataResponse) { if resp.ControllerID >= 0 { cl.controllerID = resp.ControllerID } - cl.clusterID = resp.ClusterID + // Clone ClusterID so cl.clusterID owns its own *string, independent + // of the broker response. Readers (dups in RequestCachedMetadata) + // would otherwise race a user mutating *resp.ClusterID on a + // previously-returned cl.Request(MetadataRequest) response. + cl.clusterID = nil + if resp.ClusterID != nil { + s := *resp.ClusterID + cl.clusterID = &s + } cl.controllerIDMu.Unlock() cl.updateBrokers(resp.Brokers) } // updateBrokers is called with the broker portion of every metadata response. -// All metadata responses contain all known live brokers, so we can always -// use the response. +// All metadata responses contain all known live brokers, so the response list +// is authoritative and we diff-merge it: brokers absent from it are stopped. +// +// An EMPTY list therefore wipes all discovered brokers and falls back to +// seeds. This is intentional and long-standing: if a broker ever answers +// metadata with no brokers, falling back to the seeds is safer than being +// left with none, and it re-covers every seed should the cluster have somehow +// split. KIP-1102's rebootstrap rides the same path, calling updateBrokers(nil) +// explicitly. A buggy broker sending a transient subset only kills those +// connections (in-flight requests fail with retriable errChosenBrokerDead) and +// the next good response heals. Do not special-case the empty list back into a +// no-op. func (cl *Client) updateBrokers(brokers []kmsg.MetadataResponseBroker) { sort.Slice(brokers, func(i, j int) bool { return brokers[i].NodeID < brokers[j].NodeID }) newBrokers := make([]*broker, 0, len(brokers)) @@ -1263,23 +1333,28 @@ func (cl *Client) close(ctx context.Context) (rerr error) { wg.Wait() sessCloseCancel() - // Now we kill the client context and all brokers, ensuring all - // requests fail. This will finish all producer callbacks and - // stop the metadata loop and metrics loop. - cl.ctxCancel() - - // Before killing brokers, give metrics 1s to push any final - // terminating message. The client context cancelation awakens - // the push-period-wait loop. + // Tell the metrics loop to send its final Terminating=true push and + // give it 1s to do so. This must happen BEFORE we cancel the client + // context: the entire request path (shardedRequest's cancel watchdog, + // Broker.request's select, and the broker connection write/read + // loops) aborts requests once cl.ctx is dead, so a terminating push + // started after cancelation could never be delivered. The metrics + // loop cancels metrics.ctx when it exits; clients with metrics + // disabled, unsupported, or never observed pass through instantly. + cl.metrics.quit() after := time.NewTimer(time.Second) select { case <-cl.metrics.ctx.Done(): + after.Stop() case <-after.C: cl.metrics.ctxCancel() - case <-ctx.Done(): - cl.metrics.ctxCancel() } + // Now we kill the client context and all brokers, ensuring all + // requests fail. This will finish all producer callbacks and + // stop the metadata loop and metrics loop. + cl.ctxCancel() + cl.brokersMu.Lock() cl.stopBrokers = true for _, broker := range cl.brokers { @@ -1349,6 +1424,8 @@ func (cl *Client) close(ctx context.Context) (rerr error) { // ListGroups // DeleteRecords // OffsetForLeaderEpoch +// AddPartitionsToTxn +// WriteTxnMarkers // DescribeConfigs // AlterConfigs // AlterReplicaLogDirs @@ -1511,7 +1588,7 @@ func (cl *Client) RequestCachedMetadata(ctx context.Context, req *kmsg.MetadataR NodeID: b.meta.NodeID, Host: b.meta.Host, Port: b.meta.Port, - Rack: b.meta.Rack, + Rack: dups(b.meta.Rack), }) } cl.brokersMu.RUnlock() @@ -1657,7 +1734,7 @@ type ResponseShard struct { // unknown (node ID -1) metadata if the request could not be issued. // // Requests can fail to even be issued if an appropriate broker cannot - // be loaded of if the client cannot understand the request. + // be loaded or if the client cannot understand the request. Meta BrokerMetadata // Req is the request that was issued to this broker. @@ -1683,9 +1760,9 @@ type ResponseShard struct { // // If, in the process of splitting a request, some topics or partitions are // found to not exist, or Kafka replies that a request should go to a broker -// that does not exist, all those non-existent pieces are grouped into one -// request to the first seed broker. This will show up as a seed broker node ID -// (min int32) and the response will likely contain purely errors. +// that does not exist, all those non-existent pieces are not issued; they are +// returned as error shards with an unknown broker metadata (node ID -1) and +// the error that prevented the piece from being mapped to a broker. // // The response shards are ordered by broker metadata. func (cl *Client) RequestSharded(ctx context.Context, req kmsg.Request) []ResponseShard { @@ -1827,20 +1904,23 @@ func findBroker(candidates []*broker, node int32) *broker { // that error. func (cl *Client) brokerOrErr(ctx context.Context, id int32, err error) (*broker, error) { if id < 0 { + // Negative IDs are seed brokers (unknownSeedID), exposed to + // users via SeedBrokers(). Any other negative ID (-1 unknown + // controller / coordinator sentinels) never exists, and + // metadata responses cannot introduce negative IDs, so we + // look up seeds directly and never try a metadata load. + if b := findBroker(cl.loadSeeds(), id); b != nil { + return b, nil + } return nil, err } tryLoad := ctx != nil tries := 0 start: - var broker *broker - if id < 0 { - broker = findBroker(cl.loadSeeds(), id) - } else { - cl.brokersMu.RLock() - broker = findBroker(cl.brokers, id) - cl.brokersMu.RUnlock() - } + cl.brokersMu.RLock() + broker := findBroker(cl.brokers, id) + cl.brokersMu.RUnlock() if broker == nil { if tryLoad { @@ -1897,6 +1977,11 @@ func (cl *Client) forgetControllerID(id int32) { } } +// Coordinator types match Kafka's FindCoordinator key-type enum. +// coordinatorTypeShare (the share-state coordinator) is keyed by a +// groupId:topicId:partition SharePartitionKey and serves only the +// broker-internal persister RPCs (keys 83-87), which kgo never issues; share +// groups go entirely through the GROUP coordinator (see #1330). const ( coordinatorTypeGroup int8 = 0 coordinatorTypeTxn int8 = 1 @@ -1934,13 +2019,13 @@ func (cl *Client) loadCoordinators(ctx context.Context, typ int8, keys ...string } } -// doLoadCoordinators uses the caller context to cancel loading metadata -// (brokerOrErr), but we use the client context to actually issue the request. -// There should be only one direct call to doLoadCoordinators, just above in -// loadCoordinator. It is possible for two requests to be loading the same -// coordinator (in fact, that's the point of this function -- collapse these -// requests). We do not want the first request canceling it's context to cause -// errors for the second request. +// doLoadCoordinators issues the FindCoordinator request - and any broker +// metadata load needed to resolve the response - on the client context. It is +// possible for two requests to be loading the same coordinator (in fact, +// that's the point of this function -- collapse these requests). We do not +// want the first request canceling its context to cause errors for the +// second request. The caller context only cancels the caller's wait, via +// loadCoordinators above. // // It is ok to leave FindCoordinator running even if the caller quits. Worst // case, we just cache things for some time in the future; yay. @@ -2140,13 +2225,35 @@ func (cl *Client) deleteStaleCoordinatorsByNode(node int32) { cl.coordinatorsMu.Lock() defer cl.coordinatorsMu.Unlock() for k, v := range cl.coordinators { - if v == nil || v.node != node { + if v == nil { continue } + // v.node is written by doLoadCoordinators outside of + // coordinatorsMu; that write is published only by the + // close(loadWait) ending the load. We must observe the close + // before reading v.node, so the v.node check lives inside the + // loadWait arm -- not in the range filter above. + // + // Race walkthrough if we checked v.node before the select: + // 1) doLoadCoordinators inserts v with an open loadWait, then + // releases coordinatorsMu and issues FindCoordinator. + // 2) The response arrives and the loader writes v.node = + // rc.NodeID, lock-free (doLoadCoordinators, above). + // 3) Concurrently a broker disconnect calls us here. We hold + // coordinatorsMu, but the writer in step 2 never takes it, + // so the mutex does not order us against that write -- + // reading v.node now is a data race (go test -race flags + // it). close(loadWait) in step 2 has not happened yet, so + // the default arm is what we would take anyway. + // Reading inside the loadWait arm makes the read happen-after + // the publishing close, so v.node is safe to observe. select { case <-v.loadWait: - delete(cl.coordinators, k) + if v.node == node { + delete(cl.coordinators, k) + } default: + // Still loading: v.node is not yet published; skip. } } } @@ -2285,8 +2392,18 @@ func (cl *Client) handleCoordinatorReq(ctx context.Context, req kmsg.Request) Re case *kmsg.OffsetDeleteRequest: return cl.handleCoordinatorReqSimple(ctx, coordinatorTypeGroup, t.Group, req) - // ConsumerGroupHeartbeat cannot be retried at all + // ConsumerGroupHeartbeat carries reconciliation state and cannot be + // blindly retried; the 848 heartbeat loop owns retries with full + // state knowledge. The exception is leaving (MemberEpoch -1, or -2 + // for static members): a leave carries no reconcilable state and is + // idempotent, and the coordinator moving is precisely when leaves + // are issued against a stale cached coordinator - firing it once + // would lose the leave to a single NOT_COORDINATOR and ghost the + // member until the session timeout. case *kmsg.ConsumerGroupHeartbeatRequest: + if t.MemberEpoch < 0 { + return cl.handleCoordinatorReqSimple(ctx, coordinatorTypeGroup, t.Group, req) + } br, err := cl.loadCoordinator(ctx, coordinatorTypeGroup, t.Group) var resp kmsg.Response if err == nil { @@ -2298,10 +2415,14 @@ func (cl *Client) handleCoordinatorReq(ctx context.Context, req kmsg.Request) Re // SHARE // /////////// - // ShareGroupHeartbeat cannot be retried (like ConsumerGroupHeartbeat). - // Like ConsumerGroupHeartbeat, share membership is managed by the - // GROUP coordinator, not the share-state coordinator. + // ShareGroupHeartbeat cannot be retried (like ConsumerGroupHeartbeat), + // except for the leave, which is retried for the same reason as + // above. Share membership is managed by the GROUP coordinator, not + // the share-state coordinator. case *kmsg.ShareGroupHeartbeatRequest: + if t.MemberEpoch < 0 { + return cl.handleCoordinatorReqSimple(ctx, coordinatorTypeGroup, t.GroupID, req) + } br, err := cl.loadCoordinator(ctx, coordinatorTypeGroup, t.GroupID) var resp kmsg.Response if err == nil { @@ -2309,9 +2430,9 @@ func (cl *Client) handleCoordinatorReq(ctx context.Context, req kmsg.Request) Re } return shard(br, req, resp, err) case *kmsg.AlterShareGroupOffsetsRequest: - return cl.handleCoordinatorReqSimple(ctx, coordinatorTypeShare, t.GroupID, req) + return cl.handleCoordinatorReqSimple(ctx, coordinatorTypeGroup, t.GroupID, req) case *kmsg.DeleteShareGroupOffsetsRequest: - return cl.handleCoordinatorReqSimple(ctx, coordinatorTypeShare, t.GroupID, req) + return cl.handleCoordinatorReqSimple(ctx, coordinatorTypeGroup, t.GroupID, req) } } @@ -2376,6 +2497,8 @@ func (cl *Client) handleReqWithCoordinator( code = t.ErrorCode case *kmsg.ConsumerGroupHeartbeatResponse: code = t.ErrorCode + case *kmsg.ShareGroupHeartbeatResponse: + code = t.ErrorCode } // ListGroups, OffsetFetch, DeleteGroups, DescribeGroups, and @@ -2730,13 +2853,18 @@ func (cl *Client) handleShardedReq(ctx context.Context, req kmsg.Request) ([]Res start: tries++ - br := cl.broker() + var br *broker var err error if !myIssue.any { br, err = cl.brokerOrErr(ctx, myIssue.broker, errUnknownBroker) - } else if avoidBroker != -1 { - for i := 0; i < 3 && br.meta.NodeID == avoidBroker; i++ { - br = cl.broker() + } else { + // Only consume an any-broker rotation slot for + // shards that actually go to any broker. + br = cl.broker() + if avoidBroker != -1 { + for i := 0; i < 3 && br.meta.NodeID == avoidBroker; i++ { + br = cl.broker() + } } } if err != nil { @@ -3016,7 +3144,6 @@ func (cl *Client) storeCachedMeta(meta *kmsg.MetadataResponse, all bool, results cl.metaCache.byID = make(map[[16]byte]string) } when := time.Now() - cl.metaCache.anyAt = when var zeroID [16]byte var stored int for _, topic := range meta.Topics { @@ -3026,22 +3153,49 @@ func (cl *Client) storeCachedMeta(meta *kmsg.MetadataResponse, all bool, results continue } stored++ + // Deep-clone the topic name, Partitions, and each partition's + // inner slices so the cache owns fully independent state. The + // broker response is shared with whoever consumed it: + // fetchTopicMetadata sort.Slice's the outer Partitions slice + // in place to validate ordering (issue #1328), and + // cl.Request(MetadataRequest) hands the response back to user + // code that may mutate the inner slices or write through the + // Topic *string. Without these clones, readers via + // RequestCachedMetadata or sharded request paths (which read + // ps[part].Replicas) would race those writers. dupt on the + // GET side clones separately: that isolates returned responses + // from the cache, this isolates the cache from the response. + topicName := *topic.Topic + topic.Topic = &topicName + topic.Partitions = slices.Clone(topic.Partitions) + for i := range topic.Partitions { + p := &topic.Partitions[i] + p.Replicas = slices.Clone(p.Replicas) + p.ISR = slices.Clone(p.ISR) + p.OfflineReplicas = slices.Clone(p.OfflineReplicas) + } t := cachedMetaTopic{ id: topic.TopicID, t: topic, ps: make(map[int32]kmsg.MetadataResponseTopicPartition), when: when, } - cl.metaCache.topics[*topic.Topic] = t + // A recreated topic comes back under a new ID. Delete the old + // ID's mapping when overwriting the entry, else byID accumulates + // stale IDs forever and resolves IDs that no longer exist. + if old, ok := cl.metaCache.topics[topicName]; ok && old.id != topic.TopicID && old.id != zeroID { + delete(cl.metaCache.byID, old.id) + } + cl.metaCache.topics[topicName] = t for _, partition := range topic.Partitions { t.ps[partition.Partition] = partition } if topic.TopicID != zeroID { - cl.metaCache.byID[topic.TopicID] = *topic.Topic + cl.metaCache.byID[topic.TopicID] = topicName } if results != nil { - results[*t.t.Topic] = t + results[topicName] = t } } @@ -4202,15 +4356,26 @@ func (cl *addPartitionsToTxnSharder) shard(ctx context.Context, kreq kmsg.Reques var issues []issueShard for id, req := range brokerReqs { - if len(req.Transactions) <= 1 || len(req.Transactions) == 1 && !req.Transactions[0].VerifyOnly { + if len(req.Transactions) == 1 && !req.Transactions[0].VerifyOnly { + // Clients must use v3 and below; v4+ requires CLUSTER_ACTION + // authorization because it is the broker-to-broker side of + // KIP-890. issues = append(issues, issueShard{ req: req, pin: &pinReq{pinMax: true, max: 3}, broker: id, }) } else { + // Batched transactions and VerifyOnly only exist in v4+: + // the v3 body has no Transactions array and no VerifyOnly + // field, so serializing this request any lower silently + // drops everything that matters - VerifyOnly in particular + // would turn a verification into a real partition add. Pin + // min 4 so brokers that cannot express the request fail + // loudly with errBrokerTooOld instead. issues = append(issues, issueShard{ req: req, + pin: &pinReq{pinMin: true, min: 4}, broker: id, }) } @@ -4315,10 +4480,11 @@ func (cl *writeTxnMarkersSharder) shard(ctx context.Context, kreq kmsg.Request, } type pidEpochCommit struct { - pid int64 - epoch int16 - commit bool - txnVersion int8 + pid int64 + epoch int16 + commit bool + coordinatorEpoch int32 + txnVersion int8 } brokerReqs := make(map[int32]map[pidEpochCommit]map[string][]int32) @@ -4356,6 +4522,7 @@ func (cl *writeTxnMarkersSharder) shard(ctx context.Context, kreq kmsg.Request, marker.ProducerID, marker.ProducerEpoch, marker.Committed, + marker.CoordinatorEpoch, marker.TransactionVersion, } for _, topic := range marker.Topics { @@ -4392,6 +4559,7 @@ func (cl *writeTxnMarkersSharder) shard(ctx context.Context, kreq kmsg.Request, rm.ProducerID = pec.pid rm.ProducerEpoch = pec.epoch rm.Committed = pec.commit + rm.CoordinatorEpoch = pec.coordinatorEpoch rm.TransactionVersion = pec.txnVersion for topic, parts := range topics { rt := kmsg.NewWriteTxnMarkersRequestMarkerTopic() @@ -4414,6 +4582,7 @@ func (cl *writeTxnMarkersSharder) shard(ctx context.Context, kreq kmsg.Request, rm.ProducerID = pec.pid rm.ProducerEpoch = pec.epoch rm.Committed = pec.commit + rm.CoordinatorEpoch = pec.coordinatorEpoch rm.TransactionVersion = pec.txnVersion for topic, parts := range topics { rt := kmsg.NewWriteTxnMarkersRequestMarkerTopic() @@ -5450,7 +5619,7 @@ func (cl *describeShareGroupOffsetsSharder) shard(ctx context.Context, kreq kmsg for _, g := range req.Groups { groupIDs = append(groupIDs, g.GroupID) } - coordinators := cl.loadCoordinators(ctx, coordinatorTypeShare, groupIDs...) + coordinators := cl.loadCoordinators(ctx, coordinatorTypeGroup, groupIDs...) type unkerr struct { err error groupID string @@ -5510,7 +5679,7 @@ func (cl *describeShareGroupOffsetsSharder) onResp(_ kmsg.Request, kresp kmsg.Re for i := range resp.Groups { group := &resp.Groups[i] err := kerr.ErrorForCode(group.ErrorCode) - cl.maybeDeleteStaleCoordinator(group.GroupID, coordinatorTypeShare, err) + cl.maybeDeleteStaleCoordinator(group.GroupID, coordinatorTypeGroup, err) onRespShardErr(&retErr, err) } return retErr diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/compression.go b/vendor/github.com/twmb/franz-go/pkg/kgo/compression.go index ff114664a9b..216939bd8c7 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/compression.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/compression.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "errors" "io" + "math" "runtime" "slices" "sync" @@ -17,6 +18,24 @@ import ( var byteBuffers = sync.Pool{New: func() any { return bytes.NewBuffer(make([]byte, 8<<10)) }} +// maxDecompressedSize caps how much one batch may decompress to. Fetch +// limits bound only the COMPRESSED bytes on the wire; nothing in the +// protocol bounds the decompressed size, and the whole batch is +// materialized contiguously while decompressing. Without a cap, a few-KB +// malicious or corrupt batch can demand tens of GiB: zstd frames declare a +// content size that is honored up to the decoder's configured limit (the +// library default is 64 GiB), gzip expands up to ~1032x, lz4 up to ~255x, +// and snappy headers claim up to 4 GiB. No legitimate batch can exceed +// math.MaxInt32 decompressed: every known producer serializes a batch's +// records into an int32-indexed buffer before compressing (this client's +// own appendTo, Java's MemoryRecordsBuilder over a ByteBuffer, librdkafka), +// so a batch claiming more is corrupt or hostile and is rejected like any +// other corrupt batch: a loud, repeated fetch error with no offset advance. +// A var only so tests can shrink it. +var maxDecompressedSize = int64(math.MaxInt32) + +var errDecompressedTooLarge = errors.New("decompressed data exceeds the maximum allowed decompressed batch size (corrupt or malicious batch)") + // CompressionCodecType is a bitfield specifying a Kafka-defined compression // codec. Per spec, only four compression codecs are supported. However, if // you control both the producer and consumer, you can technically override the @@ -35,8 +54,9 @@ const ( // CodecZstd is a compression codec signifying zstd compression. CodecZstd - // CodecError is returned from compressing or decompressing if an error - // occurred. + // CodecError is returned as the used-codec from Compress if an error + // occurred while compressing (Decompress reports errors via its error + // return instead). CodecError = -1 ) @@ -176,7 +196,7 @@ out: case CodecGzip: level := gzip.DefaultCompression if codec.level != 0 { - if _, err := gzip.NewWriterLevel(nil, codec.level); err != nil { + if _, err := gzip.NewWriterLevel(nil, codec.level); err == nil { level = codec.level } } @@ -322,6 +342,7 @@ func DefaultDecompressor(pools ...Pool) Decompressor { zstdDec, _ := zstd.NewReader(nil, zstd.WithDecoderLowmem(true), zstd.WithDecoderConcurrency(1), + zstd.WithDecoderMaxMemory(uint64(maxDecompressedSize)), ) r := &zstdDecoder{zstdDec} runtime.SetFinalizer(r, func(r *zstdDecoder) { @@ -352,7 +373,12 @@ func (d *decompressor) Decompress(src []byte, codecType CompressionCodecType) ([ d.pools.each(func(p Pool) bool { if pdecompressBytes, ok := p.(PoolDecompressBytes); ok { s := pdecompressBytes.GetDecompressBytes(src, codecType) - out = bytes.NewBuffer(s) + // Only the slice's capacity is used: decompressed data + // must start at index 0, while a buffer initialized with + // len(s) > 0 (a pool returning make([]byte, sizeGuess)) + // would have the copy/append based codecs write AFTER the + // existing length, prefixing the output with stale bytes. + out = bytes.NewBuffer(s[:0]) rfn = out.Bytes userPooled = true return true @@ -382,13 +408,30 @@ func (d *decompressor) Decompress(src []byte, codecType CompressionCodecType) ([ if err := ungz.Reset(bytes.NewReader(src)); err != nil { return nil, err } - if _, err := io.Copy(out, ungz); err != nil { + if n, err := io.Copy(out, io.LimitReader(ungz, maxDecompressedSize+1)); err != nil { return nil, err + } else if n > maxDecompressedSize { + return nil, errDecompressedTooLarge } return rfn(), nil case CodecSnappy: if len(src) > 16 && bytes.HasPrefix(src, xerialPfx) { - return xerialDecode(src) + // Decode into the pooled destination when one exists; + // this path previously ignored the pool's Get entirely + // (fresh allocation every batch, and the Get'd slice was + // orphaned: never used, never put back). + var xdst []byte + if userPooled { + xdst = out.Bytes() + } + return xerialDecode(xdst, src) + } + // The decoded length is read from the header and allocated up + // front; check the claim before decoding. + if l, err := s2.DecodedLen(src); err != nil { + return nil, err + } else if int64(l) > maxDecompressedSize { + return nil, errDecompressedTooLarge } decoded, err := s2.Decode(out.Bytes(), src) if err != nil { @@ -402,8 +445,10 @@ func (d *decompressor) Decompress(src []byte, codecType CompressionCodecType) ([ unlz4 := d.unlz4Pool.Get().(*lz4.Reader) defer d.unlz4Pool.Put(unlz4) unlz4.Reset(bytes.NewReader(src)) - if _, err := io.Copy(out, unlz4); err != nil { + if n, err := io.Copy(out, io.LimitReader(unlz4, maxDecompressedSize+1)); err != nil { return nil, err + } else if n > maxDecompressedSize { + return nil, errDecompressedTooLarge } return rfn(), nil case CodecZstd: @@ -426,13 +471,15 @@ var xerialPfx = []byte{130, 83, 78, 65, 80, 80, 89, 0} var errMalformedXerial = errors.New("malformed xerial framing") -func xerialDecode(src []byte) ([]byte, error) { +// xerialDecode appends the decoded chunks to dst (commonly a len-0 pooled +// slice, or nil) and returns the result. +func xerialDecode(dst, src []byte) ([]byte, error) { // bytes 0-8: xerial header // bytes 8-16: xerial version // everything after: uint32 chunk size, snappy chunk // we come into this function knowing src is at least 16 src = src[16:] - var dst, chunk []byte + var chunk []byte var err error for len(src) > 0 { if len(src) < 4 { @@ -443,6 +490,13 @@ func xerialDecode(src []byte) ([]byte, error) { if size < 0 || len(src) < int(size) { return nil, errMalformedXerial } + // Chunks accumulate; bound the cumulative claimed output before + // decoding each chunk. + if l, err := s2.DecodedLen(src[:size]); err != nil { + return nil, err + } else if int64(l) > maxDecompressedSize-int64(len(dst)) { + return nil, errDecompressedTooLarge + } if chunk, err = s2.Decode(chunk[:cap(chunk)], src[:size]); err != nil { return nil, err } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/config.go b/vendor/github.com/twmb/franz-go/pkg/kgo/config.go index ee361a1c05f..72d5d82ae1a 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/config.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/config.go @@ -286,6 +286,18 @@ func (cfg *cfg) validate() error { i64lt := func(l, r int64) (bool, string) { return l < r, "less" } i64gt := func(l, r int64) (bool, string) { return l > r, "larger" } + + // Several Durations are serialized to int32-millisecond wire fields + // (JoinGroup SessionTimeoutMs / RebalanceTimeoutMs, ProduceRequest + // TimeoutMs, InitProducerId TransactionTimeoutMs). A Duration whose + // millisecond value exceeds an int32 silently overflows that field when + // cast - e.g. a 30 day session timeout wraps to a negative wire value, + // and a ~50 day one wraps to a small positive value the broker quietly + // accepts as a completely different timeout. Java cannot hit this because + // its equivalent configs are int32-millisecond typed at the source; kgo + // takes a Duration, so the bound must be enforced here. The wire field's + // capacity is the only principled cap. + const maxWireTimeout = time.Duration(math.MaxInt32) * time.Millisecond for _, limit := range []struct { name string v int64 @@ -343,6 +355,11 @@ func (cfg *cfg) validate() error { {name: "max buffered bytes", v: cfg.maxBufferedBytes, allowed: 0, badcmp: i64lt}, {name: "linger", v: int64(cfg.linger), allowed: int64(time.Minute), badcmp: i64gt, durs: true}, {name: "produce timeout", v: int64(cfg.produceTimeout), allowed: int64(100 * time.Millisecond), badcmp: i64lt, durs: true}, + {name: "produce timeout", v: int64(cfg.produceTimeout), allowed: int64(maxWireTimeout), badcmp: i64gt, durs: true}, + + // The transaction timeout is serialized to an int32-millisecond wire + // field and is otherwise unvalidated; bound it so it cannot overflow. + {name: "transaction timeout", v: int64(cfg.txnTimeout), allowed: int64(maxWireTimeout), badcmp: i64gt, durs: true}, {name: "record timeout", v: int64(cfg.recordTimeout), allowed: int64(time.Second), badcmp: func(l, r int64) (bool, string) { if l == 0 { return false, "" // we print nothing when things are good @@ -360,10 +377,12 @@ func (cfg *cfg) validate() error { {name: "consumer protocol length", v: int64(len(cfg.protocol)), allowed: 1, badcmp: i64lt}, {name: "session timeout", v: int64(cfg.sessionTimeout), allowed: int64(100 * time.Millisecond), badcmp: i64lt, durs: true}, + {name: "session timeout", v: int64(cfg.sessionTimeout), allowed: int64(maxWireTimeout), badcmp: i64gt, durs: true}, {name: "rebalance timeout", v: int64(cfg.rebalanceTimeout), allowed: int64(100 * time.Millisecond), badcmp: i64lt, durs: true}, + {name: "rebalance timeout", v: int64(cfg.rebalanceTimeout), allowed: int64(maxWireTimeout), badcmp: i64gt, durs: true}, {name: "autocommit interval", v: int64(cfg.autocommitInterval), allowed: int64(100 * time.Millisecond), badcmp: i64lt, durs: true}, - {v: int64(cfg.heartbeatInterval), allowed: int64(cfg.rebalanceTimeout) * int64(time.Millisecond), badcmp: i64gt, durs: true, fmt: "heartbeat interval %v is erroneously larger than the session timeout %v"}, + {v: int64(cfg.heartbeatInterval), allowed: int64(cfg.sessionTimeout), badcmp: i64gt, durs: true, fmt: "heartbeat interval %v is erroneously larger than the session timeout %v"}, } { bad, cmp := limit.badcmp(limit.v, limit.allowed) if bad { @@ -443,6 +462,40 @@ func (cfg *cfg) validate() error { return errors.New("invalid use of ConsumeExcludeTopics when not using ConsumeRegex") } + // A topic literally named "" cannot exist; consuming it would spin on + // UNKNOWN_TOPIC metadata forever with no surfaced error. In regex mode the + // ConsumeTopics values are patterns ("" is a valid match-all regex), so we + // only reject empty names when not consuming via regex. + if !cfg.regex { + for topic := range cfg.topics { + if topic == "" { + return errors.New("invalid empty topic name in ConsumeTopics") + } + } + } + for topic, partitions := range cfg.partitions { + if topic == "" { + return errors.New("invalid empty topic name in ConsumePartitions") + } + for p := range partitions { + if p < 0 { + return fmt.Errorf("invalid negative partition %d for topic %q in ConsumePartitions", p, topic) + } + } + } + + // These options take a value; if explicitly set to "" it is a mistake (an + // empty transactional or instance ID is not valid). Both are *string so an + // explicit "" is distinguishable from unset (nil). ConsumerGroup and + // ShareGroup are plain strings, indistinguishable from unset, so they are + // not checked here. + if cfg.txnID != nil && *cfg.txnID == "" { + return errors.New("invalid empty TransactionalID") + } + if cfg.instanceID != nil && *cfg.instanceID == "" { + return errors.New("invalid empty InstanceID") + } + if cfg.topics != nil && cfg.partitions != nil { for topic := range cfg.partitions { if _, exists := cfg.topics[topic]; exists { @@ -686,6 +739,12 @@ func WithLogger(l Logger) Opt { // WithContext sets the client to use a custom context. // // By default, the client uses context.Background. +// +// Canceling this context stops the client's background goroutines and fails +// in-flight requests with ErrClientClosed, but it does not replace Close: +// records still buffered for producing are reliably failed only by Close, and +// a group leave is sent only by Close. Always call Close for a clean shutdown; +// canceling this context first (to interrupt blocking calls) is fine. func WithContext(ctx context.Context) Opt { return clientOpt{func(cfg *cfg) { cfg.ctx = ctx }} } @@ -813,7 +872,7 @@ func MinVersions(versions *kversion.Versions) Opt { // RetryBackoffFn sets the backoff strategy for how long to backoff for a given // amount of retries, overriding the default jittery exponential backoff that -// ranges from 250ms min to 2.5s max. +// ranges from 250ms min to 5s max. // // This (roughly) corresponds to Kafka's retry.backoff.ms setting and // retry.backoff.max.ms (which is being introduced with KIP-500). @@ -1296,16 +1355,18 @@ func RecordRetries(n int) ProducerOpt { } // UnknownTopicRetries sets the number of times a record can fail with -// UNKNOWN_TOPIC_OR_PARTITION, overriding the default 4. +// UNKNOWN_TOPIC_OR_PARTITION or UNKNOWN_TOPIC_ID, overriding the default 4. // // This is a separate limit from RecordRetries because unknown topic or // partition errors should only happen if the topic does not exist. It is // pointless for the client to continue producing to a topic that does not // exist, and if we repeatedly see that the topic does not exist across // multiple metadata queries (which are going to different brokers), then we -// may as well stop trying and fail the records. +// may as well stop trying and fail the records. The count is reset whenever +// a produce to the partition succeeds; errors other than the two unknown +// topic errors leave it unchanged. // -// If this is -1, the client never fails records with this error. +// If this is -1, the client never fails records with these errors. func UnknownTopicRetries(n int) ProducerOpt { return producerOpt{func(cfg *cfg) { cfg.maxUnknownFailures = int64(n) }} } @@ -1409,9 +1470,9 @@ func TransactionalID(id string) ProducerOpt { // default 40s. It is a good idea to keep this less than a group's session // timeout, so that a group member will always be alive for the duration of a // transaction even if connectivity dies. This helps prevent a transaction -// finishing after a rebalance, which is problematic pre-Kafka 2.5. If you -// are on Kafka 2.5+, then you can use the RequireStableFetchOffsets option -// when assigning the group, and you can set this to whatever you would like. +// finishing after a rebalance, which is problematic pre-Kafka 2.5. On Kafka +// 2.5+, the client always requires stable fetch offsets (KIP-447), so you +// can set this to whatever you would like. // // Transaction timeouts begin when the first record is produced within a // transaction, not when a transaction begins. @@ -1877,9 +1938,9 @@ func Balancers(balancers ...GroupBalancer) GroupOpt { // If you are using a [GroupTransactSession] for EOS, wish to lower this, and are // talking to a Kafka cluster pre 2.5, consider lowering the // TransactionTimeout. If you do not, you risk a transaction finishing after a -// group has rebalanced, which could lead to duplicate processing. If you are -// talking to a Kafka 2.5+ cluster, you can safely use the -// RequireStableFetchOffsets group option and prevent any problems. +// group has rebalanced, which could lead to duplicate processing. On a Kafka +// 2.5+ cluster there is no problem: the client always requires stable fetch +// offsets (KIP-447). // // This option corresponds to Kafka's session.timeout.ms setting and must be // within the broker's group.min.session.timeout.ms and @@ -2002,6 +2063,13 @@ func AdjustFetchOffsetsFn(adjustOffsetsBeforeAssign func(context.Context, map[st // This function can be called at any time you are polling or processing // records. If you want to ensure this function is called serially with // processing, consider the BlockRebalanceOnPoll option. +// +// Do not call Close or LeaveGroup synchronously from within this callback +// (nor from OnPartitionsRevoked or OnPartitionsLost): leaving the group +// waits for the group management loop to finish, and the loop is waiting +// for your callback to return - a permanent deadlock. To leave from within +// a callback, use LeaveGroupContext with a nil context (it triggers the +// leave without waiting), or call LeaveGroup from a separate goroutine. func OnPartitionsAssigned(onAssigned func(context.Context, *Client, map[string][]int32)) GroupOpt { return groupOpt{func(cfg *cfg) { cfg.onAssigned = onAssigned }} } @@ -2034,6 +2102,9 @@ func OnPartitionsAssigned(onAssigned func(context.Context, *Client, map[string][ // // This function is called if a "fatal" group error is encountered and you have // not set [OnPartitionsLost]. See OnPartitionsLost for more details. +// +// Do not call Close or LeaveGroup synchronously from within this callback; +// see the warning on [OnPartitionsAssigned]. func OnPartitionsRevoked(onRevoked func(context.Context, *Client, map[string][]int32)) GroupOpt { return groupOpt{func(cfg *cfg) { cfg.onRevoked = onRevoked }} } @@ -2053,6 +2124,9 @@ func OnPartitionsRevoked(onRevoked func(context.Context, *Client, map[string][]i // This function can be called at any time you are polling or processing // records. If you want to ensure this function is called serially with // processing, consider the BlockRebalanceOnPoll option. +// +// Do not call Close or LeaveGroup synchronously from within this callback; +// see the warning on [OnPartitionsAssigned]. func OnPartitionsLost(onLost func(context.Context, *Client, map[string][]int32)) GroupOpt { return groupOpt{func(cfg *cfg) { cfg.onLost = onLost }} } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer.go b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer.go index b5e5443123e..4970f965741 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer.go @@ -263,7 +263,16 @@ func (c *consumer) unaddPoller() { } c.pollWaitMu.Lock() defer c.pollWaitMu.Unlock() - c.pollWaitState-- + // AllowRebalance zeroes the poller count outright. If the user calls it + // while another goroutine's poll is still in flight (a contract + // violation: AllowRebalance means "all pollers are done"), that poll's + // release lands here after the mask and must not decrement: the low 32 + // bits would underflow and borrow into the rebalance count, permanently + // blocking both polls and rebalances. A poller whose accounting was + // force-cleared simply no-ops its release. + if c.pollWaitState&math.MaxUint32 > 0 { + c.pollWaitState-- + } c.pollWaitC.Broadcast() } @@ -401,7 +410,7 @@ func (c *consumer) addFakeReadyForDraining(topic string, partition int32, err er } // NewErrFetch returns a fake fetch containing a single empty topic with a -// single zero partition with the given error. +// single partition of -1 with the given error. func NewErrFetch(err error) Fetches { return []Fetch{{ Topics: []FetchTopic{{ @@ -420,7 +429,7 @@ func NewErrFetch(err error) Fetches { // equivalent to calling PollRecords(ctx, 0). // // If the client is closed, a fake fetch will be injected that has no topic, a -// partition of 0, and a partition error of ErrClientClosed. If the context is +// partition of -1, and a partition error of ErrClientClosed. If the context is // canceled, a fake fetch will be injected with ctx.Err. These injected errors // can be used to break out of a poll loop. // @@ -816,7 +825,12 @@ func (c *consumer) purgeTopics(topics []string) { delete(c.g.using, topic) delete(c.g.reSeen, topic) } - c.g.rejoin("rejoin from PurgeFetchTopics") + // Our subscription shrank; reconcile per protocol. This MUST NOT + // feed rejoinCh in 848 mode (signalSubscriptionChange forces a + // heartbeat instead): a rejoinCh bounce there runs the session-end + // revoke's nowAssigned read-modify-write concurrently with live + // heartbeats, losing a heartbeat's nowAssigned store. + c.g.signalSubscriptionChange("topics purged from consuming") } else { c.assignPartitions(purgeAssignments, assignPurgeMatching, c.d.tps, fmt.Sprintf("purge of %v requested", topics)) for _, topic := range topics { @@ -838,7 +852,7 @@ func (c *consumer) purgeTopics(topics []string) { // entire topic is purged. func (cl *Client) AddConsumeTopics(topics ...string) { c := &cl.consumer - if len(topics) == 0 || c.g == nil && c.d == nil || cl.cfg.regex { + if len(topics) == 0 || !c.consuming() || cl.cfg.regex { return } @@ -863,7 +877,7 @@ func (cl *Client) AddConsumeTopics(topics ...string) { // GetConsumeTopics retrieves a list of current topics being consumed. func (cl *Client) GetConsumeTopics() []string { c := &cl.consumer - if c.g == nil && c.d == nil { + if !c.consuming() { return nil } var m map[string]*topicPartitions @@ -1045,10 +1059,9 @@ func (f fmtAssignment) String() string { // assignPartitions, called under the consumer's mu, is used to set new cursors // or add to the existing cursors. // -// We do not need to pass tps when we are bumping the session or when we are -// invalidating all. All other cases, we want the tps -- the logic below does -// not fully differentiate needing to start a new session vs. just reusing the -// old (third if case below) +// We do not need to pass tps when we are invalidating all. All other cases, +// we want the tps: guarding the session may create a new session needing it, +// and stopping the session needs it for the restart. func (c *consumer) assignPartitions(assignments map[string]map[int32]Offset, how assignHow, tps *topicsPartitions, why string) { if c.mu.TryLock() { c.mu.Unlock() @@ -1115,6 +1128,23 @@ func (c *consumer) assignPartitions(assignments map[string]map[int32]Offset, how offset: assignPart.at, lastConsumedEpoch: assignPart.epoch, }) + // This partition can have a pending list or epoch + // load: an OffsetOutOfRange reload, or an epoch + // validation from a leader move. The cursor is then + // unusable and the load's completion is its only + // re-enabler -- and that completion would also + // overwrite the offset we just set with the load's + // now-stale result. A transact session resetting to + // committed offsets after an abort would be undone: + // consumption would resume at the pre-abort position, + // never re-consuming the aborted records. The set + // offset is the new truth: drop the load and + // re-enable the cursor ourselves. Safe here because + // the session is stopped (no source can use the + // cursor until the new session starts). + if loadOffsets.removeLoad(usedCursor.topic, usedCursor.partition) { + usedCursor.allowUsable() + } } } } @@ -1140,8 +1170,12 @@ func (c *consumer) assignPartitions(assignments map[string]map[int32]Offset, how case assignInvalidateAll: loadOffsets = listOrEpochLoads{} case assignSetMatching: - // We had not yet loaded this partition, so there is - // nothing to set, and we keep everything. + // Loads for partitions that were being consumed were + // handled in the cursor walk above (offset set directly, + // pending load dropped). Anything remaining is a load for + // a partition that never finished loading; SetOffsets + // documents those are skipped, so we keep their loads + // untouched. case assignInvalidateMatching: loadOffsets.keepFilter(func(t string, p int32) bool { if assignTopic, ok := assignments[t]; ok { @@ -1466,7 +1500,7 @@ func (l *listOrEpochLoads) addLoad(t string, p int32, loadType listOrEpochLoadTy ps[p] = load } -func (l *listOrEpochLoads) removeLoad(t string, p int32) { +func (l *listOrEpochLoads) removeLoad(t string, p int32) (removed bool) { for _, m := range []offsetLoadMap{ l.List, l.Epoch, @@ -1478,11 +1512,16 @@ func (l *listOrEpochLoads) removeLoad(t string, p int32) { if ps == nil { continue } + if _, exists := ps[p]; !exists { + continue + } delete(ps, p) + removed = true if len(ps) == 0 { delete(m, t) } } + return removed } func (l listOrEpochLoads) each(fn func(string, int32)) { @@ -1679,7 +1718,14 @@ func (fm *fetchManager) manageFetchConcurrency() { continue } - if wantQuit && activeFetches == 0 { + // We cannot return while sources are still registered in + // wantFetch: each of them is (or is about to be) blocked + // sending on cancelFetchCh, which only we drain. Returning + // early orphans those sends once the channel's small buffer + // fills; the sources then hold session workers forever and + // stopSession never finishes (consumer deadlock). Keep + // looping until every registered source has canceled. + if wantQuit && activeFetches == 0 && len(wantFetch) == 0 { return } } @@ -1937,6 +1983,19 @@ func (s *consumerSession) listOrEpoch(waiting listOrEpochLoads, immediate bool, } } + // If the session is dying, park: the loads were stored in waiting above, + // and stopSession returns waiting loads to the caller for the next + // session. Without this check, a dying session whose metadata is fresh + // busy-loops until metadataMinAge elapses: wait is false above, so we + // would issue requests on the dead context, every one fails instantly, + // the reload timer below is canceled by the same dead context, and its + // loadWithSession re-enters this function - burning CPU and holding the + // session-stop (every revoke, leave, close, or seek) for the full + // metadataMinAge. + if s.ctx.Err() != nil { + return + } + s.listOrEpochMu.Lock() loading := s.listOrEpochLoadsWaiting s.listOrEpochLoadsLoading.mergeFrom(loading) @@ -2395,8 +2454,23 @@ func (cl *Client) listOffsetsForBrokerLoad(ctx context.Context, broker *broker, offset = start } } + // Every arm above yields a non-negative offset from a + // well-behaved broker: by-time listings exist only for + // afterMilli, whose -1 is replaced by the end listing, + // and the start/end/exact arms bound within the + // responses. A negative offset here means the broker + // violated the protocol; clamping to 0 (the old + // behavior) would silently re-consume the partition + // from the start. Surface the misbehavior and retry + // the load instead. if offset < 0 { - offset = 0 // sanity + loaded.add(loadedOffset{ + topic: topic, + partition: partition, + err: errNegativeListedOffset, + request: loadPart, + }) + continue } loaded.add(loadedOffset{ @@ -2422,10 +2496,14 @@ func (*Client) loadEpochsForBrokerLoad(ctx context.Context, broker *broker, load return } - // If the version is < 2, we are speaking to an old broker. We should - // not have an old version, but we could have spoken to a new broker - // first then an old broker in the middle of a broker roll. For now, we - // will just loop retrying until the broker is upgraded. + // If the negotiated version is < 2, we are speaking to an old broker: + // possible mid-roll when metadata (with leader epochs) came from an + // upgraded broker while the partition leader is not yet upgraded. The + // request then goes out without CurrentLeaderEpoch fencing, and a v0 + // response carries no LeaderEpoch (kmsg defaults it to -1). Validation + // still compares EndOffset and completes, just unfenced and without + // epoch information - a degraded but correct fallback for a window + // that only exists rolling from pre-KIP-320 brokers. topics := tps.load() resp := kresp.(*kmsg.OffsetForLeaderEpochResponse) @@ -2469,7 +2547,27 @@ func (*Client) loadEpochsForBrokerLoad(ctx context.Context, broker *broker, load // validating. offset := loadPart.at var err error - if rPartition.EndOffset < offset { + switch { + case rPartition.EndOffset < 0: + // KIP-320 UNDEFINED_EPOCH_OFFSET: a conformant broker + // answers endOffset -1 (and leaderEpoch -1) when its + // leader-epoch cache holds no record of the requested + // epoch - an empty or freshly-truncated cache, an unclean + // election to a replica with no epoch history, or an epoch + // newer than anything in the log. This is NOT data loss; the + // broker simply cannot tell us a truncation point. The old + // `EndOffset < offset` arm treated the -1 sentinel as + // "truncated to offset -1", surfacing a spurious ErrDataLoss + // and pinning the cursor at -1. Instead carry the sentinel + // through so the next fetch hits OFFSET_OUT_OF_RANGE and + // resets via the configured ConsumeResetOffset (or, under + // NoResetOffset, surfaces OOOR rather than a bogus data-loss + // error) - the same reset path the cursor already took, + // minus the false alarm. Matches the Java client, which + // resets per policy on this sentinel rather than comparing + // -1 against the validating position. + offset = rPartition.EndOffset + case rPartition.EndOffset < offset: err = &ErrDataLoss{topic, partition, offset, loadPart.epoch, rPartition.EndOffset, rPartition.LeaderEpoch} offset = rPartition.EndOffset } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group.go b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group.go index 7ccc5d195e6..04fa0f07f0a 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group.go @@ -153,10 +153,17 @@ type groupConsumer struct { // done, and then starts its own. commitDone chan struct{} - // blockAuto is set and cleared in CommitOffsets{,Sync} to block - // autocommitting if autocommitting is active. This ensures that an - // autocommit does not cancel the user's manual commit. - blockAuto bool + // blockAuto counts outstanding CommitOffsets{,Sync} commits and + // blocks autocommitting while any are in flight. This ensures that + // an autocommit does not trample a user's manual commit: the + // autocommit snapshot is taken when the commit is enqueued, but the + // request is issued only after all prior commits complete, so a + // snapshot taken while a higher manual commit is in flight would be + // committed after it and rewind the broker's offset. This must be a + // count, not a bool: with two overlapping async commits, the first + // completion would otherwise re-enable autocommit while the second + // is still in flight, reopening exactly that window. + blockAuto int // We set this once to manage the group lifecycle once. // If we detect we should run in 848 mode, we set is848 true. @@ -237,6 +244,12 @@ func (cl *Client) LeaveGroup() { // group. If you have configured the group with an InstanceID, this // does not leave the group. // +// For next-gen (KIP-848) consumer groups, the leave is a final +// heartbeat with MemberEpoch -1; with an InstanceID configured the +// epoch is -2 instead, a temporary "static" departure where the +// member's partitions stay reserved until the session timeout or +// until a replacement with the same InstanceID rejoins. +// // For share groups: this drains any pending acks, releases records that // were acquired but never finalized, closes each per-broker share // session, and sends the final ShareGroupHeartbeat with MemberEpoch=-1 @@ -250,6 +263,13 @@ func (cl *Client) LeaveGroup() { // failed with an internal "consumer left" error). // // LeaveGroupContext is a no-op for direct (non-group) consumers. +// +// Do not call this function with a non-nil context synchronously from +// within an OnPartitions callback: the leave waits for the group +// management loop to finish, and the loop is waiting for your callback to +// return. With the client's own context (LeaveGroup), that is a permanent +// deadlock. A nil context is safe anywhere: it triggers the leave and +// returns immediately. func (cl *Client) LeaveGroupContext(ctx context.Context) error { c := &cl.consumer if c.g == nil && c.s == nil { @@ -465,7 +485,7 @@ func (g *groupConsumer) manageFailWait(consecutiveErrors int, err error) (ctxCan g.resetExternal() } - // Unblock bolling now that we have called onLost and + // Unblock polling now that we have called onLost and // re-assigned. g.c.unaddRebalance() @@ -811,7 +831,25 @@ func (g *groupConsumer) revoke(stage revokeStage, lost map[string][]int32, leavi } if stage != revokeThisSession { // cooperative consumers rejoin after revoking what they lost - defer g.rejoin("after revoking what we lost from a rebalance") + // The rejoin triggers the second join of the classic + // cooperative two-phase rebalance: after giving up lost + // partitions, the member rejoins so the group can reassign + // them. 848 has no second join, the server reconciles + // through heartbeats. There, this signal would only tear + // down and rebuild the heartbeat session: the session that + // called us already handled both our lost and added + // partitions, so the rebuilt session re-enters with an empty + // diff, and because rebuilding re-arms the heartbeat timer + // at a full interval, the bounce also DELAYS the heartbeat + // that acks our revocation to the server. For 848, prerevoke + // instead forces an immediate heartbeat to ack the + // revocation. + g.mu.Lock() + is848 := g.is848 + g.mu.Unlock() + if !is848 { + defer g.rejoin("after revoking what we lost from a rebalance") + } } // The block below deletes everything lost from our uncommitted map. @@ -863,6 +901,7 @@ func (s *assignRevokeSession) prerevoke(g *groupConsumer, lost map[string][]int3 // very first concurrent heartbeat sends keepalive. g.mu.Lock() g848 := g.g848 + is848 := g.is848 // g848 stays non-nil after a fallback to classic; is848 is what tracks the protocol g.mu.Unlock() if g848 != nil { g848.prerevoking.Store(true) @@ -877,6 +916,40 @@ func (s *assignRevokeSession) prerevoke(g *groupConsumer, lost map[string][]int3 if g848 != nil { g848.prerevoking.Store(false) } + // If we revoked, ack the revocation to the server right away + // rather than waiting out the heartbeat timer: the server + // cannot give the revoked partitions to other members until + // it sees a heartbeat without them, so an immediate full + // heartbeat (prerevoking was cleared above, so it will not + // be a keepalive) directly speeds group-wide reconciliation. + // The Java client acks the same way the moment revocation + // callbacks complete. + // + // The send must be best effort, NOT blocking. If the + // heartbeat loop exits on a fatal error before consuming our + // send (its first heartbeat can fail while we are still + // revoking), nothing reads heartbeatForceCh again until the + // next session begins, but the next session cannot begin + // until we return: setupAssignedAndHeartbeat waits on + // assignDone, which waits on prerevokeDone, which closes + // only when this goroutine exits. A blocking send would + // deadlock the manage loop. If the send is missed (loop + // mid-heartbeat or already gone), the regular heartbeat + // timer acks within one interval, which is no worse than + // what the session bounce this replaced provided. + // + // We force even when nothing was lost: a session (re)entry + // with only added partitions also owes the server an ack - + // the next full heartbeat's Topics is what reports the new + // assignment as owned. The Java client likewise heartbeats + // the moment reconciliation completes rather than waiting + // out the interval. + if is848 { + select { + case g.heartbeatForceCh <- func(error) {}: + default: + } + } }() return s.prerevokeDone } @@ -1076,6 +1149,7 @@ func (g *groupConsumer) heartbeat(initialHb time.Duration, fetchErrCh <-chan err for { var err error var force func(error) + var fetchErr bool heartbeat = false select { case <-cooperativeFastCheck: @@ -1091,6 +1165,7 @@ func (g *groupConsumer) heartbeat(initialHb time.Duration, fetchErrCh <-chan err err = kerr.RebalanceInProgress case err = <-fetchErrCh: fetchErrCh = nil + fetchErr = true case <-revoked: revoked = nil didRevoke = true @@ -1147,7 +1222,22 @@ func (g *groupConsumer) heartbeat(initialHb time.Duration, fetchErrCh <-chan err // If cfg.retries consecutive failures occur without any // success, the error propagates to manage848 which // rebuilds the session. - if is848 && (isRetryableBrokerErr(err) || isAnyDialErr(err) || g.cl.maybeDeleteStaleCoordinator(g.cfg.group, coordinatorTypeGroup, err)) { + // + // This arm must only see errors from the heartbeat itself, + // never from fetchErrCh, even though both feed the same err + // variable. Walkthrough of what would go wrong: the + // coordinator moves, OffsetFetch exhausts its internal + // retries, fetchOffsets returns the retryable error here, we + // "retry" by heartbeating in place, the next heartbeat + // succeeds and resets the counter - and the session lives on + // with partitions that were never handed to assignPartitions + // (that only happens after a successful fetch). The fetch + // goroutine is already gone and nothing inside a live session + // re-runs it, so those partitions silently never consume. + // Only re-entering setupAssignedAndHeartbeat re-fetches (via + // g.fetching), so a fetch error must propagate to manage848, + // whose transient arm restarts the session. + if is848 && !fetchErr && (isRetryableBrokerErr(err) || isAnyDialErr(err) || g.cl.maybeDeleteStaleCoordinator(g.cfg.group, coordinatorTypeGroup, err)) { if int64(hbBrokerRetries) < g.cfg.retries { hbBrokerRetries++ backoff := g.cfg.retryBackoff(hbBrokerRetries) @@ -1234,9 +1324,23 @@ func (g *groupConsumer) heartbeat(initialHb time.Duration, fetchErrCh <-chan err // If neither of the cases above are true (this member is not a leader, and the // join group metadata has not changed), then Kafka will not actually trigger a // rebalance and will instead reply to the member with its current assignment. +// +// For next-gen (KIP-848) consumer groups, assignment is entirely server +// driven and there is no client-side join to redo: this instead forces an +// immediate full heartbeat (best effort), which re-syncs the subscription +// and assignment with the broker. func (cl *Client) ForceRebalance() { if g := cl.consumer.g; g != nil { - g.rejoin("from ForceRebalance") + // Classic rejoins; 848 forces a heartbeat (848 must never feed + // rejoinCh - see signalSubscriptionChange). Routing every + // rejoinCh feeder through the one helper is what keeps "nothing + // feeds rejoinCh in 848 mode" true: every remaining session-end + // path stops heartbeating (or has a dead context) before revoke + // runs, so revoke's nowAssigned read-modify-write never races a + // live heartbeat's store. + g.mu.Lock() + g.signalSubscriptionChange("from ForceRebalance") + g.mu.Unlock() } } @@ -1250,6 +1354,36 @@ func (g *groupConsumer) rejoin(why string) { } } +// signalSubscriptionChange tells the manage loop that our local set of +// subscribed topics changed (AddConsumeTopics growth, PurgeConsumeTopics +// shrink) and a reconcile is owed. The caller must hold g.mu (we read +// g.is848). +// +// Classic and 848 reconcile differently, and routing every caller through +// here is what keeps the difference from being re-derived (and forgotten) +// at each site: +// +// - Classic: bounce the heartbeat session via rejoinCh so the member +// re-joins and the group re-balances with the new subscription. +// - 848: the server reconciles through heartbeats, so feeding rejoinCh +// would only bounce the session pointlessly - AND that bounce runs the +// session-end revoke concurrently with live heartbeats, the one +// interleaving where a completing heartbeat's nowAssigned store is lost +// to revoke's read-modify-write. Instead force an immediate heartbeat +// (best effort, must not block; see the walkthrough in prerevoke): the +// next request rebuilds the subscription from live state, and if the +// force is missed the heartbeat timer sends within one interval. +func (g *groupConsumer) signalSubscriptionChange(why string) { + if g.is848 { + select { + case g.heartbeatForceCh <- func(error) {}: + default: + } + return + } + g.rejoin(why) +} + // Joins and then syncs, issuing the two slow requests in goroutines to allow // for group cancelation to return early. func (g *groupConsumer) joinAndSync(joinWhy string) error { @@ -1571,6 +1705,13 @@ func (g *groupExternal) eachTopic(fn func(string)) { } func (g *groupExternal) updateLatest(meta map[string]*metadataTopic) { + // These are topics the leader balances but does not itself consume, so + // there is no kept-partition floor like the leader's own topics have + // (metadata.go). We rewrite the cached count and trigger a rejoin on + // ANY change, INCLUDING a one-response stale shrink - that is one churn + // cycle (revoke + re-assign) that self-heals on the next refresh. This + // is the same stale-snapshot exposure Java's leader carries; it is + // intentional, not a bug to silence with a shrink filter. g.cloned(func(tps map[string]int32) { var rejoin bool for t, ps := range tps { @@ -1744,6 +1885,16 @@ func (g *groupConsumer) fetchOffsets(ctx context.Context, added map[string][]int // Groups format, and resp.Topics is a copy that may lose TopicID. var staleRetries int var unknownTopicIDRetries int + var omittedRetries int + // injected tracks partitions whose non-retryable error we have already + // surfaced via a fake fetch. It is declared BEFORE the start label so it + // survives the goto-start retries below. addFakeReadyForDraining is not + // idempotent: a non-conformant broker that omits a requested partition + // (driving the omitted retry) or returns a non-retryable partition error + // ordered ahead of an UNSTABLE_OFFSET_COMMIT partition (driving the + // retryable goto-start) would otherwise re-run the injection arm every + // pass and emit a duplicate fake fetch for the same partition each retry. + var injected mtmps start: member, gen := g.memberGen.load() req := kmsg.NewPtrOffsetFetchRequest() @@ -1757,9 +1908,28 @@ start: groupTopics := g.tps.load() pinV9 := false for topic, partitions := range added { + // Skip partitions we have already surfaced a non-retryable error + // for and dropped (injected, below). On the first pass injected is + // nil and nothing is filtered; on a goto-start retry (driven by an + // UNSTABLE_OFFSET_COMMIT or UNKNOWN_TOPIC_ID partition) this avoids + // re-fetching partitions we will never re-add to the assignment. + if inj := injected[topic]; inj != nil { + kept := partitions[:0:0] // fresh backing array; do not mutate added + for _, p := range partitions { + if _, ok := inj[p]; !ok { + kept = append(kept, p) + } + } + partitions = kept + } + if len(partitions) == 0 { + continue + } reqTopic := kmsg.NewOffsetFetchRequestGroupTopic() reqTopic.Topic = topic - reqTopic.TopicID = groupTopics.loadTopic(topic).id + if td := groupTopics.loadTopic(topic); td != nil { + reqTopic.TopicID = td.id + } if reqTopic.TopicID == ([16]byte{}) { pinV9 = true } @@ -1872,7 +2042,18 @@ start: // Some partition errors are retryable: // // - UnstableOffsetCommit (KIP-447): a pending - // transaction should be committing soon. + // transaction should be committing soon. This + // 1s retry is deliberately UNBOUNDED and has no + // counter - the block is protocol-mandated: + // require_stable hides pending txnal offsets + // until the commit marker lands, so a bound + // would convert a mandated wait into a spurious + // error. The worst legal wait is the blocking + // producer's transaction timeout; an adversarial + // producer extending its txn extends the block + // server-side, exactly as it does for Java. Only + // session teardown (ctx below) interrupts it. + // Do not add a retry cap. // // - UnknownTopicID: the broker has not yet // propagated the topic ID for a newly created @@ -1915,6 +2096,15 @@ start: // Instead we surface the error to the user via a // fake fetch and drop the partition from this // assignment; the rest of the session proceeds. + // + // Surface each partition's error exactly once across + // the goto-start retries: injected persists (declared + // before the start label), so a partition already + // surfaced on an earlier pass is skipped here rather + // than re-injected. + if _, ok := injected[topic][rPartition.Partition]; ok { + continue + } g.cfg.logger.Log(LogLevelError, "fetch offsets failed for partition; injecting error and continuing with remaining partitions", "group", g.cfg.group, "topic", topic, @@ -1922,6 +2112,7 @@ start: "err", err, ) g.c.addFakeReadyForDraining(topic, rPartition.Partition, err, "fetch offsets returned a non-retryable partition error") + injected.add(topic, rPartition.Partition) continue } offset := Offset{ @@ -1931,7 +2122,12 @@ start: if resp.Version >= 5 && kip320 { // KIP-320 offset.epoch = rPartition.LeaderEpoch } - if rPartition.Offset == -1 { + // The coordinator's "no committed offset" sentinel is -1. + // We treat ANY negative offset as no-commit, matching the + // Java client's `offset >= 0` test: a buggy broker's -5 + // must not flow into partition assignment as a literal + // negative offset. + if rPartition.Offset < 0 { offset = g.cfg.startOffset } topicOffsets[rPartition.Partition] = offset @@ -1969,6 +2165,64 @@ start: } } + // The dual of the validation above: every partition we requested must + // be present in the response. The group coordinator answers every + // requested partition (filling -1 for those with no commit), so an + // omission is a buggy/hostile broker - as is a duplicated topic entry, + // which overwrites and discards the earlier entry's partitions in the + // response loop above. A partition silently absent from `offsets` is + // never assigned a cursor, and a successful return here clears + // g.fetching: nothing inside a live session ever re-fetches it, so for + // cooperative and 848 sessions (whose unchanged assignment diffs to an + // empty "added" on the next session) the partition would silently + // never consume. Retry a few times in case the omission is transient, + // then surface a loud error fetch and drop the partition from this + // assignment, exactly like the non-retryable partition error path + // above. + var omitted mtmps + for topic, partitions := range added { + if !groupTopics.hasTopic(topic) { + continue // already warned and skipped above + } + topicOffsets := offsets[topic] + for _, partition := range partitions { + if injected != nil { + if _, ok := injected[topic][partition]; ok { + continue // deliberately dropped, not omitted + } + } + if _, ok := topicOffsets[partition]; !ok { + omitted.add(topic, partition) + } + } + } + if len(omitted) > 0 { + if omittedRetries < 3 { + omittedRetries++ + g.cfg.logger.Log(LogLevelError, "fetch offsets response omitted requested partitions, waiting 1s and retrying", + "group", g.cfg.group, + "omitted", omitted, + "attempt", omittedRetries, + ) + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(time.Second): + goto start + } + } + for topic, partitions := range omitted { + for partition := range partitions { + g.cfg.logger.Log(LogLevelError, "fetch offsets response repeatedly omitted a requested partition; injecting error and continuing with remaining partitions", + "group", g.cfg.group, + "topic", topic, + "partition", partition, + ) + g.c.addFakeReadyForDraining(topic, partition, errOffsetFetchOmitted, "fetch offsets response omitted the partition") + } + } + } + if g.cfg.onFetched != nil { g.onFetchedMu.Lock() err = g.cfg.onFetched(ctx, g.cl, resp) @@ -2112,7 +2366,9 @@ func (g *groupConsumer) findNewAssignments() { } if numNewTopics > 0 { - g.rejoin("rejoining because there are more topics to consume, our interests have changed") + // Our subscription grew; reconcile per protocol (848 forces a + // heartbeat, classic rejoins). See signalSubscriptionChange. + g.signalSubscriptionChange("rejoining because there are more topics to consume, our interests have changed") } else if g.leader.Load() { if len(toChange) > 0 { g.rejoin("rejoining because we are the leader and noticed some topics have new partitions") @@ -2165,6 +2421,18 @@ func (g *groupConsumer) updateUncommitted(fetches Fetches) { // We set the head offset if autocommitting is disabled (because we // only use head / committed in that case), or if we are greedily // autocommitting (so that the latest head is available to autocommit). + // + // Under DEFAULT autocommit (neither disabled nor greedy) we set only + // dirty here, and undirtyUncommitted promotes dirty->head at the START + // of the next poll. This one-poll lag is INTENTIONAL and is what makes + // default autocommit at-least-once: defaultRevoke commits head, so a + // revoke between poll N and N+1 commits none of poll N's records and + // the new owner re-reads them. Committing dirty at revoke instead would + // mark records consumed while the app may still be mid-processing them - + // a loss window. Do not "fix" the duplicate re-read by committing dirty + // on revoke; users wanting eager semantics use AutoCommitGreedy or their + // own OnPartitionsRevoked -> CommitUncommittedOffsets (user decision + // 2026-04-24). setHead := g.cfg.autocommitDisable || g.cfg.autocommitGreedy g.mu.Lock() @@ -2476,7 +2744,7 @@ func (g *groupConsumer) loopCommit() { // offsets. g.noCommitDuringJoinAndSync.RLock() g.mu.Lock() - if !g.blockAuto { + if g.blockAuto == 0 { uncommitted := g.getUncommittedLocked(true, false) if len(uncommitted) == 0 { g.cfg.logger.Log(LogLevelDebug, "skipping autocommit due to no offsets to commit", "group", g.cfg.group) @@ -2878,10 +3146,11 @@ func (cl *Client) commitOffsets(ctx context.Context, offsets map[string]map[int3 return rerr } -// CommitOffsetsSync cancels any active CommitOffsets, begins a commit that -// cannot be canceled, and waits for that commit to complete. This function -// will not return until the commit is done and the onDone callback is -// complete. +// CommitOffsetsSync waits for any active CommitOffsets to complete, begins a +// commit that cannot be canceled by other commits or by rebalancing, and +// waits for that commit to complete. The commit is canceled only if the +// passed context is canceled. This function will not return until the commit +// is done and the onDone callback is complete. // // The purpose of this function is for use in OnPartitionsRevoked or committing // before leaving a group, because you do not want to have a commit issued in @@ -2984,12 +3253,12 @@ func (g *groupConsumer) commitOffsetsSync( g.mu.Lock() defer g.mu.Unlock() - g.blockAuto = true + g.blockAuto++ unblockAuto := func(cl *Client, req *kmsg.OffsetCommitRequest, resp *kmsg.OffsetCommitResponse, err error) { unblockCommits(cl, req, resp, err) g.mu.Lock() defer g.mu.Unlock() - g.blockAuto = false + g.blockAuto-- } g.commit(ctx, uncommitted, unblockAuto) @@ -3013,12 +3282,14 @@ func (g *groupConsumer) commitOffsetsSync( // It is invalid to use this function to commit offsets for a transaction. // // Note that this function ensures absolute ordering of commit requests by -// canceling prior requests and ensuring they are done before executing a new -// one. This means, for absolute control, you can use this function to -// periodically commit async and then issue a final sync commit before quitting -// (this is the behavior of autocommiting and using the default revoke). This -// differs from the Java async commit, which does not retry requests to avoid -// trampling on future commits. +// waiting for any prior in-flight commit to complete before issuing a new +// one. Prior commits are never canceled: canceling kills the connection, +// and the broker could then process a replacement commit issued on a new +// connection before the original. This means, for absolute control, you can +// use this function to periodically commit async and then issue a final sync +// commit before quitting (this is the behavior of autocommiting and using +// the default revoke). This differs from the Java async commit, which does +// not retry requests to avoid trampling on future commits. // // It is highly recommended to check the response's partition's error codes if // the response is non-nil. While unlikely, individual partitions can error. @@ -3065,12 +3336,12 @@ func (cl *Client) CommitOffsets( g.mu.Lock() defer g.mu.Unlock() - g.blockAuto = true + g.blockAuto++ unblockAuto := func(cl *Client, req *kmsg.OffsetCommitRequest, resp *kmsg.OffsetCommitResponse, err error) { unblockJoinSync(cl, req, resp, err) g.mu.Lock() defer g.mu.Unlock() - g.blockAuto = false + g.blockAuto-- } g.commit(ctx, uncommitted, unblockAuto) @@ -3159,16 +3430,7 @@ func (g *groupConsumer) commit( req.Generation = generation req.MemberID = memberID req.InstanceID = g.cfg.instanceID - - if ctx.Done() != nil { - go func() { - select { - case <-ctx.Done(): - commitCancel() - case <-commitCtx.Done(): - } - }() - } + is848 := g.is848 // g.mu is held, per the function comment above go func() { defer close(commitDone) // allow future commits to continue when we are done @@ -3377,8 +3639,18 @@ func (g *groupConsumer) commit( for _, d := range dropped { var rt *kmsg.OffsetCommitResponseTopic for i := range resp.Topics { - if resp.Topics[i].Topic == d.name && resp.Topics[i].TopicID == d.id { - rt = &resp.Topics[i] + // v10+ responses carry only the TopicID (Topic is + // v0-v9 on the wire, so kept topics arrive with an + // empty name); v9 and below carry only the name (and + // pinV9 above guarantees an id-less topic never goes + // out v10+, so a zero d.id implies a v9 response). + // Match whichever side the wire carried; requiring + // both duplicated the topic on v10 and the length + // mismatch then made updateCommitted skip the whole + // response. + t := &resp.Topics[i] + if d.id != ([16]byte{}) && t.TopicID == d.id || t.Topic != "" && t.Topic == d.name { + rt = t break } } @@ -3401,11 +3673,67 @@ func (g *groupConsumer) commit( // original request, not the wire-filtered one. req.Topics = origReqTopics + // If the broker no longer recognizes our member (the session + // expired during a network blip, or the group rebalanced + // without us), every commit from here on fails identically + // while we keep consuming as a zombie, until the heartbeat + // loop sees the same error up to a full heartbeat interval + // later. Rejoin immediately instead; the join itself repairs + // the session (joinAndSync clears the member id and retries + // if the broker rejects the join with UnknownMemberID). + // + // Classic protocol only: in 848 mode, a forced "rejoin" does + // not actually rejoin. The heartbeat loop treats the signal + // as RebalanceInProgress and the manage loop restarts the + // session with the same member id and epoch; only a + // heartbeat error resets the member to epoch 0. Worse, with + // autocommit the restart livelocks: ending a session runs + // the default revoke, which sync-commits uncommitted + // offsets; that commit fails with the same fatal error and + // re-queues the rejoin signal; the restarted session then + // consumes the queued signal before its first heartbeat + // timer can fire, and the cycle repeats forever without a + // single heartbeat reaching the broker. Classic does not + // loop because joinAndSync drains rejoinCh before joining + // and the join re-registers us. For 848 we leave fatal + // member errors to the heartbeat loop, matching the Java + // clients: the classic Java consumer rejoins from the commit + // path, while the next-gen one leaves fencing detection to + // the heartbeat. + if !is848 { + if fatalErr := commitHasFatalMemberError(resp); fatalErr != nil { + g.cfg.logger.Log(LogLevelInfo, "offset commit returned a fatal group member error, triggering rejoin", + "group", g.cfg.group, + "err", fatalErr, + ) + g.rejoin(fmt.Sprintf("offset commit error: %s", fatalErr)) + } + } + g.updateCommitted(req, resp) onDone(g.cl, req, resp, nil) }() } +// commitHasFatalMemberError returns the first per-partition error that +// means the broker no longer recognizes this member's session. The +// broker validates membership before any per-partition handling, so +// these errors arrive on every partition or none. FencedInstanceID is +// deliberately not included: it means another instance with our +// instance id has taken over, and rejoining would fight that instance +// for the group slot rather than repair anything. +func commitHasFatalMemberError(resp *kmsg.OffsetCommitResponse) error { + for i := range resp.Topics { + for _, p := range resp.Topics[i].Partitions { + switch p.ErrorCode { + case kerr.UnknownMemberID.Code, kerr.IllegalGeneration.Code: + return kerr.ErrorForCode(p.ErrorCode) + } + } + } + return nil +} + type reNews struct { added map[string][]string skipped []string diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group_848.go b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group_848.go index 756d45122e7..a6c34f1cc64 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group_848.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_group_848.go @@ -38,6 +38,27 @@ func (g *groupConsumer) should848() bool { return true } +// manage848 drives the KIP-848 heartbeat session: it restarts the session on +// transient errors and re-fetches outstanding partitions via g.fetching. +// +// Constraints any change to coordinator/leader-churn recovery (here, in +// heartbeat, and in fetchOffsets) must preserve — established by the +// rebalance-churn audit: +// +// 1. Heartbeat-originated transport and coordinator errors retry in place +// (the stale-connection cycle 90bcc2bb fixed is real). Fetch errors do +// NOT take that arm — they propagate here so the session restarts and +// re-fetches; do not collapse the two error sources back together. +// 2. Session restart is the designed heal for fetch failures: the g.fetching +// carryover exists precisely so a torn-down session re-fetches. Route +// fixes through it rather than inventing a second retry inside fetchOffsets. +// 3. Member-identity resets are the minimum the error implies: a fresh UUID +// for UnknownMemberID, the SAME UUID for epoch problems (FENCED and STALE +// both keep it). Anything stronger strands server-side state for a full +// session timeout. +// 4. Leaves (MemberEpoch -1/-2) are idempotent and stateless — safe to retry +// anywhere. The CGHB no-retry rule applies only to reconciliation-carrying +// heartbeats, never to leaves. func (g *groupConsumer) manage848() { var serverAssignor string switch g.cfg.balancers[0].(type) { @@ -91,19 +112,28 @@ outer: // Even if Kafka replies that the API is available, if we use it // and the broker is not configured to support it, we receive - // UnsupportedVersion. On the first loop + // UnsupportedVersion. Until a join attempt settles the question + // (any other kerr, or success, means the API is really served), + // an UnsupportedVersion error falls back to classic group + // management. if !known848Support { if err != nil { var ke *kerr.Error if errors.As(err, &ke) { if ke.Code == kerr.UnsupportedVersion.Code { // It's okay to update is848 here. This is used while leaving - // and while heartbeating. We have not yet entered heartbeating, - // and if the user is concurrently leaving, the lack of a memberID - // means both 848 and old group mgmt leaves return early. + // and while heartbeating. We have not yet entered heartbeating. g.mu.Lock() g.is848 = false g.mu.Unlock() + // We pre-stored a self-generated member id (v1 semantics) + // that the server never admitted - the join just failed. + // Clear it so a concurrent leave returns early (there is + // no member to remove; both the 848 and classic leave + // paths check for an empty member id) and so the classic + // join below starts with an empty member id rather than + // burning an UNKNOWN_MEMBER_ID round trip on our UUID. + g.memberGen.store("", -1) g.cfg.logger.Log(LogLevelInfo, "falling back to standard consumer group management due to lack of broker support", "group", g.cfg.group) fallbackToClassic = true go g.manage() @@ -231,7 +261,12 @@ outer: sleep := g.cfg.heartbeatInterval if err == nil { err = errCodeMessage(resp.ErrorCode, resp.ErrorMessage) - sleep = time.Duration(resp.HeartbeatIntervalMillis) * time.Millisecond + // A zero or negative server interval (buggy or + // hostile broker) would hot-loop heartbeats at + // round-trip pace; keep the configured cadence. + if hb := time.Duration(resp.HeartbeatIntervalMillis) * time.Millisecond; hb > 0 { + sleep = hb + } } if err != nil { // Reset last-sent state so the next attempt @@ -268,21 +303,27 @@ outer: isAnyDialErr(err), g.cl.maybeDeleteStaleCoordinator(g.cfg.group, coordinatorTypeGroup, err): consecutiveTransientRestarts++ - if int64(consecutiveTransientRestarts) >= g.cfg.retries && int64(consecutiveTransientRestarts)%g.cfg.retries == 0 { + if shouldNotify848Restart(int64(consecutiveTransientRestarts), g.cfg.retries) { g.c.addFakeReadyForDraining("", 0, &ErrGroupSession{ Err: fmt.Errorf("consumer group %s heartbeat has been failing for %d consecutive attempts, still retrying: %w", g.cfg.group, consecutiveTransientRestarts, err), }, "consumer group heartbeat persistently failing") } err = nil + // Continue directly: we nil err only to keep the + // session loop going, not because anything + // succeeded. Falling into the err == nil reset + // below would zero the counter we just + // incremented, capping it at 1 forever and making + // the every-cfg.retries notification above + // unreachable. The reset is for the other arms, + // whose nil means a processed response. + continue - case errors.Is(err, kerr.UnknownMemberID), - errors.Is(err, kerr.StaleMemberEpoch): - // UnknownMemberID: server forgot us. - // StaleMemberEpoch: our epoch drifted (e.g. a - // heartbeat response was lost). Either way, the - // fix is identical: abandon the assignment and - // re-initialJoin with a fresh member id so the - // server hands us back a current epoch. + case errors.Is(err, kerr.UnknownMemberID): + // The server forgot us (session expired during an + // outage, or we were administratively removed). + // Abandon the assignment and re-initialJoin with a + // fresh member id. member, gen := g.memberGen.load() g.cfg.logger.Log(LogLevelInfo, "consumer group heartbeat error, abandoning assignment and rejoining with new member id", "group", g.cfg.group, @@ -294,7 +335,17 @@ outer: g.memberGen.store(newStringUUID(), 0) continue outer + // StaleMemberEpoch means our epoch drifted from the + // server's; it reaches us via OffsetFetch (the heartbeat + // itself fences with FencedMemberEpoch), so the server + // still has this member. We must KEEP our member id: + // rejoining at epoch 0 with the same id is the protocol's + // lost-response recovery - the server re-admits the member + // in place and re-delivers its assignment. Rejoining with + // a fresh id would strand the old member server-side, + // parking its partitions until the session timeout. case errors.Is(err, kerr.FencedMemberEpoch), + errors.Is(err, kerr.StaleMemberEpoch), errors.Is(err, kerr.GroupMaxSizeReached), errors.Is(err, kerr.UnsupportedAssignor): lvl := LogLevelInfo @@ -332,8 +383,9 @@ outer: } // The errors we have to handle are: - // * UnknownMemberID: abandon partitions, rejoin - // * FencedMemberEpoch: abandon partitions, rejoin + // * UnknownMemberID: abandon partitions, rejoin w/ new member id + // * FencedMemberEpoch / StaleMemberEpoch: abandon partitions, + // rejoin with the SAME member id // * UnreleasedInstanceID: fatal error, do not rejoin // * General error: fatal error, do not rejoin // @@ -353,6 +405,25 @@ outer: } } +// shouldNotify848Restart reports whether a transient-restart count warrants +// surfacing the "heartbeat persistently failing" notification - the only +// user-visible signal that an 848 group is unreachable: once we have +// restarted at least `retries` times, on every `retries`-th restart. +// +// retries <= 0 means the user disabled retries (RequestRetries(0)). That also +// disables in-session heartbeat retries - heartbeat() propagates the first +// transient error immediately rather than retrying in place - so every +// transient error is its own restart and each one warrants the notification. +// We must therefore notify on every restart, NOT divide restarts by zero +// (an integer divide-by-zero panic that would crash the manage goroutine on +// the first transient heartbeat error). +func shouldNotify848Restart(restarts, retries int64) bool { + if retries < 1 { + return true + } + return restarts >= retries && restarts%retries == 0 +} + func (g *groupConsumer) leave848(ctx context.Context) { memberID := g.memberGen.memberID() g.cfg.logger.Log(LogLevelInfo, "leaving next-gen group", @@ -375,7 +446,16 @@ func (g *groupConsumer) leave848(ctx context.Context) { g.leaveErr = err return } - g.leaveErr = errCodeMessage(resp.ErrorCode, resp.ErrorMessage) + err = errCodeMessage(resp.ErrorCode, resp.ErrorMessage) + // The leave rides the coordinator retry wrapper: if a prior attempt + // succeeded but its response was lost (the connection died), the + // retry finds the member already gone. Same if the session expired + // before we could leave. Either way the member is out of the group, + // which is the goal state of leaving, not an error. + if errors.Is(err, kerr.UnknownMemberID) { + err = nil + } + g.leaveErr = err } type g848 struct { @@ -402,6 +482,23 @@ type g848 struct { prerevoking atomic.Bool } +// sanitizePartitions returns the broker-provided partitions sorted, with +// duplicates and negatives dropped. A duplicated partition is not just +// redundant: it survives into nowAssigned, makes the assignment compare as +// changed, and diffAssigned then re-"adds" the partition we already own - +// re-fetching its committed offset and rewinding the live cursor into +// duplicate consumption. Negative numbers can only come from a buggy or +// hostile broker and would otherwise flow into the offset-load machinery. +func sanitizePartitions(ps []int32) []int32 { + ps = slices.Clone(ps) + slices.Sort(ps) + ps = slices.Compact(ps) + for len(ps) > 0 && ps[0] < 0 { + ps = ps[1:] + } + return ps +} + // v1+ requires the end user to generate their own MemberID, with the // recommendation being v4 uuid base64 encoded so it can be put in URLs. We // roughly do that (no version nor variant bits). crypto/rand does not fail @@ -424,7 +521,32 @@ func (g *g848) initialJoin() (time.Duration, error) { g.g.memberGen.storeGeneration(0) g.lastSubscribedTopics = nil g.lastTopics = nil + // A (re)join must carry an EMPTY owned-partitions list: the broker + // rejects any epoch-0 heartbeat whose Topics is non-empty (or null) + // with INVALID_REQUEST, "TopicPartitions must be empty when + // (re-)joining." unresolvedAssigned holds the OLD member's + // server-side assignment, and mkreq folds it into Topics - so + // carrying it across a member reset would poison every join, and + // permanently: the only other thing that clears unresolvedAssigned + // is a successful assignment-carrying response, which a rejected + // join never produces. Dropping it loses nothing - the join + // response always re-delivers the member's full assignment. The + // Java client likewise clears its unresolved-IDs cache on every + // transition to joining. + g.unresolvedAssigned = nil g.prerevoking.Store(false) + // Drain any stale rejoin signal, mirroring joinAndSync. Nothing + // else on the 848 path consumes the channel across a member reset: + // if a signal was queued (e.g. metadata found new matching topics) + // and the heartbeat loop then exited on a fatal error without + // reading it, the signal would survive into the session we are + // about to build and immediately bounce it. The join below already + // carries our current subscription (mkreq reads live state), which + // is everything a queued signal could ask for. + select { + case <-g.g.rejoinCh: + default: + } req := g.mkreq() resp, err := req.RequestWith(g.g.ctx, g.g.cl) if err == nil { @@ -442,10 +564,30 @@ func (g *g848) initialJoin() (time.Duration, error) { "now_assigned", nowAssigned, ) - return time.Duration(resp.HeartbeatIntervalMillis) * time.Millisecond, nil + // As in the heartbeat closure: never adopt a zero/negative server + // interval, it would hot-loop the heartbeat timer. + if hb := time.Duration(resp.HeartbeatIntervalMillis) * time.Millisecond; hb > 0 { + return hb, nil + } + return g.g.cfg.heartbeatInterval, nil } func (g *g848) handleResp(req *kmsg.ConsumerGroupHeartbeatRequest, resp *kmsg.ConsumerGroupHeartbeatResponse) map[string][]int32 { + // A success response can only legitimately carry a negative member + // epoch as the echo of a leave (-1, or -2 static), which this loop + // never sends; the broker rejects requests below -2 outright. If a + // buggy or hostile broker hands us a negative epoch here and we + // store it, our next heartbeat would BE a leave: the member silently + // exits the group while fetches continue. Ignore the response + // entirely, like the Java client does. + if resp.MemberEpoch < 0 { + g.g.cfg.logger.Log(LogLevelWarn, "ignoring consumer group heartbeat response with an invalid negative member epoch", + "group", g.g.cfg.group, + "epoch", resp.MemberEpoch, + ) + return nil + } + id2t := g.g.cl.id2tMap() newAssigned := make(map[string][]int32) @@ -469,16 +611,16 @@ func (g *g848) handleResp(req *kmsg.ConsumerGroupHeartbeatRequest, resp *kmsg.Co // Fresh assignment from server - replace unresolved state. g.unresolvedAssigned = nil for _, t := range resp.Assignment.Topics { + ps := sanitizePartitions(t.Partitions) name := id2t[t.TopicID] if name == "" { if g.unresolvedAssigned == nil { g.unresolvedAssigned = make(map[topicID][]int32) } - g.unresolvedAssigned[topicID(t.TopicID)] = slices.Clone(t.Partitions) + g.unresolvedAssigned[topicID(t.TopicID)] = ps continue } - slices.Sort(t.Partitions) - newAssigned[name] = t.Partitions + newAssigned[name] = ps } } @@ -489,7 +631,6 @@ func (g *g848) handleResp(req *kmsg.ConsumerGroupHeartbeatRequest, resp *kmsg.Co // simpler and only costs one heartbeat interval (~5s). for id, ps := range g.unresolvedAssigned { if name := id2t[[16]byte(id)]; name != "" { - slices.Sort(ps) newAssigned[name] = ps delete(g.unresolvedAssigned, id) } @@ -590,8 +731,17 @@ func (g *g848) mkreq() *kmsg.ConsumerGroupHeartbeatRequest { // the already-resolved topic names from g.tps (which // filterMetadataAllTopics populates with excludes applied). // New topics are picked up on the next metadata refresh. + // + // Skip internal topics: classic regex consuming never uses them + // (findNewAssignments skips isInternal), and the broker honors + // explicit name subscriptions to internal topics, so emulating + // the regex with names would otherwise consume e.g. + // __consumer_offsets whenever the regex matches it. subscribedTopics := make([]string, 0, len(tps)) - for t := range tps { + for t, tp := range tps { + if tp.load().isInternal { + continue + } subscribedTopics = append(subscribedTopics, t) } slices.Sort(subscribedTopics) diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_share.go b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_share.go index f97bf9797a6..f61bb25d05b 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_share.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/consumer_share.go @@ -43,6 +43,15 @@ type ( // names. Owned by the manage goroutine. unresolvedAssigns map[topicID][]int32 + // Whether the last assignPartitions pass skipped an assigned + // partition our metadata does not know yet (the broker assigned + // newly added partitions before our metadata refreshed). We ack + // the member epoch regardless, so the broker never re-sends the + // assignment; while true, handleHeartbeatResp re-returns the + // current assignment so we retry once metadata catches up. Owned + // by the manage goroutine. + pendingAssigns bool + lastSentSubscribedTopics []string lastSentRack bool @@ -80,7 +89,7 @@ type ( mu xsync.Mutex cond *sync.Cond dying bool // single-shot leave guard + incWorker gate - workers int // active goroutines (manage + source loops) + workers int // active goroutines (manage + source loops + in-flight cursor migrations) left chan struct{} leaveErr error @@ -96,6 +105,13 @@ type ( // sources concurrent with user acking. source atomic.Pointer[source] + // unknownIDFails counts consecutive UnknownTopicID fetch + // errors, mirroring cursor.unknownIDFails: the error is + // transient on a just-created topic while brokers sync, so we + // strip it for a few fetches, but persistent means the topic + // was recreated and we surface it forever (stall loudly). + unknownIDFails atomic.Int32 + cursorsIdx int // assigned is true when the cursor's partition is currently @@ -110,6 +126,19 @@ type ( // a similar flow actually makes the code worse. assigned atomic.Bool + // moving is true while a leader-move (applyMoves) is queued and + // in flight for this cursor. createShareReq skips a moving cursor + // (it then falls into the forget set, dropping it from the old + // broker's session like the classic strip), so the old source does + // not keep re-fetching the partition - getting NOT_LEADER and + // re-queuing the move - until the async migration lands. This is + // the share analog of the classic cursor going unusable for the + // duration of a move (source.go use() + strip, never re-enabled + // until the move replaces the cursor). applyMoves sets it before + // spawning the migration; applyMovesBlocking clears it and + // re-signals the cursor's source once the move has run. + moving atomic.Bool + ackMu xsync.Mutex pendingAcks []*shareAckState // user acks (r.Ack, finalizePreviousPoll, batchAckRecords) pendingGaps []shareAckRange // internal acks (gap acks, release-undeliverable) @@ -145,6 +174,7 @@ type ( topicID [16]byte partition int32 leaderID int32 + cursor *shareCursor // cursor to re-enable (clear moving) after the migration runs; see shareCursor.moving } // shareAckRange is a contiguous offset range with a fixed ack @@ -620,7 +650,15 @@ func (sc *shareConsumer) leave(ctx context.Context) { sc.leaveErr = err return } - sc.leaveErr = errCodeMessage(resp.ErrorCode, resp.ErrorMessage) + err = errCodeMessage(resp.ErrorCode, resp.ErrorMessage) + // As with the 848 leave: the leave is retried, so a retry can find + // the member already gone (prior attempt's response lost, or the + // session expired first). The member being out of the group is the + // goal state of leaving, not an error. + if errors.Is(err, kerr.UnknownMemberID) { + err = nil + } + sc.leaveErr = err } // closeShareSession releases any buffered records on this source, @@ -969,9 +1007,12 @@ func (sc *shareConsumer) manage() { consecutiveErrors = 0 continue + // Evict with coordinatorTypeGroup to match how the heartbeat loads it: + // the cache is keyed by {name, type}, so a share-typed evict never + // matches and we would retry the stale coordinator forever (#1330). case isRetryableBrokerErr(err), isAnyDialErr(err), - sc.cl.maybeDeleteStaleCoordinator(sc.cfg.shareGroup, coordinatorTypeShare, err): + sc.cl.maybeDeleteStaleCoordinator(sc.cfg.shareGroup, coordinatorTypeGroup, err): // Retryable -- fall through to shared backoff below. default: @@ -1084,14 +1125,17 @@ func (sc *shareConsumer) handleHeartbeatResp(resp *kmsg.ShareGroupHeartbeatRespo sc.memberGen.storeGeneration(resp.MemberEpoch) if resp.Assignment == nil { - if len(sc.unresolvedAssigns) == 0 { + if len(sc.unresolvedAssigns) == 0 && !sc.pendingAssigns { return nil } - // No assignment: try to resolve prior un-resolvable - // topics. If we can, that updates our current assignment - // and we return the new update. + // No assignment: try to resolve prior un-resolvable topics, + // and if a prior assignPartitions could not activate some + // partitions (pendingAssigns), re-return the current + // assignment so activation is retried: the broker considers + // the assignment delivered (we acked the epoch) and will not + // re-send it on its own. resolved := sc.resolveUnresolvedTopicIDs() - if len(resolved) == 0 { + if len(resolved) == 0 && !sc.pendingAssigns { return nil } current := sc.nowAssigned.read() @@ -1176,7 +1220,7 @@ func (sc *shareConsumer) assignPartitions(assignments map[string][]int32) { if slices.Contains(newPs, p) { // linear, *usually* fast... continue } - if int(p) >= len(td.partitions) { + if p < 0 || int(p) >= len(td.partitions) { continue } cursor := td.partitions[p].shareCursor @@ -1185,26 +1229,52 @@ func (sc *shareConsumer) assignPartitions(assignments map[string][]int32) { } } - // Add what is new. + // Add what is new. We skip based on the cursor's own activation + // state, not on what nowAssigned previously contained: a partition + // can be in nowAssigned but never activated (skipped below because + // our metadata did not know it yet), and it must be re-attempted on + // a later pass. var needsMetaUpdate bool + sc.pendingAssigns = false for t, newPs := range assignments { - oldPs := old[t] tp, ok := tps[t] if !ok { + // Not subscribed (e.g. purged): the broker revokes once + // our next heartbeat updates SubscribedTopicNames. We + // deliberately do not set pendingAssigns: the topic will + // never appear in tps, and the broker is guaranteed to + // send a new assignment in response to the subscription + // change. needsMetaUpdate = true - continue // if we don't know the tps data, we can't assign it; force a meta refresh + continue } td := tp.load() for _, p := range newPs { - if slices.Contains(oldPs, p) { - continue // already was assigned, no-op + if p < 0 { + // A sane broker never assigns a negative partition; + // guard a buggy/hostile one. Unlike the too-large + // case below, a negative index can never become + // valid, so do not set pendingAssigns for it. + sc.cfg.logger.Log(LogLevelWarn, "share assignment contains a negative partition, ignoring it", + "topic", t, + "partition", p, + ) + continue } if int(p) >= len(td.partitions) { + // Assigned a partition our metadata does not know + // yet (partitions were just added and the + // coordinator is ahead of our metadata). We cannot + // activate it now; retry after the metadata + // refresh below. + sc.pendingAssigns = true needsMetaUpdate = true continue } cursor := td.partitions[p].shareCursor - cursor.assigned.Store(true) + if cursor.assigned.Swap(true) { + continue // already active from a prior pass + } sourcesToWake[cursor.source.Load()] = struct{}{} } } @@ -1226,7 +1296,37 @@ func (sc *shareConsumer) applyMoves(moves []shareMove, endpoints []BrokerMetadat if len(moves) == 0 { return } - go sc.cl.blockingMetadataFn(func() { + // Mark each migrating cursor unusable BEFORE spawning, on this (the + // fetch) goroutine, so the very next createShareReq already skips it. + // Setting it inside the spawned goroutine would race the next fetch, + // which could rebuild a request that re-fetches the partition (getting + // NOT_LEADER again) before the goroutine runs. applyMovesBlocking clears + // the flag once the migration has run. See shareCursor.moving. + for i := range moves { + moves[i].cursor.moving.Store(true) + } + go sc.applyMovesBlocking(moves, endpoints) +} + +// applyMovesBlocking performs the cursor migration on the metadata loop. +// It registers as a share-consumer worker (incWorker/decWorker) so leave's +// barrier waits for an in-flight migration before it drains and closes the +// per-source sessions: the move runs via blockingMetadataFn and can relocate +// a cursor (or create a brand-new source) concurrently with leave. Without +// the worker registration, a CurrentLeader-hint move racing LeaveGroup/Close +// can land a cursor on a source whose closeShareSession already drained (or +// on a source created after leave snapshotted the source list), stranding +// that cursor's pending acks: sc.pendingAcks never returns to 0 (FlushAcks +// hangs) and the held records release only via the broker's acquisition-lock +// timeout. If the consumer is already dying, incWorker returns false and the +// move is skipped; the cursor stays on its current source, which the leave's +// closeShareSession drains. +func (sc *shareConsumer) applyMovesBlocking(moves []shareMove, endpoints []BrokerMetadata) { + if !sc.incWorker() { + return + } + defer sc.decWorker() + sc.cl.blockingMetadataFn(func() { // Seed any brokers from the response's NodeEndpoints that we // do not yet know about. Same merge-without-remove invariant // as kip951move.ensureBrokers. @@ -1286,7 +1386,7 @@ func (sc *shareConsumer) applyMoves(moves []shareMove, endpoints []BrokerMetadat continue } td := tp.load() - if int(m.partition) >= len(td.partitions) { + if m.partition < 0 || int(m.partition) >= len(td.partitions) { continue } cursor := td.partitions[m.partition].shareCursor @@ -1306,6 +1406,22 @@ func (sc *shareConsumer) applyMoves(moves []shareMove, endpoints []BrokerMetadat "applied", moved, ) } + + // Re-enable each cursor for fetching now that its move has run, and + // re-signal its (current) source. addShareCursor above woke the new + // source's loop while moving was still set, so that loop may have + // skipped this cursor and exited via maybeFinish before we got here; + // maybeShareConsume re-fetches it. Cursors whose move was skipped + // (topic unresolved, out of range, already on the leader) are + // re-enabled on their current source so they retry. This clear runs + // before decWorker, so it cannot race leave's barrier; the dying + // bail and the cl.ctx escape skip it, but those are shutdown paths + // where closeShareSession drains the cursor regardless of moving. + for i := range moves { + c := moves[i].cursor + c.moving.Store(false) + c.source.Load().maybeShareConsume() + } }) } @@ -1737,6 +1853,7 @@ func (s *source) shareAck(predrained []cursorAckDrain) { topicID: rt.TopicID, partition: rp.Partition, leaderID: rp.CurrentLeader.LeaderID, + cursor: drained.cursor, }) } if isShareAckRetryable(partErr) { @@ -2328,12 +2445,18 @@ func (s *source) shareFetch(doneFetch chan<- bool) (fetched bool) { } var didBackoff bool - backoff := func() { + backoff := func(why any) { // Release fetch slot before sleeping so other sources // can fetch during our backoff. doneFetch <- false alreadySentToDoneFetch = true didBackoff = true + + // Like the classic source backoff: a fetch failure is the + // only signal we get when a broker dies (no response means no + // CurrentLeader hint), so opportunistically refresh metadata + // to migrate our cursors to the new leader. + s.cl.triggerUpdateMetadata(false, fmt.Sprintf("opportunistic load during share source backoff: %v", why)) s.consecutiveFailures++ after := time.NewTimer(sc.cfg.retryBackoff(s.consecutiveFailures)) defer after.Stop() @@ -2350,7 +2473,7 @@ func (s *source) shareFetch(doneFetch chan<- bool) (fetched bool) { if err != nil { s.resetShareSession() - backoff() + backoff(err) sc.enqueueAckErrors(piggybackAcks, err, nAcks) return fetched } @@ -2360,7 +2483,13 @@ func (s *source) shareFetch(doneFetch chan<- bool) (fetched bool) { res := s.handleShareReqResp(req, resp, usable, piggybackAcks, sentPiggyback) if res.discardErr != nil { + // Top-level errors are not necessarily transient (e.g. group + // auth revoked mid-run answers GROUP_AUTHORIZATION_FAILED + // top-level on every fetch); without a backoff this loops at + // round-trip pace. Transport errors and all-errors-stripped + // responses already back off; treat top-level errors the same. sc.enqueueAckErrors(piggybackAcks, res.discardErr, nAcks) + backoff(res.discardErr) return fetched } @@ -2380,7 +2509,7 @@ func (s *source) shareFetch(doneFetch chan<- bool) (fetched bool) { s.hook(&res.fetch, true, false) sc.c.addSourceReadyForDraining(s) } else if res.allErrsStripped { - backoff() + backoff("empty share fetch response due to all partitions having retryable errors") } return fetched } @@ -2410,14 +2539,17 @@ func (s *source) handleShareReqResp(req *kmsg.ShareFetchRequest, resp *kmsg.Shar sessionStale := s.share.sessionEpoch != epoch if !sessionStale { s.share.sessionEpoch++ - // Only add cursors that were in the WANT set (usable) to - // sessionParts. req.Topics may also contain piggyback-only - // partitions for cursors that got revoked after we drained - // their acks: adding those to sessionParts would force us - // to forget them on the next request, generating an extra - // round trip of ForgottenTopicsData. - for _, c := range usable { - s.share.sessionParts[tidp{c.topicID, c.partition}] = struct{}{} + // Mirror the broker's session bookkeeping exactly: the broker + // adds EVERY partition we list in the request topics to its + // share session, whether the partition carries a fetch or only + // piggybacked acks (a cursor that was revoked, paused, or + // migrated after we drained its acks). It removes a partition + // from the session only when we forget it. + for i := range req.Topics { + t := &req.Topics[i] + for j := range t.Partitions { + s.share.sessionParts[tidp{t.TopicID, t.Partitions[j].Partition}] = struct{}{} + } } for _, ft := range req.ForgottenTopicsData { for _, p := range ft.Partitions { @@ -2464,6 +2596,7 @@ func (s *source) handleShareReqResp(req *kmsg.ShareFetchRequest, resp *kmsg.Shar ackRequeued int64 partitionsWithErrs int seen = make(map[tidp]struct{}, len(usable)+len(piggybackAcks)) + updateWhy multiUpdateWhy ) for i := range resp.Topics { @@ -2529,16 +2662,48 @@ func (s *source) handleShareReqResp(req *kmsg.ShareFetchRequest, resp *kmsg.Shar topicID: rt.TopicID, partition: rp.Partition, leaderID: rp.CurrentLeader.LeaderID, + cursor: cursor, }) continue } + // No leader hint: classify like the classic fetch + // path (source.go handleReqResp). Retriable errors + // are stripped and heal via the metadata update + // triggered below (the broker only fills + // CurrentLeader for NotLeader/FencedLeaderEpoch and + // only when it knows the new leader, so hint-less + // errors are common: leaderless windows, storage + // errors, topic ID propagation). Non-retriable + // errors surface: share sessions give the user no + // other signal. partErr := kerr.ErrorForCode(rp.ErrorCode) - partitions = append(partitions, FetchPartition{ - Partition: rp.Partition, - Err: partErr, - }) + updateWhy.add(topicName, rp.Partition, partErr) + keep := true + switch { + case errors.Is(partErr, kerr.UnknownTopicID): + // Transient on just-created topics while + // brokers sync; persistent means recreation. + // Strip a few, then surface forever, exactly + // like the classic cursor's grace counter. + if fails := cursor.unknownIDFails.Add(1); fails > 5 { + cursor.unknownIDFails.Add(-1) + } else if !sc.cfg.keepRetryableFetchErrors { + keep = false + } + default: + if kerr.IsRetriable(partErr) && !sc.cfg.keepRetryableFetchErrors { + keep = false + } + } + if keep { + partitions = append(partitions, FetchPartition{ + Partition: rp.Partition, + Err: partErr, + }) + } continue } + cursor.unknownIDFails.Store(0) if len(rp.Records) == 0 && len(rp.AcquiredRecords) == 0 { continue @@ -2591,6 +2756,22 @@ func (s *source) handleShareReqResp(req *kmsg.ShareFetchRequest, resp *kmsg.Shar } } + // Like the classic fetch path: per-partition errors trigger an + // immediate metadata update so the cursor can migrate (this is the + // only heal when the response carries no CurrentLeader hint), except + // pure unknown-topic reasons, which likely mean the topic does not + // exist yet and reloading is wasteful - those ride the debounced + // trigger. Hinted moves are handled via applyMoves and do not land + // in updateWhy. + if updateWhy != nil { + why := updateWhy.reason(fmt.Sprintf("share fetch had inner topic errors from broker %d", s.nodeID)) + if updateWhy.isOnly(kerr.UnknownTopicOrPartition) || updateWhy.isOnly(kerr.UnknownTopicID) { + s.cl.triggerUpdateMetadata(false, why) + } else { + s.cl.triggerUpdateMetadataNow(why) + } + } + var moveBrokers []BrokerMetadata if len(moves) > 0 && len(resp.NodeEndpoints) > 0 { moveBrokers = make([]BrokerMetadata, 0, len(resp.NodeEndpoints)) @@ -2834,7 +3015,13 @@ func (s *source) createShareReq(skipAckDrain bool) ( for range s.share.cursors { c := s.share.cursors[ci] ci = (ci + 1) % nShareCursors - if !c.assigned.Load() || paused.has(c.topic, c.partition) { + // Skip a cursor whose leader move is in flight (moving): leaving it + // in the want-set would re-fetch the partition on the old leader, + // getting NOT_LEADER and re-queuing the move until the migration + // lands. Skipping drops it into the forget set below, releasing it + // from the old broker's session (the share analog of the classic + // strip). applyMovesBlocking re-enables it once the move has run. + if !c.assigned.Load() || c.moving.Load() || paused.has(c.topic, c.partition) { continue } wantSet[tidp{c.topicID, c.partition}] = struct{}{} diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/errors.go b/vendor/github.com/twmb/franz-go/pkg/kgo/errors.go index 131c47485b6..0a987427b13 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/errors.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/errors.go @@ -13,13 +13,13 @@ import ( ) // IsRetryableBrokerErr returns whether the client considers an error from a -// broker retrayble. This returns true specifically if the client thinks it can +// broker retryable. This returns true specifically if the client thinks it can // retry whatever it was just trying to do with a broker. It returns false in // all other cases. // -// This can used external to the library to help filter errors if use kgo -// hooks: errors may be sent to hooks before the client retries whatever it was -// just attempting. +// This can be used external to the library to help filter errors when using +// kgo hooks: errors may be sent to hooks before the client retries whatever it +// was just attempting. func IsRetryableBrokerErr(err error) bool { return isRetryableBrokerErr(err) } @@ -99,11 +99,6 @@ func isRetryableBrokerErr(err error) bool { if errors.Is(err, errChosenBrokerDead) { return true } - // A broker kept giving us short sasl lifetimes, so we killed the - // connection ourselves. We can retry on a new connection. - if errors.Is(err, errSaslReauthLoop) { - return true - } // We really should not get correlation mismatch, but if we do, we can // retry. if errors.Is(err, errCorrelationIDMismatch) { @@ -199,11 +194,6 @@ var ( // while a request was in-flight. errChosenBrokerDead = errors.New("the broker connection has died and the request will be retried on a new connection") - // If a broker repeatedly gives us tiny sasl lifetimes, we fail a - // request after a few tries to forcefully kill the connection and - // restart a new connection ourselves. - errSaslReauthLoop = errors.New("the broker is repeatedly giving us sasl lifetimes that are too short to write a request") - // A temporary error returned when Kafka replies with a different // correlation ID than we were expecting for the request the client // issued. @@ -238,6 +228,18 @@ var ( errNoCommittedOffset = errors.New("partition has no prior committed offset") + // Returned when a ListOffsets success response carries a negative + // offset, which no legitimate listing produces. Non-retryable so the + // broker misbehavior surfaces in polls; the load is still retried. + errNegativeListedOffset = errors.New("broker replied to a ListOffsets request with an invalid negative offset") + + // Injected as a fake errored fetch when an OffsetFetch response + // repeatedly omits a partition we requested; the group coordinator + // answers every requested partition, so an omission is a broker bug + // that would otherwise leave the partition silently unconsumed for + // the rest of the group session. + errOffsetFetchOmitted = errors.New("broker repeatedly omitted a requested partition from an OffsetFetch response") + // Returned by the 848 heartbeat closure when it detects an assignment // change. The heartbeat loop treats this like RebalanceInProgress but // suppresses further heartbeat requests so that a second heartbeat diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/group_balancer.go b/vendor/github.com/twmb/franz-go/pkg/kgo/group_balancer.go index a754ee67972..1b9d5abba69 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/group_balancer.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/group_balancer.go @@ -205,6 +205,28 @@ func ParseConsumerSyncAssignment(assignment []byte) (map[string][]int32, error) // // If any metadata parsing fails, this returns an error. func NewConsumerBalancer(balance ConsumerBalancerBalance, members []kmsg.JoinGroupResponseMember) (*ConsumerBalancer, error) { + // A buggy or hostile broker can list the same member ID twice in one + // JoinGroup response. Balancers key plans by member ID, so a duplicate + // either merges (range, roundrobin) or, worse, overwrites: the sticky + // engine balances the duplicates as two members and then loses one + // side's partitions when keying its returned plan -- partitions + // assigned to nobody. Keep the first occurrence. + seen := make(map[string]struct{}, len(members)) + for _, member := range members { + seen[member.MemberID] = struct{}{} + } + if len(seen) != len(members) { + dedup := make([]kmsg.JoinGroupResponseMember, 0, len(seen)) + clear(seen) + for _, member := range members { + if _, exists := seen[member.MemberID]; !exists { + seen[member.MemberID] = struct{}{} + dedup = append(dedup, member) + } + } + members = dedup + } + b := &ConsumerBalancer{ b: balance, members: members, @@ -225,12 +247,13 @@ func NewConsumerBalancer(balance ConsumerBalancerBalance, members []kmsg.JoinGro // claiming higher and higher version support and not // actually supporting them. Sarama has a similarish // workaround. See #493. - if bytes.HasPrefix(memberMeta, []byte{0, 1}) { - memberMeta[0] = 0 - memberMeta[1] = 0 - if err = meta.ReadFrom(memberMeta); err != nil { - return nil, fmt.Errorf("unable to read member metadata: %v", err) - } + if !bytes.HasPrefix(memberMeta, []byte{0, 1}) { + return nil, fmt.Errorf("unable to read member metadata: %v", err) + } + memberMeta[0] = 0 + memberMeta[1] = 0 + if err = meta.ReadFrom(memberMeta); err != nil { + return nil, fmt.Errorf("unable to read member metadata: %v", err) } } for _, topic := range meta.Topics { @@ -495,6 +518,13 @@ func (g *groupConsumer) balanceGroup(proto string, members []kmsg.JoinGroupRespo into = memberBalancer.Balance(topicPartitionCount) } + // A custom balancer that fails is documented to SetError and return + // nil; if it returns nil without setting an error, fail loudly rather + // than dereferencing the nil interface below. + if into == nil { + return nil, fmt.Errorf("balancer %s returned a nil plan with no error", proto) + } + if p, ok := into.(*BalancePlan); ok { g.cl.cfg.logger.Log(LogLevelInfo, "balanced", "plan", p.String()) } else { @@ -767,13 +797,13 @@ func (*rangeBalancer) Balance(b *ConsumerBalancer, topics map[string]int32) Into // StickyBalancer returns a group balancer that ensures minimal partition // movement on group changes while also ensuring optimal balancing. // -// Suppose there are three members M0, M1, and M2, and two topics t0 and t1 -// each with three partitions p0, p1, and p2. If the initial balance plan looks -// like +// Suppose there are three members M0, M1, and M2, and three topics t0, t1, +// and t2 each with three partitions p0, p1, and p2. If the initial balance +// plan looks like // // M0: [t0p0, t0p1, t0p2] // M1: [t1p0, t1p1, t1p2] -// M2: [t2p0, t2p2, t2p2] +// M2: [t2p0, t2p1, t2p2] // // If M2 disappears, both roundrobin and range would have mostly destructive // reassignments. @@ -972,6 +1002,37 @@ func (p *BalancePlan) AdjustCooperative(b *ConsumerBalancer) { tmap := make(map[string]struct{}) // reusable topic existence map pmap := make(map[int32]struct{}) // reusable partitions existence map + // KIP-792 / KAFKA-12983: an OwnedPartitions claim only proves current + // ownership when no other member claims the same partition at a + // strictly higher generation. A member that missed rebalances can + // rejoin still claiming a partition that has since been assigned to + // (and is actively consumed by) another member. The balance plan may + // deliberately move the partition back to that stale claimant (sticky + // re-sticking); if the claimant's own stale claim then masks the move + // as "already owned", we skip the revoke round and two members consume + // the partition until the current owner's next sync. We track the + // highest claimed generation per partition and ignore strictly lower + // claims when computing what was added. Same-generation claims all + // count: each claimant keeps what the plan gave it and revokes the + // rest at its own sync, which creates no new overlap. The revoked side + // below stays unfiltered on purpose -- any claimant might still be + // consuming, and revoking more is always safe. + maxClaim := make(map[string]map[int32]int32, 8) + b.EachMember(func(_ *kmsg.JoinGroupResponseMember, meta *kmsg.ConsumerMemberMetadata) { + for _, otopic := range meta.OwnedPartitions { + claimT := maxClaim[otopic.Topic] + if claimT == nil { + claimT = make(map[int32]int32, 20) + maxClaim[otopic.Topic] = claimT + } + for _, opartition := range otopic.Partitions { + if gen, ok := claimT[opartition]; !ok || meta.Generation > gen { + claimT[opartition] = meta.Generation + } + } + } + }) + plan := p.plan // First, on all members, we find what was added and what was removed @@ -997,12 +1058,17 @@ func (p *BalancePlan) AdjustCooperative(b *ConsumerBalancer) { continue } // calculate what was added by creating a planned existence map, - // then removing what was owned, and anything that remains is new, + // then removing what was owned, and anything that remains is new. + // A claim beaten by a strictly higher-generation claim elsewhere + // is stale and does not count as owned: the planned partition is + // then a real transfer that must wait for the owner's revoke. for _, ppartition := range ppartitions { pmap[ppartition] = struct{}{} } for _, opartition := range otopic.Partitions { - delete(pmap, opartition) + if meta.Generation >= maxClaim[topic][opartition] { + delete(pmap, opartition) + } } if len(pmap) > 0 { allAddedT := addT(topic) diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/hooks.go b/vendor/github.com/twmb/franz-go/pkg/kgo/hooks.go index 3ba13db0eab..0442b544b47 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/hooks.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/hooks.go @@ -42,7 +42,7 @@ type HookNewClient interface { OnNewClient(*Client) } -// HookClientClosed is called in Close or CloseAfterRebalance after a client +// HookClientClosed is called in Close or CloseAllowingRebalance after a client // has been closed. This hook can be used to perform final cleanup work. type HookClientClosed interface { // OnClientClosed is passed the client that has been closed, after @@ -176,7 +176,7 @@ type HookBrokerE2E interface { type HookBrokerThrottle interface { // OnBrokerThrottle is passed the broker metadata, the imposed // throttling interval, and whether the throttle was applied before - // Kafka responded to them request or after. + // Kafka responded to the request or after. // // For Kafka < 2.0, the throttle is applied before issuing a response. // For Kafka >= 2.0, the throttle is applied after issuing a response. @@ -380,8 +380,8 @@ type HookFetchRecordBuffered interface { // HookFetchRecordUnbuffered is called when a fetched record is unbuffered. // -// A record can be internally discarded after being in some scenarios without -// being polled, such as when the internal assignment changes. +// A record can be internally discarded in some scenarios without being +// polled, such as when the internal assignment changes. // // As an example, if using HookFetchRecordBuffered for a gauge of how many // record bytes are buffered ready to be polled, this hook can be used to diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/graph.go b/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/graph.go index d6bbb587ed2..947b55d57d6 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/graph.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/graph.go @@ -42,9 +42,10 @@ func (b *balancer) newGraph( for memberNum := range b.plan { out := outBufs[:0:len(topicPotentials)] outBufs = outBufs[len(topicPotentials):] - // In the worst case, if every node is linked to each other, - // each node will have nparts edges. We preallocate the worst - // case. It is common for the graph to be highly connected. + // Out edges are per topic, not per partition: in the worst + // case a member subscribes to every topic, so we preallocate + // one topic slot per member. The partition edges themselves + // are enumerated from topicInfos during findSteal. g.out[memberNum] = out } for topicNum, potentials := range topicPotentials { diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/sticky.go b/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/sticky.go index 06ac816937a..351636005fb 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/sticky.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/internal/sticky/sticky.go @@ -17,7 +17,8 @@ import ( // bug. The second version introduced generations with the default generation // from the first generation's consumers defaulting to -1. -// We can support up to 65533 members; two slots are reserved. +// We can support up to 65533 members; the unassignedPart sentinel and one +// spare slot are reserved. // We can support up to 2,147,483,647 partitions. // I expect a server to fall over before reaching either of these numbers. @@ -246,7 +247,10 @@ func (b *balancer) partNumByTopic(topic string, partition int32) (int32, bool) { return 0, false } topicInfo := b.topicInfos[topicNum] - if partition >= topicInfo.partitions { + // Claimed partitions are arbitrary input from other group members; a + // negative partition would index our flat partition state at a + // negative offset (or alias into the preceding topic's range). + if partition < 0 || partition >= topicInfo.partitions { return 0, false } return topicInfo.partNum + partition, true @@ -671,22 +675,36 @@ func (b *balancer) tryRestickyStales( } } if !canTake { - return + continue } - // The part cannot be unassigned here; a stale member - // would just have it. The part also cannot be deleted; - // if it is, there are no potential consumers and the - // logic above continues before getting here. The part - // must be on a different owner (cannot be lastOwner), - // otherwise it would not be a lastOwner in the stales - // map; it would just be the current owner. + // The part cannot be deleted; if it is, there are no + // potential consumers and canTake is false above. The part + // CAN be unassigned: the member that won the claim (the + // higher generation) may have dropped its subscription to + // the topic, in which case our caller un-mapped the + // partition from the winner's plan and left it unassigned. + // We give the partition straight back to the stale member. currentOwner := partitionConsumers[staleNum].memberNum + if currentOwner == unassignedPart { + b.plan[lastOwnerNum].add(staleNum) + partitionConsumers[staleNum] = partitionConsumer{lastOwnerNum, lastOwnerNum} + continue + } lastOwnerPartitions := &b.plan[lastOwnerNum] currentOwnerPartitions := &b.plan[currentOwner] if len(*lastOwnerPartitions)+1 < len(*currentOwnerPartitions) { currentOwnerPartitions.remove(staleNum) lastOwnerPartitions.add(staleNum) + // partitionConsumers seeds the steal graph's edge + // ownership (cxns) on the complex path. If we move the + // partition in the plan but not here, a later steal of + // this partition resolves to the old owner and remove() + // runs against a plan that does not contain the + // partition -- which swap-removes an unrelated + // partition: the final plan then has this partition on + // two members and the wrongly removed one on none. + partitionConsumers[staleNum] = partitionConsumer{lastOwnerNum, lastOwnerNum} } } } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/logger.go b/vendor/github.com/twmb/franz-go/pkg/kgo/logger.go index b9f1cd2465f..8d8fa61c8c0 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/logger.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/logger.go @@ -125,16 +125,14 @@ func (w *wrappedLogger) Log(level LogLevel, msg string, keyvals ...any) { w.inner.Log(level, msg, keyvals...) } -// LoggerFn returns an anonymous function that can be used in other packages -// that support their own anonymous logger functions. +// The following is a small helper you can copy into your own code to bridge a +// kgo.Logger to packages that accept an anonymous logger function of the form +// func(int8, string, ...any) - notably the sister 'sr' and 'kfake' packages, +// which are initialized with a 'LogFn' option. It is intentionally not +// exported (it would force a dependency edge); copy it where you need it: // -// Notably, this was added so that you can easily use a kgo.Logger in the -// sister 'sr' and 'kfake' packages. Both clients can be initialized with a -// 'LogFn' option. This function makes it easy to use the same kgo.Logger -// across the other packages. -// -// func LoggerFn(l Logger) func(int8, string, ...any) { +// func loggerFn(l kgo.Logger) func(int8, string, ...any) { // return func(lvl int8, msg string, keyvals ...any) { -// l.Log(LogLevel(lvl), msg, keyvals...) +// l.Log(kgo.LogLevel(lvl), msg, keyvals...) // } // } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/metadata.go b/vendor/github.com/twmb/franz-go/pkg/kgo/metadata.go index c5615c1ff72..4c2542b6180 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/metadata.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/metadata.go @@ -835,8 +835,11 @@ func (cl *Client) mergeTopicPartitions( // // 2) a topic was deleted and recreated with fewer partitions // - // Both of these scenarios should be rare to non-existent, and we do - // nothing if we encounter them. + // Case 1 is temporary and heals on a later refresh; case 2 is + // permanent. Below, we keep the missing partition around either way. + // For producers we bump its load error, which fails buffered records + // only once the unknown fail limit trips (so case 1 does not fail + // records); consumers keep consuming through the existing cursor. // Migrating topicPartitions is a little tricky because we have to // worry about underlying pointers that may currently be loaded. @@ -851,9 +854,11 @@ func (cl *Client) mergeTopicPartitions( // consuming, the partition is part of a group or part // of what was loaded for direct consuming. // - // We only clear a partition if it is purged from the - // client (which can happen automatically for consumers - // if the user opted into ConsumeRecreatedTopics). + // We only clear a partition if the topic is purged from + // the client, either manually via PurgeTopicsFromClient + // or automatically for regex consumers when the topic + // has been missing from metadata for longer than + // ConsiderMissingTopicDeletedAfter. dup := *oldTP newTP := &dup newTP.loadErr = errMissingMetadataPartition @@ -895,11 +900,47 @@ func (cl *Client) mergeTopicPartitions( // fetched from an out of date broker. We just keep the old // information. if newTP.leaderEpoch < oldTP.leaderEpoch { - // If we repeatedly rewind, then perhaps the cluster - // entered some bad state and lost forward progress. - // We will log & allow the rewind to allow the client - // to continue; other requests may encounter fenced - // epoch errors (and respectively recover). + // A negative leader epoch is the "no leader" sentinel + // (Kafka uses -1): the partition is momentarily + // leaderless, e.g. mid-election after every replica + // restarted in a full cluster bounce. This is not a + // genuinely older epoch, so we must not treat it as a + // rewind. If we counted it toward maxEpochRewinds, then + // after enough leaderless refreshes we would fall through + // below and accept -1 as the partition's leader epoch -- + // which is unsafe. A cursor at leader epoch -1 opts out of + // KIP-320 fencing: migrateCursorTo skips + // OffsetForLeaderEpoch validation for a negative new epoch, + // so a genuine log truncation during the leaderless window + // would go undetected (no ErrDataLoss), and the consumer + // would then fetch at a stale offset with currentLeaderEpoch + // -1 (which brokers never fence) and stall at the high + // watermark. Instead we keep our last known real leader and + // epoch and signal a retry; once a real epoch (>= old) + // reappears, normal validation runs and detects any + // truncation. + if newTP.leaderEpoch < 0 { + cl.cfg.logger.Log(LogLevelDebug, "metadata has a leader epoch of -1 (no leader); keeping our last known leader and epoch until a leader is elected", + "topic", topic, + "partition", part, + "old_leader_epoch", oldTP.leaderEpoch, + ) + *newTP = *oldTP + retryWhy.add(topic, int32(part), errNoLeaderEpoch) + continue + } + + // Otherwise newTP.leaderEpoch is a real (>= 0) epoch that + // is merely lower than ours. That can be the current + // reality: issue #119 saw an unclean leader election + // briefly surface a higher epoch from a broker that then + // died, leaving the surviving cluster on a real, lower + // epoch. Permanently refusing it stranded the client in an + // unrecoverable metadata loop, so if we repeatedly rewind we + // accept it to allow the client to continue. Unlike the -1 + // sentinel handled above, a real lower epoch self-corrects + // downstream: consume sees FENCED_LEADER_EPOCH (and reports + // data loss) and produce sees NOT_LEADER_FOR_PARTITION. // // Five is a pretty low amount of retries, but since // we iterate through known brokers, this basically @@ -1048,6 +1089,7 @@ func (cl *Client) mergeTopicPartitions( var ( errEpochRewind = errors.New("epoch rewind") errMissingTopicID = errors.New("missing topic ID") + errNoLeaderEpoch = errors.New("no leader epoch") ) type multiUpdateWhy map[kerrOrString]map[string]map[int32]struct{} diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/metrics_714.go b/vendor/github.com/twmb/franz-go/pkg/kgo/metrics_714.go index 927f0f9fdbe..7d7220b977f 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/metrics_714.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/metrics_714.go @@ -29,6 +29,8 @@ func (cl *Client) pushMetrics() { select { case <-cl.ctx.Done(): return + case <-m.quitting: + return case <-m.firstObserve: } @@ -58,6 +60,9 @@ func (cl *Client) pushMetrics() { case <-cl.ctx.Done(): after.Stop() return + case <-m.quitting: + after.Stop() + return case <-after.C: } continue @@ -65,6 +70,21 @@ func (cl *Client) pushMetrics() { clientInstanceID = gresp.ClientInstanceID + // A broker must advertise a positive push interval; a <=0 value is + // invalid. We substitute Kafka's documented default rather than honor + // it, matching the Java client's validateIntervalMs. Without this, the + // no-requested-metrics arm below times on the raw interval (no floor, + // unlike the push loop's max(..., time.Second)), so a broker returning + // an empty RequestedMetrics list with a non-positive interval would + // re-issue GetTelemetrySubscriptions at round-trip pace forever. + if v := validatePushIntervalMillis(gresp.PushIntervalMillis); v != gresp.PushIntervalMillis { + cl.cfg.logger.Log(LogLevelWarn, "broker advertised a non-positive telemetry push interval, substituting the default", + "advertised", gresp.PushIntervalMillis, + "substituted", v, + ) + gresp.PushIntervalMillis = v + } + // If there are no requested metrics, we wait the push interval // and re-get. if len(gresp.RequestedMetrics) == 0 { @@ -74,6 +94,10 @@ func (cl *Client) pushMetrics() { select { case <-cl.ctx.Done(): terminating = true + after.Stop() + case <-m.quitting: + terminating = true + after.Stop() case <-after.C: } continue @@ -120,12 +144,24 @@ func (cl *Client) pushMetrics() { } // Wait until our push interval; if the client is quitting, - // we immediately send a push with Terminating=true. + // we immediately send a push with Terminating=true. The + // quitting signal fires during Close BEFORE the client + // context is canceled - once cl.ctx is dead, the request + // path aborts everything and the push could not be + // delivered. This assigns the outer terminating so that + // after the terminating push is handled, both loops exit + // and our deferred ctxCancel releases Close's bounded + // wait; a shadowing variable here would re-enter the loop + // and send a second terminating push (which brokers + // reject). after := time.NewTimer(wait) - var terminating bool select { case <-cl.ctx.Done(): terminating = true + after.Stop() + case <-m.quitting: + terminating = true + after.Stop() case <-after.C: } @@ -199,6 +235,22 @@ func (cl *Client) pushMetrics() { } } +// defaultPushIntervalMillis is Kafka's documented telemetry push interval +// default (5m), substituted when a broker advertises a non-positive interval +// (Java's ClientTelemetryReporter.DEFAULT_PUSH_INTERVAL_MS). +const defaultPushIntervalMillis = 5 * 60 * 1000 + +// validatePushIntervalMillis returns the broker-advertised telemetry push +// interval, substituting the default for a non-positive (invalid) value so the +// re-get / push loops always pace on a sane interval. Mirrors the Java client's +// ClientTelemetryUtils.validateIntervalMs. +func validatePushIntervalMillis(advertised int32) int32 { + if advertised <= 0 { + return defaultPushIntervalMillis + } + return advertised +} + func buildNameFilter(requested []string) func(string) bool { if len(requested) == 0 { return func(string) bool { return false } @@ -289,16 +341,17 @@ type ( // metricRate is a count per second and a total. metricRate struct { - count atomic.Int64 // Sum of events this period; rate == float64(count/time) at rollup + count atomic.Int64 // Events this period; rate == count/elapsed-seconds at rollup. tot atomic.Int64 // Total events over all time. lastTot int64 // Updated when encoding; the last value for tot in case broker requests DELTA. } - // metricTime reports average latency, max latency, and total latency. - // The unit is in milliseconds. + // metricTime reports average latency and max latency. The unit is in + // milliseconds. metricTime struct { - sum atomic.Int64 // With separate aggDur field, avg = sum/aggDur at rollup. - max atomic.Int64 // Max latency seen during this window. + sum atomic.Int64 // Sum of all observations this period; avg = sum/count at rollup. + count atomic.Int64 // Number of observations this period; the avg denominator. + max atomic.Int64 // Max latency seen during this window. } // We skip: @@ -331,6 +384,12 @@ type ( firstObserve chan struct{} + // quitting is closed by Close before the client context is + // canceled, asking pushMetrics to send its final terminating + // push while requests can still complete. + quitting chan struct{} + closedQuitting atomic.Bool + ctx context.Context ctxCancel func() } @@ -340,9 +399,18 @@ func (m *metrics) init(cl *Client) { m.cl = cl m.initNano = time.Now().UnixNano() m.firstObserve = make(chan struct{}) + m.quitting = make(chan struct{}) m.ctx, m.ctxCancel = context.WithCancel(context.Background()) // for graceful shutdown } +// quit asks pushMetrics to send its final terminating push and exit; it is +// safe to call multiple times (Close can run more than once). +func (m *metrics) quit() { + if !m.closedQuitting.Swap(true) { + close(m.quitting) + } +} + func safeDiv[T ~int64 | ~float64](num, denom T) T { if denom == 0 { return 0 @@ -357,13 +425,17 @@ func (t *metricRate) observe() { t.tot.Add(1) } -func (t *metricRate) rollNums() (rate float64, tot, lastTot int64) { +func (t *metricRate) rollNums(aggDur time.Duration) (rate float64, tot, lastTot int64) { count := t.count.Swap(0) lastTot = t.lastTot tot = t.tot.Load() t.lastTot = tot - rate = safeDiv(float64(count), float64(tot-lastTot)) + // A rate is events-per-second over the aggregation window, matching + // Kafka's Rate stat (value / elapsed-time). The previous divisor was + // tot-lastTot, which equals count by construction (observe increments + // both count and tot), so the rate was a constant ~1.0. + rate = safeDiv(float64(count), aggDur.Seconds()) return rate, tot, lastTot } @@ -371,6 +443,7 @@ func (t *metricRate) rollNums() (rate float64, tot, lastTot int64) { // triggerFirstObserve is always called. func (t *metricTime) observe(millis int64) { t.sum.Add(millis) + t.count.Add(1) for { max := t.max.Load() if millis < max { @@ -382,10 +455,14 @@ func (t *metricTime) observe(millis int64) { } } -func (t *metricTime) rollNums(aggDur time.Duration) (avg float64, max int64) { +func (t *metricTime) rollNums() (avg float64, max int64) { sum := t.sum.Swap(0) + count := t.count.Swap(0) max = t.max.Swap(0) - avg = safeDiv(float64(sum), float64(aggDur.Milliseconds())) + // An avg is the mean observation, matching Kafka's Avg stat + // (total / count). The previous divisor was the aggregation window + // duration in millis, which is not the number of observations. + avg = safeDiv(float64(sum), float64(count)) return avg, max } @@ -512,6 +589,7 @@ func (m *metrics) appendTo(b []byte, useDeltaSums bool, maxBytes int32, allowedN timeNano: nowNano, }, aggregationTemporality: otelTempDelta, + isMonotonic: true, }, }) } else { @@ -525,6 +603,7 @@ func (m *metrics) appendTo(b []byte, useDeltaSums bool, maxBytes int32, allowedN timeNano: nowNano, }, aggregationTemporality: otelTempCumulative, + isMonotonic: true, }, }) } @@ -548,18 +627,18 @@ func (m *metrics) appendTo(b []byte, useDeltaSums bool, maxBytes int32, allowedN } { switch t := s.v.(type) { case *metricRate: - rate, tot, lastTot := t.rollNums() + rate, tot, lastTot := t.rollNums(aggDur) appendGauge(s.name+".rate", 0, rate, nil) appendSum(s.name+".total", tot, lastTot, nil) case *metricTime: - avg, max := t.rollNums(aggDur) + avg, max := t.rollNums() appendGauge(s.name+".avg", 0, avg, nil) appendGauge(s.name+".max", max, 0, nil) case *map[int32]*metricTime: for broker, m := range *t { - avg, max := m.rollNums(aggDur) + avg, max := m.rollNums() attrs := map[string]any{"node_id": broker} appendGauge(s.name+".avg", 0, avg, attrs) appendGauge(s.name+".max", max, 0, attrs) @@ -897,18 +976,13 @@ func (d *otelNumDataPoint) appendTo(b []byte) []byte { } func appendOtelAttributesTo(b []byte, fieldNumber int, attrs map[string]any) []byte { -outer: for key, value := range attrs { - b = appendProtoTag(b, fieldNumber, protoTypeLength) - - kvBytes := []byte{} - // Field 1: key (string) - kvBytes = appendProtoTag(kvBytes, 1, protoTypeLength) - kvBytes = appendProtoString(kvBytes, key) - - // Field 2: value (AnyValue) - kvBytes = appendProtoTag(kvBytes, 2, protoTypeLength) - + // We must determine that the value is serializable BEFORE we + // write anything to b: an unsupported type continues the loop, + // and if we had already appended the field tag we would leave a + // dangling tag with no length+payload, corrupting the whole + // protobuf (the documented Attrs contract is to silently skip + // unsupported types). var anyValueBytes []byte switch t := value.(type) { case *string, string: @@ -973,9 +1047,18 @@ outer: anyValueBytes = binary.AppendUvarint(anyValueBytes, uint64(len(t))) anyValueBytes = append(anyValueBytes, t...) default: - continue outer + continue } + b = appendProtoTag(b, fieldNumber, protoTypeLength) + + kvBytes := []byte{} + // Field 1: key (string) + kvBytes = appendProtoTag(kvBytes, 1, protoTypeLength) + kvBytes = appendProtoString(kvBytes, key) + + // Field 2: value (AnyValue) + kvBytes = appendProtoTag(kvBytes, 2, protoTypeLength) kvBytes = binary.AppendUvarint(kvBytes, uint64(len(anyValueBytes))) kvBytes = append(kvBytes, anyValueBytes...) diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/partitioner.go b/vendor/github.com/twmb/franz-go/pkg/kgo/partitioner.go index 46e7d11d124..da463b378e2 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/partitioner.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/partitioner.go @@ -15,8 +15,8 @@ import ( // from producing through partitioning, so you can set fields in the record // struct before producing to aid in partitioning with a custom partitioner. type Partitioner interface { - // forTopic returns a partitioner for an individual topic. It is - // guaranteed that only one record will use the an individual topic's + // ForTopic returns a partitioner for an individual topic. It is + // guaranteed that only one record will use an individual topic's // topicPartitioner at a time, meaning partitioning within a topic does // not require locks. ForTopic(string) TopicPartitioner @@ -229,7 +229,7 @@ func (p *leastBackupTopicPartitioner) PartitionByBackup(_ *Record, n int, backup leastBackup = backup p.onPart = pick npicked = 1 - } else { + } else if backup == leastBackup { npicked++ // reservoir sampling with k = 1 if p.rng.Intn(npicked) == 0 { p.onPart = pick @@ -245,11 +245,11 @@ func (p *leastBackupTopicPartitioner) PartitionByBackup(_ *Record, n int, backup /////////////////// // UniformBytesPartitioner is a redux of the StickyPartitioner, proposed in -// KIP-794 and release with the Java client in Kafka 3.3. This partitioner +// KIP-794 and released with the Java client in Kafka 3.3. This partitioner // returns the same partition until 'bytes' is hit. At that point, a // re-partitioning happens. If adaptive is false, this chooses a new random -// partition, otherwise this chooses a broker based on the inverse of the -// backlog currently buffered for that broker. If keys is true, this uses +// partition, otherwise this chooses a partition based on the inverse of the +// backlog currently buffered for that partition. If keys is true, this uses // standard hashing based on record key for records with non-nil keys. hasher // is optional; if nil, the default hasher murmur2 (Kafka's default). // @@ -355,8 +355,8 @@ func (p *uniformBytesTopicPartitioner) PartitionByBackup(r *Record, n int, backu } else { p.calc = p.calc[:0] - // For adaptive, the logic is that we pick by broker according - // to the inverse of the queue size. Presumably this means + // For adaptive, the logic is that we pick a partition according + // to the inverse of its queue size. Presumably this means // bytes, but we use records for simplicity. // // We calculate 1/recs for all brokers and choose the first one @@ -382,14 +382,28 @@ func (p *uniformBytesTopicPartitioner) PartitionByBackup(r *Record, n int, backu } r := p.rng.Float64() pick := r * t + // The loop below selects nothing in two cases: floating rounding + // can leave pick just above 0 after subtracting every weight (the + // guarded case the original code handled), and we may have entered + // this re-pick with a stale p.onPart that is not the -1 byte-reset + // sentinel but rather a previously-pinned index that is now >= n + // because the writable partition count shrank under us (e.g. a + // leader election dropped partitions from writablePartitions). In + // both cases p.onPart is unchanged by the loop, so we must fall + // back to a valid index rather than return the stale value, which + // the caller would reject as an out-of-range partitioning choice + // (failing the record). The non-adaptive branch above re-picks + // unconditionally via Intn(n) and so has never had this hole. + picked := false for _, c := range p.calc { pick -= c.f if pick <= 0 { p.onPart = c.n + picked = true break } } - if p.onPart == -1 { + if !picked { p.onPart = p.calc[len(p.calc)-1].n } } @@ -475,7 +489,7 @@ type PartitionerHasher func([]byte, int) int // KafkaHasher returns a PartitionerHasher using hashFn that mirrors how Kafka // partitions after hashing data. In Kafka, after hashing into a uint32, the // hash is converted to an int32 and the high bit is stripped. Kafka by default -// uses murmur2 hashing, and the StickyKeyPartiitoner uses this by default. +// uses murmur2 hashing, and the StickyKeyPartitioner uses this by default. // Using this KafkaHasher function is only necessary if you want to change the // underlying hashing algorithm. func KafkaHasher(hashFn func([]byte) uint32) PartitionerHasher { @@ -497,8 +511,25 @@ func KafkaHasher(hashFn func([]byte) uint32) PartitionerHasher { // In particular, using this function with a crc32.ChecksumIEEE hasher makes // this partitioner match librdkafka's consistent partitioner, or the // zendesk/ruby-kafka partitioner. +// +// Note that the arithmetic depends on Go's int width: on 32-bit platforms, +// hashes with the high bit set choose a different partition than on 64-bit +// platforms (only the 64-bit behavior matches librdkafka). This is +// deliberately left alone: the function exists to preserve a historical +// placement, and changing either platform's placement would remap keys for +// deployments relying on it. func SaramaHasher(hashFn func([]byte) uint32) PartitionerHasher { return func(key []byte, n int) int { + // The int conversion makes this arithmetic int-width + // dependent: on 64-bit platforms int(uint32) is always + // non-negative (the negation below is dead and the result + // matches librdkafka's unsigned modulo), while on 32-bit + // platforms a hash with the high bit set wraps negative and + // is negated, choosing a different partition. This stays + // as-is deliberately: this function's entire purpose is + // preserving a historical placement (see the doc above), and + // existing deployments on either width depend on the + // placement they have been writing with. p := int(hashFn(key)) % n if p < 0 { p = -p diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/pools.go b/vendor/github.com/twmb/franz-go/pkg/kgo/pools.go index f4449c3db45..63b258f7e64 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/pools.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/pools.go @@ -11,7 +11,7 @@ import ( //////////////////////////////////////////////////////////////// // NOTE: // -// NOTE: Make sure new hooks are checked in implementsAnyPool // +// NOTE: Make sure new pools are checked in implementsAnyPool // // NOTE: // //////////////////////////////////////////////////////////////// @@ -42,7 +42,9 @@ func (ps pools) each(fn func(Pool) bool) { type PoolDecompressBytes interface { // GetDecompressBytes returns a slice to decompress into. This // interface is given the compressed data and the codec that will be - // used for decompressing. + // used for decompressing. Only the returned slice's capacity is used; + // data is written starting at index 0 regardless of the slice's + // length. // // For many decompression algorithms, it is not possible to accurately // know the size that data will be once decompressed. You can guess a @@ -143,6 +145,13 @@ func (r *Record) Recycle() { return } + ps.release() +} + +// release zeroes and puts the pooled slices back. Called by a batch's last +// Recycle, or directly by the fetch processor when a batch kept no records +// (so no Recycle will ever run). +func (ps *recordPools) release() { // Reset the length of slices to max to ensure we zero things and so // that users can avoid this resetting. ps.decompressBytes = ps.decompressBytes[:cap(ps.decompressBytes)] @@ -192,6 +201,10 @@ func implementsAnyPool(p Pool) bool { return false } +// ensureLen returns s reset to exactly length n, growing it if needed. n +// must be >= 0: a negative n panics on the s[:n] slice expression. Callers +// pass a record count read off the wire, which is rejected for < 0 before +// reaching here (see processRecordBatch's negative-count guard). func ensureLen[S ~[]E, E any](s S, n int) S { s = s[:cap(s)] if len(s) >= n { diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/producer.go b/vendor/github.com/twmb/franz-go/pkg/kgo/producer.go index c4a13618f92..7ca99bc4270 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/producer.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/producer.go @@ -59,9 +59,27 @@ type producer struct { batchPromises ring[batchPromise] // we never call die() on it + // onBatchPromiseBroadcast, if non-nil, is invoked from finishPromises + // immediately before the per-batch p.c.Broadcast() fires, with moreQueued + // reporting whether further promise elements are still queued in the ring + // (i.e. the broadcast is firing mid-drain rather than at ring exit). It + // exists purely so tests can observe the broadcast deterministically at + // its source instead of racing a woken goroutine; it is always nil in + // production. + onBatchPromiseBroadcast func(moreQueued bool) + txnMu xsync.Mutex inTxn bool tx890p2 atomic.Bool + + // producedInTxn is set when a record is buffered within the current + // transaction and reset by BeginTransaction. EndTransaction consults + // it under KIP-890 part 2, where produce requests implicitly add + // partitions broker-side before the data append: a transaction whose + // every produce FAILED still needs an EndTxn abort even though no + // partition was marked addedToTxn client-side (marking happens only + // on produce success). + producedInTxn atomic.Bool } // BufferedProduceRecords returns the number of records currently buffered for @@ -87,6 +105,7 @@ func (cl *Client) BufferedProduceBytes() int64 { // EnsureProduceConnectionIsOpen attempts to open a produce connection to all // specified brokers, or all brokers if `brokers` is empty or contains -1. +// Broker IDs less than -1 are ignored. // // This can be used in an attempt to reduce the latency when producing if your // application produces infrequently: you can force open a produce connection a @@ -127,7 +146,7 @@ func (cl *Client) EnsureProduceConnectionIsOpen(ctx context.Context, brokers ... } cl.brokersMu.RUnlock() } else { - for _, b := range brokers { + for _, b := range keep { wg.Add(1) go func() { defer wg.Done() @@ -211,6 +230,20 @@ func (p *producer) purgeTopics(topics []string) { p.topicsMu.Lock() defer p.topicsMu.Unlock() + // We sweep unknown-topic waiters AND store the cleaned topics map + // while unknownTopicsMu is held. The store must not happen after the + // mu is released: partitionsForTopicProduce re-checks the topic's + // presence in p.topics under this mu before (re)creating an + // unknown-topic waiter, so holding the mu across both steps means a + // concurrent produce either sees the topic still present - and its + // just-added waiter is then swept by us - or sees it gone and + // re-registers the topic properly. If we instead released the mu + // between the sweep and the store (old behavior), a produce could + // land in that window: it saw the topic in p.topics, re-created a + // waiter, and we then removed the topic from the map - orphaning the + // waiter, which no metadata update would ever notify (the request set + // is built from p.topics), silently hanging the record forever. This + // mirrors storePartitionsUpdate's store-before-unlock requirement. p.unknownTopicsMu.Lock() for _, topic := range topics { if unknown, exists := p.unknownTopics[topic]; exists { @@ -222,17 +255,20 @@ func (p *producer) purgeTopics(topics []string) { }) } } - p.unknownTopicsMu.Unlock() - toStore := p.topics.clone() - defer p.topics.storeData(toStore) - + var purged []*topicPartitionsData for _, topic := range topics { d := toStore.loadTopic(topic) if d == nil { continue } delete(toStore, topic) + purged = append(purged, d) + } + p.topics.storeData(toStore) + p.unknownTopicsMu.Unlock() + + for _, d := range purged { for _, p := range d.partitions { r := p.records @@ -296,7 +332,7 @@ func (rs ProduceResults) FirstErr() error { return nil } -// First the first record and error in the produce results. +// First returns the first record and error in the produce results. // // This function is useful if you only passed one record to ProduceSync. func (rs ProduceResults) First() (*Record, error) { @@ -476,16 +512,26 @@ func (cl *Client) TryProduce( // Kafka replies. For a synchronous produce, see ProduceSync. Records are // produced in order per partition if the record is produced successfully. // Successfully produced records will have their attributes, offset, and -// partition set before the promise is called. All promises are called serially -// (and should be relatively fast). If a record's timestamp is unset, this -// sets the timestamp to time.Now. +// partition set before the promise is called. All promises are called +// serially, so they should be relatively fast and must not block: a promise +// that blocks on the client itself -- for example, a blocking Produce while +// the client is at its max-buffered limits, or a Flush -- waits on progress +// that only later promises can deliver and can deadlock the client. To +// produce from within a promise, spawn a goroutine (as +// AbortingFirstErrPromise does for aborting): a goroutine'd produce that +// blocks simply waits for the promise worker to make space. A direct +// TryProduce inside a promise is safe only while promise delivery is keeping +// up; if the record fails before buffering while the client is saturated +// with an extreme backlog of failing records, delivering that failure blocks +// the promise worker on itself. If a record's timestamp is unset, this sets +// the timestamp to time.Now. // // If the topic field is empty, the client will use the DefaultProduceTopic; if // that is also empty, the record is failed immediately. If the record is too // large to fit in a batch on its own in a produce request, the record will be -// failed with immediately kerr.MessageTooLarge. +// failed immediately with kerr.MessageTooLarge. // -// If the client is configured to automatically flush the client currently has +// If the client is configured to automatically flush and the client currently has // the configured maximum amount of records buffered, Produce will block. The // context can be used to cancel waiting while records flush to make space. In // contrast, if manual flushing is configured, the record will be failed @@ -625,6 +671,18 @@ func (cl *Client) produce( }() <-wait // we wait for the goroutine to exit, then unlock again (since the goroutine leaves the mutex locked) p.mu.Unlock() + // The goroutine above decremented p.blocked, but this is the + // cancel path: the record is failed, not buffered, so there is + // no compensating bufferedRecords++ (the success path below + // has one, keeping the sum unchanged). The bufferedRecords + + // blocked sum that Flush waits on therefore just dropped, and + // the only broadcast on this path - the one that woke the + // goroutine above - fired BEFORE its decrement, so a Flush that + // re-checked its predicate in between observed the stale + // pre-decrement sum and went back to waiting. Broadcast now, + // after the decrement is visible, so a Flush whose sum reached + // zero is woken; without this it can hang forever. + p.c.Broadcast() p.promiseRecordBeforeBuf(promisedRec{ctx, promise, r}, err) } @@ -645,6 +703,16 @@ func (cl *Client) produce( p.bufferedBytes += userSize p.mu.Unlock() + // Set at buffer time, before any produce reaches the broker, so this can + // over-set: a record counted here may still be failed locally (client + // close, unknown-topic timeout) before it is ever sent. The only + // consequence is an unnecessary EndTxn abort, which is always legal under + // KIP-890p2 -- an empty abort succeeds, bumps the epoch, and has nothing to + // commit. See the producedInTxn field doc and EndTransaction. + if cl.cfg.txnID != nil && !p.producedInTxn.Load() { + p.producedInTxn.Store(true) + } + cl.loadPartsAndPartition(promisedRec{ctx, promise, r}) } @@ -658,8 +726,18 @@ type batchPromise struct { err error } +// promiseBatch finishes a batch of records. This never parks on the ring's +// maxLen: every caller either carries records already admitted under the +// max-buffered accounting (sink responses, fail/purge paths) or holds a +// client lock (purgeTopics and failBufferedRecords under topicsMu and +// unknownTopicsMu, storePartitionsUpdate under unknownTopicsMu, recBuf +// failure paths under recBuf.mu). A parked lock-holder can deadlock: the +// promise worker is the only goroutine that frees ring space, and a user +// promise may re-enter the client (TryProduce) and need the very lock the +// parked pusher holds, so the worker would wait on the lock while the lock +// holder waits on the worker. func (p *producer) promiseBatch(b batchPromise) { - if first, _ := p.batchPromises.push(b); first { + if first, _ := p.batchPromises.pushForce(b); first { go p.finishPromises(b) } } @@ -668,32 +746,54 @@ func (p *producer) promiseRecord(pr promisedRec, err error) { p.promiseBatch(batchPromise{recs: []promisedRec{pr}, err: err}) } +// promiseRecordBeforeBuf finishes a record that failed before it was ever +// buffered (and before it counted toward bufferedRecords). Only this entry +// applies the ring's maxLen backpressure: pre-buffer failures are the one +// promise source not bounded by the max-buffered admission, so a spin loop +// of failing produces - blocking Produce or TryProduce alike - could +// otherwise grow the ring without bound (#1194). Parking here is the +// deliberate trade: every accepted record costs memory until its promise +// runs and the promise is the only completion channel, so a caller outpacing +// the promise worker must be blocked, not absorbed. The one caller that can +// never park is the promise worker itself (a promise calling TryProduce with +// a record that fails pre-buffer); produce-from-promise is documented to +// spawn a goroutine, whose park is safe: the worker keeps draining and the +// goroutine proceeds when space frees. func (p *producer) promiseRecordBeforeBuf(pr promisedRec, err error) { - p.promiseBatch(batchPromise{recs: []promisedRec{pr}, beforeBuf: true, err: err}) + b := batchPromise{recs: []promisedRec{pr}, beforeBuf: true, err: err} + if first, _ := p.batchPromises.push(b); first { + go p.finishPromises(b) + } } func (p *producer) finishPromises(b batchPromise) { cl := p.cl var more bool var broadcast bool - defer func() { - if broadcast { - p.c.Broadcast() - } - }() start: for i, pr := range b.recs { pr.LeaderEpoch = -1 - if b.baseOffset == -1 { - // if the base offset is invalid/unknown (-1), all record offsets should - // be treated as unknown + if b.err != nil { + // Failed records carry unknown-sentinels, not the + // batchPromise zero values: without this, a failed + // record's offset was its index within the failed + // batch and its producer id/epoch were 0 - + // plausible-looking garbage. pr.Offset = -1 + pr.ProducerID = -1 + pr.ProducerEpoch = -1 } else { - pr.Offset = b.baseOffset + int64(i) + if b.baseOffset == -1 { + // if the base offset is invalid/unknown (-1), all record offsets should + // be treated as unknown + pr.Offset = -1 + } else { + pr.Offset = b.baseOffset + int64(i) + } + pr.ProducerID = b.pid + pr.ProducerEpoch = b.epoch + pr.Attrs = b.attrs } - pr.ProducerID = b.pid - pr.ProducerEpoch = b.epoch - pr.Attrs = b.attrs recBroadcast := cl.finishRecordPromise(pr, b.err, b.beforeBuf) broadcast = broadcast || recBroadcast } @@ -702,6 +802,28 @@ start: cl.prsPool.put(b.recs) } + // We broadcast per batch, not per record (waking blocked producers on + // every record forces tiny one-record batches; see ead18d3c) - but + // also not once per ring drain: while pre-buffer failure promises keep + // arriving from other goroutines, this loop never observes an empty + // ring and never exits, and a deferred-to-exit broadcast would starve + // a Flush whose condition (bufferedRecords == 0) became true mid-drain + // and blocked Produce calls whose space opened. + if broadcast { + if p.onBatchPromiseBroadcast != nil { + // The current (just-processed) element is still in the ring + // here, since dropPeek runs below; l > 1 thus means more + // elements are queued behind it and the broadcast is firing + // mid-drain rather than at ring exit. + p.batchPromises.mu.Lock() + moreQueued := p.batchPromises.l > 1 + p.batchPromises.mu.Unlock() + p.onBatchPromiseBroadcast(moreQueued) + } + p.c.Broadcast() + broadcast = false + } + b, more, _ = p.batchPromises.dropPeek() if more { goto start @@ -767,6 +889,18 @@ func (cl *Client) doPartition(parts *topicPartitions, partsData *topicPartitions mapping := partsData.writablePartitions if parts.partitioner.RequiresConsistency(pr.Record) { mapping = partsData.partitions + } else if len(mapping) == 0 && len(partsData.partitions) > 0 { + // Every partition has a retriable load error, e.g. a rolling + // restart of an RF=1 broker briefly left all partitions + // leaderless. Rather than failing the record up front with + // the synthetic error below, fall back to the full set: the + // record buffers and rides the normal metadata-refresh retry + // path, the same as records on consistency-requiring + // partitioners via the branch above. If the outage outlasts + // the delivery timeout or retry limits, the record fails + // with the partition's actual load error. The Java client + // falls back identically when no partition is available. + mapping = partsData.partitions } if len(mapping) == 0 { cl.producer.promiseRecord(pr, errors.New("unable to partition record due to no usable partitions")) @@ -846,7 +980,7 @@ type producerID struct { var errReloadProducerID = errors.New("producer id needs reloading") -// initProducerID initializes the client's producer ID for idempotent +// producerID returns, loading if necessary, the client's producer ID for idempotent // producing only (no transactions, which are more special). After the first // load, this clears all buffered unknown topics. func (cl *Client) producerID(ctxFn func() context.Context) (int64, int16, error) { @@ -997,7 +1131,21 @@ func (cl *Client) doInitProducerID(ctxFn func() context.Context, lastID int64, l if err != nil { return err } - return nil // resp.ErrorCode handled below + // We return ConcurrentTransactions so that our wrapping + // doWithConcurrentTransactions retries in place: the + // coordinator replies with it while still completing (or + // fence-aborting) a previous transaction for this + // transactional ID. Notably, taking over a crashed + // incarnation's ongoing transaction ALWAYS receives it at + // least once: the broker internally aborts the old + // transaction and tells us to retry. Surfacing the error + // instead would bubble a routine, transient condition up as a + // BeginTransaction failure. All other response error codes + // are classified below. + if err := kerr.ErrorForCode(resp.ErrorCode); errors.Is(err, kerr.ConcurrentTransactions) { + return err + } + return nil }) if err != nil { if errors.Is(err, errUnknownRequestKey) || errors.Is(err, errBrokerTooOld) { @@ -1046,47 +1194,68 @@ func (cl *Client) partitionsForTopicProduce(pr promisedRec) (*topicPartitions, * p := &cl.producer topic := pr.Topic - topics := p.topics.load() - parts, exists := topics[topic] - if exists { - if v := parts.load(); len(v.partitions) > 0 { - return parts, v + for { + topics := p.topics.load() + parts, exists := topics[topic] + if exists { + if v := parts.load(); len(v.partitions) > 0 { + return parts, v + } } - } - - if !exists { // topic did not exist: check again under mu and potentially create it - p.topicsMu.Lock() - defer p.topicsMu.Unlock() - if parts, exists = p.topics.load()[topic]; !exists { // update parts for below - // Before we store the new topic, we lock unknown - // topics to prevent a concurrent metadata update - // seeing our new topic before we are waiting from the - // addUnknownTopicRecord fn. Otherwise, we would wait - // and never be re-notified. - p.unknownTopicsMu.Lock() - defer p.unknownTopicsMu.Unlock() - - p.topics.storeTopics([]string{topic}) - cl.addUnknownTopicRecord(pr) - cl.triggerUpdateMetadataNow("forced load because we are producing to a topic for the first time") - return nil, nil + if !exists { // topic did not exist: check again under mu and potentially create it + p.topicsMu.Lock() + if _, exists = p.topics.load()[topic]; !exists { + // Before we store the new topic, we lock unknown + // topics to prevent a concurrent metadata update + // seeing our new topic before we are waiting from the + // addUnknownTopicRecord fn. Otherwise, we would wait + // and never be re-notified. + p.unknownTopicsMu.Lock() + p.topics.storeTopics([]string{topic}) + cl.addUnknownTopicRecord(pr) + cl.triggerUpdateMetadataNow("forced load because we are producing to a topic for the first time") + p.unknownTopicsMu.Unlock() + p.topicsMu.Unlock() + return nil, nil + } + p.topicsMu.Unlock() } - } - // Here, the topic existed, but maybe has not loaded partitions yet. We - // have to lock unknown topics first to ensure ordering just in case a - // load has not happened. - p.unknownTopicsMu.Lock() - defer p.unknownTopicsMu.Unlock() + // Here, the topic existed, but maybe has not loaded partitions + // yet. We have to lock unknown topics first to ensure ordering + // just in case a load has not happened. + p.unknownTopicsMu.Lock() + + // Re-resolve the topic now that we hold the mu. Both sides of + // the entry's lifecycle change only under unknownTopicsMu: + // storePartitionsUpdate stores loaded partitions before + // releasing it, and purgeTopics stores the topic's removal + // from p.topics before releasing it. Without the re-check we + // could add a waiter for a topic a concurrent purge already + // swept: the purge then removes the topic from p.topics, no + // metadata update ever requests it (the request set is built + // from p.topics), and the waiter - and its records - silently + // hang forever. Re-resolving from the current map (not the + // `parts` pointer loaded above) also covers a purge+recreate + // swapping the topicPartitions object in between. + parts, exists = p.topics.load()[topic] + if !exists { + // Purged between our load and the lock; retry from the + // top, which re-creates the topic properly. + p.unknownTopicsMu.Unlock() + continue + } + if v := parts.load(); len(v.partitions) > 0 { + p.unknownTopicsMu.Unlock() + return parts, v + } + cl.addUnknownTopicRecord(pr) + cl.triggerUpdateMetadata(false, "reload trigger due to produce topic still not known") + p.unknownTopicsMu.Unlock() - if v := parts.load(); len(v.partitions) > 0 { - return parts, v + return nil, nil // our record is buffered waiting for metadata update; nothing to return } - cl.addUnknownTopicRecord(pr) - cl.triggerUpdateMetadata(false, "reload trigger due to produce topic still not known") - - return nil, nil // our record is buffered waiting for metadata update; nothing to return } // addUnknownTopicRecord adds a record to a topic whose partitions are @@ -1107,7 +1276,11 @@ func (cl *Client) addUnknownTopicRecord(pr promisedRec) { } } -// waitUnknownTopic waits for a notification +// waitUnknownTopic waits for the topic to be resolved by a metadata update +// (the wait channel is closed, or receives retryable load errors that count +// toward the retry limits), or for the record/produce contexts, the client, +// the record timeout, or an abort (the fatal channel) to end the wait and +// fail all buffered records. func (cl *Client) waitUnknownTopic( pctx context.Context, // context passed to Produce rctx context.Context, // context on the record itself @@ -1154,7 +1327,11 @@ func (cl *Client) waitUnknownTopic( case err = <-unknown.fatal: case retryableErr, ok := <-unknown.wait: if !ok { - cl.cfg.logger.Log(LogLevelInfo, "done waiting for metadata for new topic", "topic", topic) + // The channel is closed when the topic's partitions + // load, but also when the topic is purged or all + // buffered records are failed; whoever closed it + // already handled the buffered records. + cl.cfg.logger.Log(LogLevelInfo, "done waiting on metadata for new topic", "topic", topic) return // metadata was successful! } cl.cfg.logger.Log(LogLevelInfo, "new topic metadata wait failed, retrying wait", "topic", topic, "err", retryableErr) @@ -1214,7 +1391,7 @@ func (cl *Client) unlingerDueToMaxRecsBuffered() { // If the context finishes (Done), this returns the context's error. // // This function is safe to call multiple times concurrently, and safe to call -// concurrent with Flush. +// concurrent with AbortBufferedRecords. func (cl *Client) Flush(ctx context.Context) error { p := &cl.producer diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/record_and_fetch.go b/vendor/github.com/twmb/franz-go/pkg/kgo/record_and_fetch.go index 2c0275b16d1..a1bb8e485e7 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/record_and_fetch.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/record_and_fetch.go @@ -655,17 +655,28 @@ func (fs Fetches) EachTopic(fn func(FetchTopic)) { return } + // A topic's partitions are led by different brokers, so the same topic + // is spread across multiple Fetch entries (one per broker response); we + // must carry the TopicID across them rather than zeroing it. The broker + // returns the same ID in every fetch response for the topic, so the + // first non-zero copy is authoritative. Without this, EachTopic returns + // a zero TopicID whenever more than one broker replied -- i.e. nearly + // always in a real cluster, yet never in a single-broker test. topics := make(map[string][]FetchPartition) + ids := make(map[string][16]byte) for _, fetch := range fs { for _, topic := range fetch.Topics { topics[topic.Topic] = append(topics[topic.Topic], topic.Partitions...) + if topic.TopicID != ([16]byte{}) { + ids[topic.Topic] = topic.TopicID + } } } for topic, partitions := range topics { fn(FetchTopic{ topic, - [16]byte{}, + ids[topic], partitions, }) } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/record_formatter.go b/vendor/github.com/twmb/franz-go/pkg/kgo/record_formatter.go index 59f9d75d82d..3747dd4dc3a 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/record_formatter.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/record_formatter.go @@ -84,7 +84,7 @@ func (f *RecordFormatter) AppendPartitionRecord(b []byte, p *FetchPartition, r * // %D share group delivery count (0 if not from a share group) // %A share group acquisition deadline (timestamp, 0 if not from a share group) // -// For AppendPartitionRecord, the formatter also undersands the following three +// For AppendPartitionRecord, the formatter also understands the following three // formatting options: // // %[ partition log start offset @@ -238,9 +238,7 @@ func NewRecordFormatter(layout string) (*RecordFormatter, error) { var f RecordFormatter var literal []byte // non-formatted raw text to output - var i int for len(layout) > 0 { - i++ c, size := utf8.DecodeRuneInString(layout) rawc := layout[:size] layout = layout[size:] @@ -777,7 +775,7 @@ func parseUnpack(layout string) (func([]byte, []byte) []byte, error) { islittle := little fns = append(fns, func(dst, src []byte) ([]byte, int) { if len(src) < need { - return append(dst, fmt.Sprintf("%%!%%s(have %d bytes, need %d)", len(src), need)...), len(src) + return append(dst, fmt.Sprintf("%%!(have %d bytes, need %d)", len(src), need)...), len(src) } var ul, ub uint64 @@ -1226,7 +1224,11 @@ func (r *RecordReader) parseReadLayout(layout string) error { switch escaped { default: - return fmt.Errorf("unknown percent escape sequence %q", layout[:1]) + // escaped is the verb byte; layout has already advanced past + // it (and past any '{'), so it can be empty here - slicing + // layout[:1] would panic for an unknown verb at the end of + // the layout (e.g. "%q"). + return fmt.Errorf("unknown percent escape sequence %q", string(escaped)) case 'T', 'K', 'V', 'H': var dst *uint64 @@ -1391,7 +1393,7 @@ func (r *RecordReader) parseReadLayout(layout string) error { inner(b, r) return nil }} - bit.set(bit) + bits.set(bit) if bits.has(bitSize) { if re != nil { return errors.New("cannot specify exact size and regular expression") @@ -1481,6 +1483,13 @@ func (r *RecordReader) parseReadLayout(layout string) error { reads = append(reads, fn) } } + // A layout consisting solely of noread verbs (fixed sizes/numbers like + // "%p{3}") never consumes input, so next() never reaches an EOF, never + // sets r.done, and ReadRecord returns identical records forever. Reject + // it at construction rather than looping at read time. + if len(reads) == 0 { + return errors.New("RecordReader: layout reads nothing from the input") + } r.fns = make([]readParse, 0, len(noreads)+len(reads)) r.fns = append(r.fns, noreads...) r.fns = append(r.fns, reads...) @@ -1767,6 +1776,20 @@ func (r *RecordReader) next(rec *Record) error { continue } + // If the input EOF'd before a fixed-size read accumulated its full + // byte count, r.buf is short. This happens on the fall-through + // above: a zero-byte read surfaces as plain io.EOF (readSize only + // reports io.EOF when it read nothing; a partial read is already + // io.ErrUnexpectedEOF), and if that read is the last fn after an + // earlier real read it is not the clean record boundary, so it + // reaches here with an empty buffer. The fixed-width number parsers + // index r.buf at constant offsets (binary.*.Uint64 etc.) and panic + // on a short slice, so surface the truncation as the unexpected EOF + // that ReadRecord's doc already promises for a mid-record EOF. + if fn.read.size > 0 && len(r.buf) < fn.read.size { + return io.ErrUnexpectedEOF + } + if err := fn.parse(r.buf, rec); err != nil { return err } @@ -1837,10 +1860,34 @@ func (r *RecordReader) readRe(re *regexp.Regexp) error { } func (r *RecordReader) readSize(n int) error { - r.buf = append(r.buf, make([]byte, n)...) - n, err := io.ReadFull(r.r, r.buf) - r.buf = r.buf[:n] - return err + if n < 0 { + // A size verb (%T/%K/%V) reads its value from the input as a + // uint64; converting to int can wrap negative for values above + // math.MaxInt64. Reject rather than panicking in make below. + return fmt.Errorf("invalid negative read size %d", n) + } + // Read in bounded chunks rather than pre-allocating n bytes up front: + // a hostile or corrupt size verb can claim a huge length that would + // OOM the process before io.ReadFull notices the input is short. The + // caller resets r.buf to empty before invoking us, so we accumulate + // from index 0. + const chunk = 64 << 10 + for len(r.buf) < n { + start := len(r.buf) + r.buf = append(r.buf, make([]byte, min(n-start, chunk))...) + nn, err := io.ReadFull(r.r, r.buf[start:]) + r.buf = r.buf[:start+nn] + if err != nil { + // io.ReadFull reports EOF only when it read zero bytes of + // this chunk; if we have already accumulated bytes for this + // field the value is truncated, which is an unexpected EOF. + if err == io.EOF && len(r.buf) > 0 { + err = io.ErrUnexpectedEOF + } + return err + } + } + return nil } func (r *RecordReader) readExact(d []byte) error { @@ -2263,7 +2310,10 @@ func parseLayoutSlash(layout string) (byte, int, error) { return 0, 0, errors.New("invalid non-terminated hex escape sequence at end of delim string") } hex := layout[1:3] - n, err := strconv.ParseInt(hex, 16, 8) + // A \xNN escape names the byte with hex value NN, i.e. the full + // [0, 255] range. ParseInt with bitSize 8 caps at 0x7f and + // rejected 0x80-0xff; ParseUint with bitSize 8 accepts [0, 255]. + n, err := strconv.ParseUint(hex, 16, 8) if err != nil { return 0, 0, fmt.Errorf("unable to parse hex escape sequence %q: %v", hex, err) } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/ring.go b/vendor/github.com/twmb/franz-go/pkg/kgo/ring.go index 9aad112547b..31a4d4485d3 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/ring.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/ring.go @@ -65,13 +65,43 @@ func (r *ring[T]) die() { } } +// empty returns whether the ring currently holds no elements. Because an +// element being processed stays in the ring until dropPeek removes it, +// empty also means no worker goroutine is mid-element. +func (r *ring[T]) empty() bool { + r.mu.Lock() + defer r.mu.Unlock() + return r.l == 0 +} + func (r *ring[T]) push(elem T) (first, dead bool) { + return r.doPush(elem, true) +} + +// pushForce pushes even when the ring is at maxLen. The maxLen wait can only +// be used by pushers that do not deadlock against the ring's worker: the +// worker is the only goroutine that signals space (dropPeek), and a push +// made while holding a client lock (purge/fail paths, storePartitionsUpdate, +// recBuf failure paths) would park holding a lock the worker can need +// through a user promise re-entering the client - the worker then waits on +// the lock while the lock holder waits on the worker. Those internal pushers +// force. Forcing does not unbound the ring: every record an internal push +// carries was already admitted under the max-buffered-records accounting, so +// forced volume is capped by that admission; only produce-entry failure +// pushes (the unbounded source) take the blocking push. +func (r *ring[T]) pushForce(elem T) (first, dead bool) { + return r.doPush(elem, false) +} + +func (r *ring[T]) doPush(elem T, wait bool) (first, dead bool) { r.mu.Lock() defer r.mu.Unlock() // If a max length is set, block until there's space. - for r.maxLen > 0 && r.l >= r.maxLen && !r.dead { - r.cond.Wait() + if wait { + for r.maxLen > 0 && r.l >= r.maxLen && !r.dead { + r.cond.Wait() + } } if r.dead { diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/sink.go b/vendor/github.com/twmb/franz-go/pkg/kgo/sink.go index 29099f6ce15..df3a1543a78 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/sink.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/sink.go @@ -31,9 +31,9 @@ type sink struct { drainState workLoop - // seqRespsMu, guarded by seqRespsMu, contains responses that must - // be handled sequentially. These responses are handled asynchronously, - // but sequentially. + // seqResps contains responses that must be handled sequentially: the + // ring preserves issue order, and its single transient worker handles + // responses asynchronously but in that order. seqResps ring[*seqResp] // we never call die() on it backoffMu xsync.Mutex // guards the following @@ -461,10 +461,14 @@ func (s *sink) produce(sem <-chan struct{}) bool { // records for a new transaction. Any records in the request are // from the current transaction at epoch N, which is correct. // - // This undo is safe: resetBatchDrainIdx + decInflight rewind - // each recBuf to its pre-drain state, the existing defer releases - // the semaphore (produced is still false), and returning true - // retries produce() with the correct epoch. + // This undo is safe: undoStagedBatches rewinds each recBuf to its + // pre-drain state -- drain index, inflight, and (for any partition + // this createReq newly added to the transaction) the addedToTxn flag, + // so the next drain re-issues its AddPartitionsToTxn instead of + // producing to a partition the broker never learned is in the txn (see + // undoStagedBatches). The existing defer releases the semaphore + // (produced is still false), and returning true retries produce() with + // the correct epoch. // // We use a raw atomic load rather than producerID() to avoid // side effects (blocking on idMu, triggering InitProducerID @@ -491,10 +495,7 @@ func (s *sink) produce(sem <-chan struct{}) bool { // unchanged, so we bail and the next drain pulls the reloaded // (id, epoch) with seq=0 consistently. if cur := s.cl.producer.id.Load().(*producerID); cur.id != id || cur.epoch != epoch || cur.err != nil { - req.batches.sliced().eachOwnerLocked(func(b *recBatch) { - b.owner.resetBatchDrainIdx() - b.decInflight() - }) + req.undoStagedBatches(txnReq) return true } @@ -510,18 +511,30 @@ func (s *sink) produce(sem <-chan struct{}) bool { batchesStripped, err := s.doTxnReq(req, txnReq) if err != nil { switch { - case errors.Is(err, kerr.TransactionAbortable): - // If we get TransactionAbortable, we continue into producing. - // The produce will fail with the same error, and this is the - // only way to notify the user to abort the txn. case isRetryableBrokerErr(err) || isDialNonTimeoutErr(err): s.cl.bumpRepeatedLoadErr(err) s.cl.cfg.logger.Log(LogLevelWarn, "unable to AddPartitionsToTxn due to retryable broker err, bumping client's buffered record load errors by 1 and retrying", "err", err) s.cl.triggerUpdateMetadata(false, "attempting to refresh broker list due to failed AddPartitionsToTxn requests") return moreToDrain || len(req.batches.bs) > 0 // nothing stripped if request-issuing error default: - // Note that err can be InvalidProducerEpoch, which is - // potentially recoverable in EndTransaction. + // This includes TransactionAbortable. We used to + // continue into producing on TransactionAbortable so + // the produce failure would carry the error to the + // user, but doTxnReq's error path has already + // requeued every batch in the request (reset drain + // indexes, decremented inflight, and un-marked + // addedToTxn for the partitions whose add actually + // failed): producing those batches anyway would + // decrement inflight a second time (wrapping the + // counter and permanently wedging the recBuf's + // drain gate) and could re-drain batches that are + // already in flight. Failing the producer ID delivers + // the same error to all buffered records on the next + // drain, and TransactionAbortable remains recoverable + // via EndTransaction. + // + // Note that err can also be InvalidProducerEpoch, + // which is potentially recoverable in EndTransaction. // // We do not fail all buffered records here, // because that can lead to undesirable behavior @@ -574,9 +587,10 @@ func (s *sink) doSequenced( // We can NOT use any record context. If we do, we force the request to // fail while also force the batch to be unfailable (due to no - // response). If and only if the user has disabled idempotency, we - // allow the user to cancel the request via some random record with a - // canceling context. + // response). Only if the user has disabled idempotency or opted into + // AllowIdempotentProduceCancellation do we allow canceling the request + // via some random record with a canceling context (createReq only + // sets firstCancelingCtx under those options). ctx := req.firstCancelingCtx if ctx == nil { ctx = s.cl.ctx @@ -618,14 +632,20 @@ func (s *sink) doTxnReq( req *produceRequest, txnReq *kmsg.AddPartitionsToTxnRequest, ) (stripped bool, err error) { - // If we return an unretryable error, then we have to reset everything - // to not be in the transaction and begin draining at the start. + // If we return an unretryable error, every batch in this request must + // be requeued and any partition this request newly added to the + // transaction must be un-marked, since we will not issue the produce + // request. undoStagedBatches scopes the un-marking to txnReq so a + // partition added by an EARLIER AddPartitionsToTxn of this transaction + // (a broker-acked fact, deliberately absent here) keeps its membership; + // clearing it would make EndTransaction's anyAdded walk skip EndTxn and + // strand the broker-side transaction until its timeout abort. // // These batches must be the first in their recBuf, because we would // not be trying to add them to a partition if they were not. defer func() { if err != nil { - req.batches.eachOwnerLocked(seqRecBatch.removeFromTxn) + req.undoStagedBatches(txnReq) } }() // We do NOT let record context cancelations fail this request: doing @@ -633,6 +653,12 @@ func (s *sink) doTxnReq( // similar to the warning we give in the txn.go file, but the // difference there is the user knows explicitly at the function call // that canceling the context will opt them into invalid state. + // + // Note that the concurrent-transactions wrapper is defensive only: + // AddPartitionsToTxn is pinned at most v3 (no top-level error code) + // and a per-partition CONCURRENT_TRANSACTIONS is retriable, so it is + // stripped in issueTxnReq and healed by requeue+backoff rather than + // ever surfacing to the wrapper. err = s.cl.doWithConcurrentTransactions(s.cl.ctx, fmt.Sprintf("AddPartitionsToTxn-sink%d", s.nodeID), func() error { stripped, err = s.issueTxnReq(req, txnReq) return err @@ -640,6 +666,54 @@ func (s *sink) doTxnReq( return stripped, err } +// txnReqContains returns whether the AddPartitionsToTxn request contains the +// topic and partition. Partitions already in the transaction from an earlier +// request are deliberately absent (see txnReqBuilder.add); failure handling +// and response processing must not touch their addedToTxn state. +func txnReqContains(txnReq *kmsg.AddPartitionsToTxnRequest, topic string, partition int32) bool { + for i := range txnReq.Topics { + t := &txnReq.Topics[i] + if t.Topic != topic { + continue + } + for _, p := range t.Partitions { + if p == partition { + return true + } + } + } + return false +} + +// undoStagedBatches rewinds every batch that createReq staged into this request +// back to its pre-drain state, for the early-return arms that decide not to +// issue the request after staging it: the producer-ID/epoch recheck in +// produce() and doTxnReq's failure defer. It resets each recBuf's drain index +// and decrements inflight, and -- for the partitions THIS request newly added +// to the transaction -- clears addedToTxn so the next drain re-issues their +// AddPartitionsToTxn. +// +// txnReq holds exactly the partitions createReq newly added: txnReqBuilder.add +// only records a partition whose addedToTxn flipped false->true, so partitions +// added to the transaction by an EARLIER request are deliberately absent and +// keep their broker-acked membership. Leaving a newly-added partition's +// addedToTxn set after rewinding would suppress its AddPartitionsToTxn on the +// next drain (txnReqBuilder.add skips already-added partitions); the broker +// then rejects the produce to that unverified partition with INVALID_TXN_STATE +// (or, on a non-verifying broker, the records hang in a transaction the +// coordinator never learned the partition belongs to). txnReq is nil for +// non-transactional and pv12+ (KIP-890p2) producers, which never stage +// addedToTxn in createReq, so the clear is correctly skipped for them. +func (p *produceRequest) undoStagedBatches(txnReq *kmsg.AddPartitionsToTxnRequest) { + p.batches.eachOwnerLocked(func(batch seqRecBatch) { + if txnReq != nil && txnReqContains(txnReq, batch.owner.topic, batch.owner.partition) { + batch.owner.addedToTxn.Store(false) + } + batch.owner.resetBatchDrainIdx() + batch.decInflight() + }) +} + // Removing a batch from the transaction means we will not be issuing it // inflight, and that it was not added to the txn and that we need to reset the // drain index. @@ -665,7 +739,24 @@ func (s *sink) issueTxnReq( continue } for _, partition := range topic.Partitions { - if err := kerr.ErrorForCode(partition.ErrorCode); err != nil && err != kerr.TransactionAbortable { // see below for txn abortable + // TransactionAbortable partitions are deliberately NOT + // handled as errors here: the batch stays in the request, + // the subsequent produce fails with the same abortable + // error, and the record promises carry it to the user (who + // then aborts; recovery happens via EndTransaction). + if err := kerr.ErrorForCode(partition.ErrorCode); err != nil && err != kerr.TransactionAbortable { + // An errored partition that we did not ask to add must + // not strip a batch nor fail the producer ID: it could + // name a partition added by an earlier request of this + // transaction (deliberately absent from this txnReq), + // and un-marking that would break EndTransaction's + // anyAdded accounting -- see doTxnReq's deferred + // failure handling. + if !txnReqContains(txnReq, topic.Topic, partition.Partition) { + s.cl.cfg.logger.Log(LogLevelError, "broker replied with errored partition in AddPartitionsToTxnResponse that was not in the request", "topic", topic.Topic, "partition", partition.Partition) + continue + } + // OperationNotAttempted is set for all partitions that are authorized // if any partition is unauthorized _or_ does not exist. We simply remove // unattempted partitions and treat them as retryable. @@ -821,11 +912,18 @@ func (s *sink) handleReqResp(br *broker, req *produceRequest, resp kmsg.Response rt := &kresp.Topics[i] topic := rt.Topic tid := rt.TopicID + // For topics (and partitions below) that we did not produce to, + // we deliberately do NOT touch req.metrics: metrics entries only + // exist for batches that were actually appended to the request, + // so a genuinely invented entry has nothing to remove -- and a + // DUPLICATED reply entry lands here too (the first occurrence + // empties req.batches), where deleting would erase the metrics + // of a batch the first occurrence legitimately processed and + // silently skip its OnProduceBatchWritten hook. if req.version >= 13 { var ok bool if topic, ok = req.batches.id2t[rt.TopicID]; !ok { - s.cl.cfg.logger.Log(LogLevelError, "broker erroneously replied with topic id in produce request that we did not produce to", "broker", logID(s.nodeID), "topic", topic, "topic_id", strtid(rt.TopicID)) - delete(req.metrics, topic) + s.cl.cfg.logger.Log(LogLevelError, "broker erroneously replied with topic id in produce request that we did not produce to", "broker", logID(s.nodeID), "topic_id", strtid(rt.TopicID)) continue } } else { @@ -834,7 +932,6 @@ func (s *sink) handleReqResp(br *broker, req *produceRequest, resp kmsg.Response partitions, ok := req.batches.bs[topic] if !ok { s.cl.cfg.logger.Log(LogLevelError, "broker erroneously replied with topic in produce request that we did not produce to", "broker", logID(s.nodeID), "topic", topic) - delete(req.metrics, topic) continue } @@ -849,8 +946,7 @@ func (s *sink) handleReqResp(br *broker, req *produceRequest, resp kmsg.Response batch, ok := partitions[partition] if !ok { s.cl.cfg.logger.Log(LogLevelError, "broker erroneously replied with partition in produce request that we did not produce to", "broker", logID(s.nodeID), "topic", rt.Topic, "partition", partition) - delete(tmetrics, partition) - continue // should not hit this + continue // should not hit this; see the topic-level comment above for why tmetrics is left alone } delete(partitions, partition) @@ -1420,7 +1516,13 @@ type recBuf struct { // this recBuf. Every time this hits zero, if the batchDrainIdx is not // at the end, we clear inflightOnSink and trigger the *current* sink // to drain. - inflight uint8 + // + // This is bounded by the sink's inflight sem: 1 or 4 when idempotent, + // or the user's MaxProduceRequestsInflightPerBroker (no upper bound) + // when idempotency is disabled -- which is why this is an int32 and + // not a small type that a large user value could wrap, breaking the + // != 0 drain gates here and in createReq. + inflight int32 lastAckedOffset int64 // last ProduceResponse's BaseOffset + how many records we produced @@ -1509,6 +1611,27 @@ func (recBuf *recBuf) bufferRecord(pr promisedRec, abortOnNewBatch bool) bool { return true } + // If the client is closing, fail the record rather than buffering it + // into a recBuf whose sink drain loop has already exited. close() cancels + // cl.ctx and then sweeps every recBuf exactly once via + // failBufferedRecords; a record buffered after that sweep would never be + // failed - its promise would never fire, BufferedProduceRecords would + // never return to zero, and a later Flush would hang - contradicting the + // documented ErrClientClosed contract ("for producing, records are failed + // with this error"). Checking cl.ctx under recBuf.mu (held here and by + // failAllRecords) is race-free given the close ordering (ctxCancel then + // sweep): we either observe the cancel and fail here, or we buffer before + // the sweep and the sweep fails us. The unknown-topic sibling path already + // honors this via waitUnknownTopic's cl.ctx.Done arm; this is the missing + // guard on the known-topic sibling. We select on Done rather than calling + // Err to keep this per-record hot path free of the context's per-call mutex. + select { + case <-recBuf.cl.ctx.Done(): + recBuf.cl.producer.promiseRecord(pr, ErrClientClosed) + return true + default: + } + var ( mkNewBatch = true produceVersion = recBuf.sink.produceVersion.Load() @@ -1604,9 +1727,11 @@ func (recBuf *recBuf) unlingerAndManuallyDrain() { // load errors during metadata updates. // // Partition load errors are generally temporary (leader/listener/replica not -// available), and this try bump is not expected to do much. If for some reason -// a partition errors for a long time and we are not idempotent, this function -// drops all buffered records. +// available, or a metadata response from an out of date broker that is +// missing a partition we know about), and this try bump is not expected to do +// much. Records are failed only once a bound trips: the record timeout or +// retry limit, or for unknown-partition style errors (including a metadata +// response missing the partition), the unknown fail limit. func (recBuf *recBuf) bumpRepeatedLoadErr(err error) { recBuf.mu.Lock() defer recBuf.mu.Unlock() @@ -1624,10 +1749,10 @@ func (recBuf *recBuf) bumpRepeatedLoadErr(err error) { canFail = !recBuf.cl.idempotent() || recBuf.cl.cfg.allowIdempotentProduceCancellation || (batch0.canFailFromLoadErrs && !batch0.unsureIfProduced) // we can only fail if we are not idempotent, cancellation is allowed, or if we have no outstanding requests batch0Fail = batch0.maybeFailErr(&recBuf.cl.cfg) != nil // timeout, retries, or aborting netErr = isRetryableBrokerErr(err) || isDialNonTimeoutErr(err) // we can fail if this is *not* a network error - retryableKerr = kerr.IsRetriable(err) // we fail if this is not a retryable kerr, - isUnknownLimit = recBuf.checkUnknownFailLimit(err) // or if it is, but it is UnknownTopicOrPartition and we are at our limit + retryableErr = kerr.IsRetriable(err) || errors.Is(err, errMissingMetadataPartition) // we fail if this is not a retryable error (missing-metadata-partition retries like unknown topic), + isUnknownLimit = recBuf.checkUnknownFailLimit(err) // or if it is, but it is an unknown topic error and we are at our limit - willFail = canFail && (batch0Fail || !netErr && (!retryableKerr || retryableKerr && isUnknownLimit)) + willFail = canFail && (batch0Fail || !netErr && (!retryableErr || retryableErr && isUnknownLimit)) ) batch0.isFailingFromLoadErr = willFail batch0.mu.Unlock() @@ -1640,7 +1765,7 @@ func (recBuf *recBuf) bumpRepeatedLoadErr(err error) { "can_fail", canFail, "batch0_should_fail", batch0Fail, "is_network_err", netErr, - "is_retryable_kerr", retryableKerr, + "is_retryable_err", retryableErr, "is_unknown_limit", isUnknownLimit, "will_fail", willFail, ) @@ -1650,13 +1775,20 @@ func (recBuf *recBuf) bumpRepeatedLoadErr(err error) { } } -// Called locked, if err is an unknown error, bumps our limit, otherwise resets -// it. This returns if we have reached or exceeded the limit. +// Called locked. A successful produce (nil err) resets the count; an unknown +// topic error bumps it; any other error leaves it unchanged -- resetting only +// on success is what keeps interleaved errors (e.g. an alternating +// NOT_LEADER_FOR_PARTITION) from holding the count below the limit forever. +// Three errors count: UNKNOWN_TOPIC_OR_PARTITION, UNKNOWN_TOPIC_ID (a deleted- +// and-recreated topic returns it until the user purges and re-adds, since +// produce v13+ keys topics by ID), and the metadata-side +// errMissingMetadataPartition twin. Returns whether we have exceeded the limit. func (recBuf *recBuf) checkUnknownFailLimit(err error) bool { - if errors.Is(err, kerr.UnknownTopicOrPartition) { - recBuf.unknownFailures++ - } else { + switch { + case err == nil: recBuf.unknownFailures = 0 + case errors.Is(err, kerr.UnknownTopicOrPartition) || errors.Is(err, kerr.UnknownTopicID) || errors.Is(err, errMissingMetadataPartition): + recBuf.unknownFailures++ } return recBuf.cl.cfg.maxUnknownFailures >= 0 && recBuf.unknownFailures > recBuf.cl.cfg.maxUnknownFailures } @@ -1918,7 +2050,7 @@ type produceRequest struct { timeout int32 batches seqRecBatches - firstCancelingCtx context.Context // of all batches added, the first one with a record that has a canceling context; only used with disableIdempotency + firstCancelingCtx context.Context // of all batches added, the first one with a record that has a canceling context; only used with disableIdempotency or allowIdempotentProduceCancellation producerID int64 producerEpoch int16 diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/source.go b/vendor/github.com/twmb/franz-go/pkg/kgo/source.go index 4266cbea2d5..458247cc038 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/source.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/source.go @@ -29,7 +29,7 @@ type readerFrom interface { // another fetch in the background. type source struct { cl *Client // our owning client, for cfg, metadata triggering, context, etc. - nodeID int32 // the node ID of the broker this sink belongs to + nodeID int32 // the node ID of the broker this source belongs to // Tracks how many _failed_ fetch requests we have in a row (unable to // receive a response). Any response, even responses with an ErrorCode @@ -117,7 +117,17 @@ func (s *source) removeCursor(rm *cursor) { // cursor is where we are consuming from for an individual partition. type cursor struct { - topic string + topic string + // topicID is written once at cursor creation and is deliberately + // never re-adopted if a delete+recreate hands back a new ID for the + // same name: a recreated topic stalls loudly (UNKNOWN_TOPIC_ID, see + // the UnknownTopicID arm below) and the user must purge+re-add. This + // is the principled alternative to librdkafka/Java's adopt-and-gamble; + // issue #908 records why auto-adoption was backed out (PR #391/#377: + // OffsetForLeaderEpoch has no TopicID field, so an adopted ID cannot + // be validated against truncation). The metadata merge copies this + // pointer over rather than swapping the ID; do not "fix" the stall + // into an adopt without solving #908. topicID [16]byte partition int32 @@ -297,7 +307,25 @@ func (p *cursorOffsetPreferred) move() { c.source.cl.sinksAndSourcesMu.Unlock() if !exists { + // The preferred replica is a broker we have not yet learned from + // metadata - e.g. a freshly added replica that the broker we + // fetched from already knows about, before our periodic refresh + // caught up. We force a metadata update so the source comes to + // exist for a future move, but we must ALSO re-enable the cursor + // on its current (leader) source. The caller (source.fetch) deletes + // this cursor from the request's used offsets right after we return, + // so neither the fetch's used-offset finishing nor a later buffered + // poll will re-enable it: leaving it unusable here would strand the + // partition. The leader is unchanged, so no cursor + // migration re-enables it, and a metadata refresh that merely + // learns the new broker never touches cursor usability - the + // partition would silently never be consumed again until an + // unrelated session restart (rebalance, assign, leader change). + // + // Re-enabling on the current source keeps us consuming from the + // leader until a later fetch's preferred replica can be honored. c.source.cl.triggerUpdateMetadataNow("cursor moving to a different broker that is not yet known") + c.allowUsable() return } @@ -1011,13 +1039,21 @@ func (s *source) fetch(consumerSession *consumerSession, doneFetch chan<- bool) return fetched default: - // Any other top-level error is unexpected: current brokers - // only emit session-related codes here. Rather than bumping - // the session epoch against a failed request, reset defensively - // so the next request re-establishes state the broker agrees - // with. - s.cl.cfg.logger.Log(LogLevelWarn, "fetch response has unexpected top-level error, resetting session", "broker", logID(s.nodeID), "err", err) - s.session.reset() + // Any other top-level error is unexpected: current brokers only + // emit session-related codes here, and every one of those arms + // above self-heals in a single round-trip (a reset re-establishes + // the session at epoch 0, which the broker then accepts). An + // unexpected code has no such bounded heal: a non-conformant or + // future broker that returns one persistently would spin this + // fetch at round-trip pace, re-logging on every iteration, because + // nothing here paces the loop. Back off rather than bumping the + // session epoch against a failed request; backoff also resets the + // session defensively so the next request re-establishes state the + // broker agrees with. This mirrors the transport-error and + // all-partitions-stripped paths, and the share fetch loop's + // top-level-error arm. + s.cl.cfg.logger.Log(LogLevelWarn, "fetch response has unexpected top-level error, resetting session and backing off", "broker", logID(s.nodeID), "err", err) + backoff(err) return fetched } @@ -1096,6 +1132,15 @@ func (s *source) handleReqResp(br *broker, req *fetchRequest, resp *kmsg.FetchRe numErrsStripped int kip320 = s.cl.supportsOffsetForLeaderEpoch() kmove kip951move + // seen guards against a broker returning the same partition (or the + // same topic) more than once in a single fetch response. Each + // requested partition maps to one stable *cursorOffsetNext for the + // life of the request; processing one twice would double-advance its + // offset / double-append its records, or enqueue two move()s for one + // cursor (the #1167 concurrent-source hazard). We must not dedup by + // deleting from req.usedOffsets - that map re-enables the cursor + // after the response - so we track seen pointers separately. + seen map[*cursorOffsetNext]struct{} ) defer kmove.maybeBeginMove(s.cl) @@ -1145,6 +1190,18 @@ func (s *source) handleReqResp(br *broker, req *fetchRequest, resp *kmsg.FetchRe ) continue } + if _, dup := seen[partOffset]; dup { + s.cl.cfg.logger.Log(LogLevelWarn, "broker returned a duplicate partition in a fetch response, ignoring the duplicate", + "broker", logID(s.nodeID), + "topic", topic, + "partition", partition, + ) + continue + } + if seen == nil { + seen = make(map[*cursorOffsetNext]struct{}, req.numOffsets) + } + seen[partOffset] = struct{}{} c := partOffset.from // If we are fetching from the replica already, Kafka replies with a -1 @@ -1496,7 +1553,13 @@ func ProcessFetchPartition(o ProcessFetchPartitionOpts, rp *kmsg.FetchResponseTo offset := int64(binary.BigEndian.Uint64(in)) length = int32(binary.BigEndian.Uint32(in[8:])) length += 12 // for the int64 offset we skipped and int32 length field itself - if len(in) < int(length) { + // length is read as a signed int32: a high-bit-set length field (or a + // near-MaxInt32 one, which overflows negative once we add 12) is + // negative and would slip past the truncation check below, panicking + // check()'s in[:length] with a negative bound. Treat a negative length + // as an untrustworthy/truncated batch and stop, matching the negative + // guards already in parseReadSize and the xerial decoder. + if length < 0 || len(in) < int(length) { break } @@ -1593,6 +1656,25 @@ func buildAborter(rp *kmsg.FetchResponseTopicPartition) aborter { for _, abort := range rp.AbortedTransactions { a[abort.ProducerID] = append(a[abort.ProducerID], abort.FirstOffset) } + // shouldAbortBatch and trackAbortedPID below both treat a[pid][0] as the + // smallest remaining aborted first offset for that producer: a batch is + // aborted once its FirstOffset reaches a[pid][0], and each abort marker + // pops a[pid][0]. The broker is NOT required to return a producer's aborted + // transactions sorted by first offset, though. Apache Kafka happens to (its + // transaction index is appended in last-offset order, which for one + // producer's strictly sequential transactions coincides with first-offset + // order), but Redpanda concatenates its newest in-memory aborted ranges + // (highest offsets) ahead of older on-disk snapshot ranges, so one + // producer's entries can arrive highest-first-offset first. With a[pid][0] + // not the smallest, a lower aborted transaction slips past the + // `FirstOffset < pidAborts[0]` guard and its records are surfaced to the + // application as committed - a read_committed violation. Sort each + // producer's first offsets ascending to restore the invariant the rest of + // the filtering relies on (the Java client makes the same guarantee with a + // first-offset-ordered priority queue). + for pid := range a { + slices.Sort(a[pid]) + } return a } @@ -1613,7 +1695,16 @@ func (a aborter) shouldAbortBatch(b *kmsg.RecordBatch) bool { } func (a aborter) trackAbortedPID(producerID int64) { - remaining := a[producerID][1:] + pidAborts := a[producerID] + if len(pidAborts) == 0 { + // Already exhausted for this PID. A well-formed response pops once + // per aborted transaction (one abort marker each), so this is only + // reachable from a buggy/hostile broker; reslicing a[producerID][1:] + // on the nil/empty slice would panic. Java removes the PID from a Set + // here, which is idempotent - mirror that. + return + } + remaining := pidAborts[1:] if len(remaining) == 0 { delete(a, producerID) } else { @@ -1691,6 +1782,24 @@ func (o *ProcessFetchPartitionOpts) processRecordBatch( uncompressedBytes := len(rawRecords) numRecords := int(batch.NumRecords) + // NumRecords is decoded straight off the wire and is therefore + // attacker/bug controlled. A negative count would panic the slice + // sizing below (ensureLen does s[:n], which panics for n<0); reject it + // as a corrupt batch, matching the Java client's InvalidRecordException + // guard (DefaultRecordBatch: "Found invalid record count"). A count + // larger than the available record bytes is likewise impossible for a + // well-formed batch - every record needs at least one byte - so clamp + // the up-front allocation to the byte count to keep a bogus huge count + // from driving a massive allocation. The true decodable count is + // recomputed by readRawRecordsInto, and the truncation defer below + // leaves the offset unadvanced whenever it disagrees with numRecords. + if numRecords < 0 { + fp.Err = fmt.Errorf("invalid record batch: negative record count %d", numRecords) + return 0, 0 + } + if numRecords > len(rawRecords) { + numRecords = len(rawRecords) + } var krecords []kmsg.Record var krecordsPool PoolKRecords pools(o.Pools).each(func(p Pool) bool { @@ -1746,8 +1855,10 @@ func (o *ProcessFetchPartitionOpts) processRecordBatch( } recordCtx := poolsCtx + var slabbed bool if o.shareAckSlab != nil && len(rrecords) > 0 { if slab := o.shareAckSlab(numRecords, &rrecords[0]); slab != nil { + slabbed = true parent := poolsCtx if parent == nil { parent = context.Background() @@ -1757,11 +1868,36 @@ func (o *ProcessFetchPartitionOpts) processRecordBatch( } var nkept int defer func() { - if p != nil && nkept > 0 { + if p == nil { + return + } + if nkept > 0 { p.n.Add(int64(nkept)) + return + } + // No record from this batch was kept: an aborted transaction's + // data batch, a control/marker batch, or a batch wholly below + // the requested offset. Nothing will ever call Recycle, so the + // recordPools put-back would never run and abort-heavy + // read_committed workloads would leak every pool Get. Release + // the pooled slices now, zeroing the written-then-discarded + // records like Recycle would have. Skip when a share-ack slab + // was created: the slab indexes rrecords by pointer, and putting + // the slice back would let the pool hand out memory the slab + // still references. + if slabbed { + return } + clear(p.recs) + p.release() }() + // A control batch ends at most one aborted transaction for its producer, + // so we pop the aborter at most once per batch. A well-formed control + // batch holds a single marker record; a buggy/hostile broker can pack many + // (and Java inspects only a control batch's first record), so without this + // guard a second abort marker would pop an already-empty aborter slice. + abortMarkerHandled := false for i := range krecords { record := &rrecords[i] recordToRecord( @@ -1777,12 +1913,13 @@ func (o *ProcessFetchPartitionOpts) processRecordBatch( nkept++ } - if abortBatch && record.Attrs.IsControl() { + if abortBatch && !abortMarkerHandled && record.Attrs.IsControl() { // A control record has a key and a value where the key // is int16 version and int16 type. Aborted records // have a type of 0. if key := record.Key; len(key) >= 4 && key[2] == 0 && key[3] == 0 { aborter.trackAbortedPID(batch.ProducerID) + abortMarkerHandled = true } } } @@ -1818,7 +1955,10 @@ out: for len(rawInner) > 17 { // magic at byte 17 length := int32(binary.BigEndian.Uint32(rawInner[8:])) length += 12 // offset and length fields - if len(rawInner) < int(length) { + // A negative length (high-bit-set length field, signed int32) would + // slip past the truncation check and panic rawInner[:length]; treat it + // as a truncated message set. See the record-batch loop's guard. + if length < 0 || len(rawInner) < int(length) { break } @@ -1931,7 +2071,10 @@ func (o *ProcessFetchPartitionOpts) processV0OuterMessage( for len(rawInner) > 17 { // magic at byte 17 length := int32(binary.BigEndian.Uint32(rawInner[8:])) length += 12 // offset and length fields - if len(rawInner) < int(length) { + // A negative length (high-bit-set length field, signed int32) would + // slip past the truncation check and panic rawInner[:length]; treat it + // as a truncated message set. See the record-batch loop's guard. + if length < 0 || len(rawInner) < int(length) { break // truncated batch } var m kmsg.MessageV0 @@ -2730,7 +2873,7 @@ func (s *source) removeShareCursor(c *shareCursor) { s.share.cursorsStart = 0 } s.share.mu.Unlock() - // We don't ned to wake the source to send this is a forgotten + // We don't need to wake the source to send this as a forgotten // partition, but it doesn't hurt. s.maybeShareConsume() } diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/topics_and_partitions.go b/vendor/github.com/twmb/franz-go/pkg/kgo/topics_and_partitions.go index 1fb5941996d..0eefc9be3f7 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/topics_and_partitions.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/topics_and_partitions.go @@ -657,9 +657,13 @@ func (old *topicPartition) migrateCursorTo( //nolint:revive // old/new naming ma // leader epoch on the new broker to see if we experienced data loss // before we can use this cursor. // - // Metadata ensures that leaderEpoch is non-negative only if the broker - // supports KIP-320. - if new.leaderEpoch != -1 && old.cursor.lastConsumedEpoch >= 0 { + // We can only validate against a real (non-negative) leader epoch. + // Metadata reports a non-negative epoch only if the broker supports + // KIP-320, and the metadata merge keeps our last known real epoch + // rather than ever migrating us to the -1 "no leader" sentinel (see + // mergeTopicPartitions), so a negative epoch here means we genuinely + // have nothing to validate against and must skip validation. + if new.leaderEpoch >= 0 && old.cursor.lastConsumedEpoch >= 0 { // Since the cursor consumed messages, it is definitely usable. // We use it so that the epoch load can finish using it // properly. @@ -681,6 +685,32 @@ func (old *topicPartition) migrateCursorTo( //nolint:revive // old/new naming ma func (tp *topicPartition) migrateShareCursorTo(cl *Client, new *topicPartition) { c := tp.shareCursor + new.shareCursor = c + + // Relocating the cursor between sources races the share consumer's + // leave. leave waits for every share worker to exit (sc.workers == 0), + // then drains each source's cursors via closeShareSession, iterating a + // snapshot of the source list taken after that barrier. A relocation that + // removes the cursor from its old source before that source is drained, + // and lands it on an already-drained source (or on one created after the + // snapshot), leaves the cursor's pending acks on a source nothing will + // drain: sc.pendingAcks never returns to 0 (FlushAcks hangs) and the held + // records release only via the broker's acquisition-lock timeout. + // + // Register the migration as a share worker so leave's barrier waits for an + // in-flight migration before it snapshots and drains. This mirrors + // applyMovesBlocking, the CurrentLeader-hint sibling that already does + // this; the metadata-merge path (this function) was the only share-cursor + // relocation not covered by the barrier. If the consumer is already dying, + // incWorker returns false: skip the swap and leave the cursor on its + // current source, which closeShareSession then drains. new.shareCursor is + // assigned above either way, so the stored partition data is always valid. + sc := cl.consumer.s + if !sc.incWorker() { + return + } + defer sc.decWorker() + cl.sinksAndSourcesMu.Lock() sns := cl.sinksAndSources[new.leader] cl.sinksAndSourcesMu.Unlock() @@ -689,7 +719,6 @@ func (tp *topicPartition) migrateShareCursorTo(cl *Client, new *topicPartition) } c.source.Store(sns.source) sns.source.addShareCursor(c) - new.shareCursor = c } type kip951move struct { @@ -907,8 +936,27 @@ func (k *kip951move) doMove(cl *Client) { // same (this allows easier injection of failures in local testing). A // higher epoch can come from a concurrent metadata update that // actually performed the move first. - modifyP := func(d *topicPartitionsData, partition int32, td topicPartitionData) (old, new *topicPartition, modified bool) { + // + // The hint was staged from a produce/fetch response and we are applied + // asynchronously: between staging and now, the user can purge the + // topic and re-add it (a produce or AddConsumeTopics recreates the + // topic with zero partitions until metadata loads), so the partition + // index can be out of range, and even in range the object at this + // index can belong to the new topic incarnation rather than the one + // whose response produced the hint. The owns check pins object + // identity: the records/cursor pointer is preserved across legitimate + // metadata updates and prior moves (the migrate functions copy it into + // the new topicPartition), so a mismatch can only mean purge+re-add - + // skip, and let the live incarnation resolve its own leader via + // metadata. + modifyP := func(d *topicPartitionsData, partition int32, td topicPartitionData, owns func(*topicPartition) bool) (old, new *topicPartition, modified bool) { + if int(partition) < 0 || int(partition) >= len(d.partitions) { + return nil, nil, false + } old = d.partitions[partition] + if !owns(old) { + return nil, nil, false + } if old.leaderEpoch > td.leaderEpoch { return nil, nil, false } @@ -959,7 +1007,7 @@ func (k *kip951move) doMove(cl *Client) { if !ok { continue // perhaps concurrently purged } - old, new, modified := modifyP(lr.r, recBuf.partition, td) + old, new, modified := modifyP(lr.r, recBuf.partition, td, func(tp *topicPartition) bool { return tp.records == recBuf }) if modified { cl.cfg.logger.Log(LogLevelInfo, "moving producing partition due to kip-951 not_leader_for_partition", "topic", recBuf.topic, @@ -990,7 +1038,7 @@ func (k *kip951move) doMove(cl *Client) { if !ok { continue // perhaps concurrently purged } - old, new, modified := modifyP(lr.r, cursor.partition, td) + old, new, modified := modifyP(lr.r, cursor.partition, td, func(tp *topicPartition) bool { return tp.cursor == cursor }) if modified { cl.cfg.logger.Log(LogLevelInfo, "moving consuming partition due to kip-951 not_leader_for_partition", "topic", cursor.topic, diff --git a/vendor/github.com/twmb/franz-go/pkg/kgo/txn.go b/vendor/github.com/twmb/franz-go/pkg/kgo/txn.go index 289777e25b4..b08f9ff603f 100644 --- a/vendor/github.com/twmb/franz-go/pkg/kgo/txn.go +++ b/vendor/github.com/twmb/franz-go/pkg/kgo/txn.go @@ -27,10 +27,6 @@ const ( // GroupTransactSession abstracts away the proper way to begin and end a // transaction when consuming in a group, modifying records, and producing // (EOS). -// -// If you are running Kafka 2.5+, it is strongly recommended that you also use -// RequireStableFetchOffsets. See that config option's documentation for more -// details. type GroupTransactSession struct { cl *Client @@ -65,9 +61,9 @@ type GroupTransactSession struct { // proper rebalance timeout, this single request will not fail and the commit // will succeed properly. // -// If this client detects you are talking to a pre-2.5 cluster, OR if you have -// not enabled RequireStableFetchOffsets, the client will sleep for 200ms after -// a successful commit to allow Kafka's txn markers to propagate. This is not +// If this client detects you are talking to a pre-2.5 cluster (one too old +// for KIP-447 stable fetch offsets), the client sleeps for 500ms after a +// successful commit to allow Kafka's txn markers to propagate. This is not // foolproof in the event of some extremely unlikely communication patterns and // **potentially** could allow duplicates. See this repo's transaction's doc // for more details. @@ -436,10 +432,11 @@ func (s *GroupTransactSession) End(ctx context.Context, commit TransactionEndTry // We have a few potential retryable errors from EndTransaction. // OperationNotAttempted will be returned at most once. // - // UnknownServerError should not be returned, but some brokers do: - // technically this is fatal, but there is no downside to retrying - // (even retrying a commit) and seeing if we are successful or if we - // get a better error. + // UnknownServerError should not be returned, but some brokers do + // (e.g. Redpanda in certain versions). It leaves the commit/abort + // unconfirmed: the broker may or may not have completed it. We + // retry as an abort (see the arm below) rather than reporting a + // commit we cannot confirm. var tries int retry: endTxnErr := s.cl.EndTransaction(ctx, TransactionEndTry(willTryCommit)) @@ -457,13 +454,20 @@ retry: goto retry case errors.Is(endTxnErr, kerr.UnknownServerError): - s.cl.cfg.logger.Log(LogLevelInfo, "end transaction with commit unknown server error; retrying") - after := time.NewTimer(s.cl.cfg.retryBackoff(tries)) - select { - case <-after.C: // context canceled; we will see when we retry - case <-s.cl.ctx.Done(): - after.Stop() - } + // We must downgrade to an abort exactly like the two arms + // above. EndTransaction already consumed inTxn on the + // erroring call, so re-calling it returns nil at its !inTxn + // guard without issuing another EndTxn: we cannot actually + // re-commit. If willTryCommit stayed true, that manufactured + // nil would fall into the "willTryCommit && endTxnErr == nil" + // success tail below and report a committed transaction, + // advancing the consumer offsets to postcommit even though the + // broker's UNKNOWN_SERVER_ERROR may have aborted it: a silent + // EOS data loss. Retrying as an abort reports not-committed and + // rewinds to the last committed offsets, so the caller + // reprocesses (at-least-once). + s.cl.cfg.logger.Log(LogLevelInfo, "end transaction returned an unknown server error; the commit is unconfirmed, retrying as abort to avoid reporting a false commit") + willTryCommit = false goto retry } } @@ -525,6 +529,7 @@ func (cl *Client) BeginTransaction() error { } cl.producer.inTxn = true + cl.producer.producedInTxn.Store(false) if !cl.producer.tx890p2.Load() && cl.supportsKIP890p2() { cl.producer.tx890p2.Store(true) } @@ -588,7 +593,7 @@ func (cl *Client) EndAndBeginTransaction( return cl.EndTransaction(ctx, commit) } -// AbortBufferedRecords fails all unflushed records with ErrAborted and waits +// AbortBufferedRecords fails all unflushed records with ErrAborting and waits // for there to be no buffered records. // // This accepts a context to quit the wait early, but quitting the wait may @@ -625,7 +630,7 @@ func (cl *Client) AbortBufferedRecords(ctx context.Context) error { return cl.Flush(ctx) } -// UnsafeAbortBufferedRecords fails all unflushed records with ErrAborted and +// UnsafeAbortBufferedRecords fails all unflushed records with ErrAborting and // waits for there to be no buffered records. This function does NOT wait for // any inflight produce requests to finish, meaning topics in the client may be // in an invalid state and producing to an invalid-state topic may cause the @@ -664,8 +669,9 @@ func (cl *Client) UnsafeAbortBufferedRecords() { // It may be possible for the client to recover in a new transaction via // BeginTransaction if an error is returned from this function: // -// - Before Kafka 4.0, InvalidProducerIDMapping and InvalidProducerEpoch -// are recoverable +// - When transactions are not running under KIP-890 part 2 (the cluster's +// transaction.version feature is below 2), InvalidProducerIDMapping and +// InvalidProducerEpoch are recoverable // - UnknownProducerID is recoverable for Kafka 2.5+ // - TransactionAbortable is always recoverable (after aborting) // @@ -692,12 +698,18 @@ func (cl *Client) EndTransaction(ctx context.Context, commit TransactionEndTry) // issues AddOffsetsToTxn, which internally adds a __consumer_offsets // partition to the transaction. Thus, if we added offsets, then we // also produced. - var anyAdded bool - if g := cl.consumer.g; g != nil { + var ( + anyAdded bool + addedSwapped []*recBuf // every addedToTxn we consume, restored if the commit is not attempted + offsetsWereAdded bool + ) + g := cl.consumer.g + if g != nil { // We do not lock because we expect commitTransactionOffsets to // be called *before* ending a transaction. if g.offsetsAddedToTxn { g.offsetsAddedToTxn = false + offsetsWereAdded = true anyAdded = true } } else { @@ -708,7 +720,10 @@ func (cl *Client) EndTransaction(ctx context.Context, commit TransactionEndTry) // addedToTxn to false outside of any mutex. for _, parts := range cl.producer.topics.load() { for _, part := range parts.load().partitions { - anyAdded = part.records.addedToTxn.Swap(false) || anyAdded + if part.records.addedToTxn.Swap(false) { + addedSwapped = append(addedSwapped, part.records) + anyAdded = true + } } } @@ -717,13 +732,52 @@ func (cl *Client) EndTransaction(ctx context.Context, commit TransactionEndTry) // Note that anyAdded is true if the producer ID was failed, meaning we will // get to the potential recovery logic below if necessary. if !anyAdded { - cl.cfg.logger.Log(LogLevelDebug, "no records were produced during the commit; thus no transaction was began; ending without doing anything") - return nil + // Under KIP-890 part 2, produce requests implicitly add their + // partition to the transaction on the broker BEFORE the data + // append; the registration is durable even if the append then + // fails, and we mark a partition added client-side only on a + // SUCCESSFUL produce response. If produces were attempted but + // none succeeded, the broker can have an ongoing transaction + // with registered partitions that only the transaction timeout + // would clear, and the next transaction's produces (same + // epoch, since no EndTxn bumped it) would silently join that + // ongoing transaction. Aborting is always legal under 890p2 + // (aborting an empty transaction succeeds and bumps the + // epoch), so abort regardless of what the caller asked: with + // zero successful produces and no committed offsets, there is + // nothing to commit anyway. + if !cl.producer.tx890p2.Load() || !cl.producer.producedInTxn.Load() { + cl.cfg.logger.Log(LogLevelDebug, "no records were produced during the commit; thus no transaction was began; ending without doing anything") + return nil + } + cl.cfg.logger.Log(LogLevelInfo, "no produce succeeded in this transaction but produces were attempted; issuing an abort to clear any server-side partition registrations", + "transactional_id", *cl.cfg.txnID, + ) + commit = TryAbort } id, epoch, err := cl.producerID(ctx2fn(ctx)) if err != nil { if commit { + // We are NOT attempting the commit: restore everything this + // call consumed (inTxn, addedToTxn, offsetsAddedToTxn). We + // document that the caller should retry with TryAbort, and + // that retry must still see the transaction state to issue + // the EndTxn abort; consuming the state here would turn the + // retry into a silent no-op that leaves the broker-side + // transaction ongoing (stalling read_committed consumers on + // the LSO) until the transaction timeout aborts it. + // producingTxn deliberately stays false: produces between + // the failed commit and the abort retry fail fast with + // errNotInTransaction rather than buffering against a + // failed producer ID. + for _, rb := range addedSwapped { + rb.addedToTxn.Store(true) + } + if offsetsWereAdded { + g.offsetsAddedToTxn = true + } + cl.producer.inTxn = true return kerr.OperationNotAttempted } @@ -847,11 +901,37 @@ func (cl *Client) maybeRecoverProducerID(ctx context.Context) (necessary, did bo return true, false, err } + if ke.Retriable { + // The stored failure is a retriable broker code, e.g. + // COORDINATOR_LOAD_IN_PROGRESS or NOT_COORDINATOR that + // outlived its internal retries, or CONCURRENT_TRANSACTIONS + // that outlived doWithConcurrentTransactions. These are + // transient load failures, not a fatal producer state: flag + // the ID for reload exactly like the transport-level failures + // above, rather than reporting "fatal, unrecoverable" for a + // condition that clears on its own. + cl.producer.id.Store(&producerID{ + id: id, + epoch: epoch, + err: errReloadProducerID, + }) + return true, true, nil + } + var recoverable bool - if cl.supportsKeyVersion(int16(kmsg.EndTxn), 5) { - // As of KIP-890 / Kafka 4.0, InvalidProducerIDMapping and + if cl.producer.tx890p2.Load() { + // Under KIP-890 part 2 (transaction.version=2 in effect for + // this client's transactions), InvalidProducerIDMapping and // InvalidProducerEpoch are NOT recoverable. Only // UnknownProducerID and TransactionAbortable are. + // + // We gate on the mode our transactions actually ran in, NOT + // on broker-advertised EndTxn versions: a 4.0+ broker + // advertises EndTxn v5 even while the cluster's + // transaction.version is still 0 or 1, and under those the + // cluster still operates the pre-890p2 semantics where the + // KIP-360/KIP-588 re-init below is the designed recovery + // (e.g. after a transaction-timeout abort bumped our epoch). recoverable = errors.Is(ke, kerr.UnknownProducerID) || errors.Is(ke, kerr.TransactionAbortable) } else { kip360 := cl.producer.idVersion >= 3 && (errors.Is(ke, kerr.UnknownProducerID) || errors.Is(ke, kerr.InvalidProducerIDMapping)) @@ -876,6 +956,31 @@ func (cl *Client) maybeRecoverProducerID(ctx context.Context) (necessary, did bo // If a transaction is begun too quickly after finishing an old transaction, // Kafka may still be finalizing its commit / abort and will return a // concurrent transactions error. We handle that by retrying for a bit. +// +// Constraints any change to EOS-under-coordinator-churn (here and in +// maybeRecoverProducerID / EndTransaction) must preserve — established by the +// txn-churn audit: +// +// 1. This wrapper / coordinator-retry division stays: the coordinator +// wrapper retries only coordinator-move codes; CONCURRENT_TRANSACTIONS +// loops belong to callers, ctx-bounded, because CT can legitimately last +// as long as a marker drain. Route CT recovery through this loop, not a +// second one. +// 2. anyAdded gating stays for TV1 — EndTxn on an EMPTY TV1 transaction is +// INVALID_TXN_STATE. The TV2 forced-abort-when-every-produce-failed path +// must stay TV2-only and attempted-only; idle Begin/End cycles stay +// wireless. +// 3. Producer-fenced means dead: no fix may add recovery for PRODUCER_FENCED +// from coordinator paths. Only the timeout-abort IPE-on-produce path is +// recoverable, and only under TV1 semantics. +// +// Two design-sized items remain deliberately NOT taken (would need their own +// round; until then docs + AbortingFirstErrPromise carry them): (a) +// commit-after-failed-produce — kgo commits whatever succeeded if the caller +// asks, unlike Java's abortable-state block, so changing it means tracking +// per-txn batch failures and changing End's contract; (b) TV2 feature +// downgrade mid-session (transaction.version 2=>1 while a client lives) — +// Java's per-EndTxn re-check is the reference shape if it ever bites. func (cl *Client) doWithConcurrentTransactions(ctx context.Context, name string, fn func() error) error { start := time.Now() tries := 0 @@ -885,20 +990,21 @@ start: err := fn() if errors.Is(err, kerr.ConcurrentTransactions) { // The longer we are stalled, the more we enforce a minimum - // backoff. + // backoff. Checks are ordered longest first; switch takes the + // first true case. since := time.Since(start) switch { - case since > time.Second: - if backoff < 200*time.Millisecond { - backoff = 200 * time.Millisecond + case since > 5*time.Second: + if backoff < time.Second { + backoff = time.Second } case since > 5*time.Second/2: if backoff < 500*time.Millisecond { backoff = 500 * time.Millisecond } - case since > 5*time.Second: - if backoff < time.Second { - backoff = time.Second + case since > time.Second: + if backoff < 200*time.Millisecond { + backoff = 200 * time.Millisecond } } @@ -1069,31 +1175,12 @@ func (g *groupConsumer) commitTxn(ctx context.Context, tx890p2 bool, req *kmsg.T } priorDone := g.commitDone - - // Unlike the non-txn consumer, we use the group context for - // transaction offset committing. We want to quit when the group is - // left, and we are not committing when leaving. We rely on proper - // usage of the GroupTransactSession API to issue commits, so there is - // no reason not to use the group context here. - commitCtx, commitCancel := context.WithCancel(g.ctx) // enable ours to be canceled and waited for commitDone := make(chan struct{}) - g.commitDone = commitDone - if ctx.Done() != nil { - go func() { - select { - case <-ctx.Done(): - commitCancel() - case <-commitCtx.Done(): - } - }() - } - go func() { defer close(commitDone) // allow future commits to continue when we are done - defer commitCancel() - if priorDone != nil { // wait for any prior request to finish + if priorDone != nil { // wait for any prior request to finish // Same as commit(): we must NOT cancel the prior commit // because canceling kills the TCP connection, and our // subsequent request on a new connection can be processed @@ -1108,7 +1195,14 @@ func (g *groupConsumer) commitTxn(ctx context.Context, tx890p2 bool, req *kmsg.T g.cl.cfg.logger.Log(LogLevelDebug, "issuing txn offset commit", "uncommitted", req) start := time.Now() - ctx := ctx // capture a local ctx variable; do not use the shared one that is concurrently read above + // The request rides the caller's context (the End context), + // not the group context: a transactional offset commit must + // not be canceled by group teardown midway, because canceling + // an in-flight request kills the connection and a replacement + // commit on a new connection can be reordered behind the + // canceled one by the broker. End documents that canceling + // ITS context risks an invalid state. + ctx := ctx if !tx890p2 { ctx = context.WithValue(ctx, ctxPinReq, &pinReq{pinMax: true, max: 4}) // v5 is only supported with KIP-890 part 2 } diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/clienttrace.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/clienttrace.go index 7b624649160..2ad6c7cc884 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/clienttrace.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/clienttrace.go @@ -63,8 +63,20 @@ func (fn clientTraceOptionFunc) apply(c *clientTracer) { } // WithoutSubSpans will modify the httptrace.ClientTrace to only collect data -// as Events and Attributes on a span found in the context. By default +// as Events and Attributes on a span found in the context. By default // sub-spans will be generated. +// +// This option is recommended for services that make a large number of +// outbound HTTP requests per incoming request (e.g., API gateways, +// fan-out proxies, or GraphQL servers). Each outbound request creates +// up to 7 sub-spans (http.getconn, http.dns, http.connect, http.tls, +// http.headers, http.send, http.receive) as separate heap-allocated +// trace.Span objects. In high fan-out services this multiplied span +// volume can overwhelm the span processor queue and increase GC +// pressure, resulting in elevated and continuously growing memory usage. +// Using WithoutSubSpans replaces those spans with lightweight events on +// the parent span, preserving the diagnostic information at a fraction +// of the cost. func WithoutSubSpans() ClientTraceOption { return clientTraceOptionFunc(func(ct *clientTracer) { ct.useSpans = false @@ -189,10 +201,11 @@ func NewClientTrace(ctx context.Context, opts ...ClientTraceOption) *httptrace.C } func (ct *clientTracer) start(hook, spanName string, attrs ...attribute.KeyValue) { + if ct.root == nil { + ct.root = trace.SpanFromContext(ct.Context) + } + if !ct.useSpans { - if ct.root == nil { - ct.root = trace.SpanFromContext(ct.Context) - } ct.root.AddEvent(hook+".start", trace.WithAttributes(attrs...)) return } @@ -201,11 +214,7 @@ func (ct *clientTracer) start(hook, spanName string, attrs ...attribute.KeyValue defer ct.mtx.Unlock() if hookCtx, found := ct.activeHooks[hook]; !found { - var sp trace.Span - ct.activeHooks[hook], sp = ct.tr.Start(ct.getParentContext(hook), spanName, trace.WithAttributes(attrs...), trace.WithSpanKind(trace.SpanKindClient)) - if ct.root == nil { - ct.root = sp - } + ct.activeHooks[hook], _ = ct.tr.Start(ct.getParentContext(hook), spanName, trace.WithAttributes(attrs...), trace.WithSpanKind(trace.SpanKindClient)) } else { // end was called before start finished, add the start attributes and end the span here span := trace.SpanFromContext(hookCtx) @@ -306,14 +315,16 @@ func (ct *clientTracer) dnsDone(info httptrace.DNSDoneInfo) { } func (ct *clientTracer) connectStart(network, addr string) { - ct.start("http.connect."+addr, "http.connect", + ct.start( + "http.connect."+addr, "http.connect", HTTPRemoteAddr.String(addr), HTTPConnectionStartNetwork.String(network), ) } func (ct *clientTracer) connectDone(network, addr string, err error) { - ct.end("http.connect."+addr, err, + ct.end( + "http.connect."+addr, err, HTTPConnectionDoneAddr.String(addr), HTTPConnectionDoneNetwork.String(network), ) diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/client.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/client.go index 353ed2ff53c..d88cd079d14 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/client.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/client.go @@ -12,6 +12,7 @@ import ( "context" "fmt" "net/http" + "reflect" "slices" "strconv" "strings" @@ -19,8 +20,8 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/semconv/v1.40.0" - "go.opentelemetry.io/otel/semconv/v1.40.0/httpconv" + "go.opentelemetry.io/otel/semconv/v1.41.0" + "go.opentelemetry.io/otel/semconv/v1.41.0/httpconv" ) type HTTPClient struct { @@ -166,7 +167,7 @@ func (n HTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue func (n HTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) { if method == "" { - return semconv.HTTPRequestMethodGet, attribute.KeyValue{} + return semconv.HTTPRequestMethodOther, attribute.KeyValue{} } if attr, ok := methodLookup[method]; ok { return attr, attribute.KeyValue{} @@ -176,7 +177,7 @@ func (n HTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValu if attr, ok := methodLookup[strings.ToUpper(method)]; ok { return attr, orig } - return semconv.HTTPRequestMethodGet, orig + return semconv.HTTPRequestMethodOther, orig } func (n HTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue { @@ -249,6 +250,9 @@ func (o MetricOpts) AddOptions() metric.AddOption { func (n HTTPClient) MetricOptions(ma MetricAttributes) MetricOpts { attributes := n.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes) + if ma.StatusCode == 0 && ma.Err != nil { + attributes = append(attributes, n.ErrorType(ma.Err)) + } set := metric.WithAttributeSet(attribute.NewSet(attributes...)) return MetricOpts{ @@ -257,6 +261,39 @@ func (n HTTPClient) MetricOptions(ma MetricAttributes) MetricOpts { } } +// ErrorType returns an error.type attribute for the given error. The otelhttp +// Transport calls the underlying RoundTripper directly, so transport failures +// arrive as *net.OpError (connection refused, timeout, etc.) rather than +// *url.Error (which http.Client.Do adds above the Transport layer). This +// function intentionally does not unwrap further: reporting a single concrete +// type per failure keeps attribute cardinality bounded, as required by the +// OTel spec (error.type SHOULD have low cardinality). Callers that need +// finer-grained error distinctions should inspect the error themselves. +func (n HTTPClient) ErrorType(err error) attribute.KeyValue { + t := reflect.TypeOf(err) + if t == nil { + return semconv.ErrorTypeOther + } + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + var value string + if t.PkgPath() == "" || t.Name() == "" { + // t.PkgPath() == "" covers builtin and unnamed types. + // t.Name() == "" covers anonymous struct types that implement error, + // which are uncommon but possible. Fall back to t.String() for both. + value = t.String() + } else { + value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()) + } + + if value == "" { + return semconv.ErrorTypeOther + } + + return semconv.ErrorTypeKey.String(value) +} + func (n HTTPClient) RecordMetrics(ctx context.Context, md MetricData, opts MetricOpts) { recordOpts := metricRecordOptionPool.Get().(*[]metric.RecordOption) defer func() { diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/server.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/server.go index 332057bafcd..a50124078d3 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/server.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/server.go @@ -20,8 +20,8 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/semconv/v1.40.0" - "go.opentelemetry.io/otel/semconv/v1.40.0/httpconv" + "go.opentelemetry.io/otel/semconv/v1.41.0" + "go.opentelemetry.io/otel/semconv/v1.41.0/httpconv" ) type RequestTraceAttrsOpts struct { @@ -243,6 +243,7 @@ type MetricAttributes struct { StatusCode int Route string AdditionalAttributes []attribute.KeyValue + Err error } type MetricData struct { @@ -250,13 +251,11 @@ type MetricData struct { RequestDuration time.Duration } -var ( - metricRecordOptionPool = &sync.Pool{ - New: func() any { - return &[]metric.RecordOption{} - }, - } -) +var metricRecordOptionPool = &sync.Pool{ + New: func() any { + return &[]metric.RecordOption{} + }, +} func (n HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) { attributes := n.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.Route, md.AdditionalAttributes) @@ -270,9 +269,27 @@ func (n HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) { metricRecordOptionPool.Put(recordOpts) } +// SpanName returns the span name for an HTTP request following the +// OpenTelemetry HTTP semantic conventions. +// It returns "{method} {route}" when the request has a pattern, +// or just "{method}" when no route is available. +// Non-standard HTTP methods are replaced by "HTTP". +func (n HTTPServer) SpanName(r *http.Request) string { + method := strings.ToUpper(r.Method) + if _, ok := methodLookup[method]; !ok { + method = "HTTP" + } + + route := httpRoute(r.Pattern) + if route != "" { + return method + " " + route + } + return method +} + func (n HTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) { if method == "" { - return semconv.HTTPRequestMethodGet, attribute.KeyValue{} + return semconv.HTTPRequestMethodOther, attribute.KeyValue{} } if attr, ok := methodLookup[method]; ok { return attr, attribute.KeyValue{} @@ -282,7 +299,7 @@ func (n HTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValu if attr, ok := methodLookup[strings.ToUpper(method)]; ok { return attr, orig } - return semconv.HTTPRequestMethodGet, orig + return semconv.HTTPRequestMethodOther, orig } func (n HTTPServer) scheme(https bool) attribute.KeyValue { //nolint:revive // ignore linter diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/util.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/util.go index b2dc8548f41..88b67003cc7 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/util.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv/util.go @@ -15,7 +15,7 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - semconvNew "go.opentelemetry.io/otel/semconv/v1.40.0" + semconvNew "go.opentelemetry.io/otel/semconv/v1.41.0" ) // SplitHostPort splits a network address hostport of the form "host", diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/version.go index 5473bb88415..f38ce8da374 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/version.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/version.go @@ -4,4 +4,4 @@ package otelhttptrace // import "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace" // Version is the current release version of the httptrace instrumentation. -const Version = "0.68.0" +const Version = "0.69.0" diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go index a269fce0f7a..204588b849a 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go @@ -35,10 +35,6 @@ type middleware struct { semconv semconv.HTTPServer } -func defaultHandlerFormatter(operation string, _ *http.Request) string { - return operation -} - // NewHandler wraps the passed handler in a span named after the operation and // enriches it with metrics. func NewHandler(handler http.Handler, operation string, opts ...Option) http.Handler { @@ -55,12 +51,17 @@ func NewMiddleware(operation string, opts ...Option) func(http.Handler) http.Han defaultOpts := []Option{ WithSpanOptions(trace.WithSpanKind(trace.SpanKindServer)), - WithSpanNameFormatter(defaultHandlerFormatter), } c := newConfig(append(defaultOpts, opts...)...) h.configure(c) + if h.spanNameFormatter == nil { + h.spanNameFormatter = func(_ string, r *http.Request) string { + return h.semconv.SpanName(r) + } + } + return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h.serveHTTP(w, r, next) @@ -138,7 +139,13 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http // ReadCloser fulfills a certain interface and it is indeed nil or NoBody. bw := request.NewBodyWrapper(r.Body, readRecordFunc) if r.Body != nil && r.Body != http.NoBody { + origReq := r + prevBody := r.Body r.Body = bw + + // Restore the original body after the request is processed to avoid issues + // with extra wrapper since `http/server.go` later checks type of `r.Body`. + defer func() { origReq.Body = prevBody }() } writeRecordFunc := func(int64) {} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/client.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/client.go index 1398d85c2e9..0241b08e856 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/client.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/client.go @@ -12,6 +12,7 @@ import ( "context" "fmt" "net/http" + "reflect" "slices" "strconv" "strings" @@ -19,8 +20,8 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/semconv/v1.40.0" - "go.opentelemetry.io/otel/semconv/v1.40.0/httpconv" + "go.opentelemetry.io/otel/semconv/v1.41.0" + "go.opentelemetry.io/otel/semconv/v1.41.0/httpconv" ) type HTTPClient struct { @@ -166,7 +167,7 @@ func (n HTTPClient) ResponseTraceAttrs(resp *http.Response) []attribute.KeyValue func (n HTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValue) { if method == "" { - return semconv.HTTPRequestMethodGet, attribute.KeyValue{} + return semconv.HTTPRequestMethodOther, attribute.KeyValue{} } if attr, ok := methodLookup[method]; ok { return attr, attribute.KeyValue{} @@ -176,7 +177,7 @@ func (n HTTPClient) method(method string) (attribute.KeyValue, attribute.KeyValu if attr, ok := methodLookup[strings.ToUpper(method)]; ok { return attr, orig } - return semconv.HTTPRequestMethodGet, orig + return semconv.HTTPRequestMethodOther, orig } func (n HTTPClient) MetricAttributes(req *http.Request, statusCode int, additionalAttributes []attribute.KeyValue) []attribute.KeyValue { @@ -249,6 +250,9 @@ func (o MetricOpts) AddOptions() metric.AddOption { func (n HTTPClient) MetricOptions(ma MetricAttributes) MetricOpts { attributes := n.MetricAttributes(ma.Req, ma.StatusCode, ma.AdditionalAttributes) + if ma.StatusCode == 0 && ma.Err != nil { + attributes = append(attributes, n.ErrorType(ma.Err)) + } set := metric.WithAttributeSet(attribute.NewSet(attributes...)) return MetricOpts{ @@ -257,6 +261,39 @@ func (n HTTPClient) MetricOptions(ma MetricAttributes) MetricOpts { } } +// ErrorType returns an error.type attribute for the given error. The otelhttp +// Transport calls the underlying RoundTripper directly, so transport failures +// arrive as *net.OpError (connection refused, timeout, etc.) rather than +// *url.Error (which http.Client.Do adds above the Transport layer). This +// function intentionally does not unwrap further: reporting a single concrete +// type per failure keeps attribute cardinality bounded, as required by the +// OTel spec (error.type SHOULD have low cardinality). Callers that need +// finer-grained error distinctions should inspect the error themselves. +func (n HTTPClient) ErrorType(err error) attribute.KeyValue { + t := reflect.TypeOf(err) + if t == nil { + return semconv.ErrorTypeOther + } + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + var value string + if t.PkgPath() == "" || t.Name() == "" { + // t.PkgPath() == "" covers builtin and unnamed types. + // t.Name() == "" covers anonymous struct types that implement error, + // which are uncommon but possible. Fall back to t.String() for both. + value = t.String() + } else { + value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()) + } + + if value == "" { + return semconv.ErrorTypeOther + } + + return semconv.ErrorTypeKey.String(value) +} + func (n HTTPClient) RecordMetrics(ctx context.Context, md MetricData, opts MetricOpts) { recordOpts := metricRecordOptionPool.Get().(*[]metric.RecordOption) defer func() { diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/server.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/server.go index 83c6ae24653..8e0430863d9 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/server.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/server.go @@ -20,8 +20,8 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/semconv/v1.40.0" - "go.opentelemetry.io/otel/semconv/v1.40.0/httpconv" + "go.opentelemetry.io/otel/semconv/v1.41.0" + "go.opentelemetry.io/otel/semconv/v1.41.0/httpconv" ) type RequestTraceAttrsOpts struct { @@ -243,6 +243,7 @@ type MetricAttributes struct { StatusCode int Route string AdditionalAttributes []attribute.KeyValue + Err error } type MetricData struct { @@ -250,13 +251,11 @@ type MetricData struct { RequestDuration time.Duration } -var ( - metricRecordOptionPool = &sync.Pool{ - New: func() any { - return &[]metric.RecordOption{} - }, - } -) +var metricRecordOptionPool = &sync.Pool{ + New: func() any { + return &[]metric.RecordOption{} + }, +} func (n HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) { attributes := n.MetricAttributes(md.ServerName, md.Req, md.StatusCode, md.Route, md.AdditionalAttributes) @@ -270,9 +269,27 @@ func (n HTTPServer) RecordMetrics(ctx context.Context, md ServerMetricData) { metricRecordOptionPool.Put(recordOpts) } +// SpanName returns the span name for an HTTP request following the +// OpenTelemetry HTTP semantic conventions. +// It returns "{method} {route}" when the request has a pattern, +// or just "{method}" when no route is available. +// Non-standard HTTP methods are replaced by "HTTP". +func (n HTTPServer) SpanName(r *http.Request) string { + method := strings.ToUpper(r.Method) + if _, ok := methodLookup[method]; !ok { + method = "HTTP" + } + + route := httpRoute(r.Pattern) + if route != "" { + return method + " " + route + } + return method +} + func (n HTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValue) { if method == "" { - return semconv.HTTPRequestMethodGet, attribute.KeyValue{} + return semconv.HTTPRequestMethodOther, attribute.KeyValue{} } if attr, ok := methodLookup[method]; ok { return attr, attribute.KeyValue{} @@ -282,7 +299,7 @@ func (n HTTPServer) method(method string) (attribute.KeyValue, attribute.KeyValu if attr, ok := methodLookup[strings.ToUpper(method)]; ok { return attr, orig } - return semconv.HTTPRequestMethodGet, orig + return semconv.HTTPRequestMethodOther, orig } func (n HTTPServer) scheme(https bool) attribute.KeyValue { //nolint:revive // ignore linter diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go index 2eab2ecabde..d6842ed2ab5 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go @@ -15,7 +15,7 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - semconvNew "go.opentelemetry.io/otel/semconv/v1.40.0" + semconvNew "go.opentelemetry.io/otel/semconv/v1.41.0" ) // SplitHostPort splits a network address hostport of the form "host", diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go index d8d204d1f8a..b15895cee22 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go @@ -15,7 +15,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" - otelsemconv "go.opentelemetry.io/otel/semconv/v1.40.0" + otelsemconv "go.opentelemetry.io/otel/semconv/v1.41.0" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request" @@ -161,6 +161,7 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { t.semconv.MetricOptions(semconv.MetricAttributes{ Req: r, StatusCode: statusCode, + Err: err, AdditionalAttributes: append(labeler.Get(), t.metricAttributesFromRequest(r)...), }), ) diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go index 835ec5aa7e8..2feb885000f 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go @@ -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.68.0" +const Version = "0.69.0" diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go index 4ae569ff4b1..f81098b3811 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go @@ -143,9 +143,9 @@ func (c *client) Start(ctx context.Context) error { } // Stop shuts down the client and interrupt any in-flight request. -func (d *client) Stop(ctx context.Context) error { - d.stopOnce.Do(func() { - close(d.stopCh) +func (c *client) Stop(ctx context.Context) error { + c.stopOnce.Do(func() { + close(c.stopCh) }) select { case <-ctx.Done(): @@ -156,7 +156,7 @@ func (d *client) Stop(ctx context.Context) error { } // UploadTraces sends a batch of spans to the collector. -func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.ResourceSpans) (uploadErr error) { +func (c *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.ResourceSpans) (uploadErr error) { pbRequest := &coltracepb.ExportTraceServiceRequest{ ResourceSpans: protoSpans, } @@ -165,30 +165,41 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc return err } - ctx, cancel := d.contextWithStop(ctx) + ctx, cancel := c.contextWithStop(ctx) defer cancel() - request, err := d.newRequest(rawRequest) + if maxSize := c.cfg.MaxRequestSize; maxSize > 0 && len(rawRequest) > maxSize { + return fmt.Errorf("request body too large: exceeded %d bytes", maxSize) + } + + request, err := c.newRequest(rawRequest) if err != nil { return err } var statusCode int - if d.inst != nil { - op := d.inst.ExportSpans(ctx, len(protoSpans)) + if c.inst != nil { + var spanCount int + for _, rs := range protoSpans { + for _, ss := range rs.ScopeSpans { + spanCount += len(ss.Spans) + } + } + op := c.inst.ExportSpans(ctx, spanCount) defer func() { op.End(uploadErr, statusCode) }() } - return errors.Join(uploadErr, d.requestFunc(ctx, func(ctx context.Context) error { + return errors.Join(uploadErr, c.requestFunc(ctx, func(ctx context.Context) error { select { case <-ctx.Done(): return ctx.Err() default: } + statusCode = 0 request.reset(ctx) // nolint:gosec // URL is constructed from validated OTLP endpoint configuration - resp, err := d.client.Do(request.Request) + resp, err := c.client.Do(request.Request) var urlErr *url.Error if errors.As(err, &urlErr) && urlErr.Temporary() { return newResponseError(http.Header{}, err) @@ -272,8 +283,8 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc })) } -func (d *client) newRequest(body []byte) (request, error) { - u := url.URL{Scheme: d.getScheme(), Host: d.cfg.Endpoint, Path: d.cfg.URLPath} +func (c *client) newRequest(body []byte) (request, error) { + u := url.URL{Scheme: c.getScheme(), Host: c.cfg.Endpoint, Path: c.cfg.URLPath} r, err := http.NewRequestWithContext(context.Background(), http.MethodPost, u.String(), http.NoBody) if err != nil { return request{Request: r}, err @@ -282,13 +293,13 @@ func (d *client) newRequest(body []byte) (request, error) { userAgent := "OTel OTLP Exporter Go/" + otlptrace.Version() r.Header.Set("User-Agent", userAgent) - for k, v := range d.cfg.Headers { + for k, v := range c.cfg.Headers { r.Header.Set(k, v) } r.Header.Set("Content-Type", contentTypeProto) req := request{Request: r} - switch Compression(d.cfg.Compression) { + switch Compression(c.cfg.Compression) { case NoCompression: r.ContentLength = int64(len(body)) req.bodyReader = bodyReader(body) @@ -299,7 +310,10 @@ func (d *client) newRequest(body []byte) (request, error) { r.Header.Set("Content-Encoding", "gzip") gz := gzPool.Get().(*gzip.Writer) - defer gzPool.Put(gz) + defer func() { + gz.Reset(io.Discard) + gzPool.Put(gz) + }() var b bytes.Buffer gz.Reset(&b) @@ -320,15 +334,15 @@ func (d *client) newRequest(body []byte) (request, error) { } // MarshalLog is the marshaling function used by the logging system to represent this Client. -func (d *client) MarshalLog() any { +func (c *client) MarshalLog() any { return struct { Type string Endpoint string Insecure bool }{ Type: "otlptracehttp", - Endpoint: d.cfg.Endpoint, - Insecure: d.cfg.Insecure, + Endpoint: c.cfg.Endpoint, + Insecure: c.cfg.Insecure, } } @@ -425,14 +439,14 @@ func evaluate(err error) (bool, time.Duration) { return true, time.Duration(rErr.throttle) } -func (d *client) getScheme() string { - if d.cfg.Insecure { +func (c *client) getScheme() string { + if c.cfg.Insecure { return "http" } return "https" } -func (d *client) contextWithStop(ctx context.Context) (context.Context, context.CancelFunc) { +func (c *client) contextWithStop(ctx context.Context) (context.Context, context.CancelFunc) { // Unify the parent context Done signal with the client's stop // channel. ctx, cancel := context.WithCancel(ctx) @@ -441,7 +455,7 @@ func (d *client) contextWithStop(ctx context.Context) (context.Context, context. case <-ctx.Done(): // Nothing to do, either cancelled or deadline // happened. - case <-d.stopCh: + case <-c.stopCh: cancel() } }(ctx, cancel) diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/observ/instrumentation.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/observ/instrumentation.go index 3f2556e7a60..1f4fc55c6f6 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/observ/instrumentation.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/observ/instrumentation.go @@ -23,8 +23,8 @@ import ( "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/x" "go.opentelemetry.io/otel/internal/global" "go.opentelemetry.io/otel/metric" - semconv "go.opentelemetry.io/otel/semconv/v1.40.0" - "go.opentelemetry.io/otel/semconv/v1.40.0/otelconv" + semconv "go.opentelemetry.io/otel/semconv/v1.41.0" + "go.opentelemetry.io/otel/semconv/v1.41.0/otelconv" ) const ( @@ -77,6 +77,7 @@ var ( func get[T any](p *sync.Pool) *[]T { return p.Get().(*[]T) } func put[T any](p *sync.Pool, s *[]T) { + clear(*s) // erase elements to allow GC to collect what they refer to. *s = (*s)[:0] // Reset. p.Put(s) } @@ -167,7 +168,7 @@ func NewInstrumentation(id int64, endpoint string) (*Instrumentation, error) { // to set the "component.name" attribute. // // The endpoint is the HTTP endpoint the exporter is exporting to. It should be -// in the format "host:port" or a full URL. +// in the format "host[:port]". func BaseAttrs(id int64, endpoint string) []attribute.KeyValue { host, port, err := parseEndpoint(endpoint) if err != nil || (host == "" && port < 0) { @@ -345,7 +346,7 @@ func (e ExportOp) End(err error, status int) { // // Otherwise, a new RecordOption is returned with the base attributes of the // Instrumentation plus the http.response.status_code attribute set to the -// provided status, and if err is not nil, the error.type attribute set +// provided status (if non-zero), and if err is not nil, the error.type attribute set // to the type of the error. func (i *Instrumentation) recordOption(err error, status int) metric.RecordOption { if err == nil && status == http.StatusOK { @@ -356,7 +357,9 @@ func (i *Instrumentation) recordOption(err error, status int) metric.RecordOptio defer put(measureAttrsPool, attrs) *attrs = append(*attrs, i.attrs...) - *attrs = append(*attrs, semconv.HTTPResponseStatusCode(status)) + if status != 0 { + *attrs = append(*attrs, semconv.HTTPResponseStatusCode(status)) + } if err != nil { *attrs = append(*attrs, semconv.ErrorType(err)) } @@ -394,7 +397,10 @@ var errPartialPool = &sync.Pool{ // the provided non-nil err. func rejected(n int64, err error) int64 { ps := errPartialPool.Get().(*internal.PartialSuccess) - defer errPartialPool.Put(ps) + defer func() { + *ps = internal.PartialSuccess{} // erase fields to allow GC to collect them. + errPartialPool.Put(ps) + }() // Check for partial success. if errors.As(err, ps) { // Bound RejectedItems to [0, n]. This should not be needed, diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go index e415feea6eb..2abde661507 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go @@ -31,6 +31,9 @@ const ( // DefaultTracesPath is a default URL path for endpoint that // receives spans. DefaultTracesPath string = "/v1/traces" + // DefaultMaxRequestSize is the default maximum size of a serialized export + // request, before compression. + DefaultMaxRequestSize int = 64 * 1024 * 1024 // DefaultTimeout is a default max waiting time for the backend to process // each span batch. DefaultTimeout time.Duration = 10 * time.Second @@ -42,13 +45,14 @@ type ( HTTPTransportProxyFunc func(*http.Request) (*url.URL, error) SignalConfig struct { - Endpoint string - Insecure bool - TLSCfg *tls.Config - Headers map[string]string - Compression Compression - Timeout time.Duration - URLPath string + Endpoint string + Insecure bool + TLSCfg *tls.Config + Headers map[string]string + Compression Compression + MaxRequestSize int + Timeout time.Duration + URLPath string // gRPC configurations GRPCCredentials credentials.TransportCredentials @@ -77,10 +81,11 @@ type ( func NewHTTPConfig(opts ...HTTPOption) Config { cfg := Config{ Traces: SignalConfig{ - Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorHTTPPort), - URLPath: DefaultTracesPath, - Compression: NoCompression, - Timeout: DefaultTimeout, + Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorHTTPPort), + URLPath: DefaultTracesPath, + Compression: NoCompression, + MaxRequestSize: DefaultMaxRequestSize, + Timeout: DefaultTimeout, }, RetryConfig: retry.DefaultConfig, } @@ -111,10 +116,11 @@ func NewGRPCConfig(opts ...GRPCOption) Config { userAgent := "OTel OTLP Exporter Go/" + otlptrace.Version() cfg := Config{ Traces: SignalConfig{ - Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorGRPCPort), - URLPath: DefaultTracesPath, - Compression: NoCompression, - Timeout: DefaultTimeout, + Endpoint: fmt.Sprintf("%s:%d", DefaultCollectorHost, DefaultCollectorGRPCPort), + URLPath: DefaultTracesPath, + Compression: NoCompression, + MaxRequestSize: DefaultMaxRequestSize, + Timeout: DefaultTimeout, }, RetryConfig: retry.DefaultConfig, DialOptions: []grpc.DialOption{grpc.WithUserAgent(userAgent)}, @@ -345,6 +351,13 @@ func WithTimeout(duration time.Duration) GenericOption { }) } +func WithMaxRequestSize(size int) GenericOption { + return newGenericOption(func(cfg Config) Config { + cfg.Traces.MaxRequestSize = size + return cfg + }) +} + func WithProxy(pf HTTPTransportProxyFunc) GenericOption { return newGenericOption(func(cfg Config) Config { cfg.Traces.Proxy = pf diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/version.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/version.go index 3e43f771131..882b6713804 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/version.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/version.go @@ -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 HTTP trace // exporter in use. -const Version = "1.43.0" +const Version = "1.44.0" diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go index cfe21dbfb05..291b5f9b64a 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/options.go @@ -138,6 +138,16 @@ func WithTimeout(duration time.Duration) Option { return wrappedOption{otlpconfig.WithTimeout(duration)} } +// WithMaxRequestSize sets the maximum size, in bytes, of a serialized export +// request, before compression, that the exporter will send. +// +// If size is less than or equal to zero, no request-size limit is applied. +// Disabling the limit is not recommended because it can lead to excessive +// resource consumption or abuse. +func WithMaxRequestSize(size int) Option { + return wrappedOption{otlpconfig.WithMaxRequestSize(size)} +} + // WithRetry configures the retry policy for transient errors that may occurs // when exporting traces. An exponential back-off algorithm is used to ensure // endpoints are not overwhelmed with retries. If unset, the default retry diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/MIGRATION.md b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/MIGRATION.md deleted file mode 100644 index e246b1692d6..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/MIGRATION.md +++ /dev/null @@ -1,27 +0,0 @@ - -# Migration from v1.39.0 to v1.40.0 - -The `go.opentelemetry.io/otel/semconv/v1.40.0` package should be a drop-in replacement for `go.opentelemetry.io/otel/semconv/v1.39.0` with the following exceptions. - -## Removed - -The following declarations have been removed. -Refer to the [OpenTelemetry Semantic Conventions documentation] for deprecation instructions. - -If the type is not listed in the documentation as deprecated, it has been removed in this version due to lack of applicability or use. -If you use any of these non-deprecated declarations in your Go application, please [open an issue] describing your use-case. - -- `ErrorMessage` -- `ErrorMessageKey` -- `RPCMessageCompressedSize` -- `RPCMessageCompressedSizeKey` -- `RPCMessageID` -- `RPCMessageIDKey` -- `RPCMessageTypeKey` -- `RPCMessageTypeReceived` -- `RPCMessageTypeSent` -- `RPCMessageUncompressedSize` -- `RPCMessageUncompressedSizeKey` - -[OpenTelemetry Semantic Conventions documentation]: https://github.com/open-telemetry/semantic-conventions -[open an issue]: https://github.com/open-telemetry/opentelemetry-go/issues/new?template=Blank+issue diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/README.md b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/README.md deleted file mode 100644 index c51b7fb7b07..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Semconv v1.40.0 - -[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/semconv/v1.40.0)](https://pkg.go.dev/go.opentelemetry.io/otel/semconv/v1.40.0) diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/attribute_group.go b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/attribute_group.go deleted file mode 100644 index eb6f8fdf4bb..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/attribute_group.go +++ /dev/null @@ -1,16865 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv - -import "go.opentelemetry.io/otel/attribute" - -// Namespace: android -const ( - // AndroidAppStateKey is the attribute Key conforming to the "android.app.state" - // semantic conventions. It represents the this attribute represents the state - // of the application. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "created" - // Note: The Android lifecycle states are defined in - // [Activity lifecycle callbacks], and from which the `OS identifiers` are - // derived. - // - // [Activity lifecycle callbacks]: https://developer.android.com/guide/components/activities/activity-lifecycle#lc - AndroidAppStateKey = attribute.Key("android.app.state") - - // AndroidOSAPILevelKey is the attribute Key conforming to the - // "android.os.api_level" semantic conventions. It represents the uniquely - // identifies the framework API revision offered by a version (`os.version`) of - // the android operating system. More information can be found in the - // [Android API levels documentation]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "33", "32" - // - // [Android API levels documentation]: https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels - AndroidOSAPILevelKey = attribute.Key("android.os.api_level") -) - -// AndroidOSAPILevel returns an attribute KeyValue conforming to the -// "android.os.api_level" semantic conventions. It represents the uniquely -// identifies the framework API revision offered by a version (`os.version`) of -// the android operating system. More information can be found in the -// [Android API levels documentation]. -// -// [Android API levels documentation]: https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels -func AndroidOSAPILevel(val string) attribute.KeyValue { - return AndroidOSAPILevelKey.String(val) -} - -// Enum values for android.app.state -var ( - // Any time before Activity.onResume() or, if the app has no Activity, - // Context.startService() has been called in the app for the first time. - // - // Stability: development - AndroidAppStateCreated = AndroidAppStateKey.String("created") - // Any time after Activity.onPause() or, if the app has no Activity, - // Context.stopService() has been called when the app was in the foreground - // state. - // - // Stability: development - AndroidAppStateBackground = AndroidAppStateKey.String("background") - // Any time after Activity.onResume() or, if the app has no Activity, - // Context.startService() has been called when the app was in either the created - // or background states. - // - // Stability: development - AndroidAppStateForeground = AndroidAppStateKey.String("foreground") -) - -// Namespace: app -const ( - // AppBuildIDKey is the attribute Key conforming to the "app.build_id" semantic - // conventions. It represents the unique identifier for a particular build or - // compilation of the application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "6cff0a7e-cefc-4668-96f5-1273d8b334d0", - // "9f2b833506aa6973a92fde9733e6271f", "my-app-1.0.0-code-123" - AppBuildIDKey = attribute.Key("app.build_id") - - // AppInstallationIDKey is the attribute Key conforming to the - // "app.installation.id" semantic conventions. It represents a unique identifier - // representing the installation of an application on a specific device. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2ab2916d-a51f-4ac8-80ee-45ac31a28092" - // Note: Its value SHOULD persist across launches of the same application - // installation, including through application upgrades. - // It SHOULD change if the application is uninstalled or if all applications of - // the vendor are uninstalled. - // Additionally, users might be able to reset this value (e.g. by clearing - // application data). - // If an app is installed multiple times on the same device (e.g. in different - // accounts on Android), each `app.installation.id` SHOULD have a different - // value. - // If multiple OpenTelemetry SDKs are used within the same application, they - // SHOULD use the same value for `app.installation.id`. - // Hardware IDs (e.g. serial number, IMEI, MAC address) MUST NOT be used as the - // `app.installation.id`. - // - // For iOS, this value SHOULD be equal to the [vendor identifier]. - // - // For Android, examples of `app.installation.id` implementations include: - // - // - [Firebase Installation ID]. - // - A globally unique UUID which is persisted across sessions in your - // application. - // - [App set ID]. - // - [`Settings.getString(Settings.Secure.ANDROID_ID)`]. - // - // More information about Android identifier best practices can be found in the - // [Android user data IDs guide]. - // - // [vendor identifier]: https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor - // [Firebase Installation ID]: https://firebase.google.com/docs/projects/manage-installations - // [App set ID]: https://developer.android.com/identity/app-set-id - // [`Settings.getString(Settings.Secure.ANDROID_ID)`]: https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID - // [Android user data IDs guide]: https://developer.android.com/training/articles/user-data-ids - AppInstallationIDKey = attribute.Key("app.installation.id") - - // AppJankFrameCountKey is the attribute Key conforming to the - // "app.jank.frame_count" semantic conventions. It represents a number of frame - // renders that experienced jank. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 9, 42 - // Note: Depending on platform limitations, the value provided MAY be - // approximation. - AppJankFrameCountKey = attribute.Key("app.jank.frame_count") - - // AppJankPeriodKey is the attribute Key conforming to the "app.jank.period" - // semantic conventions. It represents the time period, in seconds, for which - // this jank is being reported. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1.0, 5.0, 10.24 - AppJankPeriodKey = attribute.Key("app.jank.period") - - // AppJankThresholdKey is the attribute Key conforming to the - // "app.jank.threshold" semantic conventions. It represents the minimum - // rendering threshold for this jank, in seconds. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0.016, 0.7, 1.024 - AppJankThresholdKey = attribute.Key("app.jank.threshold") - - // AppScreenCoordinateXKey is the attribute Key conforming to the - // "app.screen.coordinate.x" semantic conventions. It represents the x - // (horizontal) coordinate of a screen coordinate, in screen pixels. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0, 131 - AppScreenCoordinateXKey = attribute.Key("app.screen.coordinate.x") - - // AppScreenCoordinateYKey is the attribute Key conforming to the - // "app.screen.coordinate.y" semantic conventions. It represents the y - // (vertical) component of a screen coordinate, in screen pixels. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 12, 99 - AppScreenCoordinateYKey = attribute.Key("app.screen.coordinate.y") - - // AppScreenIDKey is the attribute Key conforming to the "app.screen.id" - // semantic conventions. It represents an identifier that uniquely - // differentiates this screen from other screens in the same application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "f9bc787d-ff05-48ad-90e1-fca1d46130b3", - // "com.example.app.MainActivity", "com.example.shop.ProductDetailFragment", - // "MyApp.ProfileView", "MyApp.ProfileViewController" - // Note: A screen represents only the part of the device display drawn by the - // app. It typically contains multiple widgets or UI components and is larger in - // scope than individual widgets. Multiple screens can coexist on the same - // display simultaneously (e.g., split view on tablets). - AppScreenIDKey = attribute.Key("app.screen.id") - - // AppScreenNameKey is the attribute Key conforming to the "app.screen.name" - // semantic conventions. It represents the name of an application screen. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "MainActivity", "ProductDetailFragment", "ProfileView", - // "ProfileViewController" - // Note: A screen represents only the part of the device display drawn by the - // app. It typically contains multiple widgets or UI components and is larger in - // scope than individual widgets. Multiple screens can coexist on the same - // display simultaneously (e.g., split view on tablets). - AppScreenNameKey = attribute.Key("app.screen.name") - - // AppWidgetIDKey is the attribute Key conforming to the "app.widget.id" - // semantic conventions. It represents an identifier that uniquely - // differentiates this widget from other widgets in the same application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "f9bc787d-ff05-48ad-90e1-fca1d46130b3", "submit_order_1829" - // Note: A widget is an application component, typically an on-screen visual GUI - // element. - AppWidgetIDKey = attribute.Key("app.widget.id") - - // AppWidgetNameKey is the attribute Key conforming to the "app.widget.name" - // semantic conventions. It represents the name of an application widget. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "submit", "attack", "Clear Cart" - // Note: A widget is an application component, typically an on-screen visual GUI - // element. - AppWidgetNameKey = attribute.Key("app.widget.name") -) - -// AppBuildID returns an attribute KeyValue conforming to the "app.build_id" -// semantic conventions. It represents the unique identifier for a particular -// build or compilation of the application. -func AppBuildID(val string) attribute.KeyValue { - return AppBuildIDKey.String(val) -} - -// AppInstallationID returns an attribute KeyValue conforming to the -// "app.installation.id" semantic conventions. It represents a unique identifier -// representing the installation of an application on a specific device. -func AppInstallationID(val string) attribute.KeyValue { - return AppInstallationIDKey.String(val) -} - -// AppJankFrameCount returns an attribute KeyValue conforming to the -// "app.jank.frame_count" semantic conventions. It represents a number of frame -// renders that experienced jank. -func AppJankFrameCount(val int) attribute.KeyValue { - return AppJankFrameCountKey.Int(val) -} - -// AppJankPeriod returns an attribute KeyValue conforming to the -// "app.jank.period" semantic conventions. It represents the time period, in -// seconds, for which this jank is being reported. -func AppJankPeriod(val float64) attribute.KeyValue { - return AppJankPeriodKey.Float64(val) -} - -// AppJankThreshold returns an attribute KeyValue conforming to the -// "app.jank.threshold" semantic conventions. It represents the minimum rendering -// threshold for this jank, in seconds. -func AppJankThreshold(val float64) attribute.KeyValue { - return AppJankThresholdKey.Float64(val) -} - -// AppScreenCoordinateX returns an attribute KeyValue conforming to the -// "app.screen.coordinate.x" semantic conventions. It represents the x -// (horizontal) coordinate of a screen coordinate, in screen pixels. -func AppScreenCoordinateX(val int) attribute.KeyValue { - return AppScreenCoordinateXKey.Int(val) -} - -// AppScreenCoordinateY returns an attribute KeyValue conforming to the -// "app.screen.coordinate.y" semantic conventions. It represents the y (vertical) -// component of a screen coordinate, in screen pixels. -func AppScreenCoordinateY(val int) attribute.KeyValue { - return AppScreenCoordinateYKey.Int(val) -} - -// AppScreenID returns an attribute KeyValue conforming to the "app.screen.id" -// semantic conventions. It represents an identifier that uniquely differentiates -// this screen from other screens in the same application. -func AppScreenID(val string) attribute.KeyValue { - return AppScreenIDKey.String(val) -} - -// AppScreenName returns an attribute KeyValue conforming to the -// "app.screen.name" semantic conventions. It represents the name of an -// application screen. -func AppScreenName(val string) attribute.KeyValue { - return AppScreenNameKey.String(val) -} - -// AppWidgetID returns an attribute KeyValue conforming to the "app.widget.id" -// semantic conventions. It represents an identifier that uniquely differentiates -// this widget from other widgets in the same application. -func AppWidgetID(val string) attribute.KeyValue { - return AppWidgetIDKey.String(val) -} - -// AppWidgetName returns an attribute KeyValue conforming to the -// "app.widget.name" semantic conventions. It represents the name of an -// application widget. -func AppWidgetName(val string) attribute.KeyValue { - return AppWidgetNameKey.String(val) -} - -// Namespace: artifact -const ( - // ArtifactAttestationFilenameKey is the attribute Key conforming to the - // "artifact.attestation.filename" semantic conventions. It represents the - // provenance filename of the built attestation which directly relates to the - // build artifact filename. This filename SHOULD accompany the artifact at - // publish time. See the [SLSA Relationship] specification for more information. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "golang-binary-amd64-v0.1.0.attestation", - // "docker-image-amd64-v0.1.0.intoto.json1", "release-1.tar.gz.attestation", - // "file-name-package.tar.gz.intoto.json1" - // - // [SLSA Relationship]: https://slsa.dev/spec/v1.0/distributing-provenance#relationship-between-artifacts-and-attestations - ArtifactAttestationFilenameKey = attribute.Key("artifact.attestation.filename") - - // ArtifactAttestationHashKey is the attribute Key conforming to the - // "artifact.attestation.hash" semantic conventions. It represents the full - // [hash value (see glossary)], of the built attestation. Some envelopes in the - // [software attestation space] also refer to this as the **digest**. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1b31dfcd5b7f9267bf2ff47651df1cfb9147b9e4df1f335accf65b4cda498408" - // - // [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - // [software attestation space]: https://github.com/in-toto/attestation/tree/main/spec - ArtifactAttestationHashKey = attribute.Key("artifact.attestation.hash") - - // ArtifactAttestationIDKey is the attribute Key conforming to the - // "artifact.attestation.id" semantic conventions. It represents the id of the - // build [software attestation]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "123" - // - // [software attestation]: https://slsa.dev/attestation-model - ArtifactAttestationIDKey = attribute.Key("artifact.attestation.id") - - // ArtifactFilenameKey is the attribute Key conforming to the - // "artifact.filename" semantic conventions. It represents the human readable - // file name of the artifact, typically generated during build and release - // processes. Often includes the package name and version in the file name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "golang-binary-amd64-v0.1.0", "docker-image-amd64-v0.1.0", - // "release-1.tar.gz", "file-name-package.tar.gz" - // Note: This file name can also act as the [Package Name] - // in cases where the package ecosystem maps accordingly. - // Additionally, the artifact [can be published] - // for others, but that is not a guarantee. - // - // [Package Name]: https://slsa.dev/spec/v1.0/terminology#package-model - // [can be published]: https://slsa.dev/spec/v1.0/terminology#software-supply-chain - ArtifactFilenameKey = attribute.Key("artifact.filename") - - // ArtifactHashKey is the attribute Key conforming to the "artifact.hash" - // semantic conventions. It represents the full [hash value (see glossary)], - // often found in checksum.txt on a release of the artifact and used to verify - // package integrity. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "9ff4c52759e2c4ac70b7d517bc7fcdc1cda631ca0045271ddd1b192544f8a3e9" - // Note: The specific algorithm used to create the cryptographic hash value is - // not defined. In situations where an artifact has multiple - // cryptographic hashes, it is up to the implementer to choose which - // hash value to set here; this should be the most secure hash algorithm - // that is suitable for the situation and consistent with the - // corresponding attestation. The implementer can then provide the other - // hash values through an additional set of attribute extensions as they - // deem necessary. - // - // [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - ArtifactHashKey = attribute.Key("artifact.hash") - - // ArtifactPurlKey is the attribute Key conforming to the "artifact.purl" - // semantic conventions. It represents the [Package URL] of the - // [package artifact] provides a standard way to identify and locate the - // packaged artifact. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "pkg:github/package-url/purl-spec@1209109710924", - // "pkg:npm/foo@12.12.3" - // - // [Package URL]: https://github.com/package-url/purl-spec - // [package artifact]: https://slsa.dev/spec/v1.0/terminology#package-model - ArtifactPurlKey = attribute.Key("artifact.purl") - - // ArtifactVersionKey is the attribute Key conforming to the "artifact.version" - // semantic conventions. It represents the version of the artifact. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "v0.1.0", "1.2.1", "122691-build" - ArtifactVersionKey = attribute.Key("artifact.version") -) - -// ArtifactAttestationFilename returns an attribute KeyValue conforming to the -// "artifact.attestation.filename" semantic conventions. It represents the -// provenance filename of the built attestation which directly relates to the -// build artifact filename. This filename SHOULD accompany the artifact at -// publish time. See the [SLSA Relationship] specification for more information. -// -// [SLSA Relationship]: https://slsa.dev/spec/v1.0/distributing-provenance#relationship-between-artifacts-and-attestations -func ArtifactAttestationFilename(val string) attribute.KeyValue { - return ArtifactAttestationFilenameKey.String(val) -} - -// ArtifactAttestationHash returns an attribute KeyValue conforming to the -// "artifact.attestation.hash" semantic conventions. It represents the full -// [hash value (see glossary)], of the built attestation. Some envelopes in the -// [software attestation space] also refer to this as the **digest**. -// -// [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf -// [software attestation space]: https://github.com/in-toto/attestation/tree/main/spec -func ArtifactAttestationHash(val string) attribute.KeyValue { - return ArtifactAttestationHashKey.String(val) -} - -// ArtifactAttestationID returns an attribute KeyValue conforming to the -// "artifact.attestation.id" semantic conventions. It represents the id of the -// build [software attestation]. -// -// [software attestation]: https://slsa.dev/attestation-model -func ArtifactAttestationID(val string) attribute.KeyValue { - return ArtifactAttestationIDKey.String(val) -} - -// ArtifactFilename returns an attribute KeyValue conforming to the -// "artifact.filename" semantic conventions. It represents the human readable -// file name of the artifact, typically generated during build and release -// processes. Often includes the package name and version in the file name. -func ArtifactFilename(val string) attribute.KeyValue { - return ArtifactFilenameKey.String(val) -} - -// ArtifactHash returns an attribute KeyValue conforming to the "artifact.hash" -// semantic conventions. It represents the full [hash value (see glossary)], -// often found in checksum.txt on a release of the artifact and used to verify -// package integrity. -// -// [hash value (see glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf -func ArtifactHash(val string) attribute.KeyValue { - return ArtifactHashKey.String(val) -} - -// ArtifactPurl returns an attribute KeyValue conforming to the "artifact.purl" -// semantic conventions. It represents the [Package URL] of the -// [package artifact] provides a standard way to identify and locate the packaged -// artifact. -// -// [Package URL]: https://github.com/package-url/purl-spec -// [package artifact]: https://slsa.dev/spec/v1.0/terminology#package-model -func ArtifactPurl(val string) attribute.KeyValue { - return ArtifactPurlKey.String(val) -} - -// ArtifactVersion returns an attribute KeyValue conforming to the -// "artifact.version" semantic conventions. It represents the version of the -// artifact. -func ArtifactVersion(val string) attribute.KeyValue { - return ArtifactVersionKey.String(val) -} - -// Namespace: aws -const ( - // AWSBedrockGuardrailIDKey is the attribute Key conforming to the - // "aws.bedrock.guardrail.id" semantic conventions. It represents the unique - // identifier of the AWS Bedrock Guardrail. A [guardrail] helps safeguard and - // prevent unwanted behavior from model responses or user messages. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "sgi5gkybzqak" - // - // [guardrail]: https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html - AWSBedrockGuardrailIDKey = attribute.Key("aws.bedrock.guardrail.id") - - // AWSBedrockKnowledgeBaseIDKey is the attribute Key conforming to the - // "aws.bedrock.knowledge_base.id" semantic conventions. It represents the - // unique identifier of the AWS Bedrock Knowledge base. A [knowledge base] is a - // bank of information that can be queried by models to generate more relevant - // responses and augment prompts. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "XFWUPB9PAW" - // - // [knowledge base]: https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base.html - AWSBedrockKnowledgeBaseIDKey = attribute.Key("aws.bedrock.knowledge_base.id") - - // AWSDynamoDBAttributeDefinitionsKey is the attribute Key conforming to the - // "aws.dynamodb.attribute_definitions" semantic conventions. It represents the - // JSON-serialized value of each item in the `AttributeDefinitions` request - // field. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{ "AttributeName": "string", "AttributeType": "string" }" - AWSDynamoDBAttributeDefinitionsKey = attribute.Key("aws.dynamodb.attribute_definitions") - - // AWSDynamoDBAttributesToGetKey is the attribute Key conforming to the - // "aws.dynamodb.attributes_to_get" semantic conventions. It represents the - // value of the `AttributesToGet` request parameter. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "lives", "id" - AWSDynamoDBAttributesToGetKey = attribute.Key("aws.dynamodb.attributes_to_get") - - // AWSDynamoDBConsistentReadKey is the attribute Key conforming to the - // "aws.dynamodb.consistent_read" semantic conventions. It represents the value - // of the `ConsistentRead` request parameter. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - AWSDynamoDBConsistentReadKey = attribute.Key("aws.dynamodb.consistent_read") - - // AWSDynamoDBConsumedCapacityKey is the attribute Key conforming to the - // "aws.dynamodb.consumed_capacity" semantic conventions. It represents the - // JSON-serialized value of each item in the `ConsumedCapacity` response field. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{ "CapacityUnits": number, "GlobalSecondaryIndexes": { "string" : - // { "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits": - // number } }, "LocalSecondaryIndexes": { "string" : { "CapacityUnits": number, - // "ReadCapacityUnits": number, "WriteCapacityUnits": number } }, - // "ReadCapacityUnits": number, "Table": { "CapacityUnits": number, - // "ReadCapacityUnits": number, "WriteCapacityUnits": number }, "TableName": - // "string", "WriteCapacityUnits": number }" - AWSDynamoDBConsumedCapacityKey = attribute.Key("aws.dynamodb.consumed_capacity") - - // AWSDynamoDBCountKey is the attribute Key conforming to the - // "aws.dynamodb.count" semantic conventions. It represents the value of the - // `Count` response parameter. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 10 - AWSDynamoDBCountKey = attribute.Key("aws.dynamodb.count") - - // AWSDynamoDBExclusiveStartTableKey is the attribute Key conforming to the - // "aws.dynamodb.exclusive_start_table" semantic conventions. It represents the - // value of the `ExclusiveStartTableName` request parameter. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Users", "CatsTable" - AWSDynamoDBExclusiveStartTableKey = attribute.Key("aws.dynamodb.exclusive_start_table") - - // AWSDynamoDBGlobalSecondaryIndexUpdatesKey is the attribute Key conforming to - // the "aws.dynamodb.global_secondary_index_updates" semantic conventions. It - // represents the JSON-serialized value of each item in the - // `GlobalSecondaryIndexUpdates` request field. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{ "Create": { "IndexName": "string", "KeySchema": [ { - // "AttributeName": "string", "KeyType": "string" } ], "Projection": { - // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, - // "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits": - // number } }" - AWSDynamoDBGlobalSecondaryIndexUpdatesKey = attribute.Key("aws.dynamodb.global_secondary_index_updates") - - // AWSDynamoDBGlobalSecondaryIndexesKey is the attribute Key conforming to the - // "aws.dynamodb.global_secondary_indexes" semantic conventions. It represents - // the JSON-serialized value of each item of the `GlobalSecondaryIndexes` - // request field. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{ "IndexName": "string", "KeySchema": [ { "AttributeName": - // "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ - // "string" ], "ProjectionType": "string" }, "ProvisionedThroughput": { - // "ReadCapacityUnits": number, "WriteCapacityUnits": number } }" - AWSDynamoDBGlobalSecondaryIndexesKey = attribute.Key("aws.dynamodb.global_secondary_indexes") - - // AWSDynamoDBIndexNameKey is the attribute Key conforming to the - // "aws.dynamodb.index_name" semantic conventions. It represents the value of - // the `IndexName` request parameter. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "name_to_group" - AWSDynamoDBIndexNameKey = attribute.Key("aws.dynamodb.index_name") - - // AWSDynamoDBItemCollectionMetricsKey is the attribute Key conforming to the - // "aws.dynamodb.item_collection_metrics" semantic conventions. It represents - // the JSON-serialized value of the `ItemCollectionMetrics` response field. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{ "string" : [ { "ItemCollectionKey": { "string" : { "B": blob, - // "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { "string" : - // "AttributeValue" }, "N": "string", "NS": [ "string" ], "NULL": boolean, "S": - // "string", "SS": [ "string" ] } }, "SizeEstimateRangeGB": [ number ] } ] }" - AWSDynamoDBItemCollectionMetricsKey = attribute.Key("aws.dynamodb.item_collection_metrics") - - // AWSDynamoDBLimitKey is the attribute Key conforming to the - // "aws.dynamodb.limit" semantic conventions. It represents the value of the - // `Limit` request parameter. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 10 - AWSDynamoDBLimitKey = attribute.Key("aws.dynamodb.limit") - - // AWSDynamoDBLocalSecondaryIndexesKey is the attribute Key conforming to the - // "aws.dynamodb.local_secondary_indexes" semantic conventions. It represents - // the JSON-serialized value of each item of the `LocalSecondaryIndexes` request - // field. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{ "IndexArn": "string", "IndexName": "string", "IndexSizeBytes": - // number, "ItemCount": number, "KeySchema": [ { "AttributeName": "string", - // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], - // "ProjectionType": "string" } }" - AWSDynamoDBLocalSecondaryIndexesKey = attribute.Key("aws.dynamodb.local_secondary_indexes") - - // AWSDynamoDBProjectionKey is the attribute Key conforming to the - // "aws.dynamodb.projection" semantic conventions. It represents the value of - // the `ProjectionExpression` request parameter. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Title", "Title, Price, Color", "Title, Description, RelatedItems, - // ProductReviews" - AWSDynamoDBProjectionKey = attribute.Key("aws.dynamodb.projection") - - // AWSDynamoDBProvisionedReadCapacityKey is the attribute Key conforming to the - // "aws.dynamodb.provisioned_read_capacity" semantic conventions. It represents - // the value of the `ProvisionedThroughput.ReadCapacityUnits` request parameter. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1.0, 2.0 - AWSDynamoDBProvisionedReadCapacityKey = attribute.Key("aws.dynamodb.provisioned_read_capacity") - - // AWSDynamoDBProvisionedWriteCapacityKey is the attribute Key conforming to the - // "aws.dynamodb.provisioned_write_capacity" semantic conventions. It represents - // the value of the `ProvisionedThroughput.WriteCapacityUnits` request - // parameter. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1.0, 2.0 - AWSDynamoDBProvisionedWriteCapacityKey = attribute.Key("aws.dynamodb.provisioned_write_capacity") - - // AWSDynamoDBScanForwardKey is the attribute Key conforming to the - // "aws.dynamodb.scan_forward" semantic conventions. It represents the value of - // the `ScanIndexForward` request parameter. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - AWSDynamoDBScanForwardKey = attribute.Key("aws.dynamodb.scan_forward") - - // AWSDynamoDBScannedCountKey is the attribute Key conforming to the - // "aws.dynamodb.scanned_count" semantic conventions. It represents the value of - // the `ScannedCount` response parameter. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 50 - AWSDynamoDBScannedCountKey = attribute.Key("aws.dynamodb.scanned_count") - - // AWSDynamoDBSegmentKey is the attribute Key conforming to the - // "aws.dynamodb.segment" semantic conventions. It represents the value of the - // `Segment` request parameter. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 10 - AWSDynamoDBSegmentKey = attribute.Key("aws.dynamodb.segment") - - // AWSDynamoDBSelectKey is the attribute Key conforming to the - // "aws.dynamodb.select" semantic conventions. It represents the value of the - // `Select` request parameter. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ALL_ATTRIBUTES", "COUNT" - AWSDynamoDBSelectKey = attribute.Key("aws.dynamodb.select") - - // AWSDynamoDBTableCountKey is the attribute Key conforming to the - // "aws.dynamodb.table_count" semantic conventions. It represents the number of - // items in the `TableNames` response parameter. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 20 - AWSDynamoDBTableCountKey = attribute.Key("aws.dynamodb.table_count") - - // AWSDynamoDBTableNamesKey is the attribute Key conforming to the - // "aws.dynamodb.table_names" semantic conventions. It represents the keys in - // the `RequestItems` object field. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Users", "Cats" - AWSDynamoDBTableNamesKey = attribute.Key("aws.dynamodb.table_names") - - // AWSDynamoDBTotalSegmentsKey is the attribute Key conforming to the - // "aws.dynamodb.total_segments" semantic conventions. It represents the value - // of the `TotalSegments` request parameter. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 100 - AWSDynamoDBTotalSegmentsKey = attribute.Key("aws.dynamodb.total_segments") - - // AWSECSClusterARNKey is the attribute Key conforming to the - // "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an - // [ECS cluster]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster" - // - // [ECS cluster]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html - AWSECSClusterARNKey = attribute.Key("aws.ecs.cluster.arn") - - // AWSECSContainerARNKey is the attribute Key conforming to the - // "aws.ecs.container.arn" semantic conventions. It represents the Amazon - // Resource Name (ARN) of an [ECS container instance]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "arn:aws:ecs:us-west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9" - // - // [ECS container instance]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html - AWSECSContainerARNKey = attribute.Key("aws.ecs.container.arn") - - // AWSECSLaunchtypeKey is the attribute Key conforming to the - // "aws.ecs.launchtype" semantic conventions. It represents the [launch type] - // for an ECS task. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [launch type]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html - AWSECSLaunchtypeKey = attribute.Key("aws.ecs.launchtype") - - // AWSECSTaskARNKey is the attribute Key conforming to the "aws.ecs.task.arn" - // semantic conventions. It represents the ARN of a running [ECS task]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "arn:aws:ecs:us-west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b", - // "arn:aws:ecs:us-west-1:123456789123:task/my-cluster/task-id/23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd" - // - // [ECS task]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids - AWSECSTaskARNKey = attribute.Key("aws.ecs.task.arn") - - // AWSECSTaskFamilyKey is the attribute Key conforming to the - // "aws.ecs.task.family" semantic conventions. It represents the family name of - // the [ECS task definition] used to create the ECS task. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "opentelemetry-family" - // - // [ECS task definition]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html - AWSECSTaskFamilyKey = attribute.Key("aws.ecs.task.family") - - // AWSECSTaskIDKey is the attribute Key conforming to the "aws.ecs.task.id" - // semantic conventions. It represents the ID of a running ECS task. The ID MUST - // be extracted from `task.arn`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "10838bed-421f-43ef-870a-f43feacbbb5b", - // "23ebb8ac-c18f-46c6-8bbe-d55d0e37cfbd" - AWSECSTaskIDKey = attribute.Key("aws.ecs.task.id") - - // AWSECSTaskRevisionKey is the attribute Key conforming to the - // "aws.ecs.task.revision" semantic conventions. It represents the revision for - // the task definition used to create the ECS task. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "8", "26" - AWSECSTaskRevisionKey = attribute.Key("aws.ecs.task.revision") - - // AWSEKSClusterARNKey is the attribute Key conforming to the - // "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an EKS - // cluster. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster" - AWSEKSClusterARNKey = attribute.Key("aws.eks.cluster.arn") - - // AWSExtendedRequestIDKey is the attribute Key conforming to the - // "aws.extended_request_id" semantic conventions. It represents the AWS - // extended request ID as returned in the response header `x-amz-id-2`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "wzHcyEWfmOGDIE5QOhTAqFDoDWP3y8IUvpNINCwL9N4TEHbUw0/gZJ+VZTmCNCWR7fezEN3eCiQ=" - AWSExtendedRequestIDKey = attribute.Key("aws.extended_request_id") - - // AWSKinesisStreamNameKey is the attribute Key conforming to the - // "aws.kinesis.stream_name" semantic conventions. It represents the name of the - // AWS Kinesis [stream] the request refers to. Corresponds to the - // `--stream-name` parameter of the Kinesis [describe-stream] operation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "some-stream-name" - // - // [stream]: https://docs.aws.amazon.com/streams/latest/dev/introduction.html - // [describe-stream]: https://docs.aws.amazon.com/cli/latest/reference/kinesis/describe-stream.html - AWSKinesisStreamNameKey = attribute.Key("aws.kinesis.stream_name") - - // AWSLambdaInvokedARNKey is the attribute Key conforming to the - // "aws.lambda.invoked_arn" semantic conventions. It represents the full invoked - // ARN as provided on the `Context` passed to the function ( - // `Lambda-Runtime-Invoked-Function-Arn` header on the - // `/runtime/invocation/next` applicable). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "arn:aws:lambda:us-east-1:123456:function:myfunction:myalias" - // Note: This may be different from `cloud.resource_id` if an alias is involved. - AWSLambdaInvokedARNKey = attribute.Key("aws.lambda.invoked_arn") - - // AWSLambdaResourceMappingIDKey is the attribute Key conforming to the - // "aws.lambda.resource_mapping.id" semantic conventions. It represents the UUID - // of the [AWS Lambda EvenSource Mapping]. An event source is mapped to a lambda - // function. It's contents are read by Lambda and used to trigger a function. - // This isn't available in the lambda execution context or the lambda runtime - // environtment. This is going to be populated by the AWS SDK for each language - // when that UUID is present. Some of these operations are - // Create/Delete/Get/List/Update EventSourceMapping. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "587ad24b-03b9-4413-8202-bbd56b36e5b7" - // - // [AWS Lambda EvenSource Mapping]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html - AWSLambdaResourceMappingIDKey = attribute.Key("aws.lambda.resource_mapping.id") - - // AWSLogGroupARNsKey is the attribute Key conforming to the - // "aws.log.group.arns" semantic conventions. It represents the Amazon Resource - // Name(s) (ARN) of the AWS log group(s). - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*" - // Note: See the [log group ARN format documentation]. - // - // [log group ARN format documentation]: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format - AWSLogGroupARNsKey = attribute.Key("aws.log.group.arns") - - // AWSLogGroupNamesKey is the attribute Key conforming to the - // "aws.log.group.names" semantic conventions. It represents the name(s) of the - // AWS log group(s) an application is writing to. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/aws/lambda/my-function", "opentelemetry-service" - // Note: Multiple log groups must be supported for cases like multi-container - // applications, where a single application has sidecar containers, and each - // write to their own log group. - AWSLogGroupNamesKey = attribute.Key("aws.log.group.names") - - // AWSLogStreamARNsKey is the attribute Key conforming to the - // "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of the - // AWS log stream(s). - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log-stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b" - // Note: See the [log stream ARN format documentation]. One log group can - // contain several log streams, so these ARNs necessarily identify both a log - // group and a log stream. - // - // [log stream ARN format documentation]: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format - AWSLogStreamARNsKey = attribute.Key("aws.log.stream.arns") - - // AWSLogStreamNamesKey is the attribute Key conforming to the - // "aws.log.stream.names" semantic conventions. It represents the name(s) of the - // AWS log stream(s) an application is writing to. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "logs/main/10838bed-421f-43ef-870a-f43feacbbb5b" - AWSLogStreamNamesKey = attribute.Key("aws.log.stream.names") - - // AWSRequestIDKey is the attribute Key conforming to the "aws.request_id" - // semantic conventions. It represents the AWS request ID as returned in the - // response headers `x-amzn-requestid`, `x-amzn-request-id` or - // `x-amz-request-id`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "79b9da39-b7ae-508a-a6bc-864b2829c622", "C9ER4AJX75574TDJ" - AWSRequestIDKey = attribute.Key("aws.request_id") - - // AWSS3BucketKey is the attribute Key conforming to the "aws.s3.bucket" - // semantic conventions. It represents the S3 bucket name the request refers to. - // Corresponds to the `--bucket` parameter of the [S3 API] operations. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "some-bucket-name" - // Note: The `bucket` attribute is applicable to all S3 operations that - // reference a bucket, i.e. that require the bucket name as a mandatory - // parameter. - // This applies to almost all S3 operations except `list-buckets`. - // - // [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html - AWSS3BucketKey = attribute.Key("aws.s3.bucket") - - // AWSS3CopySourceKey is the attribute Key conforming to the - // "aws.s3.copy_source" semantic conventions. It represents the source object - // (in the form `bucket`/`key`) for the copy operation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "someFile.yml" - // Note: The `copy_source` attribute applies to S3 copy operations and - // corresponds to the `--copy-source` parameter - // of the [copy-object operation within the S3 API]. - // This applies in particular to the following operations: - // - // - [copy-object] - // - [upload-part-copy] - // - // - // [copy-object operation within the S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html - // [copy-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html - // [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html - AWSS3CopySourceKey = attribute.Key("aws.s3.copy_source") - - // AWSS3DeleteKey is the attribute Key conforming to the "aws.s3.delete" - // semantic conventions. It represents the delete request container that - // specifies the objects to be deleted. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "Objects=[{Key=string,VersionId=string},{Key=string,VersionId=string}],Quiet=boolean" - // Note: The `delete` attribute is only applicable to the [delete-object] - // operation. - // The `delete` attribute corresponds to the `--delete` parameter of the - // [delete-objects operation within the S3 API]. - // - // [delete-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html - // [delete-objects operation within the S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-objects.html - AWSS3DeleteKey = attribute.Key("aws.s3.delete") - - // AWSS3KeyKey is the attribute Key conforming to the "aws.s3.key" semantic - // conventions. It represents the S3 object key the request refers to. - // Corresponds to the `--key` parameter of the [S3 API] operations. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "someFile.yml" - // Note: The `key` attribute is applicable to all object-related S3 operations, - // i.e. that require the object key as a mandatory parameter. - // This applies in particular to the following operations: - // - // - [copy-object] - // - [delete-object] - // - [get-object] - // - [head-object] - // - [put-object] - // - [restore-object] - // - [select-object-content] - // - [abort-multipart-upload] - // - [complete-multipart-upload] - // - [create-multipart-upload] - // - [list-parts] - // - [upload-part] - // - [upload-part-copy] - // - // - // [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html - // [copy-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html - // [delete-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html - // [get-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/get-object.html - // [head-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/head-object.html - // [put-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html - // [restore-object]: https://docs.aws.amazon.com/cli/latest/reference/s3api/restore-object.html - // [select-object-content]: https://docs.aws.amazon.com/cli/latest/reference/s3api/select-object-content.html - // [abort-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html - // [complete-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html - // [create-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/create-multipart-upload.html - // [list-parts]: https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html - // [upload-part]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html - // [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html - AWSS3KeyKey = attribute.Key("aws.s3.key") - - // AWSS3PartNumberKey is the attribute Key conforming to the - // "aws.s3.part_number" semantic conventions. It represents the part number of - // the part being uploaded in a multipart-upload operation. This is a positive - // integer between 1 and 10,000. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 3456 - // Note: The `part_number` attribute is only applicable to the [upload-part] - // and [upload-part-copy] operations. - // The `part_number` attribute corresponds to the `--part-number` parameter of - // the - // [upload-part operation within the S3 API]. - // - // [upload-part]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html - // [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html - // [upload-part operation within the S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html - AWSS3PartNumberKey = attribute.Key("aws.s3.part_number") - - // AWSS3UploadIDKey is the attribute Key conforming to the "aws.s3.upload_id" - // semantic conventions. It represents the upload ID that identifies the - // multipart upload. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "dfRtDYWFbkRONycy.Yxwh66Yjlx.cph0gtNBtJ" - // Note: The `upload_id` attribute applies to S3 multipart-upload operations and - // corresponds to the `--upload-id` parameter - // of the [S3 API] multipart operations. - // This applies in particular to the following operations: - // - // - [abort-multipart-upload] - // - [complete-multipart-upload] - // - [list-parts] - // - [upload-part] - // - [upload-part-copy] - // - // - // [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html - // [abort-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html - // [complete-multipart-upload]: https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html - // [list-parts]: https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html - // [upload-part]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html - // [upload-part-copy]: https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html - AWSS3UploadIDKey = attribute.Key("aws.s3.upload_id") - - // AWSSecretsmanagerSecretARNKey is the attribute Key conforming to the - // "aws.secretsmanager.secret.arn" semantic conventions. It represents the ARN - // of the Secret stored in the Secrets Mangger. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "arn:aws:secretsmanager:us-east-1:123456789012:secret:SecretName-6RandomCharacters" - AWSSecretsmanagerSecretARNKey = attribute.Key("aws.secretsmanager.secret.arn") - - // AWSSNSTopicARNKey is the attribute Key conforming to the "aws.sns.topic.arn" - // semantic conventions. It represents the ARN of the AWS SNS Topic. An Amazon - // SNS [topic] is a logical access point that acts as a communication channel. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "arn:aws:sns:us-east-1:123456789012:mystack-mytopic-NZJ5JSMVGFIE" - // - // [topic]: https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html - AWSSNSTopicARNKey = attribute.Key("aws.sns.topic.arn") - - // AWSSQSQueueURLKey is the attribute Key conforming to the "aws.sqs.queue.url" - // semantic conventions. It represents the URL of the AWS SQS Queue. It's a - // unique identifier for a queue in Amazon Simple Queue Service (SQS) and is - // used to access the queue and perform actions on it. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue" - AWSSQSQueueURLKey = attribute.Key("aws.sqs.queue.url") - - // AWSStepFunctionsActivityARNKey is the attribute Key conforming to the - // "aws.step_functions.activity.arn" semantic conventions. It represents the ARN - // of the AWS Step Functions Activity. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "arn:aws:states:us-east-1:123456789012:activity:get-greeting" - AWSStepFunctionsActivityARNKey = attribute.Key("aws.step_functions.activity.arn") - - // AWSStepFunctionsStateMachineARNKey is the attribute Key conforming to the - // "aws.step_functions.state_machine.arn" semantic conventions. It represents - // the ARN of the AWS Step Functions State Machine. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "arn:aws:states:us-east-1:123456789012:stateMachine:myStateMachine:1" - AWSStepFunctionsStateMachineARNKey = attribute.Key("aws.step_functions.state_machine.arn") -) - -// AWSBedrockGuardrailID returns an attribute KeyValue conforming to the -// "aws.bedrock.guardrail.id" semantic conventions. It represents the unique -// identifier of the AWS Bedrock Guardrail. A [guardrail] helps safeguard and -// prevent unwanted behavior from model responses or user messages. -// -// [guardrail]: https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html -func AWSBedrockGuardrailID(val string) attribute.KeyValue { - return AWSBedrockGuardrailIDKey.String(val) -} - -// AWSBedrockKnowledgeBaseID returns an attribute KeyValue conforming to the -// "aws.bedrock.knowledge_base.id" semantic conventions. It represents the unique -// identifier of the AWS Bedrock Knowledge base. A [knowledge base] is a bank of -// information that can be queried by models to generate more relevant responses -// and augment prompts. -// -// [knowledge base]: https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base.html -func AWSBedrockKnowledgeBaseID(val string) attribute.KeyValue { - return AWSBedrockKnowledgeBaseIDKey.String(val) -} - -// AWSDynamoDBAttributeDefinitions returns an attribute KeyValue conforming to -// the "aws.dynamodb.attribute_definitions" semantic conventions. It represents -// the JSON-serialized value of each item in the `AttributeDefinitions` request -// field. -func AWSDynamoDBAttributeDefinitions(val ...string) attribute.KeyValue { - return AWSDynamoDBAttributeDefinitionsKey.StringSlice(val) -} - -// AWSDynamoDBAttributesToGet returns an attribute KeyValue conforming to the -// "aws.dynamodb.attributes_to_get" semantic conventions. It represents the value -// of the `AttributesToGet` request parameter. -func AWSDynamoDBAttributesToGet(val ...string) attribute.KeyValue { - return AWSDynamoDBAttributesToGetKey.StringSlice(val) -} - -// AWSDynamoDBConsistentRead returns an attribute KeyValue conforming to the -// "aws.dynamodb.consistent_read" semantic conventions. It represents the value -// of the `ConsistentRead` request parameter. -func AWSDynamoDBConsistentRead(val bool) attribute.KeyValue { - return AWSDynamoDBConsistentReadKey.Bool(val) -} - -// AWSDynamoDBConsumedCapacity returns an attribute KeyValue conforming to the -// "aws.dynamodb.consumed_capacity" semantic conventions. It represents the -// JSON-serialized value of each item in the `ConsumedCapacity` response field. -func AWSDynamoDBConsumedCapacity(val ...string) attribute.KeyValue { - return AWSDynamoDBConsumedCapacityKey.StringSlice(val) -} - -// AWSDynamoDBCount returns an attribute KeyValue conforming to the -// "aws.dynamodb.count" semantic conventions. It represents the value of the -// `Count` response parameter. -func AWSDynamoDBCount(val int) attribute.KeyValue { - return AWSDynamoDBCountKey.Int(val) -} - -// AWSDynamoDBExclusiveStartTable returns an attribute KeyValue conforming to the -// "aws.dynamodb.exclusive_start_table" semantic conventions. It represents the -// value of the `ExclusiveStartTableName` request parameter. -func AWSDynamoDBExclusiveStartTable(val string) attribute.KeyValue { - return AWSDynamoDBExclusiveStartTableKey.String(val) -} - -// AWSDynamoDBGlobalSecondaryIndexUpdates returns an attribute KeyValue -// conforming to the "aws.dynamodb.global_secondary_index_updates" semantic -// conventions. It represents the JSON-serialized value of each item in the -// `GlobalSecondaryIndexUpdates` request field. -func AWSDynamoDBGlobalSecondaryIndexUpdates(val ...string) attribute.KeyValue { - return AWSDynamoDBGlobalSecondaryIndexUpdatesKey.StringSlice(val) -} - -// AWSDynamoDBGlobalSecondaryIndexes returns an attribute KeyValue conforming to -// the "aws.dynamodb.global_secondary_indexes" semantic conventions. It -// represents the JSON-serialized value of each item of the -// `GlobalSecondaryIndexes` request field. -func AWSDynamoDBGlobalSecondaryIndexes(val ...string) attribute.KeyValue { - return AWSDynamoDBGlobalSecondaryIndexesKey.StringSlice(val) -} - -// AWSDynamoDBIndexName returns an attribute KeyValue conforming to the -// "aws.dynamodb.index_name" semantic conventions. It represents the value of the -// `IndexName` request parameter. -func AWSDynamoDBIndexName(val string) attribute.KeyValue { - return AWSDynamoDBIndexNameKey.String(val) -} - -// AWSDynamoDBItemCollectionMetrics returns an attribute KeyValue conforming to -// the "aws.dynamodb.item_collection_metrics" semantic conventions. It represents -// the JSON-serialized value of the `ItemCollectionMetrics` response field. -func AWSDynamoDBItemCollectionMetrics(val string) attribute.KeyValue { - return AWSDynamoDBItemCollectionMetricsKey.String(val) -} - -// AWSDynamoDBLimit returns an attribute KeyValue conforming to the -// "aws.dynamodb.limit" semantic conventions. It represents the value of the -// `Limit` request parameter. -func AWSDynamoDBLimit(val int) attribute.KeyValue { - return AWSDynamoDBLimitKey.Int(val) -} - -// AWSDynamoDBLocalSecondaryIndexes returns an attribute KeyValue conforming to -// the "aws.dynamodb.local_secondary_indexes" semantic conventions. It represents -// the JSON-serialized value of each item of the `LocalSecondaryIndexes` request -// field. -func AWSDynamoDBLocalSecondaryIndexes(val ...string) attribute.KeyValue { - return AWSDynamoDBLocalSecondaryIndexesKey.StringSlice(val) -} - -// AWSDynamoDBProjection returns an attribute KeyValue conforming to the -// "aws.dynamodb.projection" semantic conventions. It represents the value of the -// `ProjectionExpression` request parameter. -func AWSDynamoDBProjection(val string) attribute.KeyValue { - return AWSDynamoDBProjectionKey.String(val) -} - -// AWSDynamoDBProvisionedReadCapacity returns an attribute KeyValue conforming to -// the "aws.dynamodb.provisioned_read_capacity" semantic conventions. It -// represents the value of the `ProvisionedThroughput.ReadCapacityUnits` request -// parameter. -func AWSDynamoDBProvisionedReadCapacity(val float64) attribute.KeyValue { - return AWSDynamoDBProvisionedReadCapacityKey.Float64(val) -} - -// AWSDynamoDBProvisionedWriteCapacity returns an attribute KeyValue conforming -// to the "aws.dynamodb.provisioned_write_capacity" semantic conventions. It -// represents the value of the `ProvisionedThroughput.WriteCapacityUnits` request -// parameter. -func AWSDynamoDBProvisionedWriteCapacity(val float64) attribute.KeyValue { - return AWSDynamoDBProvisionedWriteCapacityKey.Float64(val) -} - -// AWSDynamoDBScanForward returns an attribute KeyValue conforming to the -// "aws.dynamodb.scan_forward" semantic conventions. It represents the value of -// the `ScanIndexForward` request parameter. -func AWSDynamoDBScanForward(val bool) attribute.KeyValue { - return AWSDynamoDBScanForwardKey.Bool(val) -} - -// AWSDynamoDBScannedCount returns an attribute KeyValue conforming to the -// "aws.dynamodb.scanned_count" semantic conventions. It represents the value of -// the `ScannedCount` response parameter. -func AWSDynamoDBScannedCount(val int) attribute.KeyValue { - return AWSDynamoDBScannedCountKey.Int(val) -} - -// AWSDynamoDBSegment returns an attribute KeyValue conforming to the -// "aws.dynamodb.segment" semantic conventions. It represents the value of the -// `Segment` request parameter. -func AWSDynamoDBSegment(val int) attribute.KeyValue { - return AWSDynamoDBSegmentKey.Int(val) -} - -// AWSDynamoDBSelect returns an attribute KeyValue conforming to the -// "aws.dynamodb.select" semantic conventions. It represents the value of the -// `Select` request parameter. -func AWSDynamoDBSelect(val string) attribute.KeyValue { - return AWSDynamoDBSelectKey.String(val) -} - -// AWSDynamoDBTableCount returns an attribute KeyValue conforming to the -// "aws.dynamodb.table_count" semantic conventions. It represents the number of -// items in the `TableNames` response parameter. -func AWSDynamoDBTableCount(val int) attribute.KeyValue { - return AWSDynamoDBTableCountKey.Int(val) -} - -// AWSDynamoDBTableNames returns an attribute KeyValue conforming to the -// "aws.dynamodb.table_names" semantic conventions. It represents the keys in the -// `RequestItems` object field. -func AWSDynamoDBTableNames(val ...string) attribute.KeyValue { - return AWSDynamoDBTableNamesKey.StringSlice(val) -} - -// AWSDynamoDBTotalSegments returns an attribute KeyValue conforming to the -// "aws.dynamodb.total_segments" semantic conventions. It represents the value of -// the `TotalSegments` request parameter. -func AWSDynamoDBTotalSegments(val int) attribute.KeyValue { - return AWSDynamoDBTotalSegmentsKey.Int(val) -} - -// AWSECSClusterARN returns an attribute KeyValue conforming to the -// "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an -// [ECS cluster]. -// -// [ECS cluster]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html -func AWSECSClusterARN(val string) attribute.KeyValue { - return AWSECSClusterARNKey.String(val) -} - -// AWSECSContainerARN returns an attribute KeyValue conforming to the -// "aws.ecs.container.arn" semantic conventions. It represents the Amazon -// Resource Name (ARN) of an [ECS container instance]. -// -// [ECS container instance]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html -func AWSECSContainerARN(val string) attribute.KeyValue { - return AWSECSContainerARNKey.String(val) -} - -// AWSECSTaskARN returns an attribute KeyValue conforming to the -// "aws.ecs.task.arn" semantic conventions. It represents the ARN of a running -// [ECS task]. -// -// [ECS task]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids -func AWSECSTaskARN(val string) attribute.KeyValue { - return AWSECSTaskARNKey.String(val) -} - -// AWSECSTaskFamily returns an attribute KeyValue conforming to the -// "aws.ecs.task.family" semantic conventions. It represents the family name of -// the [ECS task definition] used to create the ECS task. -// -// [ECS task definition]: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html -func AWSECSTaskFamily(val string) attribute.KeyValue { - return AWSECSTaskFamilyKey.String(val) -} - -// AWSECSTaskID returns an attribute KeyValue conforming to the "aws.ecs.task.id" -// semantic conventions. It represents the ID of a running ECS task. The ID MUST -// be extracted from `task.arn`. -func AWSECSTaskID(val string) attribute.KeyValue { - return AWSECSTaskIDKey.String(val) -} - -// AWSECSTaskRevision returns an attribute KeyValue conforming to the -// "aws.ecs.task.revision" semantic conventions. It represents the revision for -// the task definition used to create the ECS task. -func AWSECSTaskRevision(val string) attribute.KeyValue { - return AWSECSTaskRevisionKey.String(val) -} - -// AWSEKSClusterARN returns an attribute KeyValue conforming to the -// "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an EKS -// cluster. -func AWSEKSClusterARN(val string) attribute.KeyValue { - return AWSEKSClusterARNKey.String(val) -} - -// AWSExtendedRequestID returns an attribute KeyValue conforming to the -// "aws.extended_request_id" semantic conventions. It represents the AWS extended -// request ID as returned in the response header `x-amz-id-2`. -func AWSExtendedRequestID(val string) attribute.KeyValue { - return AWSExtendedRequestIDKey.String(val) -} - -// AWSKinesisStreamName returns an attribute KeyValue conforming to the -// "aws.kinesis.stream_name" semantic conventions. It represents the name of the -// AWS Kinesis [stream] the request refers to. Corresponds to the `--stream-name` -// -// parameter of the Kinesis [describe-stream] operation. -// -// [stream]: https://docs.aws.amazon.com/streams/latest/dev/introduction.html -// -// [describe-stream]: https://docs.aws.amazon.com/cli/latest/reference/kinesis/describe-stream.html -func AWSKinesisStreamName(val string) attribute.KeyValue { - return AWSKinesisStreamNameKey.String(val) -} - -// AWSLambdaInvokedARN returns an attribute KeyValue conforming to the -// "aws.lambda.invoked_arn" semantic conventions. It represents the full invoked -// ARN as provided on the `Context` passed to the function ( -// `Lambda-Runtime-Invoked-Function-Arn` header on the `/runtime/invocation/next` -// -// applicable). -func AWSLambdaInvokedARN(val string) attribute.KeyValue { - return AWSLambdaInvokedARNKey.String(val) -} - -// AWSLambdaResourceMappingID returns an attribute KeyValue conforming to the -// "aws.lambda.resource_mapping.id" semantic conventions. It represents the UUID -// of the [AWS Lambda EvenSource Mapping]. An event source is mapped to a lambda -// function. It's contents are read by Lambda and used to trigger a function. -// This isn't available in the lambda execution context or the lambda runtime -// environtment. This is going to be populated by the AWS SDK for each language -// when that UUID is present. Some of these operations are -// Create/Delete/Get/List/Update EventSourceMapping. -// -// [AWS Lambda EvenSource Mapping]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html -func AWSLambdaResourceMappingID(val string) attribute.KeyValue { - return AWSLambdaResourceMappingIDKey.String(val) -} - -// AWSLogGroupARNs returns an attribute KeyValue conforming to the -// "aws.log.group.arns" semantic conventions. It represents the Amazon Resource -// Name(s) (ARN) of the AWS log group(s). -func AWSLogGroupARNs(val ...string) attribute.KeyValue { - return AWSLogGroupARNsKey.StringSlice(val) -} - -// AWSLogGroupNames returns an attribute KeyValue conforming to the -// "aws.log.group.names" semantic conventions. It represents the name(s) of the -// AWS log group(s) an application is writing to. -func AWSLogGroupNames(val ...string) attribute.KeyValue { - return AWSLogGroupNamesKey.StringSlice(val) -} - -// AWSLogStreamARNs returns an attribute KeyValue conforming to the -// "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of the -// AWS log stream(s). -func AWSLogStreamARNs(val ...string) attribute.KeyValue { - return AWSLogStreamARNsKey.StringSlice(val) -} - -// AWSLogStreamNames returns an attribute KeyValue conforming to the -// "aws.log.stream.names" semantic conventions. It represents the name(s) of the -// AWS log stream(s) an application is writing to. -func AWSLogStreamNames(val ...string) attribute.KeyValue { - return AWSLogStreamNamesKey.StringSlice(val) -} - -// AWSRequestID returns an attribute KeyValue conforming to the "aws.request_id" -// semantic conventions. It represents the AWS request ID as returned in the -// response headers `x-amzn-requestid`, `x-amzn-request-id` or `x-amz-request-id` -// . -func AWSRequestID(val string) attribute.KeyValue { - return AWSRequestIDKey.String(val) -} - -// AWSS3Bucket returns an attribute KeyValue conforming to the "aws.s3.bucket" -// semantic conventions. It represents the S3 bucket name the request refers to. -// Corresponds to the `--bucket` parameter of the [S3 API] operations. -// -// [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html -func AWSS3Bucket(val string) attribute.KeyValue { - return AWSS3BucketKey.String(val) -} - -// AWSS3CopySource returns an attribute KeyValue conforming to the -// "aws.s3.copy_source" semantic conventions. It represents the source object (in -// the form `bucket`/`key`) for the copy operation. -func AWSS3CopySource(val string) attribute.KeyValue { - return AWSS3CopySourceKey.String(val) -} - -// AWSS3Delete returns an attribute KeyValue conforming to the "aws.s3.delete" -// semantic conventions. It represents the delete request container that -// specifies the objects to be deleted. -func AWSS3Delete(val string) attribute.KeyValue { - return AWSS3DeleteKey.String(val) -} - -// AWSS3Key returns an attribute KeyValue conforming to the "aws.s3.key" semantic -// conventions. It represents the S3 object key the request refers to. -// Corresponds to the `--key` parameter of the [S3 API] operations. -// -// [S3 API]: https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html -func AWSS3Key(val string) attribute.KeyValue { - return AWSS3KeyKey.String(val) -} - -// AWSS3PartNumber returns an attribute KeyValue conforming to the -// "aws.s3.part_number" semantic conventions. It represents the part number of -// the part being uploaded in a multipart-upload operation. This is a positive -// integer between 1 and 10,000. -func AWSS3PartNumber(val int) attribute.KeyValue { - return AWSS3PartNumberKey.Int(val) -} - -// AWSS3UploadID returns an attribute KeyValue conforming to the -// "aws.s3.upload_id" semantic conventions. It represents the upload ID that -// identifies the multipart upload. -func AWSS3UploadID(val string) attribute.KeyValue { - return AWSS3UploadIDKey.String(val) -} - -// AWSSecretsmanagerSecretARN returns an attribute KeyValue conforming to the -// "aws.secretsmanager.secret.arn" semantic conventions. It represents the ARN of -// the Secret stored in the Secrets Mangger. -func AWSSecretsmanagerSecretARN(val string) attribute.KeyValue { - return AWSSecretsmanagerSecretARNKey.String(val) -} - -// AWSSNSTopicARN returns an attribute KeyValue conforming to the -// "aws.sns.topic.arn" semantic conventions. It represents the ARN of the AWS SNS -// Topic. An Amazon SNS [topic] is a logical access point that acts as a -// communication channel. -// -// [topic]: https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html -func AWSSNSTopicARN(val string) attribute.KeyValue { - return AWSSNSTopicARNKey.String(val) -} - -// AWSSQSQueueURL returns an attribute KeyValue conforming to the -// "aws.sqs.queue.url" semantic conventions. It represents the URL of the AWS SQS -// Queue. It's a unique identifier for a queue in Amazon Simple Queue Service -// (SQS) and is used to access the queue and perform actions on it. -func AWSSQSQueueURL(val string) attribute.KeyValue { - return AWSSQSQueueURLKey.String(val) -} - -// AWSStepFunctionsActivityARN returns an attribute KeyValue conforming to the -// "aws.step_functions.activity.arn" semantic conventions. It represents the ARN -// of the AWS Step Functions Activity. -func AWSStepFunctionsActivityARN(val string) attribute.KeyValue { - return AWSStepFunctionsActivityARNKey.String(val) -} - -// AWSStepFunctionsStateMachineARN returns an attribute KeyValue conforming to -// the "aws.step_functions.state_machine.arn" semantic conventions. It represents -// the ARN of the AWS Step Functions State Machine. -func AWSStepFunctionsStateMachineARN(val string) attribute.KeyValue { - return AWSStepFunctionsStateMachineARNKey.String(val) -} - -// Enum values for aws.ecs.launchtype -var ( - // Amazon EC2 - // Stability: development - AWSECSLaunchtypeEC2 = AWSECSLaunchtypeKey.String("ec2") - // Amazon Fargate - // Stability: development - AWSECSLaunchtypeFargate = AWSECSLaunchtypeKey.String("fargate") -) - -// Namespace: azure -const ( - // AzureClientIDKey is the attribute Key conforming to the "azure.client.id" - // semantic conventions. It represents the unique identifier of the client - // instance. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "3ba4827d-4422-483f-b59f-85b74211c11d", "storage-client-1" - AzureClientIDKey = attribute.Key("azure.client.id") - - // AzureCosmosDBConnectionModeKey is the attribute Key conforming to the - // "azure.cosmosdb.connection.mode" semantic conventions. It represents the - // cosmos client connection mode. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - AzureCosmosDBConnectionModeKey = attribute.Key("azure.cosmosdb.connection.mode") - - // AzureCosmosDBConsistencyLevelKey is the attribute Key conforming to the - // "azure.cosmosdb.consistency.level" semantic conventions. It represents the - // account or request [consistency level]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Eventual", "ConsistentPrefix", "BoundedStaleness", "Strong", - // "Session" - // - // [consistency level]: https://learn.microsoft.com/azure/cosmos-db/consistency-levels - AzureCosmosDBConsistencyLevelKey = attribute.Key("azure.cosmosdb.consistency.level") - - // AzureCosmosDBOperationContactedRegionsKey is the attribute Key conforming to - // the "azure.cosmosdb.operation.contacted_regions" semantic conventions. It - // represents the list of regions contacted during operation in the order that - // they were contacted. If there is more than one region listed, it indicates - // that the operation was performed on multiple regions i.e. cross-regional - // call. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "North Central US", "Australia East", "Australia Southeast" - // Note: Region name matches the format of `displayName` in [Azure Location API] - // - // [Azure Location API]: https://learn.microsoft.com/rest/api/resources/subscriptions/list-locations - AzureCosmosDBOperationContactedRegionsKey = attribute.Key("azure.cosmosdb.operation.contacted_regions") - - // AzureCosmosDBOperationRequestChargeKey is the attribute Key conforming to the - // "azure.cosmosdb.operation.request_charge" semantic conventions. It represents - // the number of request units consumed by the operation. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 46.18, 1.0 - AzureCosmosDBOperationRequestChargeKey = attribute.Key("azure.cosmosdb.operation.request_charge") - - // AzureCosmosDBRequestBodySizeKey is the attribute Key conforming to the - // "azure.cosmosdb.request.body.size" semantic conventions. It represents the - // request payload size in bytes. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - AzureCosmosDBRequestBodySizeKey = attribute.Key("azure.cosmosdb.request.body.size") - - // AzureCosmosDBResponseSubStatusCodeKey is the attribute Key conforming to the - // "azure.cosmosdb.response.sub_status_code" semantic conventions. It represents - // the cosmos DB sub status code. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1000, 1002 - AzureCosmosDBResponseSubStatusCodeKey = attribute.Key("azure.cosmosdb.response.sub_status_code") - - // AzureResourceProviderNamespaceKey is the attribute Key conforming to the - // "azure.resource_provider.namespace" semantic conventions. It represents the - // [Azure Resource Provider Namespace] as recognized by the client. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Microsoft.Storage", "Microsoft.KeyVault", "Microsoft.ServiceBus" - // - // [Azure Resource Provider Namespace]: https://learn.microsoft.com/azure/azure-resource-manager/management/azure-services-resource-providers - AzureResourceProviderNamespaceKey = attribute.Key("azure.resource_provider.namespace") - - // AzureServiceRequestIDKey is the attribute Key conforming to the - // "azure.service.request.id" semantic conventions. It represents the unique - // identifier of the service request. It's generated by the Azure service and - // returned with the response. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "00000000-0000-0000-0000-000000000000" - AzureServiceRequestIDKey = attribute.Key("azure.service.request.id") -) - -// AzureClientID returns an attribute KeyValue conforming to the -// "azure.client.id" semantic conventions. It represents the unique identifier of -// the client instance. -func AzureClientID(val string) attribute.KeyValue { - return AzureClientIDKey.String(val) -} - -// AzureCosmosDBOperationContactedRegions returns an attribute KeyValue -// conforming to the "azure.cosmosdb.operation.contacted_regions" semantic -// conventions. It represents the list of regions contacted during operation in -// the order that they were contacted. If there is more than one region listed, -// it indicates that the operation was performed on multiple regions i.e. -// cross-regional call. -func AzureCosmosDBOperationContactedRegions(val ...string) attribute.KeyValue { - return AzureCosmosDBOperationContactedRegionsKey.StringSlice(val) -} - -// AzureCosmosDBOperationRequestCharge returns an attribute KeyValue conforming -// to the "azure.cosmosdb.operation.request_charge" semantic conventions. It -// represents the number of request units consumed by the operation. -func AzureCosmosDBOperationRequestCharge(val float64) attribute.KeyValue { - return AzureCosmosDBOperationRequestChargeKey.Float64(val) -} - -// AzureCosmosDBRequestBodySize returns an attribute KeyValue conforming to the -// "azure.cosmosdb.request.body.size" semantic conventions. It represents the -// request payload size in bytes. -func AzureCosmosDBRequestBodySize(val int) attribute.KeyValue { - return AzureCosmosDBRequestBodySizeKey.Int(val) -} - -// AzureCosmosDBResponseSubStatusCode returns an attribute KeyValue conforming to -// the "azure.cosmosdb.response.sub_status_code" semantic conventions. It -// represents the cosmos DB sub status code. -func AzureCosmosDBResponseSubStatusCode(val int) attribute.KeyValue { - return AzureCosmosDBResponseSubStatusCodeKey.Int(val) -} - -// AzureResourceProviderNamespace returns an attribute KeyValue conforming to the -// "azure.resource_provider.namespace" semantic conventions. It represents the -// [Azure Resource Provider Namespace] as recognized by the client. -// -// [Azure Resource Provider Namespace]: https://learn.microsoft.com/azure/azure-resource-manager/management/azure-services-resource-providers -func AzureResourceProviderNamespace(val string) attribute.KeyValue { - return AzureResourceProviderNamespaceKey.String(val) -} - -// AzureServiceRequestID returns an attribute KeyValue conforming to the -// "azure.service.request.id" semantic conventions. It represents the unique -// identifier of the service request. It's generated by the Azure service and -// returned with the response. -func AzureServiceRequestID(val string) attribute.KeyValue { - return AzureServiceRequestIDKey.String(val) -} - -// Enum values for azure.cosmosdb.connection.mode -var ( - // Gateway (HTTP) connection. - // Stability: development - AzureCosmosDBConnectionModeGateway = AzureCosmosDBConnectionModeKey.String("gateway") - // Direct connection. - // Stability: development - AzureCosmosDBConnectionModeDirect = AzureCosmosDBConnectionModeKey.String("direct") -) - -// Enum values for azure.cosmosdb.consistency.level -var ( - // Strong - // Stability: development - AzureCosmosDBConsistencyLevelStrong = AzureCosmosDBConsistencyLevelKey.String("Strong") - // Bounded Staleness - // Stability: development - AzureCosmosDBConsistencyLevelBoundedStaleness = AzureCosmosDBConsistencyLevelKey.String("BoundedStaleness") - // Session - // Stability: development - AzureCosmosDBConsistencyLevelSession = AzureCosmosDBConsistencyLevelKey.String("Session") - // Eventual - // Stability: development - AzureCosmosDBConsistencyLevelEventual = AzureCosmosDBConsistencyLevelKey.String("Eventual") - // Consistent Prefix - // Stability: development - AzureCosmosDBConsistencyLevelConsistentPrefix = AzureCosmosDBConsistencyLevelKey.String("ConsistentPrefix") -) - -// Namespace: browser -const ( - // BrowserBrandsKey is the attribute Key conforming to the "browser.brands" - // semantic conventions. It represents the array of brand name and version - // separated by a space. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: " Not A;Brand 99", "Chromium 99", "Chrome 99" - // Note: This value is intended to be taken from the [UA client hints API] ( - // `navigator.userAgentData.brands`). - // - // [UA client hints API]: https://wicg.github.io/ua-client-hints/#interface - BrowserBrandsKey = attribute.Key("browser.brands") - - // BrowserLanguageKey is the attribute Key conforming to the "browser.language" - // semantic conventions. It represents the preferred language of the user using - // the browser. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "en", "en-US", "fr", "fr-FR" - // Note: This value is intended to be taken from the Navigator API - // `navigator.language`. - BrowserLanguageKey = attribute.Key("browser.language") - - // BrowserMobileKey is the attribute Key conforming to the "browser.mobile" - // semantic conventions. It represents a boolean that is true if the browser is - // running on a mobile device. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: This value is intended to be taken from the [UA client hints API] ( - // `navigator.userAgentData.mobile`). If unavailable, this attribute SHOULD be - // left unset. - // - // [UA client hints API]: https://wicg.github.io/ua-client-hints/#interface - BrowserMobileKey = attribute.Key("browser.mobile") - - // BrowserPlatformKey is the attribute Key conforming to the "browser.platform" - // semantic conventions. It represents the platform on which the browser is - // running. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Windows", "macOS", "Android" - // Note: This value is intended to be taken from the [UA client hints API] ( - // `navigator.userAgentData.platform`). If unavailable, the legacy - // `navigator.platform` API SHOULD NOT be used instead and this attribute SHOULD - // be left unset in order for the values to be consistent. - // The list of possible values is defined in the - // [W3C User-Agent Client Hints specification]. Note that some (but not all) of - // these values can overlap with values in the - // [`os.type` and `os.name` attributes]. However, for consistency, the values in - // the `browser.platform` attribute should capture the exact value that the user - // agent provides. - // - // [UA client hints API]: https://wicg.github.io/ua-client-hints/#interface - // [W3C User-Agent Client Hints specification]: https://wicg.github.io/ua-client-hints/#sec-ch-ua-platform - // [`os.type` and `os.name` attributes]: ./os.md - BrowserPlatformKey = attribute.Key("browser.platform") -) - -// BrowserBrands returns an attribute KeyValue conforming to the "browser.brands" -// semantic conventions. It represents the array of brand name and version -// separated by a space. -func BrowserBrands(val ...string) attribute.KeyValue { - return BrowserBrandsKey.StringSlice(val) -} - -// BrowserLanguage returns an attribute KeyValue conforming to the -// "browser.language" semantic conventions. It represents the preferred language -// of the user using the browser. -func BrowserLanguage(val string) attribute.KeyValue { - return BrowserLanguageKey.String(val) -} - -// BrowserMobile returns an attribute KeyValue conforming to the "browser.mobile" -// semantic conventions. It represents a boolean that is true if the browser is -// running on a mobile device. -func BrowserMobile(val bool) attribute.KeyValue { - return BrowserMobileKey.Bool(val) -} - -// BrowserPlatform returns an attribute KeyValue conforming to the -// "browser.platform" semantic conventions. It represents the platform on which -// the browser is running. -func BrowserPlatform(val string) attribute.KeyValue { - return BrowserPlatformKey.String(val) -} - -// Namespace: cassandra -const ( - // CassandraConsistencyLevelKey is the attribute Key conforming to the - // "cassandra.consistency.level" semantic conventions. It represents the - // consistency level of the query. Based on consistency values from [CQL]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [CQL]: https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html - CassandraConsistencyLevelKey = attribute.Key("cassandra.consistency.level") - - // CassandraCoordinatorDCKey is the attribute Key conforming to the - // "cassandra.coordinator.dc" semantic conventions. It represents the data - // center of the coordinating node for a query. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: us-west-2 - CassandraCoordinatorDCKey = attribute.Key("cassandra.coordinator.dc") - - // CassandraCoordinatorIDKey is the attribute Key conforming to the - // "cassandra.coordinator.id" semantic conventions. It represents the ID of the - // coordinating node for a query. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: be13faa2-8574-4d71-926d-27f16cf8a7af - CassandraCoordinatorIDKey = attribute.Key("cassandra.coordinator.id") - - // CassandraPageSizeKey is the attribute Key conforming to the - // "cassandra.page.size" semantic conventions. It represents the fetch size used - // for paging, i.e. how many rows will be returned at once. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 5000 - CassandraPageSizeKey = attribute.Key("cassandra.page.size") - - // CassandraQueryIdempotentKey is the attribute Key conforming to the - // "cassandra.query.idempotent" semantic conventions. It represents the whether - // or not the query is idempotent. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - CassandraQueryIdempotentKey = attribute.Key("cassandra.query.idempotent") - - // CassandraSpeculativeExecutionCountKey is the attribute Key conforming to the - // "cassandra.speculative_execution.count" semantic conventions. It represents - // the number of times a query was speculatively executed. Not set or `0` if the - // query was not executed speculatively. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0, 2 - CassandraSpeculativeExecutionCountKey = attribute.Key("cassandra.speculative_execution.count") -) - -// CassandraCoordinatorDC returns an attribute KeyValue conforming to the -// "cassandra.coordinator.dc" semantic conventions. It represents the data center -// of the coordinating node for a query. -func CassandraCoordinatorDC(val string) attribute.KeyValue { - return CassandraCoordinatorDCKey.String(val) -} - -// CassandraCoordinatorID returns an attribute KeyValue conforming to the -// "cassandra.coordinator.id" semantic conventions. It represents the ID of the -// coordinating node for a query. -func CassandraCoordinatorID(val string) attribute.KeyValue { - return CassandraCoordinatorIDKey.String(val) -} - -// CassandraPageSize returns an attribute KeyValue conforming to the -// "cassandra.page.size" semantic conventions. It represents the fetch size used -// for paging, i.e. how many rows will be returned at once. -func CassandraPageSize(val int) attribute.KeyValue { - return CassandraPageSizeKey.Int(val) -} - -// CassandraQueryIdempotent returns an attribute KeyValue conforming to the -// "cassandra.query.idempotent" semantic conventions. It represents the whether -// or not the query is idempotent. -func CassandraQueryIdempotent(val bool) attribute.KeyValue { - return CassandraQueryIdempotentKey.Bool(val) -} - -// CassandraSpeculativeExecutionCount returns an attribute KeyValue conforming to -// the "cassandra.speculative_execution.count" semantic conventions. It -// represents the number of times a query was speculatively executed. Not set or -// `0` if the query was not executed speculatively. -func CassandraSpeculativeExecutionCount(val int) attribute.KeyValue { - return CassandraSpeculativeExecutionCountKey.Int(val) -} - -// Enum values for cassandra.consistency.level -var ( - // All - // Stability: development - CassandraConsistencyLevelAll = CassandraConsistencyLevelKey.String("all") - // Each Quorum - // Stability: development - CassandraConsistencyLevelEachQuorum = CassandraConsistencyLevelKey.String("each_quorum") - // Quorum - // Stability: development - CassandraConsistencyLevelQuorum = CassandraConsistencyLevelKey.String("quorum") - // Local Quorum - // Stability: development - CassandraConsistencyLevelLocalQuorum = CassandraConsistencyLevelKey.String("local_quorum") - // One - // Stability: development - CassandraConsistencyLevelOne = CassandraConsistencyLevelKey.String("one") - // Two - // Stability: development - CassandraConsistencyLevelTwo = CassandraConsistencyLevelKey.String("two") - // Three - // Stability: development - CassandraConsistencyLevelThree = CassandraConsistencyLevelKey.String("three") - // Local One - // Stability: development - CassandraConsistencyLevelLocalOne = CassandraConsistencyLevelKey.String("local_one") - // Any - // Stability: development - CassandraConsistencyLevelAny = CassandraConsistencyLevelKey.String("any") - // Serial - // Stability: development - CassandraConsistencyLevelSerial = CassandraConsistencyLevelKey.String("serial") - // Local Serial - // Stability: development - CassandraConsistencyLevelLocalSerial = CassandraConsistencyLevelKey.String("local_serial") -) - -// Namespace: cicd -const ( - // CICDPipelineActionNameKey is the attribute Key conforming to the - // "cicd.pipeline.action.name" semantic conventions. It represents the kind of - // action a pipeline run is performing. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "BUILD", "RUN", "SYNC" - CICDPipelineActionNameKey = attribute.Key("cicd.pipeline.action.name") - - // CICDPipelineNameKey is the attribute Key conforming to the - // "cicd.pipeline.name" semantic conventions. It represents the human readable - // name of the pipeline within a CI/CD system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Build and Test", "Lint", "Deploy Go Project", - // "deploy_to_environment" - CICDPipelineNameKey = attribute.Key("cicd.pipeline.name") - - // CICDPipelineResultKey is the attribute Key conforming to the - // "cicd.pipeline.result" semantic conventions. It represents the result of a - // pipeline run. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "success", "failure", "timeout", "skipped" - CICDPipelineResultKey = attribute.Key("cicd.pipeline.result") - - // CICDPipelineRunIDKey is the attribute Key conforming to the - // "cicd.pipeline.run.id" semantic conventions. It represents the unique - // identifier of a pipeline run within a CI/CD system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "120912" - CICDPipelineRunIDKey = attribute.Key("cicd.pipeline.run.id") - - // CICDPipelineRunStateKey is the attribute Key conforming to the - // "cicd.pipeline.run.state" semantic conventions. It represents the pipeline - // run goes through these states during its lifecycle. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "pending", "executing", "finalizing" - CICDPipelineRunStateKey = attribute.Key("cicd.pipeline.run.state") - - // CICDPipelineRunURLFullKey is the attribute Key conforming to the - // "cicd.pipeline.run.url.full" semantic conventions. It represents the [URL] of - // the pipeline run, providing the complete address in order to locate and - // identify the pipeline run. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "https://github.com/open-telemetry/semantic-conventions/actions/runs/9753949763?pr=1075" - // - // [URL]: https://wikipedia.org/wiki/URL - CICDPipelineRunURLFullKey = attribute.Key("cicd.pipeline.run.url.full") - - // CICDPipelineTaskNameKey is the attribute Key conforming to the - // "cicd.pipeline.task.name" semantic conventions. It represents the human - // readable name of a task within a pipeline. Task here most closely aligns with - // a [computing process] in a pipeline. Other terms for tasks include commands, - // steps, and procedures. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Run GoLang Linter", "Go Build", "go-test", "deploy_binary" - // - // [computing process]: https://wikipedia.org/wiki/Pipeline_(computing) - CICDPipelineTaskNameKey = attribute.Key("cicd.pipeline.task.name") - - // CICDPipelineTaskRunIDKey is the attribute Key conforming to the - // "cicd.pipeline.task.run.id" semantic conventions. It represents the unique - // identifier of a task run within a pipeline. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "12097" - CICDPipelineTaskRunIDKey = attribute.Key("cicd.pipeline.task.run.id") - - // CICDPipelineTaskRunResultKey is the attribute Key conforming to the - // "cicd.pipeline.task.run.result" semantic conventions. It represents the - // result of a task run. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "success", "failure", "timeout", "skipped" - CICDPipelineTaskRunResultKey = attribute.Key("cicd.pipeline.task.run.result") - - // CICDPipelineTaskRunURLFullKey is the attribute Key conforming to the - // "cicd.pipeline.task.run.url.full" semantic conventions. It represents the - // [URL] of the pipeline task run, providing the complete address in order to - // locate and identify the pipeline task run. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "https://github.com/open-telemetry/semantic-conventions/actions/runs/9753949763/job/26920038674?pr=1075" - // - // [URL]: https://wikipedia.org/wiki/URL - CICDPipelineTaskRunURLFullKey = attribute.Key("cicd.pipeline.task.run.url.full") - - // CICDPipelineTaskTypeKey is the attribute Key conforming to the - // "cicd.pipeline.task.type" semantic conventions. It represents the type of the - // task within a pipeline. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "build", "test", "deploy" - CICDPipelineTaskTypeKey = attribute.Key("cicd.pipeline.task.type") - - // CICDSystemComponentKey is the attribute Key conforming to the - // "cicd.system.component" semantic conventions. It represents the name of a - // component of the CICD system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "controller", "scheduler", "agent" - CICDSystemComponentKey = attribute.Key("cicd.system.component") - - // CICDWorkerIDKey is the attribute Key conforming to the "cicd.worker.id" - // semantic conventions. It represents the unique identifier of a worker within - // a CICD system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "abc123", "10.0.1.2", "controller" - CICDWorkerIDKey = attribute.Key("cicd.worker.id") - - // CICDWorkerNameKey is the attribute Key conforming to the "cicd.worker.name" - // semantic conventions. It represents the name of a worker within a CICD - // system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "agent-abc", "controller", "Ubuntu LTS" - CICDWorkerNameKey = attribute.Key("cicd.worker.name") - - // CICDWorkerStateKey is the attribute Key conforming to the "cicd.worker.state" - // semantic conventions. It represents the state of a CICD worker / agent. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "idle", "busy", "down" - CICDWorkerStateKey = attribute.Key("cicd.worker.state") - - // CICDWorkerURLFullKey is the attribute Key conforming to the - // "cicd.worker.url.full" semantic conventions. It represents the [URL] of the - // worker, providing the complete address in order to locate and identify the - // worker. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "https://cicd.example.org/worker/abc123" - // - // [URL]: https://wikipedia.org/wiki/URL - CICDWorkerURLFullKey = attribute.Key("cicd.worker.url.full") -) - -// CICDPipelineName returns an attribute KeyValue conforming to the -// "cicd.pipeline.name" semantic conventions. It represents the human readable -// name of the pipeline within a CI/CD system. -func CICDPipelineName(val string) attribute.KeyValue { - return CICDPipelineNameKey.String(val) -} - -// CICDPipelineRunID returns an attribute KeyValue conforming to the -// "cicd.pipeline.run.id" semantic conventions. It represents the unique -// identifier of a pipeline run within a CI/CD system. -func CICDPipelineRunID(val string) attribute.KeyValue { - return CICDPipelineRunIDKey.String(val) -} - -// CICDPipelineRunURLFull returns an attribute KeyValue conforming to the -// "cicd.pipeline.run.url.full" semantic conventions. It represents the [URL] of -// the pipeline run, providing the complete address in order to locate and -// identify the pipeline run. -// -// [URL]: https://wikipedia.org/wiki/URL -func CICDPipelineRunURLFull(val string) attribute.KeyValue { - return CICDPipelineRunURLFullKey.String(val) -} - -// CICDPipelineTaskName returns an attribute KeyValue conforming to the -// "cicd.pipeline.task.name" semantic conventions. It represents the human -// readable name of a task within a pipeline. Task here most closely aligns with -// a [computing process] in a pipeline. Other terms for tasks include commands, -// steps, and procedures. -// -// [computing process]: https://wikipedia.org/wiki/Pipeline_(computing) -func CICDPipelineTaskName(val string) attribute.KeyValue { - return CICDPipelineTaskNameKey.String(val) -} - -// CICDPipelineTaskRunID returns an attribute KeyValue conforming to the -// "cicd.pipeline.task.run.id" semantic conventions. It represents the unique -// identifier of a task run within a pipeline. -func CICDPipelineTaskRunID(val string) attribute.KeyValue { - return CICDPipelineTaskRunIDKey.String(val) -} - -// CICDPipelineTaskRunURLFull returns an attribute KeyValue conforming to the -// "cicd.pipeline.task.run.url.full" semantic conventions. It represents the -// [URL] of the pipeline task run, providing the complete address in order to -// locate and identify the pipeline task run. -// -// [URL]: https://wikipedia.org/wiki/URL -func CICDPipelineTaskRunURLFull(val string) attribute.KeyValue { - return CICDPipelineTaskRunURLFullKey.String(val) -} - -// CICDSystemComponent returns an attribute KeyValue conforming to the -// "cicd.system.component" semantic conventions. It represents the name of a -// component of the CICD system. -func CICDSystemComponent(val string) attribute.KeyValue { - return CICDSystemComponentKey.String(val) -} - -// CICDWorkerID returns an attribute KeyValue conforming to the "cicd.worker.id" -// semantic conventions. It represents the unique identifier of a worker within a -// CICD system. -func CICDWorkerID(val string) attribute.KeyValue { - return CICDWorkerIDKey.String(val) -} - -// CICDWorkerName returns an attribute KeyValue conforming to the -// "cicd.worker.name" semantic conventions. It represents the name of a worker -// within a CICD system. -func CICDWorkerName(val string) attribute.KeyValue { - return CICDWorkerNameKey.String(val) -} - -// CICDWorkerURLFull returns an attribute KeyValue conforming to the -// "cicd.worker.url.full" semantic conventions. It represents the [URL] of the -// worker, providing the complete address in order to locate and identify the -// worker. -// -// [URL]: https://wikipedia.org/wiki/URL -func CICDWorkerURLFull(val string) attribute.KeyValue { - return CICDWorkerURLFullKey.String(val) -} - -// Enum values for cicd.pipeline.action.name -var ( - // The pipeline run is executing a build. - // Stability: development - CICDPipelineActionNameBuild = CICDPipelineActionNameKey.String("BUILD") - // The pipeline run is executing. - // Stability: development - CICDPipelineActionNameRun = CICDPipelineActionNameKey.String("RUN") - // The pipeline run is executing a sync. - // Stability: development - CICDPipelineActionNameSync = CICDPipelineActionNameKey.String("SYNC") -) - -// Enum values for cicd.pipeline.result -var ( - // The pipeline run finished successfully. - // Stability: development - CICDPipelineResultSuccess = CICDPipelineResultKey.String("success") - // The pipeline run did not finish successfully, eg. due to a compile error or a - // failing test. Such failures are usually detected by non-zero exit codes of - // the tools executed in the pipeline run. - // Stability: development - CICDPipelineResultFailure = CICDPipelineResultKey.String("failure") - // The pipeline run failed due to an error in the CICD system, eg. due to the - // worker being killed. - // Stability: development - CICDPipelineResultError = CICDPipelineResultKey.String("error") - // A timeout caused the pipeline run to be interrupted. - // Stability: development - CICDPipelineResultTimeout = CICDPipelineResultKey.String("timeout") - // The pipeline run was cancelled, eg. by a user manually cancelling the - // pipeline run. - // Stability: development - CICDPipelineResultCancellation = CICDPipelineResultKey.String("cancellation") - // The pipeline run was skipped, eg. due to a precondition not being met. - // Stability: development - CICDPipelineResultSkip = CICDPipelineResultKey.String("skip") -) - -// Enum values for cicd.pipeline.run.state -var ( - // The run pending state spans from the event triggering the pipeline run until - // the execution of the run starts (eg. time spent in a queue, provisioning - // agents, creating run resources). - // - // Stability: development - CICDPipelineRunStatePending = CICDPipelineRunStateKey.String("pending") - // The executing state spans the execution of any run tasks (eg. build, test). - // Stability: development - CICDPipelineRunStateExecuting = CICDPipelineRunStateKey.String("executing") - // The finalizing state spans from when the run has finished executing (eg. - // cleanup of run resources). - // Stability: development - CICDPipelineRunStateFinalizing = CICDPipelineRunStateKey.String("finalizing") -) - -// Enum values for cicd.pipeline.task.run.result -var ( - // The task run finished successfully. - // Stability: development - CICDPipelineTaskRunResultSuccess = CICDPipelineTaskRunResultKey.String("success") - // The task run did not finish successfully, eg. due to a compile error or a - // failing test. Such failures are usually detected by non-zero exit codes of - // the tools executed in the task run. - // Stability: development - CICDPipelineTaskRunResultFailure = CICDPipelineTaskRunResultKey.String("failure") - // The task run failed due to an error in the CICD system, eg. due to the worker - // being killed. - // Stability: development - CICDPipelineTaskRunResultError = CICDPipelineTaskRunResultKey.String("error") - // A timeout caused the task run to be interrupted. - // Stability: development - CICDPipelineTaskRunResultTimeout = CICDPipelineTaskRunResultKey.String("timeout") - // The task run was cancelled, eg. by a user manually cancelling the task run. - // Stability: development - CICDPipelineTaskRunResultCancellation = CICDPipelineTaskRunResultKey.String("cancellation") - // The task run was skipped, eg. due to a precondition not being met. - // Stability: development - CICDPipelineTaskRunResultSkip = CICDPipelineTaskRunResultKey.String("skip") -) - -// Enum values for cicd.pipeline.task.type -var ( - // build - // Stability: development - CICDPipelineTaskTypeBuild = CICDPipelineTaskTypeKey.String("build") - // test - // Stability: development - CICDPipelineTaskTypeTest = CICDPipelineTaskTypeKey.String("test") - // deploy - // Stability: development - CICDPipelineTaskTypeDeploy = CICDPipelineTaskTypeKey.String("deploy") -) - -// Enum values for cicd.worker.state -var ( - // The worker is not performing work for the CICD system. It is available to the - // CICD system to perform work on (online / idle). - // Stability: development - CICDWorkerStateAvailable = CICDWorkerStateKey.String("available") - // The worker is performing work for the CICD system. - // Stability: development - CICDWorkerStateBusy = CICDWorkerStateKey.String("busy") - // The worker is not available to the CICD system (disconnected / down). - // Stability: development - CICDWorkerStateOffline = CICDWorkerStateKey.String("offline") -) - -// Namespace: client -const ( - // ClientAddressKey is the attribute Key conforming to the "client.address" - // semantic conventions. It represents the client address - domain name if - // available without reverse DNS lookup; otherwise, IP address or Unix domain - // socket name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "client.example.com", "10.1.2.80", "/tmp/my.sock" - // Note: When observed from the server side, and when communicating through an - // intermediary, `client.address` SHOULD represent the client address behind any - // intermediaries, for example proxies, if it's available. - ClientAddressKey = attribute.Key("client.address") - - // ClientPortKey is the attribute Key conforming to the "client.port" semantic - // conventions. It represents the client port number. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: 65123 - // Note: When observed from the server side, and when communicating through an - // intermediary, `client.port` SHOULD represent the client port behind any - // intermediaries, for example proxies, if it's available. - ClientPortKey = attribute.Key("client.port") -) - -// ClientAddress returns an attribute KeyValue conforming to the "client.address" -// semantic conventions. It represents the client address - domain name if -// available without reverse DNS lookup; otherwise, IP address or Unix domain -// socket name. -func ClientAddress(val string) attribute.KeyValue { - return ClientAddressKey.String(val) -} - -// ClientPort returns an attribute KeyValue conforming to the "client.port" -// semantic conventions. It represents the client port number. -func ClientPort(val int) attribute.KeyValue { - return ClientPortKey.Int(val) -} - -// Namespace: cloud -const ( - // CloudAccountIDKey is the attribute Key conforming to the "cloud.account.id" - // semantic conventions. It represents the cloud account ID the resource is - // assigned to. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "111111111111", "opentelemetry" - CloudAccountIDKey = attribute.Key("cloud.account.id") - - // CloudAvailabilityZoneKey is the attribute Key conforming to the - // "cloud.availability_zone" semantic conventions. It represents the cloud - // regions often have multiple, isolated locations known as zones to increase - // availability. Availability zone represents the zone where the resource is - // running. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "us-east-1c" - // Note: Availability zones are called "zones" on Alibaba Cloud and Google - // Cloud. - CloudAvailabilityZoneKey = attribute.Key("cloud.availability_zone") - - // CloudPlatformKey is the attribute Key conforming to the "cloud.platform" - // semantic conventions. It represents the cloud platform in use. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: The prefix of the service SHOULD match the one specified in - // `cloud.provider`. - CloudPlatformKey = attribute.Key("cloud.platform") - - // CloudProviderKey is the attribute Key conforming to the "cloud.provider" - // semantic conventions. It represents the name of the cloud provider. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - CloudProviderKey = attribute.Key("cloud.provider") - - // CloudRegionKey is the attribute Key conforming to the "cloud.region" semantic - // conventions. It represents the geographical region within a cloud provider. - // When associated with a resource, this attribute specifies the region where - // the resource operates. When calling services or APIs deployed on a cloud, - // this attribute identifies the region where the called destination is - // deployed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "us-central1", "us-east-1" - // Note: Refer to your provider's docs to see the available regions, for example - // [Alibaba Cloud regions], [AWS regions], [Azure regions], - // [Google Cloud regions], or [Tencent Cloud regions]. - // - // [Alibaba Cloud regions]: https://www.alibabacloud.com/help/doc-detail/40654.htm - // [AWS regions]: https://aws.amazon.com/about-aws/global-infrastructure/regions_az/ - // [Azure regions]: https://azure.microsoft.com/global-infrastructure/geographies/ - // [Google Cloud regions]: https://cloud.google.com/about/locations - // [Tencent Cloud regions]: https://www.tencentcloud.com/document/product/213/6091 - CloudRegionKey = attribute.Key("cloud.region") - - // CloudResourceIDKey is the attribute Key conforming to the "cloud.resource_id" - // semantic conventions. It represents the cloud provider-specific native - // identifier of the monitored cloud resource (e.g. an [ARN] on AWS, a - // [fully qualified resource ID] on Azure, a [full resource name] on GCP). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "arn:aws:lambda:REGION:ACCOUNT_ID:function:my-function", - // "//run.googleapis.com/projects/PROJECT_ID/locations/LOCATION_ID/services/SERVICE_ID", - // "/subscriptions//resourceGroups/ - // /providers/Microsoft.Web/sites//functions/" - // Note: On some cloud providers, it may not be possible to determine the full - // ID at startup, - // so it may be necessary to set `cloud.resource_id` as a span attribute - // instead. - // - // The exact value to use for `cloud.resource_id` depends on the cloud provider. - // The following well-known definitions MUST be used if you set this attribute - // and they apply: - // - // - **AWS Lambda:** The function [ARN]. - // Take care not to use the "invoked ARN" directly but replace any - // [alias suffix] - // with the resolved function version, as the same runtime instance may be - // invocable with - // multiple different aliases. - // - **GCP:** The [URI of the resource] - // - **Azure:** The [Fully Qualified Resource ID] of the invoked function, - // *not* the function app, having the form - // - // `/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/` - // . - // This means that a span attribute MUST be used, as an Azure function app - // can host multiple functions that would usually share - // a TracerProvider. - // - // - // [ARN]: https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html - // [fully qualified resource ID]: https://learn.microsoft.com/rest/api/resources/resources/get-by-id - // [full resource name]: https://google.aip.dev/122#full-resource-names - // [ARN]: https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html - // [alias suffix]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html - // [URI of the resource]: https://cloud.google.com/iam/docs/full-resource-names - // [Fully Qualified Resource ID]: https://learn.microsoft.com/rest/api/resources/resources/get-by-id - CloudResourceIDKey = attribute.Key("cloud.resource_id") -) - -// CloudAccountID returns an attribute KeyValue conforming to the -// "cloud.account.id" semantic conventions. It represents the cloud account ID -// the resource is assigned to. -func CloudAccountID(val string) attribute.KeyValue { - return CloudAccountIDKey.String(val) -} - -// CloudAvailabilityZone returns an attribute KeyValue conforming to the -// "cloud.availability_zone" semantic conventions. It represents the cloud -// regions often have multiple, isolated locations known as zones to increase -// availability. Availability zone represents the zone where the resource is -// running. -func CloudAvailabilityZone(val string) attribute.KeyValue { - return CloudAvailabilityZoneKey.String(val) -} - -// CloudRegion returns an attribute KeyValue conforming to the "cloud.region" -// semantic conventions. It represents the geographical region within a cloud -// provider. When associated with a resource, this attribute specifies the region -// where the resource operates. When calling services or APIs deployed on a -// cloud, this attribute identifies the region where the called destination is -// deployed. -func CloudRegion(val string) attribute.KeyValue { - return CloudRegionKey.String(val) -} - -// CloudResourceID returns an attribute KeyValue conforming to the -// "cloud.resource_id" semantic conventions. It represents the cloud -// provider-specific native identifier of the monitored cloud resource (e.g. an -// [ARN] on AWS, a [fully qualified resource ID] on Azure, a [full resource name] -// -// on GCP). -// -// [ARN]: https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html -// [fully qualified resource ID]: https://learn.microsoft.com/rest/api/resources/resources/get-by-id -// [full resource name]: https://google.aip.dev/122#full-resource-names -func CloudResourceID(val string) attribute.KeyValue { - return CloudResourceIDKey.String(val) -} - -// Enum values for cloud.platform -var ( - // Akamai Cloud Compute - // Stability: development - CloudPlatformAkamaiCloudCompute = CloudPlatformKey.String("akamai_cloud.compute") - // Alibaba Cloud Elastic Compute Service - // Stability: development - CloudPlatformAlibabaCloudECS = CloudPlatformKey.String("alibaba_cloud_ecs") - // Alibaba Cloud Function Compute - // Stability: development - CloudPlatformAlibabaCloudFC = CloudPlatformKey.String("alibaba_cloud_fc") - // Red Hat OpenShift on Alibaba Cloud - // Stability: development - CloudPlatformAlibabaCloudOpenShift = CloudPlatformKey.String("alibaba_cloud_openshift") - // AWS Elastic Compute Cloud - // Stability: development - CloudPlatformAWSEC2 = CloudPlatformKey.String("aws_ec2") - // AWS Elastic Container Service - // Stability: development - CloudPlatformAWSECS = CloudPlatformKey.String("aws_ecs") - // AWS Elastic Kubernetes Service - // Stability: development - CloudPlatformAWSEKS = CloudPlatformKey.String("aws_eks") - // AWS Lambda - // Stability: development - CloudPlatformAWSLambda = CloudPlatformKey.String("aws_lambda") - // AWS Elastic Beanstalk - // Stability: development - CloudPlatformAWSElasticBeanstalk = CloudPlatformKey.String("aws_elastic_beanstalk") - // AWS App Runner - // Stability: development - CloudPlatformAWSAppRunner = CloudPlatformKey.String("aws_app_runner") - // Red Hat OpenShift on AWS (ROSA) - // Stability: development - CloudPlatformAWSOpenShift = CloudPlatformKey.String("aws_openshift") - // Azure Virtual Machines - // Stability: development - CloudPlatformAzureVM = CloudPlatformKey.String("azure.vm") - // Azure Container Apps - // Stability: development - CloudPlatformAzureContainerApps = CloudPlatformKey.String("azure.container_apps") - // Azure Container Instances - // Stability: development - CloudPlatformAzureContainerInstances = CloudPlatformKey.String("azure.container_instances") - // Azure Kubernetes Service - // Stability: development - CloudPlatformAzureAKS = CloudPlatformKey.String("azure.aks") - // Azure Functions - // Stability: development - CloudPlatformAzureFunctions = CloudPlatformKey.String("azure.functions") - // Azure App Service - // Stability: development - CloudPlatformAzureAppService = CloudPlatformKey.String("azure.app_service") - // Azure Red Hat OpenShift - // Stability: development - CloudPlatformAzureOpenShift = CloudPlatformKey.String("azure.openshift") - // Google Vertex AI Agent Engine - // Stability: development - CloudPlatformGCPAgentEngine = CloudPlatformKey.String("gcp.agent_engine") - // Google Bare Metal Solution (BMS) - // Stability: development - CloudPlatformGCPBareMetalSolution = CloudPlatformKey.String("gcp_bare_metal_solution") - // Google Cloud Compute Engine (GCE) - // Stability: development - CloudPlatformGCPComputeEngine = CloudPlatformKey.String("gcp_compute_engine") - // Google Cloud Run - // Stability: development - CloudPlatformGCPCloudRun = CloudPlatformKey.String("gcp_cloud_run") - // Google Cloud Kubernetes Engine (GKE) - // Stability: development - CloudPlatformGCPKubernetesEngine = CloudPlatformKey.String("gcp_kubernetes_engine") - // Google Cloud Functions (GCF) - // Stability: development - CloudPlatformGCPCloudFunctions = CloudPlatformKey.String("gcp_cloud_functions") - // Google Cloud App Engine (GAE) - // Stability: development - CloudPlatformGCPAppEngine = CloudPlatformKey.String("gcp_app_engine") - // Red Hat OpenShift on Google Cloud - // Stability: development - CloudPlatformGCPOpenShift = CloudPlatformKey.String("gcp_openshift") - // Server on Hetzner Cloud - // Stability: development - CloudPlatformHetznerCloudServer = CloudPlatformKey.String("hetzner.cloud_server") - // Red Hat OpenShift on IBM Cloud - // Stability: development - CloudPlatformIBMCloudOpenShift = CloudPlatformKey.String("ibm_cloud_openshift") - // Compute on Oracle Cloud Infrastructure (OCI) - // Stability: development - CloudPlatformOracleCloudCompute = CloudPlatformKey.String("oracle_cloud_compute") - // Kubernetes Engine (OKE) on Oracle Cloud Infrastructure (OCI) - // Stability: development - CloudPlatformOracleCloudOKE = CloudPlatformKey.String("oracle_cloud_oke") - // Tencent Cloud Cloud Virtual Machine (CVM) - // Stability: development - CloudPlatformTencentCloudCVM = CloudPlatformKey.String("tencent_cloud_cvm") - // Tencent Cloud Elastic Kubernetes Service (EKS) - // Stability: development - CloudPlatformTencentCloudEKS = CloudPlatformKey.String("tencent_cloud_eks") - // Tencent Cloud Serverless Cloud Function (SCF) - // Stability: development - CloudPlatformTencentCloudSCF = CloudPlatformKey.String("tencent_cloud_scf") - // Vultr Cloud Compute - // Stability: development - CloudPlatformVultrCloudCompute = CloudPlatformKey.String("vultr.cloud_compute") -) - -// Enum values for cloud.provider -var ( - // Akamai Cloud - // Stability: development - CloudProviderAkamaiCloud = CloudProviderKey.String("akamai_cloud") - // Alibaba Cloud - // Stability: development - CloudProviderAlibabaCloud = CloudProviderKey.String("alibaba_cloud") - // Amazon Web Services - // Stability: development - CloudProviderAWS = CloudProviderKey.String("aws") - // Microsoft Azure - // Stability: development - CloudProviderAzure = CloudProviderKey.String("azure") - // Google Cloud Platform - // Stability: development - CloudProviderGCP = CloudProviderKey.String("gcp") - // Heroku Platform as a Service - // Stability: development - CloudProviderHeroku = CloudProviderKey.String("heroku") - // Hetzner - // Stability: development - CloudProviderHetzner = CloudProviderKey.String("hetzner") - // IBM Cloud - // Stability: development - CloudProviderIBMCloud = CloudProviderKey.String("ibm_cloud") - // Oracle Cloud Infrastructure (OCI) - // Stability: development - CloudProviderOracleCloud = CloudProviderKey.String("oracle_cloud") - // Tencent Cloud - // Stability: development - CloudProviderTencentCloud = CloudProviderKey.String("tencent_cloud") - // Vultr - // Stability: development - CloudProviderVultr = CloudProviderKey.String("vultr") -) - -// Namespace: cloudevents -const ( - // CloudEventsEventIDKey is the attribute Key conforming to the - // "cloudevents.event_id" semantic conventions. It represents the [event_id] - // uniquely identifies the event. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "123e4567-e89b-12d3-a456-426614174000", "0001" - // - // [event_id]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id - CloudEventsEventIDKey = attribute.Key("cloudevents.event_id") - - // CloudEventsEventSourceKey is the attribute Key conforming to the - // "cloudevents.event_source" semantic conventions. It represents the [source] - // identifies the context in which an event happened. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "https://github.com/cloudevents", "/cloudevents/spec/pull/123", - // "my-service" - // - // [source]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1 - CloudEventsEventSourceKey = attribute.Key("cloudevents.event_source") - - // CloudEventsEventSpecVersionKey is the attribute Key conforming to the - // "cloudevents.event_spec_version" semantic conventions. It represents the - // [version of the CloudEvents specification] which the event uses. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1.0 - // - // [version of the CloudEvents specification]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion - CloudEventsEventSpecVersionKey = attribute.Key("cloudevents.event_spec_version") - - // CloudEventsEventSubjectKey is the attribute Key conforming to the - // "cloudevents.event_subject" semantic conventions. It represents the [subject] - // of the event in the context of the event producer (identified by source). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: mynewfile.jpg - // - // [subject]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject - CloudEventsEventSubjectKey = attribute.Key("cloudevents.event_subject") - - // CloudEventsEventTypeKey is the attribute Key conforming to the - // "cloudevents.event_type" semantic conventions. It represents the [event_type] - // contains a value describing the type of event related to the originating - // occurrence. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "com.github.pull_request.opened", "com.example.object.deleted.v2" - // - // [event_type]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type - CloudEventsEventTypeKey = attribute.Key("cloudevents.event_type") -) - -// CloudEventsEventID returns an attribute KeyValue conforming to the -// "cloudevents.event_id" semantic conventions. It represents the [event_id] -// uniquely identifies the event. -// -// [event_id]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id -func CloudEventsEventID(val string) attribute.KeyValue { - return CloudEventsEventIDKey.String(val) -} - -// CloudEventsEventSource returns an attribute KeyValue conforming to the -// "cloudevents.event_source" semantic conventions. It represents the [source] -// identifies the context in which an event happened. -// -// [source]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1 -func CloudEventsEventSource(val string) attribute.KeyValue { - return CloudEventsEventSourceKey.String(val) -} - -// CloudEventsEventSpecVersion returns an attribute KeyValue conforming to the -// "cloudevents.event_spec_version" semantic conventions. It represents the -// [version of the CloudEvents specification] which the event uses. -// -// [version of the CloudEvents specification]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion -func CloudEventsEventSpecVersion(val string) attribute.KeyValue { - return CloudEventsEventSpecVersionKey.String(val) -} - -// CloudEventsEventSubject returns an attribute KeyValue conforming to the -// "cloudevents.event_subject" semantic conventions. It represents the [subject] -// of the event in the context of the event producer (identified by source). -// -// [subject]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject -func CloudEventsEventSubject(val string) attribute.KeyValue { - return CloudEventsEventSubjectKey.String(val) -} - -// CloudEventsEventType returns an attribute KeyValue conforming to the -// "cloudevents.event_type" semantic conventions. It represents the [event_type] -// contains a value describing the type of event related to the originating -// occurrence. -// -// [event_type]: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type -func CloudEventsEventType(val string) attribute.KeyValue { - return CloudEventsEventTypeKey.String(val) -} - -// Namespace: cloudfoundry -const ( - // CloudFoundryAppIDKey is the attribute Key conforming to the - // "cloudfoundry.app.id" semantic conventions. It represents the guid of the - // application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d" - // Note: Application instrumentation should use the value from environment - // variable `VCAP_APPLICATION.application_id`. This is the same value as - // reported by `cf app --guid`. - CloudFoundryAppIDKey = attribute.Key("cloudfoundry.app.id") - - // CloudFoundryAppInstanceIDKey is the attribute Key conforming to the - // "cloudfoundry.app.instance.id" semantic conventions. It represents the index - // of the application instance. 0 when just one instance is active. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "0", "1" - // Note: CloudFoundry defines the `instance_id` in the [Loggregator v2 envelope] - // . - // It is used for logs and metrics emitted by CloudFoundry. It is - // supposed to contain the application instance index for applications - // deployed on the runtime. - // - // Application instrumentation should use the value from environment - // variable `CF_INSTANCE_INDEX`. - // - // [Loggregator v2 envelope]: https://github.com/cloudfoundry/loggregator-api#v2-envelope - CloudFoundryAppInstanceIDKey = attribute.Key("cloudfoundry.app.instance.id") - - // CloudFoundryAppNameKey is the attribute Key conforming to the - // "cloudfoundry.app.name" semantic conventions. It represents the name of the - // application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-app-name" - // Note: Application instrumentation should use the value from environment - // variable `VCAP_APPLICATION.application_name`. This is the same value - // as reported by `cf apps`. - CloudFoundryAppNameKey = attribute.Key("cloudfoundry.app.name") - - // CloudFoundryOrgIDKey is the attribute Key conforming to the - // "cloudfoundry.org.id" semantic conventions. It represents the guid of the - // CloudFoundry org the application is running in. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d" - // Note: Application instrumentation should use the value from environment - // variable `VCAP_APPLICATION.org_id`. This is the same value as - // reported by `cf org --guid`. - CloudFoundryOrgIDKey = attribute.Key("cloudfoundry.org.id") - - // CloudFoundryOrgNameKey is the attribute Key conforming to the - // "cloudfoundry.org.name" semantic conventions. It represents the name of the - // CloudFoundry organization the app is running in. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-org-name" - // Note: Application instrumentation should use the value from environment - // variable `VCAP_APPLICATION.org_name`. This is the same value as - // reported by `cf orgs`. - CloudFoundryOrgNameKey = attribute.Key("cloudfoundry.org.name") - - // CloudFoundryProcessIDKey is the attribute Key conforming to the - // "cloudfoundry.process.id" semantic conventions. It represents the UID - // identifying the process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d" - // Note: Application instrumentation should use the value from environment - // variable `VCAP_APPLICATION.process_id`. It is supposed to be equal to - // `VCAP_APPLICATION.app_id` for applications deployed to the runtime. - // For system components, this could be the actual PID. - CloudFoundryProcessIDKey = attribute.Key("cloudfoundry.process.id") - - // CloudFoundryProcessTypeKey is the attribute Key conforming to the - // "cloudfoundry.process.type" semantic conventions. It represents the type of - // process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "web" - // Note: CloudFoundry applications can consist of multiple jobs. Usually the - // main process will be of type `web`. There can be additional background - // tasks or side-cars with different process types. - CloudFoundryProcessTypeKey = attribute.Key("cloudfoundry.process.type") - - // CloudFoundrySpaceIDKey is the attribute Key conforming to the - // "cloudfoundry.space.id" semantic conventions. It represents the guid of the - // CloudFoundry space the application is running in. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d" - // Note: Application instrumentation should use the value from environment - // variable `VCAP_APPLICATION.space_id`. This is the same value as - // reported by `cf space --guid`. - CloudFoundrySpaceIDKey = attribute.Key("cloudfoundry.space.id") - - // CloudFoundrySpaceNameKey is the attribute Key conforming to the - // "cloudfoundry.space.name" semantic conventions. It represents the name of the - // CloudFoundry space the application is running in. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-space-name" - // Note: Application instrumentation should use the value from environment - // variable `VCAP_APPLICATION.space_name`. This is the same value as - // reported by `cf spaces`. - CloudFoundrySpaceNameKey = attribute.Key("cloudfoundry.space.name") - - // CloudFoundrySystemIDKey is the attribute Key conforming to the - // "cloudfoundry.system.id" semantic conventions. It represents a guid or - // another name describing the event source. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "cf/gorouter" - // Note: CloudFoundry defines the `source_id` in the [Loggregator v2 envelope]. - // It is used for logs and metrics emitted by CloudFoundry. It is - // supposed to contain the component name, e.g. "gorouter", for - // CloudFoundry components. - // - // When system components are instrumented, values from the - // [Bosh spec] - // should be used. The `system.id` should be set to - // `spec.deployment/spec.name`. - // - // [Loggregator v2 envelope]: https://github.com/cloudfoundry/loggregator-api#v2-envelope - // [Bosh spec]: https://bosh.io/docs/jobs/#properties-spec - CloudFoundrySystemIDKey = attribute.Key("cloudfoundry.system.id") - - // CloudFoundrySystemInstanceIDKey is the attribute Key conforming to the - // "cloudfoundry.system.instance.id" semantic conventions. It represents a guid - // describing the concrete instance of the event source. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d" - // Note: CloudFoundry defines the `instance_id` in the [Loggregator v2 envelope] - // . - // It is used for logs and metrics emitted by CloudFoundry. It is - // supposed to contain the vm id for CloudFoundry components. - // - // When system components are instrumented, values from the - // [Bosh spec] - // should be used. The `system.instance.id` should be set to `spec.id`. - // - // [Loggregator v2 envelope]: https://github.com/cloudfoundry/loggregator-api#v2-envelope - // [Bosh spec]: https://bosh.io/docs/jobs/#properties-spec - CloudFoundrySystemInstanceIDKey = attribute.Key("cloudfoundry.system.instance.id") -) - -// CloudFoundryAppID returns an attribute KeyValue conforming to the -// "cloudfoundry.app.id" semantic conventions. It represents the guid of the -// application. -func CloudFoundryAppID(val string) attribute.KeyValue { - return CloudFoundryAppIDKey.String(val) -} - -// CloudFoundryAppInstanceID returns an attribute KeyValue conforming to the -// "cloudfoundry.app.instance.id" semantic conventions. It represents the index -// of the application instance. 0 when just one instance is active. -func CloudFoundryAppInstanceID(val string) attribute.KeyValue { - return CloudFoundryAppInstanceIDKey.String(val) -} - -// CloudFoundryAppName returns an attribute KeyValue conforming to the -// "cloudfoundry.app.name" semantic conventions. It represents the name of the -// application. -func CloudFoundryAppName(val string) attribute.KeyValue { - return CloudFoundryAppNameKey.String(val) -} - -// CloudFoundryOrgID returns an attribute KeyValue conforming to the -// "cloudfoundry.org.id" semantic conventions. It represents the guid of the -// CloudFoundry org the application is running in. -func CloudFoundryOrgID(val string) attribute.KeyValue { - return CloudFoundryOrgIDKey.String(val) -} - -// CloudFoundryOrgName returns an attribute KeyValue conforming to the -// "cloudfoundry.org.name" semantic conventions. It represents the name of the -// CloudFoundry organization the app is running in. -func CloudFoundryOrgName(val string) attribute.KeyValue { - return CloudFoundryOrgNameKey.String(val) -} - -// CloudFoundryProcessID returns an attribute KeyValue conforming to the -// "cloudfoundry.process.id" semantic conventions. It represents the UID -// identifying the process. -func CloudFoundryProcessID(val string) attribute.KeyValue { - return CloudFoundryProcessIDKey.String(val) -} - -// CloudFoundryProcessType returns an attribute KeyValue conforming to the -// "cloudfoundry.process.type" semantic conventions. It represents the type of -// process. -func CloudFoundryProcessType(val string) attribute.KeyValue { - return CloudFoundryProcessTypeKey.String(val) -} - -// CloudFoundrySpaceID returns an attribute KeyValue conforming to the -// "cloudfoundry.space.id" semantic conventions. It represents the guid of the -// CloudFoundry space the application is running in. -func CloudFoundrySpaceID(val string) attribute.KeyValue { - return CloudFoundrySpaceIDKey.String(val) -} - -// CloudFoundrySpaceName returns an attribute KeyValue conforming to the -// "cloudfoundry.space.name" semantic conventions. It represents the name of the -// CloudFoundry space the application is running in. -func CloudFoundrySpaceName(val string) attribute.KeyValue { - return CloudFoundrySpaceNameKey.String(val) -} - -// CloudFoundrySystemID returns an attribute KeyValue conforming to the -// "cloudfoundry.system.id" semantic conventions. It represents a guid or another -// name describing the event source. -func CloudFoundrySystemID(val string) attribute.KeyValue { - return CloudFoundrySystemIDKey.String(val) -} - -// CloudFoundrySystemInstanceID returns an attribute KeyValue conforming to the -// "cloudfoundry.system.instance.id" semantic conventions. It represents a guid -// describing the concrete instance of the event source. -func CloudFoundrySystemInstanceID(val string) attribute.KeyValue { - return CloudFoundrySystemInstanceIDKey.String(val) -} - -// Namespace: code -const ( - // CodeColumnNumberKey is the attribute Key conforming to the - // "code.column.number" semantic conventions. It represents the column number in - // `code.file.path` best representing the operation. It SHOULD point within the - // code unit named in `code.function.name`. This attribute MUST NOT be used on - // the Profile signal since the data is already captured in 'message Line'. This - // constraint is imposed to prevent redundancy and maintain data integrity. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - CodeColumnNumberKey = attribute.Key("code.column.number") - - // CodeFilePathKey is the attribute Key conforming to the "code.file.path" - // semantic conventions. It represents the source code file name that identifies - // the code unit as uniquely as possible (preferably an absolute file path). - // This attribute MUST NOT be used on the Profile signal since the data is - // already captured in 'message Function'. This constraint is imposed to prevent - // redundancy and maintain data integrity. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: /usr/local/MyApplication/content_root/app/index.php - CodeFilePathKey = attribute.Key("code.file.path") - - // CodeFunctionNameKey is the attribute Key conforming to the - // "code.function.name" semantic conventions. It represents the method or - // function fully-qualified name without arguments. The value should fit the - // natural representation of the language runtime, which is also likely the same - // used within `code.stacktrace` attribute value. This attribute MUST NOT be - // used on the Profile signal since the data is already captured in 'message - // Function'. This constraint is imposed to prevent redundancy and maintain data - // integrity. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "com.example.MyHttpService.serveRequest", - // "GuzzleHttp\Client::transfer", "fopen" - // Note: Values and format depends on each language runtime, thus it is - // impossible to provide an exhaustive list of examples. - // The values are usually the same (or prefixes of) the ones found in native - // stack trace representation stored in - // `code.stacktrace` without information on arguments. - // - // Examples: - // - // - Java method: `com.example.MyHttpService.serveRequest` - // - Java anonymous class method: `com.mycompany.Main$1.myMethod` - // - Java lambda method: - // `com.mycompany.Main$$Lambda/0x0000748ae4149c00.myMethod` - // - PHP function: `GuzzleHttp\Client::transfer` - // - Go function: `github.com/my/repo/pkg.foo.func5` - // - Elixir: `OpenTelemetry.Ctx.new` - // - Erlang: `opentelemetry_ctx:new` - // - Rust: `playground::my_module::my_cool_func` - // - C function: `fopen` - CodeFunctionNameKey = attribute.Key("code.function.name") - - // CodeLineNumberKey is the attribute Key conforming to the "code.line.number" - // semantic conventions. It represents the line number in `code.file.path` best - // representing the operation. It SHOULD point within the code unit named in - // `code.function.name`. This attribute MUST NOT be used on the Profile signal - // since the data is already captured in 'message Line'. This constraint is - // imposed to prevent redundancy and maintain data integrity. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - CodeLineNumberKey = attribute.Key("code.line.number") - - // CodeStacktraceKey is the attribute Key conforming to the "code.stacktrace" - // semantic conventions. It represents a stacktrace as a string in the natural - // representation for the language runtime. The representation is identical to - // [`exception.stacktrace`]. This attribute MUST NOT be used on the Profile - // signal since the data is already captured in 'message Location'. This - // constraint is imposed to prevent redundancy and maintain data integrity. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: at com.example.GenerateTrace.methodB(GenerateTrace.java:13)\n at - // com.example.GenerateTrace.methodA(GenerateTrace.java:9)\n at - // com.example.GenerateTrace.main(GenerateTrace.java:5) - // - // [`exception.stacktrace`]: /docs/exceptions/exceptions-spans.md#stacktrace-representation - CodeStacktraceKey = attribute.Key("code.stacktrace") -) - -// CodeColumnNumber returns an attribute KeyValue conforming to the -// "code.column.number" semantic conventions. It represents the column number in -// `code.file.path` best representing the operation. It SHOULD point within the -// code unit named in `code.function.name`. This attribute MUST NOT be used on -// the Profile signal since the data is already captured in 'message Line'. This -// constraint is imposed to prevent redundancy and maintain data integrity. -func CodeColumnNumber(val int) attribute.KeyValue { - return CodeColumnNumberKey.Int(val) -} - -// CodeFilePath returns an attribute KeyValue conforming to the "code.file.path" -// semantic conventions. It represents the source code file name that identifies -// the code unit as uniquely as possible (preferably an absolute file path). This -// attribute MUST NOT be used on the Profile signal since the data is already -// captured in 'message Function'. This constraint is imposed to prevent -// redundancy and maintain data integrity. -func CodeFilePath(val string) attribute.KeyValue { - return CodeFilePathKey.String(val) -} - -// CodeFunctionName returns an attribute KeyValue conforming to the -// "code.function.name" semantic conventions. It represents the method or -// function fully-qualified name without arguments. The value should fit the -// natural representation of the language runtime, which is also likely the same -// used within `code.stacktrace` attribute value. This attribute MUST NOT be used -// on the Profile signal since the data is already captured in 'message -// Function'. This constraint is imposed to prevent redundancy and maintain data -// integrity. -func CodeFunctionName(val string) attribute.KeyValue { - return CodeFunctionNameKey.String(val) -} - -// CodeLineNumber returns an attribute KeyValue conforming to the -// "code.line.number" semantic conventions. It represents the line number in -// `code.file.path` best representing the operation. It SHOULD point within the -// code unit named in `code.function.name`. This attribute MUST NOT be used on -// the Profile signal since the data is already captured in 'message Line'. This -// constraint is imposed to prevent redundancy and maintain data integrity. -func CodeLineNumber(val int) attribute.KeyValue { - return CodeLineNumberKey.Int(val) -} - -// CodeStacktrace returns an attribute KeyValue conforming to the -// "code.stacktrace" semantic conventions. It represents a stacktrace as a string -// in the natural representation for the language runtime. The representation is -// identical to [`exception.stacktrace`]. This attribute MUST NOT be used on the -// Profile signal since the data is already captured in 'message Location'. This -// constraint is imposed to prevent redundancy and maintain data integrity. -// -// [`exception.stacktrace`]: /docs/exceptions/exceptions-spans.md#stacktrace-representation -func CodeStacktrace(val string) attribute.KeyValue { - return CodeStacktraceKey.String(val) -} - -// Namespace: container -const ( - // ContainerCommandKey is the attribute Key conforming to the - // "container.command" semantic conventions. It represents the command used to - // run the container (i.e. the command name). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "otelcontribcol" - // Note: If using embedded credentials or sensitive data, it is recommended to - // remove them to prevent potential leakage. - ContainerCommandKey = attribute.Key("container.command") - - // ContainerCommandArgsKey is the attribute Key conforming to the - // "container.command_args" semantic conventions. It represents the all the - // command arguments (including the command/executable itself) run by the - // container. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "otelcontribcol", "--config", "config.yaml" - ContainerCommandArgsKey = attribute.Key("container.command_args") - - // ContainerCommandLineKey is the attribute Key conforming to the - // "container.command_line" semantic conventions. It represents the full command - // run by the container as a single string representing the full command. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "otelcontribcol --config config.yaml" - ContainerCommandLineKey = attribute.Key("container.command_line") - - // ContainerCSIPluginNameKey is the attribute Key conforming to the - // "container.csi.plugin.name" semantic conventions. It represents the name of - // the CSI ([Container Storage Interface]) plugin used by the volume. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "pd.csi.storage.gke.io" - // Note: This can sometimes be referred to as a "driver" in CSI implementations. - // This should represent the `name` field of the GetPluginInfo RPC. - // - // [Container Storage Interface]: https://github.com/container-storage-interface/spec - ContainerCSIPluginNameKey = attribute.Key("container.csi.plugin.name") - - // ContainerCSIVolumeIDKey is the attribute Key conforming to the - // "container.csi.volume.id" semantic conventions. It represents the unique - // volume ID returned by the CSI ([Container Storage Interface]) plugin. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "projects/my-gcp-project/zones/my-gcp-zone/disks/my-gcp-disk" - // Note: This can sometimes be referred to as a "volume handle" in CSI - // implementations. This should represent the `Volume.volume_id` field in CSI - // spec. - // - // [Container Storage Interface]: https://github.com/container-storage-interface/spec - ContainerCSIVolumeIDKey = attribute.Key("container.csi.volume.id") - - // ContainerIDKey is the attribute Key conforming to the "container.id" semantic - // conventions. It represents the container ID. Usually a UUID, as for example - // used to [identify Docker containers]. The UUID might be abbreviated. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "a3bf90e006b2" - // - // [identify Docker containers]: https://docs.docker.com/engine/containers/run/#container-identification - ContainerIDKey = attribute.Key("container.id") - - // ContainerImageIDKey is the attribute Key conforming to the - // "container.image.id" semantic conventions. It represents the runtime specific - // image identifier. Usually a hash algorithm followed by a UUID. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "sha256:19c92d0a00d1b66d897bceaa7319bee0dd38a10a851c60bcec9474aa3f01e50f" - // Note: Docker defines a sha256 of the image id; `container.image.id` - // corresponds to the `Image` field from the Docker container inspect [API] - // endpoint. - // K8s defines a link to the container registry repository with digest - // `"imageID": "registry.azurecr.io /namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625"` - // . - // The ID is assigned by the container runtime and can vary in different - // environments. Consider using `oci.manifest.digest` if it is important to - // identify the same image in different environments/runtimes. - // - // [API]: https://docs.docker.com/reference/api/engine/version/v1.52/#tag/Container/operation/ContainerInspect - ContainerImageIDKey = attribute.Key("container.image.id") - - // ContainerImageNameKey is the attribute Key conforming to the - // "container.image.name" semantic conventions. It represents the name of the - // image the container was built on. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "gcr.io/opentelemetry/operator" - ContainerImageNameKey = attribute.Key("container.image.name") - - // ContainerImageRepoDigestsKey is the attribute Key conforming to the - // "container.image.repo_digests" semantic conventions. It represents the repo - // digests of the container image as provided by the container runtime. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: - // "example@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb", - // "internal.registry.example.com:5000/example@sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578" - // Note: [Docker] and [CRI] report those under the `RepoDigests` field. - // - // [Docker]: https://docs.docker.com/reference/api/engine/version/v1.52/#tag/Image/operation/ImageInspect - // [CRI]: https://github.com/kubernetes/cri-api/blob/c75ef5b473bbe2d0a4fc92f82235efd665ea8e9f/pkg/apis/runtime/v1/api.proto#L1237-L1238 - ContainerImageRepoDigestsKey = attribute.Key("container.image.repo_digests") - - // ContainerImageTagsKey is the attribute Key conforming to the - // "container.image.tags" semantic conventions. It represents the container - // image tags. An example can be found in [Docker Image Inspect]. Should be only - // the `` section of the full name for example from - // `registry.example.com/my-org/my-image:`. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "v1.27.1", "3.5.7-0" - // - // [Docker Image Inspect]: https://docs.docker.com/reference/api/engine/version/v1.52/#tag/Image/operation/ImageInspect - ContainerImageTagsKey = attribute.Key("container.image.tags") - - // ContainerNameKey is the attribute Key conforming to the "container.name" - // semantic conventions. It represents the container name used by container - // runtime. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "opentelemetry-autoconf" - ContainerNameKey = attribute.Key("container.name") - - // ContainerRuntimeDescriptionKey is the attribute Key conforming to the - // "container.runtime.description" semantic conventions. It represents a - // description about the runtime which could include, for example details about - // the CRI/API version being used or other customisations. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "docker://19.3.1 - CRI: 1.22.0" - ContainerRuntimeDescriptionKey = attribute.Key("container.runtime.description") - - // ContainerRuntimeNameKey is the attribute Key conforming to the - // "container.runtime.name" semantic conventions. It represents the container - // runtime managing this container. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "docker", "containerd", "rkt" - ContainerRuntimeNameKey = attribute.Key("container.runtime.name") - - // ContainerRuntimeVersionKey is the attribute Key conforming to the - // "container.runtime.version" semantic conventions. It represents the version - // of the runtime of this process, as returned by the runtime without - // modification. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1.0.0 - ContainerRuntimeVersionKey = attribute.Key("container.runtime.version") -) - -// ContainerCommand returns an attribute KeyValue conforming to the -// "container.command" semantic conventions. It represents the command used to -// run the container (i.e. the command name). -func ContainerCommand(val string) attribute.KeyValue { - return ContainerCommandKey.String(val) -} - -// ContainerCommandArgs returns an attribute KeyValue conforming to the -// "container.command_args" semantic conventions. It represents the all the -// command arguments (including the command/executable itself) run by the -// container. -func ContainerCommandArgs(val ...string) attribute.KeyValue { - return ContainerCommandArgsKey.StringSlice(val) -} - -// ContainerCommandLine returns an attribute KeyValue conforming to the -// "container.command_line" semantic conventions. It represents the full command -// run by the container as a single string representing the full command. -func ContainerCommandLine(val string) attribute.KeyValue { - return ContainerCommandLineKey.String(val) -} - -// ContainerCSIPluginName returns an attribute KeyValue conforming to the -// "container.csi.plugin.name" semantic conventions. It represents the name of -// the CSI ([Container Storage Interface]) plugin used by the volume. -// -// [Container Storage Interface]: https://github.com/container-storage-interface/spec -func ContainerCSIPluginName(val string) attribute.KeyValue { - return ContainerCSIPluginNameKey.String(val) -} - -// ContainerCSIVolumeID returns an attribute KeyValue conforming to the -// "container.csi.volume.id" semantic conventions. It represents the unique -// volume ID returned by the CSI ([Container Storage Interface]) plugin. -// -// [Container Storage Interface]: https://github.com/container-storage-interface/spec -func ContainerCSIVolumeID(val string) attribute.KeyValue { - return ContainerCSIVolumeIDKey.String(val) -} - -// ContainerID returns an attribute KeyValue conforming to the "container.id" -// semantic conventions. It represents the container ID. Usually a UUID, as for -// example used to [identify Docker containers]. The UUID might be abbreviated. -// -// [identify Docker containers]: https://docs.docker.com/engine/containers/run/#container-identification -func ContainerID(val string) attribute.KeyValue { - return ContainerIDKey.String(val) -} - -// ContainerImageID returns an attribute KeyValue conforming to the -// "container.image.id" semantic conventions. It represents the runtime specific -// image identifier. Usually a hash algorithm followed by a UUID. -func ContainerImageID(val string) attribute.KeyValue { - return ContainerImageIDKey.String(val) -} - -// ContainerImageName returns an attribute KeyValue conforming to the -// "container.image.name" semantic conventions. It represents the name of the -// image the container was built on. -func ContainerImageName(val string) attribute.KeyValue { - return ContainerImageNameKey.String(val) -} - -// ContainerImageRepoDigests returns an attribute KeyValue conforming to the -// "container.image.repo_digests" semantic conventions. It represents the repo -// digests of the container image as provided by the container runtime. -func ContainerImageRepoDigests(val ...string) attribute.KeyValue { - return ContainerImageRepoDigestsKey.StringSlice(val) -} - -// ContainerImageTags returns an attribute KeyValue conforming to the -// "container.image.tags" semantic conventions. It represents the container image -// tags. An example can be found in [Docker Image Inspect]. Should be only the -// `` section of the full name for example from -// `registry.example.com/my-org/my-image:`. -// -// [Docker Image Inspect]: https://docs.docker.com/reference/api/engine/version/v1.52/#tag/Image/operation/ImageInspect -func ContainerImageTags(val ...string) attribute.KeyValue { - return ContainerImageTagsKey.StringSlice(val) -} - -// ContainerLabel returns an attribute KeyValue conforming to the -// "container.label" semantic conventions. It represents the container labels, -// `` being the label name, the value being the label value. -func ContainerLabel(key string, val string) attribute.KeyValue { - return attribute.String("container.label."+key, val) -} - -// ContainerName returns an attribute KeyValue conforming to the "container.name" -// semantic conventions. It represents the container name used by container -// runtime. -func ContainerName(val string) attribute.KeyValue { - return ContainerNameKey.String(val) -} - -// ContainerRuntimeDescription returns an attribute KeyValue conforming to the -// "container.runtime.description" semantic conventions. It represents a -// description about the runtime which could include, for example details about -// the CRI/API version being used or other customisations. -func ContainerRuntimeDescription(val string) attribute.KeyValue { - return ContainerRuntimeDescriptionKey.String(val) -} - -// ContainerRuntimeName returns an attribute KeyValue conforming to the -// "container.runtime.name" semantic conventions. It represents the container -// runtime managing this container. -func ContainerRuntimeName(val string) attribute.KeyValue { - return ContainerRuntimeNameKey.String(val) -} - -// ContainerRuntimeVersion returns an attribute KeyValue conforming to the -// "container.runtime.version" semantic conventions. It represents the version of -// the runtime of this process, as returned by the runtime without modification. -func ContainerRuntimeVersion(val string) attribute.KeyValue { - return ContainerRuntimeVersionKey.String(val) -} - -// Namespace: cpu -const ( - // CPULogicalNumberKey is the attribute Key conforming to the - // "cpu.logical_number" semantic conventions. It represents the logical CPU - // number [0..n-1]. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1 - CPULogicalNumberKey = attribute.Key("cpu.logical_number") - - // CPUModeKey is the attribute Key conforming to the "cpu.mode" semantic - // conventions. It represents the mode of the CPU. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "user", "system" - CPUModeKey = attribute.Key("cpu.mode") -) - -// CPULogicalNumber returns an attribute KeyValue conforming to the -// "cpu.logical_number" semantic conventions. It represents the logical CPU -// number [0..n-1]. -func CPULogicalNumber(val int) attribute.KeyValue { - return CPULogicalNumberKey.Int(val) -} - -// Enum values for cpu.mode -var ( - // User - // Stability: development - CPUModeUser = CPUModeKey.String("user") - // System - // Stability: development - CPUModeSystem = CPUModeKey.String("system") - // Nice - // Stability: development - CPUModeNice = CPUModeKey.String("nice") - // Idle - // Stability: development - CPUModeIdle = CPUModeKey.String("idle") - // IO Wait - // Stability: development - CPUModeIOWait = CPUModeKey.String("iowait") - // Interrupt - // Stability: development - CPUModeInterrupt = CPUModeKey.String("interrupt") - // Steal - // Stability: development - CPUModeSteal = CPUModeKey.String("steal") - // Kernel - // Stability: development - CPUModeKernel = CPUModeKey.String("kernel") -) - -// Namespace: db -const ( - // DBClientConnectionPoolNameKey is the attribute Key conforming to the - // "db.client.connection.pool.name" semantic conventions. It represents the name - // of the connection pool; unique within the instrumented application. In case - // the connection pool implementation doesn't provide a name, instrumentation - // SHOULD use a combination of parameters that would make the name unique, for - // example, combining attributes `server.address`, `server.port`, and - // `db.namespace`, formatted as `server.address:server.port/db.namespace`. - // Instrumentations that generate connection pool name following different - // patterns SHOULD document it. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "myDataSource" - DBClientConnectionPoolNameKey = attribute.Key("db.client.connection.pool.name") - - // DBClientConnectionStateKey is the attribute Key conforming to the - // "db.client.connection.state" semantic conventions. It represents the state of - // a connection in the pool. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "idle" - DBClientConnectionStateKey = attribute.Key("db.client.connection.state") - - // DBCollectionNameKey is the attribute Key conforming to the - // "db.collection.name" semantic conventions. It represents the name of a - // collection (table, container) within the database. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "public.users", "customers" - // Note: It is RECOMMENDED to capture the value as provided by the application - // without attempting to do any case normalization. - // - // The collection name SHOULD NOT be extracted from `db.query.text`, - // when the database system supports query text with multiple collections - // in non-batch operations. - // - // For batch operations, if the individual operations are known to have the same - // collection name then that collection name SHOULD be used. - DBCollectionNameKey = attribute.Key("db.collection.name") - - // DBNamespaceKey is the attribute Key conforming to the "db.namespace" semantic - // conventions. It represents the name of the database, fully qualified within - // the server address and port. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "customers", "test.users" - // Note: If a database system has multiple namespace components, they SHOULD be - // concatenated from the most general to the most specific namespace component, - // using `|` as a separator between the components. Any missing components (and - // their associated separators) SHOULD be omitted. - // Semantic conventions for individual database systems SHOULD document what - // `db.namespace` means in the context of that system. - // It is RECOMMENDED to capture the value as provided by the application without - // attempting to do any case normalization. - DBNamespaceKey = attribute.Key("db.namespace") - - // DBOperationBatchSizeKey is the attribute Key conforming to the - // "db.operation.batch.size" semantic conventions. It represents the number of - // queries included in a batch operation. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: 2, 3, 4 - // Note: Operations are only considered batches when they contain two or more - // operations, and so `db.operation.batch.size` SHOULD never be `1`. - DBOperationBatchSizeKey = attribute.Key("db.operation.batch.size") - - // DBOperationNameKey is the attribute Key conforming to the "db.operation.name" - // semantic conventions. It represents the name of the operation or command - // being executed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "findAndModify", "HMSET", "SELECT" - // Note: It is RECOMMENDED to capture the value as provided by the application - // without attempting to do any case normalization. - // - // The operation name SHOULD NOT be extracted from `db.query.text`, - // when the database system supports query text with multiple operations - // in non-batch operations. - // - // If spaces can occur in the operation name, multiple consecutive spaces - // SHOULD be normalized to a single space. - // - // For batch operations, if the individual operations are known to have the same - // operation name - // then that operation name SHOULD be used prepended by `BATCH `, - // otherwise `db.operation.name` SHOULD be `BATCH` or some other database - // system specific term if more applicable. - DBOperationNameKey = attribute.Key("db.operation.name") - - // DBQuerySummaryKey is the attribute Key conforming to the "db.query.summary" - // semantic conventions. It represents the low cardinality summary of a database - // query. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "SELECT wuser_table", "INSERT shipping_details SELECT orders", "get - // user by id" - // Note: The query summary describes a class of database queries and is useful - // as a grouping key, especially when analyzing telemetry for database - // calls involving complex queries. - // - // Summary may be available to the instrumentation through - // instrumentation hooks or other means. If it is not available, - // instrumentations - // that support query parsing SHOULD generate a summary following - // [Generating query summary] - // section. - // - // For batch operations, if the individual operations are known to have the same - // query summary - // then that query summary SHOULD be used prepended by `BATCH `, - // otherwise `db.query.summary` SHOULD be `BATCH` or some other database - // system specific term if more applicable. - // - // [Generating query summary]: /docs/db/database-spans.md#generating-a-summary-of-the-query - DBQuerySummaryKey = attribute.Key("db.query.summary") - - // DBQueryTextKey is the attribute Key conforming to the "db.query.text" - // semantic conventions. It represents the database query being executed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "SELECT * FROM wuser_table where username = ?", "SET mykey ?" - // Note: For sanitization see [Sanitization of `db.query.text`]. - // For batch operations, if the individual operations are known to have the same - // query text then that query text SHOULD be used, otherwise all of the - // individual query texts SHOULD be concatenated with separator `; ` or some - // other database system specific separator if more applicable. - // Parameterized query text SHOULD NOT be sanitized. Even though parameterized - // query text can potentially have sensitive data, by using a parameterized - // query the user is giving a strong signal that any sensitive data will be - // passed as parameter values, and the benefit to observability of capturing the - // static part of the query text by default outweighs the risk. - // - // [Sanitization of `db.query.text`]: /docs/db/database-spans.md#sanitization-of-dbquerytext - DBQueryTextKey = attribute.Key("db.query.text") - - // DBResponseReturnedRowsKey is the attribute Key conforming to the - // "db.response.returned_rows" semantic conventions. It represents the number of - // rows returned by the operation. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 10, 30, 1000 - DBResponseReturnedRowsKey = attribute.Key("db.response.returned_rows") - - // DBResponseStatusCodeKey is the attribute Key conforming to the - // "db.response.status_code" semantic conventions. It represents the database - // response status code. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "102", "ORA-17002", "08P01", "404" - // Note: The status code returned by the database. Usually it represents an - // error code, but may also represent partial success, warning, or differentiate - // between various types of successful outcomes. - // Semantic conventions for individual database systems SHOULD document what - // `db.response.status_code` means in the context of that system. - DBResponseStatusCodeKey = attribute.Key("db.response.status_code") - - // DBStoredProcedureNameKey is the attribute Key conforming to the - // "db.stored_procedure.name" semantic conventions. It represents the name of a - // stored procedure within the database. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "GetCustomer" - // Note: It is RECOMMENDED to capture the value as provided by the application - // without attempting to do any case normalization. - // - // For batch operations, if the individual operations are known to have the same - // stored procedure name then that stored procedure name SHOULD be used. - DBStoredProcedureNameKey = attribute.Key("db.stored_procedure.name") - - // DBSystemNameKey is the attribute Key conforming to the "db.system.name" - // semantic conventions. It represents the database management system (DBMS) - // product as identified by the client instrumentation. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: - // Note: The actual DBMS may differ from the one identified by the client. For - // example, when using PostgreSQL client libraries to connect to a CockroachDB, - // the `db.system.name` is set to `postgresql` based on the instrumentation's - // best knowledge. - DBSystemNameKey = attribute.Key("db.system.name") -) - -// DBClientConnectionPoolName returns an attribute KeyValue conforming to the -// "db.client.connection.pool.name" semantic conventions. It represents the name -// of the connection pool; unique within the instrumented application. In case -// the connection pool implementation doesn't provide a name, instrumentation -// SHOULD use a combination of parameters that would make the name unique, for -// example, combining attributes `server.address`, `server.port`, and -// `db.namespace`, formatted as `server.address:server.port/db.namespace`. -// Instrumentations that generate connection pool name following different -// patterns SHOULD document it. -func DBClientConnectionPoolName(val string) attribute.KeyValue { - return DBClientConnectionPoolNameKey.String(val) -} - -// DBCollectionName returns an attribute KeyValue conforming to the -// "db.collection.name" semantic conventions. It represents the name of a -// collection (table, container) within the database. -func DBCollectionName(val string) attribute.KeyValue { - return DBCollectionNameKey.String(val) -} - -// DBNamespace returns an attribute KeyValue conforming to the "db.namespace" -// semantic conventions. It represents the name of the database, fully qualified -// within the server address and port. -func DBNamespace(val string) attribute.KeyValue { - return DBNamespaceKey.String(val) -} - -// DBOperationBatchSize returns an attribute KeyValue conforming to the -// "db.operation.batch.size" semantic conventions. It represents the number of -// queries included in a batch operation. -func DBOperationBatchSize(val int) attribute.KeyValue { - return DBOperationBatchSizeKey.Int(val) -} - -// DBOperationName returns an attribute KeyValue conforming to the -// "db.operation.name" semantic conventions. It represents the name of the -// operation or command being executed. -func DBOperationName(val string) attribute.KeyValue { - return DBOperationNameKey.String(val) -} - -// DBOperationParameter returns an attribute KeyValue conforming to the -// "db.operation.parameter" semantic conventions. It represents a database -// operation parameter, with `` being the parameter name, and the attribute -// value being a string representation of the parameter value. -func DBOperationParameter(key string, val string) attribute.KeyValue { - return attribute.String("db.operation.parameter."+key, val) -} - -// DBQueryParameter returns an attribute KeyValue conforming to the -// "db.query.parameter" semantic conventions. It represents a database query -// parameter, with `` being the parameter name, and the attribute value -// being a string representation of the parameter value. -func DBQueryParameter(key string, val string) attribute.KeyValue { - return attribute.String("db.query.parameter."+key, val) -} - -// DBQuerySummary returns an attribute KeyValue conforming to the -// "db.query.summary" semantic conventions. It represents the low cardinality -// summary of a database query. -func DBQuerySummary(val string) attribute.KeyValue { - return DBQuerySummaryKey.String(val) -} - -// DBQueryText returns an attribute KeyValue conforming to the "db.query.text" -// semantic conventions. It represents the database query being executed. -func DBQueryText(val string) attribute.KeyValue { - return DBQueryTextKey.String(val) -} - -// DBResponseReturnedRows returns an attribute KeyValue conforming to the -// "db.response.returned_rows" semantic conventions. It represents the number of -// rows returned by the operation. -func DBResponseReturnedRows(val int) attribute.KeyValue { - return DBResponseReturnedRowsKey.Int(val) -} - -// DBResponseStatusCode returns an attribute KeyValue conforming to the -// "db.response.status_code" semantic conventions. It represents the database -// response status code. -func DBResponseStatusCode(val string) attribute.KeyValue { - return DBResponseStatusCodeKey.String(val) -} - -// DBStoredProcedureName returns an attribute KeyValue conforming to the -// "db.stored_procedure.name" semantic conventions. It represents the name of a -// stored procedure within the database. -func DBStoredProcedureName(val string) attribute.KeyValue { - return DBStoredProcedureNameKey.String(val) -} - -// Enum values for db.client.connection.state -var ( - // idle - // Stability: development - DBClientConnectionStateIdle = DBClientConnectionStateKey.String("idle") - // used - // Stability: development - DBClientConnectionStateUsed = DBClientConnectionStateKey.String("used") -) - -// Enum values for db.system.name -var ( - // Some other SQL database. Fallback only. - // Stability: development - DBSystemNameOtherSQL = DBSystemNameKey.String("other_sql") - // [Adabas (Adaptable Database System)] - // Stability: development - // - // [Adabas (Adaptable Database System)]: https://documentation.softwareag.com/?pf=adabas - DBSystemNameSoftwareagAdabas = DBSystemNameKey.String("softwareag.adabas") - // [Actian Ingres] - // Stability: development - // - // [Actian Ingres]: https://www.actian.com/databases/ingres/ - DBSystemNameActianIngres = DBSystemNameKey.String("actian.ingres") - // [Amazon DynamoDB] - // Stability: development - // - // [Amazon DynamoDB]: https://aws.amazon.com/pm/dynamodb/ - DBSystemNameAWSDynamoDB = DBSystemNameKey.String("aws.dynamodb") - // [Amazon Redshift] - // Stability: development - // - // [Amazon Redshift]: https://aws.amazon.com/redshift/ - DBSystemNameAWSRedshift = DBSystemNameKey.String("aws.redshift") - // [Azure Cosmos DB] - // Stability: development - // - // [Azure Cosmos DB]: https://learn.microsoft.com/azure/cosmos-db - DBSystemNameAzureCosmosDB = DBSystemNameKey.String("azure.cosmosdb") - // [InterSystems Caché] - // Stability: development - // - // [InterSystems Caché]: https://www.intersystems.com/products/cache/ - DBSystemNameIntersystemsCache = DBSystemNameKey.String("intersystems.cache") - // [Apache Cassandra] - // Stability: development - // - // [Apache Cassandra]: https://cassandra.apache.org/ - DBSystemNameCassandra = DBSystemNameKey.String("cassandra") - // [ClickHouse] - // Stability: development - // - // [ClickHouse]: https://clickhouse.com/ - DBSystemNameClickHouse = DBSystemNameKey.String("clickhouse") - // [CockroachDB] - // Stability: development - // - // [CockroachDB]: https://www.cockroachlabs.com/ - DBSystemNameCockroachDB = DBSystemNameKey.String("cockroachdb") - // [Couchbase] - // Stability: development - // - // [Couchbase]: https://www.couchbase.com/ - DBSystemNameCouchbase = DBSystemNameKey.String("couchbase") - // [Apache CouchDB] - // Stability: development - // - // [Apache CouchDB]: https://couchdb.apache.org/ - DBSystemNameCouchDB = DBSystemNameKey.String("couchdb") - // [Apache Derby] - // Stability: development - // - // [Apache Derby]: https://db.apache.org/derby/ - DBSystemNameDerby = DBSystemNameKey.String("derby") - // [Elasticsearch] - // Stability: development - // - // [Elasticsearch]: https://www.elastic.co/elasticsearch - DBSystemNameElasticsearch = DBSystemNameKey.String("elasticsearch") - // [Firebird] - // Stability: development - // - // [Firebird]: https://www.firebirdsql.org/ - DBSystemNameFirebirdSQL = DBSystemNameKey.String("firebirdsql") - // [Google Cloud Spanner] - // Stability: development - // - // [Google Cloud Spanner]: https://cloud.google.com/spanner - DBSystemNameGCPSpanner = DBSystemNameKey.String("gcp.spanner") - // [Apache Geode] - // Stability: development - // - // [Apache Geode]: https://geode.apache.org/ - DBSystemNameGeode = DBSystemNameKey.String("geode") - // [H2 Database] - // Stability: development - // - // [H2 Database]: https://h2database.com/ - DBSystemNameH2database = DBSystemNameKey.String("h2database") - // [Apache HBase] - // Stability: development - // - // [Apache HBase]: https://hbase.apache.org/ - DBSystemNameHBase = DBSystemNameKey.String("hbase") - // [Apache Hive] - // Stability: development - // - // [Apache Hive]: https://hive.apache.org/ - DBSystemNameHive = DBSystemNameKey.String("hive") - // [HyperSQL Database] - // Stability: development - // - // [HyperSQL Database]: https://hsqldb.org/ - DBSystemNameHSQLDB = DBSystemNameKey.String("hsqldb") - // [IBM Db2] - // Stability: development - // - // [IBM Db2]: https://www.ibm.com/db2 - DBSystemNameIBMDB2 = DBSystemNameKey.String("ibm.db2") - // [IBM Informix] - // Stability: development - // - // [IBM Informix]: https://www.ibm.com/products/informix - DBSystemNameIBMInformix = DBSystemNameKey.String("ibm.informix") - // [IBM Netezza] - // Stability: development - // - // [IBM Netezza]: https://www.ibm.com/products/netezza - DBSystemNameIBMNetezza = DBSystemNameKey.String("ibm.netezza") - // [InfluxDB] - // Stability: development - // - // [InfluxDB]: https://www.influxdata.com/ - DBSystemNameInfluxDB = DBSystemNameKey.String("influxdb") - // [Instant] - // Stability: development - // - // [Instant]: https://www.instantdb.com/ - DBSystemNameInstantDB = DBSystemNameKey.String("instantdb") - // [MariaDB] - // Stability: stable - // - // [MariaDB]: https://mariadb.org/ - DBSystemNameMariaDB = DBSystemNameKey.String("mariadb") - // [Memcached] - // Stability: development - // - // [Memcached]: https://memcached.org/ - DBSystemNameMemcached = DBSystemNameKey.String("memcached") - // [MongoDB] - // Stability: development - // - // [MongoDB]: https://www.mongodb.com/ - DBSystemNameMongoDB = DBSystemNameKey.String("mongodb") - // [Microsoft SQL Server] - // Stability: stable - // - // [Microsoft SQL Server]: https://www.microsoft.com/sql-server - DBSystemNameMicrosoftSQLServer = DBSystemNameKey.String("microsoft.sql_server") - // [MySQL] - // Stability: stable - // - // [MySQL]: https://www.mysql.com/ - DBSystemNameMySQL = DBSystemNameKey.String("mysql") - // [Neo4j] - // Stability: development - // - // [Neo4j]: https://neo4j.com/ - DBSystemNameNeo4j = DBSystemNameKey.String("neo4j") - // [OpenSearch] - // Stability: development - // - // [OpenSearch]: https://opensearch.org/ - DBSystemNameOpenSearch = DBSystemNameKey.String("opensearch") - // [Oracle Database] - // Stability: development - // - // [Oracle Database]: https://www.oracle.com/database/ - DBSystemNameOracleDB = DBSystemNameKey.String("oracle.db") - // [PostgreSQL] - // Stability: stable - // - // [PostgreSQL]: https://www.postgresql.org/ - DBSystemNamePostgreSQL = DBSystemNameKey.String("postgresql") - // [Redis] - // Stability: development - // - // [Redis]: https://redis.io/ - DBSystemNameRedis = DBSystemNameKey.String("redis") - // [SAP HANA] - // Stability: development - // - // [SAP HANA]: https://www.sap.com/products/technology-platform/hana/what-is-sap-hana.html - DBSystemNameSAPHANA = DBSystemNameKey.String("sap.hana") - // [SAP MaxDB] - // Stability: development - // - // [SAP MaxDB]: https://maxdb.sap.com/ - DBSystemNameSAPMaxDB = DBSystemNameKey.String("sap.maxdb") - // [SQLite] - // Stability: development - // - // [SQLite]: https://www.sqlite.org/ - DBSystemNameSQLite = DBSystemNameKey.String("sqlite") - // [Teradata] - // Stability: development - // - // [Teradata]: https://www.teradata.com/ - DBSystemNameTeradata = DBSystemNameKey.String("teradata") - // [Trino] - // Stability: development - // - // [Trino]: https://trino.io/ - DBSystemNameTrino = DBSystemNameKey.String("trino") -) - -// Namespace: deployment -const ( - // DeploymentEnvironmentNameKey is the attribute Key conforming to the - // "deployment.environment.name" semantic conventions. It represents the name of - // the [deployment environment] (aka deployment tier). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "staging", "production" - // Note: `deployment.environment.name` does not affect the uniqueness - // constraints defined through - // the `service.namespace`, `service.name` and `service.instance.id` resource - // attributes. - // This implies that resources carrying the following attribute combinations - // MUST be - // considered to be identifying the same service: - // - // - `service.name=frontend`, `deployment.environment.name=production` - // - `service.name=frontend`, `deployment.environment.name=staging`. - // - // - // [deployment environment]: https://wikipedia.org/wiki/Deployment_environment - DeploymentEnvironmentNameKey = attribute.Key("deployment.environment.name") - - // DeploymentIDKey is the attribute Key conforming to the "deployment.id" - // semantic conventions. It represents the id of the deployment. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1208" - DeploymentIDKey = attribute.Key("deployment.id") - - // DeploymentNameKey is the attribute Key conforming to the "deployment.name" - // semantic conventions. It represents the name of the deployment. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "deploy my app", "deploy-frontend" - DeploymentNameKey = attribute.Key("deployment.name") - - // DeploymentStatusKey is the attribute Key conforming to the - // "deployment.status" semantic conventions. It represents the status of the - // deployment. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - DeploymentStatusKey = attribute.Key("deployment.status") -) - -// DeploymentEnvironmentName returns an attribute KeyValue conforming to the -// "deployment.environment.name" semantic conventions. It represents the name of -// the [deployment environment] (aka deployment tier). -// -// [deployment environment]: https://wikipedia.org/wiki/Deployment_environment -func DeploymentEnvironmentName(val string) attribute.KeyValue { - return DeploymentEnvironmentNameKey.String(val) -} - -// DeploymentID returns an attribute KeyValue conforming to the "deployment.id" -// semantic conventions. It represents the id of the deployment. -func DeploymentID(val string) attribute.KeyValue { - return DeploymentIDKey.String(val) -} - -// DeploymentName returns an attribute KeyValue conforming to the -// "deployment.name" semantic conventions. It represents the name of the -// deployment. -func DeploymentName(val string) attribute.KeyValue { - return DeploymentNameKey.String(val) -} - -// Enum values for deployment.status -var ( - // failed - // Stability: development - DeploymentStatusFailed = DeploymentStatusKey.String("failed") - // succeeded - // Stability: development - DeploymentStatusSucceeded = DeploymentStatusKey.String("succeeded") -) - -// Namespace: destination -const ( - // DestinationAddressKey is the attribute Key conforming to the - // "destination.address" semantic conventions. It represents the destination - // address - domain name if available without reverse DNS lookup; otherwise, IP - // address or Unix domain socket name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "destination.example.com", "10.1.2.80", "/tmp/my.sock" - // Note: When observed from the source side, and when communicating through an - // intermediary, `destination.address` SHOULD represent the destination address - // behind any intermediaries, for example proxies, if it's available. - DestinationAddressKey = attribute.Key("destination.address") - - // DestinationPortKey is the attribute Key conforming to the "destination.port" - // semantic conventions. It represents the destination port number. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 3389, 2888 - DestinationPortKey = attribute.Key("destination.port") -) - -// DestinationAddress returns an attribute KeyValue conforming to the -// "destination.address" semantic conventions. It represents the destination -// address - domain name if available without reverse DNS lookup; otherwise, IP -// address or Unix domain socket name. -func DestinationAddress(val string) attribute.KeyValue { - return DestinationAddressKey.String(val) -} - -// DestinationPort returns an attribute KeyValue conforming to the -// "destination.port" semantic conventions. It represents the destination port -// number. -func DestinationPort(val int) attribute.KeyValue { - return DestinationPortKey.Int(val) -} - -// Namespace: device -const ( - // DeviceIDKey is the attribute Key conforming to the "device.id" semantic - // conventions. It represents a unique identifier representing the device. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "123456789012345", "01:23:45:67:89:AB" - // Note: Its value SHOULD be identical for all apps on a device and it SHOULD - // NOT change if an app is uninstalled and re-installed. - // However, it might be resettable by the user for all apps on a device. - // Hardware IDs (e.g. vendor-specific serial number, IMEI or MAC address) MAY be - // used as values. - // - // More information about Android identifier best practices can be found in the - // [Android user data IDs guide]. - // - // > [!WARNING]> This attribute may contain sensitive (PII) information. Caution - // > should be taken when storing personal data or anything which can identify a - // > user. GDPR and data protection laws may apply, - // > ensure you do your own due diligence.> Due to these reasons, this - // > identifier is not recommended for consumer applications and will likely - // > result in rejection from both Google Play and App Store. - // > However, it may be appropriate for specific enterprise scenarios, such as - // > kiosk devices or enterprise-managed devices, with appropriate compliance - // > clearance. - // > Any instrumentation providing this identifier MUST implement it as an - // > opt-in feature.> See [`app.installation.id`]> for a more - // > privacy-preserving alternative. - // - // [Android user data IDs guide]: https://developer.android.com/training/articles/user-data-ids - // [`app.installation.id`]: /docs/registry/attributes/app.md#app-installation-id - DeviceIDKey = attribute.Key("device.id") - - // DeviceManufacturerKey is the attribute Key conforming to the - // "device.manufacturer" semantic conventions. It represents the name of the - // device manufacturer. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Apple", "Samsung" - // Note: The Android OS provides this field via [Build]. iOS apps SHOULD - // hardcode the value `Apple`. - // - // [Build]: https://developer.android.com/reference/android/os/Build#MANUFACTURER - DeviceManufacturerKey = attribute.Key("device.manufacturer") - - // DeviceModelIdentifierKey is the attribute Key conforming to the - // "device.model.identifier" semantic conventions. It represents the model - // identifier for the device. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "iPhone3,4", "SM-G920F" - // Note: It's recommended this value represents a machine-readable version of - // the model identifier rather than the market or consumer-friendly name of the - // device. - DeviceModelIdentifierKey = attribute.Key("device.model.identifier") - - // DeviceModelNameKey is the attribute Key conforming to the "device.model.name" - // semantic conventions. It represents the marketing name for the device model. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "iPhone 6s Plus", "Samsung Galaxy S6" - // Note: It's recommended this value represents a human-readable version of the - // device model rather than a machine-readable alternative. - DeviceModelNameKey = attribute.Key("device.model.name") -) - -// DeviceID returns an attribute KeyValue conforming to the "device.id" semantic -// conventions. It represents a unique identifier representing the device. -func DeviceID(val string) attribute.KeyValue { - return DeviceIDKey.String(val) -} - -// DeviceManufacturer returns an attribute KeyValue conforming to the -// "device.manufacturer" semantic conventions. It represents the name of the -// device manufacturer. -func DeviceManufacturer(val string) attribute.KeyValue { - return DeviceManufacturerKey.String(val) -} - -// DeviceModelIdentifier returns an attribute KeyValue conforming to the -// "device.model.identifier" semantic conventions. It represents the model -// identifier for the device. -func DeviceModelIdentifier(val string) attribute.KeyValue { - return DeviceModelIdentifierKey.String(val) -} - -// DeviceModelName returns an attribute KeyValue conforming to the -// "device.model.name" semantic conventions. It represents the marketing name for -// the device model. -func DeviceModelName(val string) attribute.KeyValue { - return DeviceModelNameKey.String(val) -} - -// Namespace: disk -const ( - // DiskIODirectionKey is the attribute Key conforming to the "disk.io.direction" - // semantic conventions. It represents the disk IO operation direction. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "read" - DiskIODirectionKey = attribute.Key("disk.io.direction") -) - -// Enum values for disk.io.direction -var ( - // read - // Stability: development - DiskIODirectionRead = DiskIODirectionKey.String("read") - // write - // Stability: development - DiskIODirectionWrite = DiskIODirectionKey.String("write") -) - -// Namespace: dns -const ( - // DNSAnswersKey is the attribute Key conforming to the "dns.answers" semantic - // conventions. It represents the list of IPv4 or IPv6 addresses resolved during - // DNS lookup. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334" - DNSAnswersKey = attribute.Key("dns.answers") - - // DNSQuestionNameKey is the attribute Key conforming to the "dns.question.name" - // semantic conventions. It represents the name being queried. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "www.example.com", "opentelemetry.io" - // Note: The name represents the queried domain name as it appears in the DNS - // query without any additional normalization. - DNSQuestionNameKey = attribute.Key("dns.question.name") -) - -// DNSAnswers returns an attribute KeyValue conforming to the "dns.answers" -// semantic conventions. It represents the list of IPv4 or IPv6 addresses -// resolved during DNS lookup. -func DNSAnswers(val ...string) attribute.KeyValue { - return DNSAnswersKey.StringSlice(val) -} - -// DNSQuestionName returns an attribute KeyValue conforming to the -// "dns.question.name" semantic conventions. It represents the name being -// queried. -func DNSQuestionName(val string) attribute.KeyValue { - return DNSQuestionNameKey.String(val) -} - -// Namespace: elasticsearch -const ( - // ElasticsearchNodeNameKey is the attribute Key conforming to the - // "elasticsearch.node.name" semantic conventions. It represents the represents - // the human-readable identifier of the node/instance to which a request was - // routed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "instance-0000000001" - ElasticsearchNodeNameKey = attribute.Key("elasticsearch.node.name") -) - -// ElasticsearchNodeName returns an attribute KeyValue conforming to the -// "elasticsearch.node.name" semantic conventions. It represents the represents -// the human-readable identifier of the node/instance to which a request was -// routed. -func ElasticsearchNodeName(val string) attribute.KeyValue { - return ElasticsearchNodeNameKey.String(val) -} - -// Namespace: enduser -const ( - // EnduserIDKey is the attribute Key conforming to the "enduser.id" semantic - // conventions. It represents the unique identifier of an end user in the - // system. It maybe a username, email address, or other identifier. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "username" - // Note: Unique identifier of an end user in the system. - // - // > [!Warning] - // > This field contains sensitive (PII) information. - EnduserIDKey = attribute.Key("enduser.id") - - // EnduserPseudoIDKey is the attribute Key conforming to the "enduser.pseudo.id" - // semantic conventions. It represents the pseudonymous identifier of an end - // user. This identifier should be a random value that is not directly linked or - // associated with the end user's actual identity. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "QdH5CAWJgqVT4rOr0qtumf" - // Note: Pseudonymous identifier of an end user. - // - // > [!Warning] - // > This field contains sensitive (linkable PII) information. - EnduserPseudoIDKey = attribute.Key("enduser.pseudo.id") -) - -// EnduserID returns an attribute KeyValue conforming to the "enduser.id" -// semantic conventions. It represents the unique identifier of an end user in -// the system. It maybe a username, email address, or other identifier. -func EnduserID(val string) attribute.KeyValue { - return EnduserIDKey.String(val) -} - -// EnduserPseudoID returns an attribute KeyValue conforming to the -// "enduser.pseudo.id" semantic conventions. It represents the pseudonymous -// identifier of an end user. This identifier should be a random value that is -// not directly linked or associated with the end user's actual identity. -func EnduserPseudoID(val string) attribute.KeyValue { - return EnduserPseudoIDKey.String(val) -} - -// Namespace: error -const ( - // ErrorTypeKey is the attribute Key conforming to the "error.type" semantic - // conventions. It represents the describes a class of error the operation ended - // with. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "timeout", "java.net.UnknownHostException", - // "server_certificate_invalid", "500" - // Note: The `error.type` SHOULD be predictable, and SHOULD have low - // cardinality. - // - // When `error.type` is set to a type (e.g., an exception type), its - // canonical class name identifying the type within the artifact SHOULD be used. - // - // Instrumentations SHOULD document the list of errors they report. - // - // The cardinality of `error.type` within one instrumentation library SHOULD be - // low. - // Telemetry consumers that aggregate data from multiple instrumentation - // libraries and applications - // should be prepared for `error.type` to have high cardinality at query time - // when no - // additional filters are applied. - // - // If the operation has completed successfully, instrumentations SHOULD NOT set - // `error.type`. - // - // If a specific domain defines its own set of error identifiers (such as HTTP - // or RPC status codes), - // it's RECOMMENDED to: - // - // - Use a domain-specific attribute - // - Set `error.type` to capture all errors, regardless of whether they are - // defined within the domain-specific set or not. - ErrorTypeKey = attribute.Key("error.type") -) - -// Enum values for error.type -var ( - // A fallback error value to be used when the instrumentation doesn't define a - // custom value. - // - // Stability: stable - ErrorTypeOther = ErrorTypeKey.String("_OTHER") -) - -// Namespace: exception -const ( - // ExceptionMessageKey is the attribute Key conforming to the - // "exception.message" semantic conventions. It represents the exception - // message. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "Division by zero", "Can't convert 'int' object to str implicitly" - // Note: > [!WARNING] - // - // > This attribute may contain sensitive information. - ExceptionMessageKey = attribute.Key("exception.message") - - // ExceptionStacktraceKey is the attribute Key conforming to the - // "exception.stacktrace" semantic conventions. It represents a stacktrace as a - // string in the natural representation for the language runtime. The - // representation is to be determined and documented by each language SIG. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: Exception in thread "main" java.lang.RuntimeException: Test - // exception\n at com.example.GenerateTrace.methodB(GenerateTrace.java:13)\n at - // com.example.GenerateTrace.methodA(GenerateTrace.java:9)\n at - // com.example.GenerateTrace.main(GenerateTrace.java:5) - ExceptionStacktraceKey = attribute.Key("exception.stacktrace") - - // ExceptionTypeKey is the attribute Key conforming to the "exception.type" - // semantic conventions. It represents the type of the exception (its - // fully-qualified class name, if applicable). The dynamic type of the exception - // should be preferred over the static type in languages that support it. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "java.net.ConnectException", "OSError" - ExceptionTypeKey = attribute.Key("exception.type") -) - -// ExceptionMessage returns an attribute KeyValue conforming to the -// "exception.message" semantic conventions. It represents the exception message. -func ExceptionMessage(val string) attribute.KeyValue { - return ExceptionMessageKey.String(val) -} - -// ExceptionStacktrace returns an attribute KeyValue conforming to the -// "exception.stacktrace" semantic conventions. It represents a stacktrace as a -// string in the natural representation for the language runtime. The -// representation is to be determined and documented by each language SIG. -func ExceptionStacktrace(val string) attribute.KeyValue { - return ExceptionStacktraceKey.String(val) -} - -// ExceptionType returns an attribute KeyValue conforming to the "exception.type" -// semantic conventions. It represents the type of the exception (its -// fully-qualified class name, if applicable). The dynamic type of the exception -// should be preferred over the static type in languages that support it. -func ExceptionType(val string) attribute.KeyValue { - return ExceptionTypeKey.String(val) -} - -// Namespace: faas -const ( - // FaaSColdstartKey is the attribute Key conforming to the "faas.coldstart" - // semantic conventions. It represents a boolean that is true if the serverless - // function is executed for the first time (aka cold-start). - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - FaaSColdstartKey = attribute.Key("faas.coldstart") - - // FaaSCronKey is the attribute Key conforming to the "faas.cron" semantic - // conventions. It represents a string containing the schedule period as - // [Cron Expression]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0/5 * * * ? * - // - // [Cron Expression]: https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm - FaaSCronKey = attribute.Key("faas.cron") - - // FaaSDocumentCollectionKey is the attribute Key conforming to the - // "faas.document.collection" semantic conventions. It represents the name of - // the source on which the triggering operation was performed. For example, in - // Cloud Storage or S3 corresponds to the bucket name, and in Cosmos DB to the - // database name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "myBucketName", "myDbName" - FaaSDocumentCollectionKey = attribute.Key("faas.document.collection") - - // FaaSDocumentNameKey is the attribute Key conforming to the - // "faas.document.name" semantic conventions. It represents the document - // name/table subjected to the operation. For example, in Cloud Storage or S3 is - // the name of the file, and in Cosmos DB the table name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "myFile.txt", "myTableName" - FaaSDocumentNameKey = attribute.Key("faas.document.name") - - // FaaSDocumentOperationKey is the attribute Key conforming to the - // "faas.document.operation" semantic conventions. It represents the describes - // the type of the operation that was performed on the data. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - FaaSDocumentOperationKey = attribute.Key("faas.document.operation") - - // FaaSDocumentTimeKey is the attribute Key conforming to the - // "faas.document.time" semantic conventions. It represents a string containing - // the time when the data was accessed in the [ISO 8601] format expressed in - // [UTC]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 2020-01-23T13:47:06Z - // - // [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html - // [UTC]: https://www.w3.org/TR/NOTE-datetime - FaaSDocumentTimeKey = attribute.Key("faas.document.time") - - // FaaSInstanceKey is the attribute Key conforming to the "faas.instance" - // semantic conventions. It represents the execution environment ID as a string, - // that will be potentially reused for other invocations to the same - // function/function version. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de" - // Note: - **AWS Lambda:** Use the (full) log stream name. - FaaSInstanceKey = attribute.Key("faas.instance") - - // FaaSInvocationIDKey is the attribute Key conforming to the - // "faas.invocation_id" semantic conventions. It represents the invocation ID of - // the current function invocation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: af9d5aa4-a685-4c5f-a22b-444f80b3cc28 - FaaSInvocationIDKey = attribute.Key("faas.invocation_id") - - // FaaSInvokedNameKey is the attribute Key conforming to the "faas.invoked_name" - // semantic conventions. It represents the name of the invoked function. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: my-function - // Note: SHOULD be equal to the `faas.name` resource attribute of the invoked - // function. - FaaSInvokedNameKey = attribute.Key("faas.invoked_name") - - // FaaSInvokedProviderKey is the attribute Key conforming to the - // "faas.invoked_provider" semantic conventions. It represents the cloud - // provider of the invoked function. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: SHOULD be equal to the `cloud.provider` resource attribute of the - // invoked function. - FaaSInvokedProviderKey = attribute.Key("faas.invoked_provider") - - // FaaSInvokedRegionKey is the attribute Key conforming to the - // "faas.invoked_region" semantic conventions. It represents the cloud region of - // the invoked function. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: eu-central-1 - // Note: SHOULD be equal to the `cloud.region` resource attribute of the invoked - // function. - FaaSInvokedRegionKey = attribute.Key("faas.invoked_region") - - // FaaSMaxMemoryKey is the attribute Key conforming to the "faas.max_memory" - // semantic conventions. It represents the amount of memory available to the - // serverless function converted to Bytes. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Note: It's recommended to set this attribute since e.g. too little memory can - // easily stop a Java AWS Lambda function from working correctly. On AWS Lambda, - // the environment variable `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this - // information (which must be multiplied by 1,048,576). - FaaSMaxMemoryKey = attribute.Key("faas.max_memory") - - // FaaSNameKey is the attribute Key conforming to the "faas.name" semantic - // conventions. It represents the name of the single function that this runtime - // instance executes. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-function", "myazurefunctionapp/some-function-name" - // Note: This is the name of the function as configured/deployed on the FaaS - // platform and is usually different from the name of the callback - // function (which may be stored in the - // [`code.namespace`/`code.function.name`] - // span attributes). - // - // For some cloud providers, the above definition is ambiguous. The following - // definition of function name MUST be used for this attribute - // (and consequently the span name) for the listed cloud providers/products: - // - // - **Azure:** The full name `/`, i.e., function app name - // followed by a forward slash followed by the function name (this form - // can also be seen in the resource JSON for the function). - // This means that a span attribute MUST be used, as an Azure function - // app can host multiple functions that would usually share - // a TracerProvider (see also the `cloud.resource_id` attribute). - // - // - // [`code.namespace`/`code.function.name`]: /docs/general/attributes.md#source-code-attributes - FaaSNameKey = attribute.Key("faas.name") - - // FaaSTimeKey is the attribute Key conforming to the "faas.time" semantic - // conventions. It represents a string containing the function invocation time - // in the [ISO 8601] format expressed in [UTC]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 2020-01-23T13:47:06Z - // - // [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html - // [UTC]: https://www.w3.org/TR/NOTE-datetime - FaaSTimeKey = attribute.Key("faas.time") - - // FaaSTriggerKey is the attribute Key conforming to the "faas.trigger" semantic - // conventions. It represents the type of the trigger which caused this function - // invocation. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - FaaSTriggerKey = attribute.Key("faas.trigger") - - // FaaSVersionKey is the attribute Key conforming to the "faas.version" semantic - // conventions. It represents the immutable version of the function being - // executed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "26", "pinkfroid-00002" - // Note: Depending on the cloud provider and platform, use: - // - // - **AWS Lambda:** The [function version] - // (an integer represented as a decimal string). - // - **Google Cloud Run (Services):** The [revision] - // (i.e., the function name plus the revision suffix). - // - **Google Cloud Functions:** The value of the - // [`K_REVISION` environment variable]. - // - **Azure Functions:** Not applicable. Do not set this attribute. - // - // - // [function version]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html - // [revision]: https://cloud.google.com/run/docs/managing/revisions - // [`K_REVISION` environment variable]: https://cloud.google.com/run/docs/container-contract#services-env-vars - FaaSVersionKey = attribute.Key("faas.version") -) - -// FaaSColdstart returns an attribute KeyValue conforming to the "faas.coldstart" -// semantic conventions. It represents a boolean that is true if the serverless -// function is executed for the first time (aka cold-start). -func FaaSColdstart(val bool) attribute.KeyValue { - return FaaSColdstartKey.Bool(val) -} - -// FaaSCron returns an attribute KeyValue conforming to the "faas.cron" semantic -// conventions. It represents a string containing the schedule period as -// [Cron Expression]. -// -// [Cron Expression]: https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm -func FaaSCron(val string) attribute.KeyValue { - return FaaSCronKey.String(val) -} - -// FaaSDocumentCollection returns an attribute KeyValue conforming to the -// "faas.document.collection" semantic conventions. It represents the name of the -// source on which the triggering operation was performed. For example, in Cloud -// Storage or S3 corresponds to the bucket name, and in Cosmos DB to the database -// name. -func FaaSDocumentCollection(val string) attribute.KeyValue { - return FaaSDocumentCollectionKey.String(val) -} - -// FaaSDocumentName returns an attribute KeyValue conforming to the -// "faas.document.name" semantic conventions. It represents the document -// name/table subjected to the operation. For example, in Cloud Storage or S3 is -// the name of the file, and in Cosmos DB the table name. -func FaaSDocumentName(val string) attribute.KeyValue { - return FaaSDocumentNameKey.String(val) -} - -// FaaSDocumentTime returns an attribute KeyValue conforming to the -// "faas.document.time" semantic conventions. It represents a string containing -// the time when the data was accessed in the [ISO 8601] format expressed in -// [UTC]. -// -// [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html -// [UTC]: https://www.w3.org/TR/NOTE-datetime -func FaaSDocumentTime(val string) attribute.KeyValue { - return FaaSDocumentTimeKey.String(val) -} - -// FaaSInstance returns an attribute KeyValue conforming to the "faas.instance" -// semantic conventions. It represents the execution environment ID as a string, -// that will be potentially reused for other invocations to the same -// function/function version. -func FaaSInstance(val string) attribute.KeyValue { - return FaaSInstanceKey.String(val) -} - -// FaaSInvocationID returns an attribute KeyValue conforming to the -// "faas.invocation_id" semantic conventions. It represents the invocation ID of -// the current function invocation. -func FaaSInvocationID(val string) attribute.KeyValue { - return FaaSInvocationIDKey.String(val) -} - -// FaaSInvokedName returns an attribute KeyValue conforming to the -// "faas.invoked_name" semantic conventions. It represents the name of the -// invoked function. -func FaaSInvokedName(val string) attribute.KeyValue { - return FaaSInvokedNameKey.String(val) -} - -// FaaSInvokedRegion returns an attribute KeyValue conforming to the -// "faas.invoked_region" semantic conventions. It represents the cloud region of -// the invoked function. -func FaaSInvokedRegion(val string) attribute.KeyValue { - return FaaSInvokedRegionKey.String(val) -} - -// FaaSMaxMemory returns an attribute KeyValue conforming to the -// "faas.max_memory" semantic conventions. It represents the amount of memory -// available to the serverless function converted to Bytes. -func FaaSMaxMemory(val int) attribute.KeyValue { - return FaaSMaxMemoryKey.Int(val) -} - -// FaaSName returns an attribute KeyValue conforming to the "faas.name" semantic -// conventions. It represents the name of the single function that this runtime -// instance executes. -func FaaSName(val string) attribute.KeyValue { - return FaaSNameKey.String(val) -} - -// FaaSTime returns an attribute KeyValue conforming to the "faas.time" semantic -// conventions. It represents a string containing the function invocation time in -// the [ISO 8601] format expressed in [UTC]. -// -// [ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html -// [UTC]: https://www.w3.org/TR/NOTE-datetime -func FaaSTime(val string) attribute.KeyValue { - return FaaSTimeKey.String(val) -} - -// FaaSVersion returns an attribute KeyValue conforming to the "faas.version" -// semantic conventions. It represents the immutable version of the function -// being executed. -func FaaSVersion(val string) attribute.KeyValue { - return FaaSVersionKey.String(val) -} - -// Enum values for faas.document.operation -var ( - // When a new object is created. - // Stability: development - FaaSDocumentOperationInsert = FaaSDocumentOperationKey.String("insert") - // When an object is modified. - // Stability: development - FaaSDocumentOperationEdit = FaaSDocumentOperationKey.String("edit") - // When an object is deleted. - // Stability: development - FaaSDocumentOperationDelete = FaaSDocumentOperationKey.String("delete") -) - -// Enum values for faas.invoked_provider -var ( - // Alibaba Cloud - // Stability: development - FaaSInvokedProviderAlibabaCloud = FaaSInvokedProviderKey.String("alibaba_cloud") - // Amazon Web Services - // Stability: development - FaaSInvokedProviderAWS = FaaSInvokedProviderKey.String("aws") - // Microsoft Azure - // Stability: development - FaaSInvokedProviderAzure = FaaSInvokedProviderKey.String("azure") - // Google Cloud Platform - // Stability: development - FaaSInvokedProviderGCP = FaaSInvokedProviderKey.String("gcp") - // Tencent Cloud - // Stability: development - FaaSInvokedProviderTencentCloud = FaaSInvokedProviderKey.String("tencent_cloud") -) - -// Enum values for faas.trigger -var ( - // A response to some data source operation such as a database or filesystem - // read/write - // Stability: development - FaaSTriggerDatasource = FaaSTriggerKey.String("datasource") - // To provide an answer to an inbound HTTP request - // Stability: development - FaaSTriggerHTTP = FaaSTriggerKey.String("http") - // A function is set to be executed when messages are sent to a messaging system - // Stability: development - FaaSTriggerPubSub = FaaSTriggerKey.String("pubsub") - // A function is scheduled to be executed regularly - // Stability: development - FaaSTriggerTimer = FaaSTriggerKey.String("timer") - // If none of the others apply - // Stability: development - FaaSTriggerOther = FaaSTriggerKey.String("other") -) - -// Namespace: feature_flag -const ( - // FeatureFlagContextIDKey is the attribute Key conforming to the - // "feature_flag.context.id" semantic conventions. It represents the unique - // identifier for the flag evaluation context. For example, the targeting key. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "5157782b-2203-4c80-a857-dbbd5e7761db" - FeatureFlagContextIDKey = attribute.Key("feature_flag.context.id") - - // FeatureFlagErrorMessageKey is the attribute Key conforming to the - // "feature_flag.error.message" semantic conventions. It represents a message - // providing more detail about an error that occurred during feature flag - // evaluation in human-readable form. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "Unexpected input type: string", "The user has exceeded their - // storage quota" - FeatureFlagErrorMessageKey = attribute.Key("feature_flag.error.message") - - // FeatureFlagKeyKey is the attribute Key conforming to the "feature_flag.key" - // semantic conventions. It represents the lookup key of the feature flag. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "logo-color" - FeatureFlagKeyKey = attribute.Key("feature_flag.key") - - // FeatureFlagProviderNameKey is the attribute Key conforming to the - // "feature_flag.provider.name" semantic conventions. It represents the - // identifies the feature flag provider. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "Flag Manager" - FeatureFlagProviderNameKey = attribute.Key("feature_flag.provider.name") - - // FeatureFlagResultReasonKey is the attribute Key conforming to the - // "feature_flag.result.reason" semantic conventions. It represents the reason - // code which shows how a feature flag value was determined. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "static", "targeting_match", "error", "default" - FeatureFlagResultReasonKey = attribute.Key("feature_flag.result.reason") - - // FeatureFlagResultValueKey is the attribute Key conforming to the - // "feature_flag.result.value" semantic conventions. It represents the evaluated - // value of the feature flag. - // - // Type: any - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "#ff0000", true, 3 - // Note: With some feature flag providers, feature flag results can be quite - // large or contain private or sensitive details. - // Because of this, `feature_flag.result.variant` is often the preferred - // attribute if it is available. - // - // It may be desirable to redact or otherwise limit the size and scope of - // `feature_flag.result.value` if possible. - // Because the evaluated flag value is unstructured and may be any type, it is - // left to the instrumentation author to determine how best to achieve this. - FeatureFlagResultValueKey = attribute.Key("feature_flag.result.value") - - // FeatureFlagResultVariantKey is the attribute Key conforming to the - // "feature_flag.result.variant" semantic conventions. It represents a semantic - // identifier for an evaluated flag value. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "red", "true", "on" - // Note: A semantic identifier, commonly referred to as a variant, provides a - // means - // for referring to a value without including the value itself. This can - // provide additional context for understanding the meaning behind a value. - // For example, the variant `red` maybe be used for the value `#c05543`. - FeatureFlagResultVariantKey = attribute.Key("feature_flag.result.variant") - - // FeatureFlagSetIDKey is the attribute Key conforming to the - // "feature_flag.set.id" semantic conventions. It represents the identifier of - // the [flag set] to which the feature flag belongs. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "proj-1", "ab98sgs", "service1/dev" - // - // [flag set]: https://openfeature.dev/specification/glossary/#flag-set - FeatureFlagSetIDKey = attribute.Key("feature_flag.set.id") - - // FeatureFlagVersionKey is the attribute Key conforming to the - // "feature_flag.version" semantic conventions. It represents the version of the - // ruleset used during the evaluation. This may be any stable value which - // uniquely identifies the ruleset. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "1", "01ABCDEF" - FeatureFlagVersionKey = attribute.Key("feature_flag.version") -) - -// FeatureFlagContextID returns an attribute KeyValue conforming to the -// "feature_flag.context.id" semantic conventions. It represents the unique -// identifier for the flag evaluation context. For example, the targeting key. -func FeatureFlagContextID(val string) attribute.KeyValue { - return FeatureFlagContextIDKey.String(val) -} - -// FeatureFlagErrorMessage returns an attribute KeyValue conforming to the -// "feature_flag.error.message" semantic conventions. It represents a message -// providing more detail about an error that occurred during feature flag -// evaluation in human-readable form. -func FeatureFlagErrorMessage(val string) attribute.KeyValue { - return FeatureFlagErrorMessageKey.String(val) -} - -// FeatureFlagKey returns an attribute KeyValue conforming to the -// "feature_flag.key" semantic conventions. It represents the lookup key of the -// feature flag. -func FeatureFlagKey(val string) attribute.KeyValue { - return FeatureFlagKeyKey.String(val) -} - -// FeatureFlagProviderName returns an attribute KeyValue conforming to the -// "feature_flag.provider.name" semantic conventions. It represents the -// identifies the feature flag provider. -func FeatureFlagProviderName(val string) attribute.KeyValue { - return FeatureFlagProviderNameKey.String(val) -} - -// FeatureFlagResultVariant returns an attribute KeyValue conforming to the -// "feature_flag.result.variant" semantic conventions. It represents a semantic -// identifier for an evaluated flag value. -func FeatureFlagResultVariant(val string) attribute.KeyValue { - return FeatureFlagResultVariantKey.String(val) -} - -// FeatureFlagSetID returns an attribute KeyValue conforming to the -// "feature_flag.set.id" semantic conventions. It represents the identifier of -// the [flag set] to which the feature flag belongs. -// -// [flag set]: https://openfeature.dev/specification/glossary/#flag-set -func FeatureFlagSetID(val string) attribute.KeyValue { - return FeatureFlagSetIDKey.String(val) -} - -// FeatureFlagVersion returns an attribute KeyValue conforming to the -// "feature_flag.version" semantic conventions. It represents the version of the -// ruleset used during the evaluation. This may be any stable value which -// uniquely identifies the ruleset. -func FeatureFlagVersion(val string) attribute.KeyValue { - return FeatureFlagVersionKey.String(val) -} - -// Enum values for feature_flag.result.reason -var ( - // The resolved value is static (no dynamic evaluation). - // Stability: release_candidate - FeatureFlagResultReasonStatic = FeatureFlagResultReasonKey.String("static") - // The resolved value fell back to a pre-configured value (no dynamic evaluation - // occurred or dynamic evaluation yielded no result). - // Stability: release_candidate - FeatureFlagResultReasonDefault = FeatureFlagResultReasonKey.String("default") - // The resolved value was the result of a dynamic evaluation, such as a rule or - // specific user-targeting. - // Stability: release_candidate - FeatureFlagResultReasonTargetingMatch = FeatureFlagResultReasonKey.String("targeting_match") - // The resolved value was the result of pseudorandom assignment. - // Stability: release_candidate - FeatureFlagResultReasonSplit = FeatureFlagResultReasonKey.String("split") - // The resolved value was retrieved from cache. - // Stability: release_candidate - FeatureFlagResultReasonCached = FeatureFlagResultReasonKey.String("cached") - // The resolved value was the result of the flag being disabled in the - // management system. - // Stability: release_candidate - FeatureFlagResultReasonDisabled = FeatureFlagResultReasonKey.String("disabled") - // The reason for the resolved value could not be determined. - // Stability: release_candidate - FeatureFlagResultReasonUnknown = FeatureFlagResultReasonKey.String("unknown") - // The resolved value is non-authoritative or possibly out of date - // Stability: release_candidate - FeatureFlagResultReasonStale = FeatureFlagResultReasonKey.String("stale") - // The resolved value was the result of an error. - // Stability: release_candidate - FeatureFlagResultReasonError = FeatureFlagResultReasonKey.String("error") -) - -// Namespace: file -const ( - // FileAccessedKey is the attribute Key conforming to the "file.accessed" - // semantic conventions. It represents the time when the file was last accessed, - // in ISO 8601 format. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2021-01-01T12:00:00Z" - // Note: This attribute might not be supported by some file systems — NFS, - // FAT32, in embedded OS, etc. - FileAccessedKey = attribute.Key("file.accessed") - - // FileAttributesKey is the attribute Key conforming to the "file.attributes" - // semantic conventions. It represents the array of file attributes. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "readonly", "hidden" - // Note: Attributes names depend on the OS or file system. Here’s a - // non-exhaustive list of values expected for this attribute: `archive`, - // `compressed`, `directory`, `encrypted`, `execute`, `hidden`, `immutable`, - // `journaled`, `read`, `readonly`, `symbolic link`, `system`, `temporary`, - // `write`. - FileAttributesKey = attribute.Key("file.attributes") - - // FileChangedKey is the attribute Key conforming to the "file.changed" semantic - // conventions. It represents the time when the file attributes or metadata was - // last changed, in ISO 8601 format. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2021-01-01T12:00:00Z" - // Note: `file.changed` captures the time when any of the file's properties or - // attributes (including the content) are changed, while `file.modified` - // captures the timestamp when the file content is modified. - FileChangedKey = attribute.Key("file.changed") - - // FileCreatedKey is the attribute Key conforming to the "file.created" semantic - // conventions. It represents the time when the file was created, in ISO 8601 - // format. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2021-01-01T12:00:00Z" - // Note: This attribute might not be supported by some file systems — NFS, - // FAT32, in embedded OS, etc. - FileCreatedKey = attribute.Key("file.created") - - // FileDirectoryKey is the attribute Key conforming to the "file.directory" - // semantic conventions. It represents the directory where the file is located. - // It should include the drive letter, when appropriate. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/home/user", "C:\Program Files\MyApp" - FileDirectoryKey = attribute.Key("file.directory") - - // FileExtensionKey is the attribute Key conforming to the "file.extension" - // semantic conventions. It represents the file extension, excluding the leading - // dot. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "png", "gz" - // Note: When the file name has multiple extensions (example.tar.gz), only the - // last one should be captured ("gz", not "tar.gz"). - FileExtensionKey = attribute.Key("file.extension") - - // FileForkNameKey is the attribute Key conforming to the "file.fork_name" - // semantic conventions. It represents the name of the fork. A fork is - // additional data associated with a filesystem object. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Zone.Identifier" - // Note: On Linux, a resource fork is used to store additional data with a - // filesystem object. A file always has at least one fork for the data portion, - // and additional forks may exist. - // On NTFS, this is analogous to an Alternate Data Stream (ADS), and the default - // data stream for a file is just called $DATA. Zone.Identifier is commonly used - // by Windows to track contents downloaded from the Internet. An ADS is - // typically of the form: C:\path\to\filename.extension:some_fork_name, and - // some_fork_name is the value that should populate `fork_name`. - // `filename.extension` should populate `file.name`, and `extension` should - // populate `file.extension`. The full path, `file.path`, will include the fork - // name. - FileForkNameKey = attribute.Key("file.fork_name") - - // FileGroupIDKey is the attribute Key conforming to the "file.group.id" - // semantic conventions. It represents the primary Group ID (GID) of the file. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1000" - FileGroupIDKey = attribute.Key("file.group.id") - - // FileGroupNameKey is the attribute Key conforming to the "file.group.name" - // semantic conventions. It represents the primary group name of the file. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "users" - FileGroupNameKey = attribute.Key("file.group.name") - - // FileInodeKey is the attribute Key conforming to the "file.inode" semantic - // conventions. It represents the inode representing the file in the filesystem. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "256383" - FileInodeKey = attribute.Key("file.inode") - - // FileModeKey is the attribute Key conforming to the "file.mode" semantic - // conventions. It represents the mode of the file in octal representation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "0640" - FileModeKey = attribute.Key("file.mode") - - // FileModifiedKey is the attribute Key conforming to the "file.modified" - // semantic conventions. It represents the time when the file content was last - // modified, in ISO 8601 format. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2021-01-01T12:00:00Z" - FileModifiedKey = attribute.Key("file.modified") - - // FileNameKey is the attribute Key conforming to the "file.name" semantic - // conventions. It represents the name of the file including the extension, - // without the directory. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "example.png" - FileNameKey = attribute.Key("file.name") - - // FileOwnerIDKey is the attribute Key conforming to the "file.owner.id" - // semantic conventions. It represents the user ID (UID) or security identifier - // (SID) of the file owner. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1000" - FileOwnerIDKey = attribute.Key("file.owner.id") - - // FileOwnerNameKey is the attribute Key conforming to the "file.owner.name" - // semantic conventions. It represents the username of the file owner. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "root" - FileOwnerNameKey = attribute.Key("file.owner.name") - - // FilePathKey is the attribute Key conforming to the "file.path" semantic - // conventions. It represents the full path to the file, including the file - // name. It should include the drive letter, when appropriate. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/home/alice/example.png", "C:\Program Files\MyApp\myapp.exe" - FilePathKey = attribute.Key("file.path") - - // FileSizeKey is the attribute Key conforming to the "file.size" semantic - // conventions. It represents the file size in bytes. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - FileSizeKey = attribute.Key("file.size") - - // FileSymbolicLinkTargetPathKey is the attribute Key conforming to the - // "file.symbolic_link.target_path" semantic conventions. It represents the path - // to the target of a symbolic link. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/usr/bin/python3" - // Note: This attribute is only applicable to symbolic links. - FileSymbolicLinkTargetPathKey = attribute.Key("file.symbolic_link.target_path") -) - -// FileAccessed returns an attribute KeyValue conforming to the "file.accessed" -// semantic conventions. It represents the time when the file was last accessed, -// in ISO 8601 format. -func FileAccessed(val string) attribute.KeyValue { - return FileAccessedKey.String(val) -} - -// FileAttributes returns an attribute KeyValue conforming to the -// "file.attributes" semantic conventions. It represents the array of file -// attributes. -func FileAttributes(val ...string) attribute.KeyValue { - return FileAttributesKey.StringSlice(val) -} - -// FileChanged returns an attribute KeyValue conforming to the "file.changed" -// semantic conventions. It represents the time when the file attributes or -// metadata was last changed, in ISO 8601 format. -func FileChanged(val string) attribute.KeyValue { - return FileChangedKey.String(val) -} - -// FileCreated returns an attribute KeyValue conforming to the "file.created" -// semantic conventions. It represents the time when the file was created, in ISO -// 8601 format. -func FileCreated(val string) attribute.KeyValue { - return FileCreatedKey.String(val) -} - -// FileDirectory returns an attribute KeyValue conforming to the "file.directory" -// semantic conventions. It represents the directory where the file is located. -// It should include the drive letter, when appropriate. -func FileDirectory(val string) attribute.KeyValue { - return FileDirectoryKey.String(val) -} - -// FileExtension returns an attribute KeyValue conforming to the "file.extension" -// semantic conventions. It represents the file extension, excluding the leading -// dot. -func FileExtension(val string) attribute.KeyValue { - return FileExtensionKey.String(val) -} - -// FileForkName returns an attribute KeyValue conforming to the "file.fork_name" -// semantic conventions. It represents the name of the fork. A fork is additional -// data associated with a filesystem object. -func FileForkName(val string) attribute.KeyValue { - return FileForkNameKey.String(val) -} - -// FileGroupID returns an attribute KeyValue conforming to the "file.group.id" -// semantic conventions. It represents the primary Group ID (GID) of the file. -func FileGroupID(val string) attribute.KeyValue { - return FileGroupIDKey.String(val) -} - -// FileGroupName returns an attribute KeyValue conforming to the -// "file.group.name" semantic conventions. It represents the primary group name -// of the file. -func FileGroupName(val string) attribute.KeyValue { - return FileGroupNameKey.String(val) -} - -// FileInode returns an attribute KeyValue conforming to the "file.inode" -// semantic conventions. It represents the inode representing the file in the -// filesystem. -func FileInode(val string) attribute.KeyValue { - return FileInodeKey.String(val) -} - -// FileMode returns an attribute KeyValue conforming to the "file.mode" semantic -// conventions. It represents the mode of the file in octal representation. -func FileMode(val string) attribute.KeyValue { - return FileModeKey.String(val) -} - -// FileModified returns an attribute KeyValue conforming to the "file.modified" -// semantic conventions. It represents the time when the file content was last -// modified, in ISO 8601 format. -func FileModified(val string) attribute.KeyValue { - return FileModifiedKey.String(val) -} - -// FileName returns an attribute KeyValue conforming to the "file.name" semantic -// conventions. It represents the name of the file including the extension, -// without the directory. -func FileName(val string) attribute.KeyValue { - return FileNameKey.String(val) -} - -// FileOwnerID returns an attribute KeyValue conforming to the "file.owner.id" -// semantic conventions. It represents the user ID (UID) or security identifier -// (SID) of the file owner. -func FileOwnerID(val string) attribute.KeyValue { - return FileOwnerIDKey.String(val) -} - -// FileOwnerName returns an attribute KeyValue conforming to the -// "file.owner.name" semantic conventions. It represents the username of the file -// owner. -func FileOwnerName(val string) attribute.KeyValue { - return FileOwnerNameKey.String(val) -} - -// FilePath returns an attribute KeyValue conforming to the "file.path" semantic -// conventions. It represents the full path to the file, including the file name. -// It should include the drive letter, when appropriate. -func FilePath(val string) attribute.KeyValue { - return FilePathKey.String(val) -} - -// FileSize returns an attribute KeyValue conforming to the "file.size" semantic -// conventions. It represents the file size in bytes. -func FileSize(val int) attribute.KeyValue { - return FileSizeKey.Int(val) -} - -// FileSymbolicLinkTargetPath returns an attribute KeyValue conforming to the -// "file.symbolic_link.target_path" semantic conventions. It represents the path -// to the target of a symbolic link. -func FileSymbolicLinkTargetPath(val string) attribute.KeyValue { - return FileSymbolicLinkTargetPathKey.String(val) -} - -// Namespace: gcp -const ( - // GCPAppHubApplicationContainerKey is the attribute Key conforming to the - // "gcp.apphub.application.container" semantic conventions. It represents the - // container within GCP where the AppHub application is defined. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "projects/my-container-project" - GCPAppHubApplicationContainerKey = attribute.Key("gcp.apphub.application.container") - - // GCPAppHubApplicationIDKey is the attribute Key conforming to the - // "gcp.apphub.application.id" semantic conventions. It represents the name of - // the application as configured in AppHub. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-application" - GCPAppHubApplicationIDKey = attribute.Key("gcp.apphub.application.id") - - // GCPAppHubApplicationLocationKey is the attribute Key conforming to the - // "gcp.apphub.application.location" semantic conventions. It represents the GCP - // zone or region where the application is defined. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "us-central1" - GCPAppHubApplicationLocationKey = attribute.Key("gcp.apphub.application.location") - - // GCPAppHubServiceCriticalityTypeKey is the attribute Key conforming to the - // "gcp.apphub.service.criticality_type" semantic conventions. It represents the - // criticality of a service indicates its importance to the business. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: [See AppHub type enum] - // - // [See AppHub type enum]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type - GCPAppHubServiceCriticalityTypeKey = attribute.Key("gcp.apphub.service.criticality_type") - - // GCPAppHubServiceEnvironmentTypeKey is the attribute Key conforming to the - // "gcp.apphub.service.environment_type" semantic conventions. It represents the - // environment of a service is the stage of a software lifecycle. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: [See AppHub environment type] - // - // [See AppHub environment type]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type_1 - GCPAppHubServiceEnvironmentTypeKey = attribute.Key("gcp.apphub.service.environment_type") - - // GCPAppHubServiceIDKey is the attribute Key conforming to the - // "gcp.apphub.service.id" semantic conventions. It represents the name of the - // service as configured in AppHub. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-service" - GCPAppHubServiceIDKey = attribute.Key("gcp.apphub.service.id") - - // GCPAppHubWorkloadCriticalityTypeKey is the attribute Key conforming to the - // "gcp.apphub.workload.criticality_type" semantic conventions. It represents - // the criticality of a workload indicates its importance to the business. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: [See AppHub type enum] - // - // [See AppHub type enum]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type - GCPAppHubWorkloadCriticalityTypeKey = attribute.Key("gcp.apphub.workload.criticality_type") - - // GCPAppHubWorkloadEnvironmentTypeKey is the attribute Key conforming to the - // "gcp.apphub.workload.environment_type" semantic conventions. It represents - // the environment of a workload is the stage of a software lifecycle. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: [See AppHub environment type] - // - // [See AppHub environment type]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type_1 - GCPAppHubWorkloadEnvironmentTypeKey = attribute.Key("gcp.apphub.workload.environment_type") - - // GCPAppHubWorkloadIDKey is the attribute Key conforming to the - // "gcp.apphub.workload.id" semantic conventions. It represents the name of the - // workload as configured in AppHub. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-workload" - GCPAppHubWorkloadIDKey = attribute.Key("gcp.apphub.workload.id") - - // GCPAppHubDestinationApplicationContainerKey is the attribute Key conforming - // to the "gcp.apphub_destination.application.container" semantic conventions. - // It represents the container within GCP where the AppHub destination - // application is defined. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "projects/my-container-project" - GCPAppHubDestinationApplicationContainerKey = attribute.Key("gcp.apphub_destination.application.container") - - // GCPAppHubDestinationApplicationIDKey is the attribute Key conforming to the - // "gcp.apphub_destination.application.id" semantic conventions. It represents - // the name of the destination application as configured in AppHub. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-application" - GCPAppHubDestinationApplicationIDKey = attribute.Key("gcp.apphub_destination.application.id") - - // GCPAppHubDestinationApplicationLocationKey is the attribute Key conforming to - // the "gcp.apphub_destination.application.location" semantic conventions. It - // represents the GCP zone or region where the destination application is - // defined. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "us-central1" - GCPAppHubDestinationApplicationLocationKey = attribute.Key("gcp.apphub_destination.application.location") - - // GCPAppHubDestinationServiceCriticalityTypeKey is the attribute Key conforming - // to the "gcp.apphub_destination.service.criticality_type" semantic - // conventions. It represents the criticality of a destination workload - // indicates its importance to the business as specified in [AppHub type enum]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [AppHub type enum]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type - GCPAppHubDestinationServiceCriticalityTypeKey = attribute.Key("gcp.apphub_destination.service.criticality_type") - - // GCPAppHubDestinationServiceEnvironmentTypeKey is the attribute Key conforming - // to the "gcp.apphub_destination.service.environment_type" semantic - // conventions. It represents the software lifecycle stage of a destination - // service as defined [AppHub environment type]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [AppHub environment type]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type_1 - GCPAppHubDestinationServiceEnvironmentTypeKey = attribute.Key("gcp.apphub_destination.service.environment_type") - - // GCPAppHubDestinationServiceIDKey is the attribute Key conforming to the - // "gcp.apphub_destination.service.id" semantic conventions. It represents the - // name of the destination service as configured in AppHub. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-service" - GCPAppHubDestinationServiceIDKey = attribute.Key("gcp.apphub_destination.service.id") - - // GCPAppHubDestinationWorkloadCriticalityTypeKey is the attribute Key - // conforming to the "gcp.apphub_destination.workload.criticality_type" semantic - // conventions. It represents the criticality of a destination workload - // indicates its importance to the business as specified in [AppHub type enum]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [AppHub type enum]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type - GCPAppHubDestinationWorkloadCriticalityTypeKey = attribute.Key("gcp.apphub_destination.workload.criticality_type") - - // GCPAppHubDestinationWorkloadEnvironmentTypeKey is the attribute Key - // conforming to the "gcp.apphub_destination.workload.environment_type" semantic - // conventions. It represents the environment of a destination workload is the - // stage of a software lifecycle as provided in the [AppHub environment type]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [AppHub environment type]: https://cloud.google.com/app-hub/docs/reference/rest/v1/Attributes#type_1 - GCPAppHubDestinationWorkloadEnvironmentTypeKey = attribute.Key("gcp.apphub_destination.workload.environment_type") - - // GCPAppHubDestinationWorkloadIDKey is the attribute Key conforming to the - // "gcp.apphub_destination.workload.id" semantic conventions. It represents the - // name of the destination workload as configured in AppHub. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-workload" - GCPAppHubDestinationWorkloadIDKey = attribute.Key("gcp.apphub_destination.workload.id") - - // GCPClientServiceKey is the attribute Key conforming to the - // "gcp.client.service" semantic conventions. It represents the identifies the - // Google Cloud service for which the official client library is intended. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "appengine", "run", "firestore", "alloydb", "spanner" - // Note: Intended to be a stable identifier for Google Cloud client libraries - // that is uniform across implementation languages. The value should be derived - // from the canonical service domain for the service; for example, - // 'foo.googleapis.com' should result in a value of 'foo'. - GCPClientServiceKey = attribute.Key("gcp.client.service") - - // GCPCloudRunJobExecutionKey is the attribute Key conforming to the - // "gcp.cloud_run.job.execution" semantic conventions. It represents the name of - // the Cloud Run [execution] being run for the Job, as set by the - // [`CLOUD_RUN_EXECUTION`] environment variable. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "job-name-xxxx", "sample-job-mdw84" - // - // [execution]: https://cloud.google.com/run/docs/managing/job-executions - // [`CLOUD_RUN_EXECUTION`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars - GCPCloudRunJobExecutionKey = attribute.Key("gcp.cloud_run.job.execution") - - // GCPCloudRunJobTaskIndexKey is the attribute Key conforming to the - // "gcp.cloud_run.job.task_index" semantic conventions. It represents the index - // for a task within an execution as provided by the [`CLOUD_RUN_TASK_INDEX`] - // environment variable. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0, 1 - // - // [`CLOUD_RUN_TASK_INDEX`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars - GCPCloudRunJobTaskIndexKey = attribute.Key("gcp.cloud_run.job.task_index") - - // GCPGCEInstanceHostnameKey is the attribute Key conforming to the - // "gcp.gce.instance.hostname" semantic conventions. It represents the hostname - // of a GCE instance. This is the full value of the default or [custom hostname] - // . - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-host1234.example.com", - // "sample-vm.us-west1-b.c.my-project.internal" - // - // [custom hostname]: https://cloud.google.com/compute/docs/instances/custom-hostname-vm - GCPGCEInstanceHostnameKey = attribute.Key("gcp.gce.instance.hostname") - - // GCPGCEInstanceNameKey is the attribute Key conforming to the - // "gcp.gce.instance.name" semantic conventions. It represents the instance name - // of a GCE instance. This is the value provided by `host.name`, the visible - // name of the instance in the Cloud Console UI, and the prefix for the default - // hostname of the instance as defined by the [default internal DNS name]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "instance-1", "my-vm-name" - // - // [default internal DNS name]: https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names - GCPGCEInstanceNameKey = attribute.Key("gcp.gce.instance.name") - - // GCPGCEInstanceGroupManagerNameKey is the attribute Key conforming to the - // "gcp.gce.instance_group_manager.name" semantic conventions. It represents the - // name of the Instance Group Manager (IGM) that manages this VM, if any. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "web-igm", "my-managed-group" - GCPGCEInstanceGroupManagerNameKey = attribute.Key("gcp.gce.instance_group_manager.name") - - // GCPGCEInstanceGroupManagerRegionKey is the attribute Key conforming to the - // "gcp.gce.instance_group_manager.region" semantic conventions. It represents - // the region of a **regional** Instance Group Manager (e.g., `us-central1`). - // Set this **only** when the IGM is regional. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "us-central1", "europe-west1" - GCPGCEInstanceGroupManagerRegionKey = attribute.Key("gcp.gce.instance_group_manager.region") - - // GCPGCEInstanceGroupManagerZoneKey is the attribute Key conforming to the - // "gcp.gce.instance_group_manager.zone" semantic conventions. It represents the - // zone of a **zonal** Instance Group Manager (e.g., `us-central1-a`). Set this - // **only** when the IGM is zonal. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "us-central1-a", "europe-west1-b" - GCPGCEInstanceGroupManagerZoneKey = attribute.Key("gcp.gce.instance_group_manager.zone") -) - -// GCPAppHubApplicationContainer returns an attribute KeyValue conforming to the -// "gcp.apphub.application.container" semantic conventions. It represents the -// container within GCP where the AppHub application is defined. -func GCPAppHubApplicationContainer(val string) attribute.KeyValue { - return GCPAppHubApplicationContainerKey.String(val) -} - -// GCPAppHubApplicationID returns an attribute KeyValue conforming to the -// "gcp.apphub.application.id" semantic conventions. It represents the name of -// the application as configured in AppHub. -func GCPAppHubApplicationID(val string) attribute.KeyValue { - return GCPAppHubApplicationIDKey.String(val) -} - -// GCPAppHubApplicationLocation returns an attribute KeyValue conforming to the -// "gcp.apphub.application.location" semantic conventions. It represents the GCP -// zone or region where the application is defined. -func GCPAppHubApplicationLocation(val string) attribute.KeyValue { - return GCPAppHubApplicationLocationKey.String(val) -} - -// GCPAppHubServiceID returns an attribute KeyValue conforming to the -// "gcp.apphub.service.id" semantic conventions. It represents the name of the -// service as configured in AppHub. -func GCPAppHubServiceID(val string) attribute.KeyValue { - return GCPAppHubServiceIDKey.String(val) -} - -// GCPAppHubWorkloadID returns an attribute KeyValue conforming to the -// "gcp.apphub.workload.id" semantic conventions. It represents the name of the -// workload as configured in AppHub. -func GCPAppHubWorkloadID(val string) attribute.KeyValue { - return GCPAppHubWorkloadIDKey.String(val) -} - -// GCPAppHubDestinationApplicationContainer returns an attribute KeyValue -// conforming to the "gcp.apphub_destination.application.container" semantic -// conventions. It represents the container within GCP where the AppHub -// destination application is defined. -func GCPAppHubDestinationApplicationContainer(val string) attribute.KeyValue { - return GCPAppHubDestinationApplicationContainerKey.String(val) -} - -// GCPAppHubDestinationApplicationID returns an attribute KeyValue conforming to -// the "gcp.apphub_destination.application.id" semantic conventions. It -// represents the name of the destination application as configured in AppHub. -func GCPAppHubDestinationApplicationID(val string) attribute.KeyValue { - return GCPAppHubDestinationApplicationIDKey.String(val) -} - -// GCPAppHubDestinationApplicationLocation returns an attribute KeyValue -// conforming to the "gcp.apphub_destination.application.location" semantic -// conventions. It represents the GCP zone or region where the destination -// application is defined. -func GCPAppHubDestinationApplicationLocation(val string) attribute.KeyValue { - return GCPAppHubDestinationApplicationLocationKey.String(val) -} - -// GCPAppHubDestinationServiceID returns an attribute KeyValue conforming to the -// "gcp.apphub_destination.service.id" semantic conventions. It represents the -// name of the destination service as configured in AppHub. -func GCPAppHubDestinationServiceID(val string) attribute.KeyValue { - return GCPAppHubDestinationServiceIDKey.String(val) -} - -// GCPAppHubDestinationWorkloadID returns an attribute KeyValue conforming to the -// "gcp.apphub_destination.workload.id" semantic conventions. It represents the -// name of the destination workload as configured in AppHub. -func GCPAppHubDestinationWorkloadID(val string) attribute.KeyValue { - return GCPAppHubDestinationWorkloadIDKey.String(val) -} - -// GCPClientService returns an attribute KeyValue conforming to the -// "gcp.client.service" semantic conventions. It represents the identifies the -// Google Cloud service for which the official client library is intended. -func GCPClientService(val string) attribute.KeyValue { - return GCPClientServiceKey.String(val) -} - -// GCPCloudRunJobExecution returns an attribute KeyValue conforming to the -// "gcp.cloud_run.job.execution" semantic conventions. It represents the name of -// the Cloud Run [execution] being run for the Job, as set by the -// [`CLOUD_RUN_EXECUTION`] environment variable. -// -// [execution]: https://cloud.google.com/run/docs/managing/job-executions -// [`CLOUD_RUN_EXECUTION`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars -func GCPCloudRunJobExecution(val string) attribute.KeyValue { - return GCPCloudRunJobExecutionKey.String(val) -} - -// GCPCloudRunJobTaskIndex returns an attribute KeyValue conforming to the -// "gcp.cloud_run.job.task_index" semantic conventions. It represents the index -// for a task within an execution as provided by the [`CLOUD_RUN_TASK_INDEX`] -// environment variable. -// -// [`CLOUD_RUN_TASK_INDEX`]: https://cloud.google.com/run/docs/container-contract#jobs-env-vars -func GCPCloudRunJobTaskIndex(val int) attribute.KeyValue { - return GCPCloudRunJobTaskIndexKey.Int(val) -} - -// GCPGCEInstanceHostname returns an attribute KeyValue conforming to the -// "gcp.gce.instance.hostname" semantic conventions. It represents the hostname -// of a GCE instance. This is the full value of the default or [custom hostname] -// . -// -// [custom hostname]: https://cloud.google.com/compute/docs/instances/custom-hostname-vm -func GCPGCEInstanceHostname(val string) attribute.KeyValue { - return GCPGCEInstanceHostnameKey.String(val) -} - -// GCPGCEInstanceName returns an attribute KeyValue conforming to the -// "gcp.gce.instance.name" semantic conventions. It represents the instance name -// of a GCE instance. This is the value provided by `host.name`, the visible name -// of the instance in the Cloud Console UI, and the prefix for the default -// hostname of the instance as defined by the [default internal DNS name]. -// -// [default internal DNS name]: https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names -func GCPGCEInstanceName(val string) attribute.KeyValue { - return GCPGCEInstanceNameKey.String(val) -} - -// GCPGCEInstanceGroupManagerName returns an attribute KeyValue conforming to the -// "gcp.gce.instance_group_manager.name" semantic conventions. It represents the -// name of the Instance Group Manager (IGM) that manages this VM, if any. -func GCPGCEInstanceGroupManagerName(val string) attribute.KeyValue { - return GCPGCEInstanceGroupManagerNameKey.String(val) -} - -// GCPGCEInstanceGroupManagerRegion returns an attribute KeyValue conforming to -// the "gcp.gce.instance_group_manager.region" semantic conventions. It -// represents the region of a **regional** Instance Group Manager (e.g., -// `us-central1`). Set this **only** when the IGM is regional. -func GCPGCEInstanceGroupManagerRegion(val string) attribute.KeyValue { - return GCPGCEInstanceGroupManagerRegionKey.String(val) -} - -// GCPGCEInstanceGroupManagerZone returns an attribute KeyValue conforming to the -// "gcp.gce.instance_group_manager.zone" semantic conventions. It represents the -// zone of a **zonal** Instance Group Manager (e.g., `us-central1-a`). Set this -// **only** when the IGM is zonal. -func GCPGCEInstanceGroupManagerZone(val string) attribute.KeyValue { - return GCPGCEInstanceGroupManagerZoneKey.String(val) -} - -// Enum values for gcp.apphub.service.criticality_type -var ( - // Mission critical service. - // Stability: development - GCPAppHubServiceCriticalityTypeMissionCritical = GCPAppHubServiceCriticalityTypeKey.String("MISSION_CRITICAL") - // High impact. - // Stability: development - GCPAppHubServiceCriticalityTypeHigh = GCPAppHubServiceCriticalityTypeKey.String("HIGH") - // Medium impact. - // Stability: development - GCPAppHubServiceCriticalityTypeMedium = GCPAppHubServiceCriticalityTypeKey.String("MEDIUM") - // Low impact. - // Stability: development - GCPAppHubServiceCriticalityTypeLow = GCPAppHubServiceCriticalityTypeKey.String("LOW") -) - -// Enum values for gcp.apphub.service.environment_type -var ( - // Production environment. - // Stability: development - GCPAppHubServiceEnvironmentTypeProduction = GCPAppHubServiceEnvironmentTypeKey.String("PRODUCTION") - // Staging environment. - // Stability: development - GCPAppHubServiceEnvironmentTypeStaging = GCPAppHubServiceEnvironmentTypeKey.String("STAGING") - // Test environment. - // Stability: development - GCPAppHubServiceEnvironmentTypeTest = GCPAppHubServiceEnvironmentTypeKey.String("TEST") - // Development environment. - // Stability: development - GCPAppHubServiceEnvironmentTypeDevelopment = GCPAppHubServiceEnvironmentTypeKey.String("DEVELOPMENT") -) - -// Enum values for gcp.apphub.workload.criticality_type -var ( - // Mission critical service. - // Stability: development - GCPAppHubWorkloadCriticalityTypeMissionCritical = GCPAppHubWorkloadCriticalityTypeKey.String("MISSION_CRITICAL") - // High impact. - // Stability: development - GCPAppHubWorkloadCriticalityTypeHigh = GCPAppHubWorkloadCriticalityTypeKey.String("HIGH") - // Medium impact. - // Stability: development - GCPAppHubWorkloadCriticalityTypeMedium = GCPAppHubWorkloadCriticalityTypeKey.String("MEDIUM") - // Low impact. - // Stability: development - GCPAppHubWorkloadCriticalityTypeLow = GCPAppHubWorkloadCriticalityTypeKey.String("LOW") -) - -// Enum values for gcp.apphub.workload.environment_type -var ( - // Production environment. - // Stability: development - GCPAppHubWorkloadEnvironmentTypeProduction = GCPAppHubWorkloadEnvironmentTypeKey.String("PRODUCTION") - // Staging environment. - // Stability: development - GCPAppHubWorkloadEnvironmentTypeStaging = GCPAppHubWorkloadEnvironmentTypeKey.String("STAGING") - // Test environment. - // Stability: development - GCPAppHubWorkloadEnvironmentTypeTest = GCPAppHubWorkloadEnvironmentTypeKey.String("TEST") - // Development environment. - // Stability: development - GCPAppHubWorkloadEnvironmentTypeDevelopment = GCPAppHubWorkloadEnvironmentTypeKey.String("DEVELOPMENT") -) - -// Enum values for gcp.apphub_destination.service.criticality_type -var ( - // Mission critical service. - // Stability: development - GCPAppHubDestinationServiceCriticalityTypeMissionCritical = GCPAppHubDestinationServiceCriticalityTypeKey.String("MISSION_CRITICAL") - // High impact. - // Stability: development - GCPAppHubDestinationServiceCriticalityTypeHigh = GCPAppHubDestinationServiceCriticalityTypeKey.String("HIGH") - // Medium impact. - // Stability: development - GCPAppHubDestinationServiceCriticalityTypeMedium = GCPAppHubDestinationServiceCriticalityTypeKey.String("MEDIUM") - // Low impact. - // Stability: development - GCPAppHubDestinationServiceCriticalityTypeLow = GCPAppHubDestinationServiceCriticalityTypeKey.String("LOW") -) - -// Enum values for gcp.apphub_destination.service.environment_type -var ( - // Production environment. - // Stability: development - GCPAppHubDestinationServiceEnvironmentTypeProduction = GCPAppHubDestinationServiceEnvironmentTypeKey.String("PRODUCTION") - // Staging environment. - // Stability: development - GCPAppHubDestinationServiceEnvironmentTypeStaging = GCPAppHubDestinationServiceEnvironmentTypeKey.String("STAGING") - // Test environment. - // Stability: development - GCPAppHubDestinationServiceEnvironmentTypeTest = GCPAppHubDestinationServiceEnvironmentTypeKey.String("TEST") - // Development environment. - // Stability: development - GCPAppHubDestinationServiceEnvironmentTypeDevelopment = GCPAppHubDestinationServiceEnvironmentTypeKey.String("DEVELOPMENT") -) - -// Enum values for gcp.apphub_destination.workload.criticality_type -var ( - // Mission critical service. - // Stability: development - GCPAppHubDestinationWorkloadCriticalityTypeMissionCritical = GCPAppHubDestinationWorkloadCriticalityTypeKey.String("MISSION_CRITICAL") - // High impact. - // Stability: development - GCPAppHubDestinationWorkloadCriticalityTypeHigh = GCPAppHubDestinationWorkloadCriticalityTypeKey.String("HIGH") - // Medium impact. - // Stability: development - GCPAppHubDestinationWorkloadCriticalityTypeMedium = GCPAppHubDestinationWorkloadCriticalityTypeKey.String("MEDIUM") - // Low impact. - // Stability: development - GCPAppHubDestinationWorkloadCriticalityTypeLow = GCPAppHubDestinationWorkloadCriticalityTypeKey.String("LOW") -) - -// Enum values for gcp.apphub_destination.workload.environment_type -var ( - // Production environment. - // Stability: development - GCPAppHubDestinationWorkloadEnvironmentTypeProduction = GCPAppHubDestinationWorkloadEnvironmentTypeKey.String("PRODUCTION") - // Staging environment. - // Stability: development - GCPAppHubDestinationWorkloadEnvironmentTypeStaging = GCPAppHubDestinationWorkloadEnvironmentTypeKey.String("STAGING") - // Test environment. - // Stability: development - GCPAppHubDestinationWorkloadEnvironmentTypeTest = GCPAppHubDestinationWorkloadEnvironmentTypeKey.String("TEST") - // Development environment. - // Stability: development - GCPAppHubDestinationWorkloadEnvironmentTypeDevelopment = GCPAppHubDestinationWorkloadEnvironmentTypeKey.String("DEVELOPMENT") -) - -// Namespace: gen_ai -const ( - // GenAIAgentDescriptionKey is the attribute Key conforming to the - // "gen_ai.agent.description" semantic conventions. It represents the free-form - // description of the GenAI agent provided by the application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Helps with math problems", "Generates fiction stories" - GenAIAgentDescriptionKey = attribute.Key("gen_ai.agent.description") - - // GenAIAgentIDKey is the attribute Key conforming to the "gen_ai.agent.id" - // semantic conventions. It represents the unique identifier of the GenAI agent. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "asst_5j66UpCpwteGg4YSxUnt7lPY" - GenAIAgentIDKey = attribute.Key("gen_ai.agent.id") - - // GenAIAgentNameKey is the attribute Key conforming to the "gen_ai.agent.name" - // semantic conventions. It represents the human-readable name of the GenAI - // agent provided by the application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Math Tutor", "Fiction Writer" - GenAIAgentNameKey = attribute.Key("gen_ai.agent.name") - - // GenAIAgentVersionKey is the attribute Key conforming to the - // "gen_ai.agent.version" semantic conventions. It represents the version of the - // GenAI agent. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1.0.0", "2025-05-01" - GenAIAgentVersionKey = attribute.Key("gen_ai.agent.version") - - // GenAIConversationIDKey is the attribute Key conforming to the - // "gen_ai.conversation.id" semantic conventions. It represents the unique - // identifier for a conversation (session, thread), used to store and correlate - // messages within this conversation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "conv_5j66UpCpwteGg4YSxUnt7lPY" - GenAIConversationIDKey = attribute.Key("gen_ai.conversation.id") - - // GenAIDataSourceIDKey is the attribute Key conforming to the - // "gen_ai.data_source.id" semantic conventions. It represents the data source - // identifier. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "H7STPQYOND" - // Note: Data sources are used by AI agents and RAG applications to store - // grounding data. A data source may be an external database, object store, - // document collection, website, or any other storage system used by the GenAI - // agent or application. The `gen_ai.data_source.id` SHOULD match the identifier - // used by the GenAI system rather than a name specific to the external storage, - // such as a database or object store. Semantic conventions referencing - // `gen_ai.data_source.id` MAY also leverage additional attributes, such as - // `db.*`, to further identify and describe the data source. - GenAIDataSourceIDKey = attribute.Key("gen_ai.data_source.id") - - // GenAIEmbeddingsDimensionCountKey is the attribute Key conforming to the - // "gen_ai.embeddings.dimension.count" semantic conventions. It represents the - // number of dimensions the resulting output embeddings should have. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 512, 1024 - GenAIEmbeddingsDimensionCountKey = attribute.Key("gen_ai.embeddings.dimension.count") - - // GenAIEvaluationExplanationKey is the attribute Key conforming to the - // "gen_ai.evaluation.explanation" semantic conventions. It represents a - // free-form explanation for the assigned score provided by the evaluator. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "The response is factually accurate but lacks sufficient detail to - // fully address the question." - GenAIEvaluationExplanationKey = attribute.Key("gen_ai.evaluation.explanation") - - // GenAIEvaluationNameKey is the attribute Key conforming to the - // "gen_ai.evaluation.name" semantic conventions. It represents the name of the - // evaluation metric used for the GenAI response. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Relevance", "IntentResolution" - GenAIEvaluationNameKey = attribute.Key("gen_ai.evaluation.name") - - // GenAIEvaluationScoreLabelKey is the attribute Key conforming to the - // "gen_ai.evaluation.score.label" semantic conventions. It represents the human - // readable label for evaluation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "relevant", "not_relevant", "correct", "incorrect", "pass", "fail" - // Note: This attribute provides a human-readable interpretation of the - // evaluation score produced by an evaluator. For example, a score value of 1 - // could mean "relevant" in one evaluation system and "not relevant" in another, - // depending on the scoring range and evaluator. The label SHOULD have low - // cardinality. Possible values depend on the evaluation metric and evaluator - // used; implementations SHOULD document the possible values. - GenAIEvaluationScoreLabelKey = attribute.Key("gen_ai.evaluation.score.label") - - // GenAIEvaluationScoreValueKey is the attribute Key conforming to the - // "gen_ai.evaluation.score.value" semantic conventions. It represents the - // evaluation score returned by the evaluator. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 4.0 - GenAIEvaluationScoreValueKey = attribute.Key("gen_ai.evaluation.score.value") - - // GenAIInputMessagesKey is the attribute Key conforming to the - // "gen_ai.input.messages" semantic conventions. It represents the chat history - // provided to the model as an input. - // - // Type: any - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "[\n {\n "role": "user",\n "parts": [\n {\n "type": "text",\n - // "content": "Weather in Paris?"\n }\n ]\n },\n {\n "role": "assistant",\n - // "parts": [\n {\n "type": "tool_call",\n "id": - // "call_VSPygqKTWdrhaFErNvMV18Yl",\n "name": "get_weather",\n "arguments": {\n - // "location": "Paris"\n }\n }\n ]\n },\n {\n "role": "tool",\n "parts": [\n {\n - // "type": "tool_call_response",\n "id": " call_VSPygqKTWdrhaFErNvMV18Yl",\n - // "result": "rainy, 57°F"\n }\n ]\n }\n]\n" - // Note: Instrumentations MUST follow [Input messages JSON schema]. - // When the attribute is recorded on events, it MUST be recorded in structured - // form. When recorded on spans, it MAY be recorded as a JSON string if - // structured - // format is not supported and SHOULD be recorded in structured form otherwise. - // - // Messages MUST be provided in the order they were sent to the model. - // Instrumentations MAY provide a way for users to filter or truncate - // input messages. - // - // > [!Warning] - // > This attribute is likely to contain sensitive information including - // > user/PII data. - // - // See [Recording content on attributes] - // section for more details. - // - // [Input messages JSON schema]: /docs/gen-ai/gen-ai-input-messages.json - // [Recording content on attributes]: /docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes - GenAIInputMessagesKey = attribute.Key("gen_ai.input.messages") - - // GenAIOperationNameKey is the attribute Key conforming to the - // "gen_ai.operation.name" semantic conventions. It represents the name of the - // operation being performed. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: If one of the predefined values applies, but specific system uses a - // different name it's RECOMMENDED to document it in the semantic conventions - // for specific GenAI system and use system-specific name in the - // instrumentation. If a different name is not documented, instrumentation - // libraries SHOULD use applicable predefined value. - GenAIOperationNameKey = attribute.Key("gen_ai.operation.name") - - // GenAIOutputMessagesKey is the attribute Key conforming to the - // "gen_ai.output.messages" semantic conventions. It represents the messages - // returned by the model where each message represents a specific model response - // (choice, candidate). - // - // Type: any - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "[\n {\n "role": "assistant",\n "parts": [\n {\n "type": "text",\n - // "content": "The weather in Paris is currently rainy with a temperature of - // 57°F."\n }\n ],\n "finish_reason": "stop"\n }\n]\n" - // Note: Instrumentations MUST follow [Output messages JSON schema] - // - // Each message represents a single output choice/candidate generated by - // the model. Each message corresponds to exactly one generation - // (choice/candidate) and vice versa - one choice cannot be split across - // multiple messages or one message cannot contain parts from multiple choices. - // - // When the attribute is recorded on events, it MUST be recorded in structured - // form. When recorded on spans, it MAY be recorded as a JSON string if - // structured - // format is not supported and SHOULD be recorded in structured form otherwise. - // - // Instrumentations MAY provide a way for users to filter or truncate - // output messages. - // - // > [!Warning] - // > This attribute is likely to contain sensitive information including - // > user/PII data. - // - // See [Recording content on attributes] - // section for more details. - // - // [Output messages JSON schema]: /docs/gen-ai/gen-ai-output-messages.json - // [Recording content on attributes]: /docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes - GenAIOutputMessagesKey = attribute.Key("gen_ai.output.messages") - - // GenAIOutputTypeKey is the attribute Key conforming to the - // "gen_ai.output.type" semantic conventions. It represents the represents the - // content type requested by the client. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: This attribute SHOULD be used when the client requests output of a - // specific type. The model may return zero or more outputs of this type. - // This attribute specifies the output modality and not the actual output - // format. For example, if an image is requested, the actual output could be a - // URL pointing to an image file. - // Additional output format details may be recorded in the future in the - // `gen_ai.output.{type}.*` attributes. - GenAIOutputTypeKey = attribute.Key("gen_ai.output.type") - - // GenAIPromptNameKey is the attribute Key conforming to the - // "gen_ai.prompt.name" semantic conventions. It represents the name of the - // prompt that uniquely identifies it. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "analyze-code" - GenAIPromptNameKey = attribute.Key("gen_ai.prompt.name") - - // GenAIProviderNameKey is the attribute Key conforming to the - // "gen_ai.provider.name" semantic conventions. It represents the Generative AI - // provider as identified by the client or server instrumentation. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: The attribute SHOULD be set based on the instrumentation's best - // knowledge and may differ from the actual model provider. - // - // Multiple providers, including Azure OpenAI, Gemini, and AI hosting platforms - // are accessible using the OpenAI REST API and corresponding client libraries, - // but may proxy or host models from different providers. - // - // The `gen_ai.request.model`, `gen_ai.response.model`, and `server.address` - // attributes may help identify the actual system in use. - // - // The `gen_ai.provider.name` attribute acts as a discriminator that - // identifies the GenAI telemetry format flavor specific to that provider - // within GenAI semantic conventions. - // It SHOULD be set consistently with provider-specific attributes and signals. - // For example, GenAI spans, metrics, and events related to AWS Bedrock - // should have the `gen_ai.provider.name` set to `aws.bedrock` and include - // applicable `aws.bedrock.*` attributes and are not expected to include - // `openai.*` attributes. - GenAIProviderNameKey = attribute.Key("gen_ai.provider.name") - - // GenAIRequestChoiceCountKey is the attribute Key conforming to the - // "gen_ai.request.choice.count" semantic conventions. It represents the target - // number of candidate completions to return. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 3 - GenAIRequestChoiceCountKey = attribute.Key("gen_ai.request.choice.count") - - // GenAIRequestEncodingFormatsKey is the attribute Key conforming to the - // "gen_ai.request.encoding_formats" semantic conventions. It represents the - // encoding formats requested in an embeddings operation, if specified. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "base64"], ["float", "binary" - // Note: In some GenAI systems the encoding formats are called embedding types. - // Also, some GenAI systems only accept a single format per request. - GenAIRequestEncodingFormatsKey = attribute.Key("gen_ai.request.encoding_formats") - - // GenAIRequestFrequencyPenaltyKey is the attribute Key conforming to the - // "gen_ai.request.frequency_penalty" semantic conventions. It represents the - // frequency penalty setting for the GenAI request. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0.1 - GenAIRequestFrequencyPenaltyKey = attribute.Key("gen_ai.request.frequency_penalty") - - // GenAIRequestMaxTokensKey is the attribute Key conforming to the - // "gen_ai.request.max_tokens" semantic conventions. It represents the maximum - // number of tokens the model generates for a request. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 100 - GenAIRequestMaxTokensKey = attribute.Key("gen_ai.request.max_tokens") - - // GenAIRequestModelKey is the attribute Key conforming to the - // "gen_ai.request.model" semantic conventions. It represents the name of the - // GenAI model a request is being made to. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: gpt-4 - GenAIRequestModelKey = attribute.Key("gen_ai.request.model") - - // GenAIRequestPresencePenaltyKey is the attribute Key conforming to the - // "gen_ai.request.presence_penalty" semantic conventions. It represents the - // presence penalty setting for the GenAI request. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0.1 - GenAIRequestPresencePenaltyKey = attribute.Key("gen_ai.request.presence_penalty") - - // GenAIRequestSeedKey is the attribute Key conforming to the - // "gen_ai.request.seed" semantic conventions. It represents the requests with - // same seed value more likely to return same result. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 100 - GenAIRequestSeedKey = attribute.Key("gen_ai.request.seed") - - // GenAIRequestStopSequencesKey is the attribute Key conforming to the - // "gen_ai.request.stop_sequences" semantic conventions. It represents the list - // of sequences that the model will use to stop generating further tokens. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "forest", "lived" - GenAIRequestStopSequencesKey = attribute.Key("gen_ai.request.stop_sequences") - - // GenAIRequestTemperatureKey is the attribute Key conforming to the - // "gen_ai.request.temperature" semantic conventions. It represents the - // temperature setting for the GenAI request. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0.0 - GenAIRequestTemperatureKey = attribute.Key("gen_ai.request.temperature") - - // GenAIRequestTopKKey is the attribute Key conforming to the - // "gen_ai.request.top_k" semantic conventions. It represents the top_k sampling - // setting for the GenAI request. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1.0 - GenAIRequestTopKKey = attribute.Key("gen_ai.request.top_k") - - // GenAIRequestTopPKey is the attribute Key conforming to the - // "gen_ai.request.top_p" semantic conventions. It represents the top_p sampling - // setting for the GenAI request. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1.0 - GenAIRequestTopPKey = attribute.Key("gen_ai.request.top_p") - - // GenAIResponseFinishReasonsKey is the attribute Key conforming to the - // "gen_ai.response.finish_reasons" semantic conventions. It represents the - // array of reasons the model stopped generating tokens, corresponding to each - // generation received. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "stop"], ["stop", "length" - GenAIResponseFinishReasonsKey = attribute.Key("gen_ai.response.finish_reasons") - - // GenAIResponseIDKey is the attribute Key conforming to the - // "gen_ai.response.id" semantic conventions. It represents the unique - // identifier for the completion. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "chatcmpl-123" - GenAIResponseIDKey = attribute.Key("gen_ai.response.id") - - // GenAIResponseModelKey is the attribute Key conforming to the - // "gen_ai.response.model" semantic conventions. It represents the name of the - // model that generated the response. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "gpt-4-0613" - GenAIResponseModelKey = attribute.Key("gen_ai.response.model") - - // GenAIRetrievalDocumentsKey is the attribute Key conforming to the - // "gen_ai.retrieval.documents" semantic conventions. It represents the - // documents retrieved. - // - // Type: any - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "[\n {\n "id": "doc_123",\n "score": 0.95\n },\n {\n "id": - // "doc_456",\n "score": 0.87\n },\n {\n "id": "doc_789",\n "score": 0.82\n - // }\n]\n" - // Note: Instrumentations MUST follow [Retrieval documents JSON schema]. - // When the attribute is recorded on events, it MUST be recorded in structured - // form. When recorded on spans, it MAY be recorded as a JSON string if - // structured - // format is not supported and SHOULD be recorded in structured form otherwise. - // - // Each document object SHOULD contain at least the following properties: - // `id` (string): A unique identifier for the document, `score` (double): The - // relevance score of the document - // - // [Retrieval documents JSON schema]: /docs/gen-ai/gen-ai-retrieval-documents.json - GenAIRetrievalDocumentsKey = attribute.Key("gen_ai.retrieval.documents") - - // GenAIRetrievalQueryTextKey is the attribute Key conforming to the - // "gen_ai.retrieval.query.text" semantic conventions. It represents the query - // text used for retrieval. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "What is the capital of France?", "weather in Paris" - // Note: > [!Warning] - // - // > This attribute may contain sensitive information. - GenAIRetrievalQueryTextKey = attribute.Key("gen_ai.retrieval.query.text") - - // GenAISystemInstructionsKey is the attribute Key conforming to the - // "gen_ai.system_instructions" semantic conventions. It represents the system - // message or instructions provided to the GenAI model separately from the chat - // history. - // - // Type: any - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "[\n {\n "type": "text",\n "content": "You are an Agent that greet - // users, always use greetings tool to respond"\n }\n]\n", "[\n {\n "type": - // "text",\n "content": "You are a language translator."\n },\n {\n "type": - // "text",\n "content": "Your mission is to translate text in English to - // French."\n }\n]\n" - // Note: This attribute SHOULD be used when the corresponding provider or API - // allows to provide system instructions or messages separately from the - // chat history. - // - // Instructions that are part of the chat history SHOULD be recorded in - // `gen_ai.input.messages` attribute instead. - // - // Instrumentations MUST follow [System instructions JSON schema]. - // - // When recorded on spans, it MAY be recorded as a JSON string if structured - // format is not supported and SHOULD be recorded in structured form otherwise. - // - // Instrumentations MAY provide a way for users to filter or truncate - // system instructions. - // - // > [!Warning] - // > This attribute may contain sensitive information. - // - // See [Recording content on attributes] - // section for more details. - // - // [System instructions JSON schema]: /docs/gen-ai/gen-ai-system-instructions.json - // [Recording content on attributes]: /docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes - GenAISystemInstructionsKey = attribute.Key("gen_ai.system_instructions") - - // GenAITokenTypeKey is the attribute Key conforming to the "gen_ai.token.type" - // semantic conventions. It represents the type of token being counted. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "input", "output" - GenAITokenTypeKey = attribute.Key("gen_ai.token.type") - - // GenAIToolCallArgumentsKey is the attribute Key conforming to the - // "gen_ai.tool.call.arguments" semantic conventions. It represents the - // parameters passed to the tool call. - // - // Type: any - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{\n "location": "San Francisco?",\n "date": "2025-10-01"\n}\n" - // Note: > [!WARNING] - // - // > This attribute may contain sensitive information. - // - // It's expected to be an object - in case a serialized string is available - // to the instrumentation, the instrumentation SHOULD do the best effort to - // deserialize it to an object. When recorded on spans, it MAY be recorded as a - // JSON string if structured format is not supported and SHOULD be recorded in - // structured form otherwise. - GenAIToolCallArgumentsKey = attribute.Key("gen_ai.tool.call.arguments") - - // GenAIToolCallIDKey is the attribute Key conforming to the - // "gen_ai.tool.call.id" semantic conventions. It represents the tool call - // identifier. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "call_mszuSIzqtI65i1wAUOE8w5H4" - GenAIToolCallIDKey = attribute.Key("gen_ai.tool.call.id") - - // GenAIToolCallResultKey is the attribute Key conforming to the - // "gen_ai.tool.call.result" semantic conventions. It represents the result - // returned by the tool call (if any and if execution was successful). - // - // Type: any - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "{\n "temperature_range": {\n "high": 75,\n "low": 60\n },\n - // "conditions": "sunny"\n}\n" - // Note: > [!WARNING] - // - // > This attribute may contain sensitive information. - // - // It's expected to be an object - in case a serialized string is available - // to the instrumentation, the instrumentation SHOULD do the best effort to - // deserialize it to an object. When recorded on spans, it MAY be recorded as a - // JSON string if structured format is not supported and SHOULD be recorded in - // structured form otherwise. - GenAIToolCallResultKey = attribute.Key("gen_ai.tool.call.result") - - // GenAIToolDefinitionsKey is the attribute Key conforming to the - // "gen_ai.tool.definitions" semantic conventions. It represents the list of - // source system tool definitions available to the GenAI agent or model. - // - // Type: any - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "[\n {\n "type": "function",\n "name": "get_current_weather",\n - // "description": "Get the current weather in a given location",\n "parameters": - // {\n "type": "object",\n "properties": {\n "location": {\n "type": "string",\n - // "description": "The city and state, e.g. San Francisco, CA"\n },\n "unit": - // {\n "type": "string",\n "enum": [\n "celsius",\n "fahrenheit"\n ]\n }\n },\n - // "required": [\n "location",\n "unit"\n ]\n }\n }\n]\n" - // Note: The value of this attribute matches source system tool definition - // format. - // - // It's expected to be an array of objects where each object represents a tool - // definition. In case a serialized string is available - // to the instrumentation, the instrumentation SHOULD do the best effort to - // deserialize it to an array. When recorded on spans, it MAY be recorded as a - // JSON string if structured format is not supported and SHOULD be recorded in - // structured form otherwise. - // - // Since this attribute could be large, it's NOT RECOMMENDED to populate - // it by default. Instrumentations MAY provide a way to enable - // populating this attribute. - GenAIToolDefinitionsKey = attribute.Key("gen_ai.tool.definitions") - - // GenAIToolDescriptionKey is the attribute Key conforming to the - // "gen_ai.tool.description" semantic conventions. It represents the tool - // description. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Multiply two numbers" - GenAIToolDescriptionKey = attribute.Key("gen_ai.tool.description") - - // GenAIToolNameKey is the attribute Key conforming to the "gen_ai.tool.name" - // semantic conventions. It represents the name of the tool utilized by the - // agent. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Flights" - GenAIToolNameKey = attribute.Key("gen_ai.tool.name") - - // GenAIToolTypeKey is the attribute Key conforming to the "gen_ai.tool.type" - // semantic conventions. It represents the type of the tool utilized by the - // agent. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "function", "extension", "datastore" - // Note: Extension: A tool executed on the agent-side to directly call external - // APIs, bridging the gap between the agent and real-world systems. - // Agent-side operations involve actions that are performed by the agent on the - // server or within the agent's controlled environment. - // Function: A tool executed on the client-side, where the agent generates - // parameters for a predefined function, and the client executes the logic. - // Client-side operations are actions taken on the user's end or within the - // client application. - // Datastore: A tool used by the agent to access and query structured or - // unstructured external data for retrieval-augmented tasks or knowledge - // updates. - GenAIToolTypeKey = attribute.Key("gen_ai.tool.type") - - // GenAIUsageCacheCreationInputTokensKey is the attribute Key conforming to the - // "gen_ai.usage.cache_creation.input_tokens" semantic conventions. It - // represents the number of input tokens written to a provider-managed cache. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 25 - // Note: The value SHOULD be included in `gen_ai.usage.input_tokens`. - GenAIUsageCacheCreationInputTokensKey = attribute.Key("gen_ai.usage.cache_creation.input_tokens") - - // GenAIUsageCacheReadInputTokensKey is the attribute Key conforming to the - // "gen_ai.usage.cache_read.input_tokens" semantic conventions. It represents - // the number of input tokens served from a provider-managed cache. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 50 - // Note: The value SHOULD be included in `gen_ai.usage.input_tokens`. - GenAIUsageCacheReadInputTokensKey = attribute.Key("gen_ai.usage.cache_read.input_tokens") - - // GenAIUsageInputTokensKey is the attribute Key conforming to the - // "gen_ai.usage.input_tokens" semantic conventions. It represents the number of - // tokens used in the GenAI input (prompt). - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 100 - // Note: This value SHOULD include all types of input tokens, including cached - // tokens. - // Instrumentations SHOULD make a best effort to populate this value, using a - // total - // provided by the provider when available or, depending on the provider API, - // by summing different token types parsed from the provider output. - GenAIUsageInputTokensKey = attribute.Key("gen_ai.usage.input_tokens") - - // GenAIUsageOutputTokensKey is the attribute Key conforming to the - // "gen_ai.usage.output_tokens" semantic conventions. It represents the number - // of tokens used in the GenAI response (completion). - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 180 - GenAIUsageOutputTokensKey = attribute.Key("gen_ai.usage.output_tokens") -) - -// GenAIAgentDescription returns an attribute KeyValue conforming to the -// "gen_ai.agent.description" semantic conventions. It represents the free-form -// description of the GenAI agent provided by the application. -func GenAIAgentDescription(val string) attribute.KeyValue { - return GenAIAgentDescriptionKey.String(val) -} - -// GenAIAgentID returns an attribute KeyValue conforming to the "gen_ai.agent.id" -// semantic conventions. It represents the unique identifier of the GenAI agent. -func GenAIAgentID(val string) attribute.KeyValue { - return GenAIAgentIDKey.String(val) -} - -// GenAIAgentName returns an attribute KeyValue conforming to the -// "gen_ai.agent.name" semantic conventions. It represents the human-readable -// name of the GenAI agent provided by the application. -func GenAIAgentName(val string) attribute.KeyValue { - return GenAIAgentNameKey.String(val) -} - -// GenAIAgentVersion returns an attribute KeyValue conforming to the -// "gen_ai.agent.version" semantic conventions. It represents the version of the -// GenAI agent. -func GenAIAgentVersion(val string) attribute.KeyValue { - return GenAIAgentVersionKey.String(val) -} - -// GenAIConversationID returns an attribute KeyValue conforming to the -// "gen_ai.conversation.id" semantic conventions. It represents the unique -// identifier for a conversation (session, thread), used to store and correlate -// messages within this conversation. -func GenAIConversationID(val string) attribute.KeyValue { - return GenAIConversationIDKey.String(val) -} - -// GenAIDataSourceID returns an attribute KeyValue conforming to the -// "gen_ai.data_source.id" semantic conventions. It represents the data source -// identifier. -func GenAIDataSourceID(val string) attribute.KeyValue { - return GenAIDataSourceIDKey.String(val) -} - -// GenAIEmbeddingsDimensionCount returns an attribute KeyValue conforming to the -// "gen_ai.embeddings.dimension.count" semantic conventions. It represents the -// number of dimensions the resulting output embeddings should have. -func GenAIEmbeddingsDimensionCount(val int) attribute.KeyValue { - return GenAIEmbeddingsDimensionCountKey.Int(val) -} - -// GenAIEvaluationExplanation returns an attribute KeyValue conforming to the -// "gen_ai.evaluation.explanation" semantic conventions. It represents a -// free-form explanation for the assigned score provided by the evaluator. -func GenAIEvaluationExplanation(val string) attribute.KeyValue { - return GenAIEvaluationExplanationKey.String(val) -} - -// GenAIEvaluationName returns an attribute KeyValue conforming to the -// "gen_ai.evaluation.name" semantic conventions. It represents the name of the -// evaluation metric used for the GenAI response. -func GenAIEvaluationName(val string) attribute.KeyValue { - return GenAIEvaluationNameKey.String(val) -} - -// GenAIEvaluationScoreLabel returns an attribute KeyValue conforming to the -// "gen_ai.evaluation.score.label" semantic conventions. It represents the human -// readable label for evaluation. -func GenAIEvaluationScoreLabel(val string) attribute.KeyValue { - return GenAIEvaluationScoreLabelKey.String(val) -} - -// GenAIEvaluationScoreValue returns an attribute KeyValue conforming to the -// "gen_ai.evaluation.score.value" semantic conventions. It represents the -// evaluation score returned by the evaluator. -func GenAIEvaluationScoreValue(val float64) attribute.KeyValue { - return GenAIEvaluationScoreValueKey.Float64(val) -} - -// GenAIPromptName returns an attribute KeyValue conforming to the -// "gen_ai.prompt.name" semantic conventions. It represents the name of the -// prompt that uniquely identifies it. -func GenAIPromptName(val string) attribute.KeyValue { - return GenAIPromptNameKey.String(val) -} - -// GenAIRequestChoiceCount returns an attribute KeyValue conforming to the -// "gen_ai.request.choice.count" semantic conventions. It represents the target -// number of candidate completions to return. -func GenAIRequestChoiceCount(val int) attribute.KeyValue { - return GenAIRequestChoiceCountKey.Int(val) -} - -// GenAIRequestEncodingFormats returns an attribute KeyValue conforming to the -// "gen_ai.request.encoding_formats" semantic conventions. It represents the -// encoding formats requested in an embeddings operation, if specified. -func GenAIRequestEncodingFormats(val ...string) attribute.KeyValue { - return GenAIRequestEncodingFormatsKey.StringSlice(val) -} - -// GenAIRequestFrequencyPenalty returns an attribute KeyValue conforming to the -// "gen_ai.request.frequency_penalty" semantic conventions. It represents the -// frequency penalty setting for the GenAI request. -func GenAIRequestFrequencyPenalty(val float64) attribute.KeyValue { - return GenAIRequestFrequencyPenaltyKey.Float64(val) -} - -// GenAIRequestMaxTokens returns an attribute KeyValue conforming to the -// "gen_ai.request.max_tokens" semantic conventions. It represents the maximum -// number of tokens the model generates for a request. -func GenAIRequestMaxTokens(val int) attribute.KeyValue { - return GenAIRequestMaxTokensKey.Int(val) -} - -// GenAIRequestModel returns an attribute KeyValue conforming to the -// "gen_ai.request.model" semantic conventions. It represents the name of the -// GenAI model a request is being made to. -func GenAIRequestModel(val string) attribute.KeyValue { - return GenAIRequestModelKey.String(val) -} - -// GenAIRequestPresencePenalty returns an attribute KeyValue conforming to the -// "gen_ai.request.presence_penalty" semantic conventions. It represents the -// presence penalty setting for the GenAI request. -func GenAIRequestPresencePenalty(val float64) attribute.KeyValue { - return GenAIRequestPresencePenaltyKey.Float64(val) -} - -// GenAIRequestSeed returns an attribute KeyValue conforming to the -// "gen_ai.request.seed" semantic conventions. It represents the requests with -// same seed value more likely to return same result. -func GenAIRequestSeed(val int) attribute.KeyValue { - return GenAIRequestSeedKey.Int(val) -} - -// GenAIRequestStopSequences returns an attribute KeyValue conforming to the -// "gen_ai.request.stop_sequences" semantic conventions. It represents the list -// of sequences that the model will use to stop generating further tokens. -func GenAIRequestStopSequences(val ...string) attribute.KeyValue { - return GenAIRequestStopSequencesKey.StringSlice(val) -} - -// GenAIRequestTemperature returns an attribute KeyValue conforming to the -// "gen_ai.request.temperature" semantic conventions. It represents the -// temperature setting for the GenAI request. -func GenAIRequestTemperature(val float64) attribute.KeyValue { - return GenAIRequestTemperatureKey.Float64(val) -} - -// GenAIRequestTopK returns an attribute KeyValue conforming to the -// "gen_ai.request.top_k" semantic conventions. It represents the top_k sampling -// setting for the GenAI request. -func GenAIRequestTopK(val float64) attribute.KeyValue { - return GenAIRequestTopKKey.Float64(val) -} - -// GenAIRequestTopP returns an attribute KeyValue conforming to the -// "gen_ai.request.top_p" semantic conventions. It represents the top_p sampling -// setting for the GenAI request. -func GenAIRequestTopP(val float64) attribute.KeyValue { - return GenAIRequestTopPKey.Float64(val) -} - -// GenAIResponseFinishReasons returns an attribute KeyValue conforming to the -// "gen_ai.response.finish_reasons" semantic conventions. It represents the array -// of reasons the model stopped generating tokens, corresponding to each -// generation received. -func GenAIResponseFinishReasons(val ...string) attribute.KeyValue { - return GenAIResponseFinishReasonsKey.StringSlice(val) -} - -// GenAIResponseID returns an attribute KeyValue conforming to the -// "gen_ai.response.id" semantic conventions. It represents the unique identifier -// for the completion. -func GenAIResponseID(val string) attribute.KeyValue { - return GenAIResponseIDKey.String(val) -} - -// GenAIResponseModel returns an attribute KeyValue conforming to the -// "gen_ai.response.model" semantic conventions. It represents the name of the -// model that generated the response. -func GenAIResponseModel(val string) attribute.KeyValue { - return GenAIResponseModelKey.String(val) -} - -// GenAIRetrievalQueryText returns an attribute KeyValue conforming to the -// "gen_ai.retrieval.query.text" semantic conventions. It represents the query -// text used for retrieval. -func GenAIRetrievalQueryText(val string) attribute.KeyValue { - return GenAIRetrievalQueryTextKey.String(val) -} - -// GenAIToolCallID returns an attribute KeyValue conforming to the -// "gen_ai.tool.call.id" semantic conventions. It represents the tool call -// identifier. -func GenAIToolCallID(val string) attribute.KeyValue { - return GenAIToolCallIDKey.String(val) -} - -// GenAIToolDescription returns an attribute KeyValue conforming to the -// "gen_ai.tool.description" semantic conventions. It represents the tool -// description. -func GenAIToolDescription(val string) attribute.KeyValue { - return GenAIToolDescriptionKey.String(val) -} - -// GenAIToolName returns an attribute KeyValue conforming to the -// "gen_ai.tool.name" semantic conventions. It represents the name of the tool -// utilized by the agent. -func GenAIToolName(val string) attribute.KeyValue { - return GenAIToolNameKey.String(val) -} - -// GenAIToolType returns an attribute KeyValue conforming to the -// "gen_ai.tool.type" semantic conventions. It represents the type of the tool -// utilized by the agent. -func GenAIToolType(val string) attribute.KeyValue { - return GenAIToolTypeKey.String(val) -} - -// GenAIUsageCacheCreationInputTokens returns an attribute KeyValue conforming to -// the "gen_ai.usage.cache_creation.input_tokens" semantic conventions. It -// represents the number of input tokens written to a provider-managed cache. -func GenAIUsageCacheCreationInputTokens(val int) attribute.KeyValue { - return GenAIUsageCacheCreationInputTokensKey.Int(val) -} - -// GenAIUsageCacheReadInputTokens returns an attribute KeyValue conforming to the -// "gen_ai.usage.cache_read.input_tokens" semantic conventions. It represents the -// number of input tokens served from a provider-managed cache. -func GenAIUsageCacheReadInputTokens(val int) attribute.KeyValue { - return GenAIUsageCacheReadInputTokensKey.Int(val) -} - -// GenAIUsageInputTokens returns an attribute KeyValue conforming to the -// "gen_ai.usage.input_tokens" semantic conventions. It represents the number of -// tokens used in the GenAI input (prompt). -func GenAIUsageInputTokens(val int) attribute.KeyValue { - return GenAIUsageInputTokensKey.Int(val) -} - -// GenAIUsageOutputTokens returns an attribute KeyValue conforming to the -// "gen_ai.usage.output_tokens" semantic conventions. It represents the number of -// tokens used in the GenAI response (completion). -func GenAIUsageOutputTokens(val int) attribute.KeyValue { - return GenAIUsageOutputTokensKey.Int(val) -} - -// Enum values for gen_ai.operation.name -var ( - // Chat completion operation such as [OpenAI Chat API] - // Stability: development - // - // [OpenAI Chat API]: https://platform.openai.com/docs/api-reference/chat - GenAIOperationNameChat = GenAIOperationNameKey.String("chat") - // Multimodal content generation operation such as [Gemini Generate Content] - // Stability: development - // - // [Gemini Generate Content]: https://ai.google.dev/api/generate-content - GenAIOperationNameGenerateContent = GenAIOperationNameKey.String("generate_content") - // Text completions operation such as [OpenAI Completions API (Legacy)] - // Stability: development - // - // [OpenAI Completions API (Legacy)]: https://platform.openai.com/docs/api-reference/completions - GenAIOperationNameTextCompletion = GenAIOperationNameKey.String("text_completion") - // Embeddings operation such as [OpenAI Create embeddings API] - // Stability: development - // - // [OpenAI Create embeddings API]: https://platform.openai.com/docs/api-reference/embeddings/create - GenAIOperationNameEmbeddings = GenAIOperationNameKey.String("embeddings") - // Retrieval operation such as [OpenAI Search Vector Store API] - // Stability: development - // - // [OpenAI Search Vector Store API]: https://platform.openai.com/docs/api-reference/vector-stores/search - GenAIOperationNameRetrieval = GenAIOperationNameKey.String("retrieval") - // Create GenAI agent - // Stability: development - GenAIOperationNameCreateAgent = GenAIOperationNameKey.String("create_agent") - // Invoke GenAI agent - // Stability: development - GenAIOperationNameInvokeAgent = GenAIOperationNameKey.String("invoke_agent") - // Execute a tool - // Stability: development - GenAIOperationNameExecuteTool = GenAIOperationNameKey.String("execute_tool") -) - -// Enum values for gen_ai.output.type -var ( - // Plain text - // Stability: development - GenAIOutputTypeText = GenAIOutputTypeKey.String("text") - // JSON object with known or unknown schema - // Stability: development - GenAIOutputTypeJSON = GenAIOutputTypeKey.String("json") - // Image - // Stability: development - GenAIOutputTypeImage = GenAIOutputTypeKey.String("image") - // Speech - // Stability: development - GenAIOutputTypeSpeech = GenAIOutputTypeKey.String("speech") -) - -// Enum values for gen_ai.provider.name -var ( - // [OpenAI] - // Stability: development - // - // [OpenAI]: https://openai.com/ - GenAIProviderNameOpenAI = GenAIProviderNameKey.String("openai") - // Any Google generative AI endpoint - // Stability: development - GenAIProviderNameGCPGenAI = GenAIProviderNameKey.String("gcp.gen_ai") - // [Vertex AI] - // Stability: development - // - // [Vertex AI]: https://cloud.google.com/vertex-ai - GenAIProviderNameGCPVertexAI = GenAIProviderNameKey.String("gcp.vertex_ai") - // [Gemini] - // Stability: development - // - // [Gemini]: https://cloud.google.com/products/gemini - GenAIProviderNameGCPGemini = GenAIProviderNameKey.String("gcp.gemini") - // [Anthropic] - // Stability: development - // - // [Anthropic]: https://www.anthropic.com/ - GenAIProviderNameAnthropic = GenAIProviderNameKey.String("anthropic") - // [Cohere] - // Stability: development - // - // [Cohere]: https://cohere.com/ - GenAIProviderNameCohere = GenAIProviderNameKey.String("cohere") - // Azure AI Inference - // Stability: development - GenAIProviderNameAzureAIInference = GenAIProviderNameKey.String("azure.ai.inference") - // [Azure OpenAI] - // Stability: development - // - // [Azure OpenAI]: https://azure.microsoft.com/products/ai-services/openai-service/ - GenAIProviderNameAzureAIOpenAI = GenAIProviderNameKey.String("azure.ai.openai") - // [IBM Watsonx AI] - // Stability: development - // - // [IBM Watsonx AI]: https://www.ibm.com/products/watsonx-ai - GenAIProviderNameIBMWatsonxAI = GenAIProviderNameKey.String("ibm.watsonx.ai") - // [AWS Bedrock] - // Stability: development - // - // [AWS Bedrock]: https://aws.amazon.com/bedrock - GenAIProviderNameAWSBedrock = GenAIProviderNameKey.String("aws.bedrock") - // [Perplexity] - // Stability: development - // - // [Perplexity]: https://www.perplexity.ai/ - GenAIProviderNamePerplexity = GenAIProviderNameKey.String("perplexity") - // [xAI] - // Stability: development - // - // [xAI]: https://x.ai/ - GenAIProviderNameXAI = GenAIProviderNameKey.String("x_ai") - // [DeepSeek] - // Stability: development - // - // [DeepSeek]: https://www.deepseek.com/ - GenAIProviderNameDeepseek = GenAIProviderNameKey.String("deepseek") - // [Groq] - // Stability: development - // - // [Groq]: https://groq.com/ - GenAIProviderNameGroq = GenAIProviderNameKey.String("groq") - // [Mistral AI] - // Stability: development - // - // [Mistral AI]: https://mistral.ai/ - GenAIProviderNameMistralAI = GenAIProviderNameKey.String("mistral_ai") -) - -// Enum values for gen_ai.token.type -var ( - // Input tokens (prompt, input, etc.) - // Stability: development - GenAITokenTypeInput = GenAITokenTypeKey.String("input") - // Output tokens (completion, response, etc.) - // Stability: development - GenAITokenTypeOutput = GenAITokenTypeKey.String("output") -) - -// Namespace: geo -const ( - // GeoContinentCodeKey is the attribute Key conforming to the - // "geo.continent.code" semantic conventions. It represents the two-letter code - // representing continent’s name. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - GeoContinentCodeKey = attribute.Key("geo.continent.code") - - // GeoCountryISOCodeKey is the attribute Key conforming to the - // "geo.country.iso_code" semantic conventions. It represents the two-letter ISO - // Country Code ([ISO 3166-1 alpha2]). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "CA" - // - // [ISO 3166-1 alpha2]: https://wikipedia.org/wiki/ISO_3166-1#Codes - GeoCountryISOCodeKey = attribute.Key("geo.country.iso_code") - - // GeoLocalityNameKey is the attribute Key conforming to the "geo.locality.name" - // semantic conventions. It represents the locality name. Represents the name of - // a city, town, village, or similar populated place. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Montreal", "Berlin" - GeoLocalityNameKey = attribute.Key("geo.locality.name") - - // GeoLocationLatKey is the attribute Key conforming to the "geo.location.lat" - // semantic conventions. It represents the latitude of the geo location in - // [WGS84]. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 45.505918 - // - // [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84 - GeoLocationLatKey = attribute.Key("geo.location.lat") - - // GeoLocationLonKey is the attribute Key conforming to the "geo.location.lon" - // semantic conventions. It represents the longitude of the geo location in - // [WGS84]. - // - // Type: double - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: -73.61483 - // - // [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84 - GeoLocationLonKey = attribute.Key("geo.location.lon") - - // GeoPostalCodeKey is the attribute Key conforming to the "geo.postal_code" - // semantic conventions. It represents the postal code associated with the - // location. Values appropriate for this field may also be known as a postcode - // or ZIP code and will vary widely from country to country. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "94040" - GeoPostalCodeKey = attribute.Key("geo.postal_code") - - // GeoRegionISOCodeKey is the attribute Key conforming to the - // "geo.region.iso_code" semantic conventions. It represents the region ISO code - // ([ISO 3166-2]). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "CA-QC" - // - // [ISO 3166-2]: https://wikipedia.org/wiki/ISO_3166-2 - GeoRegionISOCodeKey = attribute.Key("geo.region.iso_code") -) - -// GeoCountryISOCode returns an attribute KeyValue conforming to the -// "geo.country.iso_code" semantic conventions. It represents the two-letter ISO -// Country Code ([ISO 3166-1 alpha2]). -// -// [ISO 3166-1 alpha2]: https://wikipedia.org/wiki/ISO_3166-1#Codes -func GeoCountryISOCode(val string) attribute.KeyValue { - return GeoCountryISOCodeKey.String(val) -} - -// GeoLocalityName returns an attribute KeyValue conforming to the -// "geo.locality.name" semantic conventions. It represents the locality name. -// Represents the name of a city, town, village, or similar populated place. -func GeoLocalityName(val string) attribute.KeyValue { - return GeoLocalityNameKey.String(val) -} - -// GeoLocationLat returns an attribute KeyValue conforming to the -// "geo.location.lat" semantic conventions. It represents the latitude of the geo -// location in [WGS84]. -// -// [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84 -func GeoLocationLat(val float64) attribute.KeyValue { - return GeoLocationLatKey.Float64(val) -} - -// GeoLocationLon returns an attribute KeyValue conforming to the -// "geo.location.lon" semantic conventions. It represents the longitude of the -// geo location in [WGS84]. -// -// [WGS84]: https://wikipedia.org/wiki/World_Geodetic_System#WGS84 -func GeoLocationLon(val float64) attribute.KeyValue { - return GeoLocationLonKey.Float64(val) -} - -// GeoPostalCode returns an attribute KeyValue conforming to the -// "geo.postal_code" semantic conventions. It represents the postal code -// associated with the location. Values appropriate for this field may also be -// known as a postcode or ZIP code and will vary widely from country to country. -func GeoPostalCode(val string) attribute.KeyValue { - return GeoPostalCodeKey.String(val) -} - -// GeoRegionISOCode returns an attribute KeyValue conforming to the -// "geo.region.iso_code" semantic conventions. It represents the region ISO code -// ([ISO 3166-2]). -// -// [ISO 3166-2]: https://wikipedia.org/wiki/ISO_3166-2 -func GeoRegionISOCode(val string) attribute.KeyValue { - return GeoRegionISOCodeKey.String(val) -} - -// Enum values for geo.continent.code -var ( - // Africa - // Stability: development - GeoContinentCodeAf = GeoContinentCodeKey.String("AF") - // Antarctica - // Stability: development - GeoContinentCodeAn = GeoContinentCodeKey.String("AN") - // Asia - // Stability: development - GeoContinentCodeAs = GeoContinentCodeKey.String("AS") - // Europe - // Stability: development - GeoContinentCodeEu = GeoContinentCodeKey.String("EU") - // North America - // Stability: development - GeoContinentCodeNa = GeoContinentCodeKey.String("NA") - // Oceania - // Stability: development - GeoContinentCodeOc = GeoContinentCodeKey.String("OC") - // South America - // Stability: development - GeoContinentCodeSa = GeoContinentCodeKey.String("SA") -) - -// Namespace: go -const ( - // GoMemoryTypeKey is the attribute Key conforming to the "go.memory.type" - // semantic conventions. It represents the type of memory. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "other", "stack" - GoMemoryTypeKey = attribute.Key("go.memory.type") -) - -// Enum values for go.memory.type -var ( - // Memory allocated from the heap that is reserved for stack space, whether or - // not it is currently in-use. - // Stability: development - GoMemoryTypeStack = GoMemoryTypeKey.String("stack") - // Memory used by the Go runtime, excluding other categories of memory usage - // described in this enumeration. - // Stability: development - GoMemoryTypeOther = GoMemoryTypeKey.String("other") -) - -// Namespace: graphql -const ( - // GraphQLDocumentKey is the attribute Key conforming to the "graphql.document" - // semantic conventions. It represents the GraphQL document being executed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: query findBookById { bookById(id: ?) { name } } - // Note: The value may be sanitized to exclude sensitive information. - GraphQLDocumentKey = attribute.Key("graphql.document") - - // GraphQLOperationNameKey is the attribute Key conforming to the - // "graphql.operation.name" semantic conventions. It represents the name of the - // operation being executed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: findBookById - GraphQLOperationNameKey = attribute.Key("graphql.operation.name") - - // GraphQLOperationTypeKey is the attribute Key conforming to the - // "graphql.operation.type" semantic conventions. It represents the type of the - // operation being executed. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "query", "mutation", "subscription" - GraphQLOperationTypeKey = attribute.Key("graphql.operation.type") -) - -// GraphQLDocument returns an attribute KeyValue conforming to the -// "graphql.document" semantic conventions. It represents the GraphQL document -// being executed. -func GraphQLDocument(val string) attribute.KeyValue { - return GraphQLDocumentKey.String(val) -} - -// GraphQLOperationName returns an attribute KeyValue conforming to the -// "graphql.operation.name" semantic conventions. It represents the name of the -// operation being executed. -func GraphQLOperationName(val string) attribute.KeyValue { - return GraphQLOperationNameKey.String(val) -} - -// Enum values for graphql.operation.type -var ( - // GraphQL query - // Stability: development - GraphQLOperationTypeQuery = GraphQLOperationTypeKey.String("query") - // GraphQL mutation - // Stability: development - GraphQLOperationTypeMutation = GraphQLOperationTypeKey.String("mutation") - // GraphQL subscription - // Stability: development - GraphQLOperationTypeSubscription = GraphQLOperationTypeKey.String("subscription") -) - -// Namespace: heroku -const ( - // HerokuAppIDKey is the attribute Key conforming to the "heroku.app.id" - // semantic conventions. It represents the unique identifier for the - // application. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2daa2797-e42b-4624-9322-ec3f968df4da" - HerokuAppIDKey = attribute.Key("heroku.app.id") - - // HerokuReleaseCommitKey is the attribute Key conforming to the - // "heroku.release.commit" semantic conventions. It represents the commit hash - // for the current release. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "e6134959463efd8966b20e75b913cafe3f5ec" - HerokuReleaseCommitKey = attribute.Key("heroku.release.commit") - - // HerokuReleaseCreationTimestampKey is the attribute Key conforming to the - // "heroku.release.creation_timestamp" semantic conventions. It represents the - // time and date the release was created. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2022-10-23T18:00:42Z" - HerokuReleaseCreationTimestampKey = attribute.Key("heroku.release.creation_timestamp") -) - -// HerokuAppID returns an attribute KeyValue conforming to the "heroku.app.id" -// semantic conventions. It represents the unique identifier for the application. -func HerokuAppID(val string) attribute.KeyValue { - return HerokuAppIDKey.String(val) -} - -// HerokuReleaseCommit returns an attribute KeyValue conforming to the -// "heroku.release.commit" semantic conventions. It represents the commit hash -// for the current release. -func HerokuReleaseCommit(val string) attribute.KeyValue { - return HerokuReleaseCommitKey.String(val) -} - -// HerokuReleaseCreationTimestamp returns an attribute KeyValue conforming to the -// "heroku.release.creation_timestamp" semantic conventions. It represents the -// time and date the release was created. -func HerokuReleaseCreationTimestamp(val string) attribute.KeyValue { - return HerokuReleaseCreationTimestampKey.String(val) -} - -// Namespace: host -const ( - // HostArchKey is the attribute Key conforming to the "host.arch" semantic - // conventions. It represents the CPU architecture the host system is running - // on. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HostArchKey = attribute.Key("host.arch") - - // HostCPUCacheL2SizeKey is the attribute Key conforming to the - // "host.cpu.cache.l2.size" semantic conventions. It represents the amount of - // level 2 memory cache available to the processor (in Bytes). - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 12288000 - HostCPUCacheL2SizeKey = attribute.Key("host.cpu.cache.l2.size") - - // HostCPUFamilyKey is the attribute Key conforming to the "host.cpu.family" - // semantic conventions. It represents the family or generation of the CPU. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "6", "PA-RISC 1.1e" - HostCPUFamilyKey = attribute.Key("host.cpu.family") - - // HostCPUModelIDKey is the attribute Key conforming to the "host.cpu.model.id" - // semantic conventions. It represents the model identifier. It provides more - // granular information about the CPU, distinguishing it from other CPUs within - // the same family. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "6", "9000/778/B180L" - HostCPUModelIDKey = attribute.Key("host.cpu.model.id") - - // HostCPUModelNameKey is the attribute Key conforming to the - // "host.cpu.model.name" semantic conventions. It represents the model - // designation of the processor. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz" - HostCPUModelNameKey = attribute.Key("host.cpu.model.name") - - // HostCPUSteppingKey is the attribute Key conforming to the "host.cpu.stepping" - // semantic conventions. It represents the stepping or core revisions. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1", "r1p1" - HostCPUSteppingKey = attribute.Key("host.cpu.stepping") - - // HostCPUVendorIDKey is the attribute Key conforming to the - // "host.cpu.vendor.id" semantic conventions. It represents the processor - // manufacturer identifier. A maximum 12-character string. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "GenuineIntel" - // Note: [CPUID] command returns the vendor ID string in EBX, EDX and ECX - // registers. Writing these to memory in this order results in a 12-character - // string. - // - // [CPUID]: https://wiki.osdev.org/CPUID - HostCPUVendorIDKey = attribute.Key("host.cpu.vendor.id") - - // HostIDKey is the attribute Key conforming to the "host.id" semantic - // conventions. It represents the unique host ID. For Cloud, this must be the - // instance_id assigned by the cloud provider. For non-containerized systems, - // this should be the `machine-id`. See the table below for the sources to use - // to determine the `machine-id` based on operating system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "fdbf79e8af94cb7f9e8df36789187052" - HostIDKey = attribute.Key("host.id") - - // HostImageIDKey is the attribute Key conforming to the "host.image.id" - // semantic conventions. It represents the VM image ID or host OS image ID. For - // Cloud, this value is from the provider. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ami-07b06b442921831e5" - HostImageIDKey = attribute.Key("host.image.id") - - // HostImageNameKey is the attribute Key conforming to the "host.image.name" - // semantic conventions. It represents the name of the VM image or OS install - // the host was instantiated from. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "infra-ami-eks-worker-node-7d4ec78312", "CentOS-8-x86_64-1905" - HostImageNameKey = attribute.Key("host.image.name") - - // HostImageVersionKey is the attribute Key conforming to the - // "host.image.version" semantic conventions. It represents the version string - // of the VM image or host OS as defined in [Version Attributes]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "0.1" - // - // [Version Attributes]: /docs/resource/README.md#version-attributes - HostImageVersionKey = attribute.Key("host.image.version") - - // HostIPKey is the attribute Key conforming to the "host.ip" semantic - // conventions. It represents the available IP addresses of the host, excluding - // loopback interfaces. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "192.168.1.140", "fe80::abc2:4a28:737a:609e" - // Note: IPv4 Addresses MUST be specified in dotted-quad notation. IPv6 - // addresses MUST be specified in the [RFC 5952] format. - // - // [RFC 5952]: https://www.rfc-editor.org/rfc/rfc5952.html - HostIPKey = attribute.Key("host.ip") - - // HostMacKey is the attribute Key conforming to the "host.mac" semantic - // conventions. It represents the available MAC addresses of the host, excluding - // loopback interfaces. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "AC-DE-48-23-45-67", "AC-DE-48-23-45-67-01-9F" - // Note: MAC Addresses MUST be represented in [IEEE RA hexadecimal form]: as - // hyphen-separated octets in uppercase hexadecimal form from most to least - // significant. - // - // [IEEE RA hexadecimal form]: https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/eui.pdf - HostMacKey = attribute.Key("host.mac") - - // HostNameKey is the attribute Key conforming to the "host.name" semantic - // conventions. It represents the name of the host. On Unix systems, it may - // contain what the hostname command returns, or the fully qualified hostname, - // or another name specified by the user. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "opentelemetry-test" - HostNameKey = attribute.Key("host.name") - - // HostTypeKey is the attribute Key conforming to the "host.type" semantic - // conventions. It represents the type of host. For Cloud, this must be the - // machine type. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "n1-standard-1" - HostTypeKey = attribute.Key("host.type") -) - -// HostCPUCacheL2Size returns an attribute KeyValue conforming to the -// "host.cpu.cache.l2.size" semantic conventions. It represents the amount of -// level 2 memory cache available to the processor (in Bytes). -func HostCPUCacheL2Size(val int) attribute.KeyValue { - return HostCPUCacheL2SizeKey.Int(val) -} - -// HostCPUFamily returns an attribute KeyValue conforming to the -// "host.cpu.family" semantic conventions. It represents the family or generation -// of the CPU. -func HostCPUFamily(val string) attribute.KeyValue { - return HostCPUFamilyKey.String(val) -} - -// HostCPUModelID returns an attribute KeyValue conforming to the -// "host.cpu.model.id" semantic conventions. It represents the model identifier. -// It provides more granular information about the CPU, distinguishing it from -// other CPUs within the same family. -func HostCPUModelID(val string) attribute.KeyValue { - return HostCPUModelIDKey.String(val) -} - -// HostCPUModelName returns an attribute KeyValue conforming to the -// "host.cpu.model.name" semantic conventions. It represents the model -// designation of the processor. -func HostCPUModelName(val string) attribute.KeyValue { - return HostCPUModelNameKey.String(val) -} - -// HostCPUStepping returns an attribute KeyValue conforming to the -// "host.cpu.stepping" semantic conventions. It represents the stepping or core -// revisions. -func HostCPUStepping(val string) attribute.KeyValue { - return HostCPUSteppingKey.String(val) -} - -// HostCPUVendorID returns an attribute KeyValue conforming to the -// "host.cpu.vendor.id" semantic conventions. It represents the processor -// manufacturer identifier. A maximum 12-character string. -func HostCPUVendorID(val string) attribute.KeyValue { - return HostCPUVendorIDKey.String(val) -} - -// HostID returns an attribute KeyValue conforming to the "host.id" semantic -// conventions. It represents the unique host ID. For Cloud, this must be the -// instance_id assigned by the cloud provider. For non-containerized systems, -// this should be the `machine-id`. See the table below for the sources to use to -// determine the `machine-id` based on operating system. -func HostID(val string) attribute.KeyValue { - return HostIDKey.String(val) -} - -// HostImageID returns an attribute KeyValue conforming to the "host.image.id" -// semantic conventions. It represents the VM image ID or host OS image ID. For -// Cloud, this value is from the provider. -func HostImageID(val string) attribute.KeyValue { - return HostImageIDKey.String(val) -} - -// HostImageName returns an attribute KeyValue conforming to the -// "host.image.name" semantic conventions. It represents the name of the VM image -// or OS install the host was instantiated from. -func HostImageName(val string) attribute.KeyValue { - return HostImageNameKey.String(val) -} - -// HostImageVersion returns an attribute KeyValue conforming to the -// "host.image.version" semantic conventions. It represents the version string of -// the VM image or host OS as defined in [Version Attributes]. -// -// [Version Attributes]: /docs/resource/README.md#version-attributes -func HostImageVersion(val string) attribute.KeyValue { - return HostImageVersionKey.String(val) -} - -// HostIP returns an attribute KeyValue conforming to the "host.ip" semantic -// conventions. It represents the available IP addresses of the host, excluding -// loopback interfaces. -func HostIP(val ...string) attribute.KeyValue { - return HostIPKey.StringSlice(val) -} - -// HostMac returns an attribute KeyValue conforming to the "host.mac" semantic -// conventions. It represents the available MAC addresses of the host, excluding -// loopback interfaces. -func HostMac(val ...string) attribute.KeyValue { - return HostMacKey.StringSlice(val) -} - -// HostName returns an attribute KeyValue conforming to the "host.name" semantic -// conventions. It represents the name of the host. On Unix systems, it may -// contain what the hostname command returns, or the fully qualified hostname, or -// another name specified by the user. -func HostName(val string) attribute.KeyValue { - return HostNameKey.String(val) -} - -// HostType returns an attribute KeyValue conforming to the "host.type" semantic -// conventions. It represents the type of host. For Cloud, this must be the -// machine type. -func HostType(val string) attribute.KeyValue { - return HostTypeKey.String(val) -} - -// Enum values for host.arch -var ( - // AMD64 - // Stability: development - HostArchAMD64 = HostArchKey.String("amd64") - // ARM32 - // Stability: development - HostArchARM32 = HostArchKey.String("arm32") - // ARM64 - // Stability: development - HostArchARM64 = HostArchKey.String("arm64") - // Itanium - // Stability: development - HostArchIA64 = HostArchKey.String("ia64") - // 32-bit PowerPC - // Stability: development - HostArchPPC32 = HostArchKey.String("ppc32") - // 64-bit PowerPC - // Stability: development - HostArchPPC64 = HostArchKey.String("ppc64") - // IBM z/Architecture - // Stability: development - HostArchS390x = HostArchKey.String("s390x") - // 32-bit x86 - // Stability: development - HostArchX86 = HostArchKey.String("x86") -) - -// Namespace: http -const ( - // HTTPConnectionStateKey is the attribute Key conforming to the - // "http.connection.state" semantic conventions. It represents the state of the - // HTTP connection in the HTTP connection pool. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "active", "idle" - HTTPConnectionStateKey = attribute.Key("http.connection.state") - - // HTTPRequestBodySizeKey is the attribute Key conforming to the - // "http.request.body.size" semantic conventions. It represents the size of the - // request payload body in bytes. This is the number of bytes transferred - // excluding headers and is often, but not always, present as the - // [Content-Length] header. For requests using transport encoding, this should - // be the compressed size. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length - HTTPRequestBodySizeKey = attribute.Key("http.request.body.size") - - // HTTPRequestMethodKey is the attribute Key conforming to the - // "http.request.method" semantic conventions. It represents the HTTP request - // method. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "GET", "POST", "HEAD" - // Note: HTTP request method value SHOULD be "known" to the instrumentation. - // By default, this convention defines "known" methods as the ones listed in - // [RFC9110], - // the PATCH method defined in [RFC5789] - // and the QUERY method defined in [httpbis-safe-method-w-body]. - // - // If the HTTP request method is not known to instrumentation, it MUST set the - // `http.request.method` attribute to `_OTHER`. - // - // If the HTTP instrumentation could end up converting valid HTTP request - // methods to `_OTHER`, then it MUST provide a way to override - // the list of known HTTP methods. If this override is done via environment - // variable, then the environment variable MUST be named - // OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of - // case-sensitive known HTTP methods. - // - // - // If this override is done via declarative configuration, then the list MUST be - // configurable via the `known_methods` property - // (an array of case-sensitive strings with minimum items 0) under - // `.instrumentation/development.general.http.client` and/or - // `.instrumentation/development.general.http.server`. - // - // In either case, this list MUST be a full override of the default known - // methods, - // it is not a list of known methods in addition to the defaults. - // - // HTTP method names are case-sensitive and `http.request.method` attribute - // value MUST match a known HTTP method name exactly. - // Instrumentations for specific web frameworks that consider HTTP methods to be - // case insensitive, SHOULD populate a canonical equivalent. - // Tracing instrumentations that do so, MUST also set - // `http.request.method_original` to the original value. - // - // [RFC9110]: https://www.rfc-editor.org/rfc/rfc9110.html#name-methods - // [RFC5789]: https://www.rfc-editor.org/rfc/rfc5789.html - // [httpbis-safe-method-w-body]: https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/?include_text=1 - HTTPRequestMethodKey = attribute.Key("http.request.method") - - // HTTPRequestMethodOriginalKey is the attribute Key conforming to the - // "http.request.method_original" semantic conventions. It represents the - // original HTTP method sent by the client in the request line. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "GeT", "ACL", "foo" - HTTPRequestMethodOriginalKey = attribute.Key("http.request.method_original") - - // HTTPRequestResendCountKey is the attribute Key conforming to the - // "http.request.resend_count" semantic conventions. It represents the ordinal - // number of request resending attempt (for any reason, including redirects). - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - // - // Note: The resend count SHOULD be updated each time an HTTP request gets - // resent by the client, regardless of what was the cause of the resending (e.g. - // redirection, authorization failure, 503 Server Unavailable, network issues, - // or any other). - HTTPRequestResendCountKey = attribute.Key("http.request.resend_count") - - // HTTPRequestSizeKey is the attribute Key conforming to the "http.request.size" - // semantic conventions. It represents the total size of the request in bytes. - // This should be the total number of bytes sent over the wire, including the - // request line (HTTP/1.1), framing (HTTP/2 and HTTP/3), headers, and request - // body if any. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - HTTPRequestSizeKey = attribute.Key("http.request.size") - - // HTTPResponseBodySizeKey is the attribute Key conforming to the - // "http.response.body.size" semantic conventions. It represents the size of the - // response payload body in bytes. This is the number of bytes transferred - // excluding headers and is often, but not always, present as the - // [Content-Length] header. For requests using transport encoding, this should - // be the compressed size. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length - HTTPResponseBodySizeKey = attribute.Key("http.response.body.size") - - // HTTPResponseSizeKey is the attribute Key conforming to the - // "http.response.size" semantic conventions. It represents the total size of - // the response in bytes. This should be the total number of bytes sent over the - // wire, including the status line (HTTP/1.1), framing (HTTP/2 and HTTP/3), - // headers, and response body and trailers if any. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - HTTPResponseSizeKey = attribute.Key("http.response.size") - - // HTTPResponseStatusCodeKey is the attribute Key conforming to the - // "http.response.status_code" semantic conventions. It represents the - // [HTTP response status code]. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: 200 - // - // [HTTP response status code]: https://tools.ietf.org/html/rfc7231#section-6 - HTTPResponseStatusCodeKey = attribute.Key("http.response.status_code") - - // HTTPRouteKey is the attribute Key conforming to the "http.route" semantic - // conventions. It represents the matched route template for the request. This - // MUST be low-cardinality and include all static path segments, with dynamic - // path segments represented with placeholders. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "/users/:userID?", "my-controller/my-action/{id?}" - // Note: MUST NOT be populated when this is not supported by the HTTP server - // framework as the route attribute should have low-cardinality and the URI path - // can NOT substitute it. - // SHOULD include the [application root] if there is one. - // - // A static path segment is a part of the route template with a fixed, - // low-cardinality value. This includes literal strings like `/users/` and - // placeholders that - // are constrained to a finite, predefined set of values, e.g. `{controller}` or - // `{action}`. - // - // A dynamic path segment is a placeholder for a value that can have high - // cardinality and is not constrained to a predefined list like static path - // segments. - // - // Instrumentations SHOULD use routing information provided by the corresponding - // web framework. They SHOULD pick the most precise source of routing - // information and MAY - // support custom route formatting. Instrumentations SHOULD document the format - // and the API used to obtain the route string. - // - // [application root]: /docs/http/http-spans.md#http-server-definitions - HTTPRouteKey = attribute.Key("http.route") -) - -// HTTPRequestBodySize returns an attribute KeyValue conforming to the -// "http.request.body.size" semantic conventions. It represents the size of the -// request payload body in bytes. This is the number of bytes transferred -// excluding headers and is often, but not always, present as the -// [Content-Length] header. For requests using transport encoding, this should be -// the compressed size. -// -// [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length -func HTTPRequestBodySize(val int) attribute.KeyValue { - return HTTPRequestBodySizeKey.Int(val) -} - -// HTTPRequestHeader returns an attribute KeyValue conforming to the -// "http.request.header" semantic conventions. It represents the HTTP request -// headers, `` being the normalized HTTP Header name (lowercase), the value -// being the header values. -func HTTPRequestHeader(key string, val ...string) attribute.KeyValue { - return attribute.StringSlice("http.request.header."+key, val) -} - -// HTTPRequestMethodOriginal returns an attribute KeyValue conforming to the -// "http.request.method_original" semantic conventions. It represents the -// original HTTP method sent by the client in the request line. -func HTTPRequestMethodOriginal(val string) attribute.KeyValue { - return HTTPRequestMethodOriginalKey.String(val) -} - -// HTTPRequestResendCount returns an attribute KeyValue conforming to the -// "http.request.resend_count" semantic conventions. It represents the ordinal -// number of request resending attempt (for any reason, including redirects). -func HTTPRequestResendCount(val int) attribute.KeyValue { - return HTTPRequestResendCountKey.Int(val) -} - -// HTTPRequestSize returns an attribute KeyValue conforming to the -// "http.request.size" semantic conventions. It represents the total size of the -// request in bytes. This should be the total number of bytes sent over the wire, -// including the request line (HTTP/1.1), framing (HTTP/2 and HTTP/3), headers, -// and request body if any. -func HTTPRequestSize(val int) attribute.KeyValue { - return HTTPRequestSizeKey.Int(val) -} - -// HTTPResponseBodySize returns an attribute KeyValue conforming to the -// "http.response.body.size" semantic conventions. It represents the size of the -// response payload body in bytes. This is the number of bytes transferred -// excluding headers and is often, but not always, present as the -// [Content-Length] header. For requests using transport encoding, this should be -// the compressed size. -// -// [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length -func HTTPResponseBodySize(val int) attribute.KeyValue { - return HTTPResponseBodySizeKey.Int(val) -} - -// HTTPResponseHeader returns an attribute KeyValue conforming to the -// "http.response.header" semantic conventions. It represents the HTTP response -// headers, `` being the normalized HTTP Header name (lowercase), the value -// being the header values. -func HTTPResponseHeader(key string, val ...string) attribute.KeyValue { - return attribute.StringSlice("http.response.header."+key, val) -} - -// HTTPResponseSize returns an attribute KeyValue conforming to the -// "http.response.size" semantic conventions. It represents the total size of the -// response in bytes. This should be the total number of bytes sent over the -// wire, including the status line (HTTP/1.1), framing (HTTP/2 and HTTP/3), -// headers, and response body and trailers if any. -func HTTPResponseSize(val int) attribute.KeyValue { - return HTTPResponseSizeKey.Int(val) -} - -// HTTPResponseStatusCode returns an attribute KeyValue conforming to the -// "http.response.status_code" semantic conventions. It represents the -// [HTTP response status code]. -// -// [HTTP response status code]: https://tools.ietf.org/html/rfc7231#section-6 -func HTTPResponseStatusCode(val int) attribute.KeyValue { - return HTTPResponseStatusCodeKey.Int(val) -} - -// HTTPRoute returns an attribute KeyValue conforming to the "http.route" -// semantic conventions. It represents the matched route template for the -// request. This MUST be low-cardinality and include all static path segments, -// with dynamic path segments represented with placeholders. -func HTTPRoute(val string) attribute.KeyValue { - return HTTPRouteKey.String(val) -} - -// Enum values for http.connection.state -var ( - // active state. - // Stability: development - HTTPConnectionStateActive = HTTPConnectionStateKey.String("active") - // idle state. - // Stability: development - HTTPConnectionStateIdle = HTTPConnectionStateKey.String("idle") -) - -// Enum values for http.request.method -var ( - // CONNECT method. - // Stability: stable - HTTPRequestMethodConnect = HTTPRequestMethodKey.String("CONNECT") - // DELETE method. - // Stability: stable - HTTPRequestMethodDelete = HTTPRequestMethodKey.String("DELETE") - // GET method. - // Stability: stable - HTTPRequestMethodGet = HTTPRequestMethodKey.String("GET") - // HEAD method. - // Stability: stable - HTTPRequestMethodHead = HTTPRequestMethodKey.String("HEAD") - // OPTIONS method. - // Stability: stable - HTTPRequestMethodOptions = HTTPRequestMethodKey.String("OPTIONS") - // PATCH method. - // Stability: stable - HTTPRequestMethodPatch = HTTPRequestMethodKey.String("PATCH") - // POST method. - // Stability: stable - HTTPRequestMethodPost = HTTPRequestMethodKey.String("POST") - // PUT method. - // Stability: stable - HTTPRequestMethodPut = HTTPRequestMethodKey.String("PUT") - // TRACE method. - // Stability: stable - HTTPRequestMethodTrace = HTTPRequestMethodKey.String("TRACE") - // QUERY method. - // Stability: development - HTTPRequestMethodQuery = HTTPRequestMethodKey.String("QUERY") - // Any HTTP method that the instrumentation has no prior knowledge of. - // Stability: stable - HTTPRequestMethodOther = HTTPRequestMethodKey.String("_OTHER") -) - -// Namespace: hw -const ( - // HwBatteryCapacityKey is the attribute Key conforming to the - // "hw.battery.capacity" semantic conventions. It represents the design capacity - // in Watts-hours or Amper-hours. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "9.3Ah", "50Wh" - HwBatteryCapacityKey = attribute.Key("hw.battery.capacity") - - // HwBatteryChemistryKey is the attribute Key conforming to the - // "hw.battery.chemistry" semantic conventions. It represents the battery - // [chemistry], e.g. Lithium-Ion, Nickel-Cadmium, etc. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Li-ion", "NiMH" - // - // [chemistry]: https://schemas.dmtf.org/wbem/cim-html/2.31.0/CIM_Battery.html - HwBatteryChemistryKey = attribute.Key("hw.battery.chemistry") - - // HwBatteryStateKey is the attribute Key conforming to the "hw.battery.state" - // semantic conventions. It represents the current state of the battery. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HwBatteryStateKey = attribute.Key("hw.battery.state") - - // HwBiosVersionKey is the attribute Key conforming to the "hw.bios_version" - // semantic conventions. It represents the BIOS version of the hardware - // component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1.2.3" - HwBiosVersionKey = attribute.Key("hw.bios_version") - - // HwDriverVersionKey is the attribute Key conforming to the "hw.driver_version" - // semantic conventions. It represents the driver version for the hardware - // component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "10.2.1-3" - HwDriverVersionKey = attribute.Key("hw.driver_version") - - // HwEnclosureTypeKey is the attribute Key conforming to the "hw.enclosure.type" - // semantic conventions. It represents the type of the enclosure (useful for - // modular systems). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Computer", "Storage", "Switch" - HwEnclosureTypeKey = attribute.Key("hw.enclosure.type") - - // HwFirmwareVersionKey is the attribute Key conforming to the - // "hw.firmware_version" semantic conventions. It represents the firmware - // version of the hardware component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2.0.1" - HwFirmwareVersionKey = attribute.Key("hw.firmware_version") - - // HwGpuTaskKey is the attribute Key conforming to the "hw.gpu.task" semantic - // conventions. It represents the type of task the GPU is performing. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HwGpuTaskKey = attribute.Key("hw.gpu.task") - - // HwIDKey is the attribute Key conforming to the "hw.id" semantic conventions. - // It represents an identifier for the hardware component, unique within the - // monitored host. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "win32battery_battery_testsysa33_1" - HwIDKey = attribute.Key("hw.id") - - // HwLimitTypeKey is the attribute Key conforming to the "hw.limit_type" - // semantic conventions. It represents the type of limit for hardware - // components. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HwLimitTypeKey = attribute.Key("hw.limit_type") - - // HwLogicalDiskRaidLevelKey is the attribute Key conforming to the - // "hw.logical_disk.raid_level" semantic conventions. It represents the RAID - // Level of the logical disk. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "RAID0+1", "RAID5", "RAID10" - HwLogicalDiskRaidLevelKey = attribute.Key("hw.logical_disk.raid_level") - - // HwLogicalDiskStateKey is the attribute Key conforming to the - // "hw.logical_disk.state" semantic conventions. It represents the state of the - // logical disk space usage. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HwLogicalDiskStateKey = attribute.Key("hw.logical_disk.state") - - // HwMemoryTypeKey is the attribute Key conforming to the "hw.memory.type" - // semantic conventions. It represents the type of the memory module. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "DDR4", "DDR5", "LPDDR5" - HwMemoryTypeKey = attribute.Key("hw.memory.type") - - // HwModelKey is the attribute Key conforming to the "hw.model" semantic - // conventions. It represents the descriptive model name of the hardware - // component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "PERC H740P", "Intel(R) Core(TM) i7-10700K", "Dell XPS 15 Battery" - HwModelKey = attribute.Key("hw.model") - - // HwNameKey is the attribute Key conforming to the "hw.name" semantic - // conventions. It represents an easily-recognizable name for the hardware - // component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "eth0" - HwNameKey = attribute.Key("hw.name") - - // HwNetworkLogicalAddressesKey is the attribute Key conforming to the - // "hw.network.logical_addresses" semantic conventions. It represents the - // logical addresses of the adapter (e.g. IP address, or WWPN). - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "172.16.8.21", "57.11.193.42" - HwNetworkLogicalAddressesKey = attribute.Key("hw.network.logical_addresses") - - // HwNetworkPhysicalAddressKey is the attribute Key conforming to the - // "hw.network.physical_address" semantic conventions. It represents the - // physical address of the adapter (e.g. MAC address, or WWNN). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "00-90-F5-E9-7B-36" - HwNetworkPhysicalAddressKey = attribute.Key("hw.network.physical_address") - - // HwParentKey is the attribute Key conforming to the "hw.parent" semantic - // conventions. It represents the unique identifier of the parent component - // (typically the `hw.id` attribute of the enclosure, or disk controller). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "dellStorage_perc_0" - HwParentKey = attribute.Key("hw.parent") - - // HwPhysicalDiskSmartAttributeKey is the attribute Key conforming to the - // "hw.physical_disk.smart_attribute" semantic conventions. It represents the - // [S.M.A.R.T.] (Self-Monitoring, Analysis, and Reporting Technology) attribute - // of the physical disk. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Spin Retry Count", "Seek Error Rate", "Raw Read Error Rate" - // - // [S.M.A.R.T.]: https://wikipedia.org/wiki/S.M.A.R.T. - HwPhysicalDiskSmartAttributeKey = attribute.Key("hw.physical_disk.smart_attribute") - - // HwPhysicalDiskStateKey is the attribute Key conforming to the - // "hw.physical_disk.state" semantic conventions. It represents the state of the - // physical disk endurance utilization. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HwPhysicalDiskStateKey = attribute.Key("hw.physical_disk.state") - - // HwPhysicalDiskTypeKey is the attribute Key conforming to the - // "hw.physical_disk.type" semantic conventions. It represents the type of the - // physical disk. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "HDD", "SSD", "10K" - HwPhysicalDiskTypeKey = attribute.Key("hw.physical_disk.type") - - // HwSensorLocationKey is the attribute Key conforming to the - // "hw.sensor_location" semantic conventions. It represents the location of the - // sensor. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "cpu0", "ps1", "INLET", "CPU0_DIE", "AMBIENT", "MOTHERBOARD", "PS0 - // V3_3", "MAIN_12V", "CPU_VCORE" - HwSensorLocationKey = attribute.Key("hw.sensor_location") - - // HwSerialNumberKey is the attribute Key conforming to the "hw.serial_number" - // semantic conventions. It represents the serial number of the hardware - // component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "CNFCP0123456789" - HwSerialNumberKey = attribute.Key("hw.serial_number") - - // HwStateKey is the attribute Key conforming to the "hw.state" semantic - // conventions. It represents the current state of the component. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HwStateKey = attribute.Key("hw.state") - - // HwTapeDriveOperationTypeKey is the attribute Key conforming to the - // "hw.tape_drive.operation_type" semantic conventions. It represents the type - // of tape drive operation. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - HwTapeDriveOperationTypeKey = attribute.Key("hw.tape_drive.operation_type") - - // HwTypeKey is the attribute Key conforming to the "hw.type" semantic - // conventions. It represents the type of the component. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: Describes the category of the hardware component for which `hw.state` - // is being reported. For example, `hw.type=temperature` along with - // `hw.state=degraded` would indicate that the temperature of the hardware - // component has been reported as `degraded`. - HwTypeKey = attribute.Key("hw.type") - - // HwVendorKey is the attribute Key conforming to the "hw.vendor" semantic - // conventions. It represents the vendor name of the hardware component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Dell", "HP", "Intel", "AMD", "LSI", "Lenovo" - HwVendorKey = attribute.Key("hw.vendor") -) - -// HwBatteryCapacity returns an attribute KeyValue conforming to the -// "hw.battery.capacity" semantic conventions. It represents the design capacity -// in Watts-hours or Amper-hours. -func HwBatteryCapacity(val string) attribute.KeyValue { - return HwBatteryCapacityKey.String(val) -} - -// HwBatteryChemistry returns an attribute KeyValue conforming to the -// "hw.battery.chemistry" semantic conventions. It represents the battery -// [chemistry], e.g. Lithium-Ion, Nickel-Cadmium, etc. -// -// [chemistry]: https://schemas.dmtf.org/wbem/cim-html/2.31.0/CIM_Battery.html -func HwBatteryChemistry(val string) attribute.KeyValue { - return HwBatteryChemistryKey.String(val) -} - -// HwBiosVersion returns an attribute KeyValue conforming to the -// "hw.bios_version" semantic conventions. It represents the BIOS version of the -// hardware component. -func HwBiosVersion(val string) attribute.KeyValue { - return HwBiosVersionKey.String(val) -} - -// HwDriverVersion returns an attribute KeyValue conforming to the -// "hw.driver_version" semantic conventions. It represents the driver version for -// the hardware component. -func HwDriverVersion(val string) attribute.KeyValue { - return HwDriverVersionKey.String(val) -} - -// HwEnclosureType returns an attribute KeyValue conforming to the -// "hw.enclosure.type" semantic conventions. It represents the type of the -// enclosure (useful for modular systems). -func HwEnclosureType(val string) attribute.KeyValue { - return HwEnclosureTypeKey.String(val) -} - -// HwFirmwareVersion returns an attribute KeyValue conforming to the -// "hw.firmware_version" semantic conventions. It represents the firmware version -// of the hardware component. -func HwFirmwareVersion(val string) attribute.KeyValue { - return HwFirmwareVersionKey.String(val) -} - -// HwID returns an attribute KeyValue conforming to the "hw.id" semantic -// conventions. It represents an identifier for the hardware component, unique -// within the monitored host. -func HwID(val string) attribute.KeyValue { - return HwIDKey.String(val) -} - -// HwLogicalDiskRaidLevel returns an attribute KeyValue conforming to the -// "hw.logical_disk.raid_level" semantic conventions. It represents the RAID -// Level of the logical disk. -func HwLogicalDiskRaidLevel(val string) attribute.KeyValue { - return HwLogicalDiskRaidLevelKey.String(val) -} - -// HwMemoryType returns an attribute KeyValue conforming to the "hw.memory.type" -// semantic conventions. It represents the type of the memory module. -func HwMemoryType(val string) attribute.KeyValue { - return HwMemoryTypeKey.String(val) -} - -// HwModel returns an attribute KeyValue conforming to the "hw.model" semantic -// conventions. It represents the descriptive model name of the hardware -// component. -func HwModel(val string) attribute.KeyValue { - return HwModelKey.String(val) -} - -// HwName returns an attribute KeyValue conforming to the "hw.name" semantic -// conventions. It represents an easily-recognizable name for the hardware -// component. -func HwName(val string) attribute.KeyValue { - return HwNameKey.String(val) -} - -// HwNetworkLogicalAddresses returns an attribute KeyValue conforming to the -// "hw.network.logical_addresses" semantic conventions. It represents the logical -// addresses of the adapter (e.g. IP address, or WWPN). -func HwNetworkLogicalAddresses(val ...string) attribute.KeyValue { - return HwNetworkLogicalAddressesKey.StringSlice(val) -} - -// HwNetworkPhysicalAddress returns an attribute KeyValue conforming to the -// "hw.network.physical_address" semantic conventions. It represents the physical -// address of the adapter (e.g. MAC address, or WWNN). -func HwNetworkPhysicalAddress(val string) attribute.KeyValue { - return HwNetworkPhysicalAddressKey.String(val) -} - -// HwParent returns an attribute KeyValue conforming to the "hw.parent" semantic -// conventions. It represents the unique identifier of the parent component -// (typically the `hw.id` attribute of the enclosure, or disk controller). -func HwParent(val string) attribute.KeyValue { - return HwParentKey.String(val) -} - -// HwPhysicalDiskSmartAttribute returns an attribute KeyValue conforming to the -// "hw.physical_disk.smart_attribute" semantic conventions. It represents the -// [S.M.A.R.T.] (Self-Monitoring, Analysis, and Reporting Technology) attribute -// of the physical disk. -// -// [S.M.A.R.T.]: https://wikipedia.org/wiki/S.M.A.R.T. -func HwPhysicalDiskSmartAttribute(val string) attribute.KeyValue { - return HwPhysicalDiskSmartAttributeKey.String(val) -} - -// HwPhysicalDiskType returns an attribute KeyValue conforming to the -// "hw.physical_disk.type" semantic conventions. It represents the type of the -// physical disk. -func HwPhysicalDiskType(val string) attribute.KeyValue { - return HwPhysicalDiskTypeKey.String(val) -} - -// HwSensorLocation returns an attribute KeyValue conforming to the -// "hw.sensor_location" semantic conventions. It represents the location of the -// sensor. -func HwSensorLocation(val string) attribute.KeyValue { - return HwSensorLocationKey.String(val) -} - -// HwSerialNumber returns an attribute KeyValue conforming to the -// "hw.serial_number" semantic conventions. It represents the serial number of -// the hardware component. -func HwSerialNumber(val string) attribute.KeyValue { - return HwSerialNumberKey.String(val) -} - -// HwVendor returns an attribute KeyValue conforming to the "hw.vendor" semantic -// conventions. It represents the vendor name of the hardware component. -func HwVendor(val string) attribute.KeyValue { - return HwVendorKey.String(val) -} - -// Enum values for hw.battery.state -var ( - // Charging - // Stability: development - HwBatteryStateCharging = HwBatteryStateKey.String("charging") - // Discharging - // Stability: development - HwBatteryStateDischarging = HwBatteryStateKey.String("discharging") -) - -// Enum values for hw.gpu.task -var ( - // Decoder - // Stability: development - HwGpuTaskDecoder = HwGpuTaskKey.String("decoder") - // Encoder - // Stability: development - HwGpuTaskEncoder = HwGpuTaskKey.String("encoder") - // General - // Stability: development - HwGpuTaskGeneral = HwGpuTaskKey.String("general") -) - -// Enum values for hw.limit_type -var ( - // Critical - // Stability: development - HwLimitTypeCritical = HwLimitTypeKey.String("critical") - // Degraded - // Stability: development - HwLimitTypeDegraded = HwLimitTypeKey.String("degraded") - // High Critical - // Stability: development - HwLimitTypeHighCritical = HwLimitTypeKey.String("high.critical") - // High Degraded - // Stability: development - HwLimitTypeHighDegraded = HwLimitTypeKey.String("high.degraded") - // Low Critical - // Stability: development - HwLimitTypeLowCritical = HwLimitTypeKey.String("low.critical") - // Low Degraded - // Stability: development - HwLimitTypeLowDegraded = HwLimitTypeKey.String("low.degraded") - // Maximum - // Stability: development - HwLimitTypeMax = HwLimitTypeKey.String("max") - // Throttled - // Stability: development - HwLimitTypeThrottled = HwLimitTypeKey.String("throttled") - // Turbo - // Stability: development - HwLimitTypeTurbo = HwLimitTypeKey.String("turbo") -) - -// Enum values for hw.logical_disk.state -var ( - // Used - // Stability: development - HwLogicalDiskStateUsed = HwLogicalDiskStateKey.String("used") - // Free - // Stability: development - HwLogicalDiskStateFree = HwLogicalDiskStateKey.String("free") -) - -// Enum values for hw.physical_disk.state -var ( - // Remaining - // Stability: development - HwPhysicalDiskStateRemaining = HwPhysicalDiskStateKey.String("remaining") -) - -// Enum values for hw.state -var ( - // Degraded - // Stability: development - HwStateDegraded = HwStateKey.String("degraded") - // Failed - // Stability: development - HwStateFailed = HwStateKey.String("failed") - // Needs Cleaning - // Stability: development - HwStateNeedsCleaning = HwStateKey.String("needs_cleaning") - // OK - // Stability: development - HwStateOk = HwStateKey.String("ok") - // Predicted Failure - // Stability: development - HwStatePredictedFailure = HwStateKey.String("predicted_failure") -) - -// Enum values for hw.tape_drive.operation_type -var ( - // Mount - // Stability: development - HwTapeDriveOperationTypeMount = HwTapeDriveOperationTypeKey.String("mount") - // Unmount - // Stability: development - HwTapeDriveOperationTypeUnmount = HwTapeDriveOperationTypeKey.String("unmount") - // Clean - // Stability: development - HwTapeDriveOperationTypeClean = HwTapeDriveOperationTypeKey.String("clean") -) - -// Enum values for hw.type -var ( - // Battery - // Stability: development - HwTypeBattery = HwTypeKey.String("battery") - // CPU - // Stability: development - HwTypeCPU = HwTypeKey.String("cpu") - // Disk controller - // Stability: development - HwTypeDiskController = HwTypeKey.String("disk_controller") - // Enclosure - // Stability: development - HwTypeEnclosure = HwTypeKey.String("enclosure") - // Fan - // Stability: development - HwTypeFan = HwTypeKey.String("fan") - // GPU - // Stability: development - HwTypeGpu = HwTypeKey.String("gpu") - // Logical disk - // Stability: development - HwTypeLogicalDisk = HwTypeKey.String("logical_disk") - // Memory - // Stability: development - HwTypeMemory = HwTypeKey.String("memory") - // Network - // Stability: development - HwTypeNetwork = HwTypeKey.String("network") - // Physical disk - // Stability: development - HwTypePhysicalDisk = HwTypeKey.String("physical_disk") - // Power supply - // Stability: development - HwTypePowerSupply = HwTypeKey.String("power_supply") - // Tape drive - // Stability: development - HwTypeTapeDrive = HwTypeKey.String("tape_drive") - // Temperature - // Stability: development - HwTypeTemperature = HwTypeKey.String("temperature") - // Voltage - // Stability: development - HwTypeVoltage = HwTypeKey.String("voltage") -) - -// Namespace: ios -const ( - // IOSAppStateKey is the attribute Key conforming to the "ios.app.state" - // semantic conventions. It represents the this attribute represents the state - // of the application. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: The iOS lifecycle states are defined in the - // [UIApplicationDelegate documentation], and from which the `OS terminology` - // column values are derived. - // - // [UIApplicationDelegate documentation]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate - IOSAppStateKey = attribute.Key("ios.app.state") -) - -// Enum values for ios.app.state -var ( - // The app has become `active`. Associated with UIKit notification - // `applicationDidBecomeActive`. - // - // Stability: development - IOSAppStateActive = IOSAppStateKey.String("active") - // The app is now `inactive`. Associated with UIKit notification - // `applicationWillResignActive`. - // - // Stability: development - IOSAppStateInactive = IOSAppStateKey.String("inactive") - // The app is now in the background. This value is associated with UIKit - // notification `applicationDidEnterBackground`. - // - // Stability: development - IOSAppStateBackground = IOSAppStateKey.String("background") - // The app is now in the foreground. This value is associated with UIKit - // notification `applicationWillEnterForeground`. - // - // Stability: development - IOSAppStateForeground = IOSAppStateKey.String("foreground") - // The app is about to terminate. Associated with UIKit notification - // `applicationWillTerminate`. - // - // Stability: development - IOSAppStateTerminate = IOSAppStateKey.String("terminate") -) - -// Namespace: jsonrpc -const ( - // JSONRPCProtocolVersionKey is the attribute Key conforming to the - // "jsonrpc.protocol.version" semantic conventions. It represents the protocol - // version, as specified in the `jsonrpc` property of the request and its - // corresponding response. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2.0", "1.0" - JSONRPCProtocolVersionKey = attribute.Key("jsonrpc.protocol.version") - - // JSONRPCRequestIDKey is the attribute Key conforming to the - // "jsonrpc.request.id" semantic conventions. It represents a string - // representation of the `id` property of the request and its corresponding - // response. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "10", "request-7" - // Note: Under the [JSON-RPC specification], the `id` property may be a string, - // number, null, or omitted entirely. When omitted, the request is treated as a - // notification. Using `null` is not equivalent to omitting the `id`, but it is - // discouraged. - // Instrumentations SHOULD NOT capture this attribute when the `id` is `null` or - // omitted. - // - // [JSON-RPC specification]: https://www.jsonrpc.org/specification - JSONRPCRequestIDKey = attribute.Key("jsonrpc.request.id") -) - -// JSONRPCProtocolVersion returns an attribute KeyValue conforming to the -// "jsonrpc.protocol.version" semantic conventions. It represents the protocol -// version, as specified in the `jsonrpc` property of the request and its -// corresponding response. -func JSONRPCProtocolVersion(val string) attribute.KeyValue { - return JSONRPCProtocolVersionKey.String(val) -} - -// JSONRPCRequestID returns an attribute KeyValue conforming to the -// "jsonrpc.request.id" semantic conventions. It represents a string -// representation of the `id` property of the request and its corresponding -// response. -func JSONRPCRequestID(val string) attribute.KeyValue { - return JSONRPCRequestIDKey.String(val) -} - -// Namespace: k8s -const ( - // K8SClusterNameKey is the attribute Key conforming to the "k8s.cluster.name" - // semantic conventions. It represents the name of the cluster. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry-cluster" - K8SClusterNameKey = attribute.Key("k8s.cluster.name") - - // K8SClusterUIDKey is the attribute Key conforming to the "k8s.cluster.uid" - // semantic conventions. It represents a pseudo-ID for the cluster, set to the - // UID of the `kube-system` namespace. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "218fc5a9-a5f1-4b54-aa05-46717d0ab26d" - // Note: K8s doesn't have support for obtaining a cluster ID. If this is ever - // added, we will recommend collecting the `k8s.cluster.uid` through the - // official APIs. In the meantime, we are able to use the `uid` of the - // `kube-system` namespace as a proxy for cluster ID. Read on for the - // rationale. - // - // Every object created in a K8s cluster is assigned a distinct UID. The - // `kube-system` namespace is used by Kubernetes itself and will exist - // for the lifetime of the cluster. Using the `uid` of the `kube-system` - // namespace is a reasonable proxy for the K8s ClusterID as it will only - // change if the cluster is rebuilt. Furthermore, Kubernetes UIDs are - // UUIDs as standardized by - // [ISO/IEC 9834-8 and ITU-T X.667]. - // Which states: - // - // > If generated according to one of the mechanisms defined in Rec. - // > ITU-T X.667 | ISO/IEC 9834-8, a UUID is either guaranteed to be - // > different from all other UUIDs generated before 3603 A.D., or is - // > extremely likely to be different (depending on the mechanism chosen). - // - // Therefore, UIDs between clusters should be extremely unlikely to - // conflict. - // - // [ISO/IEC 9834-8 and ITU-T X.667]: https://www.itu.int/ITU-T/studygroups/com17/oid.html - K8SClusterUIDKey = attribute.Key("k8s.cluster.uid") - - // K8SContainerNameKey is the attribute Key conforming to the - // "k8s.container.name" semantic conventions. It represents the name of the - // Container from Pod specification, must be unique within a Pod. Container - // runtime usually uses different globally unique name (`container.name`). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "redis" - K8SContainerNameKey = attribute.Key("k8s.container.name") - - // K8SContainerRestartCountKey is the attribute Key conforming to the - // "k8s.container.restart_count" semantic conventions. It represents the number - // of times the container was restarted. This attribute can be used to identify - // a particular container (running or stopped) within a container spec. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: - K8SContainerRestartCountKey = attribute.Key("k8s.container.restart_count") - - // K8SContainerStatusLastTerminatedReasonKey is the attribute Key conforming to - // the "k8s.container.status.last_terminated_reason" semantic conventions. It - // represents the last terminated reason of the Container. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Evicted", "Error" - K8SContainerStatusLastTerminatedReasonKey = attribute.Key("k8s.container.status.last_terminated_reason") - - // K8SContainerStatusReasonKey is the attribute Key conforming to the - // "k8s.container.status.reason" semantic conventions. It represents the reason - // for the container state. Corresponds to the `reason` field of the: - // [K8s ContainerStateWaiting] or [K8s ContainerStateTerminated]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ContainerCreating", "CrashLoopBackOff", - // "CreateContainerConfigError", "ErrImagePull", "ImagePullBackOff", - // "OOMKilled", "Completed", "Error", "ContainerCannotRun" - // - // [K8s ContainerStateWaiting]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#containerstatewaiting-v1-core - // [K8s ContainerStateTerminated]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#containerstateterminated-v1-core - K8SContainerStatusReasonKey = attribute.Key("k8s.container.status.reason") - - // K8SContainerStatusStateKey is the attribute Key conforming to the - // "k8s.container.status.state" semantic conventions. It represents the state of - // the container. [K8s ContainerState]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "terminated", "running", "waiting" - // - // [K8s ContainerState]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#containerstate-v1-core - K8SContainerStatusStateKey = attribute.Key("k8s.container.status.state") - - // K8SCronJobNameKey is the attribute Key conforming to the "k8s.cronjob.name" - // semantic conventions. It represents the name of the CronJob. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry" - K8SCronJobNameKey = attribute.Key("k8s.cronjob.name") - - // K8SCronJobUIDKey is the attribute Key conforming to the "k8s.cronjob.uid" - // semantic conventions. It represents the UID of the CronJob. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SCronJobUIDKey = attribute.Key("k8s.cronjob.uid") - - // K8SDaemonSetNameKey is the attribute Key conforming to the - // "k8s.daemonset.name" semantic conventions. It represents the name of the - // DaemonSet. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry" - K8SDaemonSetNameKey = attribute.Key("k8s.daemonset.name") - - // K8SDaemonSetUIDKey is the attribute Key conforming to the "k8s.daemonset.uid" - // semantic conventions. It represents the UID of the DaemonSet. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SDaemonSetUIDKey = attribute.Key("k8s.daemonset.uid") - - // K8SDeploymentNameKey is the attribute Key conforming to the - // "k8s.deployment.name" semantic conventions. It represents the name of the - // Deployment. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry" - K8SDeploymentNameKey = attribute.Key("k8s.deployment.name") - - // K8SDeploymentUIDKey is the attribute Key conforming to the - // "k8s.deployment.uid" semantic conventions. It represents the UID of the - // Deployment. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SDeploymentUIDKey = attribute.Key("k8s.deployment.uid") - - // K8SHPAMetricTypeKey is the attribute Key conforming to the - // "k8s.hpa.metric.type" semantic conventions. It represents the type of metric - // source for the horizontal pod autoscaler. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Resource", "ContainerResource" - // Note: This attribute reflects the `type` field of spec.metrics[] in the HPA. - K8SHPAMetricTypeKey = attribute.Key("k8s.hpa.metric.type") - - // K8SHPANameKey is the attribute Key conforming to the "k8s.hpa.name" semantic - // conventions. It represents the name of the horizontal pod autoscaler. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "opentelemetry" - K8SHPANameKey = attribute.Key("k8s.hpa.name") - - // K8SHPAScaletargetrefAPIVersionKey is the attribute Key conforming to the - // "k8s.hpa.scaletargetref.api_version" semantic conventions. It represents the - // API version of the target resource to scale for the HorizontalPodAutoscaler. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "apps/v1", "autoscaling/v2" - // Note: This maps to the `apiVersion` field in the `scaleTargetRef` of the HPA - // spec. - K8SHPAScaletargetrefAPIVersionKey = attribute.Key("k8s.hpa.scaletargetref.api_version") - - // K8SHPAScaletargetrefKindKey is the attribute Key conforming to the - // "k8s.hpa.scaletargetref.kind" semantic conventions. It represents the kind of - // the target resource to scale for the HorizontalPodAutoscaler. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Deployment", "StatefulSet" - // Note: This maps to the `kind` field in the `scaleTargetRef` of the HPA spec. - K8SHPAScaletargetrefKindKey = attribute.Key("k8s.hpa.scaletargetref.kind") - - // K8SHPAScaletargetrefNameKey is the attribute Key conforming to the - // "k8s.hpa.scaletargetref.name" semantic conventions. It represents the name of - // the target resource to scale for the HorizontalPodAutoscaler. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-deployment", "my-statefulset" - // Note: This maps to the `name` field in the `scaleTargetRef` of the HPA spec. - K8SHPAScaletargetrefNameKey = attribute.Key("k8s.hpa.scaletargetref.name") - - // K8SHPAUIDKey is the attribute Key conforming to the "k8s.hpa.uid" semantic - // conventions. It represents the UID of the horizontal pod autoscaler. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SHPAUIDKey = attribute.Key("k8s.hpa.uid") - - // K8SHugepageSizeKey is the attribute Key conforming to the "k8s.hugepage.size" - // semantic conventions. It represents the size (identifier) of the K8s huge - // page. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2Mi" - K8SHugepageSizeKey = attribute.Key("k8s.hugepage.size") - - // K8SJobNameKey is the attribute Key conforming to the "k8s.job.name" semantic - // conventions. It represents the name of the Job. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry" - K8SJobNameKey = attribute.Key("k8s.job.name") - - // K8SJobUIDKey is the attribute Key conforming to the "k8s.job.uid" semantic - // conventions. It represents the UID of the Job. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SJobUIDKey = attribute.Key("k8s.job.uid") - - // K8SNamespaceNameKey is the attribute Key conforming to the - // "k8s.namespace.name" semantic conventions. It represents the name of the - // namespace that the pod is running in. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "default" - K8SNamespaceNameKey = attribute.Key("k8s.namespace.name") - - // K8SNamespacePhaseKey is the attribute Key conforming to the - // "k8s.namespace.phase" semantic conventions. It represents the phase of the - // K8s namespace. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "active", "terminating" - // Note: This attribute aligns with the `phase` field of the - // [K8s NamespaceStatus] - // - // [K8s NamespaceStatus]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#namespacestatus-v1-core - K8SNamespacePhaseKey = attribute.Key("k8s.namespace.phase") - - // K8SNodeConditionStatusKey is the attribute Key conforming to the - // "k8s.node.condition.status" semantic conventions. It represents the status of - // the condition, one of True, False, Unknown. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "true", "false", "unknown" - // Note: This attribute aligns with the `status` field of the - // [NodeCondition] - // - // [NodeCondition]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#nodecondition-v1-core - K8SNodeConditionStatusKey = attribute.Key("k8s.node.condition.status") - - // K8SNodeConditionTypeKey is the attribute Key conforming to the - // "k8s.node.condition.type" semantic conventions. It represents the condition - // type of a K8s Node. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Ready", "DiskPressure" - // Note: K8s Node conditions as described - // by [K8s documentation]. - // - // This attribute aligns with the `type` field of the - // [NodeCondition] - // - // The set of possible values is not limited to those listed here. Managed - // Kubernetes environments, - // or custom controllers MAY introduce additional node condition types. - // When this occurs, the exact value as reported by the Kubernetes API SHOULD be - // used. - // - // [K8s documentation]: https://v1-32.docs.kubernetes.io/docs/reference/node/node-status/#condition - // [NodeCondition]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#nodecondition-v1-core - K8SNodeConditionTypeKey = attribute.Key("k8s.node.condition.type") - - // K8SNodeNameKey is the attribute Key conforming to the "k8s.node.name" - // semantic conventions. It represents the name of the Node. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "node-1" - K8SNodeNameKey = attribute.Key("k8s.node.name") - - // K8SNodeUIDKey is the attribute Key conforming to the "k8s.node.uid" semantic - // conventions. It represents the UID of the Node. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2" - K8SNodeUIDKey = attribute.Key("k8s.node.uid") - - // K8SPodHostnameKey is the attribute Key conforming to the "k8s.pod.hostname" - // semantic conventions. It represents the specifies the hostname of the Pod. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "collector-gateway" - // Note: The K8s Pod spec has an optional hostname field, which can be used to - // specify a hostname. - // Refer to [K8s docs] - // for more information about this field. - // - // This attribute aligns with the `hostname` field of the - // [K8s PodSpec]. - // - // [K8s docs]: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-hostname-and-subdomain-field - // [K8s PodSpec]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podspec-v1-core - K8SPodHostnameKey = attribute.Key("k8s.pod.hostname") - - // K8SPodIPKey is the attribute Key conforming to the "k8s.pod.ip" semantic - // conventions. It represents the IP address allocated to the Pod. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "172.18.0.2" - // Note: This attribute aligns with the `podIP` field of the - // [K8s PodStatus]. - // - // [K8s PodStatus]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podstatus-v1-core - K8SPodIPKey = attribute.Key("k8s.pod.ip") - - // K8SPodNameKey is the attribute Key conforming to the "k8s.pod.name" semantic - // conventions. It represents the name of the Pod. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry-pod-autoconf" - K8SPodNameKey = attribute.Key("k8s.pod.name") - - // K8SPodStartTimeKey is the attribute Key conforming to the - // "k8s.pod.start_time" semantic conventions. It represents the start timestamp - // of the Pod. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "2025-12-04T08:41:03Z" - // Note: Date and time at which the object was acknowledged by the Kubelet. - // This is before the Kubelet pulled the container image(s) for the pod. - // - // This attribute aligns with the `startTime` field of the - // [K8s PodStatus], - // in ISO 8601 (RFC 3339 compatible) format. - // - // [K8s PodStatus]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#podstatus-v1-core - K8SPodStartTimeKey = attribute.Key("k8s.pod.start_time") - - // K8SPodStatusPhaseKey is the attribute Key conforming to the - // "k8s.pod.status.phase" semantic conventions. It represents the phase for the - // pod. Corresponds to the `phase` field of the: [K8s PodStatus]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Pending", "Running" - // - // [K8s PodStatus]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.33/#podstatus-v1-core - K8SPodStatusPhaseKey = attribute.Key("k8s.pod.status.phase") - - // K8SPodStatusReasonKey is the attribute Key conforming to the - // "k8s.pod.status.reason" semantic conventions. It represents the reason for - // the pod state. Corresponds to the `reason` field of the: [K8s PodStatus]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Evicted", "NodeAffinity" - // - // [K8s PodStatus]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.33/#podstatus-v1-core - K8SPodStatusReasonKey = attribute.Key("k8s.pod.status.reason") - - // K8SPodUIDKey is the attribute Key conforming to the "k8s.pod.uid" semantic - // conventions. It represents the UID of the Pod. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SPodUIDKey = attribute.Key("k8s.pod.uid") - - // K8SReplicaSetNameKey is the attribute Key conforming to the - // "k8s.replicaset.name" semantic conventions. It represents the name of the - // ReplicaSet. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry" - K8SReplicaSetNameKey = attribute.Key("k8s.replicaset.name") - - // K8SReplicaSetUIDKey is the attribute Key conforming to the - // "k8s.replicaset.uid" semantic conventions. It represents the UID of the - // ReplicaSet. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SReplicaSetUIDKey = attribute.Key("k8s.replicaset.uid") - - // K8SReplicationControllerNameKey is the attribute Key conforming to the - // "k8s.replicationcontroller.name" semantic conventions. It represents the name - // of the replication controller. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "opentelemetry" - K8SReplicationControllerNameKey = attribute.Key("k8s.replicationcontroller.name") - - // K8SReplicationControllerUIDKey is the attribute Key conforming to the - // "k8s.replicationcontroller.uid" semantic conventions. It represents the UID - // of the replication controller. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SReplicationControllerUIDKey = attribute.Key("k8s.replicationcontroller.uid") - - // K8SResourceQuotaNameKey is the attribute Key conforming to the - // "k8s.resourcequota.name" semantic conventions. It represents the name of the - // resource quota. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "opentelemetry" - K8SResourceQuotaNameKey = attribute.Key("k8s.resourcequota.name") - - // K8SResourceQuotaResourceNameKey is the attribute Key conforming to the - // "k8s.resourcequota.resource_name" semantic conventions. It represents the - // name of the K8s resource a resource quota defines. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "count/replicationcontrollers" - // Note: The value for this attribute can be either the full - // `count/[.]` string (e.g., count/deployments.apps, - // count/pods), or, for certain core Kubernetes resources, just the resource - // name (e.g., pods, services, configmaps). Both forms are supported by - // Kubernetes for object count quotas. See - // [Kubernetes Resource Quotas documentation] for more details. - // - // [Kubernetes Resource Quotas documentation]: https://kubernetes.io/docs/concepts/policy/resource-quotas/#quota-on-object-count - K8SResourceQuotaResourceNameKey = attribute.Key("k8s.resourcequota.resource_name") - - // K8SResourceQuotaUIDKey is the attribute Key conforming to the - // "k8s.resourcequota.uid" semantic conventions. It represents the UID of the - // resource quota. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SResourceQuotaUIDKey = attribute.Key("k8s.resourcequota.uid") - - // K8SServiceEndpointAddressTypeKey is the attribute Key conforming to the - // "k8s.service.endpoint.address_type" semantic conventions. It represents the - // address type of the service endpoint. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "IPv4", "IPv6" - // Note: The network address family or type of the endpoint. - // This attribute aligns with the `addressType` field of the - // [K8s EndpointSlice]. - // It is used to differentiate metrics when a Service is backed by multiple - // address types - // (e.g., in dual-stack clusters). - // - // [K8s EndpointSlice]: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/ - K8SServiceEndpointAddressTypeKey = attribute.Key("k8s.service.endpoint.address_type") - - // K8SServiceEndpointConditionKey is the attribute Key conforming to the - // "k8s.service.endpoint.condition" semantic conventions. It represents the - // condition of the service endpoint. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ready", "serving", "terminating" - // Note: The current operational condition of the service endpoint. - // An endpoint can have multiple conditions set at once (e.g., both `serving` - // and `terminating` during rollout). - // This attribute aligns with the condition fields in the [K8s EndpointSlice]. - // - // [K8s EndpointSlice]: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/ - K8SServiceEndpointConditionKey = attribute.Key("k8s.service.endpoint.condition") - - // K8SServiceEndpointZoneKey is the attribute Key conforming to the - // "k8s.service.endpoint.zone" semantic conventions. It represents the zone of - // the service endpoint. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "us-east-1a", "us-west-2b", "zone-a", "" - // Note: The zone where the endpoint is located, typically corresponding to a - // failure domain. - // This attribute aligns with the `zone` field of endpoints in the - // [K8s EndpointSlice]. - // It enables zone-aware monitoring of service endpoint distribution and - // supports - // features like [Topology Aware Routing]. - // - // If the zone is not populated (e.g., nodes without the - // `topology.kubernetes.io/zone` label), - // the attribute value will be an empty string. - // - // [K8s EndpointSlice]: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/ - // [Topology Aware Routing]: https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/ - K8SServiceEndpointZoneKey = attribute.Key("k8s.service.endpoint.zone") - - // K8SServiceNameKey is the attribute Key conforming to the "k8s.service.name" - // semantic conventions. It represents the name of the Service. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-service" - K8SServiceNameKey = attribute.Key("k8s.service.name") - - // K8SServicePublishNotReadyAddressesKey is the attribute Key conforming to the - // "k8s.service.publish_not_ready_addresses" semantic conventions. It represents - // the whether the Service publishes not-ready endpoints. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: true, false - // Note: Whether the Service is configured to publish endpoints before the pods - // are ready. - // This attribute is typically used to indicate that a Service (such as a - // headless - // Service for a StatefulSet) allows peer discovery before pods pass their - // readiness probes. - // It aligns with the `publishNotReadyAddresses` field of the - // [K8s ServiceSpec]. - // - // [K8s ServiceSpec]: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec - K8SServicePublishNotReadyAddressesKey = attribute.Key("k8s.service.publish_not_ready_addresses") - - // K8SServiceTrafficDistributionKey is the attribute Key conforming to the - // "k8s.service.traffic_distribution" semantic conventions. It represents the - // traffic distribution policy for the Service. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "PreferSameZone", "PreferSameNode" - // Note: Specifies how traffic is distributed to endpoints for this Service. - // This attribute aligns with the `trafficDistribution` field of the - // [K8s ServiceSpec]. - // Known values include `PreferSameZone` (prefer endpoints in the same zone as - // the client) and - // `PreferSameNode` (prefer endpoints on the same node, fallback to same zone, - // then cluster-wide). - // If this field is not set on the Service, the attribute SHOULD NOT be emitted. - // When not set, Kubernetes distributes traffic evenly across all endpoints - // cluster-wide. - // - // [K8s ServiceSpec]: https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution - K8SServiceTrafficDistributionKey = attribute.Key("k8s.service.traffic_distribution") - - // K8SServiceTypeKey is the attribute Key conforming to the "k8s.service.type" - // semantic conventions. It represents the type of the Kubernetes Service. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ClusterIP", "NodePort", "LoadBalancer" - // Note: This attribute aligns with the `type` field of the - // [K8s ServiceSpec]. - // - // [K8s ServiceSpec]: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec - K8SServiceTypeKey = attribute.Key("k8s.service.type") - - // K8SServiceUIDKey is the attribute Key conforming to the "k8s.service.uid" - // semantic conventions. It represents the UID of the Service. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SServiceUIDKey = attribute.Key("k8s.service.uid") - - // K8SStatefulSetNameKey is the attribute Key conforming to the - // "k8s.statefulset.name" semantic conventions. It represents the name of the - // StatefulSet. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "opentelemetry" - K8SStatefulSetNameKey = attribute.Key("k8s.statefulset.name") - - // K8SStatefulSetUIDKey is the attribute Key conforming to the - // "k8s.statefulset.uid" semantic conventions. It represents the UID of the - // StatefulSet. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Beta - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - K8SStatefulSetUIDKey = attribute.Key("k8s.statefulset.uid") - - // K8SStorageclassNameKey is the attribute Key conforming to the - // "k8s.storageclass.name" semantic conventions. It represents the name of K8s - // [StorageClass] object. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "gold.storageclass.storage.k8s.io" - // - // [StorageClass]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#storageclass-v1-storage-k8s-io - K8SStorageclassNameKey = attribute.Key("k8s.storageclass.name") - - // K8SVolumeNameKey is the attribute Key conforming to the "k8s.volume.name" - // semantic conventions. It represents the name of the K8s volume. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "volume0" - K8SVolumeNameKey = attribute.Key("k8s.volume.name") - - // K8SVolumeTypeKey is the attribute Key conforming to the "k8s.volume.type" - // semantic conventions. It represents the type of the K8s volume. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "emptyDir", "persistentVolumeClaim" - K8SVolumeTypeKey = attribute.Key("k8s.volume.type") -) - -// K8SClusterName returns an attribute KeyValue conforming to the -// "k8s.cluster.name" semantic conventions. It represents the name of the -// cluster. -func K8SClusterName(val string) attribute.KeyValue { - return K8SClusterNameKey.String(val) -} - -// K8SClusterUID returns an attribute KeyValue conforming to the -// "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for the -// cluster, set to the UID of the `kube-system` namespace. -func K8SClusterUID(val string) attribute.KeyValue { - return K8SClusterUIDKey.String(val) -} - -// K8SContainerName returns an attribute KeyValue conforming to the -// "k8s.container.name" semantic conventions. It represents the name of the -// Container from Pod specification, must be unique within a Pod. Container -// runtime usually uses different globally unique name (`container.name`). -func K8SContainerName(val string) attribute.KeyValue { - return K8SContainerNameKey.String(val) -} - -// K8SContainerRestartCount returns an attribute KeyValue conforming to the -// "k8s.container.restart_count" semantic conventions. It represents the number -// of times the container was restarted. This attribute can be used to identify a -// particular container (running or stopped) within a container spec. -func K8SContainerRestartCount(val int) attribute.KeyValue { - return K8SContainerRestartCountKey.Int(val) -} - -// K8SContainerStatusLastTerminatedReason returns an attribute KeyValue -// conforming to the "k8s.container.status.last_terminated_reason" semantic -// conventions. It represents the last terminated reason of the Container. -func K8SContainerStatusLastTerminatedReason(val string) attribute.KeyValue { - return K8SContainerStatusLastTerminatedReasonKey.String(val) -} - -// K8SCronJobAnnotation returns an attribute KeyValue conforming to the -// "k8s.cronjob.annotation" semantic conventions. It represents the cronjob -// annotation placed on the CronJob, the `` being the annotation name, the -// value being the annotation value. -func K8SCronJobAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.cronjob.annotation."+key, val) -} - -// K8SCronJobLabel returns an attribute KeyValue conforming to the -// "k8s.cronjob.label" semantic conventions. It represents the label placed on -// the CronJob, the `` being the label name, the value being the label -// value. -func K8SCronJobLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.cronjob.label."+key, val) -} - -// K8SCronJobName returns an attribute KeyValue conforming to the -// "k8s.cronjob.name" semantic conventions. It represents the name of the -// CronJob. -func K8SCronJobName(val string) attribute.KeyValue { - return K8SCronJobNameKey.String(val) -} - -// K8SCronJobUID returns an attribute KeyValue conforming to the -// "k8s.cronjob.uid" semantic conventions. It represents the UID of the CronJob. -func K8SCronJobUID(val string) attribute.KeyValue { - return K8SCronJobUIDKey.String(val) -} - -// K8SDaemonSetAnnotation returns an attribute KeyValue conforming to the -// "k8s.daemonset.annotation" semantic conventions. It represents the annotation -// placed on the DaemonSet, the `` being the annotation name, the value -// being the annotation value, even if the value is empty. -func K8SDaemonSetAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.daemonset.annotation."+key, val) -} - -// K8SDaemonSetLabel returns an attribute KeyValue conforming to the -// "k8s.daemonset.label" semantic conventions. It represents the label placed on -// the DaemonSet, the `` being the label name, the value being the label -// value, even if the value is empty. -func K8SDaemonSetLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.daemonset.label."+key, val) -} - -// K8SDaemonSetName returns an attribute KeyValue conforming to the -// "k8s.daemonset.name" semantic conventions. It represents the name of the -// DaemonSet. -func K8SDaemonSetName(val string) attribute.KeyValue { - return K8SDaemonSetNameKey.String(val) -} - -// K8SDaemonSetUID returns an attribute KeyValue conforming to the -// "k8s.daemonset.uid" semantic conventions. It represents the UID of the -// DaemonSet. -func K8SDaemonSetUID(val string) attribute.KeyValue { - return K8SDaemonSetUIDKey.String(val) -} - -// K8SDeploymentAnnotation returns an attribute KeyValue conforming to the -// "k8s.deployment.annotation" semantic conventions. It represents the annotation -// placed on the Deployment, the `` being the annotation name, the value -// being the annotation value, even if the value is empty. -func K8SDeploymentAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.deployment.annotation."+key, val) -} - -// K8SDeploymentLabel returns an attribute KeyValue conforming to the -// "k8s.deployment.label" semantic conventions. It represents the label placed on -// the Deployment, the `` being the label name, the value being the label -// value, even if the value is empty. -func K8SDeploymentLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.deployment.label."+key, val) -} - -// K8SDeploymentName returns an attribute KeyValue conforming to the -// "k8s.deployment.name" semantic conventions. It represents the name of the -// Deployment. -func K8SDeploymentName(val string) attribute.KeyValue { - return K8SDeploymentNameKey.String(val) -} - -// K8SDeploymentUID returns an attribute KeyValue conforming to the -// "k8s.deployment.uid" semantic conventions. It represents the UID of the -// Deployment. -func K8SDeploymentUID(val string) attribute.KeyValue { - return K8SDeploymentUIDKey.String(val) -} - -// K8SHPAMetricType returns an attribute KeyValue conforming to the -// "k8s.hpa.metric.type" semantic conventions. It represents the type of metric -// source for the horizontal pod autoscaler. -func K8SHPAMetricType(val string) attribute.KeyValue { - return K8SHPAMetricTypeKey.String(val) -} - -// K8SHPAName returns an attribute KeyValue conforming to the "k8s.hpa.name" -// semantic conventions. It represents the name of the horizontal pod autoscaler. -func K8SHPAName(val string) attribute.KeyValue { - return K8SHPANameKey.String(val) -} - -// K8SHPAScaletargetrefAPIVersion returns an attribute KeyValue conforming to the -// "k8s.hpa.scaletargetref.api_version" semantic conventions. It represents the -// API version of the target resource to scale for the HorizontalPodAutoscaler. -func K8SHPAScaletargetrefAPIVersion(val string) attribute.KeyValue { - return K8SHPAScaletargetrefAPIVersionKey.String(val) -} - -// K8SHPAScaletargetrefKind returns an attribute KeyValue conforming to the -// "k8s.hpa.scaletargetref.kind" semantic conventions. It represents the kind of -// the target resource to scale for the HorizontalPodAutoscaler. -func K8SHPAScaletargetrefKind(val string) attribute.KeyValue { - return K8SHPAScaletargetrefKindKey.String(val) -} - -// K8SHPAScaletargetrefName returns an attribute KeyValue conforming to the -// "k8s.hpa.scaletargetref.name" semantic conventions. It represents the name of -// the target resource to scale for the HorizontalPodAutoscaler. -func K8SHPAScaletargetrefName(val string) attribute.KeyValue { - return K8SHPAScaletargetrefNameKey.String(val) -} - -// K8SHPAUID returns an attribute KeyValue conforming to the "k8s.hpa.uid" -// semantic conventions. It represents the UID of the horizontal pod autoscaler. -func K8SHPAUID(val string) attribute.KeyValue { - return K8SHPAUIDKey.String(val) -} - -// K8SHugepageSize returns an attribute KeyValue conforming to the -// "k8s.hugepage.size" semantic conventions. It represents the size (identifier) -// of the K8s huge page. -func K8SHugepageSize(val string) attribute.KeyValue { - return K8SHugepageSizeKey.String(val) -} - -// K8SJobAnnotation returns an attribute KeyValue conforming to the -// "k8s.job.annotation" semantic conventions. It represents the annotation placed -// on the Job, the `` being the annotation name, the value being the -// annotation value, even if the value is empty. -func K8SJobAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.job.annotation."+key, val) -} - -// K8SJobLabel returns an attribute KeyValue conforming to the "k8s.job.label" -// semantic conventions. It represents the label placed on the Job, the `` -// being the label name, the value being the label value, even if the value is -// empty. -func K8SJobLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.job.label."+key, val) -} - -// K8SJobName returns an attribute KeyValue conforming to the "k8s.job.name" -// semantic conventions. It represents the name of the Job. -func K8SJobName(val string) attribute.KeyValue { - return K8SJobNameKey.String(val) -} - -// K8SJobUID returns an attribute KeyValue conforming to the "k8s.job.uid" -// semantic conventions. It represents the UID of the Job. -func K8SJobUID(val string) attribute.KeyValue { - return K8SJobUIDKey.String(val) -} - -// K8SNamespaceAnnotation returns an attribute KeyValue conforming to the -// "k8s.namespace.annotation" semantic conventions. It represents the annotation -// placed on the Namespace, the `` being the annotation name, the value -// being the annotation value, even if the value is empty. -func K8SNamespaceAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.namespace.annotation."+key, val) -} - -// K8SNamespaceLabel returns an attribute KeyValue conforming to the -// "k8s.namespace.label" semantic conventions. It represents the label placed on -// the Namespace, the `` being the label name, the value being the label -// value, even if the value is empty. -func K8SNamespaceLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.namespace.label."+key, val) -} - -// K8SNamespaceName returns an attribute KeyValue conforming to the -// "k8s.namespace.name" semantic conventions. It represents the name of the -// namespace that the pod is running in. -func K8SNamespaceName(val string) attribute.KeyValue { - return K8SNamespaceNameKey.String(val) -} - -// K8SNodeAnnotation returns an attribute KeyValue conforming to the -// "k8s.node.annotation" semantic conventions. It represents the annotation -// placed on the Node, the `` being the annotation name, the value being the -// annotation value, even if the value is empty. -func K8SNodeAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.node.annotation."+key, val) -} - -// K8SNodeLabel returns an attribute KeyValue conforming to the "k8s.node.label" -// semantic conventions. It represents the label placed on the Node, the `` -// being the label name, the value being the label value, even if the value is -// empty. -func K8SNodeLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.node.label."+key, val) -} - -// K8SNodeName returns an attribute KeyValue conforming to the "k8s.node.name" -// semantic conventions. It represents the name of the Node. -func K8SNodeName(val string) attribute.KeyValue { - return K8SNodeNameKey.String(val) -} - -// K8SNodeUID returns an attribute KeyValue conforming to the "k8s.node.uid" -// semantic conventions. It represents the UID of the Node. -func K8SNodeUID(val string) attribute.KeyValue { - return K8SNodeUIDKey.String(val) -} - -// K8SPodAnnotation returns an attribute KeyValue conforming to the -// "k8s.pod.annotation" semantic conventions. It represents the annotation placed -// on the Pod, the `` being the annotation name, the value being the -// annotation value. -func K8SPodAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.pod.annotation."+key, val) -} - -// K8SPodHostname returns an attribute KeyValue conforming to the -// "k8s.pod.hostname" semantic conventions. It represents the specifies the -// hostname of the Pod. -func K8SPodHostname(val string) attribute.KeyValue { - return K8SPodHostnameKey.String(val) -} - -// K8SPodIP returns an attribute KeyValue conforming to the "k8s.pod.ip" semantic -// conventions. It represents the IP address allocated to the Pod. -func K8SPodIP(val string) attribute.KeyValue { - return K8SPodIPKey.String(val) -} - -// K8SPodLabel returns an attribute KeyValue conforming to the "k8s.pod.label" -// semantic conventions. It represents the label placed on the Pod, the `` -// being the label name, the value being the label value. -func K8SPodLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.pod.label."+key, val) -} - -// K8SPodName returns an attribute KeyValue conforming to the "k8s.pod.name" -// semantic conventions. It represents the name of the Pod. -func K8SPodName(val string) attribute.KeyValue { - return K8SPodNameKey.String(val) -} - -// K8SPodStartTime returns an attribute KeyValue conforming to the -// "k8s.pod.start_time" semantic conventions. It represents the start timestamp -// of the Pod. -func K8SPodStartTime(val string) attribute.KeyValue { - return K8SPodStartTimeKey.String(val) -} - -// K8SPodUID returns an attribute KeyValue conforming to the "k8s.pod.uid" -// semantic conventions. It represents the UID of the Pod. -func K8SPodUID(val string) attribute.KeyValue { - return K8SPodUIDKey.String(val) -} - -// K8SReplicaSetAnnotation returns an attribute KeyValue conforming to the -// "k8s.replicaset.annotation" semantic conventions. It represents the annotation -// placed on the ReplicaSet, the `` being the annotation name, the value -// being the annotation value, even if the value is empty. -func K8SReplicaSetAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.replicaset.annotation."+key, val) -} - -// K8SReplicaSetLabel returns an attribute KeyValue conforming to the -// "k8s.replicaset.label" semantic conventions. It represents the label placed on -// the ReplicaSet, the `` being the label name, the value being the label -// value, even if the value is empty. -func K8SReplicaSetLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.replicaset.label."+key, val) -} - -// K8SReplicaSetName returns an attribute KeyValue conforming to the -// "k8s.replicaset.name" semantic conventions. It represents the name of the -// ReplicaSet. -func K8SReplicaSetName(val string) attribute.KeyValue { - return K8SReplicaSetNameKey.String(val) -} - -// K8SReplicaSetUID returns an attribute KeyValue conforming to the -// "k8s.replicaset.uid" semantic conventions. It represents the UID of the -// ReplicaSet. -func K8SReplicaSetUID(val string) attribute.KeyValue { - return K8SReplicaSetUIDKey.String(val) -} - -// K8SReplicationControllerName returns an attribute KeyValue conforming to the -// "k8s.replicationcontroller.name" semantic conventions. It represents the name -// of the replication controller. -func K8SReplicationControllerName(val string) attribute.KeyValue { - return K8SReplicationControllerNameKey.String(val) -} - -// K8SReplicationControllerUID returns an attribute KeyValue conforming to the -// "k8s.replicationcontroller.uid" semantic conventions. It represents the UID of -// the replication controller. -func K8SReplicationControllerUID(val string) attribute.KeyValue { - return K8SReplicationControllerUIDKey.String(val) -} - -// K8SResourceQuotaName returns an attribute KeyValue conforming to the -// "k8s.resourcequota.name" semantic conventions. It represents the name of the -// resource quota. -func K8SResourceQuotaName(val string) attribute.KeyValue { - return K8SResourceQuotaNameKey.String(val) -} - -// K8SResourceQuotaResourceName returns an attribute KeyValue conforming to the -// "k8s.resourcequota.resource_name" semantic conventions. It represents the name -// of the K8s resource a resource quota defines. -func K8SResourceQuotaResourceName(val string) attribute.KeyValue { - return K8SResourceQuotaResourceNameKey.String(val) -} - -// K8SResourceQuotaUID returns an attribute KeyValue conforming to the -// "k8s.resourcequota.uid" semantic conventions. It represents the UID of the -// resource quota. -func K8SResourceQuotaUID(val string) attribute.KeyValue { - return K8SResourceQuotaUIDKey.String(val) -} - -// K8SServiceAnnotation returns an attribute KeyValue conforming to the -// "k8s.service.annotation" semantic conventions. It represents the annotation -// placed on the Service, the `` being the annotation name, the value being -// the annotation value, even if the value is empty. -func K8SServiceAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.service.annotation."+key, val) -} - -// K8SServiceEndpointZone returns an attribute KeyValue conforming to the -// "k8s.service.endpoint.zone" semantic conventions. It represents the zone of -// the service endpoint. -func K8SServiceEndpointZone(val string) attribute.KeyValue { - return K8SServiceEndpointZoneKey.String(val) -} - -// K8SServiceLabel returns an attribute KeyValue conforming to the -// "k8s.service.label" semantic conventions. It represents the label placed on -// the Service, the `` being the label name, the value being the label -// value, even if the value is empty. -func K8SServiceLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.service.label."+key, val) -} - -// K8SServiceName returns an attribute KeyValue conforming to the -// "k8s.service.name" semantic conventions. It represents the name of the -// Service. -func K8SServiceName(val string) attribute.KeyValue { - return K8SServiceNameKey.String(val) -} - -// K8SServicePublishNotReadyAddresses returns an attribute KeyValue conforming to -// the "k8s.service.publish_not_ready_addresses" semantic conventions. It -// represents the whether the Service publishes not-ready endpoints. -func K8SServicePublishNotReadyAddresses(val bool) attribute.KeyValue { - return K8SServicePublishNotReadyAddressesKey.Bool(val) -} - -// K8SServiceSelector returns an attribute KeyValue conforming to the -// "k8s.service.selector" semantic conventions. It represents the selector -// key-value pair placed on the Service, the `` being the selector key, the -// value being the selector value. -func K8SServiceSelector(key string, val string) attribute.KeyValue { - return attribute.String("k8s.service.selector."+key, val) -} - -// K8SServiceTrafficDistribution returns an attribute KeyValue conforming to the -// "k8s.service.traffic_distribution" semantic conventions. It represents the -// traffic distribution policy for the Service. -func K8SServiceTrafficDistribution(val string) attribute.KeyValue { - return K8SServiceTrafficDistributionKey.String(val) -} - -// K8SServiceUID returns an attribute KeyValue conforming to the -// "k8s.service.uid" semantic conventions. It represents the UID of the Service. -func K8SServiceUID(val string) attribute.KeyValue { - return K8SServiceUIDKey.String(val) -} - -// K8SStatefulSetAnnotation returns an attribute KeyValue conforming to the -// "k8s.statefulset.annotation" semantic conventions. It represents the -// annotation placed on the StatefulSet, the `` being the annotation name, -// the value being the annotation value, even if the value is empty. -func K8SStatefulSetAnnotation(key string, val string) attribute.KeyValue { - return attribute.String("k8s.statefulset.annotation."+key, val) -} - -// K8SStatefulSetLabel returns an attribute KeyValue conforming to the -// "k8s.statefulset.label" semantic conventions. It represents the label placed -// on the StatefulSet, the `` being the label name, the value being the -// label value, even if the value is empty. -func K8SStatefulSetLabel(key string, val string) attribute.KeyValue { - return attribute.String("k8s.statefulset.label."+key, val) -} - -// K8SStatefulSetName returns an attribute KeyValue conforming to the -// "k8s.statefulset.name" semantic conventions. It represents the name of the -// StatefulSet. -func K8SStatefulSetName(val string) attribute.KeyValue { - return K8SStatefulSetNameKey.String(val) -} - -// K8SStatefulSetUID returns an attribute KeyValue conforming to the -// "k8s.statefulset.uid" semantic conventions. It represents the UID of the -// StatefulSet. -func K8SStatefulSetUID(val string) attribute.KeyValue { - return K8SStatefulSetUIDKey.String(val) -} - -// K8SStorageclassName returns an attribute KeyValue conforming to the -// "k8s.storageclass.name" semantic conventions. It represents the name of K8s -// [StorageClass] object. -// -// [StorageClass]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#storageclass-v1-storage-k8s-io -func K8SStorageclassName(val string) attribute.KeyValue { - return K8SStorageclassNameKey.String(val) -} - -// K8SVolumeName returns an attribute KeyValue conforming to the -// "k8s.volume.name" semantic conventions. It represents the name of the K8s -// volume. -func K8SVolumeName(val string) attribute.KeyValue { - return K8SVolumeNameKey.String(val) -} - -// Enum values for k8s.container.status.reason -var ( - // The container is being created. - // Stability: development - K8SContainerStatusReasonContainerCreating = K8SContainerStatusReasonKey.String("ContainerCreating") - // The container is in a crash loop back off state. - // Stability: development - K8SContainerStatusReasonCrashLoopBackOff = K8SContainerStatusReasonKey.String("CrashLoopBackOff") - // There was an error creating the container configuration. - // Stability: development - K8SContainerStatusReasonCreateContainerConfigError = K8SContainerStatusReasonKey.String("CreateContainerConfigError") - // There was an error pulling the container image. - // Stability: development - K8SContainerStatusReasonErrImagePull = K8SContainerStatusReasonKey.String("ErrImagePull") - // The container image pull is in back off state. - // Stability: development - K8SContainerStatusReasonImagePullBackOff = K8SContainerStatusReasonKey.String("ImagePullBackOff") - // The container was killed due to out of memory. - // Stability: development - K8SContainerStatusReasonOomKilled = K8SContainerStatusReasonKey.String("OOMKilled") - // The container has completed execution. - // Stability: development - K8SContainerStatusReasonCompleted = K8SContainerStatusReasonKey.String("Completed") - // There was an error with the container. - // Stability: development - K8SContainerStatusReasonError = K8SContainerStatusReasonKey.String("Error") - // The container cannot run. - // Stability: development - K8SContainerStatusReasonContainerCannotRun = K8SContainerStatusReasonKey.String("ContainerCannotRun") -) - -// Enum values for k8s.container.status.state -var ( - // The container has terminated. - // Stability: development - K8SContainerStatusStateTerminated = K8SContainerStatusStateKey.String("terminated") - // The container is running. - // Stability: development - K8SContainerStatusStateRunning = K8SContainerStatusStateKey.String("running") - // The container is waiting. - // Stability: development - K8SContainerStatusStateWaiting = K8SContainerStatusStateKey.String("waiting") -) - -// Enum values for k8s.namespace.phase -var ( - // Active namespace phase as described by [K8s API] - // Stability: development - // - // [K8s API]: https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase - K8SNamespacePhaseActive = K8SNamespacePhaseKey.String("active") - // Terminating namespace phase as described by [K8s API] - // Stability: development - // - // [K8s API]: https://pkg.go.dev/k8s.io/api@v0.31.3/core/v1#NamespacePhase - K8SNamespacePhaseTerminating = K8SNamespacePhaseKey.String("terminating") -) - -// Enum values for k8s.node.condition.status -var ( - // condition_true - // Stability: development - K8SNodeConditionStatusConditionTrue = K8SNodeConditionStatusKey.String("true") - // condition_false - // Stability: development - K8SNodeConditionStatusConditionFalse = K8SNodeConditionStatusKey.String("false") - // condition_unknown - // Stability: development - K8SNodeConditionStatusConditionUnknown = K8SNodeConditionStatusKey.String("unknown") -) - -// Enum values for k8s.node.condition.type -var ( - // The node is healthy and ready to accept pods - // Stability: development - K8SNodeConditionTypeReady = K8SNodeConditionTypeKey.String("Ready") - // Pressure exists on the disk size—that is, if the disk capacity is low - // Stability: development - K8SNodeConditionTypeDiskPressure = K8SNodeConditionTypeKey.String("DiskPressure") - // Pressure exists on the node memory—that is, if the node memory is low - // Stability: development - K8SNodeConditionTypeMemoryPressure = K8SNodeConditionTypeKey.String("MemoryPressure") - // Pressure exists on the processes—that is, if there are too many processes - // on the node - // Stability: development - K8SNodeConditionTypePIDPressure = K8SNodeConditionTypeKey.String("PIDPressure") - // The network for the node is not correctly configured - // Stability: development - K8SNodeConditionTypeNetworkUnavailable = K8SNodeConditionTypeKey.String("NetworkUnavailable") -) - -// Enum values for k8s.pod.status.phase -var ( - // The pod has been accepted by the system, but one or more of the containers - // has not been started. This includes time before being bound to a node, as - // well as time spent pulling images onto the host. - // - // Stability: development - K8SPodStatusPhasePending = K8SPodStatusPhaseKey.String("Pending") - // The pod has been bound to a node and all of the containers have been started. - // At least one container is still running or is in the process of being - // restarted. - // - // Stability: development - K8SPodStatusPhaseRunning = K8SPodStatusPhaseKey.String("Running") - // All containers in the pod have voluntarily terminated with a container exit - // code of 0, and the system is not going to restart any of these containers. - // - // Stability: development - K8SPodStatusPhaseSucceeded = K8SPodStatusPhaseKey.String("Succeeded") - // All containers in the pod have terminated, and at least one container has - // terminated in a failure (exited with a non-zero exit code or was stopped by - // the system). - // - // Stability: development - K8SPodStatusPhaseFailed = K8SPodStatusPhaseKey.String("Failed") - // For some reason the state of the pod could not be obtained, typically due to - // an error in communicating with the host of the pod. - // - // Stability: development - K8SPodStatusPhaseUnknown = K8SPodStatusPhaseKey.String("Unknown") -) - -// Enum values for k8s.pod.status.reason -var ( - // The pod is evicted. - // Stability: development - K8SPodStatusReasonEvicted = K8SPodStatusReasonKey.String("Evicted") - // The pod is in a status because of its node affinity - // Stability: development - K8SPodStatusReasonNodeAffinity = K8SPodStatusReasonKey.String("NodeAffinity") - // The reason on a pod when its state cannot be confirmed as kubelet is - // unresponsive on the node it is (was) running. - // - // Stability: development - K8SPodStatusReasonNodeLost = K8SPodStatusReasonKey.String("NodeLost") - // The node is shutdown - // Stability: development - K8SPodStatusReasonShutdown = K8SPodStatusReasonKey.String("Shutdown") - // The pod was rejected admission to the node because of an error during - // admission that could not be categorized. - // - // Stability: development - K8SPodStatusReasonUnexpectedAdmissionError = K8SPodStatusReasonKey.String("UnexpectedAdmissionError") -) - -// Enum values for k8s.service.endpoint.address_type -var ( - // IPv4 address type - // Stability: development - K8SServiceEndpointAddressTypeIPv4 = K8SServiceEndpointAddressTypeKey.String("IPv4") - // IPv6 address type - // Stability: development - K8SServiceEndpointAddressTypeIPv6 = K8SServiceEndpointAddressTypeKey.String("IPv6") - // FQDN address type - // Stability: development - K8SServiceEndpointAddressTypeFqdn = K8SServiceEndpointAddressTypeKey.String("FQDN") -) - -// Enum values for k8s.service.endpoint.condition -var ( - // The endpoint is ready to receive new connections. - // Stability: development - K8SServiceEndpointConditionReady = K8SServiceEndpointConditionKey.String("ready") - // The endpoint is currently handling traffic. - // Stability: development - K8SServiceEndpointConditionServing = K8SServiceEndpointConditionKey.String("serving") - // The endpoint is in the process of shutting down. - // Stability: development - K8SServiceEndpointConditionTerminating = K8SServiceEndpointConditionKey.String("terminating") -) - -// Enum values for k8s.service.type -var ( - // ClusterIP service type - // Stability: development - K8SServiceTypeClusterIP = K8SServiceTypeKey.String("ClusterIP") - // NodePort service type - // Stability: development - K8SServiceTypeNodePort = K8SServiceTypeKey.String("NodePort") - // LoadBalancer service type - // Stability: development - K8SServiceTypeLoadBalancer = K8SServiceTypeKey.String("LoadBalancer") - // ExternalName service type - // Stability: development - K8SServiceTypeExternalName = K8SServiceTypeKey.String("ExternalName") -) - -// Enum values for k8s.volume.type -var ( - // A [persistentVolumeClaim] volume - // Stability: development - // - // [persistentVolumeClaim]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim - K8SVolumeTypePersistentVolumeClaim = K8SVolumeTypeKey.String("persistentVolumeClaim") - // A [configMap] volume - // Stability: development - // - // [configMap]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#configmap - K8SVolumeTypeConfigMap = K8SVolumeTypeKey.String("configMap") - // A [downwardAPI] volume - // Stability: development - // - // [downwardAPI]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#downwardapi - K8SVolumeTypeDownwardAPI = K8SVolumeTypeKey.String("downwardAPI") - // An [emptyDir] volume - // Stability: development - // - // [emptyDir]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#emptydir - K8SVolumeTypeEmptyDir = K8SVolumeTypeKey.String("emptyDir") - // A [secret] volume - // Stability: development - // - // [secret]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#secret - K8SVolumeTypeSecret = K8SVolumeTypeKey.String("secret") - // A [local] volume - // Stability: development - // - // [local]: https://v1-30.docs.kubernetes.io/docs/concepts/storage/volumes/#local - K8SVolumeTypeLocal = K8SVolumeTypeKey.String("local") -) - -// Namespace: log -const ( - // LogFileNameKey is the attribute Key conforming to the "log.file.name" - // semantic conventions. It represents the basename of the file. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "audit.log" - LogFileNameKey = attribute.Key("log.file.name") - - // LogFileNameResolvedKey is the attribute Key conforming to the - // "log.file.name_resolved" semantic conventions. It represents the basename of - // the file, with symlinks resolved. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "uuid.log" - LogFileNameResolvedKey = attribute.Key("log.file.name_resolved") - - // LogFilePathKey is the attribute Key conforming to the "log.file.path" - // semantic conventions. It represents the full path to the file. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/var/log/mysql/audit.log" - LogFilePathKey = attribute.Key("log.file.path") - - // LogFilePathResolvedKey is the attribute Key conforming to the - // "log.file.path_resolved" semantic conventions. It represents the full path to - // the file, with symlinks resolved. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/var/lib/docker/uuid.log" - LogFilePathResolvedKey = attribute.Key("log.file.path_resolved") - - // LogIostreamKey is the attribute Key conforming to the "log.iostream" semantic - // conventions. It represents the stream associated with the log. See below for - // a list of well-known values. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - LogIostreamKey = attribute.Key("log.iostream") - - // LogRecordOriginalKey is the attribute Key conforming to the - // "log.record.original" semantic conventions. It represents the complete - // original Log Record. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "77 <86>1 2015-08-06T21:58:59.694Z 192.168.2.133 inactive - - - - // Something happened", "[INFO] 8/3/24 12:34:56 Something happened" - // Note: This value MAY be added when processing a Log Record which was - // originally transmitted as a string or equivalent data type AND the Body field - // of the Log Record does not contain the same value. (e.g. a syslog or a log - // record read from a file.) - LogRecordOriginalKey = attribute.Key("log.record.original") - - // LogRecordUIDKey is the attribute Key conforming to the "log.record.uid" - // semantic conventions. It represents a unique identifier for the Log Record. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "01ARZ3NDEKTSV4RRFFQ69G5FAV" - // Note: If an id is provided, other log records with the same id will be - // considered duplicates and can be removed safely. This means, that two - // distinguishable log records MUST have different values. - // The id MAY be an - // [Universally Unique Lexicographically Sortable Identifier (ULID)], but other - // identifiers (e.g. UUID) may be used as needed. - // - // [Universally Unique Lexicographically Sortable Identifier (ULID)]: https://github.com/ulid/spec - LogRecordUIDKey = attribute.Key("log.record.uid") -) - -// LogFileName returns an attribute KeyValue conforming to the "log.file.name" -// semantic conventions. It represents the basename of the file. -func LogFileName(val string) attribute.KeyValue { - return LogFileNameKey.String(val) -} - -// LogFileNameResolved returns an attribute KeyValue conforming to the -// "log.file.name_resolved" semantic conventions. It represents the basename of -// the file, with symlinks resolved. -func LogFileNameResolved(val string) attribute.KeyValue { - return LogFileNameResolvedKey.String(val) -} - -// LogFilePath returns an attribute KeyValue conforming to the "log.file.path" -// semantic conventions. It represents the full path to the file. -func LogFilePath(val string) attribute.KeyValue { - return LogFilePathKey.String(val) -} - -// LogFilePathResolved returns an attribute KeyValue conforming to the -// "log.file.path_resolved" semantic conventions. It represents the full path to -// the file, with symlinks resolved. -func LogFilePathResolved(val string) attribute.KeyValue { - return LogFilePathResolvedKey.String(val) -} - -// LogRecordOriginal returns an attribute KeyValue conforming to the -// "log.record.original" semantic conventions. It represents the complete -// original Log Record. -func LogRecordOriginal(val string) attribute.KeyValue { - return LogRecordOriginalKey.String(val) -} - -// LogRecordUID returns an attribute KeyValue conforming to the "log.record.uid" -// semantic conventions. It represents a unique identifier for the Log Record. -func LogRecordUID(val string) attribute.KeyValue { - return LogRecordUIDKey.String(val) -} - -// Enum values for log.iostream -var ( - // Logs from stdout stream - // Stability: development - LogIostreamStdout = LogIostreamKey.String("stdout") - // Events from stderr stream - // Stability: development - LogIostreamStderr = LogIostreamKey.String("stderr") -) - -// Namespace: mainframe -const ( - // MainframeLparNameKey is the attribute Key conforming to the - // "mainframe.lpar.name" semantic conventions. It represents the name of the - // logical partition that hosts a systems with a mainframe operating system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "LPAR01" - MainframeLparNameKey = attribute.Key("mainframe.lpar.name") -) - -// MainframeLparName returns an attribute KeyValue conforming to the -// "mainframe.lpar.name" semantic conventions. It represents the name of the -// logical partition that hosts a systems with a mainframe operating system. -func MainframeLparName(val string) attribute.KeyValue { - return MainframeLparNameKey.String(val) -} - -// Namespace: mcp -const ( - // McpMethodNameKey is the attribute Key conforming to the "mcp.method.name" - // semantic conventions. It represents the name of the request or notification - // method. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - McpMethodNameKey = attribute.Key("mcp.method.name") - - // McpProtocolVersionKey is the attribute Key conforming to the - // "mcp.protocol.version" semantic conventions. It represents the [version] of - // the Model Context Protocol used. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2025-06-18" - // - // [version]: https://modelcontextprotocol.io/specification/versioning - McpProtocolVersionKey = attribute.Key("mcp.protocol.version") - - // McpResourceURIKey is the attribute Key conforming to the "mcp.resource.uri" - // semantic conventions. It represents the value of the resource uri. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "postgres://database/customers/schema", - // "file:///home/user/documents/report.pdf" - // Note: This is a URI of the resource provided in the following requests or - // notifications: `resources/read`, `resources/subscribe`, - // `resources/unsubscribe`, or `notifications/resources/updated`. - McpResourceURIKey = attribute.Key("mcp.resource.uri") - - // McpSessionIDKey is the attribute Key conforming to the "mcp.session.id" - // semantic conventions. It represents the identifies [MCP session]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "191c4850af6c49e08843a3f6c80e5046" - // - // [MCP session]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#session-management - McpSessionIDKey = attribute.Key("mcp.session.id") -) - -// McpProtocolVersion returns an attribute KeyValue conforming to the -// "mcp.protocol.version" semantic conventions. It represents the [version] of -// the Model Context Protocol used. -// -// [version]: https://modelcontextprotocol.io/specification/versioning -func McpProtocolVersion(val string) attribute.KeyValue { - return McpProtocolVersionKey.String(val) -} - -// McpResourceURI returns an attribute KeyValue conforming to the -// "mcp.resource.uri" semantic conventions. It represents the value of the -// resource uri. -func McpResourceURI(val string) attribute.KeyValue { - return McpResourceURIKey.String(val) -} - -// McpSessionID returns an attribute KeyValue conforming to the "mcp.session.id" -// semantic conventions. It represents the identifies [MCP session]. -// -// [MCP session]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#session-management -func McpSessionID(val string) attribute.KeyValue { - return McpSessionIDKey.String(val) -} - -// Enum values for mcp.method.name -var ( - // Notification cancelling a previously-issued request. - // - // Stability: development - McpMethodNameNotificationsCancelled = McpMethodNameKey.String("notifications/cancelled") - // Request to initialize the MCP client. - // - // Stability: development - McpMethodNameInitialize = McpMethodNameKey.String("initialize") - // Notification indicating that the MCP client has been initialized. - // - // Stability: development - McpMethodNameNotificationsInitialized = McpMethodNameKey.String("notifications/initialized") - // Notification indicating the progress for a long-running operation. - // - // Stability: development - McpMethodNameNotificationsProgress = McpMethodNameKey.String("notifications/progress") - // Request to check that the other party is still alive. - // - // Stability: development - McpMethodNamePing = McpMethodNameKey.String("ping") - // Request to list resources available on server. - // - // Stability: development - McpMethodNameResourcesList = McpMethodNameKey.String("resources/list") - // Request to list resource templates available on server. - // - // Stability: development - McpMethodNameResourcesTemplatesList = McpMethodNameKey.String("resources/templates/list") - // Request to read a resource. - // - // Stability: development - McpMethodNameResourcesRead = McpMethodNameKey.String("resources/read") - // Notification indicating that the list of resources has changed. - // - // Stability: development - McpMethodNameNotificationsResourcesListChanged = McpMethodNameKey.String("notifications/resources/list_changed") - // Request to subscribe to a resource. - // - // Stability: development - McpMethodNameResourcesSubscribe = McpMethodNameKey.String("resources/subscribe") - // Request to unsubscribe from resource updates. - // - // Stability: development - McpMethodNameResourcesUnsubscribe = McpMethodNameKey.String("resources/unsubscribe") - // Notification indicating that a resource has been updated. - // - // Stability: development - McpMethodNameNotificationsResourcesUpdated = McpMethodNameKey.String("notifications/resources/updated") - // Request to list prompts available on server. - // - // Stability: development - McpMethodNamePromptsList = McpMethodNameKey.String("prompts/list") - // Request to get a prompt. - // - // Stability: development - McpMethodNamePromptsGet = McpMethodNameKey.String("prompts/get") - // Notification indicating that the list of prompts has changed. - // - // Stability: development - McpMethodNameNotificationsPromptsListChanged = McpMethodNameKey.String("notifications/prompts/list_changed") - // Request to list tools available on server. - // - // Stability: development - McpMethodNameToolsList = McpMethodNameKey.String("tools/list") - // Request to call a tool. - // - // Stability: development - McpMethodNameToolsCall = McpMethodNameKey.String("tools/call") - // Notification indicating that the list of tools has changed. - // - // Stability: development - McpMethodNameNotificationsToolsListChanged = McpMethodNameKey.String("notifications/tools/list_changed") - // Request to set the logging level. - // - // Stability: development - McpMethodNameLoggingSetLevel = McpMethodNameKey.String("logging/setLevel") - // Notification indicating that a message has been received. - // - // Stability: development - McpMethodNameNotificationsMessage = McpMethodNameKey.String("notifications/message") - // Request to create a sampling message. - // - // Stability: development - McpMethodNameSamplingCreateMessage = McpMethodNameKey.String("sampling/createMessage") - // Request to complete a prompt. - // - // Stability: development - McpMethodNameCompletionComplete = McpMethodNameKey.String("completion/complete") - // Request to list roots available on server. - // - // Stability: development - McpMethodNameRootsList = McpMethodNameKey.String("roots/list") - // Notification indicating that the list of roots has changed. - // - // Stability: development - McpMethodNameNotificationsRootsListChanged = McpMethodNameKey.String("notifications/roots/list_changed") - // Request from the server to elicit additional information from the user via - // the client - // - // Stability: development - McpMethodNameElicitationCreate = McpMethodNameKey.String("elicitation/create") -) - -// Namespace: messaging -const ( - // MessagingBatchMessageCountKey is the attribute Key conforming to the - // "messaging.batch.message_count" semantic conventions. It represents the - // number of messages sent, received, or processed in the scope of the batching - // operation. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 0, 1, 2 - // Note: Instrumentations SHOULD NOT set `messaging.batch.message_count` on - // spans that operate with a single message. When a messaging client library - // supports both batch and single-message API for the same operation, - // instrumentations SHOULD use `messaging.batch.message_count` for batching APIs - // and SHOULD NOT use it for single-message APIs. - MessagingBatchMessageCountKey = attribute.Key("messaging.batch.message_count") - - // MessagingClientIDKey is the attribute Key conforming to the - // "messaging.client.id" semantic conventions. It represents a unique identifier - // for the client that consumes or produces a message. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "client-5", "myhost@8742@s8083jm" - MessagingClientIDKey = attribute.Key("messaging.client.id") - - // MessagingConsumerGroupNameKey is the attribute Key conforming to the - // "messaging.consumer.group.name" semantic conventions. It represents the name - // of the consumer group with which a consumer is associated. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-group", "indexer" - // Note: Semantic conventions for individual messaging systems SHOULD document - // whether `messaging.consumer.group.name` is applicable and what it means in - // the context of that system. - MessagingConsumerGroupNameKey = attribute.Key("messaging.consumer.group.name") - - // MessagingDestinationAnonymousKey is the attribute Key conforming to the - // "messaging.destination.anonymous" semantic conventions. It represents a - // boolean that is true if the message destination is anonymous (could be - // unnamed or have auto-generated name). - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - MessagingDestinationAnonymousKey = attribute.Key("messaging.destination.anonymous") - - // MessagingDestinationNameKey is the attribute Key conforming to the - // "messaging.destination.name" semantic conventions. It represents the message - // destination name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "MyQueue", "MyTopic" - // Note: Destination name SHOULD uniquely identify a specific queue, topic or - // other entity within the broker. If - // the broker doesn't have such notion, the destination name SHOULD uniquely - // identify the broker. - MessagingDestinationNameKey = attribute.Key("messaging.destination.name") - - // MessagingDestinationPartitionIDKey is the attribute Key conforming to the - // "messaging.destination.partition.id" semantic conventions. It represents the - // identifier of the partition messages are sent to or received from, unique - // within the `messaging.destination.name`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1 - MessagingDestinationPartitionIDKey = attribute.Key("messaging.destination.partition.id") - - // MessagingDestinationSubscriptionNameKey is the attribute Key conforming to - // the "messaging.destination.subscription.name" semantic conventions. It - // represents the name of the destination subscription from which a message is - // consumed. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "subscription-a" - // Note: Semantic conventions for individual messaging systems SHOULD document - // whether `messaging.destination.subscription.name` is applicable and what it - // means in the context of that system. - MessagingDestinationSubscriptionNameKey = attribute.Key("messaging.destination.subscription.name") - - // MessagingDestinationTemplateKey is the attribute Key conforming to the - // "messaging.destination.template" semantic conventions. It represents the low - // cardinality representation of the messaging destination name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/customers/{customerId}" - // Note: Destination names could be constructed from templates. An example would - // be a destination name involving a user name or product id. Although the - // destination name in this case is of high cardinality, the underlying template - // is of low cardinality and can be effectively used for grouping and - // aggregation. - MessagingDestinationTemplateKey = attribute.Key("messaging.destination.template") - - // MessagingDestinationTemporaryKey is the attribute Key conforming to the - // "messaging.destination.temporary" semantic conventions. It represents a - // boolean that is true if the message destination is temporary and might not - // exist anymore after messages are processed. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - MessagingDestinationTemporaryKey = attribute.Key("messaging.destination.temporary") - - // MessagingEventHubsMessageEnqueuedTimeKey is the attribute Key conforming to - // the "messaging.eventhubs.message.enqueued_time" semantic conventions. It - // represents the UTC epoch seconds at which the message has been accepted and - // stored in the entity. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingEventHubsMessageEnqueuedTimeKey = attribute.Key("messaging.eventhubs.message.enqueued_time") - - // MessagingGCPPubSubMessageAckDeadlineKey is the attribute Key conforming to - // the "messaging.gcp_pubsub.message.ack_deadline" semantic conventions. It - // represents the ack deadline in seconds set for the modify ack deadline - // request. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingGCPPubSubMessageAckDeadlineKey = attribute.Key("messaging.gcp_pubsub.message.ack_deadline") - - // MessagingGCPPubSubMessageAckIDKey is the attribute Key conforming to the - // "messaging.gcp_pubsub.message.ack_id" semantic conventions. It represents the - // ack id for a given message. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: ack_id - MessagingGCPPubSubMessageAckIDKey = attribute.Key("messaging.gcp_pubsub.message.ack_id") - - // MessagingGCPPubSubMessageDeliveryAttemptKey is the attribute Key conforming - // to the "messaging.gcp_pubsub.message.delivery_attempt" semantic conventions. - // It represents the delivery attempt for a given message. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingGCPPubSubMessageDeliveryAttemptKey = attribute.Key("messaging.gcp_pubsub.message.delivery_attempt") - - // MessagingGCPPubSubMessageOrderingKeyKey is the attribute Key conforming to - // the "messaging.gcp_pubsub.message.ordering_key" semantic conventions. It - // represents the ordering key for a given message. If the attribute is not - // present, the message does not have an ordering key. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: ordering_key - MessagingGCPPubSubMessageOrderingKeyKey = attribute.Key("messaging.gcp_pubsub.message.ordering_key") - - // MessagingKafkaMessageKeyKey is the attribute Key conforming to the - // "messaging.kafka.message.key" semantic conventions. It represents the message - // keys in Kafka are used for grouping alike messages to ensure they're - // processed on the same partition. They differ from `messaging.message.id` in - // that they're not unique. If the key is `null`, the attribute MUST NOT be set. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: myKey - // Note: If the key type is not string, it's string representation has to be - // supplied for the attribute. If the key has no unambiguous, canonical string - // form, don't include its value. - MessagingKafkaMessageKeyKey = attribute.Key("messaging.kafka.message.key") - - // MessagingKafkaMessageTombstoneKey is the attribute Key conforming to the - // "messaging.kafka.message.tombstone" semantic conventions. It represents a - // boolean that is true if the message is a tombstone. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - MessagingKafkaMessageTombstoneKey = attribute.Key("messaging.kafka.message.tombstone") - - // MessagingKafkaOffsetKey is the attribute Key conforming to the - // "messaging.kafka.offset" semantic conventions. It represents the offset of a - // record in the corresponding Kafka partition. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingKafkaOffsetKey = attribute.Key("messaging.kafka.offset") - - // MessagingMessageBodySizeKey is the attribute Key conforming to the - // "messaging.message.body.size" semantic conventions. It represents the size of - // the message body in bytes. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Note: This can refer to both the compressed or uncompressed body size. If - // both sizes are known, the uncompressed - // body size should be used. - MessagingMessageBodySizeKey = attribute.Key("messaging.message.body.size") - - // MessagingMessageConversationIDKey is the attribute Key conforming to the - // "messaging.message.conversation_id" semantic conventions. It represents the - // conversation ID identifying the conversation to which the message belongs, - // represented as a string. Sometimes called "Correlation ID". - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: MyConversationId - MessagingMessageConversationIDKey = attribute.Key("messaging.message.conversation_id") - - // MessagingMessageEnvelopeSizeKey is the attribute Key conforming to the - // "messaging.message.envelope.size" semantic conventions. It represents the - // size of the message body and metadata in bytes. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Note: This can refer to both the compressed or uncompressed size. If both - // sizes are known, the uncompressed - // size should be used. - MessagingMessageEnvelopeSizeKey = attribute.Key("messaging.message.envelope.size") - - // MessagingMessageIDKey is the attribute Key conforming to the - // "messaging.message.id" semantic conventions. It represents a value used by - // the messaging system as an identifier for the message, represented as a - // string. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 452a7c7c7c7048c2f887f61572b18fc2 - MessagingMessageIDKey = attribute.Key("messaging.message.id") - - // MessagingOperationNameKey is the attribute Key conforming to the - // "messaging.operation.name" semantic conventions. It represents the - // system-specific name of the messaging operation. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ack", "nack", "send" - MessagingOperationNameKey = attribute.Key("messaging.operation.name") - - // MessagingOperationTypeKey is the attribute Key conforming to the - // "messaging.operation.type" semantic conventions. It represents a string - // identifying the type of the messaging operation. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: If a custom value is used, it MUST be of low cardinality. - MessagingOperationTypeKey = attribute.Key("messaging.operation.type") - - // MessagingRabbitMQDestinationRoutingKeyKey is the attribute Key conforming to - // the "messaging.rabbitmq.destination.routing_key" semantic conventions. It - // represents the rabbitMQ message routing key. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: myKey - MessagingRabbitMQDestinationRoutingKeyKey = attribute.Key("messaging.rabbitmq.destination.routing_key") - - // MessagingRabbitMQMessageDeliveryTagKey is the attribute Key conforming to the - // "messaging.rabbitmq.message.delivery_tag" semantic conventions. It represents - // the rabbitMQ message delivery tag. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingRabbitMQMessageDeliveryTagKey = attribute.Key("messaging.rabbitmq.message.delivery_tag") - - // MessagingRocketMQConsumptionModelKey is the attribute Key conforming to the - // "messaging.rocketmq.consumption_model" semantic conventions. It represents - // the model of message consumption. This only applies to consumer spans. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - MessagingRocketMQConsumptionModelKey = attribute.Key("messaging.rocketmq.consumption_model") - - // MessagingRocketMQMessageDelayTimeLevelKey is the attribute Key conforming to - // the "messaging.rocketmq.message.delay_time_level" semantic conventions. It - // represents the delay time level for delay message, which determines the - // message delay time. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingRocketMQMessageDelayTimeLevelKey = attribute.Key("messaging.rocketmq.message.delay_time_level") - - // MessagingRocketMQMessageDeliveryTimestampKey is the attribute Key conforming - // to the "messaging.rocketmq.message.delivery_timestamp" semantic conventions. - // It represents the timestamp in milliseconds that the delay message is - // expected to be delivered to consumer. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingRocketMQMessageDeliveryTimestampKey = attribute.Key("messaging.rocketmq.message.delivery_timestamp") - - // MessagingRocketMQMessageGroupKey is the attribute Key conforming to the - // "messaging.rocketmq.message.group" semantic conventions. It represents the it - // is essential for FIFO message. Messages that belong to the same message group - // are always processed one by one within the same consumer group. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: myMessageGroup - MessagingRocketMQMessageGroupKey = attribute.Key("messaging.rocketmq.message.group") - - // MessagingRocketMQMessageKeysKey is the attribute Key conforming to the - // "messaging.rocketmq.message.keys" semantic conventions. It represents the - // key(s) of message, another way to mark message besides message id. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "keyA", "keyB" - MessagingRocketMQMessageKeysKey = attribute.Key("messaging.rocketmq.message.keys") - - // MessagingRocketMQMessageTagKey is the attribute Key conforming to the - // "messaging.rocketmq.message.tag" semantic conventions. It represents the - // secondary classifier of message besides topic. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: tagA - MessagingRocketMQMessageTagKey = attribute.Key("messaging.rocketmq.message.tag") - - // MessagingRocketMQMessageTypeKey is the attribute Key conforming to the - // "messaging.rocketmq.message.type" semantic conventions. It represents the - // type of message. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - MessagingRocketMQMessageTypeKey = attribute.Key("messaging.rocketmq.message.type") - - // MessagingRocketMQNamespaceKey is the attribute Key conforming to the - // "messaging.rocketmq.namespace" semantic conventions. It represents the - // namespace of RocketMQ resources, resources in different namespaces are - // individual. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: myNamespace - MessagingRocketMQNamespaceKey = attribute.Key("messaging.rocketmq.namespace") - - // MessagingServiceBusDispositionStatusKey is the attribute Key conforming to - // the "messaging.servicebus.disposition_status" semantic conventions. It - // represents the describes the [settlement type]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [settlement type]: https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock - MessagingServiceBusDispositionStatusKey = attribute.Key("messaging.servicebus.disposition_status") - - // MessagingServiceBusMessageDeliveryCountKey is the attribute Key conforming to - // the "messaging.servicebus.message.delivery_count" semantic conventions. It - // represents the number of deliveries that have been attempted for this - // message. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingServiceBusMessageDeliveryCountKey = attribute.Key("messaging.servicebus.message.delivery_count") - - // MessagingServiceBusMessageEnqueuedTimeKey is the attribute Key conforming to - // the "messaging.servicebus.message.enqueued_time" semantic conventions. It - // represents the UTC epoch seconds at which the message has been accepted and - // stored in the entity. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - MessagingServiceBusMessageEnqueuedTimeKey = attribute.Key("messaging.servicebus.message.enqueued_time") - - // MessagingSystemKey is the attribute Key conforming to the "messaging.system" - // semantic conventions. It represents the messaging system as identified by the - // client instrumentation. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: The actual messaging system may differ from the one known by the - // client. For example, when using Kafka client libraries to communicate with - // Azure Event Hubs, the `messaging.system` is set to `kafka` based on the - // instrumentation's best knowledge. - MessagingSystemKey = attribute.Key("messaging.system") -) - -// MessagingBatchMessageCount returns an attribute KeyValue conforming to the -// "messaging.batch.message_count" semantic conventions. It represents the number -// of messages sent, received, or processed in the scope of the batching -// operation. -func MessagingBatchMessageCount(val int) attribute.KeyValue { - return MessagingBatchMessageCountKey.Int(val) -} - -// MessagingClientID returns an attribute KeyValue conforming to the -// "messaging.client.id" semantic conventions. It represents a unique identifier -// for the client that consumes or produces a message. -func MessagingClientID(val string) attribute.KeyValue { - return MessagingClientIDKey.String(val) -} - -// MessagingConsumerGroupName returns an attribute KeyValue conforming to the -// "messaging.consumer.group.name" semantic conventions. It represents the name -// of the consumer group with which a consumer is associated. -func MessagingConsumerGroupName(val string) attribute.KeyValue { - return MessagingConsumerGroupNameKey.String(val) -} - -// MessagingDestinationAnonymous returns an attribute KeyValue conforming to the -// "messaging.destination.anonymous" semantic conventions. It represents a -// boolean that is true if the message destination is anonymous (could be unnamed -// or have auto-generated name). -func MessagingDestinationAnonymous(val bool) attribute.KeyValue { - return MessagingDestinationAnonymousKey.Bool(val) -} - -// MessagingDestinationName returns an attribute KeyValue conforming to the -// "messaging.destination.name" semantic conventions. It represents the message -// destination name. -func MessagingDestinationName(val string) attribute.KeyValue { - return MessagingDestinationNameKey.String(val) -} - -// MessagingDestinationPartitionID returns an attribute KeyValue conforming to -// the "messaging.destination.partition.id" semantic conventions. It represents -// the identifier of the partition messages are sent to or received from, unique -// within the `messaging.destination.name`. -func MessagingDestinationPartitionID(val string) attribute.KeyValue { - return MessagingDestinationPartitionIDKey.String(val) -} - -// MessagingDestinationSubscriptionName returns an attribute KeyValue conforming -// to the "messaging.destination.subscription.name" semantic conventions. It -// represents the name of the destination subscription from which a message is -// consumed. -func MessagingDestinationSubscriptionName(val string) attribute.KeyValue { - return MessagingDestinationSubscriptionNameKey.String(val) -} - -// MessagingDestinationTemplate returns an attribute KeyValue conforming to the -// "messaging.destination.template" semantic conventions. It represents the low -// cardinality representation of the messaging destination name. -func MessagingDestinationTemplate(val string) attribute.KeyValue { - return MessagingDestinationTemplateKey.String(val) -} - -// MessagingDestinationTemporary returns an attribute KeyValue conforming to the -// "messaging.destination.temporary" semantic conventions. It represents a -// boolean that is true if the message destination is temporary and might not -// exist anymore after messages are processed. -func MessagingDestinationTemporary(val bool) attribute.KeyValue { - return MessagingDestinationTemporaryKey.Bool(val) -} - -// MessagingEventHubsMessageEnqueuedTime returns an attribute KeyValue conforming -// to the "messaging.eventhubs.message.enqueued_time" semantic conventions. It -// represents the UTC epoch seconds at which the message has been accepted and -// stored in the entity. -func MessagingEventHubsMessageEnqueuedTime(val int) attribute.KeyValue { - return MessagingEventHubsMessageEnqueuedTimeKey.Int(val) -} - -// MessagingGCPPubSubMessageAckDeadline returns an attribute KeyValue conforming -// to the "messaging.gcp_pubsub.message.ack_deadline" semantic conventions. It -// represents the ack deadline in seconds set for the modify ack deadline -// request. -func MessagingGCPPubSubMessageAckDeadline(val int) attribute.KeyValue { - return MessagingGCPPubSubMessageAckDeadlineKey.Int(val) -} - -// MessagingGCPPubSubMessageAckID returns an attribute KeyValue conforming to the -// "messaging.gcp_pubsub.message.ack_id" semantic conventions. It represents the -// ack id for a given message. -func MessagingGCPPubSubMessageAckID(val string) attribute.KeyValue { - return MessagingGCPPubSubMessageAckIDKey.String(val) -} - -// MessagingGCPPubSubMessageDeliveryAttempt returns an attribute KeyValue -// conforming to the "messaging.gcp_pubsub.message.delivery_attempt" semantic -// conventions. It represents the delivery attempt for a given message. -func MessagingGCPPubSubMessageDeliveryAttempt(val int) attribute.KeyValue { - return MessagingGCPPubSubMessageDeliveryAttemptKey.Int(val) -} - -// MessagingGCPPubSubMessageOrderingKey returns an attribute KeyValue conforming -// to the "messaging.gcp_pubsub.message.ordering_key" semantic conventions. It -// represents the ordering key for a given message. If the attribute is not -// present, the message does not have an ordering key. -func MessagingGCPPubSubMessageOrderingKey(val string) attribute.KeyValue { - return MessagingGCPPubSubMessageOrderingKeyKey.String(val) -} - -// MessagingKafkaMessageKey returns an attribute KeyValue conforming to the -// "messaging.kafka.message.key" semantic conventions. It represents the message -// keys in Kafka are used for grouping alike messages to ensure they're processed -// on the same partition. They differ from `messaging.message.id` in that they're -// not unique. If the key is `null`, the attribute MUST NOT be set. -func MessagingKafkaMessageKey(val string) attribute.KeyValue { - return MessagingKafkaMessageKeyKey.String(val) -} - -// MessagingKafkaMessageTombstone returns an attribute KeyValue conforming to the -// "messaging.kafka.message.tombstone" semantic conventions. It represents a -// boolean that is true if the message is a tombstone. -func MessagingKafkaMessageTombstone(val bool) attribute.KeyValue { - return MessagingKafkaMessageTombstoneKey.Bool(val) -} - -// MessagingKafkaOffset returns an attribute KeyValue conforming to the -// "messaging.kafka.offset" semantic conventions. It represents the offset of a -// record in the corresponding Kafka partition. -func MessagingKafkaOffset(val int) attribute.KeyValue { - return MessagingKafkaOffsetKey.Int(val) -} - -// MessagingMessageBodySize returns an attribute KeyValue conforming to the -// "messaging.message.body.size" semantic conventions. It represents the size of -// the message body in bytes. -func MessagingMessageBodySize(val int) attribute.KeyValue { - return MessagingMessageBodySizeKey.Int(val) -} - -// MessagingMessageConversationID returns an attribute KeyValue conforming to the -// "messaging.message.conversation_id" semantic conventions. It represents the -// conversation ID identifying the conversation to which the message belongs, -// represented as a string. Sometimes called "Correlation ID". -func MessagingMessageConversationID(val string) attribute.KeyValue { - return MessagingMessageConversationIDKey.String(val) -} - -// MessagingMessageEnvelopeSize returns an attribute KeyValue conforming to the -// "messaging.message.envelope.size" semantic conventions. It represents the size -// of the message body and metadata in bytes. -func MessagingMessageEnvelopeSize(val int) attribute.KeyValue { - return MessagingMessageEnvelopeSizeKey.Int(val) -} - -// MessagingMessageID returns an attribute KeyValue conforming to the -// "messaging.message.id" semantic conventions. It represents a value used by the -// messaging system as an identifier for the message, represented as a string. -func MessagingMessageID(val string) attribute.KeyValue { - return MessagingMessageIDKey.String(val) -} - -// MessagingOperationName returns an attribute KeyValue conforming to the -// "messaging.operation.name" semantic conventions. It represents the -// system-specific name of the messaging operation. -func MessagingOperationName(val string) attribute.KeyValue { - return MessagingOperationNameKey.String(val) -} - -// MessagingRabbitMQDestinationRoutingKey returns an attribute KeyValue -// conforming to the "messaging.rabbitmq.destination.routing_key" semantic -// conventions. It represents the rabbitMQ message routing key. -func MessagingRabbitMQDestinationRoutingKey(val string) attribute.KeyValue { - return MessagingRabbitMQDestinationRoutingKeyKey.String(val) -} - -// MessagingRabbitMQMessageDeliveryTag returns an attribute KeyValue conforming -// to the "messaging.rabbitmq.message.delivery_tag" semantic conventions. It -// represents the rabbitMQ message delivery tag. -func MessagingRabbitMQMessageDeliveryTag(val int) attribute.KeyValue { - return MessagingRabbitMQMessageDeliveryTagKey.Int(val) -} - -// MessagingRocketMQMessageDelayTimeLevel returns an attribute KeyValue -// conforming to the "messaging.rocketmq.message.delay_time_level" semantic -// conventions. It represents the delay time level for delay message, which -// determines the message delay time. -func MessagingRocketMQMessageDelayTimeLevel(val int) attribute.KeyValue { - return MessagingRocketMQMessageDelayTimeLevelKey.Int(val) -} - -// MessagingRocketMQMessageDeliveryTimestamp returns an attribute KeyValue -// conforming to the "messaging.rocketmq.message.delivery_timestamp" semantic -// conventions. It represents the timestamp in milliseconds that the delay -// message is expected to be delivered to consumer. -func MessagingRocketMQMessageDeliveryTimestamp(val int) attribute.KeyValue { - return MessagingRocketMQMessageDeliveryTimestampKey.Int(val) -} - -// MessagingRocketMQMessageGroup returns an attribute KeyValue conforming to the -// "messaging.rocketmq.message.group" semantic conventions. It represents the it -// is essential for FIFO message. Messages that belong to the same message group -// are always processed one by one within the same consumer group. -func MessagingRocketMQMessageGroup(val string) attribute.KeyValue { - return MessagingRocketMQMessageGroupKey.String(val) -} - -// MessagingRocketMQMessageKeys returns an attribute KeyValue conforming to the -// "messaging.rocketmq.message.keys" semantic conventions. It represents the -// key(s) of message, another way to mark message besides message id. -func MessagingRocketMQMessageKeys(val ...string) attribute.KeyValue { - return MessagingRocketMQMessageKeysKey.StringSlice(val) -} - -// MessagingRocketMQMessageTag returns an attribute KeyValue conforming to the -// "messaging.rocketmq.message.tag" semantic conventions. It represents the -// secondary classifier of message besides topic. -func MessagingRocketMQMessageTag(val string) attribute.KeyValue { - return MessagingRocketMQMessageTagKey.String(val) -} - -// MessagingRocketMQNamespace returns an attribute KeyValue conforming to the -// "messaging.rocketmq.namespace" semantic conventions. It represents the -// namespace of RocketMQ resources, resources in different namespaces are -// individual. -func MessagingRocketMQNamespace(val string) attribute.KeyValue { - return MessagingRocketMQNamespaceKey.String(val) -} - -// MessagingServiceBusMessageDeliveryCount returns an attribute KeyValue -// conforming to the "messaging.servicebus.message.delivery_count" semantic -// conventions. It represents the number of deliveries that have been attempted -// for this message. -func MessagingServiceBusMessageDeliveryCount(val int) attribute.KeyValue { - return MessagingServiceBusMessageDeliveryCountKey.Int(val) -} - -// MessagingServiceBusMessageEnqueuedTime returns an attribute KeyValue -// conforming to the "messaging.servicebus.message.enqueued_time" semantic -// conventions. It represents the UTC epoch seconds at which the message has been -// accepted and stored in the entity. -func MessagingServiceBusMessageEnqueuedTime(val int) attribute.KeyValue { - return MessagingServiceBusMessageEnqueuedTimeKey.Int(val) -} - -// Enum values for messaging.operation.type -var ( - // A message is created. "Create" spans always refer to a single message and are - // used to provide a unique creation context for messages in batch sending - // scenarios. - // - // Stability: development - MessagingOperationTypeCreate = MessagingOperationTypeKey.String("create") - // One or more messages are provided for sending to an intermediary. If a single - // message is sent, the context of the "Send" span can be used as the creation - // context and no "Create" span needs to be created. - // - // Stability: development - MessagingOperationTypeSend = MessagingOperationTypeKey.String("send") - // One or more messages are requested by a consumer. This operation refers to - // pull-based scenarios, where consumers explicitly call methods of messaging - // SDKs to receive messages. - // - // Stability: development - MessagingOperationTypeReceive = MessagingOperationTypeKey.String("receive") - // One or more messages are processed by a consumer. - // - // Stability: development - MessagingOperationTypeProcess = MessagingOperationTypeKey.String("process") - // One or more messages are settled. - // - // Stability: development - MessagingOperationTypeSettle = MessagingOperationTypeKey.String("settle") -) - -// Enum values for messaging.rocketmq.consumption_model -var ( - // Clustering consumption model - // Stability: development - MessagingRocketMQConsumptionModelClustering = MessagingRocketMQConsumptionModelKey.String("clustering") - // Broadcasting consumption model - // Stability: development - MessagingRocketMQConsumptionModelBroadcasting = MessagingRocketMQConsumptionModelKey.String("broadcasting") -) - -// Enum values for messaging.rocketmq.message.type -var ( - // Normal message - // Stability: development - MessagingRocketMQMessageTypeNormal = MessagingRocketMQMessageTypeKey.String("normal") - // FIFO message - // Stability: development - MessagingRocketMQMessageTypeFifo = MessagingRocketMQMessageTypeKey.String("fifo") - // Delay message - // Stability: development - MessagingRocketMQMessageTypeDelay = MessagingRocketMQMessageTypeKey.String("delay") - // Transaction message - // Stability: development - MessagingRocketMQMessageTypeTransaction = MessagingRocketMQMessageTypeKey.String("transaction") -) - -// Enum values for messaging.servicebus.disposition_status -var ( - // Message is completed - // Stability: development - MessagingServiceBusDispositionStatusComplete = MessagingServiceBusDispositionStatusKey.String("complete") - // Message is abandoned - // Stability: development - MessagingServiceBusDispositionStatusAbandon = MessagingServiceBusDispositionStatusKey.String("abandon") - // Message is sent to dead letter queue - // Stability: development - MessagingServiceBusDispositionStatusDeadLetter = MessagingServiceBusDispositionStatusKey.String("dead_letter") - // Message is deferred - // Stability: development - MessagingServiceBusDispositionStatusDefer = MessagingServiceBusDispositionStatusKey.String("defer") -) - -// Enum values for messaging.system -var ( - // Apache ActiveMQ - // Stability: development - MessagingSystemActiveMQ = MessagingSystemKey.String("activemq") - // Amazon Simple Notification Service (SNS) - // Stability: development - MessagingSystemAWSSNS = MessagingSystemKey.String("aws.sns") - // Amazon Simple Queue Service (SQS) - // Stability: development - MessagingSystemAWSSQS = MessagingSystemKey.String("aws_sqs") - // Azure Event Grid - // Stability: development - MessagingSystemEventGrid = MessagingSystemKey.String("eventgrid") - // Azure Event Hubs - // Stability: development - MessagingSystemEventHubs = MessagingSystemKey.String("eventhubs") - // Azure Service Bus - // Stability: development - MessagingSystemServiceBus = MessagingSystemKey.String("servicebus") - // Google Cloud Pub/Sub - // Stability: development - MessagingSystemGCPPubSub = MessagingSystemKey.String("gcp_pubsub") - // Java Message Service - // Stability: development - MessagingSystemJMS = MessagingSystemKey.String("jms") - // Apache Kafka - // Stability: development - MessagingSystemKafka = MessagingSystemKey.String("kafka") - // RabbitMQ - // Stability: development - MessagingSystemRabbitMQ = MessagingSystemKey.String("rabbitmq") - // Apache RocketMQ - // Stability: development - MessagingSystemRocketMQ = MessagingSystemKey.String("rocketmq") - // Apache Pulsar - // Stability: development - MessagingSystemPulsar = MessagingSystemKey.String("pulsar") -) - -// Namespace: network -const ( - // NetworkCarrierICCKey is the attribute Key conforming to the - // "network.carrier.icc" semantic conventions. It represents the ISO 3166-1 - // alpha-2 2-character country code associated with the mobile carrier network. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: DE - NetworkCarrierICCKey = attribute.Key("network.carrier.icc") - - // NetworkCarrierMCCKey is the attribute Key conforming to the - // "network.carrier.mcc" semantic conventions. It represents the mobile carrier - // country code. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 310 - NetworkCarrierMCCKey = attribute.Key("network.carrier.mcc") - - // NetworkCarrierMNCKey is the attribute Key conforming to the - // "network.carrier.mnc" semantic conventions. It represents the mobile carrier - // network code. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 001 - NetworkCarrierMNCKey = attribute.Key("network.carrier.mnc") - - // NetworkCarrierNameKey is the attribute Key conforming to the - // "network.carrier.name" semantic conventions. It represents the name of the - // mobile carrier. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: sprint - NetworkCarrierNameKey = attribute.Key("network.carrier.name") - - // NetworkConnectionStateKey is the attribute Key conforming to the - // "network.connection.state" semantic conventions. It represents the state of - // network connection. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "close_wait" - // Note: Connection states are defined as part of the [rfc9293] - // - // [rfc9293]: https://datatracker.ietf.org/doc/html/rfc9293#section-3.3.2 - NetworkConnectionStateKey = attribute.Key("network.connection.state") - - // NetworkConnectionSubtypeKey is the attribute Key conforming to the - // "network.connection.subtype" semantic conventions. It represents the this - // describes more details regarding the connection.type. It may be the type of - // cell technology connection, but it could be used for describing details about - // a wifi connection. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: LTE - NetworkConnectionSubtypeKey = attribute.Key("network.connection.subtype") - - // NetworkConnectionTypeKey is the attribute Key conforming to the - // "network.connection.type" semantic conventions. It represents the internet - // connection type. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: wifi - NetworkConnectionTypeKey = attribute.Key("network.connection.type") - - // NetworkInterfaceNameKey is the attribute Key conforming to the - // "network.interface.name" semantic conventions. It represents the network - // interface name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "lo", "eth0" - NetworkInterfaceNameKey = attribute.Key("network.interface.name") - - // NetworkIODirectionKey is the attribute Key conforming to the - // "network.io.direction" semantic conventions. It represents the network IO - // operation direction. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "transmit" - NetworkIODirectionKey = attribute.Key("network.io.direction") - - // NetworkLocalAddressKey is the attribute Key conforming to the - // "network.local.address" semantic conventions. It represents the local address - // of the network connection - IP address or Unix domain socket name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "10.1.2.80", "/tmp/my.sock" - NetworkLocalAddressKey = attribute.Key("network.local.address") - - // NetworkLocalPortKey is the attribute Key conforming to the - // "network.local.port" semantic conventions. It represents the local port - // number of the network connection. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: 65123 - NetworkLocalPortKey = attribute.Key("network.local.port") - - // NetworkPeerAddressKey is the attribute Key conforming to the - // "network.peer.address" semantic conventions. It represents the peer address - // of the network connection - IP address or Unix domain socket name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "10.1.2.80", "/tmp/my.sock" - NetworkPeerAddressKey = attribute.Key("network.peer.address") - - // NetworkPeerPortKey is the attribute Key conforming to the "network.peer.port" - // semantic conventions. It represents the peer port number of the network - // connection. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: 65123 - NetworkPeerPortKey = attribute.Key("network.peer.port") - - // NetworkProtocolNameKey is the attribute Key conforming to the - // "network.protocol.name" semantic conventions. It represents the - // [OSI application layer] or non-OSI equivalent. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "amqp", "http", "mqtt" - // Note: The value SHOULD be normalized to lowercase. - // - // [OSI application layer]: https://wikipedia.org/wiki/Application_layer - NetworkProtocolNameKey = attribute.Key("network.protocol.name") - - // NetworkProtocolVersionKey is the attribute Key conforming to the - // "network.protocol.version" semantic conventions. It represents the actual - // version of the protocol used for network communication. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "1.1", "2" - // Note: If protocol version is subject to negotiation (for example using [ALPN] - // ), this attribute SHOULD be set to the negotiated version. If the actual - // protocol version is not known, this attribute SHOULD NOT be set. - // - // [ALPN]: https://www.rfc-editor.org/rfc/rfc7301.html - NetworkProtocolVersionKey = attribute.Key("network.protocol.version") - - // NetworkTransportKey is the attribute Key conforming to the - // "network.transport" semantic conventions. It represents the - // [OSI transport layer] or [inter-process communication method]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "tcp", "udp" - // Note: The value SHOULD be normalized to lowercase. - // - // Consider always setting the transport when setting a port number, since - // a port number is ambiguous without knowing the transport. For example - // different processes could be listening on TCP port 12345 and UDP port 12345. - // - // [OSI transport layer]: https://wikipedia.org/wiki/Transport_layer - // [inter-process communication method]: https://wikipedia.org/wiki/Inter-process_communication - NetworkTransportKey = attribute.Key("network.transport") - - // NetworkTypeKey is the attribute Key conforming to the "network.type" semantic - // conventions. It represents the [OSI network layer] or non-OSI equivalent. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "ipv4", "ipv6" - // Note: The value SHOULD be normalized to lowercase. - // - // [OSI network layer]: https://wikipedia.org/wiki/Network_layer - NetworkTypeKey = attribute.Key("network.type") -) - -// NetworkCarrierICC returns an attribute KeyValue conforming to the -// "network.carrier.icc" semantic conventions. It represents the ISO 3166-1 -// alpha-2 2-character country code associated with the mobile carrier network. -func NetworkCarrierICC(val string) attribute.KeyValue { - return NetworkCarrierICCKey.String(val) -} - -// NetworkCarrierMCC returns an attribute KeyValue conforming to the -// "network.carrier.mcc" semantic conventions. It represents the mobile carrier -// country code. -func NetworkCarrierMCC(val string) attribute.KeyValue { - return NetworkCarrierMCCKey.String(val) -} - -// NetworkCarrierMNC returns an attribute KeyValue conforming to the -// "network.carrier.mnc" semantic conventions. It represents the mobile carrier -// network code. -func NetworkCarrierMNC(val string) attribute.KeyValue { - return NetworkCarrierMNCKey.String(val) -} - -// NetworkCarrierName returns an attribute KeyValue conforming to the -// "network.carrier.name" semantic conventions. It represents the name of the -// mobile carrier. -func NetworkCarrierName(val string) attribute.KeyValue { - return NetworkCarrierNameKey.String(val) -} - -// NetworkInterfaceName returns an attribute KeyValue conforming to the -// "network.interface.name" semantic conventions. It represents the network -// interface name. -func NetworkInterfaceName(val string) attribute.KeyValue { - return NetworkInterfaceNameKey.String(val) -} - -// NetworkLocalAddress returns an attribute KeyValue conforming to the -// "network.local.address" semantic conventions. It represents the local address -// of the network connection - IP address or Unix domain socket name. -func NetworkLocalAddress(val string) attribute.KeyValue { - return NetworkLocalAddressKey.String(val) -} - -// NetworkLocalPort returns an attribute KeyValue conforming to the -// "network.local.port" semantic conventions. It represents the local port number -// of the network connection. -func NetworkLocalPort(val int) attribute.KeyValue { - return NetworkLocalPortKey.Int(val) -} - -// NetworkPeerAddress returns an attribute KeyValue conforming to the -// "network.peer.address" semantic conventions. It represents the peer address of -// the network connection - IP address or Unix domain socket name. -func NetworkPeerAddress(val string) attribute.KeyValue { - return NetworkPeerAddressKey.String(val) -} - -// NetworkPeerPort returns an attribute KeyValue conforming to the -// "network.peer.port" semantic conventions. It represents the peer port number -// of the network connection. -func NetworkPeerPort(val int) attribute.KeyValue { - return NetworkPeerPortKey.Int(val) -} - -// NetworkProtocolName returns an attribute KeyValue conforming to the -// "network.protocol.name" semantic conventions. It represents the -// [OSI application layer] or non-OSI equivalent. -// -// [OSI application layer]: https://wikipedia.org/wiki/Application_layer -func NetworkProtocolName(val string) attribute.KeyValue { - return NetworkProtocolNameKey.String(val) -} - -// NetworkProtocolVersion returns an attribute KeyValue conforming to the -// "network.protocol.version" semantic conventions. It represents the actual -// version of the protocol used for network communication. -func NetworkProtocolVersion(val string) attribute.KeyValue { - return NetworkProtocolVersionKey.String(val) -} - -// Enum values for network.connection.state -var ( - // closed - // Stability: development - NetworkConnectionStateClosed = NetworkConnectionStateKey.String("closed") - // close_wait - // Stability: development - NetworkConnectionStateCloseWait = NetworkConnectionStateKey.String("close_wait") - // closing - // Stability: development - NetworkConnectionStateClosing = NetworkConnectionStateKey.String("closing") - // established - // Stability: development - NetworkConnectionStateEstablished = NetworkConnectionStateKey.String("established") - // fin_wait_1 - // Stability: development - NetworkConnectionStateFinWait1 = NetworkConnectionStateKey.String("fin_wait_1") - // fin_wait_2 - // Stability: development - NetworkConnectionStateFinWait2 = NetworkConnectionStateKey.String("fin_wait_2") - // last_ack - // Stability: development - NetworkConnectionStateLastAck = NetworkConnectionStateKey.String("last_ack") - // listen - // Stability: development - NetworkConnectionStateListen = NetworkConnectionStateKey.String("listen") - // syn_received - // Stability: development - NetworkConnectionStateSynReceived = NetworkConnectionStateKey.String("syn_received") - // syn_sent - // Stability: development - NetworkConnectionStateSynSent = NetworkConnectionStateKey.String("syn_sent") - // time_wait - // Stability: development - NetworkConnectionStateTimeWait = NetworkConnectionStateKey.String("time_wait") -) - -// Enum values for network.connection.subtype -var ( - // GPRS - // Stability: development - NetworkConnectionSubtypeGprs = NetworkConnectionSubtypeKey.String("gprs") - // EDGE - // Stability: development - NetworkConnectionSubtypeEdge = NetworkConnectionSubtypeKey.String("edge") - // UMTS - // Stability: development - NetworkConnectionSubtypeUmts = NetworkConnectionSubtypeKey.String("umts") - // CDMA - // Stability: development - NetworkConnectionSubtypeCdma = NetworkConnectionSubtypeKey.String("cdma") - // EVDO Rel. 0 - // Stability: development - NetworkConnectionSubtypeEvdo0 = NetworkConnectionSubtypeKey.String("evdo_0") - // EVDO Rev. A - // Stability: development - NetworkConnectionSubtypeEvdoA = NetworkConnectionSubtypeKey.String("evdo_a") - // CDMA2000 1XRTT - // Stability: development - NetworkConnectionSubtypeCdma20001xrtt = NetworkConnectionSubtypeKey.String("cdma2000_1xrtt") - // HSDPA - // Stability: development - NetworkConnectionSubtypeHsdpa = NetworkConnectionSubtypeKey.String("hsdpa") - // HSUPA - // Stability: development - NetworkConnectionSubtypeHsupa = NetworkConnectionSubtypeKey.String("hsupa") - // HSPA - // Stability: development - NetworkConnectionSubtypeHspa = NetworkConnectionSubtypeKey.String("hspa") - // IDEN - // Stability: development - NetworkConnectionSubtypeIden = NetworkConnectionSubtypeKey.String("iden") - // EVDO Rev. B - // Stability: development - NetworkConnectionSubtypeEvdoB = NetworkConnectionSubtypeKey.String("evdo_b") - // LTE - // Stability: development - NetworkConnectionSubtypeLte = NetworkConnectionSubtypeKey.String("lte") - // EHRPD - // Stability: development - NetworkConnectionSubtypeEhrpd = NetworkConnectionSubtypeKey.String("ehrpd") - // HSPAP - // Stability: development - NetworkConnectionSubtypeHspap = NetworkConnectionSubtypeKey.String("hspap") - // GSM - // Stability: development - NetworkConnectionSubtypeGsm = NetworkConnectionSubtypeKey.String("gsm") - // TD-SCDMA - // Stability: development - NetworkConnectionSubtypeTdScdma = NetworkConnectionSubtypeKey.String("td_scdma") - // IWLAN - // Stability: development - NetworkConnectionSubtypeIwlan = NetworkConnectionSubtypeKey.String("iwlan") - // 5G NR (New Radio) - // Stability: development - NetworkConnectionSubtypeNr = NetworkConnectionSubtypeKey.String("nr") - // 5G NRNSA (New Radio Non-Standalone) - // Stability: development - NetworkConnectionSubtypeNrnsa = NetworkConnectionSubtypeKey.String("nrnsa") - // LTE CA - // Stability: development - NetworkConnectionSubtypeLteCa = NetworkConnectionSubtypeKey.String("lte_ca") -) - -// Enum values for network.connection.type -var ( - // wifi - // Stability: development - NetworkConnectionTypeWifi = NetworkConnectionTypeKey.String("wifi") - // wired - // Stability: development - NetworkConnectionTypeWired = NetworkConnectionTypeKey.String("wired") - // cell - // Stability: development - NetworkConnectionTypeCell = NetworkConnectionTypeKey.String("cell") - // unavailable - // Stability: development - NetworkConnectionTypeUnavailable = NetworkConnectionTypeKey.String("unavailable") - // unknown - // Stability: development - NetworkConnectionTypeUnknown = NetworkConnectionTypeKey.String("unknown") -) - -// Enum values for network.io.direction -var ( - // transmit - // Stability: development - NetworkIODirectionTransmit = NetworkIODirectionKey.String("transmit") - // receive - // Stability: development - NetworkIODirectionReceive = NetworkIODirectionKey.String("receive") -) - -// Enum values for network.transport -var ( - // TCP - // Stability: stable - NetworkTransportTCP = NetworkTransportKey.String("tcp") - // UDP - // Stability: stable - NetworkTransportUDP = NetworkTransportKey.String("udp") - // Named or anonymous pipe. - // Stability: stable - NetworkTransportPipe = NetworkTransportKey.String("pipe") - // Unix domain socket - // Stability: stable - NetworkTransportUnix = NetworkTransportKey.String("unix") - // QUIC - // Stability: stable - NetworkTransportQUIC = NetworkTransportKey.String("quic") -) - -// Enum values for network.type -var ( - // IPv4 - // Stability: stable - NetworkTypeIPv4 = NetworkTypeKey.String("ipv4") - // IPv6 - // Stability: stable - NetworkTypeIPv6 = NetworkTypeKey.String("ipv6") -) - -// Namespace: nfs -const ( - // NfsOperationNameKey is the attribute Key conforming to the - // "nfs.operation.name" semantic conventions. It represents the NFSv4+ operation - // name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "OPEN", "READ", "GETATTR" - NfsOperationNameKey = attribute.Key("nfs.operation.name") - - // NfsServerRepcacheStatusKey is the attribute Key conforming to the - // "nfs.server.repcache.status" semantic conventions. It represents the linux: - // one of "hit" (NFSD_STATS_RC_HITS), "miss" (NFSD_STATS_RC_MISSES), or - // "nocache" (NFSD_STATS_RC_NOCACHE -- uncacheable). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: hit - NfsServerRepcacheStatusKey = attribute.Key("nfs.server.repcache.status") -) - -// NfsOperationName returns an attribute KeyValue conforming to the -// "nfs.operation.name" semantic conventions. It represents the NFSv4+ operation -// name. -func NfsOperationName(val string) attribute.KeyValue { - return NfsOperationNameKey.String(val) -} - -// NfsServerRepcacheStatus returns an attribute KeyValue conforming to the -// "nfs.server.repcache.status" semantic conventions. It represents the linux: -// one of "hit" (NFSD_STATS_RC_HITS), "miss" (NFSD_STATS_RC_MISSES), or "nocache" -// (NFSD_STATS_RC_NOCACHE -- uncacheable). -func NfsServerRepcacheStatus(val string) attribute.KeyValue { - return NfsServerRepcacheStatusKey.String(val) -} - -// Namespace: oci -const ( - // OCIManifestDigestKey is the attribute Key conforming to the - // "oci.manifest.digest" semantic conventions. It represents the digest of the - // OCI image manifest. For container images specifically is the digest by which - // the container image is known. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "sha256:e4ca62c0d62f3e886e684806dfe9d4e0cda60d54986898173c1083856cfda0f4" - // Note: Follows [OCI Image Manifest Specification], and specifically the - // [Digest property]. - // An example can be found in [Example Image Manifest]. - // - // [OCI Image Manifest Specification]: https://github.com/opencontainers/image-spec/blob/main/manifest.md - // [Digest property]: https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests - // [Example Image Manifest]: https://github.com/opencontainers/image-spec/blob/main/manifest.md#example-image-manifest - OCIManifestDigestKey = attribute.Key("oci.manifest.digest") -) - -// OCIManifestDigest returns an attribute KeyValue conforming to the -// "oci.manifest.digest" semantic conventions. It represents the digest of the -// OCI image manifest. For container images specifically is the digest by which -// the container image is known. -func OCIManifestDigest(val string) attribute.KeyValue { - return OCIManifestDigestKey.String(val) -} - -// Namespace: onc_rpc -const ( - // OncRPCProcedureNameKey is the attribute Key conforming to the - // "onc_rpc.procedure.name" semantic conventions. It represents the ONC/Sun RPC - // procedure name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "OPEN", "READ", "GETATTR" - OncRPCProcedureNameKey = attribute.Key("onc_rpc.procedure.name") - - // OncRPCProcedureNumberKey is the attribute Key conforming to the - // "onc_rpc.procedure.number" semantic conventions. It represents the ONC/Sun - // RPC procedure number. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - OncRPCProcedureNumberKey = attribute.Key("onc_rpc.procedure.number") - - // OncRPCProgramNameKey is the attribute Key conforming to the - // "onc_rpc.program.name" semantic conventions. It represents the ONC/Sun RPC - // program name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "portmapper", "nfs" - OncRPCProgramNameKey = attribute.Key("onc_rpc.program.name") - - // OncRPCVersionKey is the attribute Key conforming to the "onc_rpc.version" - // semantic conventions. It represents the ONC/Sun RPC program version. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - OncRPCVersionKey = attribute.Key("onc_rpc.version") -) - -// OncRPCProcedureName returns an attribute KeyValue conforming to the -// "onc_rpc.procedure.name" semantic conventions. It represents the ONC/Sun RPC -// procedure name. -func OncRPCProcedureName(val string) attribute.KeyValue { - return OncRPCProcedureNameKey.String(val) -} - -// OncRPCProcedureNumber returns an attribute KeyValue conforming to the -// "onc_rpc.procedure.number" semantic conventions. It represents the ONC/Sun RPC -// procedure number. -func OncRPCProcedureNumber(val int) attribute.KeyValue { - return OncRPCProcedureNumberKey.Int(val) -} - -// OncRPCProgramName returns an attribute KeyValue conforming to the -// "onc_rpc.program.name" semantic conventions. It represents the ONC/Sun RPC -// program name. -func OncRPCProgramName(val string) attribute.KeyValue { - return OncRPCProgramNameKey.String(val) -} - -// OncRPCVersion returns an attribute KeyValue conforming to the -// "onc_rpc.version" semantic conventions. It represents the ONC/Sun RPC program -// version. -func OncRPCVersion(val int) attribute.KeyValue { - return OncRPCVersionKey.Int(val) -} - -// Namespace: openai -const ( - // OpenAIAPITypeKey is the attribute Key conforming to the "openai.api.type" - // semantic conventions. It represents the type of OpenAI API being used. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - OpenAIAPITypeKey = attribute.Key("openai.api.type") - - // OpenAIRequestServiceTierKey is the attribute Key conforming to the - // "openai.request.service_tier" semantic conventions. It represents the service - // tier requested. May be a specific tier, default, or auto. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "auto", "default" - OpenAIRequestServiceTierKey = attribute.Key("openai.request.service_tier") - - // OpenAIResponseServiceTierKey is the attribute Key conforming to the - // "openai.response.service_tier" semantic conventions. It represents the - // service tier used for the response. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "scale", "default" - OpenAIResponseServiceTierKey = attribute.Key("openai.response.service_tier") - - // OpenAIResponseSystemFingerprintKey is the attribute Key conforming to the - // "openai.response.system_fingerprint" semantic conventions. It represents a - // fingerprint to track any eventual change in the Generative AI environment. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "fp_44709d6fcb" - OpenAIResponseSystemFingerprintKey = attribute.Key("openai.response.system_fingerprint") -) - -// OpenAIResponseServiceTier returns an attribute KeyValue conforming to the -// "openai.response.service_tier" semantic conventions. It represents the service -// tier used for the response. -func OpenAIResponseServiceTier(val string) attribute.KeyValue { - return OpenAIResponseServiceTierKey.String(val) -} - -// OpenAIResponseSystemFingerprint returns an attribute KeyValue conforming to -// the "openai.response.system_fingerprint" semantic conventions. It represents a -// fingerprint to track any eventual change in the Generative AI environment. -func OpenAIResponseSystemFingerprint(val string) attribute.KeyValue { - return OpenAIResponseSystemFingerprintKey.String(val) -} - -// Enum values for openai.api.type -var ( - // The OpenAI [Chat Completions API]. - // Stability: development - // - // [Chat Completions API]: https://developers.openai.com/api/reference/chat-completions/overview - OpenAIAPITypeChatCompletions = OpenAIAPITypeKey.String("chat_completions") - // The OpenAI [Responses API]. - // Stability: development - // - // [Responses API]: https://developers.openai.com/api/reference/responses/overview - OpenAIAPITypeResponses = OpenAIAPITypeKey.String("responses") -) - -// Enum values for openai.request.service_tier -var ( - // The system will utilize scale tier credits until they are exhausted. - // Stability: development - OpenAIRequestServiceTierAuto = OpenAIRequestServiceTierKey.String("auto") - // The system will utilize the default scale tier. - // Stability: development - OpenAIRequestServiceTierDefault = OpenAIRequestServiceTierKey.String("default") -) - -// Namespace: openshift -const ( - // OpenShiftClusterquotaNameKey is the attribute Key conforming to the - // "openshift.clusterquota.name" semantic conventions. It represents the name of - // the cluster quota. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "opentelemetry" - OpenShiftClusterquotaNameKey = attribute.Key("openshift.clusterquota.name") - - // OpenShiftClusterquotaUIDKey is the attribute Key conforming to the - // "openshift.clusterquota.uid" semantic conventions. It represents the UID of - // the cluster quota. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "275ecb36-5aa8-4c2a-9c47-d8bb681b9aff" - OpenShiftClusterquotaUIDKey = attribute.Key("openshift.clusterquota.uid") -) - -// OpenShiftClusterquotaName returns an attribute KeyValue conforming to the -// "openshift.clusterquota.name" semantic conventions. It represents the name of -// the cluster quota. -func OpenShiftClusterquotaName(val string) attribute.KeyValue { - return OpenShiftClusterquotaNameKey.String(val) -} - -// OpenShiftClusterquotaUID returns an attribute KeyValue conforming to the -// "openshift.clusterquota.uid" semantic conventions. It represents the UID of -// the cluster quota. -func OpenShiftClusterquotaUID(val string) attribute.KeyValue { - return OpenShiftClusterquotaUIDKey.String(val) -} - -// Namespace: opentracing -const ( - // OpenTracingRefTypeKey is the attribute Key conforming to the - // "opentracing.ref_type" semantic conventions. It represents the parent-child - // Reference type. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: The causal relationship between a child Span and a parent Span. - OpenTracingRefTypeKey = attribute.Key("opentracing.ref_type") -) - -// Enum values for opentracing.ref_type -var ( - // The parent Span depends on the child Span in some capacity - // Stability: development - OpenTracingRefTypeChildOf = OpenTracingRefTypeKey.String("child_of") - // The parent Span doesn't depend in any way on the result of the child Span - // Stability: development - OpenTracingRefTypeFollowsFrom = OpenTracingRefTypeKey.String("follows_from") -) - -// Namespace: oracle -const ( - // OracleDBDomainKey is the attribute Key conforming to the "oracle.db.domain" - // semantic conventions. It represents the database domain associated with the - // connection. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "example.com", "corp.internal", "prod.db.local" - // Note: This attribute SHOULD be set to the value of the `DB_DOMAIN` - // initialization parameter, - // as exposed in `v$parameter`. `DB_DOMAIN` defines the domain portion of the - // global - // database name and SHOULD be configured when a database is, or may become, - // part of a - // distributed environment. Its value consists of one or more valid identifiers - // (alphanumeric ASCII characters) separated by periods. - OracleDBDomainKey = attribute.Key("oracle.db.domain") - - // OracleDBInstanceNameKey is the attribute Key conforming to the - // "oracle.db.instance.name" semantic conventions. It represents the instance - // name associated with the connection in an Oracle Real Application Clusters - // environment. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ORCL1", "ORCL2", "ORCL3" - // Note: There can be multiple instances associated with a single database - // service. It indicates the - // unique instance name to which the connection is currently bound. For non-RAC - // databases, this value - // defaults to the `oracle.db.name`. - OracleDBInstanceNameKey = attribute.Key("oracle.db.instance.name") - - // OracleDBNameKey is the attribute Key conforming to the "oracle.db.name" - // semantic conventions. It represents the database name associated with the - // connection. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ORCL1", "FREE" - // Note: This attribute SHOULD be set to the value of the parameter `DB_NAME` - // exposed in `v$parameter`. - OracleDBNameKey = attribute.Key("oracle.db.name") - - // OracleDBPdbKey is the attribute Key conforming to the "oracle.db.pdb" - // semantic conventions. It represents the pluggable database (PDB) name - // associated with the connection. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "PDB1", "FREEPDB" - // Note: This attribute SHOULD reflect the PDB that the session is currently - // connected to. - // If instrumentation cannot reliably obtain the active PDB name for each - // operation - // without issuing an additional query (such as `SELECT SYS_CONTEXT`), it is - // RECOMMENDED to fall back to the PDB name specified at connection - // establishment. - OracleDBPdbKey = attribute.Key("oracle.db.pdb") - - // OracleDBServiceKey is the attribute Key conforming to the "oracle.db.service" - // semantic conventions. It represents the service name currently associated - // with the database connection. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "order-processing-service", "db_low.adb.oraclecloud.com", - // "db_high.adb.oraclecloud.com" - // Note: The effective service name for a connection can change during its - // lifetime, - // for example after executing sql, `ALTER SESSION`. If an instrumentation - // cannot reliably - // obtain the current service name for each operation without issuing an - // additional - // query (such as `SELECT SYS_CONTEXT`), it is RECOMMENDED to fall back to the - // service name originally provided at connection establishment. - OracleDBServiceKey = attribute.Key("oracle.db.service") -) - -// OracleDBDomain returns an attribute KeyValue conforming to the -// "oracle.db.domain" semantic conventions. It represents the database domain -// associated with the connection. -func OracleDBDomain(val string) attribute.KeyValue { - return OracleDBDomainKey.String(val) -} - -// OracleDBInstanceName returns an attribute KeyValue conforming to the -// "oracle.db.instance.name" semantic conventions. It represents the instance -// name associated with the connection in an Oracle Real Application Clusters -// environment. -func OracleDBInstanceName(val string) attribute.KeyValue { - return OracleDBInstanceNameKey.String(val) -} - -// OracleDBName returns an attribute KeyValue conforming to the "oracle.db.name" -// semantic conventions. It represents the database name associated with the -// connection. -func OracleDBName(val string) attribute.KeyValue { - return OracleDBNameKey.String(val) -} - -// OracleDBPdb returns an attribute KeyValue conforming to the "oracle.db.pdb" -// semantic conventions. It represents the pluggable database (PDB) name -// associated with the connection. -func OracleDBPdb(val string) attribute.KeyValue { - return OracleDBPdbKey.String(val) -} - -// OracleDBService returns an attribute KeyValue conforming to the -// "oracle.db.service" semantic conventions. It represents the service name -// currently associated with the database connection. -func OracleDBService(val string) attribute.KeyValue { - return OracleDBServiceKey.String(val) -} - -// Namespace: oracle_cloud -const ( - // OracleCloudRealmKey is the attribute Key conforming to the - // "oracle_cloud.realm" semantic conventions. It represents the OCI realm - // identifier that indicates the isolated partition in which the tenancy and its - // resources reside. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "oc1", "oc2" - // Note: See [OCI documentation on realms] - // - // [OCI documentation on realms]: https://docs.oracle.com/iaas/Content/General/Concepts/regions.htm - OracleCloudRealmKey = attribute.Key("oracle_cloud.realm") -) - -// OracleCloudRealm returns an attribute KeyValue conforming to the -// "oracle_cloud.realm" semantic conventions. It represents the OCI realm -// identifier that indicates the isolated partition in which the tenancy and its -// resources reside. -func OracleCloudRealm(val string) attribute.KeyValue { - return OracleCloudRealmKey.String(val) -} - -// Namespace: os -const ( - // OSBuildIDKey is the attribute Key conforming to the "os.build_id" semantic - // conventions. It represents the unique identifier for a particular build or - // compilation of the operating system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "TQ3C.230805.001.B2", "20E247", "22621" - OSBuildIDKey = attribute.Key("os.build_id") - - // OSDescriptionKey is the attribute Key conforming to the "os.description" - // semantic conventions. It represents the human readable (not intended to be - // parsed) OS version information, like e.g. reported by `ver` or - // `lsb_release -a` commands. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Microsoft Windows [Version 10.0.18363.778]", "Ubuntu 18.04.1 LTS" - OSDescriptionKey = attribute.Key("os.description") - - // OSNameKey is the attribute Key conforming to the "os.name" semantic - // conventions. It represents the human readable operating system name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "iOS", "Android", "Ubuntu" - OSNameKey = attribute.Key("os.name") - - // OSTypeKey is the attribute Key conforming to the "os.type" semantic - // conventions. It represents the operating system type. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - OSTypeKey = attribute.Key("os.type") - - // OSVersionKey is the attribute Key conforming to the "os.version" semantic - // conventions. It represents the version string of the operating system as - // defined in [Version Attributes]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "14.2.1", "18.04.1" - // - // [Version Attributes]: /docs/resource/README.md#version-attributes - OSVersionKey = attribute.Key("os.version") -) - -// OSBuildID returns an attribute KeyValue conforming to the "os.build_id" -// semantic conventions. It represents the unique identifier for a particular -// build or compilation of the operating system. -func OSBuildID(val string) attribute.KeyValue { - return OSBuildIDKey.String(val) -} - -// OSDescription returns an attribute KeyValue conforming to the "os.description" -// semantic conventions. It represents the human readable (not intended to be -// parsed) OS version information, like e.g. reported by `ver` or -// `lsb_release -a` commands. -func OSDescription(val string) attribute.KeyValue { - return OSDescriptionKey.String(val) -} - -// OSName returns an attribute KeyValue conforming to the "os.name" semantic -// conventions. It represents the human readable operating system name. -func OSName(val string) attribute.KeyValue { - return OSNameKey.String(val) -} - -// OSVersion returns an attribute KeyValue conforming to the "os.version" -// semantic conventions. It represents the version string of the operating system -// as defined in [Version Attributes]. -// -// [Version Attributes]: /docs/resource/README.md#version-attributes -func OSVersion(val string) attribute.KeyValue { - return OSVersionKey.String(val) -} - -// Enum values for os.type -var ( - // Microsoft Windows - // Stability: development - OSTypeWindows = OSTypeKey.String("windows") - // Linux - // Stability: development - OSTypeLinux = OSTypeKey.String("linux") - // Apple Darwin - // Stability: development - OSTypeDarwin = OSTypeKey.String("darwin") - // FreeBSD - // Stability: development - OSTypeFreeBSD = OSTypeKey.String("freebsd") - // NetBSD - // Stability: development - OSTypeNetBSD = OSTypeKey.String("netbsd") - // OpenBSD - // Stability: development - OSTypeOpenBSD = OSTypeKey.String("openbsd") - // DragonFly BSD - // Stability: development - OSTypeDragonflyBSD = OSTypeKey.String("dragonflybsd") - // HP-UX (Hewlett Packard Unix) - // Stability: development - OSTypeHPUX = OSTypeKey.String("hpux") - // AIX (Advanced Interactive eXecutive) - // Stability: development - OSTypeAIX = OSTypeKey.String("aix") - // SunOS, Oracle Solaris - // Stability: development - OSTypeSolaris = OSTypeKey.String("solaris") - // IBM z/OS - // Stability: development - OSTypeZOS = OSTypeKey.String("zos") -) - -// Namespace: otel -const ( - // OTelComponentNameKey is the attribute Key conforming to the - // "otel.component.name" semantic conventions. It represents a name uniquely - // identifying the instance of the OpenTelemetry component within its containing - // SDK instance. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "otlp_grpc_span_exporter/0", "custom-name" - // Note: Implementations SHOULD ensure a low cardinality for this attribute, - // even across application or SDK restarts. - // E.g. implementations MUST NOT use UUIDs as values for this attribute. - // - // Implementations MAY achieve these goals by following a - // `/` pattern, e.g. - // `batching_span_processor/0`. - // Hereby `otel.component.type` refers to the corresponding attribute value of - // the component. - // - // The value of `instance-counter` MAY be automatically assigned by the - // component and uniqueness within the enclosing SDK instance MUST be - // guaranteed. - // For example, `` MAY be implemented by using a monotonically - // increasing counter (starting with `0`), which is incremented every time an - // instance of the given component type is started. - // - // With this implementation, for example the first Batching Span Processor would - // have `batching_span_processor/0` - // as `otel.component.name`, the second one `batching_span_processor/1` and so - // on. - // These values will therefore be reused in the case of an application restart. - OTelComponentNameKey = attribute.Key("otel.component.name") - - // OTelComponentTypeKey is the attribute Key conforming to the - // "otel.component.type" semantic conventions. It represents a name identifying - // the type of the OpenTelemetry component. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "batching_span_processor", "com.example.MySpanExporter" - // Note: If none of the standardized values apply, implementations SHOULD use - // the language-defined name of the type. - // E.g. for Java the fully qualified classname SHOULD be used in this case. - OTelComponentTypeKey = attribute.Key("otel.component.type") - - // OTelEventNameKey is the attribute Key conforming to the "otel.event.name" - // semantic conventions. It represents the identifies the class / type of event. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "browser.mouse.click", "device.app.lifecycle" - // Note: This attribute SHOULD be used by non-OTLP exporters when destination - // does not support `EventName` or equivalent field. This attribute MAY be used - // by applications using existing logging libraries so that it can be used to - // set the `EventName` field by Collector or SDK components. - OTelEventNameKey = attribute.Key("otel.event.name") - - // OTelScopeNameKey is the attribute Key conforming to the "otel.scope.name" - // semantic conventions. It represents the name of the instrumentation scope - ( - // `InstrumentationScope.Name` in OTLP). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "io.opentelemetry.contrib.mongodb" - OTelScopeNameKey = attribute.Key("otel.scope.name") - - // OTelScopeSchemaURLKey is the attribute Key conforming to the - // "otel.scope.schema_url" semantic conventions. It represents the schema URL of - // the instrumentation scope. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "https://opentelemetry.io/schemas/1.31.0" - OTelScopeSchemaURLKey = attribute.Key("otel.scope.schema_url") - - // OTelScopeVersionKey is the attribute Key conforming to the - // "otel.scope.version" semantic conventions. It represents the version of the - // instrumentation scope - (`InstrumentationScope.Version` in OTLP). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "1.0.0" - OTelScopeVersionKey = attribute.Key("otel.scope.version") - - // OTelSpanParentOriginKey is the attribute Key conforming to the - // "otel.span.parent.origin" semantic conventions. It represents the determines - // whether the span has a parent span, and if so, - // [whether it is a remote parent]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [whether it is a remote parent]: https://opentelemetry.io/docs/specs/otel/trace/api/#isremote - OTelSpanParentOriginKey = attribute.Key("otel.span.parent.origin") - - // OTelSpanSamplingResultKey is the attribute Key conforming to the - // "otel.span.sampling_result" semantic conventions. It represents the result - // value of the sampler for this span. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - OTelSpanSamplingResultKey = attribute.Key("otel.span.sampling_result") - - // OTelStatusCodeKey is the attribute Key conforming to the "otel.status_code" - // semantic conventions. It represents the name of the code, either "OK" or - // "ERROR". MUST NOT be set if the status code is UNSET. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: - OTelStatusCodeKey = attribute.Key("otel.status_code") - - // OTelStatusDescriptionKey is the attribute Key conforming to the - // "otel.status_description" semantic conventions. It represents the description - // of the Status if it has a value, otherwise not set. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "resource not found" - OTelStatusDescriptionKey = attribute.Key("otel.status_description") -) - -// OTelComponentName returns an attribute KeyValue conforming to the -// "otel.component.name" semantic conventions. It represents a name uniquely -// identifying the instance of the OpenTelemetry component within its containing -// SDK instance. -func OTelComponentName(val string) attribute.KeyValue { - return OTelComponentNameKey.String(val) -} - -// OTelEventName returns an attribute KeyValue conforming to the -// "otel.event.name" semantic conventions. It represents the identifies the class -// / type of event. -func OTelEventName(val string) attribute.KeyValue { - return OTelEventNameKey.String(val) -} - -// OTelScopeName returns an attribute KeyValue conforming to the -// "otel.scope.name" semantic conventions. It represents the name of the -// instrumentation scope - (`InstrumentationScope.Name` in OTLP). -func OTelScopeName(val string) attribute.KeyValue { - return OTelScopeNameKey.String(val) -} - -// OTelScopeSchemaURL returns an attribute KeyValue conforming to the -// "otel.scope.schema_url" semantic conventions. It represents the schema URL of -// the instrumentation scope. -func OTelScopeSchemaURL(val string) attribute.KeyValue { - return OTelScopeSchemaURLKey.String(val) -} - -// OTelScopeVersion returns an attribute KeyValue conforming to the -// "otel.scope.version" semantic conventions. It represents the version of the -// instrumentation scope - (`InstrumentationScope.Version` in OTLP). -func OTelScopeVersion(val string) attribute.KeyValue { - return OTelScopeVersionKey.String(val) -} - -// OTelStatusDescription returns an attribute KeyValue conforming to the -// "otel.status_description" semantic conventions. It represents the description -// of the Status if it has a value, otherwise not set. -func OTelStatusDescription(val string) attribute.KeyValue { - return OTelStatusDescriptionKey.String(val) -} - -// Enum values for otel.component.type -var ( - // The builtin SDK batching span processor - // - // Stability: development - OTelComponentTypeBatchingSpanProcessor = OTelComponentTypeKey.String("batching_span_processor") - // The builtin SDK simple span processor - // - // Stability: development - OTelComponentTypeSimpleSpanProcessor = OTelComponentTypeKey.String("simple_span_processor") - // The builtin SDK batching log record processor - // - // Stability: development - OTelComponentTypeBatchingLogProcessor = OTelComponentTypeKey.String("batching_log_processor") - // The builtin SDK simple log record processor - // - // Stability: development - OTelComponentTypeSimpleLogProcessor = OTelComponentTypeKey.String("simple_log_processor") - // OTLP span exporter over gRPC with protobuf serialization - // - // Stability: development - OTelComponentTypeOtlpGRPCSpanExporter = OTelComponentTypeKey.String("otlp_grpc_span_exporter") - // OTLP span exporter over HTTP with protobuf serialization - // - // Stability: development - OTelComponentTypeOtlpHTTPSpanExporter = OTelComponentTypeKey.String("otlp_http_span_exporter") - // OTLP span exporter over HTTP with JSON serialization - // - // Stability: development - OTelComponentTypeOtlpHTTPJSONSpanExporter = OTelComponentTypeKey.String("otlp_http_json_span_exporter") - // Zipkin span exporter over HTTP - // - // Stability: development - OTelComponentTypeZipkinHTTPSpanExporter = OTelComponentTypeKey.String("zipkin_http_span_exporter") - // OTLP log record exporter over gRPC with protobuf serialization - // - // Stability: development - OTelComponentTypeOtlpGRPCLogExporter = OTelComponentTypeKey.String("otlp_grpc_log_exporter") - // OTLP log record exporter over HTTP with protobuf serialization - // - // Stability: development - OTelComponentTypeOtlpHTTPLogExporter = OTelComponentTypeKey.String("otlp_http_log_exporter") - // OTLP log record exporter over HTTP with JSON serialization - // - // Stability: development - OTelComponentTypeOtlpHTTPJSONLogExporter = OTelComponentTypeKey.String("otlp_http_json_log_exporter") - // The builtin SDK periodically exporting metric reader - // - // Stability: development - OTelComponentTypePeriodicMetricReader = OTelComponentTypeKey.String("periodic_metric_reader") - // OTLP metric exporter over gRPC with protobuf serialization - // - // Stability: development - OTelComponentTypeOtlpGRPCMetricExporter = OTelComponentTypeKey.String("otlp_grpc_metric_exporter") - // OTLP metric exporter over HTTP with protobuf serialization - // - // Stability: development - OTelComponentTypeOtlpHTTPMetricExporter = OTelComponentTypeKey.String("otlp_http_metric_exporter") - // OTLP metric exporter over HTTP with JSON serialization - // - // Stability: development - OTelComponentTypeOtlpHTTPJSONMetricExporter = OTelComponentTypeKey.String("otlp_http_json_metric_exporter") - // Prometheus metric exporter over HTTP with the default text-based format - // - // Stability: development - OTelComponentTypePrometheusHTTPTextMetricExporter = OTelComponentTypeKey.String("prometheus_http_text_metric_exporter") -) - -// Enum values for otel.span.parent.origin -var ( - // The span does not have a parent, it is a root span - // Stability: development - OTelSpanParentOriginNone = OTelSpanParentOriginKey.String("none") - // The span has a parent and the parent's span context [isRemote()] is false - // Stability: development - // - // [isRemote()]: https://opentelemetry.io/docs/specs/otel/trace/api/#isremote - OTelSpanParentOriginLocal = OTelSpanParentOriginKey.String("local") - // The span has a parent and the parent's span context [isRemote()] is true - // Stability: development - // - // [isRemote()]: https://opentelemetry.io/docs/specs/otel/trace/api/#isremote - OTelSpanParentOriginRemote = OTelSpanParentOriginKey.String("remote") -) - -// Enum values for otel.span.sampling_result -var ( - // The span is not sampled and not recording - // Stability: development - OTelSpanSamplingResultDrop = OTelSpanSamplingResultKey.String("DROP") - // The span is not sampled, but recording - // Stability: development - OTelSpanSamplingResultRecordOnly = OTelSpanSamplingResultKey.String("RECORD_ONLY") - // The span is sampled and recording - // Stability: development - OTelSpanSamplingResultRecordAndSample = OTelSpanSamplingResultKey.String("RECORD_AND_SAMPLE") -) - -// Enum values for otel.status_code -var ( - // The operation has been validated by an Application developer or Operator to - // have completed successfully. - // Stability: stable - OTelStatusCodeOk = OTelStatusCodeKey.String("OK") - // The operation contains an error. - // Stability: stable - OTelStatusCodeError = OTelStatusCodeKey.String("ERROR") -) - -// Namespace: pprof -const ( - // PprofLocationIsFoldedKey is the attribute Key conforming to the - // "pprof.location.is_folded" semantic conventions. It represents the provides - // an indication that multiple symbols map to this location's address, for - // example due to identical code folding by the linker. In that case the line - // information represents one of the multiple symbols. This field must be - // recomputed when the symbolization state of the profile changes. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - PprofLocationIsFoldedKey = attribute.Key("pprof.location.is_folded") - - // PprofMappingHasFilenamesKey is the attribute Key conforming to the - // "pprof.mapping.has_filenames" semantic conventions. It represents the - // indicates that there are filenames related to this mapping. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - PprofMappingHasFilenamesKey = attribute.Key("pprof.mapping.has_filenames") - - // PprofMappingHasFunctionsKey is the attribute Key conforming to the - // "pprof.mapping.has_functions" semantic conventions. It represents the - // indicates that there are functions related to this mapping. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - PprofMappingHasFunctionsKey = attribute.Key("pprof.mapping.has_functions") - - // PprofMappingHasInlineFramesKey is the attribute Key conforming to the - // "pprof.mapping.has_inline_frames" semantic conventions. It represents the - // indicates that there are inline frames related to this mapping. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - PprofMappingHasInlineFramesKey = attribute.Key("pprof.mapping.has_inline_frames") - - // PprofMappingHasLineNumbersKey is the attribute Key conforming to the - // "pprof.mapping.has_line_numbers" semantic conventions. It represents the - // indicates that there are line numbers related to this mapping. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - PprofMappingHasLineNumbersKey = attribute.Key("pprof.mapping.has_line_numbers") - - // PprofProfileCommentKey is the attribute Key conforming to the - // "pprof.profile.comment" semantic conventions. It represents the free-form - // text associated with the profile. This field should not be used to store any - // machine-readable information, it is only for human-friendly content. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "hello world", "bazinga" - PprofProfileCommentKey = attribute.Key("pprof.profile.comment") - - // PprofProfileDocURLKey is the attribute Key conforming to the - // "pprof.profile.doc_url" semantic conventions. It represents the documentation - // link for this profile type. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "http://pprof.example.com/cpu-profile.html" - // Note: The URL must be absolute and may be missing if the profile was - // generated by code that did not supply a link - PprofProfileDocURLKey = attribute.Key("pprof.profile.doc_url") - - // PprofProfileDropFramesKey is the attribute Key conforming to the - // "pprof.profile.drop_frames" semantic conventions. It represents the frames - // with Function.function_name fully matching the regexp will be dropped from - // the samples, along with their successors. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/foobar/" - PprofProfileDropFramesKey = attribute.Key("pprof.profile.drop_frames") - - // PprofProfileKeepFramesKey is the attribute Key conforming to the - // "pprof.profile.keep_frames" semantic conventions. It represents the frames - // with Function.function_name fully matching the regexp will be kept, even if - // it matches drop_frames. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/bazinga/" - PprofProfileKeepFramesKey = attribute.Key("pprof.profile.keep_frames") - - // PprofScopeDefaultSampleTypeKey is the attribute Key conforming to the - // "pprof.scope.default_sample_type" semantic conventions. It represents the - // records the pprof's default_sample_type in the original profile. Not set if - // the default sample type was missing. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "cpu" - // Note: This attribute, if present, MUST be set at the scope level - // (resource_profiles[].scope_profiles[].scope.attributes[]). - PprofScopeDefaultSampleTypeKey = attribute.Key("pprof.scope.default_sample_type") - - // PprofScopeSampleTypeOrderKey is the attribute Key conforming to the - // "pprof.scope.sample_type_order" semantic conventions. It represents the - // records the indexes of the sample types in the original profile. - // - // Type: int[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 3, 0, 1, 2 - // Note: This attribute, if present, MUST be set at the scope level - // (resource_profiles[].scope_profiles[].scope.attributes[]). - PprofScopeSampleTypeOrderKey = attribute.Key("pprof.scope.sample_type_order") -) - -// PprofLocationIsFolded returns an attribute KeyValue conforming to the -// "pprof.location.is_folded" semantic conventions. It represents the provides an -// indication that multiple symbols map to this location's address, for example -// due to identical code folding by the linker. In that case the line information -// represents one of the multiple symbols. This field must be recomputed when the -// symbolization state of the profile changes. -func PprofLocationIsFolded(val bool) attribute.KeyValue { - return PprofLocationIsFoldedKey.Bool(val) -} - -// PprofMappingHasFilenames returns an attribute KeyValue conforming to the -// "pprof.mapping.has_filenames" semantic conventions. It represents the -// indicates that there are filenames related to this mapping. -func PprofMappingHasFilenames(val bool) attribute.KeyValue { - return PprofMappingHasFilenamesKey.Bool(val) -} - -// PprofMappingHasFunctions returns an attribute KeyValue conforming to the -// "pprof.mapping.has_functions" semantic conventions. It represents the -// indicates that there are functions related to this mapping. -func PprofMappingHasFunctions(val bool) attribute.KeyValue { - return PprofMappingHasFunctionsKey.Bool(val) -} - -// PprofMappingHasInlineFrames returns an attribute KeyValue conforming to the -// "pprof.mapping.has_inline_frames" semantic conventions. It represents the -// indicates that there are inline frames related to this mapping. -func PprofMappingHasInlineFrames(val bool) attribute.KeyValue { - return PprofMappingHasInlineFramesKey.Bool(val) -} - -// PprofMappingHasLineNumbers returns an attribute KeyValue conforming to the -// "pprof.mapping.has_line_numbers" semantic conventions. It represents the -// indicates that there are line numbers related to this mapping. -func PprofMappingHasLineNumbers(val bool) attribute.KeyValue { - return PprofMappingHasLineNumbersKey.Bool(val) -} - -// PprofProfileComment returns an attribute KeyValue conforming to the -// "pprof.profile.comment" semantic conventions. It represents the free-form text -// associated with the profile. This field should not be used to store any -// machine-readable information, it is only for human-friendly content. -func PprofProfileComment(val ...string) attribute.KeyValue { - return PprofProfileCommentKey.StringSlice(val) -} - -// PprofProfileDocURL returns an attribute KeyValue conforming to the -// "pprof.profile.doc_url" semantic conventions. It represents the documentation -// link for this profile type. -func PprofProfileDocURL(val string) attribute.KeyValue { - return PprofProfileDocURLKey.String(val) -} - -// PprofProfileDropFrames returns an attribute KeyValue conforming to the -// "pprof.profile.drop_frames" semantic conventions. It represents the frames -// with Function.function_name fully matching the regexp will be dropped from the -// samples, along with their successors. -func PprofProfileDropFrames(val string) attribute.KeyValue { - return PprofProfileDropFramesKey.String(val) -} - -// PprofProfileKeepFrames returns an attribute KeyValue conforming to the -// "pprof.profile.keep_frames" semantic conventions. It represents the frames -// with Function.function_name fully matching the regexp will be kept, even if it -// matches drop_frames. -func PprofProfileKeepFrames(val string) attribute.KeyValue { - return PprofProfileKeepFramesKey.String(val) -} - -// PprofScopeDefaultSampleType returns an attribute KeyValue conforming to the -// "pprof.scope.default_sample_type" semantic conventions. It represents the -// records the pprof's default_sample_type in the original profile. Not set if -// the default sample type was missing. -func PprofScopeDefaultSampleType(val string) attribute.KeyValue { - return PprofScopeDefaultSampleTypeKey.String(val) -} - -// PprofScopeSampleTypeOrder returns an attribute KeyValue conforming to the -// "pprof.scope.sample_type_order" semantic conventions. It represents the -// records the indexes of the sample types in the original profile. -func PprofScopeSampleTypeOrder(val ...int) attribute.KeyValue { - return PprofScopeSampleTypeOrderKey.IntSlice(val) -} - -// Namespace: process -const ( - // ProcessArgsCountKey is the attribute Key conforming to the - // "process.args_count" semantic conventions. It represents the length of the - // process.command_args array. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 4 - // Note: This field can be useful for querying or performing bucket analysis on - // how many arguments were provided to start a process. More arguments may be an - // indication of suspicious activity. - ProcessArgsCountKey = attribute.Key("process.args_count") - - // ProcessCommandKey is the attribute Key conforming to the "process.command" - // semantic conventions. It represents the command used to launch the process - // (i.e. the command name). On Linux based systems, can be set to the zeroth - // string in `proc/[pid]/cmdline`. On Windows, can be set to the first parameter - // extracted from `GetCommandLineW`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "cmd/otelcol" - ProcessCommandKey = attribute.Key("process.command") - - // ProcessCommandArgsKey is the attribute Key conforming to the - // "process.command_args" semantic conventions. It represents the all the - // command arguments (including the command/executable itself) as received by - // the process. On Linux-based systems (and some other Unixoid systems - // supporting procfs), can be set according to the list of null-delimited - // strings extracted from `proc/[pid]/cmdline`. For libc-based executables, this - // would be the full argv vector passed to `main`. SHOULD NOT be collected by - // default unless there is sanitization that excludes sensitive data. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "cmd/otecol", "--config=config.yaml" - ProcessCommandArgsKey = attribute.Key("process.command_args") - - // ProcessCommandLineKey is the attribute Key conforming to the - // "process.command_line" semantic conventions. It represents the full command - // used to launch the process as a single string representing the full command. - // On Windows, can be set to the result of `GetCommandLineW`. Do not set this if - // you have to assemble it just for monitoring; use `process.command_args` - // instead. SHOULD NOT be collected by default unless there is sanitization that - // excludes sensitive data. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "C:\cmd\otecol --config="my directory\config.yaml"" - ProcessCommandLineKey = attribute.Key("process.command_line") - - // ProcessContextSwitchTypeKey is the attribute Key conforming to the - // "process.context_switch.type" semantic conventions. It represents the - // specifies whether the context switches for this data point were voluntary or - // involuntary. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - ProcessContextSwitchTypeKey = attribute.Key("process.context_switch.type") - - // ProcessCreationTimeKey is the attribute Key conforming to the - // "process.creation.time" semantic conventions. It represents the date and time - // the process was created, in ISO 8601 format. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2023-11-21T09:25:34.853Z" - ProcessCreationTimeKey = attribute.Key("process.creation.time") - - // ProcessExecutableBuildIDGNUKey is the attribute Key conforming to the - // "process.executable.build_id.gnu" semantic conventions. It represents the GNU - // build ID as found in the `.note.gnu.build-id` ELF section (hex string). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "c89b11207f6479603b0d49bf291c092c2b719293" - ProcessExecutableBuildIDGNUKey = attribute.Key("process.executable.build_id.gnu") - - // ProcessExecutableBuildIDGoKey is the attribute Key conforming to the - // "process.executable.build_id.go" semantic conventions. It represents the Go - // build ID as retrieved by `go tool buildid `. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "foh3mEXu7BLZjsN9pOwG/kATcXlYVCDEFouRMQed_/WwRFB1hPo9LBkekthSPG/x8hMC8emW2cCjXD0_1aY" - ProcessExecutableBuildIDGoKey = attribute.Key("process.executable.build_id.go") - - // ProcessExecutableBuildIDHtlhashKey is the attribute Key conforming to the - // "process.executable.build_id.htlhash" semantic conventions. It represents the - // profiling specific build ID for executables. See the OTel specification for - // Profiles for more information. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "600DCAFE4A110000F2BF38C493F5FB92" - ProcessExecutableBuildIDHtlhashKey = attribute.Key("process.executable.build_id.htlhash") - - // ProcessExecutableNameKey is the attribute Key conforming to the - // "process.executable.name" semantic conventions. It represents the name of the - // process executable. On Linux based systems, this SHOULD be set to the base - // name of the target of `/proc/[pid]/exe`. On Windows, this SHOULD be set to - // the base name of `GetProcessImageFileNameW`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "otelcol" - ProcessExecutableNameKey = attribute.Key("process.executable.name") - - // ProcessExecutablePathKey is the attribute Key conforming to the - // "process.executable.path" semantic conventions. It represents the full path - // to the process executable. On Linux based systems, can be set to the target - // of `proc/[pid]/exe`. On Windows, can be set to the result of - // `GetProcessImageFileNameW`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/usr/bin/cmd/otelcol" - ProcessExecutablePathKey = attribute.Key("process.executable.path") - - // ProcessExitCodeKey is the attribute Key conforming to the "process.exit.code" - // semantic conventions. It represents the exit code of the process. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 127 - ProcessExitCodeKey = attribute.Key("process.exit.code") - - // ProcessExitTimeKey is the attribute Key conforming to the "process.exit.time" - // semantic conventions. It represents the date and time the process exited, in - // ISO 8601 format. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2023-11-21T09:26:12.315Z" - ProcessExitTimeKey = attribute.Key("process.exit.time") - - // ProcessGroupLeaderPIDKey is the attribute Key conforming to the - // "process.group_leader.pid" semantic conventions. It represents the PID of the - // process's group leader. This is also the process group ID (PGID) of the - // process. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 23 - ProcessGroupLeaderPIDKey = attribute.Key("process.group_leader.pid") - - // ProcessInteractiveKey is the attribute Key conforming to the - // "process.interactive" semantic conventions. It represents the whether the - // process is connected to an interactive shell. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - ProcessInteractiveKey = attribute.Key("process.interactive") - - // ProcessLinuxCgroupKey is the attribute Key conforming to the - // "process.linux.cgroup" semantic conventions. It represents the control group - // associated with the process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1:name=systemd:/user.slice/user-1000.slice/session-3.scope", - // "0::/user.slice/user-1000.slice/user@1000.service/tmux-spawn-0267755b-4639-4a27-90ed-f19f88e53748.scope" - // Note: Control groups (cgroups) are a kernel feature used to organize and - // manage process resources. This attribute provides the path(s) to the - // cgroup(s) associated with the process, which should match the contents of the - // [/proc/[PID]/cgroup] file. - // - // [/proc/[PID]/cgroup]: https://man7.org/linux/man-pages/man7/cgroups.7.html - ProcessLinuxCgroupKey = attribute.Key("process.linux.cgroup") - - // ProcessOwnerKey is the attribute Key conforming to the "process.owner" - // semantic conventions. It represents the username of the user that owns the - // process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "root" - ProcessOwnerKey = attribute.Key("process.owner") - - // ProcessParentPIDKey is the attribute Key conforming to the - // "process.parent_pid" semantic conventions. It represents the parent Process - // identifier (PPID). - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 111 - ProcessParentPIDKey = attribute.Key("process.parent_pid") - - // ProcessPIDKey is the attribute Key conforming to the "process.pid" semantic - // conventions. It represents the process identifier (PID). - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1234 - ProcessPIDKey = attribute.Key("process.pid") - - // ProcessRealUserIDKey is the attribute Key conforming to the - // "process.real_user.id" semantic conventions. It represents the real user ID - // (RUID) of the process. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1000 - ProcessRealUserIDKey = attribute.Key("process.real_user.id") - - // ProcessRealUserNameKey is the attribute Key conforming to the - // "process.real_user.name" semantic conventions. It represents the username of - // the real user of the process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "operator" - ProcessRealUserNameKey = attribute.Key("process.real_user.name") - - // ProcessRuntimeDescriptionKey is the attribute Key conforming to the - // "process.runtime.description" semantic conventions. It represents an - // additional description about the runtime of the process, for example a - // specific vendor customization of the runtime environment. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0 - ProcessRuntimeDescriptionKey = attribute.Key("process.runtime.description") - - // ProcessRuntimeNameKey is the attribute Key conforming to the - // "process.runtime.name" semantic conventions. It represents the name of the - // runtime of this process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "OpenJDK Runtime Environment" - ProcessRuntimeNameKey = attribute.Key("process.runtime.name") - - // ProcessRuntimeVersionKey is the attribute Key conforming to the - // "process.runtime.version" semantic conventions. It represents the version of - // the runtime of this process, as returned by the runtime without modification. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 14.0.2 - ProcessRuntimeVersionKey = attribute.Key("process.runtime.version") - - // ProcessSavedUserIDKey is the attribute Key conforming to the - // "process.saved_user.id" semantic conventions. It represents the saved user ID - // (SUID) of the process. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1002 - ProcessSavedUserIDKey = attribute.Key("process.saved_user.id") - - // ProcessSavedUserNameKey is the attribute Key conforming to the - // "process.saved_user.name" semantic conventions. It represents the username of - // the saved user. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "operator" - ProcessSavedUserNameKey = attribute.Key("process.saved_user.name") - - // ProcessSessionLeaderPIDKey is the attribute Key conforming to the - // "process.session_leader.pid" semantic conventions. It represents the PID of - // the process's session leader. This is also the session ID (SID) of the - // process. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 14 - ProcessSessionLeaderPIDKey = attribute.Key("process.session_leader.pid") - - // ProcessStateKey is the attribute Key conforming to the "process.state" - // semantic conventions. It represents the process state, e.g., - // [Linux Process State Codes]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "running" - // - // [Linux Process State Codes]: https://man7.org/linux/man-pages/man1/ps.1.html#PROCESS_STATE_CODES - ProcessStateKey = attribute.Key("process.state") - - // ProcessTitleKey is the attribute Key conforming to the "process.title" - // semantic conventions. It represents the process title (proctitle). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "cat /etc/hostname", "xfce4-session", "bash" - // Note: In many Unix-like systems, process title (proctitle), is the string - // that represents the name or command line of a running process, displayed by - // system monitoring tools like ps, top, and htop. - ProcessTitleKey = attribute.Key("process.title") - - // ProcessUserIDKey is the attribute Key conforming to the "process.user.id" - // semantic conventions. It represents the effective user ID (EUID) of the - // process. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 1001 - ProcessUserIDKey = attribute.Key("process.user.id") - - // ProcessUserNameKey is the attribute Key conforming to the "process.user.name" - // semantic conventions. It represents the username of the effective user of the - // process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "root" - ProcessUserNameKey = attribute.Key("process.user.name") - - // ProcessVpidKey is the attribute Key conforming to the "process.vpid" semantic - // conventions. It represents the virtual process identifier. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 12 - // Note: The process ID within a PID namespace. This is not necessarily unique - // across all processes on the host but it is unique within the process - // namespace that the process exists within. - ProcessVpidKey = attribute.Key("process.vpid") - - // ProcessWorkingDirectoryKey is the attribute Key conforming to the - // "process.working_directory" semantic conventions. It represents the working - // directory of the process. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/root" - ProcessWorkingDirectoryKey = attribute.Key("process.working_directory") -) - -// ProcessArgsCount returns an attribute KeyValue conforming to the -// "process.args_count" semantic conventions. It represents the length of the -// process.command_args array. -func ProcessArgsCount(val int) attribute.KeyValue { - return ProcessArgsCountKey.Int(val) -} - -// ProcessCommand returns an attribute KeyValue conforming to the -// "process.command" semantic conventions. It represents the command used to -// launch the process (i.e. the command name). On Linux based systems, can be set -// to the zeroth string in `proc/[pid]/cmdline`. On Windows, can be set to the -// first parameter extracted from `GetCommandLineW`. -func ProcessCommand(val string) attribute.KeyValue { - return ProcessCommandKey.String(val) -} - -// ProcessCommandArgs returns an attribute KeyValue conforming to the -// "process.command_args" semantic conventions. It represents the all the command -// arguments (including the command/executable itself) as received by the -// process. On Linux-based systems (and some other Unixoid systems supporting -// procfs), can be set according to the list of null-delimited strings extracted -// from `proc/[pid]/cmdline`. For libc-based executables, this would be the full -// argv vector passed to `main`. SHOULD NOT be collected by default unless there -// is sanitization that excludes sensitive data. -func ProcessCommandArgs(val ...string) attribute.KeyValue { - return ProcessCommandArgsKey.StringSlice(val) -} - -// ProcessCommandLine returns an attribute KeyValue conforming to the -// "process.command_line" semantic conventions. It represents the full command -// used to launch the process as a single string representing the full command. -// On Windows, can be set to the result of `GetCommandLineW`. Do not set this if -// you have to assemble it just for monitoring; use `process.command_args` -// instead. SHOULD NOT be collected by default unless there is sanitization that -// excludes sensitive data. -func ProcessCommandLine(val string) attribute.KeyValue { - return ProcessCommandLineKey.String(val) -} - -// ProcessCreationTime returns an attribute KeyValue conforming to the -// "process.creation.time" semantic conventions. It represents the date and time -// the process was created, in ISO 8601 format. -func ProcessCreationTime(val string) attribute.KeyValue { - return ProcessCreationTimeKey.String(val) -} - -// ProcessEnvironmentVariable returns an attribute KeyValue conforming to the -// "process.environment_variable" semantic conventions. It represents the process -// environment variables, `` being the environment variable name, the value -// being the environment variable value. -func ProcessEnvironmentVariable(key string, val string) attribute.KeyValue { - return attribute.String("process.environment_variable."+key, val) -} - -// ProcessExecutableBuildIDGNU returns an attribute KeyValue conforming to the -// "process.executable.build_id.gnu" semantic conventions. It represents the GNU -// build ID as found in the `.note.gnu.build-id` ELF section (hex string). -func ProcessExecutableBuildIDGNU(val string) attribute.KeyValue { - return ProcessExecutableBuildIDGNUKey.String(val) -} - -// ProcessExecutableBuildIDGo returns an attribute KeyValue conforming to the -// "process.executable.build_id.go" semantic conventions. It represents the Go -// build ID as retrieved by `go tool buildid `. -func ProcessExecutableBuildIDGo(val string) attribute.KeyValue { - return ProcessExecutableBuildIDGoKey.String(val) -} - -// ProcessExecutableBuildIDHtlhash returns an attribute KeyValue conforming to -// the "process.executable.build_id.htlhash" semantic conventions. It represents -// the profiling specific build ID for executables. See the OTel specification -// for Profiles for more information. -func ProcessExecutableBuildIDHtlhash(val string) attribute.KeyValue { - return ProcessExecutableBuildIDHtlhashKey.String(val) -} - -// ProcessExecutableName returns an attribute KeyValue conforming to the -// "process.executable.name" semantic conventions. It represents the name of the -// process executable. On Linux based systems, this SHOULD be set to the base -// name of the target of `/proc/[pid]/exe`. On Windows, this SHOULD be set to the -// base name of `GetProcessImageFileNameW`. -func ProcessExecutableName(val string) attribute.KeyValue { - return ProcessExecutableNameKey.String(val) -} - -// ProcessExecutablePath returns an attribute KeyValue conforming to the -// "process.executable.path" semantic conventions. It represents the full path to -// the process executable. On Linux based systems, can be set to the target of -// `proc/[pid]/exe`. On Windows, can be set to the result of -// `GetProcessImageFileNameW`. -func ProcessExecutablePath(val string) attribute.KeyValue { - return ProcessExecutablePathKey.String(val) -} - -// ProcessExitCode returns an attribute KeyValue conforming to the -// "process.exit.code" semantic conventions. It represents the exit code of the -// process. -func ProcessExitCode(val int) attribute.KeyValue { - return ProcessExitCodeKey.Int(val) -} - -// ProcessExitTime returns an attribute KeyValue conforming to the -// "process.exit.time" semantic conventions. It represents the date and time the -// process exited, in ISO 8601 format. -func ProcessExitTime(val string) attribute.KeyValue { - return ProcessExitTimeKey.String(val) -} - -// ProcessGroupLeaderPID returns an attribute KeyValue conforming to the -// "process.group_leader.pid" semantic conventions. It represents the PID of the -// process's group leader. This is also the process group ID (PGID) of the -// process. -func ProcessGroupLeaderPID(val int) attribute.KeyValue { - return ProcessGroupLeaderPIDKey.Int(val) -} - -// ProcessInteractive returns an attribute KeyValue conforming to the -// "process.interactive" semantic conventions. It represents the whether the -// process is connected to an interactive shell. -func ProcessInteractive(val bool) attribute.KeyValue { - return ProcessInteractiveKey.Bool(val) -} - -// ProcessLinuxCgroup returns an attribute KeyValue conforming to the -// "process.linux.cgroup" semantic conventions. It represents the control group -// associated with the process. -func ProcessLinuxCgroup(val string) attribute.KeyValue { - return ProcessLinuxCgroupKey.String(val) -} - -// ProcessOwner returns an attribute KeyValue conforming to the "process.owner" -// semantic conventions. It represents the username of the user that owns the -// process. -func ProcessOwner(val string) attribute.KeyValue { - return ProcessOwnerKey.String(val) -} - -// ProcessParentPID returns an attribute KeyValue conforming to the -// "process.parent_pid" semantic conventions. It represents the parent Process -// identifier (PPID). -func ProcessParentPID(val int) attribute.KeyValue { - return ProcessParentPIDKey.Int(val) -} - -// ProcessPID returns an attribute KeyValue conforming to the "process.pid" -// semantic conventions. It represents the process identifier (PID). -func ProcessPID(val int) attribute.KeyValue { - return ProcessPIDKey.Int(val) -} - -// ProcessRealUserID returns an attribute KeyValue conforming to the -// "process.real_user.id" semantic conventions. It represents the real user ID -// (RUID) of the process. -func ProcessRealUserID(val int) attribute.KeyValue { - return ProcessRealUserIDKey.Int(val) -} - -// ProcessRealUserName returns an attribute KeyValue conforming to the -// "process.real_user.name" semantic conventions. It represents the username of -// the real user of the process. -func ProcessRealUserName(val string) attribute.KeyValue { - return ProcessRealUserNameKey.String(val) -} - -// ProcessRuntimeDescription returns an attribute KeyValue conforming to the -// "process.runtime.description" semantic conventions. It represents an -// additional description about the runtime of the process, for example a -// specific vendor customization of the runtime environment. -func ProcessRuntimeDescription(val string) attribute.KeyValue { - return ProcessRuntimeDescriptionKey.String(val) -} - -// ProcessRuntimeName returns an attribute KeyValue conforming to the -// "process.runtime.name" semantic conventions. It represents the name of the -// runtime of this process. -func ProcessRuntimeName(val string) attribute.KeyValue { - return ProcessRuntimeNameKey.String(val) -} - -// ProcessRuntimeVersion returns an attribute KeyValue conforming to the -// "process.runtime.version" semantic conventions. It represents the version of -// the runtime of this process, as returned by the runtime without modification. -func ProcessRuntimeVersion(val string) attribute.KeyValue { - return ProcessRuntimeVersionKey.String(val) -} - -// ProcessSavedUserID returns an attribute KeyValue conforming to the -// "process.saved_user.id" semantic conventions. It represents the saved user ID -// (SUID) of the process. -func ProcessSavedUserID(val int) attribute.KeyValue { - return ProcessSavedUserIDKey.Int(val) -} - -// ProcessSavedUserName returns an attribute KeyValue conforming to the -// "process.saved_user.name" semantic conventions. It represents the username of -// the saved user. -func ProcessSavedUserName(val string) attribute.KeyValue { - return ProcessSavedUserNameKey.String(val) -} - -// ProcessSessionLeaderPID returns an attribute KeyValue conforming to the -// "process.session_leader.pid" semantic conventions. It represents the PID of -// the process's session leader. This is also the session ID (SID) of the -// process. -func ProcessSessionLeaderPID(val int) attribute.KeyValue { - return ProcessSessionLeaderPIDKey.Int(val) -} - -// ProcessTitle returns an attribute KeyValue conforming to the "process.title" -// semantic conventions. It represents the process title (proctitle). -func ProcessTitle(val string) attribute.KeyValue { - return ProcessTitleKey.String(val) -} - -// ProcessUserID returns an attribute KeyValue conforming to the -// "process.user.id" semantic conventions. It represents the effective user ID -// (EUID) of the process. -func ProcessUserID(val int) attribute.KeyValue { - return ProcessUserIDKey.Int(val) -} - -// ProcessUserName returns an attribute KeyValue conforming to the -// "process.user.name" semantic conventions. It represents the username of the -// effective user of the process. -func ProcessUserName(val string) attribute.KeyValue { - return ProcessUserNameKey.String(val) -} - -// ProcessVpid returns an attribute KeyValue conforming to the "process.vpid" -// semantic conventions. It represents the virtual process identifier. -func ProcessVpid(val int) attribute.KeyValue { - return ProcessVpidKey.Int(val) -} - -// ProcessWorkingDirectory returns an attribute KeyValue conforming to the -// "process.working_directory" semantic conventions. It represents the working -// directory of the process. -func ProcessWorkingDirectory(val string) attribute.KeyValue { - return ProcessWorkingDirectoryKey.String(val) -} - -// Enum values for process.context_switch.type -var ( - // voluntary - // Stability: development - ProcessContextSwitchTypeVoluntary = ProcessContextSwitchTypeKey.String("voluntary") - // involuntary - // Stability: development - ProcessContextSwitchTypeInvoluntary = ProcessContextSwitchTypeKey.String("involuntary") -) - -// Enum values for process.state -var ( - // running - // Stability: development - ProcessStateRunning = ProcessStateKey.String("running") - // sleeping - // Stability: development - ProcessStateSleeping = ProcessStateKey.String("sleeping") - // stopped - // Stability: development - ProcessStateStopped = ProcessStateKey.String("stopped") - // defunct - // Stability: development - ProcessStateDefunct = ProcessStateKey.String("defunct") -) - -// Namespace: profile -const ( - // ProfileFrameTypeKey is the attribute Key conforming to the - // "profile.frame.type" semantic conventions. It represents the describes the - // interpreter or compiler of a single frame. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "cpython" - ProfileFrameTypeKey = attribute.Key("profile.frame.type") -) - -// Enum values for profile.frame.type -var ( - // [.NET] - // - // Stability: development - // - // [.NET]: https://wikipedia.org/wiki/.NET - ProfileFrameTypeDotnet = ProfileFrameTypeKey.String("dotnet") - // [JVM] - // - // Stability: development - // - // [JVM]: https://wikipedia.org/wiki/Java_virtual_machine - ProfileFrameTypeJVM = ProfileFrameTypeKey.String("jvm") - // [Kernel] - // - // Stability: development - // - // [Kernel]: https://wikipedia.org/wiki/Kernel_(operating_system) - ProfileFrameTypeKernel = ProfileFrameTypeKey.String("kernel") - // Can be one of but not limited to [C], [C++], [Go] or [Rust]. If possible, a - // more precise value MUST be used. - // - // Stability: development - // - // [C]: https://wikipedia.org/wiki/C_(programming_language) - // [C++]: https://wikipedia.org/wiki/C%2B%2B - // [Go]: https://wikipedia.org/wiki/Go_(programming_language) - // [Rust]: https://wikipedia.org/wiki/Rust_(programming_language) - ProfileFrameTypeNative = ProfileFrameTypeKey.String("native") - // [Perl] - // - // Stability: development - // - // [Perl]: https://wikipedia.org/wiki/Perl - ProfileFrameTypePerl = ProfileFrameTypeKey.String("perl") - // [PHP] - // - // Stability: development - // - // [PHP]: https://wikipedia.org/wiki/PHP - ProfileFrameTypePHP = ProfileFrameTypeKey.String("php") - // [Python] - // - // Stability: development - // - // [Python]: https://wikipedia.org/wiki/Python_(programming_language) - ProfileFrameTypeCpython = ProfileFrameTypeKey.String("cpython") - // [Ruby] - // - // Stability: development - // - // [Ruby]: https://wikipedia.org/wiki/Ruby_(programming_language) - ProfileFrameTypeRuby = ProfileFrameTypeKey.String("ruby") - // [V8JS] - // - // Stability: development - // - // [V8JS]: https://wikipedia.org/wiki/V8_(JavaScript_engine) - ProfileFrameTypeV8JS = ProfileFrameTypeKey.String("v8js") - // [Erlang] - // - // Stability: development - // - // [Erlang]: https://en.wikipedia.org/wiki/BEAM_(Erlang_virtual_machine) - ProfileFrameTypeBeam = ProfileFrameTypeKey.String("beam") - // [Go], - // - // Stability: development - // - // [Go]: https://wikipedia.org/wiki/Go_(programming_language) - ProfileFrameTypeGo = ProfileFrameTypeKey.String("go") - // [Rust] - // - // Stability: development - // - // [Rust]: https://wikipedia.org/wiki/Rust_(programming_language) - ProfileFrameTypeRust = ProfileFrameTypeKey.String("rust") -) - -// Namespace: rpc -const ( - // RPCMethodKey is the attribute Key conforming to the "rpc.method" semantic - // conventions. It represents the fully-qualified logical name of the method - // from the RPC interface perspective. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "com.example.ExampleService/exampleMethod", "EchoService/Echo", - // "_OTHER" - // Note: The method name MAY have unbounded cardinality in edge or error cases. - // - // Some RPC frameworks or libraries provide a fixed set of recognized methods - // for client stubs and server implementations. Instrumentations for such - // frameworks MUST set this attribute to the original method name only - // when the method is recognized by the framework or library. - // - // When the method is not recognized, for example, when the server receives - // a request for a method that is not predefined on the server, or when - // instrumentation is not able to reliably detect if the method is predefined, - // the attribute MUST be set to `_OTHER`. In such cases, tracing - // instrumentations MUST also set `rpc.method_original` attribute to - // the original method value. - // - // If the RPC instrumentation could end up converting valid RPC methods to - // `_OTHER`, then it SHOULD provide a way to configure the list of recognized - // RPC methods. - // - // The `rpc.method` can be different from the name of any implementing - // method/function. - // The `code.function.name` attribute may be used to record the fully-qualified - // method actually executing the call on the server side, or the - // RPC client stub method on the client side. - RPCMethodKey = attribute.Key("rpc.method") - - // RPCMethodOriginalKey is the attribute Key conforming to the - // "rpc.method_original" semantic conventions. It represents the original name - // of the method used by the client. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "com.myservice.EchoService/catchAll", - // "com.myservice.EchoService/unknownMethod", "InvalidMethod" - RPCMethodOriginalKey = attribute.Key("rpc.method_original") - - // RPCResponseStatusCodeKey is the attribute Key conforming to the - // "rpc.response.status_code" semantic conventions. It represents the status - // code of the RPC returned by the RPC server or generated by the client. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: "OK", "DEADLINE_EXCEEDED", "-32602" - // Note: Usually it represents an error code, but may also represent partial - // success, warning, or differentiate between various types of successful - // outcomes. - // Semantic conventions for individual RPC frameworks SHOULD document what - // `rpc.response.status_code` means in the context of that system and which - // values are considered to represent errors. - RPCResponseStatusCodeKey = attribute.Key("rpc.response.status_code") - - // RPCSystemNameKey is the attribute Key conforming to the "rpc.system.name" - // semantic conventions. It represents the Remote Procedure Call (RPC) system. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Release_Candidate - // - // Examples: - // Note: The client and server RPC systems may differ for the same RPC - // interaction. For example, a client may use Apache Dubbo or Connect RPC to - // communicate with a server that uses gRPC since both protocols provide - // compatibility with gRPC. - RPCSystemNameKey = attribute.Key("rpc.system.name") -) - -// RPCMethod returns an attribute KeyValue conforming to the "rpc.method" -// semantic conventions. It represents the fully-qualified logical name of the -// method from the RPC interface perspective. -func RPCMethod(val string) attribute.KeyValue { - return RPCMethodKey.String(val) -} - -// RPCMethodOriginal returns an attribute KeyValue conforming to the -// "rpc.method_original" semantic conventions. It represents the original name of -// the method used by the client. -func RPCMethodOriginal(val string) attribute.KeyValue { - return RPCMethodOriginalKey.String(val) -} - -// RPCRequestMetadata returns an attribute KeyValue conforming to the -// "rpc.request.metadata" semantic conventions. It represents the RPC request -// metadata, `` being the normalized RPC metadata key (lowercase), the value -// being the metadata values. -func RPCRequestMetadata(key string, val ...string) attribute.KeyValue { - return attribute.StringSlice("rpc.request.metadata."+key, val) -} - -// RPCResponseMetadata returns an attribute KeyValue conforming to the -// "rpc.response.metadata" semantic conventions. It represents the RPC response -// metadata, `` being the normalized RPC metadata key (lowercase), the value -// being the metadata values. -func RPCResponseMetadata(key string, val ...string) attribute.KeyValue { - return attribute.StringSlice("rpc.response.metadata."+key, val) -} - -// RPCResponseStatusCode returns an attribute KeyValue conforming to the -// "rpc.response.status_code" semantic conventions. It represents the status code -// of the RPC returned by the RPC server or generated by the client. -func RPCResponseStatusCode(val string) attribute.KeyValue { - return RPCResponseStatusCodeKey.String(val) -} - -// Enum values for rpc.system.name -var ( - // [gRPC] - // Stability: release_candidate - // - // [gRPC]: https://grpc.io/ - RPCSystemNameGRPC = RPCSystemNameKey.String("grpc") - // [Apache Dubbo] - // Stability: release_candidate - // - // [Apache Dubbo]: https://dubbo.apache.org/ - RPCSystemNameDubbo = RPCSystemNameKey.String("dubbo") - // [Connect RPC] - // Stability: development - // - // [Connect RPC]: https://connectrpc.com/ - RPCSystemNameConnectrpc = RPCSystemNameKey.String("connectrpc") - // [JSON-RPC] - // Stability: development - // - // [JSON-RPC]: https://www.jsonrpc.org/ - RPCSystemNameJSONRPC = RPCSystemNameKey.String("jsonrpc") -) - -// Namespace: security_rule -const ( - // SecurityRuleCategoryKey is the attribute Key conforming to the - // "security_rule.category" semantic conventions. It represents a categorization - // value keyword used by the entity using the rule for detection of this event. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Attempted Information Leak" - SecurityRuleCategoryKey = attribute.Key("security_rule.category") - - // SecurityRuleDescriptionKey is the attribute Key conforming to the - // "security_rule.description" semantic conventions. It represents the - // description of the rule generating the event. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Block requests to public DNS over HTTPS / TLS protocols" - SecurityRuleDescriptionKey = attribute.Key("security_rule.description") - - // SecurityRuleLicenseKey is the attribute Key conforming to the - // "security_rule.license" semantic conventions. It represents the name of the - // license under which the rule used to generate this event is made available. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Apache 2.0" - SecurityRuleLicenseKey = attribute.Key("security_rule.license") - - // SecurityRuleNameKey is the attribute Key conforming to the - // "security_rule.name" semantic conventions. It represents the name of the rule - // or signature generating the event. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "BLOCK_DNS_over_TLS" - SecurityRuleNameKey = attribute.Key("security_rule.name") - - // SecurityRuleReferenceKey is the attribute Key conforming to the - // "security_rule.reference" semantic conventions. It represents the reference - // URL to additional information about the rule used to generate this event. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "https://en.wikipedia.org/wiki/DNS_over_TLS" - // Note: The URL can point to the vendor’s documentation about the rule. If - // that’s not available, it can also be a link to a more general page - // describing this type of alert. - SecurityRuleReferenceKey = attribute.Key("security_rule.reference") - - // SecurityRuleRulesetNameKey is the attribute Key conforming to the - // "security_rule.ruleset.name" semantic conventions. It represents the name of - // the ruleset, policy, group, or parent category in which the rule used to - // generate this event is a member. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Standard_Protocol_Filters" - SecurityRuleRulesetNameKey = attribute.Key("security_rule.ruleset.name") - - // SecurityRuleUUIDKey is the attribute Key conforming to the - // "security_rule.uuid" semantic conventions. It represents a rule ID that is - // unique within the scope of a set or group of agents, observers, or other - // entities using the rule for detection of this event. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "550e8400-e29b-41d4-a716-446655440000", "1100110011" - SecurityRuleUUIDKey = attribute.Key("security_rule.uuid") - - // SecurityRuleVersionKey is the attribute Key conforming to the - // "security_rule.version" semantic conventions. It represents the version / - // revision of the rule being used for analysis. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1.0.0" - SecurityRuleVersionKey = attribute.Key("security_rule.version") -) - -// SecurityRuleCategory returns an attribute KeyValue conforming to the -// "security_rule.category" semantic conventions. It represents a categorization -// value keyword used by the entity using the rule for detection of this event. -func SecurityRuleCategory(val string) attribute.KeyValue { - return SecurityRuleCategoryKey.String(val) -} - -// SecurityRuleDescription returns an attribute KeyValue conforming to the -// "security_rule.description" semantic conventions. It represents the -// description of the rule generating the event. -func SecurityRuleDescription(val string) attribute.KeyValue { - return SecurityRuleDescriptionKey.String(val) -} - -// SecurityRuleLicense returns an attribute KeyValue conforming to the -// "security_rule.license" semantic conventions. It represents the name of the -// license under which the rule used to generate this event is made available. -func SecurityRuleLicense(val string) attribute.KeyValue { - return SecurityRuleLicenseKey.String(val) -} - -// SecurityRuleName returns an attribute KeyValue conforming to the -// "security_rule.name" semantic conventions. It represents the name of the rule -// or signature generating the event. -func SecurityRuleName(val string) attribute.KeyValue { - return SecurityRuleNameKey.String(val) -} - -// SecurityRuleReference returns an attribute KeyValue conforming to the -// "security_rule.reference" semantic conventions. It represents the reference -// URL to additional information about the rule used to generate this event. -func SecurityRuleReference(val string) attribute.KeyValue { - return SecurityRuleReferenceKey.String(val) -} - -// SecurityRuleRulesetName returns an attribute KeyValue conforming to the -// "security_rule.ruleset.name" semantic conventions. It represents the name of -// the ruleset, policy, group, or parent category in which the rule used to -// generate this event is a member. -func SecurityRuleRulesetName(val string) attribute.KeyValue { - return SecurityRuleRulesetNameKey.String(val) -} - -// SecurityRuleUUID returns an attribute KeyValue conforming to the -// "security_rule.uuid" semantic conventions. It represents a rule ID that is -// unique within the scope of a set or group of agents, observers, or other -// entities using the rule for detection of this event. -func SecurityRuleUUID(val string) attribute.KeyValue { - return SecurityRuleUUIDKey.String(val) -} - -// SecurityRuleVersion returns an attribute KeyValue conforming to the -// "security_rule.version" semantic conventions. It represents the version / -// revision of the rule being used for analysis. -func SecurityRuleVersion(val string) attribute.KeyValue { - return SecurityRuleVersionKey.String(val) -} - -// Namespace: server -const ( - // ServerAddressKey is the attribute Key conforming to the "server.address" - // semantic conventions. It represents the server domain name if available - // without reverse DNS lookup; otherwise, IP address or Unix domain socket name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "example.com", "10.1.2.80", "/tmp/my.sock" - // Note: When observed from the client side, and when communicating through an - // intermediary, `server.address` SHOULD represent the server address behind any - // intermediaries, for example proxies, if it's available. - ServerAddressKey = attribute.Key("server.address") - - // ServerPortKey is the attribute Key conforming to the "server.port" semantic - // conventions. It represents the server port number. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: 80, 8080, 443 - // Note: When observed from the client side, and when communicating through an - // intermediary, `server.port` SHOULD represent the server port behind any - // intermediaries, for example proxies, if it's available. - ServerPortKey = attribute.Key("server.port") -) - -// ServerAddress returns an attribute KeyValue conforming to the "server.address" -// semantic conventions. It represents the server domain name if available -// without reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func ServerAddress(val string) attribute.KeyValue { - return ServerAddressKey.String(val) -} - -// ServerPort returns an attribute KeyValue conforming to the "server.port" -// semantic conventions. It represents the server port number. -func ServerPort(val int) attribute.KeyValue { - return ServerPortKey.Int(val) -} - -// Namespace: service -const ( - // ServiceCriticalityKey is the attribute Key conforming to the - // "service.criticality" semantic conventions. It represents the operational - // criticality of the service. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "critical", "high", "medium", "low" - // Note: Application developers are encouraged to set `service.criticality` to - // express the operational importance of their services. Telemetry consumers MAY - // use this attribute to optimize telemetry collection or improve user - // experience. - ServiceCriticalityKey = attribute.Key("service.criticality") - - // ServiceInstanceIDKey is the attribute Key conforming to the - // "service.instance.id" semantic conventions. It represents the string ID of - // the service instance. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "627cc493-f310-47de-96bd-71410b7dec09" - // Note: MUST be unique for each instance of the same - // `service.namespace,service.name` pair (in other words - // `service.namespace,service.name,service.instance.id` triplet MUST be globally - // unique). The ID helps to - // distinguish instances of the same service that exist at the same time (e.g. - // instances of a horizontally scaled - // service). - // - // Implementations, such as SDKs, are recommended to generate a random Version 1 - // or Version 4 [RFC - // 4122] UUID, but are free to use an inherent unique ID as - // the source of - // this value if stability is desirable. In that case, the ID SHOULD be used as - // source of a UUID Version 5 and - // SHOULD use the following UUID as the namespace: - // `4d63009a-8d0f-11ee-aad7-4c796ed8e320`. - // - // UUIDs are typically recommended, as only an opaque value for the purposes of - // identifying a service instance is - // needed. Similar to what can be seen in the man page for the - // [`/etc/machine-id`] file, the underlying - // data, such as pod name and namespace should be treated as confidential, being - // the user's choice to expose it - // or not via another resource attribute. - // - // For applications running behind an application server (like unicorn), we do - // not recommend using one identifier - // for all processes participating in the application. Instead, it's recommended - // each division (e.g. a worker - // thread in unicorn) to have its own instance.id. - // - // It's not recommended for a Collector to set `service.instance.id` if it can't - // unambiguously determine the - // service instance that is generating that telemetry. For instance, creating an - // UUID based on `pod.name` will - // likely be wrong, as the Collector might not know from which container within - // that pod the telemetry originated. - // However, Collectors can set the `service.instance.id` if they can - // unambiguously determine the service instance - // for that telemetry. This is typically the case for scraping receivers, as - // they know the target address and - // port. - // - // [RFC - // 4122]: https://www.ietf.org/rfc/rfc4122.txt - // [`/etc/machine-id`]: https://www.freedesktop.org/software/systemd/man/latest/machine-id.html - ServiceInstanceIDKey = attribute.Key("service.instance.id") - - // ServiceNameKey is the attribute Key conforming to the "service.name" semantic - // conventions. It represents the logical name of the service. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "shoppingcart" - // Note: MUST be the same for all instances of horizontally scaled services. If - // the value was not specified, SDKs MUST fallback to `unknown_service:` - // concatenated with [`process.executable.name`], e.g. `unknown_service:bash`. - // If `process.executable.name` is not available, the value MUST be set to - // `unknown_service`. - // - // [`process.executable.name`]: process.md - ServiceNameKey = attribute.Key("service.name") - - // ServiceNamespaceKey is the attribute Key conforming to the - // "service.namespace" semantic conventions. It represents a namespace for - // `service.name`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "Shop" - // Note: A string value having a meaning that helps to distinguish a group of - // services, for example the team name that owns a group of services. - // `service.name` is expected to be unique within the same namespace. If - // `service.namespace` is not specified in the Resource then `service.name` is - // expected to be unique for all services that have no explicit namespace - // defined (so the empty/unspecified namespace is simply one more valid - // namespace). Zero-length namespace string is assumed equal to unspecified - // namespace. - ServiceNamespaceKey = attribute.Key("service.namespace") - - // ServicePeerNameKey is the attribute Key conforming to the "service.peer.name" - // semantic conventions. It represents the logical name of the service on the - // other side of the connection. SHOULD be equal to the actual [`service.name`] - // resource attribute of the remote service if any. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "shoppingcart" - // - // [`service.name`]: /docs/resource/README.md#service - ServicePeerNameKey = attribute.Key("service.peer.name") - - // ServicePeerNamespaceKey is the attribute Key conforming to the - // "service.peer.namespace" semantic conventions. It represents the logical - // namespace of the service on the other side of the connection. SHOULD be equal - // to the actual [`service.namespace`] resource attribute of the remote service - // if any. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Shop" - // - // [`service.namespace`]: /docs/resource/README.md#service - ServicePeerNamespaceKey = attribute.Key("service.peer.namespace") - - // ServiceVersionKey is the attribute Key conforming to the "service.version" - // semantic conventions. It represents the version string of the service - // component. The format is not defined by these conventions. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "2.0.0", "a01dbef8a" - ServiceVersionKey = attribute.Key("service.version") -) - -// ServiceInstanceID returns an attribute KeyValue conforming to the -// "service.instance.id" semantic conventions. It represents the string ID of the -// service instance. -func ServiceInstanceID(val string) attribute.KeyValue { - return ServiceInstanceIDKey.String(val) -} - -// ServiceName returns an attribute KeyValue conforming to the "service.name" -// semantic conventions. It represents the logical name of the service. -func ServiceName(val string) attribute.KeyValue { - return ServiceNameKey.String(val) -} - -// ServiceNamespace returns an attribute KeyValue conforming to the -// "service.namespace" semantic conventions. It represents a namespace for -// `service.name`. -func ServiceNamespace(val string) attribute.KeyValue { - return ServiceNamespaceKey.String(val) -} - -// ServicePeerName returns an attribute KeyValue conforming to the -// "service.peer.name" semantic conventions. It represents the logical name of -// the service on the other side of the connection. SHOULD be equal to the actual -// [`service.name`] resource attribute of the remote service if any. -// -// [`service.name`]: /docs/resource/README.md#service -func ServicePeerName(val string) attribute.KeyValue { - return ServicePeerNameKey.String(val) -} - -// ServicePeerNamespace returns an attribute KeyValue conforming to the -// "service.peer.namespace" semantic conventions. It represents the logical -// namespace of the service on the other side of the connection. SHOULD be equal -// to the actual [`service.namespace`] resource attribute of the remote service -// if any. -// -// [`service.namespace`]: /docs/resource/README.md#service -func ServicePeerNamespace(val string) attribute.KeyValue { - return ServicePeerNamespaceKey.String(val) -} - -// ServiceVersion returns an attribute KeyValue conforming to the -// "service.version" semantic conventions. It represents the version string of -// the service component. The format is not defined by these conventions. -func ServiceVersion(val string) attribute.KeyValue { - return ServiceVersionKey.String(val) -} - -// Enum values for service.criticality -var ( - // Service is business-critical; downtime directly impacts revenue, user - // experience, or core functionality. - // - // Stability: development - ServiceCriticalityCritical = ServiceCriticalityKey.String("critical") - // Service is important but has degradation tolerance or fallback mechanisms. - // - // Stability: development - ServiceCriticalityHigh = ServiceCriticalityKey.String("high") - // Service provides supplementary functionality; degradation has limited user - // impact. - // - // Stability: development - ServiceCriticalityMedium = ServiceCriticalityKey.String("medium") - // Service is non-essential to core operations; used for background tasks or - // internal tools. - // - // Stability: development - ServiceCriticalityLow = ServiceCriticalityKey.String("low") -) - -// Namespace: session -const ( - // SessionIDKey is the attribute Key conforming to the "session.id" semantic - // conventions. It represents a unique id to identify a session. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 00112233-4455-6677-8899-aabbccddeeff - SessionIDKey = attribute.Key("session.id") - - // SessionPreviousIDKey is the attribute Key conforming to the - // "session.previous_id" semantic conventions. It represents the previous - // `session.id` for this user, when known. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 00112233-4455-6677-8899-aabbccddeeff - SessionPreviousIDKey = attribute.Key("session.previous_id") -) - -// SessionID returns an attribute KeyValue conforming to the "session.id" -// semantic conventions. It represents a unique id to identify a session. -func SessionID(val string) attribute.KeyValue { - return SessionIDKey.String(val) -} - -// SessionPreviousID returns an attribute KeyValue conforming to the -// "session.previous_id" semantic conventions. It represents the previous -// `session.id` for this user, when known. -func SessionPreviousID(val string) attribute.KeyValue { - return SessionPreviousIDKey.String(val) -} - -// Namespace: signalr -const ( - // SignalRConnectionStatusKey is the attribute Key conforming to the - // "signalr.connection.status" semantic conventions. It represents the signalR - // HTTP connection closure status. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "app_shutdown", "timeout" - SignalRConnectionStatusKey = attribute.Key("signalr.connection.status") - - // SignalRTransportKey is the attribute Key conforming to the - // "signalr.transport" semantic conventions. It represents the - // [SignalR transport type]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "web_sockets", "long_polling" - // - // [SignalR transport type]: https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/TransportProtocols.md - SignalRTransportKey = attribute.Key("signalr.transport") -) - -// Enum values for signalr.connection.status -var ( - // The connection was closed normally. - // Stability: stable - SignalRConnectionStatusNormalClosure = SignalRConnectionStatusKey.String("normal_closure") - // The connection was closed due to a timeout. - // Stability: stable - SignalRConnectionStatusTimeout = SignalRConnectionStatusKey.String("timeout") - // The connection was closed because the app is shutting down. - // Stability: stable - SignalRConnectionStatusAppShutdown = SignalRConnectionStatusKey.String("app_shutdown") -) - -// Enum values for signalr.transport -var ( - // ServerSentEvents protocol - // Stability: stable - SignalRTransportServerSentEvents = SignalRTransportKey.String("server_sent_events") - // LongPolling protocol - // Stability: stable - SignalRTransportLongPolling = SignalRTransportKey.String("long_polling") - // WebSockets protocol - // Stability: stable - SignalRTransportWebSockets = SignalRTransportKey.String("web_sockets") -) - -// Namespace: source -const ( - // SourceAddressKey is the attribute Key conforming to the "source.address" - // semantic conventions. It represents the source address - domain name if - // available without reverse DNS lookup; otherwise, IP address or Unix domain - // socket name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "source.example.com", "10.1.2.80", "/tmp/my.sock" - // Note: When observed from the destination side, and when communicating through - // an intermediary, `source.address` SHOULD represent the source address behind - // any intermediaries, for example proxies, if it's available. - SourceAddressKey = attribute.Key("source.address") - - // SourcePortKey is the attribute Key conforming to the "source.port" semantic - // conventions. It represents the source port number. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 3389, 2888 - SourcePortKey = attribute.Key("source.port") -) - -// SourceAddress returns an attribute KeyValue conforming to the "source.address" -// semantic conventions. It represents the source address - domain name if -// available without reverse DNS lookup; otherwise, IP address or Unix domain -// socket name. -func SourceAddress(val string) attribute.KeyValue { - return SourceAddressKey.String(val) -} - -// SourcePort returns an attribute KeyValue conforming to the "source.port" -// semantic conventions. It represents the source port number. -func SourcePort(val int) attribute.KeyValue { - return SourcePortKey.Int(val) -} - -// Namespace: system -const ( - // SystemDeviceKey is the attribute Key conforming to the "system.device" - // semantic conventions. It represents the device identifier. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "(identifier)" - SystemDeviceKey = attribute.Key("system.device") - - // SystemFilesystemModeKey is the attribute Key conforming to the - // "system.filesystem.mode" semantic conventions. It represents the filesystem - // mode. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "rw, ro" - SystemFilesystemModeKey = attribute.Key("system.filesystem.mode") - - // SystemFilesystemMountpointKey is the attribute Key conforming to the - // "system.filesystem.mountpoint" semantic conventions. It represents the - // filesystem mount path. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/mnt/data" - SystemFilesystemMountpointKey = attribute.Key("system.filesystem.mountpoint") - - // SystemFilesystemStateKey is the attribute Key conforming to the - // "system.filesystem.state" semantic conventions. It represents the filesystem - // state. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "used" - SystemFilesystemStateKey = attribute.Key("system.filesystem.state") - - // SystemFilesystemTypeKey is the attribute Key conforming to the - // "system.filesystem.type" semantic conventions. It represents the filesystem - // type. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ext4" - SystemFilesystemTypeKey = attribute.Key("system.filesystem.type") - - // SystemMemoryLinuxSlabStateKey is the attribute Key conforming to the - // "system.memory.linux.slab.state" semantic conventions. It represents the - // Linux Slab memory state. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "reclaimable", "unreclaimable" - SystemMemoryLinuxSlabStateKey = attribute.Key("system.memory.linux.slab.state") - - // SystemMemoryStateKey is the attribute Key conforming to the - // "system.memory.state" semantic conventions. It represents the memory state. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "free", "cached" - SystemMemoryStateKey = attribute.Key("system.memory.state") - - // SystemPagingDirectionKey is the attribute Key conforming to the - // "system.paging.direction" semantic conventions. It represents the paging - // access direction. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "in" - SystemPagingDirectionKey = attribute.Key("system.paging.direction") - - // SystemPagingFaultTypeKey is the attribute Key conforming to the - // "system.paging.fault.type" semantic conventions. It represents the paging - // fault type. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "minor" - SystemPagingFaultTypeKey = attribute.Key("system.paging.fault.type") - - // SystemPagingStateKey is the attribute Key conforming to the - // "system.paging.state" semantic conventions. It represents the memory paging - // state. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "free" - SystemPagingStateKey = attribute.Key("system.paging.state") -) - -// SystemDevice returns an attribute KeyValue conforming to the "system.device" -// semantic conventions. It represents the device identifier. -func SystemDevice(val string) attribute.KeyValue { - return SystemDeviceKey.String(val) -} - -// SystemFilesystemMode returns an attribute KeyValue conforming to the -// "system.filesystem.mode" semantic conventions. It represents the filesystem -// mode. -func SystemFilesystemMode(val string) attribute.KeyValue { - return SystemFilesystemModeKey.String(val) -} - -// SystemFilesystemMountpoint returns an attribute KeyValue conforming to the -// "system.filesystem.mountpoint" semantic conventions. It represents the -// filesystem mount path. -func SystemFilesystemMountpoint(val string) attribute.KeyValue { - return SystemFilesystemMountpointKey.String(val) -} - -// Enum values for system.filesystem.state -var ( - // used - // Stability: development - SystemFilesystemStateUsed = SystemFilesystemStateKey.String("used") - // free - // Stability: development - SystemFilesystemStateFree = SystemFilesystemStateKey.String("free") - // reserved - // Stability: development - SystemFilesystemStateReserved = SystemFilesystemStateKey.String("reserved") -) - -// Enum values for system.filesystem.type -var ( - // fat32 - // Stability: development - SystemFilesystemTypeFat32 = SystemFilesystemTypeKey.String("fat32") - // exfat - // Stability: development - SystemFilesystemTypeExfat = SystemFilesystemTypeKey.String("exfat") - // ntfs - // Stability: development - SystemFilesystemTypeNtfs = SystemFilesystemTypeKey.String("ntfs") - // refs - // Stability: development - SystemFilesystemTypeRefs = SystemFilesystemTypeKey.String("refs") - // hfsplus - // Stability: development - SystemFilesystemTypeHfsplus = SystemFilesystemTypeKey.String("hfsplus") - // ext4 - // Stability: development - SystemFilesystemTypeExt4 = SystemFilesystemTypeKey.String("ext4") -) - -// Enum values for system.memory.linux.slab.state -var ( - // reclaimable - // Stability: development - SystemMemoryLinuxSlabStateReclaimable = SystemMemoryLinuxSlabStateKey.String("reclaimable") - // unreclaimable - // Stability: development - SystemMemoryLinuxSlabStateUnreclaimable = SystemMemoryLinuxSlabStateKey.String("unreclaimable") -) - -// Enum values for system.memory.state -var ( - // Actual used virtual memory in bytes. - // Stability: development - SystemMemoryStateUsed = SystemMemoryStateKey.String("used") - // free - // Stability: development - SystemMemoryStateFree = SystemMemoryStateKey.String("free") - // buffers - // Stability: development - SystemMemoryStateBuffers = SystemMemoryStateKey.String("buffers") - // cached - // Stability: development - SystemMemoryStateCached = SystemMemoryStateKey.String("cached") -) - -// Enum values for system.paging.direction -var ( - // in - // Stability: development - SystemPagingDirectionIn = SystemPagingDirectionKey.String("in") - // out - // Stability: development - SystemPagingDirectionOut = SystemPagingDirectionKey.String("out") -) - -// Enum values for system.paging.fault.type -var ( - // major - // Stability: development - SystemPagingFaultTypeMajor = SystemPagingFaultTypeKey.String("major") - // minor - // Stability: development - SystemPagingFaultTypeMinor = SystemPagingFaultTypeKey.String("minor") -) - -// Enum values for system.paging.state -var ( - // used - // Stability: development - SystemPagingStateUsed = SystemPagingStateKey.String("used") - // free - // Stability: development - SystemPagingStateFree = SystemPagingStateKey.String("free") -) - -// Namespace: telemetry -const ( - // TelemetryDistroNameKey is the attribute Key conforming to the - // "telemetry.distro.name" semantic conventions. It represents the name of the - // auto instrumentation agent or distribution, if used. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "parts-unlimited-java" - // Note: Official auto instrumentation agents and distributions SHOULD set the - // `telemetry.distro.name` attribute to - // a string starting with `opentelemetry-`, e.g. - // `opentelemetry-java-instrumentation`. - TelemetryDistroNameKey = attribute.Key("telemetry.distro.name") - - // TelemetryDistroVersionKey is the attribute Key conforming to the - // "telemetry.distro.version" semantic conventions. It represents the version - // string of the auto instrumentation agent or distribution, if used. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1.2.3" - TelemetryDistroVersionKey = attribute.Key("telemetry.distro.version") - - // TelemetrySDKLanguageKey is the attribute Key conforming to the - // "telemetry.sdk.language" semantic conventions. It represents the language of - // the telemetry SDK. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: - TelemetrySDKLanguageKey = attribute.Key("telemetry.sdk.language") - - // TelemetrySDKNameKey is the attribute Key conforming to the - // "telemetry.sdk.name" semantic conventions. It represents the name of the - // telemetry SDK as defined above. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "opentelemetry" - // Note: The OpenTelemetry SDK MUST set the `telemetry.sdk.name` attribute to - // `opentelemetry`. - // If another SDK, like a fork or a vendor-provided implementation, is used, - // this SDK MUST set the - // `telemetry.sdk.name` attribute to the fully-qualified class or module name of - // this SDK's main entry point - // or another suitable identifier depending on the language. - // The identifier `opentelemetry` is reserved and MUST NOT be used in this case. - // All custom identifiers SHOULD be stable across different versions of an - // implementation. - TelemetrySDKNameKey = attribute.Key("telemetry.sdk.name") - - // TelemetrySDKVersionKey is the attribute Key conforming to the - // "telemetry.sdk.version" semantic conventions. It represents the version - // string of the telemetry SDK. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "1.2.3" - TelemetrySDKVersionKey = attribute.Key("telemetry.sdk.version") -) - -// TelemetryDistroName returns an attribute KeyValue conforming to the -// "telemetry.distro.name" semantic conventions. It represents the name of the -// auto instrumentation agent or distribution, if used. -func TelemetryDistroName(val string) attribute.KeyValue { - return TelemetryDistroNameKey.String(val) -} - -// TelemetryDistroVersion returns an attribute KeyValue conforming to the -// "telemetry.distro.version" semantic conventions. It represents the version -// string of the auto instrumentation agent or distribution, if used. -func TelemetryDistroVersion(val string) attribute.KeyValue { - return TelemetryDistroVersionKey.String(val) -} - -// TelemetrySDKName returns an attribute KeyValue conforming to the -// "telemetry.sdk.name" semantic conventions. It represents the name of the -// telemetry SDK as defined above. -func TelemetrySDKName(val string) attribute.KeyValue { - return TelemetrySDKNameKey.String(val) -} - -// TelemetrySDKVersion returns an attribute KeyValue conforming to the -// "telemetry.sdk.version" semantic conventions. It represents the version string -// of the telemetry SDK. -func TelemetrySDKVersion(val string) attribute.KeyValue { - return TelemetrySDKVersionKey.String(val) -} - -// Enum values for telemetry.sdk.language -var ( - // cpp - // Stability: stable - TelemetrySDKLanguageCPP = TelemetrySDKLanguageKey.String("cpp") - // dotnet - // Stability: stable - TelemetrySDKLanguageDotnet = TelemetrySDKLanguageKey.String("dotnet") - // erlang - // Stability: stable - TelemetrySDKLanguageErlang = TelemetrySDKLanguageKey.String("erlang") - // go - // Stability: stable - TelemetrySDKLanguageGo = TelemetrySDKLanguageKey.String("go") - // java - // Stability: stable - TelemetrySDKLanguageJava = TelemetrySDKLanguageKey.String("java") - // nodejs - // Stability: stable - TelemetrySDKLanguageNodejs = TelemetrySDKLanguageKey.String("nodejs") - // php - // Stability: stable - TelemetrySDKLanguagePHP = TelemetrySDKLanguageKey.String("php") - // python - // Stability: stable - TelemetrySDKLanguagePython = TelemetrySDKLanguageKey.String("python") - // ruby - // Stability: stable - TelemetrySDKLanguageRuby = TelemetrySDKLanguageKey.String("ruby") - // rust - // Stability: stable - TelemetrySDKLanguageRust = TelemetrySDKLanguageKey.String("rust") - // swift - // Stability: stable - TelemetrySDKLanguageSwift = TelemetrySDKLanguageKey.String("swift") - // webjs - // Stability: stable - TelemetrySDKLanguageWebJS = TelemetrySDKLanguageKey.String("webjs") -) - -// Namespace: test -const ( - // TestCaseNameKey is the attribute Key conforming to the "test.case.name" - // semantic conventions. It represents the fully qualified human readable name - // of the [test case]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "org.example.TestCase1.test1", "example/tests/TestCase1.test1", - // "ExampleTestCase1_test1" - // - // [test case]: https://wikipedia.org/wiki/Test_case - TestCaseNameKey = attribute.Key("test.case.name") - - // TestCaseResultStatusKey is the attribute Key conforming to the - // "test.case.result.status" semantic conventions. It represents the status of - // the actual test case result from test execution. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "pass", "fail" - TestCaseResultStatusKey = attribute.Key("test.case.result.status") - - // TestSuiteNameKey is the attribute Key conforming to the "test.suite.name" - // semantic conventions. It represents the human readable name of a [test suite] - // . - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "TestSuite1" - // - // [test suite]: https://wikipedia.org/wiki/Test_suite - TestSuiteNameKey = attribute.Key("test.suite.name") - - // TestSuiteRunStatusKey is the attribute Key conforming to the - // "test.suite.run.status" semantic conventions. It represents the status of the - // test suite run. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "success", "failure", "skipped", "aborted", "timed_out", - // "in_progress" - TestSuiteRunStatusKey = attribute.Key("test.suite.run.status") -) - -// TestCaseName returns an attribute KeyValue conforming to the "test.case.name" -// semantic conventions. It represents the fully qualified human readable name of -// the [test case]. -// -// [test case]: https://wikipedia.org/wiki/Test_case -func TestCaseName(val string) attribute.KeyValue { - return TestCaseNameKey.String(val) -} - -// TestSuiteName returns an attribute KeyValue conforming to the -// "test.suite.name" semantic conventions. It represents the human readable name -// of a [test suite]. -// -// [test suite]: https://wikipedia.org/wiki/Test_suite -func TestSuiteName(val string) attribute.KeyValue { - return TestSuiteNameKey.String(val) -} - -// Enum values for test.case.result.status -var ( - // pass - // Stability: development - TestCaseResultStatusPass = TestCaseResultStatusKey.String("pass") - // fail - // Stability: development - TestCaseResultStatusFail = TestCaseResultStatusKey.String("fail") -) - -// Enum values for test.suite.run.status -var ( - // success - // Stability: development - TestSuiteRunStatusSuccess = TestSuiteRunStatusKey.String("success") - // failure - // Stability: development - TestSuiteRunStatusFailure = TestSuiteRunStatusKey.String("failure") - // skipped - // Stability: development - TestSuiteRunStatusSkipped = TestSuiteRunStatusKey.String("skipped") - // aborted - // Stability: development - TestSuiteRunStatusAborted = TestSuiteRunStatusKey.String("aborted") - // timed_out - // Stability: development - TestSuiteRunStatusTimedOut = TestSuiteRunStatusKey.String("timed_out") - // in_progress - // Stability: development - TestSuiteRunStatusInProgress = TestSuiteRunStatusKey.String("in_progress") -) - -// Namespace: thread -const ( - // ThreadIDKey is the attribute Key conforming to the "thread.id" semantic - // conventions. It represents the current "managed" thread ID (as opposed to OS - // thread ID). - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Note: - // Examples of where the value can be extracted from: - // - // | Language or platform | Source | - // | --- | --- | - // | JVM | `Thread.currentThread().threadId()` | - // | .NET | `Thread.CurrentThread.ManagedThreadId` | - // | Python | `threading.current_thread().ident` | - // | Ruby | `Thread.current.object_id` | - // | C++ | `std::this_thread::get_id()` | - // | Erlang | `erlang:self()` | - ThreadIDKey = attribute.Key("thread.id") - - // ThreadNameKey is the attribute Key conforming to the "thread.name" semantic - // conventions. It represents the current thread name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: main - // Note: - // Examples of where the value can be extracted from: - // - // | Language or platform | Source | - // | --- | --- | - // | JVM | `Thread.currentThread().getName()` | - // | .NET | `Thread.CurrentThread.Name` | - // | Python | `threading.current_thread().name` | - // | Ruby | `Thread.current.name` | - // | Erlang | `erlang:process_info(self(), registered_name)` | - ThreadNameKey = attribute.Key("thread.name") -) - -// ThreadID returns an attribute KeyValue conforming to the "thread.id" semantic -// conventions. It represents the current "managed" thread ID (as opposed to OS -// thread ID). -func ThreadID(val int) attribute.KeyValue { - return ThreadIDKey.Int(val) -} - -// ThreadName returns an attribute KeyValue conforming to the "thread.name" -// semantic conventions. It represents the current thread name. -func ThreadName(val string) attribute.KeyValue { - return ThreadNameKey.String(val) -} - -// Namespace: tls -const ( - // TLSCipherKey is the attribute Key conforming to the "tls.cipher" semantic - // conventions. It represents the string indicating the [cipher] used during the - // current connection. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "TLS_RSA_WITH_3DES_EDE_CBC_SHA", - // "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" - // Note: The values allowed for `tls.cipher` MUST be one of the `Descriptions` - // of the [registered TLS Cipher Suits]. - // - // [cipher]: https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5 - // [registered TLS Cipher Suits]: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4 - TLSCipherKey = attribute.Key("tls.cipher") - - // TLSClientCertificateKey is the attribute Key conforming to the - // "tls.client.certificate" semantic conventions. It represents the PEM-encoded - // stand-alone certificate offered by the client. This is usually - // mutually-exclusive of `client.certificate_chain` since this value also exists - // in that list. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "MII..." - TLSClientCertificateKey = attribute.Key("tls.client.certificate") - - // TLSClientCertificateChainKey is the attribute Key conforming to the - // "tls.client.certificate_chain" semantic conventions. It represents the array - // of PEM-encoded certificates that make up the certificate chain offered by the - // client. This is usually mutually-exclusive of `client.certificate` since that - // value should be the first certificate in the chain. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "MII...", "MI..." - TLSClientCertificateChainKey = attribute.Key("tls.client.certificate_chain") - - // TLSClientHashMd5Key is the attribute Key conforming to the - // "tls.client.hash.md5" semantic conventions. It represents the certificate - // fingerprint using the MD5 digest of DER-encoded version of certificate - // offered by the client. For consistency with other hash values, this value - // should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC" - TLSClientHashMd5Key = attribute.Key("tls.client.hash.md5") - - // TLSClientHashSha1Key is the attribute Key conforming to the - // "tls.client.hash.sha1" semantic conventions. It represents the certificate - // fingerprint using the SHA1 digest of DER-encoded version of certificate - // offered by the client. For consistency with other hash values, this value - // should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "9E393D93138888D288266C2D915214D1D1CCEB2A" - TLSClientHashSha1Key = attribute.Key("tls.client.hash.sha1") - - // TLSClientHashSha256Key is the attribute Key conforming to the - // "tls.client.hash.sha256" semantic conventions. It represents the certificate - // fingerprint using the SHA256 digest of DER-encoded version of certificate - // offered by the client. For consistency with other hash values, this value - // should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0" - TLSClientHashSha256Key = attribute.Key("tls.client.hash.sha256") - - // TLSClientIssuerKey is the attribute Key conforming to the "tls.client.issuer" - // semantic conventions. It represents the distinguished name of [subject] of - // the issuer of the x.509 certificate presented by the client. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com" - // - // [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 - TLSClientIssuerKey = attribute.Key("tls.client.issuer") - - // TLSClientJa3Key is the attribute Key conforming to the "tls.client.ja3" - // semantic conventions. It represents a hash that identifies clients based on - // how they perform an SSL/TLS handshake. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "d4e5b18d6b55c71272893221c96ba240" - TLSClientJa3Key = attribute.Key("tls.client.ja3") - - // TLSClientNotAfterKey is the attribute Key conforming to the - // "tls.client.not_after" semantic conventions. It represents the date/Time - // indicating when client certificate is no longer considered valid. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2021-01-01T00:00:00.000Z" - TLSClientNotAfterKey = attribute.Key("tls.client.not_after") - - // TLSClientNotBeforeKey is the attribute Key conforming to the - // "tls.client.not_before" semantic conventions. It represents the date/Time - // indicating when client certificate is first considered valid. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1970-01-01T00:00:00.000Z" - TLSClientNotBeforeKey = attribute.Key("tls.client.not_before") - - // TLSClientSubjectKey is the attribute Key conforming to the - // "tls.client.subject" semantic conventions. It represents the distinguished - // name of subject of the x.509 certificate presented by the client. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "CN=myclient, OU=Documentation Team, DC=example, DC=com" - TLSClientSubjectKey = attribute.Key("tls.client.subject") - - // TLSClientSupportedCiphersKey is the attribute Key conforming to the - // "tls.client.supported_ciphers" semantic conventions. It represents the array - // of ciphers offered by the client during the client hello. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - // "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" - TLSClientSupportedCiphersKey = attribute.Key("tls.client.supported_ciphers") - - // TLSCurveKey is the attribute Key conforming to the "tls.curve" semantic - // conventions. It represents the string indicating the curve used for the given - // cipher, when applicable. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "secp256r1" - TLSCurveKey = attribute.Key("tls.curve") - - // TLSEstablishedKey is the attribute Key conforming to the "tls.established" - // semantic conventions. It represents the boolean flag indicating if the TLS - // negotiation was successful and transitioned to an encrypted tunnel. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: true - TLSEstablishedKey = attribute.Key("tls.established") - - // TLSNextProtocolKey is the attribute Key conforming to the "tls.next_protocol" - // semantic conventions. It represents the string indicating the protocol being - // tunneled. Per the values in the [IANA registry], this string should be lower - // case. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "http/1.1" - // - // [IANA registry]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids - TLSNextProtocolKey = attribute.Key("tls.next_protocol") - - // TLSProtocolNameKey is the attribute Key conforming to the "tls.protocol.name" - // semantic conventions. It represents the normalized lowercase protocol name - // parsed from original string of the negotiated [SSL/TLS protocol version]. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // - // [SSL/TLS protocol version]: https://docs.openssl.org/1.1.1/man3/SSL_get_version/#return-values - TLSProtocolNameKey = attribute.Key("tls.protocol.name") - - // TLSProtocolVersionKey is the attribute Key conforming to the - // "tls.protocol.version" semantic conventions. It represents the numeric part - // of the version parsed from the original string of the negotiated - // [SSL/TLS protocol version]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1.2", "3" - // - // [SSL/TLS protocol version]: https://docs.openssl.org/1.1.1/man3/SSL_get_version/#return-values - TLSProtocolVersionKey = attribute.Key("tls.protocol.version") - - // TLSResumedKey is the attribute Key conforming to the "tls.resumed" semantic - // conventions. It represents the boolean flag indicating if this TLS connection - // was resumed from an existing TLS negotiation. - // - // Type: boolean - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: true - TLSResumedKey = attribute.Key("tls.resumed") - - // TLSServerCertificateKey is the attribute Key conforming to the - // "tls.server.certificate" semantic conventions. It represents the PEM-encoded - // stand-alone certificate offered by the server. This is usually - // mutually-exclusive of `server.certificate_chain` since this value also exists - // in that list. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "MII..." - TLSServerCertificateKey = attribute.Key("tls.server.certificate") - - // TLSServerCertificateChainKey is the attribute Key conforming to the - // "tls.server.certificate_chain" semantic conventions. It represents the array - // of PEM-encoded certificates that make up the certificate chain offered by the - // server. This is usually mutually-exclusive of `server.certificate` since that - // value should be the first certificate in the chain. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "MII...", "MI..." - TLSServerCertificateChainKey = attribute.Key("tls.server.certificate_chain") - - // TLSServerHashMd5Key is the attribute Key conforming to the - // "tls.server.hash.md5" semantic conventions. It represents the certificate - // fingerprint using the MD5 digest of DER-encoded version of certificate - // offered by the server. For consistency with other hash values, this value - // should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC" - TLSServerHashMd5Key = attribute.Key("tls.server.hash.md5") - - // TLSServerHashSha1Key is the attribute Key conforming to the - // "tls.server.hash.sha1" semantic conventions. It represents the certificate - // fingerprint using the SHA1 digest of DER-encoded version of certificate - // offered by the server. For consistency with other hash values, this value - // should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "9E393D93138888D288266C2D915214D1D1CCEB2A" - TLSServerHashSha1Key = attribute.Key("tls.server.hash.sha1") - - // TLSServerHashSha256Key is the attribute Key conforming to the - // "tls.server.hash.sha256" semantic conventions. It represents the certificate - // fingerprint using the SHA256 digest of DER-encoded version of certificate - // offered by the server. For consistency with other hash values, this value - // should be formatted as an uppercase hash. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0" - TLSServerHashSha256Key = attribute.Key("tls.server.hash.sha256") - - // TLSServerIssuerKey is the attribute Key conforming to the "tls.server.issuer" - // semantic conventions. It represents the distinguished name of [subject] of - // the issuer of the x.509 certificate presented by the client. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com" - // - // [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 - TLSServerIssuerKey = attribute.Key("tls.server.issuer") - - // TLSServerJa3sKey is the attribute Key conforming to the "tls.server.ja3s" - // semantic conventions. It represents a hash that identifies servers based on - // how they perform an SSL/TLS handshake. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "d4e5b18d6b55c71272893221c96ba240" - TLSServerJa3sKey = attribute.Key("tls.server.ja3s") - - // TLSServerNotAfterKey is the attribute Key conforming to the - // "tls.server.not_after" semantic conventions. It represents the date/Time - // indicating when server certificate is no longer considered valid. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "2021-01-01T00:00:00.000Z" - TLSServerNotAfterKey = attribute.Key("tls.server.not_after") - - // TLSServerNotBeforeKey is the attribute Key conforming to the - // "tls.server.not_before" semantic conventions. It represents the date/Time - // indicating when server certificate is first considered valid. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "1970-01-01T00:00:00.000Z" - TLSServerNotBeforeKey = attribute.Key("tls.server.not_before") - - // TLSServerSubjectKey is the attribute Key conforming to the - // "tls.server.subject" semantic conventions. It represents the distinguished - // name of subject of the x.509 certificate presented by the server. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "CN=myserver, OU=Documentation Team, DC=example, DC=com" - TLSServerSubjectKey = attribute.Key("tls.server.subject") -) - -// TLSCipher returns an attribute KeyValue conforming to the "tls.cipher" -// semantic conventions. It represents the string indicating the [cipher] used -// during the current connection. -// -// [cipher]: https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5 -func TLSCipher(val string) attribute.KeyValue { - return TLSCipherKey.String(val) -} - -// TLSClientCertificate returns an attribute KeyValue conforming to the -// "tls.client.certificate" semantic conventions. It represents the PEM-encoded -// stand-alone certificate offered by the client. This is usually -// mutually-exclusive of `client.certificate_chain` since this value also exists -// in that list. -func TLSClientCertificate(val string) attribute.KeyValue { - return TLSClientCertificateKey.String(val) -} - -// TLSClientCertificateChain returns an attribute KeyValue conforming to the -// "tls.client.certificate_chain" semantic conventions. It represents the array -// of PEM-encoded certificates that make up the certificate chain offered by the -// client. This is usually mutually-exclusive of `client.certificate` since that -// value should be the first certificate in the chain. -func TLSClientCertificateChain(val ...string) attribute.KeyValue { - return TLSClientCertificateChainKey.StringSlice(val) -} - -// TLSClientHashMd5 returns an attribute KeyValue conforming to the -// "tls.client.hash.md5" semantic conventions. It represents the certificate -// fingerprint using the MD5 digest of DER-encoded version of certificate offered -// by the client. For consistency with other hash values, this value should be -// formatted as an uppercase hash. -func TLSClientHashMd5(val string) attribute.KeyValue { - return TLSClientHashMd5Key.String(val) -} - -// TLSClientHashSha1 returns an attribute KeyValue conforming to the -// "tls.client.hash.sha1" semantic conventions. It represents the certificate -// fingerprint using the SHA1 digest of DER-encoded version of certificate -// offered by the client. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSClientHashSha1(val string) attribute.KeyValue { - return TLSClientHashSha1Key.String(val) -} - -// TLSClientHashSha256 returns an attribute KeyValue conforming to the -// "tls.client.hash.sha256" semantic conventions. It represents the certificate -// fingerprint using the SHA256 digest of DER-encoded version of certificate -// offered by the client. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSClientHashSha256(val string) attribute.KeyValue { - return TLSClientHashSha256Key.String(val) -} - -// TLSClientIssuer returns an attribute KeyValue conforming to the -// "tls.client.issuer" semantic conventions. It represents the distinguished name -// of [subject] of the issuer of the x.509 certificate presented by the client. -// -// [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 -func TLSClientIssuer(val string) attribute.KeyValue { - return TLSClientIssuerKey.String(val) -} - -// TLSClientJa3 returns an attribute KeyValue conforming to the "tls.client.ja3" -// semantic conventions. It represents a hash that identifies clients based on -// how they perform an SSL/TLS handshake. -func TLSClientJa3(val string) attribute.KeyValue { - return TLSClientJa3Key.String(val) -} - -// TLSClientNotAfter returns an attribute KeyValue conforming to the -// "tls.client.not_after" semantic conventions. It represents the date/Time -// indicating when client certificate is no longer considered valid. -func TLSClientNotAfter(val string) attribute.KeyValue { - return TLSClientNotAfterKey.String(val) -} - -// TLSClientNotBefore returns an attribute KeyValue conforming to the -// "tls.client.not_before" semantic conventions. It represents the date/Time -// indicating when client certificate is first considered valid. -func TLSClientNotBefore(val string) attribute.KeyValue { - return TLSClientNotBeforeKey.String(val) -} - -// TLSClientSubject returns an attribute KeyValue conforming to the -// "tls.client.subject" semantic conventions. It represents the distinguished -// name of subject of the x.509 certificate presented by the client. -func TLSClientSubject(val string) attribute.KeyValue { - return TLSClientSubjectKey.String(val) -} - -// TLSClientSupportedCiphers returns an attribute KeyValue conforming to the -// "tls.client.supported_ciphers" semantic conventions. It represents the array -// of ciphers offered by the client during the client hello. -func TLSClientSupportedCiphers(val ...string) attribute.KeyValue { - return TLSClientSupportedCiphersKey.StringSlice(val) -} - -// TLSCurve returns an attribute KeyValue conforming to the "tls.curve" semantic -// conventions. It represents the string indicating the curve used for the given -// cipher, when applicable. -func TLSCurve(val string) attribute.KeyValue { - return TLSCurveKey.String(val) -} - -// TLSEstablished returns an attribute KeyValue conforming to the -// "tls.established" semantic conventions. It represents the boolean flag -// indicating if the TLS negotiation was successful and transitioned to an -// encrypted tunnel. -func TLSEstablished(val bool) attribute.KeyValue { - return TLSEstablishedKey.Bool(val) -} - -// TLSNextProtocol returns an attribute KeyValue conforming to the -// "tls.next_protocol" semantic conventions. It represents the string indicating -// the protocol being tunneled. Per the values in the [IANA registry], this -// string should be lower case. -// -// [IANA registry]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids -func TLSNextProtocol(val string) attribute.KeyValue { - return TLSNextProtocolKey.String(val) -} - -// TLSProtocolVersion returns an attribute KeyValue conforming to the -// "tls.protocol.version" semantic conventions. It represents the numeric part of -// the version parsed from the original string of the negotiated -// [SSL/TLS protocol version]. -// -// [SSL/TLS protocol version]: https://docs.openssl.org/1.1.1/man3/SSL_get_version/#return-values -func TLSProtocolVersion(val string) attribute.KeyValue { - return TLSProtocolVersionKey.String(val) -} - -// TLSResumed returns an attribute KeyValue conforming to the "tls.resumed" -// semantic conventions. It represents the boolean flag indicating if this TLS -// connection was resumed from an existing TLS negotiation. -func TLSResumed(val bool) attribute.KeyValue { - return TLSResumedKey.Bool(val) -} - -// TLSServerCertificate returns an attribute KeyValue conforming to the -// "tls.server.certificate" semantic conventions. It represents the PEM-encoded -// stand-alone certificate offered by the server. This is usually -// mutually-exclusive of `server.certificate_chain` since this value also exists -// in that list. -func TLSServerCertificate(val string) attribute.KeyValue { - return TLSServerCertificateKey.String(val) -} - -// TLSServerCertificateChain returns an attribute KeyValue conforming to the -// "tls.server.certificate_chain" semantic conventions. It represents the array -// of PEM-encoded certificates that make up the certificate chain offered by the -// server. This is usually mutually-exclusive of `server.certificate` since that -// value should be the first certificate in the chain. -func TLSServerCertificateChain(val ...string) attribute.KeyValue { - return TLSServerCertificateChainKey.StringSlice(val) -} - -// TLSServerHashMd5 returns an attribute KeyValue conforming to the -// "tls.server.hash.md5" semantic conventions. It represents the certificate -// fingerprint using the MD5 digest of DER-encoded version of certificate offered -// by the server. For consistency with other hash values, this value should be -// formatted as an uppercase hash. -func TLSServerHashMd5(val string) attribute.KeyValue { - return TLSServerHashMd5Key.String(val) -} - -// TLSServerHashSha1 returns an attribute KeyValue conforming to the -// "tls.server.hash.sha1" semantic conventions. It represents the certificate -// fingerprint using the SHA1 digest of DER-encoded version of certificate -// offered by the server. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSServerHashSha1(val string) attribute.KeyValue { - return TLSServerHashSha1Key.String(val) -} - -// TLSServerHashSha256 returns an attribute KeyValue conforming to the -// "tls.server.hash.sha256" semantic conventions. It represents the certificate -// fingerprint using the SHA256 digest of DER-encoded version of certificate -// offered by the server. For consistency with other hash values, this value -// should be formatted as an uppercase hash. -func TLSServerHashSha256(val string) attribute.KeyValue { - return TLSServerHashSha256Key.String(val) -} - -// TLSServerIssuer returns an attribute KeyValue conforming to the -// "tls.server.issuer" semantic conventions. It represents the distinguished name -// of [subject] of the issuer of the x.509 certificate presented by the client. -// -// [subject]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 -func TLSServerIssuer(val string) attribute.KeyValue { - return TLSServerIssuerKey.String(val) -} - -// TLSServerJa3s returns an attribute KeyValue conforming to the -// "tls.server.ja3s" semantic conventions. It represents a hash that identifies -// servers based on how they perform an SSL/TLS handshake. -func TLSServerJa3s(val string) attribute.KeyValue { - return TLSServerJa3sKey.String(val) -} - -// TLSServerNotAfter returns an attribute KeyValue conforming to the -// "tls.server.not_after" semantic conventions. It represents the date/Time -// indicating when server certificate is no longer considered valid. -func TLSServerNotAfter(val string) attribute.KeyValue { - return TLSServerNotAfterKey.String(val) -} - -// TLSServerNotBefore returns an attribute KeyValue conforming to the -// "tls.server.not_before" semantic conventions. It represents the date/Time -// indicating when server certificate is first considered valid. -func TLSServerNotBefore(val string) attribute.KeyValue { - return TLSServerNotBeforeKey.String(val) -} - -// TLSServerSubject returns an attribute KeyValue conforming to the -// "tls.server.subject" semantic conventions. It represents the distinguished -// name of subject of the x.509 certificate presented by the server. -func TLSServerSubject(val string) attribute.KeyValue { - return TLSServerSubjectKey.String(val) -} - -// Enum values for tls.protocol.name -var ( - // ssl - // Stability: development - TLSProtocolNameSsl = TLSProtocolNameKey.String("ssl") - // tls - // Stability: development - TLSProtocolNameTLS = TLSProtocolNameKey.String("tls") -) - -// Namespace: url -const ( - // URLDomainKey is the attribute Key conforming to the "url.domain" semantic - // conventions. It represents the domain extracted from the `url.full`, such as - // "opentelemetry.io". - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "www.foo.bar", "opentelemetry.io", "3.12.167.2", - // "[1080:0:0:0:8:800:200C:417A]" - // Note: In some cases a URL may refer to an IP and/or port directly, without a - // domain name. In this case, the IP address would go to the domain field. If - // the URL contains a [literal IPv6 address] enclosed by `[` and `]`, the `[` - // and `]` characters should also be captured in the domain field. - // - // [literal IPv6 address]: https://www.rfc-editor.org/rfc/rfc2732#section-2 - URLDomainKey = attribute.Key("url.domain") - - // URLExtensionKey is the attribute Key conforming to the "url.extension" - // semantic conventions. It represents the file extension extracted from the - // `url.full`, excluding the leading dot. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "png", "gz" - // Note: The file extension is only set if it exists, as not every url has a - // file extension. When the file name has multiple extensions `example.tar.gz`, - // only the last one should be captured `gz`, not `tar.gz`. - URLExtensionKey = attribute.Key("url.extension") - - // URLFragmentKey is the attribute Key conforming to the "url.fragment" semantic - // conventions. It represents the [URI fragment] component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "SemConv" - // - // [URI fragment]: https://www.rfc-editor.org/rfc/rfc3986#section-3.5 - URLFragmentKey = attribute.Key("url.fragment") - - // URLFullKey is the attribute Key conforming to the "url.full" semantic - // conventions. It represents the absolute URL describing a network resource - // according to [RFC3986]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "https://www.foo.bar/search?q=OpenTelemetry#SemConv", "//localhost" - // Note: For network calls, URL usually has - // `scheme://host[:port][path][?query][#fragment]` format, where the fragment - // is not transmitted over HTTP, but if it is known, it SHOULD be included - // nevertheless. - // - // `url.full` MUST NOT contain credentials passed via URL in form of - // `https://username:password@www.example.com/`. - // In such case username and password SHOULD be redacted and attribute's value - // SHOULD be `https://REDACTED:REDACTED@www.example.com/`. - // - // `url.full` SHOULD capture the absolute URL when it is available (or can be - // reconstructed). - // - // Sensitive content provided in `url.full` SHOULD be scrubbed when - // instrumentations can identify it. - // - // - // Query string values for the following keys SHOULD be redacted by default and - // replaced by the - // value `REDACTED`: - // - // - [`AWSAccessKeyId`] - // - [`Signature`] - // - [`sig`] - // - [`X-Goog-Signature`] - // - // This list is subject to change over time. - // - // Matching of query parameter keys against the sensitive list SHOULD be - // case-sensitive. - // - // - // Instrumentation MAY provide a way to override this list via declarative - // configuration. - // If so, it SHOULD use the `sensitive_query_parameters` property - // (an array of case-sensitive strings with minimum items 0) under - // `.instrumentation/development.general.sanitization.url`. - // This list is a full override of the default sensitive query parameter keys, - // it is not a list of keys in addition to the defaults. - // - // When a query string value is redacted, the query string key SHOULD still be - // preserved, e.g. - // `https://www.example.com/path?color=blue&sig=REDACTED`. - // - // [RFC3986]: https://www.rfc-editor.org/rfc/rfc3986 - // [`AWSAccessKeyId`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth - // [`Signature`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth - // [`sig`]: https://learn.microsoft.com/azure/storage/common/storage-sas-overview#sas-token - // [`X-Goog-Signature`]: https://cloud.google.com/storage/docs/access-control/signed-urls - URLFullKey = attribute.Key("url.full") - - // URLOriginalKey is the attribute Key conforming to the "url.original" semantic - // conventions. It represents the unmodified original URL as seen in the event - // source. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "https://www.foo.bar/search?q=OpenTelemetry#SemConv", - // "search?q=OpenTelemetry" - // Note: In network monitoring, the observed URL may be a full URL, whereas in - // access logs, the URL is often just represented as a path. This field is meant - // to represent the URL as it was observed, complete or not. - // `url.original` might contain credentials passed via URL in form of - // `https://username:password@www.example.com/`. In such case password and - // username SHOULD NOT be redacted and attribute's value SHOULD remain the same. - URLOriginalKey = attribute.Key("url.original") - - // URLPathKey is the attribute Key conforming to the "url.path" semantic - // conventions. It represents the [URI path] component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "/search" - // Note: Sensitive content provided in `url.path` SHOULD be scrubbed when - // instrumentations can identify it. - // - // [URI path]: https://www.rfc-editor.org/rfc/rfc3986#section-3.3 - URLPathKey = attribute.Key("url.path") - - // URLPortKey is the attribute Key conforming to the "url.port" semantic - // conventions. It represents the port extracted from the `url.full`. - // - // Type: int - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: 443 - URLPortKey = attribute.Key("url.port") - - // URLQueryKey is the attribute Key conforming to the "url.query" semantic - // conventions. It represents the [URI query] component. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "q=OpenTelemetry" - // Note: Sensitive content provided in `url.query` SHOULD be scrubbed when - // instrumentations can identify it. - // - // - // Query string values for the following keys SHOULD be redacted by default and - // replaced by the value `REDACTED`: - // - // - [`AWSAccessKeyId`] - // - [`Signature`] - // - [`sig`] - // - [`X-Goog-Signature`] - // - // This list is subject to change over time. - // - // Matching of query parameter keys against the sensitive list SHOULD be - // case-sensitive. - // - // Instrumentation MAY provide a way to override this list via declarative - // configuration. - // If so, it SHOULD use the `sensitive_query_parameters` property - // (an array of case-sensitive strings with minimum items 0) under - // `.instrumentation/development.general.sanitization.url`. - // This list is a full override of the default sensitive query parameter keys, - // it is not a list of keys in addition to the defaults. - // - // When a query string value is redacted, the query string key SHOULD still be - // preserved, e.g. - // `q=OpenTelemetry&sig=REDACTED`. - // - // [URI query]: https://www.rfc-editor.org/rfc/rfc3986#section-3.4 - // [`AWSAccessKeyId`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth - // [`Signature`]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth - // [`sig`]: https://learn.microsoft.com/azure/storage/common/storage-sas-overview#sas-token - // [`X-Goog-Signature`]: https://cloud.google.com/storage/docs/access-control/signed-urls - URLQueryKey = attribute.Key("url.query") - - // URLRegisteredDomainKey is the attribute Key conforming to the - // "url.registered_domain" semantic conventions. It represents the highest - // registered url domain, stripped of the subdomain. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "example.com", "foo.co.uk" - // Note: This value can be determined precisely with the [public suffix list]. - // For example, the registered domain for `foo.example.com` is `example.com`. - // Trying to approximate this by simply taking the last two labels will not work - // well for TLDs such as `co.uk`. - // - // [public suffix list]: https://publicsuffix.org/ - URLRegisteredDomainKey = attribute.Key("url.registered_domain") - - // URLSchemeKey is the attribute Key conforming to the "url.scheme" semantic - // conventions. It represents the [URI scheme] component identifying the used - // protocol. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "https", "ftp", "telnet" - // - // [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 - URLSchemeKey = attribute.Key("url.scheme") - - // URLSubdomainKey is the attribute Key conforming to the "url.subdomain" - // semantic conventions. It represents the subdomain portion of a fully - // qualified domain name includes all of the names except the host name under - // the registered_domain. In a partially qualified domain, or if the - // qualification level of the full name cannot be determined, subdomain contains - // all of the names below the registered domain. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "east", "sub2.sub1" - // Note: The subdomain portion of `www.east.mydomain.co.uk` is `east`. If the - // domain has multiple levels of subdomain, such as `sub2.sub1.example.com`, the - // subdomain field should contain `sub2.sub1`, with no trailing period. - URLSubdomainKey = attribute.Key("url.subdomain") - - // URLTemplateKey is the attribute Key conforming to the "url.template" semantic - // conventions. It represents the low-cardinality template of an - // [absolute path reference]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "/users/{id}", "/users/:id", "/users?id={id}" - // - // [absolute path reference]: https://www.rfc-editor.org/rfc/rfc3986#section-4.2 - URLTemplateKey = attribute.Key("url.template") - - // URLTopLevelDomainKey is the attribute Key conforming to the - // "url.top_level_domain" semantic conventions. It represents the effective top - // level domain (eTLD), also known as the domain suffix, is the last part of the - // domain name. For example, the top level domain for example.com is `com`. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "com", "co.uk" - // Note: This value can be determined precisely with the [public suffix list]. - // - // [public suffix list]: https://publicsuffix.org/ - URLTopLevelDomainKey = attribute.Key("url.top_level_domain") -) - -// URLDomain returns an attribute KeyValue conforming to the "url.domain" -// semantic conventions. It represents the domain extracted from the `url.full`, -// such as "opentelemetry.io". -func URLDomain(val string) attribute.KeyValue { - return URLDomainKey.String(val) -} - -// URLExtension returns an attribute KeyValue conforming to the "url.extension" -// semantic conventions. It represents the file extension extracted from the -// `url.full`, excluding the leading dot. -func URLExtension(val string) attribute.KeyValue { - return URLExtensionKey.String(val) -} - -// URLFragment returns an attribute KeyValue conforming to the "url.fragment" -// semantic conventions. It represents the [URI fragment] component. -// -// [URI fragment]: https://www.rfc-editor.org/rfc/rfc3986#section-3.5 -func URLFragment(val string) attribute.KeyValue { - return URLFragmentKey.String(val) -} - -// URLFull returns an attribute KeyValue conforming to the "url.full" semantic -// conventions. It represents the absolute URL describing a network resource -// according to [RFC3986]. -// -// [RFC3986]: https://www.rfc-editor.org/rfc/rfc3986 -func URLFull(val string) attribute.KeyValue { - return URLFullKey.String(val) -} - -// URLOriginal returns an attribute KeyValue conforming to the "url.original" -// semantic conventions. It represents the unmodified original URL as seen in the -// event source. -func URLOriginal(val string) attribute.KeyValue { - return URLOriginalKey.String(val) -} - -// URLPath returns an attribute KeyValue conforming to the "url.path" semantic -// conventions. It represents the [URI path] component. -// -// [URI path]: https://www.rfc-editor.org/rfc/rfc3986#section-3.3 -func URLPath(val string) attribute.KeyValue { - return URLPathKey.String(val) -} - -// URLPort returns an attribute KeyValue conforming to the "url.port" semantic -// conventions. It represents the port extracted from the `url.full`. -func URLPort(val int) attribute.KeyValue { - return URLPortKey.Int(val) -} - -// URLQuery returns an attribute KeyValue conforming to the "url.query" semantic -// conventions. It represents the [URI query] component. -// -// [URI query]: https://www.rfc-editor.org/rfc/rfc3986#section-3.4 -func URLQuery(val string) attribute.KeyValue { - return URLQueryKey.String(val) -} - -// URLRegisteredDomain returns an attribute KeyValue conforming to the -// "url.registered_domain" semantic conventions. It represents the highest -// registered url domain, stripped of the subdomain. -func URLRegisteredDomain(val string) attribute.KeyValue { - return URLRegisteredDomainKey.String(val) -} - -// URLScheme returns an attribute KeyValue conforming to the "url.scheme" -// semantic conventions. It represents the [URI scheme] component identifying the -// used protocol. -// -// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 -func URLScheme(val string) attribute.KeyValue { - return URLSchemeKey.String(val) -} - -// URLSubdomain returns an attribute KeyValue conforming to the "url.subdomain" -// semantic conventions. It represents the subdomain portion of a fully qualified -// domain name includes all of the names except the host name under the -// registered_domain. In a partially qualified domain, or if the qualification -// level of the full name cannot be determined, subdomain contains all of the -// names below the registered domain. -func URLSubdomain(val string) attribute.KeyValue { - return URLSubdomainKey.String(val) -} - -// URLTemplate returns an attribute KeyValue conforming to the "url.template" -// semantic conventions. It represents the low-cardinality template of an -// [absolute path reference]. -// -// [absolute path reference]: https://www.rfc-editor.org/rfc/rfc3986#section-4.2 -func URLTemplate(val string) attribute.KeyValue { - return URLTemplateKey.String(val) -} - -// URLTopLevelDomain returns an attribute KeyValue conforming to the -// "url.top_level_domain" semantic conventions. It represents the effective top -// level domain (eTLD), also known as the domain suffix, is the last part of the -// domain name. For example, the top level domain for example.com is `com`. -func URLTopLevelDomain(val string) attribute.KeyValue { - return URLTopLevelDomainKey.String(val) -} - -// Namespace: user -const ( - // UserEmailKey is the attribute Key conforming to the "user.email" semantic - // conventions. It represents the user email address. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "a.einstein@example.com" - UserEmailKey = attribute.Key("user.email") - - // UserFullNameKey is the attribute Key conforming to the "user.full_name" - // semantic conventions. It represents the user's full name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Albert Einstein" - UserFullNameKey = attribute.Key("user.full_name") - - // UserHashKey is the attribute Key conforming to the "user.hash" semantic - // conventions. It represents the unique user hash to correlate information for - // a user in anonymized form. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "364fc68eaf4c8acec74a4e52d7d1feaa" - // Note: Useful if `user.id` or `user.name` contain confidential information and - // cannot be used. - UserHashKey = attribute.Key("user.hash") - - // UserIDKey is the attribute Key conforming to the "user.id" semantic - // conventions. It represents the unique identifier of the user. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "S-1-5-21-202424912787-2692429404-2351956786-1000" - UserIDKey = attribute.Key("user.id") - - // UserNameKey is the attribute Key conforming to the "user.name" semantic - // conventions. It represents the short name or login/username of the user. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "a.einstein" - UserNameKey = attribute.Key("user.name") - - // UserRolesKey is the attribute Key conforming to the "user.roles" semantic - // conventions. It represents the array of user roles at the time of the event. - // - // Type: string[] - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "admin", "reporting_user" - UserRolesKey = attribute.Key("user.roles") -) - -// UserEmail returns an attribute KeyValue conforming to the "user.email" -// semantic conventions. It represents the user email address. -func UserEmail(val string) attribute.KeyValue { - return UserEmailKey.String(val) -} - -// UserFullName returns an attribute KeyValue conforming to the "user.full_name" -// semantic conventions. It represents the user's full name. -func UserFullName(val string) attribute.KeyValue { - return UserFullNameKey.String(val) -} - -// UserHash returns an attribute KeyValue conforming to the "user.hash" semantic -// conventions. It represents the unique user hash to correlate information for a -// user in anonymized form. -func UserHash(val string) attribute.KeyValue { - return UserHashKey.String(val) -} - -// UserID returns an attribute KeyValue conforming to the "user.id" semantic -// conventions. It represents the unique identifier of the user. -func UserID(val string) attribute.KeyValue { - return UserIDKey.String(val) -} - -// UserName returns an attribute KeyValue conforming to the "user.name" semantic -// conventions. It represents the short name or login/username of the user. -func UserName(val string) attribute.KeyValue { - return UserNameKey.String(val) -} - -// UserRoles returns an attribute KeyValue conforming to the "user.roles" -// semantic conventions. It represents the array of user roles at the time of the -// event. -func UserRoles(val ...string) attribute.KeyValue { - return UserRolesKey.StringSlice(val) -} - -// Namespace: user_agent -const ( - // UserAgentNameKey is the attribute Key conforming to the "user_agent.name" - // semantic conventions. It represents the name of the user-agent extracted from - // original. Usually refers to the browser's name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Safari", "YourApp" - // Note: [Example] of extracting browser's name from original string. In the - // case of using a user-agent for non-browser products, such as microservices - // with multiple names/versions inside the `user_agent.original`, the most - // significant name SHOULD be selected. In such a scenario it should align with - // `user_agent.version` - // - // [Example]: https://uaparser.dev/#demo - UserAgentNameKey = attribute.Key("user_agent.name") - - // UserAgentOriginalKey is the attribute Key conforming to the - // "user_agent.original" semantic conventions. It represents the value of the - // [HTTP User-Agent] header sent by the client. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Stable - // - // Examples: "CERN-LineMode/2.15 libwww/2.17b3", "Mozilla/5.0 (iPhone; CPU - // iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) - // Version/14.1.2 Mobile/15E148 Safari/604.1", "YourApp/1.0.0 - // grpc-java-okhttp/1.27.2" - // - // [HTTP User-Agent]: https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent - UserAgentOriginalKey = attribute.Key("user_agent.original") - - // UserAgentOSNameKey is the attribute Key conforming to the - // "user_agent.os.name" semantic conventions. It represents the human readable - // operating system name. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "iOS", "Android", "Ubuntu" - // Note: For mapping user agent strings to OS names, libraries such as - // [ua-parser] can be utilized. - // - // [ua-parser]: https://github.com/ua-parser - UserAgentOSNameKey = attribute.Key("user_agent.os.name") - - // UserAgentOSVersionKey is the attribute Key conforming to the - // "user_agent.os.version" semantic conventions. It represents the version - // string of the operating system as defined in [Version Attributes]. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "14.2.1", "18.04.1" - // Note: For mapping user agent strings to OS versions, libraries such as - // [ua-parser] can be utilized. - // - // [Version Attributes]: /docs/resource/README.md#version-attributes - // [ua-parser]: https://github.com/ua-parser - UserAgentOSVersionKey = attribute.Key("user_agent.os.version") - - // UserAgentSyntheticTypeKey is the attribute Key conforming to the - // "user_agent.synthetic.type" semantic conventions. It represents the specifies - // the category of synthetic traffic, such as tests or bots. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // Note: This attribute MAY be derived from the contents of the - // `user_agent.original` attribute. Components that populate the attribute are - // responsible for determining what they consider to be synthetic bot or test - // traffic. This attribute can either be set for self-identification purposes, - // or on telemetry detected to be generated as a result of a synthetic request. - // This attribute is useful for distinguishing between genuine client traffic - // and synthetic traffic generated by bots or tests. - UserAgentSyntheticTypeKey = attribute.Key("user_agent.synthetic.type") - - // UserAgentVersionKey is the attribute Key conforming to the - // "user_agent.version" semantic conventions. It represents the version of the - // user-agent extracted from original. Usually refers to the browser's version. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "14.1.2", "1.0.0" - // Note: [Example] of extracting browser's version from original string. In the - // case of using a user-agent for non-browser products, such as microservices - // with multiple names/versions inside the `user_agent.original`, the most - // significant version SHOULD be selected. In such a scenario it should align - // with `user_agent.name` - // - // [Example]: https://uaparser.dev/#demo - UserAgentVersionKey = attribute.Key("user_agent.version") -) - -// UserAgentName returns an attribute KeyValue conforming to the -// "user_agent.name" semantic conventions. It represents the name of the -// user-agent extracted from original. Usually refers to the browser's name. -func UserAgentName(val string) attribute.KeyValue { - return UserAgentNameKey.String(val) -} - -// UserAgentOriginal returns an attribute KeyValue conforming to the -// "user_agent.original" semantic conventions. It represents the value of the -// [HTTP User-Agent] header sent by the client. -// -// [HTTP User-Agent]: https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent -func UserAgentOriginal(val string) attribute.KeyValue { - return UserAgentOriginalKey.String(val) -} - -// UserAgentOSName returns an attribute KeyValue conforming to the -// "user_agent.os.name" semantic conventions. It represents the human readable -// operating system name. -func UserAgentOSName(val string) attribute.KeyValue { - return UserAgentOSNameKey.String(val) -} - -// UserAgentOSVersion returns an attribute KeyValue conforming to the -// "user_agent.os.version" semantic conventions. It represents the version string -// of the operating system as defined in [Version Attributes]. -// -// [Version Attributes]: /docs/resource/README.md#version-attributes -func UserAgentOSVersion(val string) attribute.KeyValue { - return UserAgentOSVersionKey.String(val) -} - -// UserAgentVersion returns an attribute KeyValue conforming to the -// "user_agent.version" semantic conventions. It represents the version of the -// user-agent extracted from original. Usually refers to the browser's version. -func UserAgentVersion(val string) attribute.KeyValue { - return UserAgentVersionKey.String(val) -} - -// Enum values for user_agent.synthetic.type -var ( - // Bot source. - // Stability: development - UserAgentSyntheticTypeBot = UserAgentSyntheticTypeKey.String("bot") - // Synthetic test source. - // Stability: development - UserAgentSyntheticTypeTest = UserAgentSyntheticTypeKey.String("test") -) - -// Namespace: vcs -const ( - // VCSChangeIDKey is the attribute Key conforming to the "vcs.change.id" - // semantic conventions. It represents the ID of the change (pull request/merge - // request/changelist) if applicable. This is usually a unique (within - // repository) identifier generated by the VCS system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "123" - VCSChangeIDKey = attribute.Key("vcs.change.id") - - // VCSChangeStateKey is the attribute Key conforming to the "vcs.change.state" - // semantic conventions. It represents the state of the change (pull - // request/merge request/changelist). - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "open", "closed", "merged" - VCSChangeStateKey = attribute.Key("vcs.change.state") - - // VCSChangeTitleKey is the attribute Key conforming to the "vcs.change.title" - // semantic conventions. It represents the human readable title of the change - // (pull request/merge request/changelist). This title is often a brief summary - // of the change and may get merged in to a ref as the commit summary. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "Fixes broken thing", "feat: add my new feature", "[chore] update - // dependency" - VCSChangeTitleKey = attribute.Key("vcs.change.title") - - // VCSLineChangeTypeKey is the attribute Key conforming to the - // "vcs.line_change.type" semantic conventions. It represents the type of line - // change being measured on a branch or change. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "added", "removed" - VCSLineChangeTypeKey = attribute.Key("vcs.line_change.type") - - // VCSOwnerNameKey is the attribute Key conforming to the "vcs.owner.name" - // semantic conventions. It represents the group owner within the version - // control system. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-org", "myteam", "business-unit" - VCSOwnerNameKey = attribute.Key("vcs.owner.name") - - // VCSProviderNameKey is the attribute Key conforming to the "vcs.provider.name" - // semantic conventions. It represents the name of the version control system - // provider. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "github", "gitlab", "gitea", "bitbucket" - VCSProviderNameKey = attribute.Key("vcs.provider.name") - - // VCSRefBaseNameKey is the attribute Key conforming to the "vcs.ref.base.name" - // semantic conventions. It represents the name of the [reference] such as - // **branch** or **tag** in the repository. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-feature-branch", "tag-1-test" - // Note: `base` refers to the starting point of a change. For example, `main` - // would be the base reference of type branch if you've created a new - // reference of type branch from it and created new commits. - // - // [reference]: https://git-scm.com/docs/gitglossary#def_ref - VCSRefBaseNameKey = attribute.Key("vcs.ref.base.name") - - // VCSRefBaseRevisionKey is the attribute Key conforming to the - // "vcs.ref.base.revision" semantic conventions. It represents the revision, - // literally [revised version], The revision most often refers to a commit - // object in Git, or a revision number in SVN. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "9d59409acf479dfa0df1aa568182e43e43df8bbe28d60fcf2bc52e30068802cc", - // "main", "123", "HEAD" - // Note: `base` refers to the starting point of a change. For example, `main` - // would be the base reference of type branch if you've created a new - // reference of type branch from it and created new commits. The - // revision can be a full [hash value (see - // glossary)], - // of the recorded change to a ref within a repository pointing to a - // commit [commit] object. It does - // not necessarily have to be a hash; it can simply define a [revision - // number] - // which is an integer that is monotonically increasing. In cases where - // it is identical to the `ref.base.name`, it SHOULD still be included. - // It is up to the implementer to decide which value to set as the - // revision based on the VCS system and situational context. - // - // [revised version]: https://www.merriam-webster.com/dictionary/revision - // [hash value (see - // glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - // [commit]: https://git-scm.com/docs/git-commit - // [revision - // number]: https://svnbook.red-bean.com/en/1.7/svn.tour.revs.specifiers.html - VCSRefBaseRevisionKey = attribute.Key("vcs.ref.base.revision") - - // VCSRefBaseTypeKey is the attribute Key conforming to the "vcs.ref.base.type" - // semantic conventions. It represents the type of the [reference] in the - // repository. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "branch", "tag" - // Note: `base` refers to the starting point of a change. For example, `main` - // would be the base reference of type branch if you've created a new - // reference of type branch from it and created new commits. - // - // [reference]: https://git-scm.com/docs/gitglossary#def_ref - VCSRefBaseTypeKey = attribute.Key("vcs.ref.base.type") - - // VCSRefHeadNameKey is the attribute Key conforming to the "vcs.ref.head.name" - // semantic conventions. It represents the name of the [reference] such as - // **branch** or **tag** in the repository. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "my-feature-branch", "tag-1-test" - // Note: `head` refers to where you are right now; the current reference at a - // given time. - // - // [reference]: https://git-scm.com/docs/gitglossary#def_ref - VCSRefHeadNameKey = attribute.Key("vcs.ref.head.name") - - // VCSRefHeadRevisionKey is the attribute Key conforming to the - // "vcs.ref.head.revision" semantic conventions. It represents the revision, - // literally [revised version], The revision most often refers to a commit - // object in Git, or a revision number in SVN. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "9d59409acf479dfa0df1aa568182e43e43df8bbe28d60fcf2bc52e30068802cc", - // "main", "123", "HEAD" - // Note: `head` refers to where you are right now; the current reference at a - // given time.The revision can be a full [hash value (see - // glossary)], - // of the recorded change to a ref within a repository pointing to a - // commit [commit] object. It does - // not necessarily have to be a hash; it can simply define a [revision - // number] - // which is an integer that is monotonically increasing. In cases where - // it is identical to the `ref.head.name`, it SHOULD still be included. - // It is up to the implementer to decide which value to set as the - // revision based on the VCS system and situational context. - // - // [revised version]: https://www.merriam-webster.com/dictionary/revision - // [hash value (see - // glossary)]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - // [commit]: https://git-scm.com/docs/git-commit - // [revision - // number]: https://svnbook.red-bean.com/en/1.7/svn.tour.revs.specifiers.html - VCSRefHeadRevisionKey = attribute.Key("vcs.ref.head.revision") - - // VCSRefHeadTypeKey is the attribute Key conforming to the "vcs.ref.head.type" - // semantic conventions. It represents the type of the [reference] in the - // repository. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "branch", "tag" - // Note: `head` refers to where you are right now; the current reference at a - // given time. - // - // [reference]: https://git-scm.com/docs/gitglossary#def_ref - VCSRefHeadTypeKey = attribute.Key("vcs.ref.head.type") - - // VCSRefTypeKey is the attribute Key conforming to the "vcs.ref.type" semantic - // conventions. It represents the type of the [reference] in the repository. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "branch", "tag" - // - // [reference]: https://git-scm.com/docs/gitglossary#def_ref - VCSRefTypeKey = attribute.Key("vcs.ref.type") - - // VCSRepositoryNameKey is the attribute Key conforming to the - // "vcs.repository.name" semantic conventions. It represents the human readable - // name of the repository. It SHOULD NOT include any additional identifier like - // Group/SubGroup in GitLab or organization in GitHub. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "semantic-conventions", "my-cool-repo" - // Note: Due to it only being the name, it can clash with forks of the same - // repository if collecting telemetry across multiple orgs or groups in - // the same backends. - VCSRepositoryNameKey = attribute.Key("vcs.repository.name") - - // VCSRepositoryURLFullKey is the attribute Key conforming to the - // "vcs.repository.url.full" semantic conventions. It represents the - // [canonical URL] of the repository providing the complete HTTP(S) address in - // order to locate and identify the repository through a browser. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: - // "https://github.com/opentelemetry/open-telemetry-collector-contrib", - // "https://gitlab.com/my-org/my-project/my-projects-project/repo" - // Note: In Git Version Control Systems, the canonical URL SHOULD NOT include - // the `.git` extension. - // - // [canonical URL]: https://support.google.com/webmasters/answer/10347851 - VCSRepositoryURLFullKey = attribute.Key("vcs.repository.url.full") - - // VCSRevisionDeltaDirectionKey is the attribute Key conforming to the - // "vcs.revision_delta.direction" semantic conventions. It represents the type - // of revision comparison. - // - // Type: Enum - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "ahead", "behind" - VCSRevisionDeltaDirectionKey = attribute.Key("vcs.revision_delta.direction") -) - -// VCSChangeID returns an attribute KeyValue conforming to the "vcs.change.id" -// semantic conventions. It represents the ID of the change (pull request/merge -// request/changelist) if applicable. This is usually a unique (within -// repository) identifier generated by the VCS system. -func VCSChangeID(val string) attribute.KeyValue { - return VCSChangeIDKey.String(val) -} - -// VCSChangeTitle returns an attribute KeyValue conforming to the -// "vcs.change.title" semantic conventions. It represents the human readable -// title of the change (pull request/merge request/changelist). This title is -// often a brief summary of the change and may get merged in to a ref as the -// commit summary. -func VCSChangeTitle(val string) attribute.KeyValue { - return VCSChangeTitleKey.String(val) -} - -// VCSOwnerName returns an attribute KeyValue conforming to the "vcs.owner.name" -// semantic conventions. It represents the group owner within the version control -// system. -func VCSOwnerName(val string) attribute.KeyValue { - return VCSOwnerNameKey.String(val) -} - -// VCSRefBaseName returns an attribute KeyValue conforming to the -// "vcs.ref.base.name" semantic conventions. It represents the name of the -// [reference] such as **branch** or **tag** in the repository. -// -// [reference]: https://git-scm.com/docs/gitglossary#def_ref -func VCSRefBaseName(val string) attribute.KeyValue { - return VCSRefBaseNameKey.String(val) -} - -// VCSRefBaseRevision returns an attribute KeyValue conforming to the -// "vcs.ref.base.revision" semantic conventions. It represents the revision, -// literally [revised version], The revision most often refers to a commit object -// in Git, or a revision number in SVN. -// -// [revised version]: https://www.merriam-webster.com/dictionary/revision -func VCSRefBaseRevision(val string) attribute.KeyValue { - return VCSRefBaseRevisionKey.String(val) -} - -// VCSRefHeadName returns an attribute KeyValue conforming to the -// "vcs.ref.head.name" semantic conventions. It represents the name of the -// [reference] such as **branch** or **tag** in the repository. -// -// [reference]: https://git-scm.com/docs/gitglossary#def_ref -func VCSRefHeadName(val string) attribute.KeyValue { - return VCSRefHeadNameKey.String(val) -} - -// VCSRefHeadRevision returns an attribute KeyValue conforming to the -// "vcs.ref.head.revision" semantic conventions. It represents the revision, -// literally [revised version], The revision most often refers to a commit object -// in Git, or a revision number in SVN. -// -// [revised version]: https://www.merriam-webster.com/dictionary/revision -func VCSRefHeadRevision(val string) attribute.KeyValue { - return VCSRefHeadRevisionKey.String(val) -} - -// VCSRepositoryName returns an attribute KeyValue conforming to the -// "vcs.repository.name" semantic conventions. It represents the human readable -// name of the repository. It SHOULD NOT include any additional identifier like -// Group/SubGroup in GitLab or organization in GitHub. -func VCSRepositoryName(val string) attribute.KeyValue { - return VCSRepositoryNameKey.String(val) -} - -// VCSRepositoryURLFull returns an attribute KeyValue conforming to the -// "vcs.repository.url.full" semantic conventions. It represents the -// [canonical URL] of the repository providing the complete HTTP(S) address in -// order to locate and identify the repository through a browser. -// -// [canonical URL]: https://support.google.com/webmasters/answer/10347851 -func VCSRepositoryURLFull(val string) attribute.KeyValue { - return VCSRepositoryURLFullKey.String(val) -} - -// Enum values for vcs.change.state -var ( - // Open means the change is currently active and under review. It hasn't been - // merged into the target branch yet, and it's still possible to make changes or - // add comments. - // Stability: development - VCSChangeStateOpen = VCSChangeStateKey.String("open") - // WIP (work-in-progress, draft) means the change is still in progress and not - // yet ready for a full review. It might still undergo significant changes. - // Stability: development - VCSChangeStateWip = VCSChangeStateKey.String("wip") - // Closed means the merge request has been closed without merging. This can - // happen for various reasons, such as the changes being deemed unnecessary, the - // issue being resolved in another way, or the author deciding to withdraw the - // request. - // Stability: development - VCSChangeStateClosed = VCSChangeStateKey.String("closed") - // Merged indicates that the change has been successfully integrated into the - // target codebase. - // Stability: development - VCSChangeStateMerged = VCSChangeStateKey.String("merged") -) - -// Enum values for vcs.line_change.type -var ( - // How many lines were added. - // Stability: development - VCSLineChangeTypeAdded = VCSLineChangeTypeKey.String("added") - // How many lines were removed. - // Stability: development - VCSLineChangeTypeRemoved = VCSLineChangeTypeKey.String("removed") -) - -// Enum values for vcs.provider.name -var ( - // [GitHub] - // Stability: development - // - // [GitHub]: https://github.com - VCSProviderNameGithub = VCSProviderNameKey.String("github") - // [GitLab] - // Stability: development - // - // [GitLab]: https://gitlab.com - VCSProviderNameGitlab = VCSProviderNameKey.String("gitlab") - // [Gitea] - // Stability: development - // - // [Gitea]: https://gitea.io - VCSProviderNameGitea = VCSProviderNameKey.String("gitea") - // [Bitbucket] - // Stability: development - // - // [Bitbucket]: https://bitbucket.org - VCSProviderNameBitbucket = VCSProviderNameKey.String("bitbucket") -) - -// Enum values for vcs.ref.base.type -var ( - // [branch] - // Stability: development - // - // [branch]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbranchabranch - VCSRefBaseTypeBranch = VCSRefBaseTypeKey.String("branch") - // [tag] - // Stability: development - // - // [tag]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftagatag - VCSRefBaseTypeTag = VCSRefBaseTypeKey.String("tag") -) - -// Enum values for vcs.ref.head.type -var ( - // [branch] - // Stability: development - // - // [branch]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbranchabranch - VCSRefHeadTypeBranch = VCSRefHeadTypeKey.String("branch") - // [tag] - // Stability: development - // - // [tag]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftagatag - VCSRefHeadTypeTag = VCSRefHeadTypeKey.String("tag") -) - -// Enum values for vcs.ref.type -var ( - // [branch] - // Stability: development - // - // [branch]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbranchabranch - VCSRefTypeBranch = VCSRefTypeKey.String("branch") - // [tag] - // Stability: development - // - // [tag]: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftagatag - VCSRefTypeTag = VCSRefTypeKey.String("tag") -) - -// Enum values for vcs.revision_delta.direction -var ( - // How many revisions the change is behind the target ref. - // Stability: development - VCSRevisionDeltaDirectionBehind = VCSRevisionDeltaDirectionKey.String("behind") - // How many revisions the change is ahead of the target ref. - // Stability: development - VCSRevisionDeltaDirectionAhead = VCSRevisionDeltaDirectionKey.String("ahead") -) - -// Namespace: webengine -const ( - // WebEngineDescriptionKey is the attribute Key conforming to the - // "webengine.description" semantic conventions. It represents the additional - // description of the web engine (e.g. detailed version and edition - // information). - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - - // 2.2.2.Final" - WebEngineDescriptionKey = attribute.Key("webengine.description") - - // WebEngineNameKey is the attribute Key conforming to the "webengine.name" - // semantic conventions. It represents the name of the web engine. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "WildFly" - WebEngineNameKey = attribute.Key("webengine.name") - - // WebEngineVersionKey is the attribute Key conforming to the - // "webengine.version" semantic conventions. It represents the version of the - // web engine. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "21.0.0" - WebEngineVersionKey = attribute.Key("webengine.version") -) - -// WebEngineDescription returns an attribute KeyValue conforming to the -// "webengine.description" semantic conventions. It represents the additional -// description of the web engine (e.g. detailed version and edition information). -func WebEngineDescription(val string) attribute.KeyValue { - return WebEngineDescriptionKey.String(val) -} - -// WebEngineName returns an attribute KeyValue conforming to the "webengine.name" -// semantic conventions. It represents the name of the web engine. -func WebEngineName(val string) attribute.KeyValue { - return WebEngineNameKey.String(val) -} - -// WebEngineVersion returns an attribute KeyValue conforming to the -// "webengine.version" semantic conventions. It represents the version of the web -// engine. -func WebEngineVersion(val string) attribute.KeyValue { - return WebEngineVersionKey.String(val) -} - -// Namespace: zos -const ( - // ZOSSmfIDKey is the attribute Key conforming to the "zos.smf.id" semantic - // conventions. It represents the System Management Facility (SMF) Identifier - // uniquely identified a z/OS system within a SYSPLEX or mainframe environment - // and is used for system and performance analysis. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "SYS1" - ZOSSmfIDKey = attribute.Key("zos.smf.id") - - // ZOSSysplexNameKey is the attribute Key conforming to the "zos.sysplex.name" - // semantic conventions. It represents the name of the SYSPLEX to which the z/OS - // system belongs too. - // - // Type: string - // RequirementLevel: Recommended - // Stability: Development - // - // Examples: "SYSPLEX1" - ZOSSysplexNameKey = attribute.Key("zos.sysplex.name") -) - -// ZOSSmfID returns an attribute KeyValue conforming to the "zos.smf.id" semantic -// conventions. It represents the System Management Facility (SMF) Identifier -// uniquely identified a z/OS system within a SYSPLEX or mainframe environment -// and is used for system and performance analysis. -func ZOSSmfID(val string) attribute.KeyValue { - return ZOSSmfIDKey.String(val) -} - -// ZOSSysplexName returns an attribute KeyValue conforming to the -// "zos.sysplex.name" semantic conventions. It represents the name of the SYSPLEX -// to which the z/OS system belongs too. -func ZOSSysplexName(val string) attribute.KeyValue { - return ZOSSysplexNameKey.String(val) -} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/doc.go b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/doc.go deleted file mode 100644 index b328d4daa2f..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Package semconv implements OpenTelemetry semantic conventions. -// -// OpenTelemetry semantic conventions are agreed standardized naming -// patterns for OpenTelemetry things. This package represents the v1.40.0 -// version of the OpenTelemetry semantic conventions. -package semconv diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/error_type.go b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/error_type.go deleted file mode 100644 index 86020e89426..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/error_type.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv - -import ( - "errors" - "fmt" - "reflect" - - "go.opentelemetry.io/otel/attribute" -) - -// ErrorType returns an [attribute.KeyValue] identifying the error type of err. -// -// If err is nil, the returned attribute has the default value -// [ErrorTypeOther]. -// -// If err or one of the errors in its chain has the method -// -// ErrorType() string -// -// the returned attribute has that method's return value. If multiple errors in -// the chain implement this method, the value from the first match found by -// [errors.As] is used. Otherwise, the returned attribute has a value derived -// from the concrete type of err after unwrapping any wrappers created with -// [fmt.Errorf]. -// -// The key of the returned attribute is [ErrorTypeKey]. -func ErrorType(err error) attribute.KeyValue { - if err == nil { - return ErrorTypeOther - } - - return ErrorTypeKey.String(errorType(err)) -} - -func errorType(err error) string { - var s string - if et, ok := err.(interface{ ErrorType() string }); ok { - // Fast path: check the top-level error first. - s = et.ErrorType() - } else { - // Fallback: search the error chain for an ErrorType method. - var et interface{ ErrorType() string } - if errors.As(err, &et) { - // Prioritize the ErrorType method if available. - s = et.ErrorType() - } - } - if s == "" { - // Fallback to reflection if the ErrorType method is not supported or - // returns an empty value. - - t := reflect.TypeOf(unwrapFmtWrapped(err)) - pkg, name := t.PkgPath(), t.Name() - if pkg != "" && name != "" { - s = pkg + "." + name - } else { - // The type has no package path or name (predeclared, not-defined, - // or alias for a not-defined type). - // - // This is not guaranteed to be unique, but is a best effort. - s = t.String() - } - } - return s -} - -var fmtWrapErrorType = reflect.TypeOf(fmt.Errorf("wrapped: %w", errors.New("err"))) - -func unwrapFmtWrapped(err error) error { - for reflect.TypeOf(err) == fmtWrapErrorType { - u := errors.Unwrap(err) - if u == nil { - return err // Should never happen, but avoid returning nil if unwrapping fails. - } - err = u - } - return err -} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/exception.go b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/exception.go deleted file mode 100644 index 3fe84aae0a9..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/exception.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv - -const ( - // ExceptionEventName is the name of the Span event representing an exception. - ExceptionEventName = "exception" -) diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/otelconv/metric.go b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/otelconv/metric.go deleted file mode 100644 index ba9d29e9d1c..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/otelconv/metric.go +++ /dev/null @@ -1,2298 +0,0 @@ -// Code generated from semantic convention specification. DO NOT EDIT. - -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Package otelconv provides types and functionality for OpenTelemetry semantic -// conventions in the "otel" namespace. -package otelconv - -import ( - "context" - "sync" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" -) - -var ( - addOptPool = &sync.Pool{New: func() any { return &[]metric.AddOption{} }} - recOptPool = &sync.Pool{New: func() any { return &[]metric.RecordOption{} }} -) - -// ErrorTypeAttr is an attribute conforming to the error.type semantic -// conventions. It represents the describes a class of error the operation ended -// with. -type ErrorTypeAttr string - -// ErrorTypeOther is a fallback error value to be used when the instrumentation -// doesn't define a custom value. -var ErrorTypeOther ErrorTypeAttr = "_OTHER" - -// ComponentTypeAttr is an attribute conforming to the otel.component.type -// semantic conventions. It represents a name identifying the type of the -// OpenTelemetry component. -type ComponentTypeAttr string - -var ( - // ComponentTypeBatchingSpanProcessor is the builtin SDK batching span - // processor. - ComponentTypeBatchingSpanProcessor ComponentTypeAttr = "batching_span_processor" - // ComponentTypeSimpleSpanProcessor is the builtin SDK simple span processor. - ComponentTypeSimpleSpanProcessor ComponentTypeAttr = "simple_span_processor" - // ComponentTypeBatchingLogProcessor is the builtin SDK batching log record - // processor. - ComponentTypeBatchingLogProcessor ComponentTypeAttr = "batching_log_processor" - // ComponentTypeSimpleLogProcessor is the builtin SDK simple log record - // processor. - ComponentTypeSimpleLogProcessor ComponentTypeAttr = "simple_log_processor" - // ComponentTypeOtlpGRPCSpanExporter is the OTLP span exporter over gRPC with - // protobuf serialization. - ComponentTypeOtlpGRPCSpanExporter ComponentTypeAttr = "otlp_grpc_span_exporter" - // ComponentTypeOtlpHTTPSpanExporter is the OTLP span exporter over HTTP with - // protobuf serialization. - ComponentTypeOtlpHTTPSpanExporter ComponentTypeAttr = "otlp_http_span_exporter" - // ComponentTypeOtlpHTTPJSONSpanExporter is the OTLP span exporter over HTTP - // with JSON serialization. - ComponentTypeOtlpHTTPJSONSpanExporter ComponentTypeAttr = "otlp_http_json_span_exporter" - // ComponentTypeZipkinHTTPSpanExporter is the zipkin span exporter over HTTP. - ComponentTypeZipkinHTTPSpanExporter ComponentTypeAttr = "zipkin_http_span_exporter" - // ComponentTypeOtlpGRPCLogExporter is the OTLP log record exporter over gRPC - // with protobuf serialization. - ComponentTypeOtlpGRPCLogExporter ComponentTypeAttr = "otlp_grpc_log_exporter" - // ComponentTypeOtlpHTTPLogExporter is the OTLP log record exporter over HTTP - // with protobuf serialization. - ComponentTypeOtlpHTTPLogExporter ComponentTypeAttr = "otlp_http_log_exporter" - // ComponentTypeOtlpHTTPJSONLogExporter is the OTLP log record exporter over - // HTTP with JSON serialization. - ComponentTypeOtlpHTTPJSONLogExporter ComponentTypeAttr = "otlp_http_json_log_exporter" - // ComponentTypePeriodicMetricReader is the builtin SDK periodically exporting - // metric reader. - ComponentTypePeriodicMetricReader ComponentTypeAttr = "periodic_metric_reader" - // ComponentTypeOtlpGRPCMetricExporter is the OTLP metric exporter over gRPC - // with protobuf serialization. - ComponentTypeOtlpGRPCMetricExporter ComponentTypeAttr = "otlp_grpc_metric_exporter" - // ComponentTypeOtlpHTTPMetricExporter is the OTLP metric exporter over HTTP - // with protobuf serialization. - ComponentTypeOtlpHTTPMetricExporter ComponentTypeAttr = "otlp_http_metric_exporter" - // ComponentTypeOtlpHTTPJSONMetricExporter is the OTLP metric exporter over HTTP - // with JSON serialization. - ComponentTypeOtlpHTTPJSONMetricExporter ComponentTypeAttr = "otlp_http_json_metric_exporter" - // ComponentTypePrometheusHTTPTextMetricExporter is the prometheus metric - // exporter over HTTP with the default text-based format. - ComponentTypePrometheusHTTPTextMetricExporter ComponentTypeAttr = "prometheus_http_text_metric_exporter" -) - -// SpanParentOriginAttr is an attribute conforming to the otel.span.parent.origin -// semantic conventions. It represents the determines whether the span has a -// parent span, and if so, [whether it is a remote parent]. -// -// [whether it is a remote parent]: https://opentelemetry.io/docs/specs/otel/trace/api/#isremote -type SpanParentOriginAttr string - -var ( - // SpanParentOriginNone is the span does not have a parent, it is a root span. - SpanParentOriginNone SpanParentOriginAttr = "none" - // SpanParentOriginLocal is the span has a parent and the parent's span context - // [isRemote()] is false. - // - // [isRemote()]: https://opentelemetry.io/docs/specs/otel/trace/api/#isremote - SpanParentOriginLocal SpanParentOriginAttr = "local" - // SpanParentOriginRemote is the span has a parent and the parent's span context - // [isRemote()] is true. - // - // [isRemote()]: https://opentelemetry.io/docs/specs/otel/trace/api/#isremote - SpanParentOriginRemote SpanParentOriginAttr = "remote" -) - -// SpanSamplingResultAttr is an attribute conforming to the -// otel.span.sampling_result semantic conventions. It represents the result value -// of the sampler for this span. -type SpanSamplingResultAttr string - -var ( - // SpanSamplingResultDrop is the span is not sampled and not recording. - SpanSamplingResultDrop SpanSamplingResultAttr = "DROP" - // SpanSamplingResultRecordOnly is the span is not sampled, but recording. - SpanSamplingResultRecordOnly SpanSamplingResultAttr = "RECORD_ONLY" - // SpanSamplingResultRecordAndSample is the span is sampled and recording. - SpanSamplingResultRecordAndSample SpanSamplingResultAttr = "RECORD_AND_SAMPLE" -) - -// SDKExporterLogExported is an instrument used to record metric values -// conforming to the "otel.sdk.exporter.log.exported" semantic conventions. It -// represents the number of log records for which the export has finished, either -// successful or failed. -type SDKExporterLogExported struct { - metric.Int64Counter -} - -var newSDKExporterLogExportedOpts = []metric.Int64CounterOption{ - metric.WithDescription("The number of log records for which the export has finished, either successful or failed."), - metric.WithUnit("{log_record}"), -} - -// NewSDKExporterLogExported returns a new SDKExporterLogExported instrument. -func NewSDKExporterLogExported( - m metric.Meter, - opt ...metric.Int64CounterOption, -) (SDKExporterLogExported, error) { - // Check if the meter is nil. - if m == nil { - return SDKExporterLogExported{noop.Int64Counter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKExporterLogExportedOpts - } else { - opt = append(opt, newSDKExporterLogExportedOpts...) - } - - i, err := m.Int64Counter( - "otel.sdk.exporter.log.exported", - opt..., - ) - if err != nil { - return SDKExporterLogExported{noop.Int64Counter{}}, err - } - return SDKExporterLogExported{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKExporterLogExported) Inst() metric.Int64Counter { - return m.Int64Counter -} - -// Name returns the semantic convention name of the instrument. -func (SDKExporterLogExported) Name() string { - return "otel.sdk.exporter.log.exported" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKExporterLogExported) Unit() string { - return "{log_record}" -} - -// Description returns the semantic convention description of the instrument -func (SDKExporterLogExported) Description() string { - return "The number of log records for which the export has finished, either successful or failed." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -// For exporters with partial success semantics (e.g. OTLP with -// `rejected_log_records`), rejected log records MUST count as failed and only -// non-rejected log records count as success. -// If no rejection reason is available, `rejected` SHOULD be used as value for -// `error.type`. -func (m SDKExporterLogExported) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -// For exporters with partial success semantics (e.g. OTLP with -// `rejected_log_records`), rejected log records MUST count as failed and only -// non-rejected log records count as success. -// If no rejection reason is available, `rejected` SHOULD be used as value for -// `error.type`. -func (m SDKExporterLogExported) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AttrErrorType returns an optional attribute for the "error.type" semantic -// convention. It represents the describes a class of error the operation ended -// with. -func (SDKExporterLogExported) AttrErrorType(val ErrorTypeAttr) attribute.KeyValue { - return attribute.String("error.type", string(val)) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKExporterLogExported) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKExporterLogExported) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// AttrServerAddress returns an optional attribute for the "server.address" -// semantic convention. It represents the server domain name if available without -// reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func (SDKExporterLogExported) AttrServerAddress(val string) attribute.KeyValue { - return attribute.String("server.address", val) -} - -// AttrServerPort returns an optional attribute for the "server.port" semantic -// convention. It represents the server port number. -func (SDKExporterLogExported) AttrServerPort(val int) attribute.KeyValue { - return attribute.Int("server.port", val) -} - -// SDKExporterLogInflight is an instrument used to record metric values -// conforming to the "otel.sdk.exporter.log.inflight" semantic conventions. It -// represents the number of log records which were passed to the exporter, but -// that have not been exported yet (neither successful, nor failed). -type SDKExporterLogInflight struct { - metric.Int64UpDownCounter -} - -var newSDKExporterLogInflightOpts = []metric.Int64UpDownCounterOption{ - metric.WithDescription("The number of log records which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)."), - metric.WithUnit("{log_record}"), -} - -// NewSDKExporterLogInflight returns a new SDKExporterLogInflight instrument. -func NewSDKExporterLogInflight( - m metric.Meter, - opt ...metric.Int64UpDownCounterOption, -) (SDKExporterLogInflight, error) { - // Check if the meter is nil. - if m == nil { - return SDKExporterLogInflight{noop.Int64UpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKExporterLogInflightOpts - } else { - opt = append(opt, newSDKExporterLogInflightOpts...) - } - - i, err := m.Int64UpDownCounter( - "otel.sdk.exporter.log.inflight", - opt..., - ) - if err != nil { - return SDKExporterLogInflight{noop.Int64UpDownCounter{}}, err - } - return SDKExporterLogInflight{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKExporterLogInflight) Inst() metric.Int64UpDownCounter { - return m.Int64UpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKExporterLogInflight) Name() string { - return "otel.sdk.exporter.log.inflight" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKExporterLogInflight) Unit() string { - return "{log_record}" -} - -// Description returns the semantic convention description of the instrument -func (SDKExporterLogInflight) Description() string { - return "The number of log records which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -func (m SDKExporterLogInflight) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -func (m SDKExporterLogInflight) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKExporterLogInflight) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKExporterLogInflight) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// AttrServerAddress returns an optional attribute for the "server.address" -// semantic convention. It represents the server domain name if available without -// reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func (SDKExporterLogInflight) AttrServerAddress(val string) attribute.KeyValue { - return attribute.String("server.address", val) -} - -// AttrServerPort returns an optional attribute for the "server.port" semantic -// convention. It represents the server port number. -func (SDKExporterLogInflight) AttrServerPort(val int) attribute.KeyValue { - return attribute.Int("server.port", val) -} - -// SDKExporterMetricDataPointExported is an instrument used to record metric -// values conforming to the "otel.sdk.exporter.metric_data_point.exported" -// semantic conventions. It represents the number of metric data points for which -// the export has finished, either successful or failed. -type SDKExporterMetricDataPointExported struct { - metric.Int64Counter -} - -var newSDKExporterMetricDataPointExportedOpts = []metric.Int64CounterOption{ - metric.WithDescription("The number of metric data points for which the export has finished, either successful or failed."), - metric.WithUnit("{data_point}"), -} - -// NewSDKExporterMetricDataPointExported returns a new -// SDKExporterMetricDataPointExported instrument. -func NewSDKExporterMetricDataPointExported( - m metric.Meter, - opt ...metric.Int64CounterOption, -) (SDKExporterMetricDataPointExported, error) { - // Check if the meter is nil. - if m == nil { - return SDKExporterMetricDataPointExported{noop.Int64Counter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKExporterMetricDataPointExportedOpts - } else { - opt = append(opt, newSDKExporterMetricDataPointExportedOpts...) - } - - i, err := m.Int64Counter( - "otel.sdk.exporter.metric_data_point.exported", - opt..., - ) - if err != nil { - return SDKExporterMetricDataPointExported{noop.Int64Counter{}}, err - } - return SDKExporterMetricDataPointExported{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKExporterMetricDataPointExported) Inst() metric.Int64Counter { - return m.Int64Counter -} - -// Name returns the semantic convention name of the instrument. -func (SDKExporterMetricDataPointExported) Name() string { - return "otel.sdk.exporter.metric_data_point.exported" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKExporterMetricDataPointExported) Unit() string { - return "{data_point}" -} - -// Description returns the semantic convention description of the instrument -func (SDKExporterMetricDataPointExported) Description() string { - return "The number of metric data points for which the export has finished, either successful or failed." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -// For exporters with partial success semantics (e.g. OTLP with -// `rejected_data_points`), rejected data points MUST count as failed and only -// non-rejected data points count as success. -// If no rejection reason is available, `rejected` SHOULD be used as value for -// `error.type`. -func (m SDKExporterMetricDataPointExported) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -// For exporters with partial success semantics (e.g. OTLP with -// `rejected_data_points`), rejected data points MUST count as failed and only -// non-rejected data points count as success. -// If no rejection reason is available, `rejected` SHOULD be used as value for -// `error.type`. -func (m SDKExporterMetricDataPointExported) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AttrErrorType returns an optional attribute for the "error.type" semantic -// convention. It represents the describes a class of error the operation ended -// with. -func (SDKExporterMetricDataPointExported) AttrErrorType(val ErrorTypeAttr) attribute.KeyValue { - return attribute.String("error.type", string(val)) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKExporterMetricDataPointExported) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKExporterMetricDataPointExported) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// AttrServerAddress returns an optional attribute for the "server.address" -// semantic convention. It represents the server domain name if available without -// reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func (SDKExporterMetricDataPointExported) AttrServerAddress(val string) attribute.KeyValue { - return attribute.String("server.address", val) -} - -// AttrServerPort returns an optional attribute for the "server.port" semantic -// convention. It represents the server port number. -func (SDKExporterMetricDataPointExported) AttrServerPort(val int) attribute.KeyValue { - return attribute.Int("server.port", val) -} - -// SDKExporterMetricDataPointInflight is an instrument used to record metric -// values conforming to the "otel.sdk.exporter.metric_data_point.inflight" -// semantic conventions. It represents the number of metric data points which -// were passed to the exporter, but that have not been exported yet (neither -// successful, nor failed). -type SDKExporterMetricDataPointInflight struct { - metric.Int64UpDownCounter -} - -var newSDKExporterMetricDataPointInflightOpts = []metric.Int64UpDownCounterOption{ - metric.WithDescription("The number of metric data points which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)."), - metric.WithUnit("{data_point}"), -} - -// NewSDKExporterMetricDataPointInflight returns a new -// SDKExporterMetricDataPointInflight instrument. -func NewSDKExporterMetricDataPointInflight( - m metric.Meter, - opt ...metric.Int64UpDownCounterOption, -) (SDKExporterMetricDataPointInflight, error) { - // Check if the meter is nil. - if m == nil { - return SDKExporterMetricDataPointInflight{noop.Int64UpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKExporterMetricDataPointInflightOpts - } else { - opt = append(opt, newSDKExporterMetricDataPointInflightOpts...) - } - - i, err := m.Int64UpDownCounter( - "otel.sdk.exporter.metric_data_point.inflight", - opt..., - ) - if err != nil { - return SDKExporterMetricDataPointInflight{noop.Int64UpDownCounter{}}, err - } - return SDKExporterMetricDataPointInflight{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKExporterMetricDataPointInflight) Inst() metric.Int64UpDownCounter { - return m.Int64UpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKExporterMetricDataPointInflight) Name() string { - return "otel.sdk.exporter.metric_data_point.inflight" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKExporterMetricDataPointInflight) Unit() string { - return "{data_point}" -} - -// Description returns the semantic convention description of the instrument -func (SDKExporterMetricDataPointInflight) Description() string { - return "The number of metric data points which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -func (m SDKExporterMetricDataPointInflight) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -func (m SDKExporterMetricDataPointInflight) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKExporterMetricDataPointInflight) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKExporterMetricDataPointInflight) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// AttrServerAddress returns an optional attribute for the "server.address" -// semantic convention. It represents the server domain name if available without -// reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func (SDKExporterMetricDataPointInflight) AttrServerAddress(val string) attribute.KeyValue { - return attribute.String("server.address", val) -} - -// AttrServerPort returns an optional attribute for the "server.port" semantic -// convention. It represents the server port number. -func (SDKExporterMetricDataPointInflight) AttrServerPort(val int) attribute.KeyValue { - return attribute.Int("server.port", val) -} - -// SDKExporterOperationDuration is an instrument used to record metric values -// conforming to the "otel.sdk.exporter.operation.duration" semantic conventions. -// It represents the duration of exporting a batch of telemetry records. -type SDKExporterOperationDuration struct { - metric.Float64Histogram -} - -var newSDKExporterOperationDurationOpts = []metric.Float64HistogramOption{ - metric.WithDescription("The duration of exporting a batch of telemetry records."), - metric.WithUnit("s"), -} - -// NewSDKExporterOperationDuration returns a new SDKExporterOperationDuration -// instrument. -func NewSDKExporterOperationDuration( - m metric.Meter, - opt ...metric.Float64HistogramOption, -) (SDKExporterOperationDuration, error) { - // Check if the meter is nil. - if m == nil { - return SDKExporterOperationDuration{noop.Float64Histogram{}}, nil - } - - if len(opt) == 0 { - opt = newSDKExporterOperationDurationOpts - } else { - opt = append(opt, newSDKExporterOperationDurationOpts...) - } - - i, err := m.Float64Histogram( - "otel.sdk.exporter.operation.duration", - opt..., - ) - if err != nil { - return SDKExporterOperationDuration{noop.Float64Histogram{}}, err - } - return SDKExporterOperationDuration{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKExporterOperationDuration) Inst() metric.Float64Histogram { - return m.Float64Histogram -} - -// Name returns the semantic convention name of the instrument. -func (SDKExporterOperationDuration) Name() string { - return "otel.sdk.exporter.operation.duration" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKExporterOperationDuration) Unit() string { - return "s" -} - -// Description returns the semantic convention description of the instrument -func (SDKExporterOperationDuration) Description() string { - return "The duration of exporting a batch of telemetry records." -} - -// Record records val to the current distribution for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// This metric defines successful operations using the full success definitions -// for [http] -// and [grpc]. Anything else is defined as an unsuccessful operation. For -// successful -// operations, `error.type` MUST NOT be set. For unsuccessful export operations, -// `error.type` MUST contain a relevant failure cause. -// -// [http]: https://github.com/open-telemetry/opentelemetry-proto/blob/v1.5.0/docs/specification.md#full-success-1 -// [grpc]: https://github.com/open-telemetry/opentelemetry-proto/blob/v1.5.0/docs/specification.md#full-success -func (m SDKExporterOperationDuration) Record( - ctx context.Context, - val float64, - attrs ...attribute.KeyValue, -) { - if !m.Float64Histogram.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Float64Histogram.Record(ctx, val) - return - } - - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Float64Histogram.Record(ctx, val, *o...) -} - -// RecordSet records val to the current distribution for set. -// -// This metric defines successful operations using the full success definitions -// for [http] -// and [grpc]. Anything else is defined as an unsuccessful operation. For -// successful -// operations, `error.type` MUST NOT be set. For unsuccessful export operations, -// `error.type` MUST contain a relevant failure cause. -// -// [http]: https://github.com/open-telemetry/opentelemetry-proto/blob/v1.5.0/docs/specification.md#full-success-1 -// [grpc]: https://github.com/open-telemetry/opentelemetry-proto/blob/v1.5.0/docs/specification.md#full-success -func (m SDKExporterOperationDuration) RecordSet(ctx context.Context, val float64, set attribute.Set) { - if !m.Float64Histogram.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Float64Histogram.Record(ctx, val) - return - } - - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Float64Histogram.Record(ctx, val, *o...) -} - -// AttrErrorType returns an optional attribute for the "error.type" semantic -// convention. It represents the describes a class of error the operation ended -// with. -func (SDKExporterOperationDuration) AttrErrorType(val ErrorTypeAttr) attribute.KeyValue { - return attribute.String("error.type", string(val)) -} - -// AttrHTTPResponseStatusCode returns an optional attribute for the -// "http.response.status_code" semantic convention. It represents the HTTP status -// code of the last HTTP request performed in scope of this export call. -func (SDKExporterOperationDuration) AttrHTTPResponseStatusCode(val int) attribute.KeyValue { - return attribute.Int("http.response.status_code", val) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKExporterOperationDuration) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKExporterOperationDuration) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// AttrRPCResponseStatusCode returns an optional attribute for the -// "rpc.response.status_code" semantic convention. It represents the gRPC status -// code of the last gRPC request performed in scope of this export call. -func (SDKExporterOperationDuration) AttrRPCResponseStatusCode(val string) attribute.KeyValue { - return attribute.String("rpc.response.status_code", val) -} - -// AttrServerAddress returns an optional attribute for the "server.address" -// semantic convention. It represents the server domain name if available without -// reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func (SDKExporterOperationDuration) AttrServerAddress(val string) attribute.KeyValue { - return attribute.String("server.address", val) -} - -// AttrServerPort returns an optional attribute for the "server.port" semantic -// convention. It represents the server port number. -func (SDKExporterOperationDuration) AttrServerPort(val int) attribute.KeyValue { - return attribute.Int("server.port", val) -} - -// SDKExporterSpanExported is an instrument used to record metric values -// conforming to the "otel.sdk.exporter.span.exported" semantic conventions. It -// represents the number of spans for which the export has finished, either -// successful or failed. -type SDKExporterSpanExported struct { - metric.Int64Counter -} - -var newSDKExporterSpanExportedOpts = []metric.Int64CounterOption{ - metric.WithDescription("The number of spans for which the export has finished, either successful or failed."), - metric.WithUnit("{span}"), -} - -// NewSDKExporterSpanExported returns a new SDKExporterSpanExported instrument. -func NewSDKExporterSpanExported( - m metric.Meter, - opt ...metric.Int64CounterOption, -) (SDKExporterSpanExported, error) { - // Check if the meter is nil. - if m == nil { - return SDKExporterSpanExported{noop.Int64Counter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKExporterSpanExportedOpts - } else { - opt = append(opt, newSDKExporterSpanExportedOpts...) - } - - i, err := m.Int64Counter( - "otel.sdk.exporter.span.exported", - opt..., - ) - if err != nil { - return SDKExporterSpanExported{noop.Int64Counter{}}, err - } - return SDKExporterSpanExported{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKExporterSpanExported) Inst() metric.Int64Counter { - return m.Int64Counter -} - -// Name returns the semantic convention name of the instrument. -func (SDKExporterSpanExported) Name() string { - return "otel.sdk.exporter.span.exported" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKExporterSpanExported) Unit() string { - return "{span}" -} - -// Description returns the semantic convention description of the instrument -func (SDKExporterSpanExported) Description() string { - return "The number of spans for which the export has finished, either successful or failed." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -// For exporters with partial success semantics (e.g. OTLP with `rejected_spans` -// ), rejected spans MUST count as failed and only non-rejected spans count as -// success. -// If no rejection reason is available, `rejected` SHOULD be used as value for -// `error.type`. -func (m SDKExporterSpanExported) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -// For exporters with partial success semantics (e.g. OTLP with `rejected_spans` -// ), rejected spans MUST count as failed and only non-rejected spans count as -// success. -// If no rejection reason is available, `rejected` SHOULD be used as value for -// `error.type`. -func (m SDKExporterSpanExported) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AttrErrorType returns an optional attribute for the "error.type" semantic -// convention. It represents the describes a class of error the operation ended -// with. -func (SDKExporterSpanExported) AttrErrorType(val ErrorTypeAttr) attribute.KeyValue { - return attribute.String("error.type", string(val)) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKExporterSpanExported) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKExporterSpanExported) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// AttrServerAddress returns an optional attribute for the "server.address" -// semantic convention. It represents the server domain name if available without -// reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func (SDKExporterSpanExported) AttrServerAddress(val string) attribute.KeyValue { - return attribute.String("server.address", val) -} - -// AttrServerPort returns an optional attribute for the "server.port" semantic -// convention. It represents the server port number. -func (SDKExporterSpanExported) AttrServerPort(val int) attribute.KeyValue { - return attribute.Int("server.port", val) -} - -// SDKExporterSpanInflight is an instrument used to record metric values -// conforming to the "otel.sdk.exporter.span.inflight" semantic conventions. It -// represents the number of spans which were passed to the exporter, but that -// have not been exported yet (neither successful, nor failed). -type SDKExporterSpanInflight struct { - metric.Int64UpDownCounter -} - -var newSDKExporterSpanInflightOpts = []metric.Int64UpDownCounterOption{ - metric.WithDescription("The number of spans which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)."), - metric.WithUnit("{span}"), -} - -// NewSDKExporterSpanInflight returns a new SDKExporterSpanInflight instrument. -func NewSDKExporterSpanInflight( - m metric.Meter, - opt ...metric.Int64UpDownCounterOption, -) (SDKExporterSpanInflight, error) { - // Check if the meter is nil. - if m == nil { - return SDKExporterSpanInflight{noop.Int64UpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKExporterSpanInflightOpts - } else { - opt = append(opt, newSDKExporterSpanInflightOpts...) - } - - i, err := m.Int64UpDownCounter( - "otel.sdk.exporter.span.inflight", - opt..., - ) - if err != nil { - return SDKExporterSpanInflight{noop.Int64UpDownCounter{}}, err - } - return SDKExporterSpanInflight{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKExporterSpanInflight) Inst() metric.Int64UpDownCounter { - return m.Int64UpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKExporterSpanInflight) Name() string { - return "otel.sdk.exporter.span.inflight" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKExporterSpanInflight) Unit() string { - return "{span}" -} - -// Description returns the semantic convention description of the instrument -func (SDKExporterSpanInflight) Description() string { - return "The number of spans which were passed to the exporter, but that have not been exported yet (neither successful, nor failed)." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -func (m SDKExporterSpanInflight) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful exports, `error.type` MUST NOT be set. For failed exports, -// `error.type` MUST contain the failure cause. -func (m SDKExporterSpanInflight) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKExporterSpanInflight) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKExporterSpanInflight) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// AttrServerAddress returns an optional attribute for the "server.address" -// semantic convention. It represents the server domain name if available without -// reverse DNS lookup; otherwise, IP address or Unix domain socket name. -func (SDKExporterSpanInflight) AttrServerAddress(val string) attribute.KeyValue { - return attribute.String("server.address", val) -} - -// AttrServerPort returns an optional attribute for the "server.port" semantic -// convention. It represents the server port number. -func (SDKExporterSpanInflight) AttrServerPort(val int) attribute.KeyValue { - return attribute.Int("server.port", val) -} - -// SDKLogCreated is an instrument used to record metric values conforming to the -// "otel.sdk.log.created" semantic conventions. It represents the number of logs -// submitted to enabled SDK Loggers. -type SDKLogCreated struct { - metric.Int64Counter -} - -var newSDKLogCreatedOpts = []metric.Int64CounterOption{ - metric.WithDescription("The number of logs submitted to enabled SDK Loggers."), - metric.WithUnit("{log_record}"), -} - -// NewSDKLogCreated returns a new SDKLogCreated instrument. -func NewSDKLogCreated( - m metric.Meter, - opt ...metric.Int64CounterOption, -) (SDKLogCreated, error) { - // Check if the meter is nil. - if m == nil { - return SDKLogCreated{noop.Int64Counter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKLogCreatedOpts - } else { - opt = append(opt, newSDKLogCreatedOpts...) - } - - i, err := m.Int64Counter( - "otel.sdk.log.created", - opt..., - ) - if err != nil { - return SDKLogCreated{noop.Int64Counter{}}, err - } - return SDKLogCreated{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKLogCreated) Inst() metric.Int64Counter { - return m.Int64Counter -} - -// Name returns the semantic convention name of the instrument. -func (SDKLogCreated) Name() string { - return "otel.sdk.log.created" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKLogCreated) Unit() string { - return "{log_record}" -} - -// Description returns the semantic convention description of the instrument -func (SDKLogCreated) Description() string { - return "The number of logs submitted to enabled SDK Loggers." -} - -// Add adds incr to the existing count for attrs. -func (m SDKLogCreated) Add(ctx context.Context, incr int64, attrs ...attribute.KeyValue) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributes(attrs...)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -func (m SDKLogCreated) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// SDKMetricReaderCollectionDuration is an instrument used to record metric -// values conforming to the "otel.sdk.metric_reader.collection.duration" semantic -// conventions. It represents the duration of the collect operation of the metric -// reader. -type SDKMetricReaderCollectionDuration struct { - metric.Float64Histogram -} - -var newSDKMetricReaderCollectionDurationOpts = []metric.Float64HistogramOption{ - metric.WithDescription("The duration of the collect operation of the metric reader."), - metric.WithUnit("s"), -} - -// NewSDKMetricReaderCollectionDuration returns a new -// SDKMetricReaderCollectionDuration instrument. -func NewSDKMetricReaderCollectionDuration( - m metric.Meter, - opt ...metric.Float64HistogramOption, -) (SDKMetricReaderCollectionDuration, error) { - // Check if the meter is nil. - if m == nil { - return SDKMetricReaderCollectionDuration{noop.Float64Histogram{}}, nil - } - - if len(opt) == 0 { - opt = newSDKMetricReaderCollectionDurationOpts - } else { - opt = append(opt, newSDKMetricReaderCollectionDurationOpts...) - } - - i, err := m.Float64Histogram( - "otel.sdk.metric_reader.collection.duration", - opt..., - ) - if err != nil { - return SDKMetricReaderCollectionDuration{noop.Float64Histogram{}}, err - } - return SDKMetricReaderCollectionDuration{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKMetricReaderCollectionDuration) Inst() metric.Float64Histogram { - return m.Float64Histogram -} - -// Name returns the semantic convention name of the instrument. -func (SDKMetricReaderCollectionDuration) Name() string { - return "otel.sdk.metric_reader.collection.duration" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKMetricReaderCollectionDuration) Unit() string { - return "s" -} - -// Description returns the semantic convention description of the instrument -func (SDKMetricReaderCollectionDuration) Description() string { - return "The duration of the collect operation of the metric reader." -} - -// Record records val to the current distribution for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful collections, `error.type` MUST NOT be set. For failed -// collections, `error.type` SHOULD contain the failure cause. -// It can happen that metrics collection is successful for some MetricProducers, -// while others fail. In that case `error.type` SHOULD be set to any of the -// failure causes. -func (m SDKMetricReaderCollectionDuration) Record( - ctx context.Context, - val float64, - attrs ...attribute.KeyValue, -) { - if !m.Float64Histogram.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Float64Histogram.Record(ctx, val) - return - } - - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Float64Histogram.Record(ctx, val, *o...) -} - -// RecordSet records val to the current distribution for set. -// -// For successful collections, `error.type` MUST NOT be set. For failed -// collections, `error.type` SHOULD contain the failure cause. -// It can happen that metrics collection is successful for some MetricProducers, -// while others fail. In that case `error.type` SHOULD be set to any of the -// failure causes. -func (m SDKMetricReaderCollectionDuration) RecordSet(ctx context.Context, val float64, set attribute.Set) { - if !m.Float64Histogram.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Float64Histogram.Record(ctx, val) - return - } - - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Float64Histogram.Record(ctx, val, *o...) -} - -// AttrErrorType returns an optional attribute for the "error.type" semantic -// convention. It represents the describes a class of error the operation ended -// with. -func (SDKMetricReaderCollectionDuration) AttrErrorType(val ErrorTypeAttr) attribute.KeyValue { - return attribute.String("error.type", string(val)) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKMetricReaderCollectionDuration) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKMetricReaderCollectionDuration) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// SDKProcessorLogProcessed is an instrument used to record metric values -// conforming to the "otel.sdk.processor.log.processed" semantic conventions. It -// represents the number of log records for which the processing has finished, -// either successful or failed. -type SDKProcessorLogProcessed struct { - metric.Int64Counter -} - -var newSDKProcessorLogProcessedOpts = []metric.Int64CounterOption{ - metric.WithDescription("The number of log records for which the processing has finished, either successful or failed."), - metric.WithUnit("{log_record}"), -} - -// NewSDKProcessorLogProcessed returns a new SDKProcessorLogProcessed instrument. -func NewSDKProcessorLogProcessed( - m metric.Meter, - opt ...metric.Int64CounterOption, -) (SDKProcessorLogProcessed, error) { - // Check if the meter is nil. - if m == nil { - return SDKProcessorLogProcessed{noop.Int64Counter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKProcessorLogProcessedOpts - } else { - opt = append(opt, newSDKProcessorLogProcessedOpts...) - } - - i, err := m.Int64Counter( - "otel.sdk.processor.log.processed", - opt..., - ) - if err != nil { - return SDKProcessorLogProcessed{noop.Int64Counter{}}, err - } - return SDKProcessorLogProcessed{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKProcessorLogProcessed) Inst() metric.Int64Counter { - return m.Int64Counter -} - -// Name returns the semantic convention name of the instrument. -func (SDKProcessorLogProcessed) Name() string { - return "otel.sdk.processor.log.processed" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKProcessorLogProcessed) Unit() string { - return "{log_record}" -} - -// Description returns the semantic convention description of the instrument -func (SDKProcessorLogProcessed) Description() string { - return "The number of log records for which the processing has finished, either successful or failed." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful processing, `error.type` MUST NOT be set. For failed -// processing, `error.type` MUST contain the failure cause. -// For the SDK Simple and Batching Log Record Processor a log record is -// considered to be processed already when it has been submitted to the exporter, -// not when the corresponding export call has finished. -func (m SDKProcessorLogProcessed) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful processing, `error.type` MUST NOT be set. For failed -// processing, `error.type` MUST contain the failure cause. -// For the SDK Simple and Batching Log Record Processor a log record is -// considered to be processed already when it has been submitted to the exporter, -// not when the corresponding export call has finished. -func (m SDKProcessorLogProcessed) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AttrErrorType returns an optional attribute for the "error.type" semantic -// convention. It represents a low-cardinality description of the failure reason. -// SDK Batching Log Record Processors MUST use `queue_full` for log records -// dropped due to a full queue. -func (SDKProcessorLogProcessed) AttrErrorType(val ErrorTypeAttr) attribute.KeyValue { - return attribute.String("error.type", string(val)) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKProcessorLogProcessed) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKProcessorLogProcessed) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// SDKProcessorLogQueueCapacity is an instrument used to record metric values -// conforming to the "otel.sdk.processor.log.queue.capacity" semantic -// conventions. It represents the maximum number of log records the queue of a -// given instance of an SDK Log Record processor can hold. -type SDKProcessorLogQueueCapacity struct { - metric.Int64ObservableUpDownCounter -} - -var newSDKProcessorLogQueueCapacityOpts = []metric.Int64ObservableUpDownCounterOption{ - metric.WithDescription("The maximum number of log records the queue of a given instance of an SDK Log Record processor can hold."), - metric.WithUnit("{log_record}"), -} - -// NewSDKProcessorLogQueueCapacity returns a new SDKProcessorLogQueueCapacity -// instrument. -func NewSDKProcessorLogQueueCapacity( - m metric.Meter, - opt ...metric.Int64ObservableUpDownCounterOption, -) (SDKProcessorLogQueueCapacity, error) { - // Check if the meter is nil. - if m == nil { - return SDKProcessorLogQueueCapacity{noop.Int64ObservableUpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKProcessorLogQueueCapacityOpts - } else { - opt = append(opt, newSDKProcessorLogQueueCapacityOpts...) - } - - i, err := m.Int64ObservableUpDownCounter( - "otel.sdk.processor.log.queue.capacity", - opt..., - ) - if err != nil { - return SDKProcessorLogQueueCapacity{noop.Int64ObservableUpDownCounter{}}, err - } - return SDKProcessorLogQueueCapacity{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKProcessorLogQueueCapacity) Inst() metric.Int64ObservableUpDownCounter { - return m.Int64ObservableUpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKProcessorLogQueueCapacity) Name() string { - return "otel.sdk.processor.log.queue.capacity" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKProcessorLogQueueCapacity) Unit() string { - return "{log_record}" -} - -// Description returns the semantic convention description of the instrument -func (SDKProcessorLogQueueCapacity) Description() string { - return "The maximum number of log records the queue of a given instance of an SDK Log Record processor can hold." -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKProcessorLogQueueCapacity) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKProcessorLogQueueCapacity) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// SDKProcessorLogQueueSize is an instrument used to record metric values -// conforming to the "otel.sdk.processor.log.queue.size" semantic conventions. It -// represents the number of log records in the queue of a given instance of an -// SDK log processor. -type SDKProcessorLogQueueSize struct { - metric.Int64ObservableUpDownCounter -} - -var newSDKProcessorLogQueueSizeOpts = []metric.Int64ObservableUpDownCounterOption{ - metric.WithDescription("The number of log records in the queue of a given instance of an SDK log processor."), - metric.WithUnit("{log_record}"), -} - -// NewSDKProcessorLogQueueSize returns a new SDKProcessorLogQueueSize instrument. -func NewSDKProcessorLogQueueSize( - m metric.Meter, - opt ...metric.Int64ObservableUpDownCounterOption, -) (SDKProcessorLogQueueSize, error) { - // Check if the meter is nil. - if m == nil { - return SDKProcessorLogQueueSize{noop.Int64ObservableUpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKProcessorLogQueueSizeOpts - } else { - opt = append(opt, newSDKProcessorLogQueueSizeOpts...) - } - - i, err := m.Int64ObservableUpDownCounter( - "otel.sdk.processor.log.queue.size", - opt..., - ) - if err != nil { - return SDKProcessorLogQueueSize{noop.Int64ObservableUpDownCounter{}}, err - } - return SDKProcessorLogQueueSize{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKProcessorLogQueueSize) Inst() metric.Int64ObservableUpDownCounter { - return m.Int64ObservableUpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKProcessorLogQueueSize) Name() string { - return "otel.sdk.processor.log.queue.size" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKProcessorLogQueueSize) Unit() string { - return "{log_record}" -} - -// Description returns the semantic convention description of the instrument -func (SDKProcessorLogQueueSize) Description() string { - return "The number of log records in the queue of a given instance of an SDK log processor." -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKProcessorLogQueueSize) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKProcessorLogQueueSize) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// SDKProcessorSpanProcessed is an instrument used to record metric values -// conforming to the "otel.sdk.processor.span.processed" semantic conventions. It -// represents the number of spans for which the processing has finished, either -// successful or failed. -type SDKProcessorSpanProcessed struct { - metric.Int64Counter -} - -var newSDKProcessorSpanProcessedOpts = []metric.Int64CounterOption{ - metric.WithDescription("The number of spans for which the processing has finished, either successful or failed."), - metric.WithUnit("{span}"), -} - -// NewSDKProcessorSpanProcessed returns a new SDKProcessorSpanProcessed -// instrument. -func NewSDKProcessorSpanProcessed( - m metric.Meter, - opt ...metric.Int64CounterOption, -) (SDKProcessorSpanProcessed, error) { - // Check if the meter is nil. - if m == nil { - return SDKProcessorSpanProcessed{noop.Int64Counter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKProcessorSpanProcessedOpts - } else { - opt = append(opt, newSDKProcessorSpanProcessedOpts...) - } - - i, err := m.Int64Counter( - "otel.sdk.processor.span.processed", - opt..., - ) - if err != nil { - return SDKProcessorSpanProcessed{noop.Int64Counter{}}, err - } - return SDKProcessorSpanProcessed{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKProcessorSpanProcessed) Inst() metric.Int64Counter { - return m.Int64Counter -} - -// Name returns the semantic convention name of the instrument. -func (SDKProcessorSpanProcessed) Name() string { - return "otel.sdk.processor.span.processed" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKProcessorSpanProcessed) Unit() string { - return "{span}" -} - -// Description returns the semantic convention description of the instrument -func (SDKProcessorSpanProcessed) Description() string { - return "The number of spans for which the processing has finished, either successful or failed." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// For successful processing, `error.type` MUST NOT be set. For failed -// processing, `error.type` MUST contain the failure cause. -// For the SDK Simple and Batching Span Processor a span is considered to be -// processed already when it has been submitted to the exporter, not when the -// corresponding export call has finished. -func (m SDKProcessorSpanProcessed) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// For successful processing, `error.type` MUST NOT be set. For failed -// processing, `error.type` MUST contain the failure cause. -// For the SDK Simple and Batching Span Processor a span is considered to be -// processed already when it has been submitted to the exporter, not when the -// corresponding export call has finished. -func (m SDKProcessorSpanProcessed) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AttrErrorType returns an optional attribute for the "error.type" semantic -// convention. It represents a low-cardinality description of the failure reason. -// SDK Batching Span Processors MUST use `queue_full` for spans dropped due to a -// full queue. -func (SDKProcessorSpanProcessed) AttrErrorType(val ErrorTypeAttr) attribute.KeyValue { - return attribute.String("error.type", string(val)) -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKProcessorSpanProcessed) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKProcessorSpanProcessed) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// SDKProcessorSpanQueueCapacity is an instrument used to record metric values -// conforming to the "otel.sdk.processor.span.queue.capacity" semantic -// conventions. It represents the maximum number of spans the queue of a given -// instance of an SDK span processor can hold. -type SDKProcessorSpanQueueCapacity struct { - metric.Int64ObservableUpDownCounter -} - -var newSDKProcessorSpanQueueCapacityOpts = []metric.Int64ObservableUpDownCounterOption{ - metric.WithDescription("The maximum number of spans the queue of a given instance of an SDK span processor can hold."), - metric.WithUnit("{span}"), -} - -// NewSDKProcessorSpanQueueCapacity returns a new SDKProcessorSpanQueueCapacity -// instrument. -func NewSDKProcessorSpanQueueCapacity( - m metric.Meter, - opt ...metric.Int64ObservableUpDownCounterOption, -) (SDKProcessorSpanQueueCapacity, error) { - // Check if the meter is nil. - if m == nil { - return SDKProcessorSpanQueueCapacity{noop.Int64ObservableUpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKProcessorSpanQueueCapacityOpts - } else { - opt = append(opt, newSDKProcessorSpanQueueCapacityOpts...) - } - - i, err := m.Int64ObservableUpDownCounter( - "otel.sdk.processor.span.queue.capacity", - opt..., - ) - if err != nil { - return SDKProcessorSpanQueueCapacity{noop.Int64ObservableUpDownCounter{}}, err - } - return SDKProcessorSpanQueueCapacity{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKProcessorSpanQueueCapacity) Inst() metric.Int64ObservableUpDownCounter { - return m.Int64ObservableUpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKProcessorSpanQueueCapacity) Name() string { - return "otel.sdk.processor.span.queue.capacity" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKProcessorSpanQueueCapacity) Unit() string { - return "{span}" -} - -// Description returns the semantic convention description of the instrument -func (SDKProcessorSpanQueueCapacity) Description() string { - return "The maximum number of spans the queue of a given instance of an SDK span processor can hold." -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKProcessorSpanQueueCapacity) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKProcessorSpanQueueCapacity) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// SDKProcessorSpanQueueSize is an instrument used to record metric values -// conforming to the "otel.sdk.processor.span.queue.size" semantic conventions. -// It represents the number of spans in the queue of a given instance of an SDK -// span processor. -type SDKProcessorSpanQueueSize struct { - metric.Int64ObservableUpDownCounter -} - -var newSDKProcessorSpanQueueSizeOpts = []metric.Int64ObservableUpDownCounterOption{ - metric.WithDescription("The number of spans in the queue of a given instance of an SDK span processor."), - metric.WithUnit("{span}"), -} - -// NewSDKProcessorSpanQueueSize returns a new SDKProcessorSpanQueueSize -// instrument. -func NewSDKProcessorSpanQueueSize( - m metric.Meter, - opt ...metric.Int64ObservableUpDownCounterOption, -) (SDKProcessorSpanQueueSize, error) { - // Check if the meter is nil. - if m == nil { - return SDKProcessorSpanQueueSize{noop.Int64ObservableUpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKProcessorSpanQueueSizeOpts - } else { - opt = append(opt, newSDKProcessorSpanQueueSizeOpts...) - } - - i, err := m.Int64ObservableUpDownCounter( - "otel.sdk.processor.span.queue.size", - opt..., - ) - if err != nil { - return SDKProcessorSpanQueueSize{noop.Int64ObservableUpDownCounter{}}, err - } - return SDKProcessorSpanQueueSize{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKProcessorSpanQueueSize) Inst() metric.Int64ObservableUpDownCounter { - return m.Int64ObservableUpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKProcessorSpanQueueSize) Name() string { - return "otel.sdk.processor.span.queue.size" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKProcessorSpanQueueSize) Unit() string { - return "{span}" -} - -// Description returns the semantic convention description of the instrument -func (SDKProcessorSpanQueueSize) Description() string { - return "The number of spans in the queue of a given instance of an SDK span processor." -} - -// AttrComponentName returns an optional attribute for the "otel.component.name" -// semantic convention. It represents a name uniquely identifying the instance of -// the OpenTelemetry component within its containing SDK instance. -func (SDKProcessorSpanQueueSize) AttrComponentName(val string) attribute.KeyValue { - return attribute.String("otel.component.name", val) -} - -// AttrComponentType returns an optional attribute for the "otel.component.type" -// semantic convention. It represents a name identifying the type of the -// OpenTelemetry component. -func (SDKProcessorSpanQueueSize) AttrComponentType(val ComponentTypeAttr) attribute.KeyValue { - return attribute.String("otel.component.type", string(val)) -} - -// SDKSpanLive is an instrument used to record metric values conforming to the -// "otel.sdk.span.live" semantic conventions. It represents the number of created -// spans with `recording=true` for which the end operation has not been called -// yet. -type SDKSpanLive struct { - metric.Int64UpDownCounter -} - -var newSDKSpanLiveOpts = []metric.Int64UpDownCounterOption{ - metric.WithDescription("The number of created spans with `recording=true` for which the end operation has not been called yet."), - metric.WithUnit("{span}"), -} - -// NewSDKSpanLive returns a new SDKSpanLive instrument. -func NewSDKSpanLive( - m metric.Meter, - opt ...metric.Int64UpDownCounterOption, -) (SDKSpanLive, error) { - // Check if the meter is nil. - if m == nil { - return SDKSpanLive{noop.Int64UpDownCounter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKSpanLiveOpts - } else { - opt = append(opt, newSDKSpanLiveOpts...) - } - - i, err := m.Int64UpDownCounter( - "otel.sdk.span.live", - opt..., - ) - if err != nil { - return SDKSpanLive{noop.Int64UpDownCounter{}}, err - } - return SDKSpanLive{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKSpanLive) Inst() metric.Int64UpDownCounter { - return m.Int64UpDownCounter -} - -// Name returns the semantic convention name of the instrument. -func (SDKSpanLive) Name() string { - return "otel.sdk.span.live" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKSpanLive) Unit() string { - return "{span}" -} - -// Description returns the semantic convention description of the instrument -func (SDKSpanLive) Description() string { - return "The number of created spans with `recording=true` for which the end operation has not been called yet." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -func (m SDKSpanLive) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -func (m SDKSpanLive) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64UpDownCounter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64UpDownCounter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64UpDownCounter.Add(ctx, incr, *o...) -} - -// AttrSpanSamplingResult returns an optional attribute for the -// "otel.span.sampling_result" semantic convention. It represents the result -// value of the sampler for this span. -func (SDKSpanLive) AttrSpanSamplingResult(val SpanSamplingResultAttr) attribute.KeyValue { - return attribute.String("otel.span.sampling_result", string(val)) -} - -// SDKSpanStarted is an instrument used to record metric values conforming to the -// "otel.sdk.span.started" semantic conventions. It represents the number of -// created spans. -type SDKSpanStarted struct { - metric.Int64Counter -} - -var newSDKSpanStartedOpts = []metric.Int64CounterOption{ - metric.WithDescription("The number of created spans."), - metric.WithUnit("{span}"), -} - -// NewSDKSpanStarted returns a new SDKSpanStarted instrument. -func NewSDKSpanStarted( - m metric.Meter, - opt ...metric.Int64CounterOption, -) (SDKSpanStarted, error) { - // Check if the meter is nil. - if m == nil { - return SDKSpanStarted{noop.Int64Counter{}}, nil - } - - if len(opt) == 0 { - opt = newSDKSpanStartedOpts - } else { - opt = append(opt, newSDKSpanStartedOpts...) - } - - i, err := m.Int64Counter( - "otel.sdk.span.started", - opt..., - ) - if err != nil { - return SDKSpanStarted{noop.Int64Counter{}}, err - } - return SDKSpanStarted{i}, nil -} - -// Inst returns the underlying metric instrument. -func (m SDKSpanStarted) Inst() metric.Int64Counter { - return m.Int64Counter -} - -// Name returns the semantic convention name of the instrument. -func (SDKSpanStarted) Name() string { - return "otel.sdk.span.started" -} - -// Unit returns the semantic convention unit of the instrument -func (SDKSpanStarted) Unit() string { - return "{span}" -} - -// Description returns the semantic convention description of the instrument -func (SDKSpanStarted) Description() string { - return "The number of created spans." -} - -// Add adds incr to the existing count for attrs. -// -// All additional attrs passed are included in the recorded value. -// -// Implementations MUST record this metric for all spans, even for non-recording -// ones. -func (m SDKSpanStarted) Add( - ctx context.Context, - incr int64, - attrs ...attribute.KeyValue, -) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if len(attrs) == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append( - *o, - metric.WithAttributes( - attrs..., - ), - ) - - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AddSet adds incr to the existing count for set. -// -// Implementations MUST record this metric for all spans, even for non-recording -// ones. -func (m SDKSpanStarted) AddSet(ctx context.Context, incr int64, set attribute.Set) { - if !m.Int64Counter.Enabled(ctx) { - return - } - if set.Len() == 0 { - m.Int64Counter.Add(ctx, incr) - return - } - - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() - - *o = append(*o, metric.WithAttributeSet(set)) - m.Int64Counter.Add(ctx, incr, *o...) -} - -// AttrSpanParentOrigin returns an optional attribute for the -// "otel.span.parent.origin" semantic convention. It represents the determines -// whether the span has a parent span, and if so, [whether it is a remote parent] -// . -// -// [whether it is a remote parent]: https://opentelemetry.io/docs/specs/otel/trace/api/#isremote -func (SDKSpanStarted) AttrSpanParentOrigin(val SpanParentOriginAttr) attribute.KeyValue { - return attribute.String("otel.span.parent.origin", string(val)) -} - -// AttrSpanSamplingResult returns an optional attribute for the -// "otel.span.sampling_result" semantic convention. It represents the result -// value of the sampler for this span. -func (SDKSpanStarted) AttrSpanSamplingResult(val SpanSamplingResultAttr) attribute.KeyValue { - return attribute.String("otel.span.sampling_result", string(val)) -} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/schema.go b/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/schema.go deleted file mode 100644 index 5d383cd13eb..00000000000 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/schema.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv - -// SchemaURL is the schema URL that matches the version of the semantic conventions -// that this package defines. Semconv packages starting from v1.4.0 must declare -// non-empty schema URL in the form https://opentelemetry.io/schemas/ -const SchemaURL = "https://opentelemetry.io/schemas/1.40.0" diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/httpconv/metric.go b/vendor/go.opentelemetry.io/otel/semconv/v1.41.0/httpconv/metric.go similarity index 81% rename from vendor/go.opentelemetry.io/otel/semconv/v1.40.0/httpconv/metric.go rename to vendor/go.opentelemetry.io/otel/semconv/v1.41.0/httpconv/metric.go index 013629dc3b6..734cf240947 100644 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.40.0/httpconv/metric.go +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.41.0/httpconv/metric.go @@ -9,16 +9,11 @@ package httpconv import ( "context" - "sync" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/noop" -) - -var ( - addOptPool = &sync.Pool{New: func() any { return &[]metric.AddOption{} }} - recOptPool = &sync.Pool{New: func() any { return &[]metric.RecordOption{} }} + "go.opentelemetry.io/otel/semconv/internal/metricpool" ) // ErrorTypeAttr is an attribute conforming to the error.type semantic @@ -26,9 +21,11 @@ var ( // with. type ErrorTypeAttr string -// ErrorTypeOther is a fallback error value to be used when the instrumentation -// doesn't define a custom value. -var ErrorTypeOther ErrorTypeAttr = "_OTHER" +var ( + // ErrorTypeOther is a fallback error value to be used when the instrumentation + // doesn't define a custom value. + ErrorTypeOther ErrorTypeAttr = "_OTHER" +) // ConnectionStateAttr is an attribute conforming to the http.connection.state // semantic conventions. It represents the state of the HTTP connection in the @@ -168,11 +165,8 @@ func (m ClientActiveRequests) Add( return } - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() + o := metricpool.AddOptions() + defer metricpool.PutAddOptions(o) *o = append( *o, @@ -198,11 +192,8 @@ func (m ClientActiveRequests) AddSet(ctx context.Context, incr int64, set attrib return } - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() + o := metricpool.AddOptions() + defer metricpool.PutAddOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Int64UpDownCounter.Add(ctx, incr, *o...) @@ -232,6 +223,102 @@ func (ClientActiveRequests) AttrURLScheme(val string) attribute.KeyValue { return attribute.String("url.scheme", val) } +// ClientActiveRequestsObservable is an instrument used to record metric values +// conforming to the "http.client.active_requests" semantic conventions. It +// represents the number of active HTTP requests. +type ClientActiveRequestsObservable struct { + metric.Int64ObservableUpDownCounter +} + +var newClientActiveRequestsObservableOpts = []metric.Int64ObservableUpDownCounterOption{ + metric.WithDescription("Number of active HTTP requests."), + metric.WithUnit("{request}"), +} + +// NewClientActiveRequestsObservable returns a new ClientActiveRequestsObservable +// instrument. +func NewClientActiveRequestsObservable( + m metric.Meter, + opt ...metric.Int64ObservableUpDownCounterOption, +) (ClientActiveRequestsObservable, error) { + // Check if the meter is nil. + if m == nil { + return ClientActiveRequestsObservable{noop.Int64ObservableUpDownCounter{}}, nil + } + + if len(opt) == 0 { + opt = newClientActiveRequestsObservableOpts + } else { + opt = append(opt, newClientActiveRequestsObservableOpts...) + } + + i, err := m.Int64ObservableUpDownCounter( + "http.client.active_requests", + opt..., + ) + if err != nil { + return ClientActiveRequestsObservable{noop.Int64ObservableUpDownCounter{}}, err + } + return ClientActiveRequestsObservable{i}, nil +} + +// Inst returns the underlying metric instrument. +func (m ClientActiveRequestsObservable) Inst() metric.Int64ObservableUpDownCounter { + return m.Int64ObservableUpDownCounter +} + +// Name returns the semantic convention name of the instrument. +func (ClientActiveRequestsObservable) Name() string { + return "http.client.active_requests" +} + +// Unit returns the semantic convention unit of the instrument +func (ClientActiveRequestsObservable) Unit() string { + return "{request}" +} + +// Description returns the semantic convention description of the instrument +func (ClientActiveRequestsObservable) Description() string { + return "Number of active HTTP requests." +} + +// AttrServerAddress returns a required attribute for the "server.address" +// semantic convention. It represents the server domain name if available without +// reverse DNS lookup; otherwise, IP address or Unix domain socket name. +func (ClientActiveRequestsObservable) AttrServerAddress(val string) attribute.KeyValue { + return attribute.String("server.address", val) +} + +// AttrServerPort returns a required attribute for the "server.port" semantic +// convention. It represents the server port number. +func (ClientActiveRequestsObservable) AttrServerPort(val int) attribute.KeyValue { + return attribute.Int("server.port", val) +} + +// AttrURLTemplate returns an optional attribute for the "url.template" semantic +// convention. It represents the low-cardinality template of an +// [absolute path reference]. +// +// [absolute path reference]: https://www.rfc-editor.org/rfc/rfc3986#section-4.2 +func (ClientActiveRequestsObservable) AttrURLTemplate(val string) attribute.KeyValue { + return attribute.String("url.template", val) +} + +// AttrRequestMethod returns an optional attribute for the "http.request.method" +// semantic convention. It represents the HTTP request method. +func (ClientActiveRequestsObservable) AttrRequestMethod(val RequestMethodAttr) attribute.KeyValue { + return attribute.String("http.request.method", string(val)) +} + +// AttrURLScheme returns an optional attribute for the "url.scheme" semantic +// convention. It represents the [URI scheme] component identifying the used +// protocol. +// +// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 +func (ClientActiveRequestsObservable) AttrURLScheme(val string) attribute.KeyValue { + return attribute.String("url.scheme", val) +} + // ClientConnectionDuration is an instrument used to record metric values // conforming to the "http.client.connection.duration" semantic conventions. It // represents the duration of the successfully established outbound HTTP @@ -317,11 +404,8 @@ func (m ClientConnectionDuration) Record( return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append( *o, @@ -347,11 +431,8 @@ func (m ClientConnectionDuration) RecordSet(ctx context.Context, val float64, se return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Float64Histogram.Record(ctx, val, *o...) @@ -470,11 +551,8 @@ func (m ClientOpenConnections) Add( return } - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() + o := metricpool.AddOptions() + defer metricpool.PutAddOptions(o) *o = append( *o, @@ -501,11 +579,8 @@ func (m ClientOpenConnections) AddSet(ctx context.Context, incr int64, set attri return } - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() + o := metricpool.AddOptions() + defer metricpool.PutAddOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Int64UpDownCounter.Add(ctx, incr, *o...) @@ -534,6 +609,109 @@ func (ClientOpenConnections) AttrURLScheme(val string) attribute.KeyValue { return attribute.String("url.scheme", val) } +// ClientOpenConnectionsObservable is an instrument used to record metric values +// conforming to the "http.client.open_connections" semantic conventions. It +// represents the number of outbound HTTP connections that are currently active +// or idle on the client. +type ClientOpenConnectionsObservable struct { + metric.Int64ObservableUpDownCounter +} + +var newClientOpenConnectionsObservableOpts = []metric.Int64ObservableUpDownCounterOption{ + metric.WithDescription("Number of outbound HTTP connections that are currently active or idle on the client."), + metric.WithUnit("{connection}"), +} + +// NewClientOpenConnectionsObservable returns a new +// ClientOpenConnectionsObservable instrument. +func NewClientOpenConnectionsObservable( + m metric.Meter, + opt ...metric.Int64ObservableUpDownCounterOption, +) (ClientOpenConnectionsObservable, error) { + // Check if the meter is nil. + if m == nil { + return ClientOpenConnectionsObservable{noop.Int64ObservableUpDownCounter{}}, nil + } + + if len(opt) == 0 { + opt = newClientOpenConnectionsObservableOpts + } else { + opt = append(opt, newClientOpenConnectionsObservableOpts...) + } + + i, err := m.Int64ObservableUpDownCounter( + "http.client.open_connections", + opt..., + ) + if err != nil { + return ClientOpenConnectionsObservable{noop.Int64ObservableUpDownCounter{}}, err + } + return ClientOpenConnectionsObservable{i}, nil +} + +// Inst returns the underlying metric instrument. +func (m ClientOpenConnectionsObservable) Inst() metric.Int64ObservableUpDownCounter { + return m.Int64ObservableUpDownCounter +} + +// Name returns the semantic convention name of the instrument. +func (ClientOpenConnectionsObservable) Name() string { + return "http.client.open_connections" +} + +// Unit returns the semantic convention unit of the instrument +func (ClientOpenConnectionsObservable) Unit() string { + return "{connection}" +} + +// Description returns the semantic convention description of the instrument +func (ClientOpenConnectionsObservable) Description() string { + return "Number of outbound HTTP connections that are currently active or idle on the client." +} + +// AttrConnectionState returns a required attribute for the +// "http.connection.state" semantic convention. It represents the state of the +// HTTP connection in the HTTP connection pool. +func (ClientOpenConnectionsObservable) AttrConnectionState(val ConnectionStateAttr) attribute.KeyValue { + return attribute.String("http.connection.state", string(val)) +} + +// AttrServerAddress returns a required attribute for the "server.address" +// semantic convention. It represents the server domain name if available without +// reverse DNS lookup; otherwise, IP address or Unix domain socket name. +func (ClientOpenConnectionsObservable) AttrServerAddress(val string) attribute.KeyValue { + return attribute.String("server.address", val) +} + +// AttrServerPort returns a required attribute for the "server.port" semantic +// convention. It represents the server port number. +func (ClientOpenConnectionsObservable) AttrServerPort(val int) attribute.KeyValue { + return attribute.Int("server.port", val) +} + +// AttrNetworkPeerAddress returns an optional attribute for the +// "network.peer.address" semantic convention. It represents the peer address of +// the network connection - IP address or Unix domain socket name. +func (ClientOpenConnectionsObservable) AttrNetworkPeerAddress(val string) attribute.KeyValue { + return attribute.String("network.peer.address", val) +} + +// AttrNetworkProtocolVersion returns an optional attribute for the +// "network.protocol.version" semantic convention. It represents the actual +// version of the protocol used for network communication. +func (ClientOpenConnectionsObservable) AttrNetworkProtocolVersion(val string) attribute.KeyValue { + return attribute.String("network.protocol.version", val) +} + +// AttrURLScheme returns an optional attribute for the "url.scheme" semantic +// convention. It represents the [URI scheme] component identifying the used +// protocol. +// +// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 +func (ClientOpenConnectionsObservable) AttrURLScheme(val string) attribute.KeyValue { + return attribute.String("url.scheme", val) +} + // ClientRequestBodySize is an instrument used to record metric values conforming // to the "http.client.request.body.size" semantic conventions. It represents the // size of HTTP client request bodies. @@ -629,11 +807,8 @@ func (m ClientRequestBodySize) Record( return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append( *o, @@ -667,11 +842,8 @@ func (m ClientRequestBodySize) RecordSet(ctx context.Context, val int64, set att return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Int64Histogram.Record(ctx, val, *o...) @@ -737,6 +909,7 @@ type ClientRequestDuration struct { var newClientRequestDurationOpts = []metric.Float64HistogramOption{ metric.WithDescription("Duration of HTTP client requests."), metric.WithUnit("s"), + metric.WithExplicitBucketBoundaries([]float64{0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10}...), } // NewClientRequestDuration returns a new ClientRequestDuration instrument. @@ -815,11 +988,8 @@ func (m ClientRequestDuration) Record( return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append( *o, @@ -846,11 +1016,8 @@ func (m ClientRequestDuration) RecordSet(ctx context.Context, val float64, set a return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Float64Histogram.Record(ctx, val, *o...) @@ -1001,11 +1168,8 @@ func (m ClientResponseBodySize) Record( return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append( *o, @@ -1039,11 +1203,8 @@ func (m ClientResponseBodySize) RecordSet(ctx context.Context, val int64, set at return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Int64Histogram.Record(ctx, val, *o...) @@ -1184,11 +1345,8 @@ func (m ServerActiveRequests) Add( return } - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() + o := metricpool.AddOptions() + defer metricpool.PutAddOptions(o) *o = append( *o, @@ -1214,11 +1372,8 @@ func (m ServerActiveRequests) AddSet(ctx context.Context, incr int64, set attrib return } - o := addOptPool.Get().(*[]metric.AddOption) - defer func() { - *o = (*o)[:0] - addOptPool.Put(o) - }() + o := metricpool.AddOptions() + defer metricpool.PutAddOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Int64UpDownCounter.Add(ctx, incr, *o...) @@ -1238,6 +1393,94 @@ func (ServerActiveRequests) AttrServerPort(val int) attribute.KeyValue { return attribute.Int("server.port", val) } +// ServerActiveRequestsObservable is an instrument used to record metric values +// conforming to the "http.server.active_requests" semantic conventions. It +// represents the number of active HTTP server requests. +type ServerActiveRequestsObservable struct { + metric.Int64ObservableUpDownCounter +} + +var newServerActiveRequestsObservableOpts = []metric.Int64ObservableUpDownCounterOption{ + metric.WithDescription("Number of active HTTP server requests."), + metric.WithUnit("{request}"), +} + +// NewServerActiveRequestsObservable returns a new ServerActiveRequestsObservable +// instrument. +func NewServerActiveRequestsObservable( + m metric.Meter, + opt ...metric.Int64ObservableUpDownCounterOption, +) (ServerActiveRequestsObservable, error) { + // Check if the meter is nil. + if m == nil { + return ServerActiveRequestsObservable{noop.Int64ObservableUpDownCounter{}}, nil + } + + if len(opt) == 0 { + opt = newServerActiveRequestsObservableOpts + } else { + opt = append(opt, newServerActiveRequestsObservableOpts...) + } + + i, err := m.Int64ObservableUpDownCounter( + "http.server.active_requests", + opt..., + ) + if err != nil { + return ServerActiveRequestsObservable{noop.Int64ObservableUpDownCounter{}}, err + } + return ServerActiveRequestsObservable{i}, nil +} + +// Inst returns the underlying metric instrument. +func (m ServerActiveRequestsObservable) Inst() metric.Int64ObservableUpDownCounter { + return m.Int64ObservableUpDownCounter +} + +// Name returns the semantic convention name of the instrument. +func (ServerActiveRequestsObservable) Name() string { + return "http.server.active_requests" +} + +// Unit returns the semantic convention unit of the instrument +func (ServerActiveRequestsObservable) Unit() string { + return "{request}" +} + +// Description returns the semantic convention description of the instrument +func (ServerActiveRequestsObservable) Description() string { + return "Number of active HTTP server requests." +} + +// AttrRequestMethod returns a required attribute for the "http.request.method" +// semantic convention. It represents the HTTP request method. +func (ServerActiveRequestsObservable) AttrRequestMethod(val RequestMethodAttr) attribute.KeyValue { + return attribute.String("http.request.method", string(val)) +} + +// AttrURLScheme returns a required attribute for the "url.scheme" semantic +// convention. It represents the [URI scheme] component identifying the used +// protocol. +// +// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 +func (ServerActiveRequestsObservable) AttrURLScheme(val string) attribute.KeyValue { + return attribute.String("url.scheme", val) +} + +// AttrServerAddress returns an optional attribute for the "server.address" +// semantic convention. It represents the name of the local HTTP server that +// received the request. +func (ServerActiveRequestsObservable) AttrServerAddress(val string) attribute.KeyValue { + return attribute.String("server.address", val) +} + +// AttrServerPort returns an optional attribute for the "server.port" semantic +// convention. It represents the port of the local HTTP server that received the +// request. +func (ServerActiveRequestsObservable) AttrServerPort(val int) attribute.KeyValue { + return attribute.Int("server.port", val) +} + // ServerRequestBodySize is an instrument used to record metric values conforming // to the "http.server.request.body.size" semantic conventions. It represents the // size of HTTP server request bodies. @@ -1304,12 +1547,13 @@ func (ServerRequestBodySize) Description() string { // // All additional attrs passed are included in the recorded value. // +// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 +// // The size of the request payload body in bytes. This is the number of bytes // transferred excluding headers and is often, but not always, present as the // [Content-Length] header. For requests using transport encoding, this should be // the compressed size. // -// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 // [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length func (m ServerRequestBodySize) Record( ctx context.Context, @@ -1329,11 +1573,8 @@ func (m ServerRequestBodySize) Record( return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append( *o, @@ -1366,11 +1607,8 @@ func (m ServerRequestBodySize) RecordSet(ctx context.Context, val int64, set att return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Int64Histogram.Record(ctx, val, *o...) @@ -1447,6 +1685,7 @@ type ServerRequestDuration struct { var newServerRequestDurationOpts = []metric.Float64HistogramOption{ metric.WithDescription("Duration of HTTP server requests."), metric.WithUnit("s"), + metric.WithExplicitBucketBoundaries([]float64{0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10}...), } // NewServerRequestDuration returns a new ServerRequestDuration instrument. @@ -1522,11 +1761,8 @@ func (m ServerRequestDuration) Record( return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append( *o, @@ -1552,11 +1788,8 @@ func (m ServerRequestDuration) RecordSet(ctx context.Context, val float64, set a return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Float64Histogram.Record(ctx, val, *o...) @@ -1689,12 +1922,13 @@ func (ServerResponseBodySize) Description() string { // // All additional attrs passed are included in the recorded value. // +// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 +// // The size of the response payload body in bytes. This is the number of bytes // transferred excluding headers and is often, but not always, present as the // [Content-Length] header. For requests using transport encoding, this should be // the compressed size. // -// [URI scheme]: https://www.rfc-editor.org/rfc/rfc3986#section-3.1 // [Content-Length]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length func (m ServerResponseBodySize) Record( ctx context.Context, @@ -1714,11 +1948,8 @@ func (m ServerResponseBodySize) Record( return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append( *o, @@ -1751,11 +1982,8 @@ func (m ServerResponseBodySize) RecordSet(ctx context.Context, val int64, set at return } - o := recOptPool.Get().(*[]metric.RecordOption) - defer func() { - *o = (*o)[:0] - recOptPool.Put(o) - }() + o := metricpool.RecordOptions() + defer metricpool.PutRecordOptions(o) *o = append(*o, metric.WithAttributeSet(set)) m.Int64Histogram.Record(ctx, val, *o...) diff --git a/vendor/golang.org/x/text/currency/common.go b/vendor/golang.org/x/text/currency/common.go new file mode 100644 index 00000000000..fef15be5545 --- /dev/null +++ b/vendor/golang.org/x/text/currency/common.go @@ -0,0 +1,67 @@ +// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. + +package currency + +import ( + "time" + + "golang.org/x/text/language" +) + +// This file contains code common to gen.go and the package code. + +const ( + cashShift = 3 + roundMask = 0x7 + + nonTenderBit = 0x8000 +) + +// currencyInfo contains information about a currency. +// bits 0..2: index into roundings for standard rounding +// bits 3..5: index into roundings for cash rounding +type currencyInfo byte + +// roundingType defines the scale (number of fractional decimals) and increments +// in terms of units of size 10^-scale. For example, for scale == 2 and +// increment == 1, the currency is rounded to units of 0.01. +type roundingType struct { + scale, increment uint8 +} + +// roundings contains rounding data for currencies. This struct is +// created by hand as it is very unlikely to change much. +var roundings = [...]roundingType{ + {2, 1}, // default + {0, 1}, + {1, 1}, + {3, 1}, + {4, 1}, + {2, 5}, // cash rounding alternative + {2, 50}, +} + +// regionToCode returns a 16-bit region code. Only two-letter codes are +// supported. (Three-letter codes are not needed.) +func regionToCode(r language.Region) uint16 { + if s := r.String(); len(s) == 2 { + return uint16(s[0])<<8 | uint16(s[1]) + } + return 0 +} + +func toDate(t time.Time) uint32 { + y := t.Year() + if y == 1 { + return 0 + } + date := uint32(y) << 4 + date |= uint32(t.Month()) + date <<= 5 + date |= uint32(t.Day()) + return date +} + +func fromDate(date uint32) time.Time { + return time.Date(int(date>>9), time.Month((date>>5)&0xf), int(date&0x1f), 0, 0, 0, 0, time.UTC) +} diff --git a/vendor/golang.org/x/text/currency/currency.go b/vendor/golang.org/x/text/currency/currency.go new file mode 100644 index 00000000000..598ddeff420 --- /dev/null +++ b/vendor/golang.org/x/text/currency/currency.go @@ -0,0 +1,185 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go gen_common.go -output tables.go + +// Package currency contains currency-related functionality. +// +// NOTE: the formatting functionality is currently under development and may +// change without notice. +package currency // import "golang.org/x/text/currency" + +import ( + "errors" + "sort" + + "golang.org/x/text/internal/tag" + "golang.org/x/text/language" +) + +// TODO: +// - language-specific currency names. +// - currency formatting. +// - currency information per region +// - register currency code (there are no private use area) + +// TODO: remove Currency type from package language. + +// Kind determines the rounding and rendering properties of a currency value. +type Kind struct { + rounding rounding + // TODO: formatting type: standard, accounting. See CLDR. +} + +type rounding byte + +const ( + standard rounding = iota + cash +) + +var ( + // Standard defines standard rounding and formatting for currencies. + Standard Kind = Kind{rounding: standard} + + // Cash defines rounding and formatting standards for cash transactions. + Cash Kind = Kind{rounding: cash} + + // Accounting defines rounding and formatting standards for accounting. + Accounting Kind = Kind{rounding: standard} +) + +// Rounding reports the rounding characteristics for the given currency, where +// scale is the number of fractional decimals and increment is the number of +// units in terms of 10^(-scale) to which to round to. +func (k Kind) Rounding(cur Unit) (scale, increment int) { + info := currency.Elem(int(cur.index))[3] + switch k.rounding { + case standard: + info &= roundMask + case cash: + info >>= cashShift + } + return int(roundings[info].scale), int(roundings[info].increment) +} + +// Unit is an ISO 4217 currency designator. +type Unit struct { + index uint16 +} + +// String returns the ISO code of u. +func (u Unit) String() string { + if u.index == 0 { + return "XXX" + } + return currency.Elem(int(u.index))[:3] +} + +// Amount creates an Amount for the given currency unit and amount. +func (u Unit) Amount(amount interface{}) Amount { + // TODO: verify amount is a supported number type + return Amount{amount: amount, currency: u} +} + +var ( + errSyntax = errors.New("currency: tag is not well-formed") + errValue = errors.New("currency: tag is not a recognized currency") +) + +// ParseISO parses a 3-letter ISO 4217 currency code. It returns an error if s +// is not well-formed or not a recognized currency code. +func ParseISO(s string) (Unit, error) { + var buf [4]byte // Take one byte more to detect oversize keys. + key := buf[:copy(buf[:], s)] + if !tag.FixCase("XXX", key) { + return Unit{}, errSyntax + } + if i := currency.Index(key); i >= 0 { + if i == xxx { + return Unit{}, nil + } + return Unit{uint16(i)}, nil + } + return Unit{}, errValue +} + +// MustParseISO is like ParseISO, but panics if the given currency unit +// cannot be parsed. It simplifies safe initialization of Unit values. +func MustParseISO(s string) Unit { + c, err := ParseISO(s) + if err != nil { + panic(err) + } + return c +} + +// FromRegion reports the currency unit that is currently legal tender in the +// given region according to CLDR. It will return false if region currently does +// not have a legal tender. +func FromRegion(r language.Region) (currency Unit, ok bool) { + x := regionToCode(r) + i := sort.Search(len(regionToCurrency), func(i int) bool { + return regionToCurrency[i].region >= x + }) + if i < len(regionToCurrency) && regionToCurrency[i].region == x { + return Unit{regionToCurrency[i].code}, true + } + return Unit{}, false +} + +// FromTag reports the most likely currency for the given tag. It considers the +// currency defined in the -u extension and infers the region if necessary. +func FromTag(t language.Tag) (Unit, language.Confidence) { + if cur := t.TypeForKey("cu"); len(cur) == 3 { + c, _ := ParseISO(cur) + return c, language.Exact + } + r, conf := t.Region() + if cur, ok := FromRegion(r); ok { + return cur, conf + } + return Unit{}, language.No +} + +var ( + // Undefined and testing. + XXX Unit = Unit{} + XTS Unit = Unit{xts} + + // G10 currencies https://en.wikipedia.org/wiki/G10_currencies. + USD Unit = Unit{usd} + EUR Unit = Unit{eur} + JPY Unit = Unit{jpy} + GBP Unit = Unit{gbp} + CHF Unit = Unit{chf} + AUD Unit = Unit{aud} + NZD Unit = Unit{nzd} + CAD Unit = Unit{cad} + SEK Unit = Unit{sek} + NOK Unit = Unit{nok} + + // Additional common currencies as defined by CLDR. + BRL Unit = Unit{brl} + CNY Unit = Unit{cny} + DKK Unit = Unit{dkk} + INR Unit = Unit{inr} + RUB Unit = Unit{rub} + HKD Unit = Unit{hkd} + IDR Unit = Unit{idr} + KRW Unit = Unit{krw} + MXN Unit = Unit{mxn} + PLN Unit = Unit{pln} + SAR Unit = Unit{sar} + THB Unit = Unit{thb} + TRY Unit = Unit{try} + TWD Unit = Unit{twd} + ZAR Unit = Unit{zar} + + // Precious metals. + XAG Unit = Unit{xag} + XAU Unit = Unit{xau} + XPT Unit = Unit{xpt} + XPD Unit = Unit{xpd} +) diff --git a/vendor/golang.org/x/text/currency/format.go b/vendor/golang.org/x/text/currency/format.go new file mode 100644 index 00000000000..cc4570d3b68 --- /dev/null +++ b/vendor/golang.org/x/text/currency/format.go @@ -0,0 +1,220 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package currency + +import ( + "fmt" + "sort" + + "golang.org/x/text/internal/format" + "golang.org/x/text/internal/language/compact" + "golang.org/x/text/internal/number" + + "golang.org/x/text/language" +) + +// Amount is an amount-currency unit pair. +type Amount struct { + amount interface{} // Change to decimal(64|128). + currency Unit +} + +// Currency reports the currency unit of this amount. +func (a Amount) Currency() Unit { return a.currency } + +// TODO: based on decimal type, but may make sense to customize a bit. +// func (a Amount) Decimal() +// func (a Amount) Int() (int64, error) +// func (a Amount) Fraction() (int64, error) +// func (a Amount) Rat() *big.Rat +// func (a Amount) Float() (float64, error) +// func (a Amount) Scale() uint +// func (a Amount) Precision() uint +// func (a Amount) Sign() int +// +// Add/Sub/Div/Mul/Round. + +// Format implements fmt.Formatter. It accepts format.State for +// language-specific rendering. +func (a Amount) Format(s fmt.State, verb rune) { + v := formattedValue{ + currency: a.currency, + amount: a.amount, + format: defaultFormat, + } + v.Format(s, verb) +} + +// formattedValue is currency amount or unit that implements language-sensitive +// formatting. +type formattedValue struct { + currency Unit + amount interface{} // Amount, Unit, or number. + format *options +} + +// Format implements fmt.Formatter. It accepts format.State for +// language-specific rendering. +func (v formattedValue) Format(s fmt.State, verb rune) { + var tag language.Tag + var lang compact.ID + if state, ok := s.(format.State); ok { + tag = state.Language() + lang, _ = compact.RegionalID(compact.Tag(tag)) + } + + // Get the options. Use DefaultFormat if not present. + opt := v.format + if opt == nil { + opt = defaultFormat + } + cur := v.currency + if cur.index == 0 { + cur = opt.currency + } + + sym := opt.symbol(lang, cur) + if v.amount != nil { + var f number.Formatter + f.InitDecimal(tag) + + scale, increment := opt.kind.Rounding(cur) + f.RoundingContext.SetScale(scale) + f.RoundingContext.Increment = uint32(increment) + f.RoundingContext.IncrementScale = uint8(scale) + f.RoundingContext.Mode = number.ToNearestAway + + d := f.Append(nil, v.amount) + + fmt.Fprint(s, sym, " ", string(d)) + } else { + fmt.Fprint(s, sym) + } +} + +// Formatter decorates a given number, Unit or Amount with formatting options. +type Formatter func(amount interface{}) formattedValue + +// func (f Formatter) Options(opts ...Option) Formatter + +// TODO: call this a Formatter or FormatFunc? + +var dummy = USD.Amount(0) + +// adjust creates a new Formatter based on the adjustments of fn on f. +func (f Formatter) adjust(fn func(*options)) Formatter { + var o options = *(f(dummy).format) + fn(&o) + return o.format +} + +// Default creates a new Formatter that defaults to currency unit c if a numeric +// value is passed that is not associated with a currency. +func (f Formatter) Default(currency Unit) Formatter { + return f.adjust(func(o *options) { o.currency = currency }) +} + +// Kind sets the kind of the underlying currency unit. +func (f Formatter) Kind(k Kind) Formatter { + return f.adjust(func(o *options) { o.kind = k }) +} + +var defaultFormat *options = ISO(dummy).format + +var ( + // Uses Narrow symbols. Overrides Symbol, if present. + NarrowSymbol Formatter = Formatter(formNarrow) + + // Use Symbols instead of ISO codes, when available. + Symbol Formatter = Formatter(formSymbol) + + // Use ISO code as symbol. + ISO Formatter = Formatter(formISO) + + // TODO: + // // Use full name as symbol. + // Name Formatter +) + +// options configures rendering and rounding options for an Amount. +type options struct { + currency Unit + kind Kind + + symbol func(compactIndex compact.ID, c Unit) string +} + +func (o *options) format(amount interface{}) formattedValue { + v := formattedValue{format: o} + switch x := amount.(type) { + case Amount: + v.amount = x.amount + v.currency = x.currency + case *Amount: + v.amount = x.amount + v.currency = x.currency + case Unit: + v.currency = x + case *Unit: + v.currency = *x + default: + if o.currency.index == 0 { + panic("cannot format number without a currency being set") + } + // TODO: Must be a number. + v.amount = x + v.currency = o.currency + } + return v +} + +var ( + optISO = options{symbol: lookupISO} + optSymbol = options{symbol: lookupSymbol} + optNarrow = options{symbol: lookupNarrow} +) + +// These need to be functions, rather than curried methods, as curried methods +// are evaluated at init time, causing tables to be included unconditionally. +func formISO(x interface{}) formattedValue { return optISO.format(x) } +func formSymbol(x interface{}) formattedValue { return optSymbol.format(x) } +func formNarrow(x interface{}) formattedValue { return optNarrow.format(x) } + +func lookupISO(x compact.ID, c Unit) string { return c.String() } +func lookupSymbol(x compact.ID, c Unit) string { return normalSymbol.lookup(x, c) } +func lookupNarrow(x compact.ID, c Unit) string { return narrowSymbol.lookup(x, c) } + +type symbolIndex struct { + index []uint16 // position corresponds with compact index of language. + data []curToIndex +} + +var ( + normalSymbol = symbolIndex{normalLangIndex, normalSymIndex} + narrowSymbol = symbolIndex{narrowLangIndex, narrowSymIndex} +) + +func (x *symbolIndex) lookup(lang compact.ID, c Unit) string { + for { + index := x.data[x.index[lang]:x.index[lang+1]] + i := sort.Search(len(index), func(i int) bool { + return index[i].cur >= c.index + }) + if i < len(index) && index[i].cur == c.index { + x := index[i].idx + start := x + 1 + end := start + uint16(symbols[x]) + if start == end { + return c.String() + } + return symbols[start:end] + } + if lang == 0 { + break + } + lang = lang.Parent() + } + return c.String() +} diff --git a/vendor/golang.org/x/text/currency/query.go b/vendor/golang.org/x/text/currency/query.go new file mode 100644 index 00000000000..7bf9430a62c --- /dev/null +++ b/vendor/golang.org/x/text/currency/query.go @@ -0,0 +1,152 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package currency + +import ( + "sort" + "time" + + "golang.org/x/text/language" +) + +// QueryIter represents a set of Units. The default set includes all Units that +// are currently in use as legal tender in any Region. +type QueryIter interface { + // Next returns true if there is a next element available. + // It must be called before any of the other methods are called. + Next() bool + + // Unit returns the unit of the current iteration. + Unit() Unit + + // Region returns the Region for the current iteration. + Region() language.Region + + // From returns the date from which the unit was used in the region. + // It returns false if this date is unknown. + From() (time.Time, bool) + + // To returns the date up till which the unit was used in the region. + // It returns false if this date is unknown or if the unit is still in use. + To() (time.Time, bool) + + // IsTender reports whether the unit is a legal tender in the region during + // the specified date range. + IsTender() bool +} + +// Query represents a set of Units. The default set includes all Units that are +// currently in use as legal tender in any Region. +func Query(options ...QueryOption) QueryIter { + it := &iter{ + end: len(regionData), + date: 0xFFFFFFFF, + } + for _, fn := range options { + fn(it) + } + return it +} + +// NonTender returns a new query that also includes matching Units that are not +// legal tender. +var NonTender QueryOption = nonTender + +func nonTender(i *iter) { + i.nonTender = true +} + +// Historical selects the units for all dates. +var Historical QueryOption = historical + +func historical(i *iter) { + i.date = hist +} + +// A QueryOption can be used to change the set of unit information returned by +// a query. +type QueryOption func(*iter) + +// Date queries the units that were in use at the given point in history. +func Date(t time.Time) QueryOption { + d := toDate(t) + return func(i *iter) { + i.date = d + } +} + +// Region limits the query to only return entries for the given region. +func Region(r language.Region) QueryOption { + p, end := len(regionData), len(regionData) + x := regionToCode(r) + i := sort.Search(len(regionData), func(i int) bool { + return regionData[i].region >= x + }) + if i < len(regionData) && regionData[i].region == x { + p = i + for i++; i < len(regionData) && regionData[i].region == x; i++ { + } + end = i + } + return func(i *iter) { + i.p, i.end = p, end + } +} + +const ( + hist = 0x00 + now = 0xFFFFFFFF +) + +type iter struct { + *regionInfo + p, end int + date uint32 + nonTender bool +} + +func (i *iter) Next() bool { + for ; i.p < i.end; i.p++ { + i.regionInfo = ®ionData[i.p] + if !i.nonTender && !i.IsTender() { + continue + } + if i.date == hist || (i.from <= i.date && (i.to == 0 || i.date <= i.to)) { + i.p++ + return true + } + } + return false +} + +func (r *regionInfo) Region() language.Region { + // TODO: this could be much faster. + var buf [2]byte + buf[0] = uint8(r.region >> 8) + buf[1] = uint8(r.region) + return language.MustParseRegion(string(buf[:])) +} + +func (r *regionInfo) Unit() Unit { + return Unit{r.code &^ nonTenderBit} +} + +func (r *regionInfo) IsTender() bool { + return r.code&nonTenderBit == 0 +} + +func (r *regionInfo) From() (time.Time, bool) { + if r.from == 0 { + return time.Time{}, false + } + return fromDate(r.from), true +} + +func (r *regionInfo) To() (time.Time, bool) { + if r.to == 0 { + return time.Time{}, false + } + return fromDate(r.to), true +} diff --git a/vendor/golang.org/x/text/currency/tables.go b/vendor/golang.org/x/text/currency/tables.go new file mode 100644 index 00000000000..d1a7440a6bd --- /dev/null +++ b/vendor/golang.org/x/text/currency/tables.go @@ -0,0 +1,2629 @@ +// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. + +package currency + +import "golang.org/x/text/internal/tag" + +// CLDRVersion is the CLDR version from which the tables in this package are derived. +const CLDRVersion = "32" + +const ( + xxx = 285 + xts = 283 + usd = 252 + eur = 94 + jpy = 133 + gbp = 99 + chf = 61 + aud = 19 + nzd = 192 + cad = 58 + sek = 219 + nok = 190 + dkk = 82 + xag = 266 + xau = 267 + xpt = 280 + xpd = 278 + brl = 46 + cny = 68 + inr = 125 + rub = 210 + hkd = 114 + idr = 120 + krw = 141 + mxn = 178 + pln = 201 + sar = 213 + thb = 235 + try = 244 + twd = 246 + zar = 293 +) + +// currency holds an alphabetically sorted list of canonical 3-letter currency +// identifiers. Each identifier is followed by a byte of type currencyInfo, +// defined in gen_common.go. +const currency tag.Index = "" + // Size: 1208 bytes + "\x00\x00\x00\x00ADP\x09AED\x00AFA\x00AFN\x09ALK\x00ALL\x09AMD\x09ANG\x00" + + "AOA\x00AOK\x00AON\x00AOR\x00ARA\x00ARL\x00ARM\x00ARP\x00ARS\x00ATS\x00AU" + + "D\x00AWG\x00AZM\x00AZN\x00BAD\x00BAM\x00BAN\x00BBD\x00BDT\x00BEC\x00BEF" + + "\x00BEL\x00BGL\x00BGM\x00BGN\x00BGO\x00BHD\x1bBIF\x09BMD\x00BND\x00BOB" + + "\x00BOL\x00BOP\x00BOV\x00BRB\x00BRC\x00BRE\x00BRL\x00BRN\x00BRR\x00BRZ" + + "\x00BSD\x00BTN\x00BUK\x00BWP\x00BYB\x00BYN\x00BYR\x09BZD\x00CAD(CDF\x00C" + + "HE\x00CHF(CHW\x00CLE\x00CLF$CLP\x09CNH\x00CNX\x00CNY\x00COP\x09COU\x00CR" + + "C\x08CSD\x00CSK\x00CUC\x00CUP\x00CVE\x00CYP\x00CZK\x08DDM\x00DEM\x00DJF" + + "\x09DKK0DOP\x00DZD\x00ECS\x00ECV\x00EEK\x00EGP\x00ERN\x00ESA\x00ESB\x00E" + + "SP\x09ETB\x00EUR\x00FIM\x00FJD\x00FKP\x00FRF\x00GBP\x00GEK\x00GEL\x00GHC" + + "\x00GHS\x00GIP\x00GMD\x00GNF\x09GNS\x00GQE\x00GRD\x00GTQ\x00GWE\x00GWP" + + "\x00GYD\x09HKD\x00HNL\x00HRD\x00HRK\x00HTG\x00HUF\x08IDR\x09IEP\x00ILP" + + "\x00ILR\x00ILS\x00INR\x00IQD\x09IRR\x09ISJ\x00ISK\x09ITL\x09JMD\x00JOD" + + "\x1bJPY\x09KES\x00KGS\x00KHR\x00KMF\x09KPW\x09KRH\x00KRO\x00KRW\x09KWD" + + "\x1bKYD\x00KZT\x00LAK\x09LBP\x09LKR\x00LRD\x00LSL\x00LTL\x00LTT\x00LUC" + + "\x00LUF\x09LUL\x00LVL\x00LVR\x00LYD\x1bMAD\x00MAF\x00MCF\x00MDC\x00MDL" + + "\x00MGA\x09MGF\x09MKD\x00MKN\x00MLF\x00MMK\x09MNT\x09MOP\x00MRO\x09MTL" + + "\x00MTP\x00MUR\x09MVP\x00MVR\x00MWK\x00MXN\x00MXP\x00MXV\x00MYR\x00MZE" + + "\x00MZM\x00MZN\x00NAD\x00NGN\x00NIC\x00NIO\x00NLG\x00NOK\x08NPR\x00NZD" + + "\x00OMR\x1bPAB\x00PEI\x00PEN\x00PES\x00PGK\x00PHP\x00PKR\x09PLN\x00PLZ" + + "\x00PTE\x00PYG\x09QAR\x00RHD\x00ROL\x00RON\x00RSD\x09RUB\x00RUR\x00RWF" + + "\x09SAR\x00SBD\x00SCR\x00SDD\x00SDG\x00SDP\x00SEK\x08SGD\x00SHP\x00SIT" + + "\x00SKK\x00SLL\x09SOS\x09SRD\x00SRG\x00SSP\x00STD\x09STN\x00SUR\x00SVC" + + "\x00SYP\x09SZL\x00THB\x00TJR\x00TJS\x00TMM\x09TMT\x00TND\x1bTOP\x00TPE" + + "\x00TRL\x09TRY\x00TTD\x00TWD\x08TZS\x09UAH\x00UAK\x00UGS\x00UGX\x09USD" + + "\x00USN\x00USS\x00UYI\x09UYP\x00UYU\x00UZS\x09VEB\x00VEF\x00VND\x09VNN" + + "\x00VUV\x09WST\x00XAF\x09XAG\x00XAU\x00XBA\x00XBB\x00XBC\x00XBD\x00XCD" + + "\x00XDR\x00XEU\x00XFO\x00XFU\x00XOF\x09XPD\x00XPF\x09XPT\x00XRE\x00XSU" + + "\x00XTS\x00XUA\x00XXX\x00YDD\x00YER\x09YUD\x00YUM\x00YUN\x00YUR\x00ZAL" + + "\x00ZAR\x00ZMK\x09ZMW\x00ZRN\x00ZRZ\x00ZWD\x09ZWL\x00ZWR\x00\xff\xff\xff" + + "\xff" + +const numCurrencies = 300 + +type toCurrency struct { + region uint16 + code uint16 +} + +var regionToCurrency = []toCurrency{ // 255 elements + 0: {region: 0x4143, code: 0xdd}, + 1: {region: 0x4144, code: 0x5e}, + 2: {region: 0x4145, code: 0x2}, + 3: {region: 0x4146, code: 0x4}, + 4: {region: 0x4147, code: 0x110}, + 5: {region: 0x4149, code: 0x110}, + 6: {region: 0x414c, code: 0x6}, + 7: {region: 0x414d, code: 0x7}, + 8: {region: 0x414f, code: 0x9}, + 9: {region: 0x4152, code: 0x11}, + 10: {region: 0x4153, code: 0xfc}, + 11: {region: 0x4154, code: 0x5e}, + 12: {region: 0x4155, code: 0x13}, + 13: {region: 0x4157, code: 0x14}, + 14: {region: 0x4158, code: 0x5e}, + 15: {region: 0x415a, code: 0x16}, + 16: {region: 0x4241, code: 0x18}, + 17: {region: 0x4242, code: 0x1a}, + 18: {region: 0x4244, code: 0x1b}, + 19: {region: 0x4245, code: 0x5e}, + 20: {region: 0x4246, code: 0x115}, + 21: {region: 0x4247, code: 0x21}, + 22: {region: 0x4248, code: 0x23}, + 23: {region: 0x4249, code: 0x24}, + 24: {region: 0x424a, code: 0x115}, + 25: {region: 0x424c, code: 0x5e}, + 26: {region: 0x424d, code: 0x25}, + 27: {region: 0x424e, code: 0x26}, + 28: {region: 0x424f, code: 0x27}, + 29: {region: 0x4251, code: 0xfc}, + 30: {region: 0x4252, code: 0x2e}, + 31: {region: 0x4253, code: 0x32}, + 32: {region: 0x4254, code: 0x33}, + 33: {region: 0x4256, code: 0xbe}, + 34: {region: 0x4257, code: 0x35}, + 35: {region: 0x4259, code: 0x37}, + 36: {region: 0x425a, code: 0x39}, + 37: {region: 0x4341, code: 0x3a}, + 38: {region: 0x4343, code: 0x13}, + 39: {region: 0x4344, code: 0x3b}, + 40: {region: 0x4346, code: 0x109}, + 41: {region: 0x4347, code: 0x109}, + 42: {region: 0x4348, code: 0x3d}, + 43: {region: 0x4349, code: 0x115}, + 44: {region: 0x434b, code: 0xc0}, + 45: {region: 0x434c, code: 0x41}, + 46: {region: 0x434d, code: 0x109}, + 47: {region: 0x434e, code: 0x44}, + 48: {region: 0x434f, code: 0x45}, + 49: {region: 0x4352, code: 0x47}, + 50: {region: 0x4355, code: 0x4b}, + 51: {region: 0x4356, code: 0x4c}, + 52: {region: 0x4357, code: 0x8}, + 53: {region: 0x4358, code: 0x13}, + 54: {region: 0x4359, code: 0x5e}, + 55: {region: 0x435a, code: 0x4e}, + 56: {region: 0x4445, code: 0x5e}, + 57: {region: 0x4447, code: 0xfc}, + 58: {region: 0x444a, code: 0x51}, + 59: {region: 0x444b, code: 0x52}, + 60: {region: 0x444d, code: 0x110}, + 61: {region: 0x444f, code: 0x53}, + 62: {region: 0x445a, code: 0x54}, + 63: {region: 0x4541, code: 0x5e}, + 64: {region: 0x4543, code: 0xfc}, + 65: {region: 0x4545, code: 0x5e}, + 66: {region: 0x4547, code: 0x58}, + 67: {region: 0x4548, code: 0x9e}, + 68: {region: 0x4552, code: 0x59}, + 69: {region: 0x4553, code: 0x5e}, + 70: {region: 0x4554, code: 0x5d}, + 71: {region: 0x4555, code: 0x5e}, + 72: {region: 0x4649, code: 0x5e}, + 73: {region: 0x464a, code: 0x60}, + 74: {region: 0x464b, code: 0x61}, + 75: {region: 0x464d, code: 0xfc}, + 76: {region: 0x464f, code: 0x52}, + 77: {region: 0x4652, code: 0x5e}, + 78: {region: 0x4741, code: 0x109}, + 79: {region: 0x4742, code: 0x63}, + 80: {region: 0x4744, code: 0x110}, + 81: {region: 0x4745, code: 0x65}, + 82: {region: 0x4746, code: 0x5e}, + 83: {region: 0x4747, code: 0x63}, + 84: {region: 0x4748, code: 0x67}, + 85: {region: 0x4749, code: 0x68}, + 86: {region: 0x474c, code: 0x52}, + 87: {region: 0x474d, code: 0x69}, + 88: {region: 0x474e, code: 0x6a}, + 89: {region: 0x4750, code: 0x5e}, + 90: {region: 0x4751, code: 0x109}, + 91: {region: 0x4752, code: 0x5e}, + 92: {region: 0x4753, code: 0x63}, + 93: {region: 0x4754, code: 0x6e}, + 94: {region: 0x4755, code: 0xfc}, + 95: {region: 0x4757, code: 0x115}, + 96: {region: 0x4759, code: 0x71}, + 97: {region: 0x484b, code: 0x72}, + 98: {region: 0x484d, code: 0x13}, + 99: {region: 0x484e, code: 0x73}, + 100: {region: 0x4852, code: 0x75}, + 101: {region: 0x4854, code: 0x76}, + 102: {region: 0x4855, code: 0x77}, + 103: {region: 0x4943, code: 0x5e}, + 104: {region: 0x4944, code: 0x78}, + 105: {region: 0x4945, code: 0x5e}, + 106: {region: 0x494c, code: 0x7c}, + 107: {region: 0x494d, code: 0x63}, + 108: {region: 0x494e, code: 0x7d}, + 109: {region: 0x494f, code: 0xfc}, + 110: {region: 0x4951, code: 0x7e}, + 111: {region: 0x4952, code: 0x7f}, + 112: {region: 0x4953, code: 0x81}, + 113: {region: 0x4954, code: 0x5e}, + 114: {region: 0x4a45, code: 0x63}, + 115: {region: 0x4a4d, code: 0x83}, + 116: {region: 0x4a4f, code: 0x84}, + 117: {region: 0x4a50, code: 0x85}, + 118: {region: 0x4b45, code: 0x86}, + 119: {region: 0x4b47, code: 0x87}, + 120: {region: 0x4b48, code: 0x88}, + 121: {region: 0x4b49, code: 0x13}, + 122: {region: 0x4b4d, code: 0x89}, + 123: {region: 0x4b4e, code: 0x110}, + 124: {region: 0x4b50, code: 0x8a}, + 125: {region: 0x4b52, code: 0x8d}, + 126: {region: 0x4b57, code: 0x8e}, + 127: {region: 0x4b59, code: 0x8f}, + 128: {region: 0x4b5a, code: 0x90}, + 129: {region: 0x4c41, code: 0x91}, + 130: {region: 0x4c42, code: 0x92}, + 131: {region: 0x4c43, code: 0x110}, + 132: {region: 0x4c49, code: 0x3d}, + 133: {region: 0x4c4b, code: 0x93}, + 134: {region: 0x4c52, code: 0x94}, + 135: {region: 0x4c53, code: 0x125}, + 136: {region: 0x4c54, code: 0x5e}, + 137: {region: 0x4c55, code: 0x5e}, + 138: {region: 0x4c56, code: 0x5e}, + 139: {region: 0x4c59, code: 0x9d}, + 140: {region: 0x4d41, code: 0x9e}, + 141: {region: 0x4d43, code: 0x5e}, + 142: {region: 0x4d44, code: 0xa2}, + 143: {region: 0x4d45, code: 0x5e}, + 144: {region: 0x4d46, code: 0x5e}, + 145: {region: 0x4d47, code: 0xa3}, + 146: {region: 0x4d48, code: 0xfc}, + 147: {region: 0x4d4b, code: 0xa5}, + 148: {region: 0x4d4c, code: 0x115}, + 149: {region: 0x4d4d, code: 0xa8}, + 150: {region: 0x4d4e, code: 0xa9}, + 151: {region: 0x4d4f, code: 0xaa}, + 152: {region: 0x4d50, code: 0xfc}, + 153: {region: 0x4d51, code: 0x5e}, + 154: {region: 0x4d52, code: 0xab}, + 155: {region: 0x4d53, code: 0x110}, + 156: {region: 0x4d54, code: 0x5e}, + 157: {region: 0x4d55, code: 0xae}, + 158: {region: 0x4d56, code: 0xb0}, + 159: {region: 0x4d57, code: 0xb1}, + 160: {region: 0x4d58, code: 0xb2}, + 161: {region: 0x4d59, code: 0xb5}, + 162: {region: 0x4d5a, code: 0xb8}, + 163: {region: 0x4e41, code: 0xb9}, + 164: {region: 0x4e43, code: 0x117}, + 165: {region: 0x4e45, code: 0x115}, + 166: {region: 0x4e46, code: 0x13}, + 167: {region: 0x4e47, code: 0xba}, + 168: {region: 0x4e49, code: 0xbc}, + 169: {region: 0x4e4c, code: 0x5e}, + 170: {region: 0x4e4f, code: 0xbe}, + 171: {region: 0x4e50, code: 0xbf}, + 172: {region: 0x4e52, code: 0x13}, + 173: {region: 0x4e55, code: 0xc0}, + 174: {region: 0x4e5a, code: 0xc0}, + 175: {region: 0x4f4d, code: 0xc1}, + 176: {region: 0x5041, code: 0xc2}, + 177: {region: 0x5045, code: 0xc4}, + 178: {region: 0x5046, code: 0x117}, + 179: {region: 0x5047, code: 0xc6}, + 180: {region: 0x5048, code: 0xc7}, + 181: {region: 0x504b, code: 0xc8}, + 182: {region: 0x504c, code: 0xc9}, + 183: {region: 0x504d, code: 0x5e}, + 184: {region: 0x504e, code: 0xc0}, + 185: {region: 0x5052, code: 0xfc}, + 186: {region: 0x5053, code: 0x7c}, + 187: {region: 0x5054, code: 0x5e}, + 188: {region: 0x5057, code: 0xfc}, + 189: {region: 0x5059, code: 0xcc}, + 190: {region: 0x5141, code: 0xcd}, + 191: {region: 0x5245, code: 0x5e}, + 192: {region: 0x524f, code: 0xd0}, + 193: {region: 0x5253, code: 0xd1}, + 194: {region: 0x5255, code: 0xd2}, + 195: {region: 0x5257, code: 0xd4}, + 196: {region: 0x5341, code: 0xd5}, + 197: {region: 0x5342, code: 0xd6}, + 198: {region: 0x5343, code: 0xd7}, + 199: {region: 0x5344, code: 0xd9}, + 200: {region: 0x5345, code: 0xdb}, + 201: {region: 0x5347, code: 0xdc}, + 202: {region: 0x5348, code: 0xdd}, + 203: {region: 0x5349, code: 0x5e}, + 204: {region: 0x534a, code: 0xbe}, + 205: {region: 0x534b, code: 0x5e}, + 206: {region: 0x534c, code: 0xe0}, + 207: {region: 0x534d, code: 0x5e}, + 208: {region: 0x534e, code: 0x115}, + 209: {region: 0x534f, code: 0xe1}, + 210: {region: 0x5352, code: 0xe2}, + 211: {region: 0x5353, code: 0xe4}, + 212: {region: 0x5354, code: 0xe6}, + 213: {region: 0x5356, code: 0xfc}, + 214: {region: 0x5358, code: 0x8}, + 215: {region: 0x5359, code: 0xe9}, + 216: {region: 0x535a, code: 0xea}, + 217: {region: 0x5441, code: 0x63}, + 218: {region: 0x5443, code: 0xfc}, + 219: {region: 0x5444, code: 0x109}, + 220: {region: 0x5446, code: 0x5e}, + 221: {region: 0x5447, code: 0x115}, + 222: {region: 0x5448, code: 0xeb}, + 223: {region: 0x544a, code: 0xed}, + 224: {region: 0x544b, code: 0xc0}, + 225: {region: 0x544c, code: 0xfc}, + 226: {region: 0x544d, code: 0xef}, + 227: {region: 0x544e, code: 0xf0}, + 228: {region: 0x544f, code: 0xf1}, + 229: {region: 0x5452, code: 0xf4}, + 230: {region: 0x5454, code: 0xf5}, + 231: {region: 0x5456, code: 0x13}, + 232: {region: 0x5457, code: 0xf6}, + 233: {region: 0x545a, code: 0xf7}, + 234: {region: 0x5541, code: 0xf8}, + 235: {region: 0x5547, code: 0xfb}, + 236: {region: 0x554d, code: 0xfc}, + 237: {region: 0x5553, code: 0xfc}, + 238: {region: 0x5559, code: 0x101}, + 239: {region: 0x555a, code: 0x102}, + 240: {region: 0x5641, code: 0x5e}, + 241: {region: 0x5643, code: 0x110}, + 242: {region: 0x5645, code: 0x104}, + 243: {region: 0x5647, code: 0xfc}, + 244: {region: 0x5649, code: 0xfc}, + 245: {region: 0x564e, code: 0x105}, + 246: {region: 0x5655, code: 0x107}, + 247: {region: 0x5746, code: 0x117}, + 248: {region: 0x5753, code: 0x108}, + 249: {region: 0x584b, code: 0x5e}, + 250: {region: 0x5945, code: 0x11f}, + 251: {region: 0x5954, code: 0x5e}, + 252: {region: 0x5a41, code: 0x125}, + 253: {region: 0x5a4d, code: 0x127}, + 254: {region: 0x5a57, code: 0xfc}, +} // Size: 1044 bytes + +type regionInfo struct { + region uint16 + code uint16 + from uint32 + to uint32 +} + +var regionData = []regionInfo{ // 495 elements + 0: {region: 0x4143, code: 0xdd, from: 0xf7021, to: 0x0}, + 1: {region: 0x4144, code: 0x5e, from: 0xf9e21, to: 0x0}, + 2: {region: 0x4144, code: 0x5c, from: 0xea221, to: 0xfa45c}, + 3: {region: 0x4144, code: 0x62, from: 0xf5021, to: 0xfa451}, + 4: {region: 0x4144, code: 0x1, from: 0xf2021, to: 0xfa39f}, + 5: {region: 0x4145, code: 0x2, from: 0xf6ab3, to: 0x0}, + 6: {region: 0x4146, code: 0x4, from: 0xfa547, to: 0x0}, + 7: {region: 0x4146, code: 0x3, from: 0xf0e6e, to: 0xfa59f}, + 8: {region: 0x4147, code: 0x110, from: 0xf5b46, to: 0x0}, + 9: {region: 0x4149, code: 0x110, from: 0xf5b46, to: 0x0}, + 10: {region: 0x414c, code: 0x6, from: 0xf5b10, to: 0x0}, + 11: {region: 0x414c, code: 0x5, from: 0xf3561, to: 0xf5b10}, + 12: {region: 0x414d, code: 0x7, from: 0xf9376, to: 0x0}, + 13: {region: 0x414d, code: 0xd3, from: 0xf8f99, to: 0xf9376}, + 14: {region: 0x414d, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 15: {region: 0x414f, code: 0x9, from: 0xf9f8d, to: 0x0}, + 16: {region: 0x414f, code: 0xc, from: 0xf96e1, to: 0xfa041}, + 17: {region: 0x414f, code: 0xb, from: 0xf8d39, to: 0xfa041}, + 18: {region: 0x414f, code: 0xa, from: 0xf7228, to: 0xf8e61}, + 19: {region: 0x4151, code: 0x811d, from: 0x0, to: 0x0}, + 20: {region: 0x4152, code: 0x11, from: 0xf9021, to: 0x0}, + 21: {region: 0x4152, code: 0xd, from: 0xf82ce, to: 0xf9021}, + 22: {region: 0x4152, code: 0x10, from: 0xf7ec1, to: 0xf82ce}, + 23: {region: 0x4152, code: 0xe, from: 0xf6421, to: 0xf7ec1}, + 24: {region: 0x4152, code: 0xf, from: 0xeb365, to: 0xf6421}, + 25: {region: 0x4153, code: 0xfc, from: 0xee0f0, to: 0x0}, + 26: {region: 0x4154, code: 0x5e, from: 0xf9e21, to: 0x0}, + 27: {region: 0x4154, code: 0x12, from: 0xf3784, to: 0xfa45c}, + 28: {region: 0x4155, code: 0x13, from: 0xf5c4e, to: 0x0}, + 29: {region: 0x4157, code: 0x14, from: 0xf8421, to: 0x0}, + 30: {region: 0x4157, code: 0x8, from: 0xf28aa, to: 0xf8421}, + 31: {region: 0x4158, code: 0x5e, from: 0xf9e21, to: 0x0}, + 32: {region: 0x415a, code: 0x16, from: 0xfac21, to: 0x0}, + 33: {region: 0x415a, code: 0x15, from: 0xf9376, to: 0xfad9f}, + 34: {region: 0x415a, code: 0xd3, from: 0xf8f99, to: 0xf9421}, + 35: {region: 0x415a, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 36: {region: 0x4241, code: 0x18, from: 0xf9621, to: 0x0}, + 37: {region: 0x4241, code: 0x19, from: 0xf950f, to: 0xf9ae1}, + 38: {region: 0x4241, code: 0x17, from: 0xf90e1, to: 0xf950f}, + 39: {region: 0x4241, code: 0x123, from: 0xf90e1, to: 0xf9341}, + 40: {region: 0x4241, code: 0x122, from: 0xf8c21, to: 0xf90e1}, + 41: {region: 0x4241, code: 0x120, from: 0xf5c21, to: 0xf8c21}, + 42: {region: 0x4242, code: 0x1a, from: 0xf6b83, to: 0x0}, + 43: {region: 0x4242, code: 0x110, from: 0xf5b46, to: 0xf6b83}, + 44: {region: 0x4244, code: 0x1b, from: 0xf6821, to: 0x0}, + 45: {region: 0x4244, code: 0xc8, from: 0xf3881, to: 0xf6821}, + 46: {region: 0x4244, code: 0x7d, from: 0xe5711, to: 0xf3881}, + 47: {region: 0x4245, code: 0x5e, from: 0xf9e21, to: 0x0}, + 48: {region: 0x4245, code: 0x1d, from: 0xe4e47, to: 0xfa45c}, + 49: {region: 0x4245, code: 0xbd, from: 0xe318f, to: 0xe4e47}, + 50: {region: 0x4245, code: 0x801e, from: 0xf6421, to: 0xf8c65}, + 51: {region: 0x4245, code: 0x801c, from: 0xf6421, to: 0xf8c65}, + 52: {region: 0x4246, code: 0x115, from: 0xf8104, to: 0x0}, + 53: {region: 0x4247, code: 0x21, from: 0xf9ee5, to: 0x0}, + 54: {region: 0x4247, code: 0x1f, from: 0xf5421, to: 0xf9ee5}, + 55: {region: 0x4247, code: 0x20, from: 0xf40ac, to: 0xf5421}, + 56: {region: 0x4247, code: 0x22, from: 0xeaee8, to: 0xf40ac}, + 57: {region: 0x4248, code: 0x23, from: 0xf5b50, to: 0x0}, + 58: {region: 0x4249, code: 0x24, from: 0xf58b3, to: 0x0}, + 59: {region: 0x424a, code: 0x115, from: 0xf6f7e, to: 0x0}, + 60: {region: 0x424c, code: 0x5e, from: 0xf9e21, to: 0x0}, + 61: {region: 0x424c, code: 0x62, from: 0xf5021, to: 0xfa451}, + 62: {region: 0x424d, code: 0x25, from: 0xf6446, to: 0x0}, + 63: {region: 0x424e, code: 0x26, from: 0xf5ecc, to: 0x0}, + 64: {region: 0x424e, code: 0xb5, from: 0xf5730, to: 0xf5ecc}, + 65: {region: 0x424f, code: 0x27, from: 0xf8621, to: 0x0}, + 66: {region: 0x424f, code: 0x29, from: 0xf5621, to: 0xf859f}, + 67: {region: 0x424f, code: 0x28, from: 0xe8ed7, to: 0xf5621}, + 68: {region: 0x424f, code: 0x802a, from: 0x0, to: 0x0}, + 69: {region: 0x4251, code: 0xfc, from: 0xfb621, to: 0x0}, + 70: {region: 0x4251, code: 0x8, from: 0xfb54a, to: 0xfb621}, + 71: {region: 0x4252, code: 0x2e, from: 0xf94e1, to: 0x0}, + 72: {region: 0x4252, code: 0x30, from: 0xf9301, to: 0xf94e1}, + 73: {region: 0x4252, code: 0x2d, from: 0xf8c70, to: 0xf9301}, + 74: {region: 0x4252, code: 0x2f, from: 0xf8a2f, to: 0xf8c70}, + 75: {region: 0x4252, code: 0x2c, from: 0xf845c, to: 0xf8a2f}, + 76: {region: 0x4252, code: 0x2b, from: 0xf5e4d, to: 0xf845c}, + 77: {region: 0x4252, code: 0x31, from: 0xf2d61, to: 0xf5e4d}, + 78: {region: 0x4253, code: 0x32, from: 0xf5cb9, to: 0x0}, + 79: {region: 0x4254, code: 0x33, from: 0xf6c90, to: 0x0}, + 80: {region: 0x4254, code: 0x7d, from: 0xee621, to: 0x0}, + 81: {region: 0x4255, code: 0x34, from: 0xf40e1, to: 0xf8ad2}, + 82: {region: 0x4256, code: 0xbe, from: 0xee2c7, to: 0x0}, + 83: {region: 0x4257, code: 0x35, from: 0xf7117, to: 0x0}, + 84: {region: 0x4257, code: 0x125, from: 0xf524e, to: 0xf7117}, + 85: {region: 0x4259, code: 0x37, from: 0xfc0e1, to: 0x0}, + 86: {region: 0x4259, code: 0x38, from: 0xfa021, to: 0xfc221}, + 87: {region: 0x4259, code: 0x36, from: 0xf9501, to: 0xfa19f}, + 88: {region: 0x4259, code: 0xd3, from: 0xf8f99, to: 0xf9568}, + 89: {region: 0x4259, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 90: {region: 0x425a, code: 0x39, from: 0xf6c21, to: 0x0}, + 91: {region: 0x4341, code: 0x3a, from: 0xe8421, to: 0x0}, + 92: {region: 0x4343, code: 0x13, from: 0xf5c4e, to: 0x0}, + 93: {region: 0x4344, code: 0x3b, from: 0xf9ce1, to: 0x0}, + 94: {region: 0x4344, code: 0x128, from: 0xf9361, to: 0xf9ce1}, + 95: {region: 0x4344, code: 0x129, from: 0xf675b, to: 0xf9361}, + 96: {region: 0x4346, code: 0x109, from: 0xf9221, to: 0x0}, + 97: {region: 0x4347, code: 0x109, from: 0xf9221, to: 0x0}, + 98: {region: 0x4348, code: 0x3d, from: 0xe0e71, to: 0x0}, + 99: {region: 0x4348, code: 0x803c, from: 0x0, to: 0x0}, + 100: {region: 0x4348, code: 0x803e, from: 0x0, to: 0x0}, + 101: {region: 0x4349, code: 0x115, from: 0xf4d84, to: 0x0}, + 102: {region: 0x434b, code: 0xc0, from: 0xf5eea, to: 0x0}, + 103: {region: 0x434c, code: 0x41, from: 0xf6f3d, to: 0x0}, + 104: {region: 0x434c, code: 0x3f, from: 0xf5021, to: 0xf6f3d}, + 105: {region: 0x434c, code: 0x8040, from: 0x0, to: 0x0}, + 106: {region: 0x434d, code: 0x109, from: 0xf6a81, to: 0x0}, + 107: {region: 0x434e, code: 0x44, from: 0xf4261, to: 0x0}, + 108: {region: 0x434e, code: 0x8043, from: 0xf7621, to: 0xf9d9f}, + 109: {region: 0x434e, code: 0x8042, from: 0xfb4f3, to: 0x0}, + 110: {region: 0x434f, code: 0x45, from: 0xee221, to: 0x0}, + 111: {region: 0x434f, code: 0x8046, from: 0x0, to: 0x0}, + 112: {region: 0x4350, code: 0x811d, from: 0x0, to: 0x0}, + 113: {region: 0x4352, code: 0x47, from: 0xed15a, to: 0x0}, + 114: {region: 0x4353, code: 0x48, from: 0xfa4af, to: 0xfacc3}, + 115: {region: 0x4353, code: 0x5e, from: 0xfa644, to: 0xfacc3}, + 116: {region: 0x4353, code: 0x121, from: 0xf9438, to: 0xfa4af}, + 117: {region: 0x4355, code: 0x4b, from: 0xe8621, to: 0x0}, + 118: {region: 0x4355, code: 0x4a, from: 0xf9421, to: 0x0}, + 119: {region: 0x4355, code: 0xfc, from: 0xed621, to: 0xf4e21}, + 120: {region: 0x4356, code: 0x4c, from: 0xef421, to: 0x0}, + 121: {region: 0x4356, code: 0xcb, from: 0xeeeb6, to: 0xf6ee5}, + 122: {region: 0x4357, code: 0x8, from: 0xfb54a, to: 0x0}, + 123: {region: 0x4358, code: 0x13, from: 0xf5c4e, to: 0x0}, + 124: {region: 0x4359, code: 0x5e, from: 0xfb021, to: 0x0}, + 125: {region: 0x4359, code: 0x4d, from: 0xef52a, to: 0xfb03f}, + 126: {region: 0x435a, code: 0x4e, from: 0xf9221, to: 0x0}, + 127: {region: 0x435a, code: 0x49, from: 0xf42c1, to: 0xf9261}, + 128: {region: 0x4444, code: 0x4f, from: 0xf38f4, to: 0xf8d42}, + 129: {region: 0x4445, code: 0x5e, from: 0xf9e21, to: 0x0}, + 130: {region: 0x4445, code: 0x50, from: 0xf38d4, to: 0xfa45c}, + 131: {region: 0x4447, code: 0xfc, from: 0xf5b68, to: 0x0}, + 132: {region: 0x444a, code: 0x51, from: 0xf72db, to: 0x0}, + 133: {region: 0x444b, code: 0x52, from: 0xea2bb, to: 0x0}, + 134: {region: 0x444d, code: 0x110, from: 0xf5b46, to: 0x0}, + 135: {region: 0x444f, code: 0x53, from: 0xf3741, to: 0x0}, + 136: {region: 0x444f, code: 0xfc, from: 0xee2d5, to: 0xf3741}, + 137: {region: 0x445a, code: 0x54, from: 0xf5881, to: 0x0}, + 138: {region: 0x4541, code: 0x5e, from: 0xf9e21, to: 0x0}, + 139: {region: 0x4543, code: 0xfc, from: 0xfa142, to: 0x0}, + 140: {region: 0x4543, code: 0x55, from: 0xeb881, to: 0xfa142}, + 141: {region: 0x4543, code: 0x8056, from: 0xf92b7, to: 0xfa029}, + 142: {region: 0x4545, code: 0x5e, from: 0xfb621, to: 0x0}, + 143: {region: 0x4545, code: 0x57, from: 0xf90d5, to: 0xfb59f}, + 144: {region: 0x4545, code: 0xe7, from: 0xf5221, to: 0xf90d4}, + 145: {region: 0x4547, code: 0x58, from: 0xebb6e, to: 0x0}, + 146: {region: 0x4548, code: 0x9e, from: 0xf705a, to: 0x0}, + 147: {region: 0x4552, code: 0x59, from: 0xf9b68, to: 0x0}, + 148: {region: 0x4552, code: 0x5d, from: 0xf92b8, to: 0xf9b68}, + 149: {region: 0x4553, code: 0x5e, from: 0xf9e21, to: 0x0}, + 150: {region: 0x4553, code: 0x5c, from: 0xe9953, to: 0xfa45c}, + 151: {region: 0x4553, code: 0x805a, from: 0xf7421, to: 0xf7b9f}, + 152: {region: 0x4553, code: 0x805b, from: 0xf6e21, to: 0xf959f}, + 153: {region: 0x4554, code: 0x5d, from: 0xf712f, to: 0x0}, + 154: {region: 0x4555, code: 0x5e, from: 0xf9e21, to: 0x0}, + 155: {region: 0x4555, code: 0x8112, from: 0xf7621, to: 0xf9d9f}, + 156: {region: 0x4649, code: 0x5e, from: 0xf9e21, to: 0x0}, + 157: {region: 0x4649, code: 0x5f, from: 0xf5621, to: 0xfa45c}, + 158: {region: 0x464a, code: 0x60, from: 0xf622d, to: 0x0}, + 159: {region: 0x464b, code: 0x61, from: 0xeda21, to: 0x0}, + 160: {region: 0x464d, code: 0xfc, from: 0xf3021, to: 0x0}, + 161: {region: 0x464d, code: 0x85, from: 0xef543, to: 0xf3021}, + 162: {region: 0x464f, code: 0x52, from: 0xf3821, to: 0x0}, + 163: {region: 0x4652, code: 0x5e, from: 0xf9e21, to: 0x0}, + 164: {region: 0x4652, code: 0x62, from: 0xf5021, to: 0xfa451}, + 165: {region: 0x4741, code: 0x109, from: 0xf9221, to: 0x0}, + 166: {region: 0x4742, code: 0x63, from: 0xd3cfb, to: 0x0}, + 167: {region: 0x4744, code: 0x110, from: 0xf5e5b, to: 0x0}, + 168: {region: 0x4745, code: 0x65, from: 0xf9737, to: 0x0}, + 169: {region: 0x4745, code: 0x64, from: 0xf9285, to: 0xf9739}, + 170: {region: 0x4745, code: 0xd3, from: 0xf8f99, to: 0xf92cb}, + 171: {region: 0x4745, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 172: {region: 0x4746, code: 0x5e, from: 0xf9e21, to: 0x0}, + 173: {region: 0x4746, code: 0x62, from: 0xf5021, to: 0xfa451}, + 174: {region: 0x4747, code: 0x63, from: 0xe4c21, to: 0x0}, + 175: {region: 0x4748, code: 0x67, from: 0xfaee3, to: 0x0}, + 176: {region: 0x4748, code: 0x66, from: 0xf7669, to: 0xfaf9f}, + 177: {region: 0x4749, code: 0x68, from: 0xd6221, to: 0x0}, + 178: {region: 0x474c, code: 0x52, from: 0xea2bb, to: 0x0}, + 179: {region: 0x474d, code: 0x69, from: 0xf66e1, to: 0x0}, + 180: {region: 0x474e, code: 0x6a, from: 0xf8426, to: 0x0}, + 181: {region: 0x474e, code: 0x6b, from: 0xf6942, to: 0xf8426}, + 182: {region: 0x4750, code: 0x5e, from: 0xf9e21, to: 0x0}, + 183: {region: 0x4750, code: 0x62, from: 0xf5021, to: 0xfa451}, + 184: {region: 0x4751, code: 0x109, from: 0xf9221, to: 0x0}, + 185: {region: 0x4751, code: 0x6c, from: 0xf6ee7, to: 0xf84c1}, + 186: {region: 0x4752, code: 0x5e, from: 0xfa221, to: 0x0}, + 187: {region: 0x4752, code: 0x6d, from: 0xf44a1, to: 0xfa45c}, + 188: {region: 0x4753, code: 0x63, from: 0xee821, to: 0x0}, + 189: {region: 0x4754, code: 0x6e, from: 0xf0abb, to: 0x0}, + 190: {region: 0x4755, code: 0xfc, from: 0xf3115, to: 0x0}, + 191: {region: 0x4757, code: 0x115, from: 0xf9a7f, to: 0x0}, + 192: {region: 0x4757, code: 0x70, from: 0xf705c, to: 0xf9a7f}, + 193: {region: 0x4757, code: 0x6f, from: 0xef421, to: 0xf705c}, + 194: {region: 0x4759, code: 0x71, from: 0xf5cba, to: 0x0}, + 195: {region: 0x484b, code: 0x72, from: 0xece42, to: 0x0}, + 196: {region: 0x484d, code: 0x13, from: 0xf5e50, to: 0x0}, + 197: {region: 0x484e, code: 0x73, from: 0xf0c83, to: 0x0}, + 198: {region: 0x4852, code: 0x75, from: 0xf94be, to: 0x0}, + 199: {region: 0x4852, code: 0x74, from: 0xf8f97, to: 0xf9621}, + 200: {region: 0x4852, code: 0x122, from: 0xf8c21, to: 0xf8f97}, + 201: {region: 0x4852, code: 0x120, from: 0xf5c21, to: 0xf8c21}, + 202: {region: 0x4854, code: 0x76, from: 0xea11a, to: 0x0}, + 203: {region: 0x4854, code: 0xfc, from: 0xef621, to: 0x0}, + 204: {region: 0x4855, code: 0x77, from: 0xf34f7, to: 0x0}, + 205: {region: 0x4943, code: 0x5e, from: 0xf9e21, to: 0x0}, + 206: {region: 0x4944, code: 0x78, from: 0xf5b8d, to: 0x0}, + 207: {region: 0x4945, code: 0x5e, from: 0xf9e21, to: 0x0}, + 208: {region: 0x4945, code: 0x79, from: 0xf0421, to: 0xfa449}, + 209: {region: 0x4945, code: 0x63, from: 0xe1021, to: 0xf0421}, + 210: {region: 0x494c, code: 0x7c, from: 0xf8324, to: 0x0}, + 211: {region: 0x494c, code: 0x7b, from: 0xf7856, to: 0xf8324}, + 212: {region: 0x494c, code: 0x7a, from: 0xf3910, to: 0xf7856}, + 213: {region: 0x494d, code: 0x63, from: 0xe6023, to: 0x0}, + 214: {region: 0x494e, code: 0x7d, from: 0xe5711, to: 0x0}, + 215: {region: 0x494f, code: 0xfc, from: 0xf5b68, to: 0x0}, + 216: {region: 0x4951, code: 0x7e, from: 0xf1693, to: 0x0}, + 217: {region: 0x4951, code: 0x58, from: 0xf016b, to: 0xf1693}, + 218: {region: 0x4951, code: 0x7d, from: 0xf016b, to: 0xf1693}, + 219: {region: 0x4952, code: 0x7f, from: 0xf18ad, to: 0x0}, + 220: {region: 0x4953, code: 0x81, from: 0xf7a21, to: 0x0}, + 221: {region: 0x4953, code: 0x80, from: 0xefd81, to: 0xf7a21}, + 222: {region: 0x4953, code: 0x52, from: 0xea2bb, to: 0xefd81}, + 223: {region: 0x4954, code: 0x5e, from: 0xf9e21, to: 0x0}, + 224: {region: 0x4954, code: 0x82, from: 0xe8d18, to: 0xfa45c}, + 225: {region: 0x4a45, code: 0x63, from: 0xe5a21, to: 0x0}, + 226: {region: 0x4a4d, code: 0x83, from: 0xf6328, to: 0x0}, + 227: {region: 0x4a4f, code: 0x84, from: 0xf3ce1, to: 0x0}, + 228: {region: 0x4a50, code: 0x85, from: 0xe9ec1, to: 0x0}, + 229: {region: 0x4b45, code: 0x86, from: 0xf5d2e, to: 0x0}, + 230: {region: 0x4b47, code: 0x87, from: 0xf92aa, to: 0x0}, + 231: {region: 0x4b47, code: 0xd3, from: 0xf8f99, to: 0xf92aa}, + 232: {region: 0x4b47, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 233: {region: 0x4b48, code: 0x88, from: 0xf7874, to: 0x0}, + 234: {region: 0x4b49, code: 0x13, from: 0xf5c4e, to: 0x0}, + 235: {region: 0x4b4d, code: 0x89, from: 0xf6ee6, to: 0x0}, + 236: {region: 0x4b4e, code: 0x110, from: 0xf5b46, to: 0x0}, + 237: {region: 0x4b50, code: 0x8a, from: 0xf4e91, to: 0x0}, + 238: {region: 0x4b52, code: 0x8d, from: 0xf54ca, to: 0x0}, + 239: {region: 0x4b52, code: 0x8b, from: 0xf424f, to: 0xf54ca}, + 240: {region: 0x4b52, code: 0x8c, from: 0xf330f, to: 0xf424f}, + 241: {region: 0x4b57, code: 0x8e, from: 0xf5281, to: 0x0}, + 242: {region: 0x4b59, code: 0x8f, from: 0xf6621, to: 0x0}, + 243: {region: 0x4b59, code: 0x83, from: 0xf6328, to: 0xf6621}, + 244: {region: 0x4b5a, code: 0x90, from: 0xf9365, to: 0x0}, + 245: {region: 0x4c41, code: 0x91, from: 0xf778a, to: 0x0}, + 246: {region: 0x4c42, code: 0x92, from: 0xf3842, to: 0x0}, + 247: {region: 0x4c43, code: 0x110, from: 0xf5b46, to: 0x0}, + 248: {region: 0x4c49, code: 0x3d, from: 0xf0241, to: 0x0}, + 249: {region: 0x4c4b, code: 0x93, from: 0xf74b6, to: 0x0}, + 250: {region: 0x4c52, code: 0x94, from: 0xf3021, to: 0x0}, + 251: {region: 0x4c53, code: 0x125, from: 0xf524e, to: 0x0}, + 252: {region: 0x4c53, code: 0x95, from: 0xf7836, to: 0x0}, + 253: {region: 0x4c54, code: 0x5e, from: 0xfbe21, to: 0x0}, + 254: {region: 0x4c54, code: 0x96, from: 0xf92d9, to: 0xfbd9f}, + 255: {region: 0x4c54, code: 0x97, from: 0xf9141, to: 0xf92d9}, + 256: {region: 0x4c54, code: 0xe7, from: 0xf5221, to: 0xf9141}, + 257: {region: 0x4c55, code: 0x5e, from: 0xf9e21, to: 0x0}, + 258: {region: 0x4c55, code: 0x99, from: 0xf3124, to: 0xfa45c}, + 259: {region: 0x4c55, code: 0x8098, from: 0xf6421, to: 0xf8c65}, + 260: {region: 0x4c55, code: 0x809a, from: 0xf6421, to: 0xf8c65}, + 261: {region: 0x4c56, code: 0x5e, from: 0xfbc21, to: 0x0}, + 262: {region: 0x4c56, code: 0x9b, from: 0xf92dc, to: 0xfbb9f}, + 263: {region: 0x4c56, code: 0x9c, from: 0xf90a7, to: 0xf9351}, + 264: {region: 0x4c56, code: 0xe7, from: 0xf5221, to: 0xf90f4}, + 265: {region: 0x4c59, code: 0x9d, from: 0xf6721, to: 0x0}, + 266: {region: 0x4d41, code: 0x9e, from: 0xf4f51, to: 0x0}, + 267: {region: 0x4d41, code: 0x9f, from: 0xeb221, to: 0xf4f51}, + 268: {region: 0x4d43, code: 0x5e, from: 0xf9e21, to: 0x0}, + 269: {region: 0x4d43, code: 0x62, from: 0xf5021, to: 0xfa451}, + 270: {region: 0x4d43, code: 0xa0, from: 0xf5021, to: 0xfa451}, + 271: {region: 0x4d44, code: 0xa2, from: 0xf937d, to: 0x0}, + 272: {region: 0x4d44, code: 0xa1, from: 0xf90c1, to: 0xf937d}, + 273: {region: 0x4d45, code: 0x5e, from: 0xfa421, to: 0x0}, + 274: {region: 0x4d45, code: 0x50, from: 0xf9f42, to: 0xfa4af}, + 275: {region: 0x4d45, code: 0x121, from: 0xf9438, to: 0xfa4af}, + 276: {region: 0x4d46, code: 0x5e, from: 0xf9e21, to: 0x0}, + 277: {region: 0x4d46, code: 0x62, from: 0xf5021, to: 0xfa451}, + 278: {region: 0x4d47, code: 0xa3, from: 0xf7f61, to: 0x0}, + 279: {region: 0x4d47, code: 0xa4, from: 0xf56e1, to: 0xfa99f}, + 280: {region: 0x4d48, code: 0xfc, from: 0xf3021, to: 0x0}, + 281: {region: 0x4d4b, code: 0xa5, from: 0xf92b4, to: 0x0}, + 282: {region: 0x4d4b, code: 0xa6, from: 0xf909a, to: 0xf92b4}, + 283: {region: 0x4d4c, code: 0x115, from: 0xf80c1, to: 0x0}, + 284: {region: 0x4d4c, code: 0xa7, from: 0xf54e2, to: 0xf811f}, + 285: {region: 0x4d4c, code: 0x115, from: 0xf4d78, to: 0xf54e2}, + 286: {region: 0x4d4d, code: 0xa8, from: 0xf8ad2, to: 0x0}, + 287: {region: 0x4d4d, code: 0x34, from: 0xf40e1, to: 0xf8ad2}, + 288: {region: 0x4d4e, code: 0xa9, from: 0xef661, to: 0x0}, + 289: {region: 0x4d4f, code: 0xaa, from: 0xeda21, to: 0x0}, + 290: {region: 0x4d50, code: 0xfc, from: 0xf3021, to: 0x0}, + 291: {region: 0x4d51, code: 0x5e, from: 0xf9e21, to: 0x0}, + 292: {region: 0x4d51, code: 0x62, from: 0xf5021, to: 0xfa451}, + 293: {region: 0x4d52, code: 0xab, from: 0xf6add, to: 0x0}, + 294: {region: 0x4d52, code: 0x115, from: 0xf4d7c, to: 0xf6add}, + 295: {region: 0x4d53, code: 0x110, from: 0xf5e5b, to: 0x0}, + 296: {region: 0x4d54, code: 0x5e, from: 0xfb021, to: 0x0}, + 297: {region: 0x4d54, code: 0xac, from: 0xf60c7, to: 0xfb03f}, + 298: {region: 0x4d54, code: 0xad, from: 0xef50d, to: 0xf60c7}, + 299: {region: 0x4d55, code: 0xae, from: 0xf1c81, to: 0x0}, + 300: {region: 0x4d56, code: 0xb0, from: 0xf7ae1, to: 0x0}, + 301: {region: 0x4d57, code: 0xb1, from: 0xf664f, to: 0x0}, + 302: {region: 0x4d58, code: 0xb2, from: 0xf9221, to: 0x0}, + 303: {region: 0x4d58, code: 0xb3, from: 0xe3c21, to: 0xf919f}, + 304: {region: 0x4d58, code: 0x80b4, from: 0x0, to: 0x0}, + 305: {region: 0x4d59, code: 0xb5, from: 0xf5730, to: 0x0}, + 306: {region: 0x4d5a, code: 0xb8, from: 0xface1, to: 0x0}, + 307: {region: 0x4d5a, code: 0xb7, from: 0xf78d0, to: 0xfad9f}, + 308: {region: 0x4d5a, code: 0xb6, from: 0xf6ed9, to: 0xf78d0}, + 309: {region: 0x4e41, code: 0xb9, from: 0xf9221, to: 0x0}, + 310: {region: 0x4e41, code: 0x125, from: 0xf524e, to: 0x0}, + 311: {region: 0x4e43, code: 0x117, from: 0xf8221, to: 0x0}, + 312: {region: 0x4e45, code: 0x115, from: 0xf4d93, to: 0x0}, + 313: {region: 0x4e46, code: 0x13, from: 0xf5c4e, to: 0x0}, + 314: {region: 0x4e47, code: 0xba, from: 0xf6a21, to: 0x0}, + 315: {region: 0x4e49, code: 0xbc, from: 0xf8e9e, to: 0x0}, + 316: {region: 0x4e49, code: 0xbb, from: 0xf884f, to: 0xf8e9e}, + 317: {region: 0x4e4c, code: 0x5e, from: 0xf9e21, to: 0x0}, + 318: {region: 0x4e4c, code: 0xbd, from: 0xe2a21, to: 0xfa45c}, + 319: {region: 0x4e4f, code: 0xbe, from: 0xee2c7, to: 0x0}, + 320: {region: 0x4e4f, code: 0xdb, from: 0xea2bb, to: 0xee2c7}, + 321: {region: 0x4e50, code: 0xbf, from: 0xf1a21, to: 0x0}, + 322: {region: 0x4e50, code: 0x7d, from: 0xe9c21, to: 0xf5d51}, + 323: {region: 0x4e52, code: 0x13, from: 0xf5c4e, to: 0x0}, + 324: {region: 0x4e55, code: 0xc0, from: 0xf5eea, to: 0x0}, + 325: {region: 0x4e5a, code: 0xc0, from: 0xf5eea, to: 0x0}, + 326: {region: 0x4f4d, code: 0xc1, from: 0xf696b, to: 0x0}, + 327: {region: 0x5041, code: 0xc2, from: 0xedf64, to: 0x0}, + 328: {region: 0x5041, code: 0xfc, from: 0xedf72, to: 0x0}, + 329: {region: 0x5045, code: 0xc4, from: 0xf8ee1, to: 0x0}, + 330: {region: 0x5045, code: 0xc3, from: 0xf8241, to: 0xf8ee1}, + 331: {region: 0x5045, code: 0xc5, from: 0xe8e4e, to: 0xf8241}, + 332: {region: 0x5046, code: 0x117, from: 0xf339a, to: 0x0}, + 333: {region: 0x5047, code: 0xc6, from: 0xf6f30, to: 0x0}, + 334: {region: 0x5047, code: 0x13, from: 0xf5c4e, to: 0xf6f30}, + 335: {region: 0x5048, code: 0xc7, from: 0xf34e4, to: 0x0}, + 336: {region: 0x504b, code: 0xc8, from: 0xf3881, to: 0x0}, + 337: {region: 0x504b, code: 0x7d, from: 0xe5711, to: 0xf370f}, + 338: {region: 0x504c, code: 0xc9, from: 0xf9621, to: 0x0}, + 339: {region: 0x504c, code: 0xca, from: 0xf3d5c, to: 0xf959f}, + 340: {region: 0x504d, code: 0x5e, from: 0xf9e21, to: 0x0}, + 341: {region: 0x504d, code: 0x62, from: 0xf6995, to: 0xfa451}, + 342: {region: 0x504e, code: 0xc0, from: 0xf622d, to: 0x0}, + 343: {region: 0x5052, code: 0xfc, from: 0xed58a, to: 0x0}, + 344: {region: 0x5052, code: 0x5c, from: 0xe1021, to: 0xed58a}, + 345: {region: 0x5053, code: 0x7c, from: 0xf8324, to: 0x0}, + 346: {region: 0x5053, code: 0x84, from: 0xf984c, to: 0x0}, + 347: {region: 0x5053, code: 0x7a, from: 0xf5ec1, to: 0xf7856}, + 348: {region: 0x5053, code: 0x84, from: 0xf3ce1, to: 0xf5ec1}, + 349: {region: 0x5054, code: 0x5e, from: 0xf9e21, to: 0x0}, + 350: {region: 0x5054, code: 0xcb, from: 0xeeeb6, to: 0xfa45c}, + 351: {region: 0x5057, code: 0xfc, from: 0xf3021, to: 0x0}, + 352: {region: 0x5059, code: 0xcc, from: 0xf2f61, to: 0x0}, + 353: {region: 0x5141, code: 0xcd, from: 0xf6ab3, to: 0x0}, + 354: {region: 0x5245, code: 0x5e, from: 0xf9e21, to: 0x0}, + 355: {region: 0x5245, code: 0x62, from: 0xf6e21, to: 0xfa451}, + 356: {region: 0x524f, code: 0xd0, from: 0xfaae1, to: 0x0}, + 357: {region: 0x524f, code: 0xcf, from: 0xf403c, to: 0xfad9f}, + 358: {region: 0x5253, code: 0xd1, from: 0xfad59, to: 0x0}, + 359: {region: 0x5253, code: 0x48, from: 0xfa4af, to: 0xfad59}, + 360: {region: 0x5253, code: 0x121, from: 0xf9438, to: 0xfa4af}, + 361: {region: 0x5255, code: 0xd2, from: 0xf9e21, to: 0x0}, + 362: {region: 0x5255, code: 0xd3, from: 0xf8f99, to: 0xf9d9f}, + 363: {region: 0x5257, code: 0xd4, from: 0xf58b3, to: 0x0}, + 364: {region: 0x5341, code: 0xd5, from: 0xf4156, to: 0x0}, + 365: {region: 0x5342, code: 0xd6, from: 0xf7358, to: 0x0}, + 366: {region: 0x5342, code: 0x13, from: 0xf5c4e, to: 0xf74de}, + 367: {region: 0x5343, code: 0xd7, from: 0xedf61, to: 0x0}, + 368: {region: 0x5344, code: 0xd9, from: 0xfae2a, to: 0x0}, + 369: {region: 0x5344, code: 0xd8, from: 0xf90c8, to: 0xfaede}, + 370: {region: 0x5344, code: 0xda, from: 0xf4a88, to: 0xf9cc1}, + 371: {region: 0x5344, code: 0x58, from: 0xec233, to: 0xf4c21}, + 372: {region: 0x5344, code: 0x63, from: 0xec233, to: 0xf4c21}, + 373: {region: 0x5345, code: 0xdb, from: 0xea2bb, to: 0x0}, + 374: {region: 0x5347, code: 0xdc, from: 0xf5ecc, to: 0x0}, + 375: {region: 0x5347, code: 0xb5, from: 0xf5730, to: 0xf5ecc}, + 376: {region: 0x5348, code: 0xdd, from: 0xefa4f, to: 0x0}, + 377: {region: 0x5349, code: 0x5e, from: 0xfae21, to: 0x0}, + 378: {region: 0x5349, code: 0xde, from: 0xf9147, to: 0xfae2e}, + 379: {region: 0x534a, code: 0xbe, from: 0xee2c7, to: 0x0}, + 380: {region: 0x534b, code: 0x5e, from: 0xfb221, to: 0x0}, + 381: {region: 0x534b, code: 0xdf, from: 0xf919f, to: 0xfb221}, + 382: {region: 0x534b, code: 0x49, from: 0xf42c1, to: 0xf919f}, + 383: {region: 0x534c, code: 0xe0, from: 0xf5904, to: 0x0}, + 384: {region: 0x534c, code: 0x63, from: 0xe217e, to: 0xf5c44}, + 385: {region: 0x534d, code: 0x5e, from: 0xf9e21, to: 0x0}, + 386: {region: 0x534d, code: 0x82, from: 0xe9397, to: 0xfa25c}, + 387: {region: 0x534e, code: 0x115, from: 0xf4e84, to: 0x0}, + 388: {region: 0x534f, code: 0xe1, from: 0xf50e1, to: 0x0}, + 389: {region: 0x5352, code: 0xe2, from: 0xfa821, to: 0x0}, + 390: {region: 0x5352, code: 0xe3, from: 0xf28aa, to: 0xfa79f}, + 391: {region: 0x5352, code: 0xbd, from: 0xe2f74, to: 0xf28aa}, + 392: {region: 0x5353, code: 0xe4, from: 0xfb6f2, to: 0x0}, + 393: {region: 0x5353, code: 0xd9, from: 0xfae2a, to: 0xfb721}, + 394: {region: 0x5354, code: 0xe6, from: 0xfc421, to: 0x0}, + 395: {region: 0x5354, code: 0xe5, from: 0xf7328, to: 0xfc39f}, + 396: {region: 0x5355, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 397: {region: 0x5356, code: 0xfc, from: 0xfa221, to: 0x0}, + 398: {region: 0x5356, code: 0xe8, from: 0xeff6b, to: 0xfa221}, + 399: {region: 0x5358, code: 0x8, from: 0xfb54a, to: 0x0}, + 400: {region: 0x5359, code: 0xe9, from: 0xf3821, to: 0x0}, + 401: {region: 0x535a, code: 0xea, from: 0xf6d26, to: 0x0}, + 402: {region: 0x5441, code: 0x63, from: 0xf242c, to: 0x0}, + 403: {region: 0x5443, code: 0xfc, from: 0xf6328, to: 0x0}, + 404: {region: 0x5444, code: 0x109, from: 0xf9221, to: 0x0}, + 405: {region: 0x5446, code: 0x5e, from: 0xf9e21, to: 0x0}, + 406: {region: 0x5446, code: 0x62, from: 0xf4e21, to: 0xfa451}, + 407: {region: 0x5447, code: 0x115, from: 0xf4d7c, to: 0x0}, + 408: {region: 0x5448, code: 0xeb, from: 0xf108f, to: 0x0}, + 409: {region: 0x544a, code: 0xed, from: 0xfa15a, to: 0x0}, + 410: {region: 0x544a, code: 0xec, from: 0xf96aa, to: 0xfa159}, + 411: {region: 0x544a, code: 0xd3, from: 0xf8f99, to: 0xf96aa}, + 412: {region: 0x544b, code: 0xc0, from: 0xf5eea, to: 0x0}, + 413: {region: 0x544c, code: 0xfc, from: 0xf9f54, to: 0x0}, + 414: {region: 0x544c, code: 0xf2, from: 0xf4e22, to: 0xfa4b4}, + 415: {region: 0x544c, code: 0x78, from: 0xf6f87, to: 0xfa4b4}, + 416: {region: 0x544d, code: 0xef, from: 0xfb221, to: 0x0}, + 417: {region: 0x544d, code: 0xee, from: 0xf9361, to: 0xfb221}, + 418: {region: 0x544d, code: 0xd3, from: 0xf8f99, to: 0xf9361}, + 419: {region: 0x544d, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 420: {region: 0x544e, code: 0xf0, from: 0xf4d61, to: 0x0}, + 421: {region: 0x544f, code: 0xf1, from: 0xf5c4e, to: 0x0}, + 422: {region: 0x5450, code: 0xf2, from: 0xf4e22, to: 0xfa4b4}, + 423: {region: 0x5450, code: 0x78, from: 0xf6f87, to: 0xfa4b4}, + 424: {region: 0x5452, code: 0xf4, from: 0xfaa21, to: 0x0}, + 425: {region: 0x5452, code: 0xf3, from: 0xf0561, to: 0xfab9f}, + 426: {region: 0x5454, code: 0xf5, from: 0xf5821, to: 0x0}, + 427: {region: 0x5456, code: 0x13, from: 0xf5c4e, to: 0x0}, + 428: {region: 0x5457, code: 0xf6, from: 0xf3acf, to: 0x0}, + 429: {region: 0x545a, code: 0xf7, from: 0xf5cce, to: 0x0}, + 430: {region: 0x5541, code: 0xf8, from: 0xf9922, to: 0x0}, + 431: {region: 0x5541, code: 0xf9, from: 0xf916d, to: 0xf9351}, + 432: {region: 0x5541, code: 0xd3, from: 0xf8f99, to: 0xf916d}, + 433: {region: 0x5541, code: 0xe7, from: 0xf5221, to: 0xf8f99}, + 434: {region: 0x5547, code: 0xfb, from: 0xf86af, to: 0x0}, + 435: {region: 0x5547, code: 0xfa, from: 0xf5d0f, to: 0xf86af}, + 436: {region: 0x554d, code: 0xfc, from: 0xf3021, to: 0x0}, + 437: {region: 0x5553, code: 0xfc, from: 0xe0021, to: 0x0}, + 438: {region: 0x5553, code: 0x80fd, from: 0x0, to: 0x0}, + 439: {region: 0x5553, code: 0x80fe, from: 0x0, to: 0xfbc61}, + 440: {region: 0x5559, code: 0x101, from: 0xf9261, to: 0x0}, + 441: {region: 0x5559, code: 0x100, from: 0xf6ee1, to: 0xf9261}, + 442: {region: 0x5559, code: 0x80ff, from: 0x0, to: 0x0}, + 443: {region: 0x555a, code: 0x102, from: 0xf94e1, to: 0x0}, + 444: {region: 0x5641, code: 0x5e, from: 0xf9e21, to: 0x0}, + 445: {region: 0x5641, code: 0x82, from: 0xe9d53, to: 0xfa45c}, + 446: {region: 0x5643, code: 0x110, from: 0xf5b46, to: 0x0}, + 447: {region: 0x5645, code: 0x104, from: 0xfb021, to: 0x0}, + 448: {region: 0x5645, code: 0x103, from: 0xe9eab, to: 0xfb0de}, + 449: {region: 0x5647, code: 0xfc, from: 0xe5221, to: 0x0}, + 450: {region: 0x5647, code: 0x63, from: 0xe5221, to: 0xf4e21}, + 451: {region: 0x5649, code: 0xfc, from: 0xe5a21, to: 0x0}, + 452: {region: 0x564e, code: 0x105, from: 0xf832e, to: 0x0}, + 453: {region: 0x564e, code: 0x106, from: 0xf74a3, to: 0xf832e}, + 454: {region: 0x5655, code: 0x107, from: 0xf7a21, to: 0x0}, + 455: {region: 0x5746, code: 0x117, from: 0xf52fe, to: 0x0}, + 456: {region: 0x5753, code: 0x108, from: 0xf5eea, to: 0x0}, + 457: {region: 0x584b, code: 0x5e, from: 0xfa421, to: 0x0}, + 458: {region: 0x584b, code: 0x50, from: 0xf9f21, to: 0xfa469}, + 459: {region: 0x584b, code: 0x121, from: 0xf9438, to: 0xf9f3e}, + 460: {region: 0x5944, code: 0x11e, from: 0xf5a81, to: 0xf9821}, + 461: {region: 0x5945, code: 0x11f, from: 0xf8cb6, to: 0x0}, + 462: {region: 0x5954, code: 0x5e, from: 0xf9e21, to: 0x0}, + 463: {region: 0x5954, code: 0x62, from: 0xf7057, to: 0xfa451}, + 464: {region: 0x5954, code: 0x89, from: 0xf6e21, to: 0xf7057}, + 465: {region: 0x5955, code: 0x121, from: 0xf9438, to: 0xfa4af}, + 466: {region: 0x5955, code: 0x122, from: 0xf8c21, to: 0xf90f8}, + 467: {region: 0x5955, code: 0x120, from: 0xf5c21, to: 0xf8c21}, + 468: {region: 0x5a41, code: 0x125, from: 0xf524e, to: 0x0}, + 469: {region: 0x5a41, code: 0x8124, from: 0xf8321, to: 0xf966d}, + 470: {region: 0x5a4d, code: 0x127, from: 0xfba21, to: 0x0}, + 471: {region: 0x5a4d, code: 0x126, from: 0xf6030, to: 0xfba21}, + 472: {region: 0x5a52, code: 0x128, from: 0xf9361, to: 0xf9cff}, + 473: {region: 0x5a52, code: 0x129, from: 0xf675b, to: 0xf9361}, + 474: {region: 0x5a57, code: 0xfc, from: 0xfb28c, to: 0x0}, + 475: {region: 0x5a57, code: 0x12b, from: 0xfb242, to: 0xfb28c}, + 476: {region: 0x5a57, code: 0x12c, from: 0xfb101, to: 0xfb242}, + 477: {region: 0x5a57, code: 0x12a, from: 0xf7892, to: 0xfb101}, + 478: {region: 0x5a57, code: 0xce, from: 0xf6451, to: 0xf7892}, + 479: {region: 0x5a5a, code: 0x810a, from: 0x0, to: 0x0}, + 480: {region: 0x5a5a, code: 0x810b, from: 0x0, to: 0x0}, + 481: {region: 0x5a5a, code: 0x810c, from: 0x0, to: 0x0}, + 482: {region: 0x5a5a, code: 0x810d, from: 0x0, to: 0x0}, + 483: {region: 0x5a5a, code: 0x810e, from: 0x0, to: 0x0}, + 484: {region: 0x5a5a, code: 0x810f, from: 0x0, to: 0x0}, + 485: {region: 0x5a5a, code: 0x8111, from: 0x0, to: 0x0}, + 486: {region: 0x5a5a, code: 0x8113, from: 0xf1421, to: 0xfa681}, + 487: {region: 0x5a5a, code: 0x8114, from: 0x0, to: 0xfbb7e}, + 488: {region: 0x5a5a, code: 0x8116, from: 0x0, to: 0x0}, + 489: {region: 0x5a5a, code: 0x8118, from: 0x0, to: 0x0}, + 490: {region: 0x5a5a, code: 0x8119, from: 0x0, to: 0xf9f7e}, + 491: {region: 0x5a5a, code: 0x811a, from: 0x0, to: 0x0}, + 492: {region: 0x5a5a, code: 0x811b, from: 0x0, to: 0x0}, + 493: {region: 0x5a5a, code: 0x811c, from: 0x0, to: 0x0}, + 494: {region: 0x5a5a, code: 0x811d, from: 0x0, to: 0x0}, +} // Size: 5964 bytes + +// symbols holds symbol data of the form , where n is the length of +// the symbol string str. +const symbols string = "" + // Size: 1445 bytes + "\x00\x02Kz\x01$\x02A$\x02KM\x03৳\x02Bs\x02R$\x01P\x03р.\x03CA$\x04CN¥" + + "\x02¥\x03₡\x03Kč\x02kr\x03E£\x03₧\x03€\x02£\x03₾\x02FG\x01Q\x03HK$\x01L" + + "\x02kn\x02Ft\x02Rp\x03₪\x03₹\x04JP¥\x03៛\x02CF\x03₩\x03₸\x03₭\x03L£\x02R" + + "s\x02Lt\x02Ls\x02Ar\x01K\x03₮\x03MX$\x02RM\x03₦\x02C$\x03NZ$\x03₱\x03zł" + + "\x03₲\x03lei\x03₽\x02RF\x02Db\x03฿\x02T$\x03₺\x03NT$\x03₴\x03US$\x03₫" + + "\x04FCFA\x03EC$\x03CFA\x04CFPF\x01R\x02ZK\x03leu\x05GH₵\x03AU$\x16የቻይና ዩ" + + "ዋን\x06ብር\x03***\x09د.إ.\u200f\x03AR$\x03BB$\x09د.ب.\u200f\x03BM$\x03BN" + + "$\x03BS$\x03BZ$\x03CL$\x03CO$\x03CU$\x03DO$\x09د.ج.\u200f\x09ج.م.\u200f" + + "\x03FJ$\x04UK£\x03GY$\x09د.ع.\u200f\x06ر.إ.\x03JM$\x09د.أ.\u200f\x09د.ك." + + "\u200f\x03KY$\x09ل.ل.\u200f\x09د.ل.\u200f\x09د.م.\u200f\x09أ.م.\u200f" + + "\x09ر.ع.\u200f\x09ر.ق.\u200f\x09ر.س.\u200f\x03SB$\x09د.س.\u200f\x06ج.س." + + "\x03SR$\x09ل.س.\u200f\x09د.ت.\u200f\x03TT$\x03UY$\x09ر.ي.\u200f\x03Fdj" + + "\x03Nfk\x01S\x04GB£\x03TSh\x03₼\x03ley\x03S£\x04Bds$\x03BD$\x02B$\x02Br" + + "\x04CUC$\x03$MN\x03RD$\x04FK£\x02G$\x04Íkr\x02J$\x03CI$\x02L$\x02N$\x07р" + + "уб.\x03SI$\x02S$\x02$U\x05лв.\x06щ.д.\x02$A\x03$CA\x04£ E\x05£ RU\x04$ " + + "HK\x03£L\x04$ ZN\x03$ T\x04$ SU\x04din.\x04КМ\x04Кч\x04зл\x07дин.\x04Тл" + + "\x01F\x06лей\x03USh\x04Kčs\x03ECU\x02TK\x03kr.\x03Ksh\x03öS\x03BGK\x03BG" + + "J\x04Cub$\x02DM\x04Fl£\x04F.G.\x02FC\x04F.Rw\x03Nu.\x05KR₩\x05TH฿\x06Δρχ" + + "\x02Tk\x02$b\x02Kr\x02Gs\x03CFP\x03FBu\x01D\x04MOP$\x02MK\x02SR\x02Le" + + "\x04NAf.\x01E\x02VT\x03WS$\x04SD£\x03BsF\x02p.\x03B/.\x02S/\x03Gs.\x03Bs" + + ".\x02؋\x04¥CN\x03$HK\x08ریال\x03$MX\x03$NZ\x03$EC\x02UM\x02mk\x03$AR\x03" + + "$AU\x02FB\x03$BM\x03$BN\x03$BS\x03$BZ\x03$CL\x03$CO\x04£CY\x03£E\x03$FJ" + + "\x04£FK\x04£GB\x04£GI\x04£IE\x04£IL\x05₤IT\x04£LB\x04£MT\x03$NA\x02$C" + + "\x03$RH\x02FR\x03$SB\x03$SG\x03$SR\x03$TT\x03$US\x03$UY\x04FCFP\x02Kw" + + "\x05$\u00a0AU\x05$\u00a0HK\x05$\u00a0NZ\x05$\u00a0SG\x05$\u00a0US\x02DA" + + "\x01G\x02LS\x02DT\x06руб\x07રૂ.\x0a\u200eCN¥\u200e\x06ל״י\x09लेई\x02֏" + + "\x03NKr\x03元\x03¥\x06レイ\x03\u200b\x06ಲೀ\x02LE\x02Kn\x06сом\x02zl\x02rb" + + "\x03MTn\x06ден\x04кр\x03NAf\x03Afl\x0cनेरू\x06रू\x04Afl.\x02ر\x03lej\x04" + + "Esc.\x06\u200bPTE\x04XXXX\x03ლ\x06ТМТ\x03Dkr\x03Skr\x03Nkr\x07රු.\x0fසිෆ" + + "්එ\x03NIS\x05Lekë\x03den\x02r.\x03BR$\x03Ekr\x04EG£\x04IE£\x03Ikr\x03R" + + "s.\x07сом.\x04AUD$\x04NZD$\x07крб.\x05soʻm\x06сўм\x03₩\x03ILS\x02P.\x03Z" + + "ł" + +type curToIndex struct { + cur uint16 + idx uint16 +} + +var normalLangIndex = []uint16{ // 776 elements + // Entry 0 - 3F + 0x0000, 0x0014, 0x0017, 0x0018, 0x0018, 0x0018, 0x0018, 0x0019, + 0x0019, 0x001d, 0x001d, 0x0034, 0x0034, 0x0034, 0x0034, 0x0035, + 0x0035, 0x0035, 0x0035, 0x0036, 0x0036, 0x0036, 0x0036, 0x0037, + 0x0037, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, + 0x0038, 0x0038, 0x0039, 0x003b, 0x003b, 0x003b, 0x003b, 0x003b, + 0x003b, 0x003b, 0x003b, 0x003c, 0x003c, 0x003f, 0x003f, 0x0041, + 0x0042, 0x0042, 0x0042, 0x0042, 0x0042, 0x0042, 0x0049, 0x0049, + 0x004a, 0x004a, 0x004b, 0x004b, 0x005c, 0x005c, 0x005c, 0x005c, + // Entry 40 - 7F + 0x005c, 0x005e, 0x005e, 0x005e, 0x005f, 0x005f, 0x0060, 0x006e, + 0x006e, 0x006e, 0x006e, 0x007f, 0x0085, 0x0085, 0x0085, 0x0085, + 0x008e, 0x008e, 0x008e, 0x008f, 0x008f, 0x0091, 0x0091, 0x0091, + 0x0092, 0x0092, 0x0093, 0x0093, 0x0094, 0x0094, 0x0095, 0x0095, + 0x0095, 0x009c, 0x009c, 0x009d, 0x009d, 0x009f, 0x009f, 0x00a3, + 0x00a3, 0x00a3, 0x00a4, 0x00a4, 0x00ac, 0x00ac, 0x00ac, 0x00ad, + 0x00ad, 0x00ad, 0x00ae, 0x00af, 0x00af, 0x00af, 0x00b4, 0x00b4, + 0x00b4, 0x00b4, 0x00b4, 0x00b4, 0x00b4, 0x00ba, 0x00ba, 0x00bb, + // Entry 80 - BF + 0x00bb, 0x00be, 0x00be, 0x00be, 0x00c1, 0x00c1, 0x00c1, 0x00c3, + 0x00c5, 0x00c5, 0x00c6, 0x00c7, 0x00c7, 0x00c7, 0x00dc, 0x00dd, + 0x00dd, 0x00de, 0x00df, 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, + 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e6, 0x00e6, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00e9, 0x00ea, 0x00ec, 0x00ec, 0x00ec, 0x00ed, + 0x00ed, 0x00ee, 0x00f0, 0x00f1, 0x00f1, 0x00f2, 0x00f2, 0x00f2, + 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f3, 0x00f4, 0x00f5, + 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fb, 0x00fc, + // Entry C0 - FF + 0x00fc, 0x00fd, 0x00fe, 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, + 0x0104, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, + 0x010b, 0x010b, 0x010b, 0x010c, 0x010d, 0x010e, 0x010e, 0x010f, + 0x0110, 0x0112, 0x0112, 0x0113, 0x0115, 0x0116, 0x0117, 0x0117, + 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011d, 0x011d, + 0x011e, 0x011e, 0x011e, 0x011f, 0x0120, 0x0121, 0x0122, 0x0122, + 0x0122, 0x0122, 0x0133, 0x0138, 0x013a, 0x013b, 0x013c, 0x013d, + 0x013f, 0x0141, 0x0142, 0x0144, 0x0146, 0x0146, 0x0147, 0x0147, + // Entry 100 - 13F + 0x0148, 0x0149, 0x014a, 0x014a, 0x014b, 0x014c, 0x014d, 0x014e, + 0x014f, 0x0150, 0x0151, 0x0152, 0x0154, 0x0156, 0x0157, 0x015c, + 0x015c, 0x015e, 0x015e, 0x015e, 0x015e, 0x0169, 0x0169, 0x0169, + 0x0169, 0x0169, 0x016a, 0x016b, 0x016b, 0x017c, 0x017c, 0x0180, + 0x0180, 0x0181, 0x0182, 0x0182, 0x01a8, 0x01a8, 0x01a8, 0x01a9, + 0x01a9, 0x01a9, 0x01ca, 0x01cb, 0x01cb, 0x01cb, 0x01cb, 0x01cb, + 0x01cb, 0x01cc, 0x01cd, 0x01cd, 0x01cd, 0x01cd, 0x01ce, 0x01ce, + 0x01ce, 0x01cf, 0x01d0, 0x01d2, 0x01d2, 0x01d2, 0x01d2, 0x01d3, + // Entry 140 - 17F + 0x01d3, 0x01d3, 0x01d4, 0x01d5, 0x01d5, 0x01d5, 0x01d5, 0x01d5, + 0x01d5, 0x01d6, 0x01d7, 0x01d7, 0x01d8, 0x01d8, 0x01d8, 0x01d9, + 0x01da, 0x01da, 0x01da, 0x01da, 0x01da, 0x01e0, 0x01e0, 0x01e3, + 0x01e3, 0x01e5, 0x01e5, 0x01e9, 0x01e9, 0x01ec, 0x01ec, 0x01ec, + 0x01ec, 0x01ed, 0x01ed, 0x01ed, 0x01ee, 0x01ee, 0x01ee, 0x01ee, + 0x01ef, 0x01f0, 0x01f0, 0x01f0, 0x01f1, 0x01f1, 0x01f6, 0x01f6, + 0x01f8, 0x01f8, 0x020a, 0x020b, 0x020b, 0x0210, 0x0210, 0x0222, + 0x0222, 0x0225, 0x0225, 0x0229, 0x0229, 0x022a, 0x022a, 0x022b, + // Entry 180 - 1BF + 0x022b, 0x022b, 0x022b, 0x0237, 0x0237, 0x023f, 0x023f, 0x023f, + 0x023f, 0x023f, 0x023f, 0x023f, 0x0242, 0x0242, 0x0242, 0x0242, + 0x0242, 0x0242, 0x0243, 0x0243, 0x0243, 0x0243, 0x024d, 0x024d, + 0x024e, 0x024e, 0x024e, 0x024f, 0x024f, 0x024f, 0x0250, 0x0250, + 0x0253, 0x0253, 0x0253, 0x0253, 0x0254, 0x0254, 0x0258, 0x0258, + 0x0258, 0x0258, 0x0259, 0x0259, 0x025a, 0x025a, 0x025d, 0x025d, + 0x025f, 0x025f, 0x0260, 0x0260, 0x0260, 0x0260, 0x0260, 0x0260, + 0x0260, 0x0261, 0x0261, 0x0261, 0x0261, 0x0261, 0x0261, 0x0261, + // Entry 1C0 - 1FF + 0x0261, 0x0261, 0x0270, 0x0270, 0x0271, 0x0271, 0x0276, 0x0276, + 0x0277, 0x0277, 0x0278, 0x0278, 0x0279, 0x027a, 0x027a, 0x027a, + 0x027a, 0x027c, 0x027c, 0x027d, 0x027d, 0x027d, 0x0290, 0x0290, + 0x0291, 0x0291, 0x0292, 0x0292, 0x0293, 0x0293, 0x0298, 0x0298, + 0x0299, 0x0299, 0x029a, 0x029b, 0x029b, 0x029c, 0x029c, 0x029d, + 0x029d, 0x029e, 0x029e, 0x029e, 0x029e, 0x02aa, 0x02aa, 0x02ad, + 0x02ad, 0x02b0, 0x02b0, 0x02b0, 0x02b2, 0x02b2, 0x02b6, 0x02b7, + 0x02b7, 0x02b8, 0x02b8, 0x02b8, 0x02b8, 0x02b8, 0x02bf, 0x02bf, + // Entry 200 - 23F + 0x02c0, 0x02c0, 0x02c0, 0x02c1, 0x02c1, 0x02d3, 0x02d3, 0x02d3, + 0x02d3, 0x02d3, 0x02d3, 0x02d3, 0x02d3, 0x02d5, 0x02d5, 0x02d5, + 0x02db, 0x02dc, 0x02dc, 0x02dd, 0x02de, 0x02de, 0x02df, 0x02e0, + 0x02e0, 0x02e0, 0x02f3, 0x02f3, 0x02f3, 0x02f3, 0x02f3, 0x02f3, + 0x02f3, 0x02f3, 0x02f5, 0x02f5, 0x02f5, 0x02f6, 0x02f6, 0x02f7, + 0x02f7, 0x02f8, 0x02fa, 0x02fa, 0x02fc, 0x02fc, 0x02fe, 0x02ff, + 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x030f, 0x030f, 0x030f, + 0x030f, 0x0310, 0x0310, 0x0313, 0x0314, 0x0314, 0x0314, 0x0316, + // Entry 240 - 27F + 0x0316, 0x0316, 0x0317, 0x0318, 0x0319, 0x031a, 0x031b, 0x031b, + 0x031c, 0x031e, 0x0320, 0x0320, 0x0320, 0x0320, 0x0321, 0x0321, + 0x0332, 0x0333, 0x0333, 0x0334, 0x0334, 0x033c, 0x033e, 0x033f, + 0x0340, 0x0341, 0x0341, 0x0341, 0x0342, 0x0342, 0x0343, 0x0343, + 0x0344, 0x0344, 0x0345, 0x0345, 0x0346, 0x0346, 0x0347, 0x0347, + 0x0347, 0x034b, 0x034b, 0x034b, 0x034d, 0x034e, 0x034e, 0x034e, + 0x034e, 0x034e, 0x034e, 0x034e, 0x034e, 0x034e, 0x034e, 0x034e, + 0x034e, 0x0351, 0x0351, 0x035f, 0x035f, 0x0369, 0x0369, 0x0369, + // Entry 280 - 2BF + 0x0369, 0x0369, 0x0369, 0x0369, 0x0369, 0x0369, 0x0369, 0x036a, + 0x036b, 0x036c, 0x036d, 0x036d, 0x036f, 0x036f, 0x0370, 0x0370, + 0x0376, 0x0376, 0x0376, 0x0376, 0x0376, 0x0376, 0x037c, 0x037c, + 0x037c, 0x037c, 0x037c, 0x037c, 0x037c, 0x037c, 0x0394, 0x0394, + 0x0394, 0x0394, 0x0397, 0x0398, 0x0398, 0x0398, 0x0399, 0x0399, + 0x039c, 0x039c, 0x039d, 0x039f, 0x03a2, 0x03a4, 0x03a4, 0x03a5, + 0x03a6, 0x03a6, 0x03a8, 0x03a8, 0x03aa, 0x03aa, 0x03ab, 0x03ac, + 0x03ac, 0x03ac, 0x03ae, 0x03ae, 0x03ae, 0x03ae, 0x03b1, 0x03b1, + // Entry 2C0 - 2FF + 0x03b6, 0x03b6, 0x03b6, 0x03b6, 0x03b8, 0x03b8, 0x03b8, 0x03b8, + 0x03b8, 0x03b8, 0x03ba, 0x03ba, 0x03cd, 0x03cd, 0x03d0, 0x03d1, + 0x03d1, 0x03d2, 0x03d3, 0x03d3, 0x03d5, 0x03d5, 0x03d5, 0x03d5, + 0x03d6, 0x03d7, 0x03d7, 0x03d7, 0x03d7, 0x03d7, 0x03d9, 0x03d9, + 0x03d9, 0x03d9, 0x03da, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03dd, + 0x03dd, 0x03dd, 0x03de, 0x03de, 0x03de, 0x03de, 0x03de, 0x03de, + 0x03df, 0x03df, 0x03df, 0x03e2, 0x03e5, 0x03e5, 0x03e5, 0x03e5, + 0x03e5, 0x03e5, 0x03e9, 0x03e9, 0x03e9, 0x03ea, 0x03ec, 0x03ee, + // Entry 300 - 33F + 0x03f2, 0x03f4, 0x03f5, 0x03f5, 0x03f7, 0x03f7, 0x03f7, 0x03f7, +} // Size: 1576 bytes + +var normalSymIndex = []curToIndex{ // 1015 elements + 0: {cur: 0x13, idx: 0x6}, + 1: {cur: 0x2e, idx: 0x13}, + 2: {cur: 0x3a, idx: 0x1c}, + 3: {cur: 0x44, idx: 0x20}, + 4: {cur: 0x5e, idx: 0x3b}, + 5: {cur: 0x63, idx: 0x3f}, + 6: {cur: 0x72, idx: 0x4b}, + 7: {cur: 0x7c, idx: 0x5a}, + 8: {cur: 0x7d, idx: 0x5e}, + 9: {cur: 0x85, idx: 0x62}, + 10: {cur: 0x8d, idx: 0x6e}, + 11: {cur: 0xb2, idx: 0x90}, + 12: {cur: 0xc0, idx: 0x9e}, + 13: {cur: 0xf6, idx: 0xc7}, + 14: {cur: 0xfc, idx: 0xcf}, + 15: {cur: 0x105, idx: 0xd3}, + 16: {cur: 0x109, idx: 0xd7}, + 17: {cur: 0x110, idx: 0xdc}, + 18: {cur: 0x115, idx: 0xe0}, + 19: {cur: 0x117, idx: 0xe4}, + 20: {cur: 0xb2, idx: 0x0}, + 21: {cur: 0xeb, idx: 0xbc}, + 22: {cur: 0x125, idx: 0xe9}, + 23: {cur: 0xb9, idx: 0x4}, + 24: {cur: 0x67, idx: 0xf2}, + 25: {cur: 0x13, idx: 0xf8}, + 26: {cur: 0x42, idx: 0xfc}, + 27: {cur: 0x5d, idx: 0x113}, + 28: {cur: 0xeb, idx: 0xbc}, + 29: {cur: 0x0, idx: 0x11a}, + 30: {cur: 0x2, idx: 0x11e}, + 31: {cur: 0x13, idx: 0xf8}, + 32: {cur: 0x23, idx: 0x130}, + 33: {cur: 0x54, idx: 0x15a}, + 34: {cur: 0x58, idx: 0x164}, + 35: {cur: 0x7e, idx: 0x17b}, + 36: {cur: 0x7f, idx: 0x185}, + 37: {cur: 0x84, idx: 0x190}, + 38: {cur: 0x8e, idx: 0x19a}, + 39: {cur: 0x92, idx: 0x1a8}, + 40: {cur: 0x9d, idx: 0x1b2}, + 41: {cur: 0x9e, idx: 0x1bc}, + 42: {cur: 0xab, idx: 0x1c6}, + 43: {cur: 0xc1, idx: 0x1d0}, + 44: {cur: 0xcd, idx: 0x1da}, + 45: {cur: 0xd5, idx: 0x1e4}, + 46: {cur: 0xd8, idx: 0x1f2}, + 47: {cur: 0xd9, idx: 0x1fc}, + 48: {cur: 0xe9, idx: 0x207}, + 49: {cur: 0xeb, idx: 0xbc}, + 50: {cur: 0xf0, idx: 0x211}, + 51: {cur: 0x11f, idx: 0x223}, + 52: {cur: 0x51, idx: 0x22d}, + 53: {cur: 0x59, idx: 0x231}, + 54: {cur: 0x89, idx: 0x6b}, + 55: {cur: 0xd9, idx: 0x0}, + 56: {cur: 0xe1, idx: 0x235}, + 57: {cur: 0x63, idx: 0x237}, + 58: {cur: 0xe4, idx: 0x3f}, + 59: {cur: 0xf7, idx: 0x23c}, + 60: {cur: 0x85, idx: 0x25}, + 61: {cur: 0xeb, idx: 0xbc}, + 62: {cur: 0xfc, idx: 0x4}, + 63: {cur: 0x16, idx: 0x240}, + 64: {cur: 0xeb, idx: 0xbc}, + 65: {cur: 0x16, idx: 0x240}, + 66: {cur: 0x2e, idx: 0x0}, + 67: {cur: 0x37, idx: 0x258}, + 68: {cur: 0x3a, idx: 0x0}, + 69: {cur: 0x85, idx: 0x25}, + 70: {cur: 0xc0, idx: 0x0}, + 71: {cur: 0xd2, idx: 0xb2}, + 72: {cur: 0xfc, idx: 0x4}, + 73: {cur: 0x127, idx: 0x8a}, + 74: {cur: 0xf7, idx: 0x23c}, + 75: {cur: 0x13, idx: 0x0}, + 76: {cur: 0x21, idx: 0x294}, + 77: {cur: 0x2e, idx: 0x0}, + 78: {cur: 0x3a, idx: 0x0}, + 79: {cur: 0x44, idx: 0x0}, + 80: {cur: 0x63, idx: 0x0}, + 81: {cur: 0x72, idx: 0x0}, + 82: {cur: 0x7c, idx: 0x0}, + 83: {cur: 0x7d, idx: 0x0}, + 84: {cur: 0x85, idx: 0x0}, + 85: {cur: 0x8d, idx: 0x0}, + 86: {cur: 0xb2, idx: 0x0}, + 87: {cur: 0xc0, idx: 0x0}, + 88: {cur: 0xf6, idx: 0x0}, + 89: {cur: 0xfc, idx: 0x29a}, + 90: {cur: 0x105, idx: 0x0}, + 91: {cur: 0x110, idx: 0x0}, + 92: {cur: 0x1b, idx: 0xc}, + 93: {cur: 0xeb, idx: 0xbc}, + 94: {cur: 0x44, idx: 0x25}, + 95: {cur: 0x44, idx: 0x20}, + 96: {cur: 0x13, idx: 0x2a1}, + 97: {cur: 0x2e, idx: 0x0}, + 98: {cur: 0x3a, idx: 0x2a4}, + 99: {cur: 0x44, idx: 0x0}, + 100: {cur: 0x63, idx: 0x2ad}, + 101: {cur: 0x72, idx: 0x2b3}, + 102: {cur: 0x7c, idx: 0x0}, + 103: {cur: 0x85, idx: 0x0}, + 104: {cur: 0x8d, idx: 0x0}, + 105: {cur: 0xc0, idx: 0x2bc}, + 106: {cur: 0xf6, idx: 0x0}, + 107: {cur: 0xfc, idx: 0x2c5}, + 108: {cur: 0x105, idx: 0x0}, + 109: {cur: 0x110, idx: 0x0}, + 110: {cur: 0x13, idx: 0x0}, + 111: {cur: 0x18, idx: 0x9}, + 112: {cur: 0x2e, idx: 0x0}, + 113: {cur: 0x3a, idx: 0x0}, + 114: {cur: 0x44, idx: 0x0}, + 115: {cur: 0x63, idx: 0x0}, + 116: {cur: 0x72, idx: 0x0}, + 117: {cur: 0x75, idx: 0x51}, + 118: {cur: 0x7c, idx: 0x0}, + 119: {cur: 0x85, idx: 0x25}, + 120: {cur: 0xb2, idx: 0x0}, + 121: {cur: 0xc0, idx: 0x0}, + 122: {cur: 0xd1, idx: 0x2ca}, + 123: {cur: 0xeb, idx: 0xbc}, + 124: {cur: 0xfc, idx: 0x0}, + 125: {cur: 0x110, idx: 0x0}, + 126: {cur: 0x117, idx: 0x0}, + 127: {cur: 0x18, idx: 0x2cf}, + 128: {cur: 0x4e, idx: 0x2d4}, + 129: {cur: 0x85, idx: 0x25}, + 130: {cur: 0xc9, idx: 0x2d9}, + 131: {cur: 0xd1, idx: 0x2de}, + 132: {cur: 0xf4, idx: 0x2e6}, + 133: {cur: 0x13, idx: 0xf8}, + 134: {cur: 0x2e, idx: 0x0}, + 135: {cur: 0x3a, idx: 0x0}, + 136: {cur: 0x44, idx: 0x25}, + 137: {cur: 0x5c, idx: 0x37}, + 138: {cur: 0xb2, idx: 0x0}, + 139: {cur: 0xeb, idx: 0xbc}, + 140: {cur: 0xfc, idx: 0x0}, + 141: {cur: 0x110, idx: 0x0}, + 142: {cur: 0x62, idx: 0x2eb}, + 143: {cur: 0x1b, idx: 0xc}, + 144: {cur: 0xeb, idx: 0xbc}, + 145: {cur: 0xd2, idx: 0xb2}, + 146: {cur: 0xfb, idx: 0x2f4}, + 147: {cur: 0xfc, idx: 0x4}, + 148: {cur: 0x7e, idx: 0x17b}, + 149: {cur: 0x13, idx: 0xf8}, + 150: {cur: 0x49, idx: 0x2f8}, + 151: {cur: 0x4e, idx: 0x2c}, + 152: {cur: 0x7c, idx: 0x0}, + 153: {cur: 0x7d, idx: 0x0}, + 154: {cur: 0x105, idx: 0x0}, + 155: {cur: 0x112, idx: 0x2fd}, + 156: {cur: 0xd2, idx: 0xb2}, + 157: {cur: 0x8d, idx: 0x0}, + 158: {cur: 0xeb, idx: 0xbc}, + 159: {cur: 0x13, idx: 0xf8}, + 160: {cur: 0x52, idx: 0x304}, + 161: {cur: 0xeb, idx: 0xbc}, + 162: {cur: 0xfc, idx: 0x4}, + 163: {cur: 0x86, idx: 0x308}, + 164: {cur: 0x12, idx: 0x30c}, + 165: {cur: 0x13, idx: 0xf8}, + 166: {cur: 0x20, idx: 0x310}, + 167: {cur: 0x22, idx: 0x314}, + 168: {cur: 0x50, idx: 0x31d}, + 169: {cur: 0x85, idx: 0x25}, + 170: {cur: 0xeb, idx: 0xbc}, + 171: {cur: 0xfc, idx: 0x4}, + 172: {cur: 0x5e, idx: 0x0}, + 173: {cur: 0x5e, idx: 0x0}, + 174: {cur: 0x99, idx: 0x2eb}, + 175: {cur: 0x13, idx: 0x0}, + 176: {cur: 0x85, idx: 0x25}, + 177: {cur: 0xc9, idx: 0xa6}, + 178: {cur: 0xeb, idx: 0xbc}, + 179: {cur: 0xfc, idx: 0x4}, + 180: {cur: 0x13, idx: 0xf8}, + 181: {cur: 0x33, idx: 0x332}, + 182: {cur: 0x7c, idx: 0x0}, + 183: {cur: 0x8d, idx: 0x336}, + 184: {cur: 0xeb, idx: 0x33c}, + 185: {cur: 0x109, idx: 0x0}, + 186: {cur: 0x86, idx: 0x308}, + 187: {cur: 0x13, idx: 0xf8}, + 188: {cur: 0x67, idx: 0xf2}, + 189: {cur: 0xeb, idx: 0xbc}, + 190: {cur: 0x6d, idx: 0x342}, + 191: {cur: 0xeb, idx: 0xbc}, + 192: {cur: 0xfc, idx: 0x4}, + 193: {cur: 0x85, idx: 0x25}, + 194: {cur: 0xfc, idx: 0x4}, + 195: {cur: 0x85, idx: 0x62}, + 196: {cur: 0xfc, idx: 0xcf}, + 197: {cur: 0x110, idx: 0x4}, + 198: {cur: 0x110, idx: 0x4}, + 199: {cur: 0x13, idx: 0x4}, + 200: {cur: 0x2e, idx: 0x0}, + 201: {cur: 0x3a, idx: 0x0}, + 202: {cur: 0x44, idx: 0x0}, + 203: {cur: 0x5e, idx: 0x0}, + 204: {cur: 0x63, idx: 0x0}, + 205: {cur: 0x72, idx: 0x0}, + 206: {cur: 0x7c, idx: 0x0}, + 207: {cur: 0x7d, idx: 0x0}, + 208: {cur: 0x85, idx: 0x0}, + 209: {cur: 0x8d, idx: 0x0}, + 210: {cur: 0xb2, idx: 0x0}, + 211: {cur: 0xc0, idx: 0x0}, + 212: {cur: 0xd7, idx: 0x7e}, + 213: {cur: 0xf6, idx: 0x0}, + 214: {cur: 0xfc, idx: 0x0}, + 215: {cur: 0x105, idx: 0x0}, + 216: {cur: 0x109, idx: 0x0}, + 217: {cur: 0x110, idx: 0x0}, + 218: {cur: 0x115, idx: 0x0}, + 219: {cur: 0x117, idx: 0x355}, + 220: {cur: 0x1a, idx: 0x4}, + 221: {cur: 0x24, idx: 0x359}, + 222: {cur: 0x25, idx: 0x4}, + 223: {cur: 0x32, idx: 0x4}, + 224: {cur: 0x35, idx: 0x16}, + 225: {cur: 0x39, idx: 0x4}, + 226: {cur: 0x3a, idx: 0x4}, + 227: {cur: 0x13, idx: 0x4}, + 228: {cur: 0xc0, idx: 0x4}, + 229: {cur: 0x13, idx: 0x4}, + 230: {cur: 0x52, idx: 0x304}, + 231: {cur: 0x110, idx: 0x4}, + 232: {cur: 0x59, idx: 0x231}, + 233: {cur: 0x60, idx: 0x4}, + 234: {cur: 0x61, idx: 0x3f}, + 235: {cur: 0x63, idx: 0x237}, + 236: {cur: 0x110, idx: 0x4}, + 237: {cur: 0x67, idx: 0xf2}, + 238: {cur: 0x63, idx: 0x237}, + 239: {cur: 0x68, idx: 0x3f}, + 240: {cur: 0x69, idx: 0x35d}, + 241: {cur: 0x71, idx: 0x4}, + 242: {cur: 0x83, idx: 0x4}, + 243: {cur: 0x86, idx: 0x308}, + 244: {cur: 0x13, idx: 0x4}, + 245: {cur: 0x110, idx: 0x4}, + 246: {cur: 0x8f, idx: 0x4}, + 247: {cur: 0x110, idx: 0x4}, + 248: {cur: 0x94, idx: 0x4}, + 249: {cur: 0x125, idx: 0xe9}, + 250: {cur: 0xa3, idx: 0x87}, + 251: {cur: 0xaa, idx: 0x35f}, + 252: {cur: 0x110, idx: 0x4}, + 253: {cur: 0x63, idx: 0x237}, + 254: {cur: 0xae, idx: 0x7e}, + 255: {cur: 0xb1, idx: 0x364}, + 256: {cur: 0xb5, idx: 0x94}, + 257: {cur: 0xb9, idx: 0x4}, + 258: {cur: 0x13, idx: 0x4}, + 259: {cur: 0xba, idx: 0x97}, + 260: {cur: 0x13, idx: 0x4}, + 261: {cur: 0xc0, idx: 0x4}, + 262: {cur: 0xc0, idx: 0x4}, + 263: {cur: 0xc6, idx: 0x8a}, + 264: {cur: 0xc7, idx: 0xa2}, + 265: {cur: 0xc8, idx: 0x7e}, + 266: {cur: 0xc0, idx: 0x4}, + 267: {cur: 0xd4, idx: 0xb6}, + 268: {cur: 0xd6, idx: 0x4}, + 269: {cur: 0xd7, idx: 0x367}, + 270: {cur: 0xdb, idx: 0x30}, + 271: {cur: 0xdc, idx: 0x4}, + 272: {cur: 0x63, idx: 0x237}, + 273: {cur: 0xdd, idx: 0x3f}, + 274: {cur: 0xe0, idx: 0x36a}, + 275: {cur: 0x63, idx: 0x237}, + 276: {cur: 0xe4, idx: 0x3f}, + 277: {cur: 0x8, idx: 0x36d}, + 278: {cur: 0xea, idx: 0x372}, + 279: {cur: 0xc0, idx: 0x4}, + 280: {cur: 0xf1, idx: 0xc0}, + 281: {cur: 0xf5, idx: 0x4}, + 282: {cur: 0x13, idx: 0x4}, + 283: {cur: 0xf7, idx: 0x23c}, + 284: {cur: 0xfb, idx: 0x2f4}, + 285: {cur: 0x110, idx: 0x4}, + 286: {cur: 0x107, idx: 0x374}, + 287: {cur: 0x108, idx: 0x377}, + 288: {cur: 0x125, idx: 0xe9}, + 289: {cur: 0x127, idx: 0x8a}, + 290: {cur: 0x13, idx: 0x0}, + 291: {cur: 0x2e, idx: 0x0}, + 292: {cur: 0x44, idx: 0x0}, + 293: {cur: 0x5c, idx: 0x37}, + 294: {cur: 0x63, idx: 0x0}, + 295: {cur: 0x72, idx: 0x0}, + 296: {cur: 0x7c, idx: 0x0}, + 297: {cur: 0x7d, idx: 0x0}, + 298: {cur: 0x85, idx: 0x0}, + 299: {cur: 0x8d, idx: 0x0}, + 300: {cur: 0xb2, idx: 0x0}, + 301: {cur: 0xc0, idx: 0x0}, + 302: {cur: 0xeb, idx: 0xbc}, + 303: {cur: 0xf6, idx: 0x0}, + 304: {cur: 0x109, idx: 0x0}, + 305: {cur: 0x110, idx: 0x0}, + 306: {cur: 0x115, idx: 0x0}, + 307: {cur: 0x3a, idx: 0x0}, + 308: {cur: 0x5e, idx: 0x0}, + 309: {cur: 0xeb, idx: 0x0}, + 310: {cur: 0xfc, idx: 0x0}, + 311: {cur: 0x105, idx: 0x0}, + 312: {cur: 0x11, idx: 0x4}, + 313: {cur: 0xfc, idx: 0xcf}, + 314: {cur: 0x27, idx: 0x10}, + 315: {cur: 0x2e, idx: 0x13}, + 316: {cur: 0x39, idx: 0x4}, + 317: {cur: 0x41, idx: 0x4}, + 318: {cur: 0xfc, idx: 0xcf}, + 319: {cur: 0x45, idx: 0x4}, + 320: {cur: 0xfc, idx: 0xcf}, + 321: {cur: 0x47, idx: 0x28}, + 322: {cur: 0x4b, idx: 0x4}, + 323: {cur: 0xfc, idx: 0xcf}, + 324: {cur: 0x53, idx: 0x264}, + 325: {cur: 0xfc, idx: 0xcf}, + 326: {cur: 0xfc, idx: 0x4}, + 327: {cur: 0x109, idx: 0xd7}, + 328: {cur: 0x6e, idx: 0x49}, + 329: {cur: 0x73, idx: 0x4f}, + 330: {cur: 0xb2, idx: 0x4}, + 331: {cur: 0xbc, idx: 0x9b}, + 332: {cur: 0xc2, idx: 0x387}, + 333: {cur: 0xc4, idx: 0x38b}, + 334: {cur: 0xc7, idx: 0xa2}, + 335: {cur: 0xfc, idx: 0x4}, + 336: {cur: 0xcc, idx: 0x38e}, + 337: {cur: 0xfc, idx: 0x4}, + 338: {cur: 0x85, idx: 0x25}, + 339: {cur: 0xfc, idx: 0x4}, + 340: {cur: 0xfc, idx: 0xcf}, + 341: {cur: 0x101, idx: 0x4}, + 342: {cur: 0x104, idx: 0x392}, + 343: {cur: 0x13, idx: 0xf8}, + 344: {cur: 0x57, idx: 0x30}, + 345: {cur: 0x85, idx: 0x25}, + 346: {cur: 0xeb, idx: 0xbc}, + 347: {cur: 0xfc, idx: 0x4}, + 348: {cur: 0x5c, idx: 0x37}, + 349: {cur: 0xeb, idx: 0xbc}, + 350: {cur: 0x4, idx: 0x396}, + 351: {cur: 0x3a, idx: 0x2a4}, + 352: {cur: 0x44, idx: 0x399}, + 353: {cur: 0x72, idx: 0x39e}, + 354: {cur: 0x7f, idx: 0x3a2}, + 355: {cur: 0x85, idx: 0x25}, + 356: {cur: 0xb2, idx: 0x3ab}, + 357: {cur: 0xc0, idx: 0x3af}, + 358: {cur: 0xeb, idx: 0xbc}, + 359: {cur: 0xfc, idx: 0x4}, + 360: {cur: 0x110, idx: 0x3b3}, + 361: {cur: 0x6a, idx: 0x46}, + 362: {cur: 0xab, idx: 0x3b7}, + 363: {cur: 0x13, idx: 0x0}, + 364: {cur: 0x2e, idx: 0x0}, + 365: {cur: 0x3a, idx: 0x0}, + 366: {cur: 0x44, idx: 0x0}, + 367: {cur: 0x5f, idx: 0x3ba}, + 368: {cur: 0x72, idx: 0x0}, + 369: {cur: 0x7c, idx: 0x0}, + 370: {cur: 0x7d, idx: 0x0}, + 371: {cur: 0x85, idx: 0x25}, + 372: {cur: 0x8d, idx: 0x0}, + 373: {cur: 0xb2, idx: 0x0}, + 374: {cur: 0xc0, idx: 0x0}, + 375: {cur: 0xf6, idx: 0x0}, + 376: {cur: 0xfc, idx: 0x4}, + 377: {cur: 0x105, idx: 0x0}, + 378: {cur: 0x110, idx: 0x0}, + 379: {cur: 0x117, idx: 0x0}, + 380: {cur: 0x85, idx: 0x25}, + 381: {cur: 0xc7, idx: 0xa2}, + 382: {cur: 0xeb, idx: 0xbc}, + 383: {cur: 0xfc, idx: 0x4}, + 384: {cur: 0x52, idx: 0x30}, + 385: {cur: 0x52, idx: 0x304}, + 386: {cur: 0x11, idx: 0x3bd}, + 387: {cur: 0x13, idx: 0x3c1}, + 388: {cur: 0x1d, idx: 0x3c5}, + 389: {cur: 0x25, idx: 0x3c8}, + 390: {cur: 0x26, idx: 0x3cc}, + 391: {cur: 0x32, idx: 0x3d0}, + 392: {cur: 0x39, idx: 0x3d4}, + 393: {cur: 0x3a, idx: 0x2a4}, + 394: {cur: 0x41, idx: 0x3d8}, + 395: {cur: 0x44, idx: 0x0}, + 396: {cur: 0x45, idx: 0x3dc}, + 397: {cur: 0x4d, idx: 0x3e0}, + 398: {cur: 0x60, idx: 0x3e9}, + 399: {cur: 0x61, idx: 0x3ed}, + 400: {cur: 0x62, idx: 0x2eb}, + 401: {cur: 0x63, idx: 0x3f2}, + 402: {cur: 0x68, idx: 0x3f7}, + 403: {cur: 0x72, idx: 0x0}, + 404: {cur: 0x79, idx: 0x3fc}, + 405: {cur: 0x7a, idx: 0x401}, + 406: {cur: 0x82, idx: 0x406}, + 407: {cur: 0x85, idx: 0x0}, + 408: {cur: 0x92, idx: 0x40c}, + 409: {cur: 0xad, idx: 0x411}, + 410: {cur: 0xb2, idx: 0x3ab}, + 411: {cur: 0xb9, idx: 0x416}, + 412: {cur: 0xc0, idx: 0x3af}, + 413: {cur: 0xce, idx: 0x41d}, + 414: {cur: 0xd6, idx: 0x424}, + 415: {cur: 0xdc, idx: 0x428}, + 416: {cur: 0xe2, idx: 0x42c}, + 417: {cur: 0xf5, idx: 0x430}, + 418: {cur: 0xf6, idx: 0x0}, + 419: {cur: 0xfc, idx: 0x434}, + 420: {cur: 0x101, idx: 0x438}, + 421: {cur: 0x108, idx: 0x377}, + 422: {cur: 0x110, idx: 0x0}, + 423: {cur: 0x117, idx: 0x43c}, + 424: {cur: 0x24, idx: 0x359}, + 425: {cur: 0x11, idx: 0x0}, + 426: {cur: 0x13, idx: 0x444}, + 427: {cur: 0x25, idx: 0x0}, + 428: {cur: 0x26, idx: 0x0}, + 429: {cur: 0x32, idx: 0x0}, + 430: {cur: 0x39, idx: 0x0}, + 431: {cur: 0x3a, idx: 0x4}, + 432: {cur: 0x41, idx: 0x0}, + 433: {cur: 0x44, idx: 0x20}, + 434: {cur: 0x45, idx: 0x0}, + 435: {cur: 0x60, idx: 0x0}, + 436: {cur: 0x61, idx: 0x0}, + 437: {cur: 0x63, idx: 0x3f}, + 438: {cur: 0x68, idx: 0x0}, + 439: {cur: 0x72, idx: 0x44a}, + 440: {cur: 0x7c, idx: 0x0}, + 441: {cur: 0x7d, idx: 0x0}, + 442: {cur: 0x85, idx: 0x25}, + 443: {cur: 0x8d, idx: 0x0}, + 444: {cur: 0x92, idx: 0x0}, + 445: {cur: 0xb2, idx: 0x0}, + 446: {cur: 0xb9, idx: 0x0}, + 447: {cur: 0xc0, idx: 0x450}, + 448: {cur: 0xd6, idx: 0x0}, + 449: {cur: 0xdc, idx: 0x456}, + 450: {cur: 0xe2, idx: 0x0}, + 451: {cur: 0xf5, idx: 0x0}, + 452: {cur: 0xfc, idx: 0x45c}, + 453: {cur: 0x101, idx: 0x0}, + 454: {cur: 0x105, idx: 0x0}, + 455: {cur: 0x109, idx: 0x0}, + 456: {cur: 0x115, idx: 0x0}, + 457: {cur: 0x117, idx: 0x0}, + 458: {cur: 0x3b, idx: 0x32a}, + 459: {cur: 0x51, idx: 0x22d}, + 460: {cur: 0x54, idx: 0x462}, + 461: {cur: 0x6a, idx: 0x46}, + 462: {cur: 0x76, idx: 0x465}, + 463: {cur: 0x89, idx: 0x6b}, + 464: {cur: 0x62, idx: 0x0}, + 465: {cur: 0x99, idx: 0x2eb}, + 466: {cur: 0xa3, idx: 0x87}, + 467: {cur: 0xab, idx: 0x3b7}, + 468: {cur: 0xae, idx: 0x7e}, + 469: {cur: 0xd4, idx: 0xb6}, + 470: {cur: 0xd7, idx: 0x367}, + 471: {cur: 0xe9, idx: 0x467}, + 472: {cur: 0xf0, idx: 0x46a}, + 473: {cur: 0x107, idx: 0x374}, + 474: {cur: 0x13, idx: 0xf8}, + 475: {cur: 0x3a, idx: 0x9b}, + 476: {cur: 0x60, idx: 0x16e}, + 477: {cur: 0xd6, idx: 0x28a}, + 478: {cur: 0xeb, idx: 0xbc}, + 479: {cur: 0x117, idx: 0x0}, + 480: {cur: 0x85, idx: 0x25}, + 481: {cur: 0xeb, idx: 0xbc}, + 482: {cur: 0xfc, idx: 0x4}, + 483: {cur: 0xeb, idx: 0xbc}, + 484: {cur: 0xfc, idx: 0x4}, + 485: {cur: 0x5c, idx: 0x37}, + 486: {cur: 0xb2, idx: 0x3ab}, + 487: {cur: 0xeb, idx: 0xbc}, + 488: {cur: 0xfc, idx: 0x4}, + 489: {cur: 0x12, idx: 0x30c}, + 490: {cur: 0x85, idx: 0x25}, + 491: {cur: 0xfc, idx: 0x4}, + 492: {cur: 0xeb, idx: 0xbc}, + 493: {cur: 0x86, idx: 0x308}, + 494: {cur: 0xba, idx: 0x97}, + 495: {cur: 0x67, idx: 0xf2}, + 496: {cur: 0xfc, idx: 0x4}, + 497: {cur: 0x44, idx: 0x47c}, + 498: {cur: 0x7a, idx: 0x487}, + 499: {cur: 0x85, idx: 0x25}, + 500: {cur: 0xeb, idx: 0xbc}, + 501: {cur: 0xfc, idx: 0x4}, + 502: {cur: 0xeb, idx: 0xbc}, + 503: {cur: 0xfc, idx: 0x4}, + 504: {cur: 0x13, idx: 0x0}, + 505: {cur: 0x2e, idx: 0x0}, + 506: {cur: 0x3a, idx: 0x0}, + 507: {cur: 0x44, idx: 0x0}, + 508: {cur: 0x5e, idx: 0x0}, + 509: {cur: 0x63, idx: 0x0}, + 510: {cur: 0x72, idx: 0x0}, + 511: {cur: 0x7c, idx: 0x0}, + 512: {cur: 0x7d, idx: 0x0}, + 513: {cur: 0x85, idx: 0x0}, + 514: {cur: 0x8d, idx: 0x0}, + 515: {cur: 0xb2, idx: 0x0}, + 516: {cur: 0xc0, idx: 0x0}, + 517: {cur: 0xf6, idx: 0x0}, + 518: {cur: 0xfc, idx: 0x0}, + 519: {cur: 0x105, idx: 0x0}, + 520: {cur: 0x110, idx: 0x0}, + 521: {cur: 0x117, idx: 0x0}, + 522: {cur: 0x18, idx: 0x9}, + 523: {cur: 0x13, idx: 0x0}, + 524: {cur: 0x85, idx: 0x25}, + 525: {cur: 0xc9, idx: 0xa6}, + 526: {cur: 0xeb, idx: 0xbc}, + 527: {cur: 0xfc, idx: 0x4}, + 528: {cur: 0x13, idx: 0x0}, + 529: {cur: 0x2e, idx: 0x0}, + 530: {cur: 0x3a, idx: 0x0}, + 531: {cur: 0x44, idx: 0x0}, + 532: {cur: 0x5e, idx: 0x0}, + 533: {cur: 0x63, idx: 0x0}, + 534: {cur: 0x72, idx: 0x0}, + 535: {cur: 0x77, idx: 0x54}, + 536: {cur: 0x7c, idx: 0x0}, + 537: {cur: 0x7d, idx: 0x0}, + 538: {cur: 0x85, idx: 0x25}, + 539: {cur: 0x8d, idx: 0x0}, + 540: {cur: 0xb2, idx: 0x0}, + 541: {cur: 0xc0, idx: 0x0}, + 542: {cur: 0xf6, idx: 0x0}, + 543: {cur: 0xfc, idx: 0x0}, + 544: {cur: 0x105, idx: 0x0}, + 545: {cur: 0x110, idx: 0x0}, + 546: {cur: 0x7, idx: 0x498}, + 547: {cur: 0xeb, idx: 0xbc}, + 548: {cur: 0xfc, idx: 0x4}, + 549: {cur: 0x13, idx: 0xf8}, + 550: {cur: 0x78, idx: 0x57}, + 551: {cur: 0x7d, idx: 0x7e}, + 552: {cur: 0xeb, idx: 0xbc}, + 553: {cur: 0xba, idx: 0x97}, + 554: {cur: 0x44, idx: 0x25}, + 555: {cur: 0x13, idx: 0x0}, + 556: {cur: 0x2e, idx: 0x0}, + 557: {cur: 0x3a, idx: 0x0}, + 558: {cur: 0x5e, idx: 0x0}, + 559: {cur: 0x63, idx: 0x0}, + 560: {cur: 0x7d, idx: 0x0}, + 561: {cur: 0x8d, idx: 0x0}, + 562: {cur: 0xb2, idx: 0x0}, + 563: {cur: 0xc0, idx: 0x0}, + 564: {cur: 0xf6, idx: 0x0}, + 565: {cur: 0xfc, idx: 0x0}, + 566: {cur: 0x105, idx: 0x0}, + 567: {cur: 0x2e, idx: 0x0}, + 568: {cur: 0x72, idx: 0x0}, + 569: {cur: 0x85, idx: 0x0}, + 570: {cur: 0x8d, idx: 0x0}, + 571: {cur: 0xb2, idx: 0x0}, + 572: {cur: 0xeb, idx: 0xbc}, + 573: {cur: 0xf6, idx: 0x0}, + 574: {cur: 0xfc, idx: 0x0}, + 575: {cur: 0x44, idx: 0x49f}, + 576: {cur: 0x85, idx: 0x4a3}, + 577: {cur: 0xfc, idx: 0x4}, + 578: {cur: 0xf7, idx: 0x23c}, + 579: {cur: 0x13, idx: 0x0}, + 580: {cur: 0x44, idx: 0x0}, + 581: {cur: 0x65, idx: 0x42}, + 582: {cur: 0x72, idx: 0x0}, + 583: {cur: 0x7c, idx: 0x0}, + 584: {cur: 0x7d, idx: 0x0}, + 585: {cur: 0x85, idx: 0x0}, + 586: {cur: 0x8d, idx: 0x0}, + 587: {cur: 0xc0, idx: 0x0}, + 588: {cur: 0x105, idx: 0x0}, + 589: {cur: 0x54, idx: 0x462}, + 590: {cur: 0x86, idx: 0x308}, + 591: {cur: 0xf7, idx: 0x23c}, + 592: {cur: 0x13, idx: 0xf8}, + 593: {cur: 0x4c, idx: 0x4ae}, + 594: {cur: 0xeb, idx: 0xbc}, + 595: {cur: 0x86, idx: 0x308}, + 596: {cur: 0x90, idx: 0x72}, + 597: {cur: 0xd2, idx: 0xb2}, + 598: {cur: 0xeb, idx: 0xbc}, + 599: {cur: 0xfc, idx: 0x4}, + 600: {cur: 0x52, idx: 0x304}, + 601: {cur: 0x86, idx: 0x308}, + 602: {cur: 0x88, idx: 0x67}, + 603: {cur: 0xeb, idx: 0xbc}, + 604: {cur: 0xfc, idx: 0x4}, + 605: {cur: 0xeb, idx: 0xbc}, + 606: {cur: 0xfc, idx: 0x4}, + 607: {cur: 0x13, idx: 0xf8}, + 608: {cur: 0xf7, idx: 0x23c}, + 609: {cur: 0x13, idx: 0x0}, + 610: {cur: 0x2e, idx: 0x0}, + 611: {cur: 0x3a, idx: 0x0}, + 612: {cur: 0x63, idx: 0x0}, + 613: {cur: 0x72, idx: 0x0}, + 614: {cur: 0x7c, idx: 0x0}, + 615: {cur: 0x7d, idx: 0x0}, + 616: {cur: 0x87, idx: 0x4bf}, + 617: {cur: 0x8d, idx: 0x0}, + 618: {cur: 0xb2, idx: 0x0}, + 619: {cur: 0xc0, idx: 0x0}, + 620: {cur: 0xeb, idx: 0xbc}, + 621: {cur: 0xf6, idx: 0x0}, + 622: {cur: 0xfc, idx: 0x0}, + 623: {cur: 0x110, idx: 0x0}, + 624: {cur: 0xf7, idx: 0x23c}, + 625: {cur: 0x12, idx: 0x30c}, + 626: {cur: 0x13, idx: 0xf8}, + 627: {cur: 0x85, idx: 0x25}, + 628: {cur: 0xeb, idx: 0xbc}, + 629: {cur: 0xfc, idx: 0x4}, + 630: {cur: 0xfb, idx: 0x2f4}, + 631: {cur: 0xfc, idx: 0x4}, + 632: {cur: 0x3b, idx: 0x32a}, + 633: {cur: 0x9, idx: 0x1}, + 634: {cur: 0x91, idx: 0x76}, + 635: {cur: 0xeb, idx: 0xbc}, + 636: {cur: 0x7e, idx: 0x17b}, + 637: {cur: 0x13, idx: 0x0}, + 638: {cur: 0x2e, idx: 0x0}, + 639: {cur: 0x3a, idx: 0x0}, + 640: {cur: 0x44, idx: 0x0}, + 641: {cur: 0x63, idx: 0x0}, + 642: {cur: 0x72, idx: 0x0}, + 643: {cur: 0x7c, idx: 0x0}, + 644: {cur: 0x7d, idx: 0x0}, + 645: {cur: 0x85, idx: 0x0}, + 646: {cur: 0x8d, idx: 0x0}, + 647: {cur: 0xb2, idx: 0x0}, + 648: {cur: 0xc0, idx: 0x0}, + 649: {cur: 0xf6, idx: 0x0}, + 650: {cur: 0xfc, idx: 0x0}, + 651: {cur: 0x105, idx: 0x0}, + 652: {cur: 0x109, idx: 0x0}, + 653: {cur: 0x110, idx: 0x0}, + 654: {cur: 0x115, idx: 0x0}, + 655: {cur: 0x117, idx: 0x0}, + 656: {cur: 0x3b, idx: 0x32a}, + 657: {cur: 0x86, idx: 0x308}, + 658: {cur: 0x86, idx: 0x308}, + 659: {cur: 0x13, idx: 0xf8}, + 660: {cur: 0x85, idx: 0x25}, + 661: {cur: 0x9b, idx: 0x84}, + 662: {cur: 0xeb, idx: 0xbc}, + 663: {cur: 0xfc, idx: 0x4}, + 664: {cur: 0x86, idx: 0x308}, + 665: {cur: 0xf7, idx: 0x23c}, + 666: {cur: 0x86, idx: 0x308}, + 667: {cur: 0xae, idx: 0x7e}, + 668: {cur: 0xa3, idx: 0x87}, + 669: {cur: 0xb8, idx: 0x4cc}, + 670: {cur: 0x13, idx: 0x0}, + 671: {cur: 0x44, idx: 0x0}, + 672: {cur: 0x63, idx: 0x0}, + 673: {cur: 0x72, idx: 0x0}, + 674: {cur: 0x7c, idx: 0x0}, + 675: {cur: 0x7d, idx: 0x0}, + 676: {cur: 0x85, idx: 0x0}, + 677: {cur: 0x8d, idx: 0x0}, + 678: {cur: 0xa5, idx: 0x4d0}, + 679: {cur: 0xc0, idx: 0x0}, + 680: {cur: 0xf6, idx: 0x0}, + 681: {cur: 0x105, idx: 0x0}, + 682: {cur: 0x85, idx: 0x25}, + 683: {cur: 0xeb, idx: 0xbc}, + 684: {cur: 0xfc, idx: 0x4}, + 685: {cur: 0xa9, idx: 0x8c}, + 686: {cur: 0xeb, idx: 0xbc}, + 687: {cur: 0xfc, idx: 0x4}, + 688: {cur: 0xeb, idx: 0xbc}, + 689: {cur: 0xfc, idx: 0x4}, + 690: {cur: 0x3a, idx: 0x0}, + 691: {cur: 0xb2, idx: 0x0}, + 692: {cur: 0xb5, idx: 0x94}, + 693: {cur: 0xfc, idx: 0x0}, + 694: {cur: 0x26, idx: 0x4}, + 695: {cur: 0xdc, idx: 0x4}, + 696: {cur: 0x8, idx: 0x4dc}, + 697: {cur: 0x14, idx: 0x4e0}, + 698: {cur: 0x76, idx: 0x465}, + 699: {cur: 0xa8, idx: 0x8a}, + 700: {cur: 0xc2, idx: 0x387}, + 701: {cur: 0xeb, idx: 0xbc}, + 702: {cur: 0xf5, idx: 0x21b}, + 703: {cur: 0xfc, idx: 0x4}, + 704: {cur: 0xb9, idx: 0x4}, + 705: {cur: 0x13, idx: 0x0}, + 706: {cur: 0x2e, idx: 0x0}, + 707: {cur: 0x3a, idx: 0x0}, + 708: {cur: 0x44, idx: 0x0}, + 709: {cur: 0x72, idx: 0x0}, + 710: {cur: 0x7c, idx: 0x0}, + 711: {cur: 0x7d, idx: 0x0}, + 712: {cur: 0x85, idx: 0x0}, + 713: {cur: 0x8d, idx: 0x0}, + 714: {cur: 0xb2, idx: 0x0}, + 715: {cur: 0xbe, idx: 0x30}, + 716: {cur: 0xc0, idx: 0x0}, + 717: {cur: 0xf6, idx: 0x0}, + 718: {cur: 0xfc, idx: 0x0}, + 719: {cur: 0x105, idx: 0x0}, + 720: {cur: 0x109, idx: 0x0}, + 721: {cur: 0x110, idx: 0x0}, + 722: {cur: 0x117, idx: 0x0}, + 723: {cur: 0xbf, idx: 0x4e4}, + 724: {cur: 0xeb, idx: 0xbc}, + 725: {cur: 0x13, idx: 0xf8}, + 726: {cur: 0x3a, idx: 0x9b}, + 727: {cur: 0x60, idx: 0x16e}, + 728: {cur: 0xd6, idx: 0x28a}, + 729: {cur: 0xeb, idx: 0xbc}, + 730: {cur: 0x117, idx: 0x0}, + 731: {cur: 0x14, idx: 0x4f8}, + 732: {cur: 0xfc, idx: 0x4}, + 733: {cur: 0x8, idx: 0x36d}, + 734: {cur: 0xe2, idx: 0x4}, + 735: {cur: 0x8, idx: 0x36d}, + 736: {cur: 0x13, idx: 0x0}, + 737: {cur: 0x2e, idx: 0x0}, + 738: {cur: 0x3a, idx: 0x0}, + 739: {cur: 0x44, idx: 0x0}, + 740: {cur: 0x63, idx: 0x0}, + 741: {cur: 0x72, idx: 0x0}, + 742: {cur: 0x7c, idx: 0x0}, + 743: {cur: 0x7d, idx: 0x0}, + 744: {cur: 0x85, idx: 0x0}, + 745: {cur: 0x8d, idx: 0x0}, + 746: {cur: 0xb2, idx: 0x0}, + 747: {cur: 0xbe, idx: 0x30}, + 748: {cur: 0xc0, idx: 0x0}, + 749: {cur: 0xf6, idx: 0x0}, + 750: {cur: 0xfc, idx: 0x0}, + 751: {cur: 0x105, idx: 0x0}, + 752: {cur: 0x109, idx: 0x0}, + 753: {cur: 0x110, idx: 0x0}, + 754: {cur: 0x117, idx: 0x0}, + 755: {cur: 0x63, idx: 0x237}, + 756: {cur: 0xe4, idx: 0x3f}, + 757: {cur: 0xfb, idx: 0x2f4}, + 758: {cur: 0x5d, idx: 0x258}, + 759: {cur: 0x86, idx: 0x308}, + 760: {cur: 0x85, idx: 0x25}, + 761: {cur: 0xfc, idx: 0x4}, + 762: {cur: 0x65, idx: 0x42}, + 763: {cur: 0xfc, idx: 0x4}, + 764: {cur: 0x65, idx: 0x0}, + 765: {cur: 0xd2, idx: 0xb2}, + 766: {cur: 0xeb, idx: 0xbc}, + 767: {cur: 0xc8, idx: 0x4fd}, + 768: {cur: 0x13, idx: 0x0}, + 769: {cur: 0x3a, idx: 0x0}, + 770: {cur: 0x44, idx: 0x0}, + 771: {cur: 0x63, idx: 0x0}, + 772: {cur: 0x72, idx: 0x0}, + 773: {cur: 0x7c, idx: 0x0}, + 774: {cur: 0x7d, idx: 0x0}, + 775: {cur: 0x85, idx: 0x0}, + 776: {cur: 0x8d, idx: 0x0}, + 777: {cur: 0xb2, idx: 0x0}, + 778: {cur: 0xc0, idx: 0x0}, + 779: {cur: 0xc9, idx: 0xa6}, + 780: {cur: 0xf6, idx: 0x0}, + 781: {cur: 0xfc, idx: 0x0}, + 782: {cur: 0x105, idx: 0x0}, + 783: {cur: 0x4, idx: 0x396}, + 784: {cur: 0x13, idx: 0xf8}, + 785: {cur: 0xcb, idx: 0x504}, + 786: {cur: 0xeb, idx: 0xbc}, + 787: {cur: 0x9, idx: 0x1}, + 788: {cur: 0x4c, idx: 0x4ae}, + 789: {cur: 0xcb, idx: 0x509}, + 790: {cur: 0x99, idx: 0x2eb}, + 791: {cur: 0xaa, idx: 0x35f}, + 792: {cur: 0xb8, idx: 0x4cc}, + 793: {cur: 0xcb, idx: 0x4ae}, + 794: {cur: 0xe5, idx: 0xb9}, + 795: {cur: 0xc4, idx: 0x38b}, + 796: {cur: 0x27, idx: 0x10}, + 797: {cur: 0xc4, idx: 0x0}, + 798: {cur: 0xc4, idx: 0x0}, + 799: {cur: 0xfc, idx: 0x4}, + 800: {cur: 0x24, idx: 0x359}, + 801: {cur: 0x13, idx: 0x0}, + 802: {cur: 0x2e, idx: 0x0}, + 803: {cur: 0x3a, idx: 0x0}, + 804: {cur: 0x44, idx: 0x0}, + 805: {cur: 0x5e, idx: 0x0}, + 806: {cur: 0x63, idx: 0x0}, + 807: {cur: 0x72, idx: 0x0}, + 808: {cur: 0x7c, idx: 0x0}, + 809: {cur: 0x7d, idx: 0x0}, + 810: {cur: 0x85, idx: 0x0}, + 811: {cur: 0x8d, idx: 0x0}, + 812: {cur: 0xb2, idx: 0x0}, + 813: {cur: 0xc0, idx: 0x0}, + 814: {cur: 0xf6, idx: 0x0}, + 815: {cur: 0xfc, idx: 0x0}, + 816: {cur: 0x105, idx: 0x0}, + 817: {cur: 0x110, idx: 0x0}, + 818: {cur: 0xa2, idx: 0x4f}, + 819: {cur: 0xf7, idx: 0x23c}, + 820: {cur: 0x0, idx: 0x510}, + 821: {cur: 0x85, idx: 0x25}, + 822: {cur: 0xd2, idx: 0xb2}, + 823: {cur: 0xd3, idx: 0x18}, + 824: {cur: 0xeb, idx: 0xbc}, + 825: {cur: 0xef, idx: 0x519}, + 826: {cur: 0xf8, idx: 0xcb}, + 827: {cur: 0xfc, idx: 0x4}, + 828: {cur: 0x37, idx: 0x258}, + 829: {cur: 0xd3, idx: 0x0}, + 830: {cur: 0x87, idx: 0x4bf}, + 831: {cur: 0x90, idx: 0x72}, + 832: {cur: 0xa2, idx: 0x4f}, + 833: {cur: 0xd4, idx: 0xb6}, + 834: {cur: 0xf7, idx: 0x23c}, + 835: {cur: 0xd2, idx: 0xb2}, + 836: {cur: 0x86, idx: 0x308}, + 837: {cur: 0xf7, idx: 0x23c}, + 838: {cur: 0xc8, idx: 0x7e}, + 839: {cur: 0x52, idx: 0x520}, + 840: {cur: 0xbe, idx: 0x30}, + 841: {cur: 0xdb, idx: 0x524}, + 842: {cur: 0xeb, idx: 0xbc}, + 843: {cur: 0xbe, idx: 0x528}, + 844: {cur: 0xdb, idx: 0x30}, + 845: {cur: 0xb8, idx: 0x4cc}, + 846: {cur: 0x93, idx: 0x52c}, + 847: {cur: 0xeb, idx: 0xbc}, + 848: {cur: 0x115, idx: 0x534}, + 849: {cur: 0x13, idx: 0x0}, + 850: {cur: 0x2e, idx: 0x0}, + 851: {cur: 0x3a, idx: 0x0}, + 852: {cur: 0x44, idx: 0x0}, + 853: {cur: 0x63, idx: 0x0}, + 854: {cur: 0x72, idx: 0x0}, + 855: {cur: 0x7c, idx: 0x544}, + 856: {cur: 0x7d, idx: 0x0}, + 857: {cur: 0x85, idx: 0x0}, + 858: {cur: 0x8d, idx: 0x0}, + 859: {cur: 0xc0, idx: 0x0}, + 860: {cur: 0xf6, idx: 0x0}, + 861: {cur: 0xfc, idx: 0x0}, + 862: {cur: 0x105, idx: 0x0}, + 863: {cur: 0x13, idx: 0x0}, + 864: {cur: 0x2e, idx: 0x0}, + 865: {cur: 0x3a, idx: 0x0}, + 866: {cur: 0x63, idx: 0x0}, + 867: {cur: 0x85, idx: 0x25}, + 868: {cur: 0xb2, idx: 0x0}, + 869: {cur: 0xc0, idx: 0x0}, + 870: {cur: 0xf6, idx: 0x0}, + 871: {cur: 0xfc, idx: 0x4}, + 872: {cur: 0x110, idx: 0x0}, + 873: {cur: 0xe1, idx: 0x235}, + 874: {cur: 0x51, idx: 0x22d}, + 875: {cur: 0x5d, idx: 0x258}, + 876: {cur: 0x86, idx: 0x308}, + 877: {cur: 0x6, idx: 0x548}, + 878: {cur: 0xeb, idx: 0xbc}, + 879: {cur: 0xa5, idx: 0x54e}, + 880: {cur: 0x13, idx: 0x0}, + 881: {cur: 0x18, idx: 0x2cf}, + 882: {cur: 0x85, idx: 0x25}, + 883: {cur: 0x8d, idx: 0x0}, + 884: {cur: 0xc0, idx: 0x0}, + 885: {cur: 0x105, idx: 0x0}, + 886: {cur: 0x13, idx: 0x0}, + 887: {cur: 0x18, idx: 0x9}, + 888: {cur: 0x85, idx: 0x25}, + 889: {cur: 0x8d, idx: 0x0}, + 890: {cur: 0xc0, idx: 0x0}, + 891: {cur: 0x105, idx: 0x0}, + 892: {cur: 0x13, idx: 0x0}, + 893: {cur: 0x1a, idx: 0x24c}, + 894: {cur: 0x25, idx: 0x13a}, + 895: {cur: 0x2e, idx: 0x555}, + 896: {cur: 0x32, idx: 0x142}, + 897: {cur: 0x39, idx: 0x146}, + 898: {cur: 0x44, idx: 0x0}, + 899: {cur: 0x52, idx: 0x520}, + 900: {cur: 0x53, idx: 0x264}, + 901: {cur: 0x57, idx: 0x559}, + 902: {cur: 0x58, idx: 0x55d}, + 903: {cur: 0x63, idx: 0x0}, + 904: {cur: 0x72, idx: 0x0}, + 905: {cur: 0x79, idx: 0x562}, + 906: {cur: 0x7d, idx: 0x0}, + 907: {cur: 0x81, idx: 0x567}, + 908: {cur: 0x83, idx: 0x18c}, + 909: {cur: 0x85, idx: 0x0}, + 910: {cur: 0x8d, idx: 0x0}, + 911: {cur: 0xbe, idx: 0x528}, + 912: {cur: 0xc0, idx: 0x0}, + 913: {cur: 0xdb, idx: 0x30}, + 914: {cur: 0xf6, idx: 0x0}, + 915: {cur: 0x105, idx: 0x0}, + 916: {cur: 0x86, idx: 0x308}, + 917: {cur: 0xeb, idx: 0xbc}, + 918: {cur: 0xf7, idx: 0x23c}, + 919: {cur: 0x3b, idx: 0x32a}, + 920: {cur: 0xfb, idx: 0x2f4}, + 921: {cur: 0x85, idx: 0x25}, + 922: {cur: 0xeb, idx: 0xbc}, + 923: {cur: 0xfc, idx: 0x4}, + 924: {cur: 0x93, idx: 0x56b}, + 925: {cur: 0xb5, idx: 0x94}, + 926: {cur: 0xdc, idx: 0x28e}, + 927: {cur: 0xb5, idx: 0x94}, + 928: {cur: 0xdc, idx: 0x4}, + 929: {cur: 0xfc, idx: 0xcf}, + 930: {cur: 0xeb, idx: 0xbc}, + 931: {cur: 0xfc, idx: 0x4}, + 932: {cur: 0xfb, idx: 0x2f4}, + 933: {cur: 0x86, idx: 0x308}, + 934: {cur: 0xed, idx: 0x56f}, + 935: {cur: 0xfc, idx: 0x4}, + 936: {cur: 0x13, idx: 0xf8}, + 937: {cur: 0x85, idx: 0x25}, + 938: {cur: 0x5d, idx: 0x258}, + 939: {cur: 0x59, idx: 0x231}, + 940: {cur: 0x5e, idx: 0x0}, + 941: {cur: 0x63, idx: 0x0}, + 942: {cur: 0x13, idx: 0x577}, + 943: {cur: 0xc0, idx: 0x57c}, + 944: {cur: 0xf1, idx: 0xc0}, + 945: {cur: 0x13, idx: 0xf8}, + 946: {cur: 0x85, idx: 0x25}, + 947: {cur: 0xeb, idx: 0xbc}, + 948: {cur: 0xf4, idx: 0xc3}, + 949: {cur: 0xfc, idx: 0x4}, + 950: {cur: 0xd2, idx: 0xb2}, + 951: {cur: 0xfc, idx: 0x4}, + 952: {cur: 0x44, idx: 0x4a3}, + 953: {cur: 0xfc, idx: 0x4}, + 954: {cur: 0x13, idx: 0x0}, + 955: {cur: 0x2e, idx: 0x0}, + 956: {cur: 0x3a, idx: 0x0}, + 957: {cur: 0x44, idx: 0x0}, + 958: {cur: 0x5e, idx: 0x0}, + 959: {cur: 0x63, idx: 0x0}, + 960: {cur: 0x72, idx: 0x0}, + 961: {cur: 0x7c, idx: 0x0}, + 962: {cur: 0x7d, idx: 0x0}, + 963: {cur: 0x85, idx: 0x25}, + 964: {cur: 0x8d, idx: 0x0}, + 965: {cur: 0xb2, idx: 0x0}, + 966: {cur: 0xc0, idx: 0x0}, + 967: {cur: 0xf6, idx: 0x0}, + 968: {cur: 0xf8, idx: 0xcb}, + 969: {cur: 0xf9, idx: 0x581}, + 970: {cur: 0xfc, idx: 0x0}, + 971: {cur: 0x105, idx: 0x0}, + 972: {cur: 0x110, idx: 0x0}, + 973: {cur: 0xc8, idx: 0x7e}, + 974: {cur: 0xeb, idx: 0xbc}, + 975: {cur: 0xfc, idx: 0x4}, + 976: {cur: 0xc8, idx: 0x0}, + 977: {cur: 0x102, idx: 0x589}, + 978: {cur: 0x4, idx: 0x396}, + 979: {cur: 0xeb, idx: 0xbc}, + 980: {cur: 0x102, idx: 0x58f}, + 981: {cur: 0x94, idx: 0x4}, + 982: {cur: 0x94, idx: 0x4}, + 983: {cur: 0x13, idx: 0xf8}, + 984: {cur: 0xeb, idx: 0xbc}, + 985: {cur: 0xf7, idx: 0x23c}, + 986: {cur: 0x85, idx: 0x25}, + 987: {cur: 0xfc, idx: 0x4}, + 988: {cur: 0xfc, idx: 0x4}, + 989: {cur: 0xfb, idx: 0x2f4}, + 990: {cur: 0xba, idx: 0x97}, + 991: {cur: 0x13, idx: 0xf8}, + 992: {cur: 0x85, idx: 0x25}, + 993: {cur: 0x8d, idx: 0x596}, + 994: {cur: 0x13, idx: 0xf8}, + 995: {cur: 0x44, idx: 0x4a3}, + 996: {cur: 0x8d, idx: 0x596}, + 997: {cur: 0x13, idx: 0xf8}, + 998: {cur: 0x44, idx: 0x4a3}, + 999: {cur: 0x7b, idx: 0x59a}, + 1000: {cur: 0x8d, idx: 0x596}, + 1001: {cur: 0x44, idx: 0x20}, + 1002: {cur: 0x44, idx: 0x20}, + 1003: {cur: 0xaa, idx: 0x35f}, + 1004: {cur: 0x44, idx: 0x20}, + 1005: {cur: 0xdc, idx: 0x4}, + 1006: {cur: 0x13, idx: 0xf8}, + 1007: {cur: 0x85, idx: 0x25}, + 1008: {cur: 0x8d, idx: 0x596}, + 1009: {cur: 0xf6, idx: 0x4}, + 1010: {cur: 0x8d, idx: 0x6e}, + 1011: {cur: 0xf6, idx: 0xc7}, + 1012: {cur: 0xaa, idx: 0x35f}, + 1013: {cur: 0xeb, idx: 0xbc}, + 1014: {cur: 0x125, idx: 0xe9}, +} // Size: 4084 bytes + +var narrowLangIndex = []uint16{ // 776 elements + // Entry 0 - 3F + 0x0000, 0x0062, 0x0064, 0x0064, 0x0064, 0x0064, 0x0064, 0x0064, + 0x0064, 0x0065, 0x0065, 0x0081, 0x0081, 0x0082, 0x0082, 0x0082, + 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, + 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, + 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, + 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, 0x008b, 0x008b, 0x008e, + 0x008e, 0x008e, 0x008e, 0x008e, 0x008e, 0x008e, 0x00a8, 0x00a8, + 0x00a8, 0x00a8, 0x00a8, 0x00a8, 0x00d8, 0x00d8, 0x00d8, 0x00d8, + // Entry 40 - 7F + 0x00d8, 0x00d9, 0x00d9, 0x00d9, 0x00d9, 0x00d9, 0x00d9, 0x00dc, + 0x00dc, 0x00dc, 0x00dc, 0x00dd, 0x00dd, 0x00dd, 0x00dd, 0x00dd, + 0x00de, 0x00de, 0x00de, 0x00de, 0x00de, 0x00df, 0x00df, 0x00df, + 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e0, + 0x00e0, 0x00e2, 0x00e2, 0x00e2, 0x00e2, 0x00e8, 0x00e8, 0x00ee, + 0x00ee, 0x00ee, 0x00ee, 0x00ee, 0x00f7, 0x00f7, 0x00f7, 0x00f8, + 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, + 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, + // Entry 80 - BF + 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, + 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + // Entry C0 - FF + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0103, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, + 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, + // Entry 100 - 13F + 0x0108, 0x0108, 0x0108, 0x0108, 0x010d, 0x010d, 0x010d, 0x010d, + 0x010d, 0x010d, 0x010d, 0x010d, 0x0111, 0x0111, 0x0112, 0x0113, + 0x0113, 0x0114, 0x0114, 0x0114, 0x0114, 0x0114, 0x0114, 0x0114, + 0x0114, 0x0114, 0x0114, 0x0114, 0x0114, 0x0171, 0x0171, 0x0172, + 0x0172, 0x0172, 0x0172, 0x0172, 0x017a, 0x017a, 0x017a, 0x017a, + 0x017a, 0x017a, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, + 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, + 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, + // Entry 140 - 17F + 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, + 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, + 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x017f, 0x0180, + 0x0180, 0x0182, 0x0182, 0x0185, 0x0185, 0x0185, 0x0185, 0x0185, + 0x0185, 0x0187, 0x0187, 0x0187, 0x0187, 0x0187, 0x0187, 0x0187, + 0x0187, 0x0187, 0x0187, 0x0187, 0x0187, 0x0187, 0x0188, 0x0188, + 0x018a, 0x018a, 0x018b, 0x018b, 0x018b, 0x018b, 0x018b, 0x018c, + 0x018c, 0x018d, 0x018d, 0x018e, 0x018e, 0x018e, 0x018e, 0x018e, + // Entry 180 - 1BF + 0x018e, 0x018e, 0x018e, 0x018f, 0x018f, 0x0193, 0x0193, 0x0193, + 0x0193, 0x0193, 0x0193, 0x0193, 0x0196, 0x0196, 0x0196, 0x0196, + 0x0196, 0x0196, 0x0196, 0x0196, 0x0196, 0x0196, 0x0197, 0x0197, + 0x0197, 0x0197, 0x0197, 0x0197, 0x0197, 0x0197, 0x0197, 0x0197, + 0x0197, 0x0197, 0x0197, 0x0197, 0x0197, 0x0197, 0x0198, 0x0198, + 0x0198, 0x0198, 0x0198, 0x0198, 0x0198, 0x0198, 0x0199, 0x0199, + 0x019b, 0x019b, 0x019d, 0x019d, 0x019d, 0x019d, 0x019d, 0x019d, + 0x019d, 0x019d, 0x019d, 0x019d, 0x019d, 0x019d, 0x019d, 0x019d, + // Entry 1C0 - 1FF + 0x019d, 0x019d, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x01a9, 0x01a9, + 0x01a9, 0x01a9, 0x01a9, 0x01a9, 0x01a9, 0x01a9, 0x01a9, 0x01a9, + 0x01a9, 0x01aa, 0x01aa, 0x01aa, 0x01aa, 0x01aa, 0x01b5, 0x01b5, + 0x01b5, 0x01b5, 0x01b5, 0x01b5, 0x01b5, 0x01b5, 0x01b6, 0x01b6, + 0x01b6, 0x01b6, 0x01b6, 0x01b6, 0x01b6, 0x01b6, 0x01b6, 0x01b6, + 0x01b6, 0x01b6, 0x01b6, 0x01b6, 0x01b6, 0x01b7, 0x01b7, 0x01b8, + 0x01b8, 0x01ba, 0x01ba, 0x01ba, 0x01bb, 0x01bb, 0x01bc, 0x01bc, + 0x01bc, 0x01bc, 0x01bc, 0x01bc, 0x01bc, 0x01bc, 0x01be, 0x01be, + // Entry 200 - 23F + 0x01be, 0x01be, 0x01be, 0x01be, 0x01be, 0x01c0, 0x01c0, 0x01c0, + 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x01c1, 0x01c1, 0x01c1, + 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, + 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, + 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, + 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c2, 0x01c3, + 0x01c3, 0x01c3, 0x01c3, 0x01c3, 0x01c3, 0x01c5, 0x01c5, 0x01c5, + 0x01c5, 0x01c5, 0x01c5, 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, + // Entry 240 - 27F + 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, + 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, 0x01c7, + 0x01c8, 0x01c8, 0x01c8, 0x01c8, 0x01c8, 0x01cb, 0x01cc, 0x01cc, + 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, + 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, + 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, + 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, 0x01cc, + 0x01cc, 0x01ce, 0x01ce, 0x01cf, 0x01cf, 0x01d0, 0x01d0, 0x01d0, + // Entry 280 - 2BF + 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, + 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, 0x01d0, + 0x01d2, 0x01d2, 0x01d2, 0x01d2, 0x01d2, 0x01d2, 0x01d5, 0x01d5, + 0x01d5, 0x01d5, 0x01d5, 0x01d5, 0x01d5, 0x01d5, 0x01d8, 0x01d8, + 0x01d8, 0x01d8, 0x01d9, 0x01d9, 0x01d9, 0x01d9, 0x01d9, 0x01d9, + 0x01da, 0x01da, 0x01da, 0x01da, 0x01da, 0x01db, 0x01db, 0x01db, + 0x01db, 0x01db, 0x01db, 0x01db, 0x01dc, 0x01dc, 0x01dc, 0x01dc, + 0x01dc, 0x01dc, 0x01dc, 0x01dc, 0x01dc, 0x01dc, 0x01dc, 0x01dc, + // Entry 2C0 - 2FF + 0x01de, 0x01de, 0x01de, 0x01de, 0x01de, 0x01de, 0x01de, 0x01de, + 0x01de, 0x01de, 0x01de, 0x01de, 0x01df, 0x01df, 0x01e0, 0x01e0, + 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e0, + 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e1, 0x01e1, + 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, + 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, + 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, 0x01e1, + 0x01e1, 0x01e1, 0x01e2, 0x01e2, 0x01e2, 0x01e2, 0x01e2, 0x01e2, + // Entry 300 - 33F + 0x01e3, 0x01e3, 0x01e3, 0x01e3, 0x01eb, 0x01eb, 0x01eb, 0x01eb, +} // Size: 1576 bytes + +var narrowSymIndex = []curToIndex{ // 491 elements + 0: {cur: 0x9, idx: 0x1}, + 1: {cur: 0x11, idx: 0x4}, + 2: {cur: 0x13, idx: 0x4}, + 3: {cur: 0x18, idx: 0x9}, + 4: {cur: 0x1a, idx: 0x4}, + 5: {cur: 0x1b, idx: 0xc}, + 6: {cur: 0x25, idx: 0x4}, + 7: {cur: 0x26, idx: 0x4}, + 8: {cur: 0x27, idx: 0x10}, + 9: {cur: 0x2e, idx: 0x13}, + 10: {cur: 0x32, idx: 0x4}, + 11: {cur: 0x35, idx: 0x16}, + 12: {cur: 0x37, idx: 0x18}, + 13: {cur: 0x39, idx: 0x4}, + 14: {cur: 0x3a, idx: 0x4}, + 15: {cur: 0x41, idx: 0x4}, + 16: {cur: 0x44, idx: 0x25}, + 17: {cur: 0x45, idx: 0x4}, + 18: {cur: 0x47, idx: 0x28}, + 19: {cur: 0x4a, idx: 0x4}, + 20: {cur: 0x4b, idx: 0x4}, + 21: {cur: 0x4e, idx: 0x2c}, + 22: {cur: 0x52, idx: 0x30}, + 23: {cur: 0x53, idx: 0x4}, + 24: {cur: 0x58, idx: 0x33}, + 25: {cur: 0x5c, idx: 0x37}, + 26: {cur: 0x5e, idx: 0x3b}, + 27: {cur: 0x60, idx: 0x4}, + 28: {cur: 0x61, idx: 0x3f}, + 29: {cur: 0x63, idx: 0x3f}, + 30: {cur: 0x65, idx: 0x42}, + 31: {cur: 0x68, idx: 0x3f}, + 32: {cur: 0x6a, idx: 0x46}, + 33: {cur: 0x6e, idx: 0x49}, + 34: {cur: 0x71, idx: 0x4}, + 35: {cur: 0x72, idx: 0x4}, + 36: {cur: 0x73, idx: 0x4f}, + 37: {cur: 0x75, idx: 0x51}, + 38: {cur: 0x77, idx: 0x54}, + 39: {cur: 0x78, idx: 0x57}, + 40: {cur: 0x7c, idx: 0x5a}, + 41: {cur: 0x7d, idx: 0x5e}, + 42: {cur: 0x81, idx: 0x30}, + 43: {cur: 0x83, idx: 0x4}, + 44: {cur: 0x85, idx: 0x25}, + 45: {cur: 0x88, idx: 0x67}, + 46: {cur: 0x89, idx: 0x6b}, + 47: {cur: 0x8a, idx: 0x6e}, + 48: {cur: 0x8d, idx: 0x6e}, + 49: {cur: 0x8f, idx: 0x4}, + 50: {cur: 0x90, idx: 0x72}, + 51: {cur: 0x91, idx: 0x76}, + 52: {cur: 0x92, idx: 0x7a}, + 53: {cur: 0x93, idx: 0x7e}, + 54: {cur: 0x94, idx: 0x4}, + 55: {cur: 0x96, idx: 0x81}, + 56: {cur: 0x9b, idx: 0x84}, + 57: {cur: 0xa3, idx: 0x87}, + 58: {cur: 0xa8, idx: 0x8a}, + 59: {cur: 0xa9, idx: 0x8c}, + 60: {cur: 0xae, idx: 0x7e}, + 61: {cur: 0xb2, idx: 0x4}, + 62: {cur: 0xb5, idx: 0x94}, + 63: {cur: 0xb9, idx: 0x4}, + 64: {cur: 0xba, idx: 0x97}, + 65: {cur: 0xbc, idx: 0x9b}, + 66: {cur: 0xbe, idx: 0x30}, + 67: {cur: 0xbf, idx: 0x7e}, + 68: {cur: 0xc0, idx: 0x4}, + 69: {cur: 0xc7, idx: 0xa2}, + 70: {cur: 0xc8, idx: 0x7e}, + 71: {cur: 0xc9, idx: 0xa6}, + 72: {cur: 0xcc, idx: 0xaa}, + 73: {cur: 0xd0, idx: 0xae}, + 74: {cur: 0xd2, idx: 0xb2}, + 75: {cur: 0xd3, idx: 0x18}, + 76: {cur: 0xd4, idx: 0xb6}, + 77: {cur: 0xd6, idx: 0x4}, + 78: {cur: 0xdb, idx: 0x30}, + 79: {cur: 0xdc, idx: 0x4}, + 80: {cur: 0xdd, idx: 0x3f}, + 81: {cur: 0xe2, idx: 0x4}, + 82: {cur: 0xe4, idx: 0x3f}, + 83: {cur: 0xe5, idx: 0xb9}, + 84: {cur: 0xe9, idx: 0x3f}, + 85: {cur: 0xeb, idx: 0xbc}, + 86: {cur: 0xf1, idx: 0xc0}, + 87: {cur: 0xf4, idx: 0xc3}, + 88: {cur: 0xf5, idx: 0x4}, + 89: {cur: 0xf6, idx: 0x4}, + 90: {cur: 0xf8, idx: 0xcb}, + 91: {cur: 0xfc, idx: 0x4}, + 92: {cur: 0x101, idx: 0x4}, + 93: {cur: 0x104, idx: 0x10}, + 94: {cur: 0x105, idx: 0xd3}, + 95: {cur: 0x110, idx: 0x4}, + 96: {cur: 0x125, idx: 0xe9}, + 97: {cur: 0x127, idx: 0xeb}, + 98: {cur: 0xd0, idx: 0xee}, + 99: {cur: 0xf6, idx: 0xc7}, + 100: {cur: 0xf6, idx: 0xc7}, + 101: {cur: 0x11, idx: 0x128}, + 102: {cur: 0x13, idx: 0xf8}, + 103: {cur: 0x1a, idx: 0x12c}, + 104: {cur: 0x25, idx: 0x13a}, + 105: {cur: 0x26, idx: 0x13e}, + 106: {cur: 0x32, idx: 0x142}, + 107: {cur: 0x39, idx: 0x146}, + 108: {cur: 0x3a, idx: 0x1c}, + 109: {cur: 0x41, idx: 0x14a}, + 110: {cur: 0x44, idx: 0x20}, + 111: {cur: 0x45, idx: 0x14e}, + 112: {cur: 0x4b, idx: 0x152}, + 113: {cur: 0x53, idx: 0x156}, + 114: {cur: 0x60, idx: 0x16e}, + 115: {cur: 0x63, idx: 0x172}, + 116: {cur: 0x71, idx: 0x177}, + 117: {cur: 0x72, idx: 0x4b}, + 118: {cur: 0x83, idx: 0x18c}, + 119: {cur: 0x85, idx: 0x62}, + 120: {cur: 0x8f, idx: 0x1a4}, + 121: {cur: 0xb2, idx: 0x90}, + 122: {cur: 0xc0, idx: 0x9e}, + 123: {cur: 0xd6, idx: 0x1ee}, + 124: {cur: 0xe2, idx: 0x203}, + 125: {cur: 0xf5, idx: 0x21b}, + 126: {cur: 0xf6, idx: 0xc7}, + 127: {cur: 0xfc, idx: 0xcf}, + 128: {cur: 0x101, idx: 0x21f}, + 129: {cur: 0x26, idx: 0x4}, + 130: {cur: 0x37, idx: 0x0}, + 131: {cur: 0x52, idx: 0x0}, + 132: {cur: 0x75, idx: 0x0}, + 133: {cur: 0x81, idx: 0x0}, + 134: {cur: 0xbe, idx: 0x0}, + 135: {cur: 0xc9, idx: 0x0}, + 136: {cur: 0xd3, idx: 0x0}, + 137: {cur: 0xdb, idx: 0x0}, + 138: {cur: 0xf6, idx: 0xc7}, + 139: {cur: 0xd0, idx: 0x244}, + 140: {cur: 0xe9, idx: 0x248}, + 141: {cur: 0xf6, idx: 0xc7}, + 142: {cur: 0x13, idx: 0x6}, + 143: {cur: 0x1a, idx: 0x24c}, + 144: {cur: 0x25, idx: 0x251}, + 145: {cur: 0x32, idx: 0x255}, + 146: {cur: 0x37, idx: 0x258}, + 147: {cur: 0x39, idx: 0x146}, + 148: {cur: 0x3a, idx: 0x1c}, + 149: {cur: 0x4a, idx: 0x25b}, + 150: {cur: 0x4b, idx: 0x260}, + 151: {cur: 0x53, idx: 0x264}, + 152: {cur: 0x60, idx: 0x16e}, + 153: {cur: 0x61, idx: 0x268}, + 154: {cur: 0x71, idx: 0x26d}, + 155: {cur: 0x81, idx: 0x270}, + 156: {cur: 0x83, idx: 0x275}, + 157: {cur: 0x8f, idx: 0x278}, + 158: {cur: 0x94, idx: 0x27c}, + 159: {cur: 0xb2, idx: 0x90}, + 160: {cur: 0xb9, idx: 0x27f}, + 161: {cur: 0xc0, idx: 0x9e}, + 162: {cur: 0xd2, idx: 0x282}, + 163: {cur: 0xd6, idx: 0x28a}, + 164: {cur: 0xdc, idx: 0x28e}, + 165: {cur: 0xf5, idx: 0x21b}, + 166: {cur: 0x101, idx: 0x291}, + 167: {cur: 0x110, idx: 0xdc}, + 168: {cur: 0x11, idx: 0x0}, + 169: {cur: 0x13, idx: 0x0}, + 170: {cur: 0x1a, idx: 0x0}, + 171: {cur: 0x1b, idx: 0x0}, + 172: {cur: 0x25, idx: 0x0}, + 173: {cur: 0x26, idx: 0x0}, + 174: {cur: 0x2e, idx: 0x0}, + 175: {cur: 0x32, idx: 0x0}, + 176: {cur: 0x37, idx: 0x0}, + 177: {cur: 0x39, idx: 0x0}, + 178: {cur: 0x3a, idx: 0x0}, + 179: {cur: 0x41, idx: 0x0}, + 180: {cur: 0x44, idx: 0x0}, + 181: {cur: 0x45, idx: 0x0}, + 182: {cur: 0x47, idx: 0x0}, + 183: {cur: 0x4b, idx: 0x0}, + 184: {cur: 0x53, idx: 0x0}, + 185: {cur: 0x60, idx: 0x0}, + 186: {cur: 0x68, idx: 0x0}, + 187: {cur: 0x71, idx: 0x0}, + 188: {cur: 0x72, idx: 0x0}, + 189: {cur: 0x7c, idx: 0x0}, + 190: {cur: 0x7d, idx: 0x0}, + 191: {cur: 0x83, idx: 0x0}, + 192: {cur: 0x88, idx: 0x0}, + 193: {cur: 0x8d, idx: 0x0}, + 194: {cur: 0x8f, idx: 0x0}, + 195: {cur: 0x90, idx: 0x0}, + 196: {cur: 0x91, idx: 0x0}, + 197: {cur: 0x94, idx: 0x0}, + 198: {cur: 0xa9, idx: 0x0}, + 199: {cur: 0xb2, idx: 0x0}, + 200: {cur: 0xb9, idx: 0x0}, + 201: {cur: 0xba, idx: 0x0}, + 202: {cur: 0xc0, idx: 0x0}, + 203: {cur: 0xc7, idx: 0x0}, + 204: {cur: 0xcc, idx: 0x0}, + 205: {cur: 0xd0, idx: 0x0}, + 206: {cur: 0xd6, idx: 0x0}, + 207: {cur: 0xdc, idx: 0x0}, + 208: {cur: 0xe2, idx: 0x0}, + 209: {cur: 0xe4, idx: 0x0}, + 210: {cur: 0xf4, idx: 0x0}, + 211: {cur: 0xf5, idx: 0x0}, + 212: {cur: 0xf6, idx: 0x0}, + 213: {cur: 0xf8, idx: 0x0}, + 214: {cur: 0x101, idx: 0x0}, + 215: {cur: 0x105, idx: 0x0}, + 216: {cur: 0xf6, idx: 0xc7}, + 217: {cur: 0x58, idx: 0x2a8}, + 218: {cur: 0x92, idx: 0x2b8}, + 219: {cur: 0xf1, idx: 0x2c1}, + 220: {cur: 0xf6, idx: 0xc7}, + 221: {cur: 0x104, idx: 0x0}, + 222: {cur: 0xf6, idx: 0xc7}, + 223: {cur: 0xd0, idx: 0x2ed}, + 224: {cur: 0xd0, idx: 0x4f}, + 225: {cur: 0xf6, idx: 0xc7}, + 226: {cur: 0x1b, idx: 0x301}, + 227: {cur: 0x35, idx: 0x0}, + 228: {cur: 0x72, idx: 0x4b}, + 229: {cur: 0xf6, idx: 0xc7}, + 230: {cur: 0x125, idx: 0x0}, + 231: {cur: 0x127, idx: 0x0}, + 232: {cur: 0x52, idx: 0x304}, + 233: {cur: 0x81, idx: 0x304}, + 234: {cur: 0xbe, idx: 0x304}, + 235: {cur: 0xd0, idx: 0x4f}, + 236: {cur: 0xdb, idx: 0x304}, + 237: {cur: 0xf6, idx: 0xc7}, + 238: {cur: 0x4a, idx: 0x318}, + 239: {cur: 0x61, idx: 0x320}, + 240: {cur: 0x6a, idx: 0x325}, + 241: {cur: 0x89, idx: 0x32a}, + 242: {cur: 0xd0, idx: 0x4f}, + 243: {cur: 0xd4, idx: 0x32d}, + 244: {cur: 0xe9, idx: 0x0}, + 245: {cur: 0xf6, idx: 0xc7}, + 246: {cur: 0x127, idx: 0x8a}, + 247: {cur: 0x5e, idx: 0x0}, + 248: {cur: 0x1b, idx: 0x349}, + 249: {cur: 0x27, idx: 0x34c}, + 250: {cur: 0x4b, idx: 0xa2}, + 251: {cur: 0x58, idx: 0x3f}, + 252: {cur: 0x81, idx: 0x34f}, + 253: {cur: 0xcc, idx: 0x352}, + 254: {cur: 0xdb, idx: 0x34f}, + 255: {cur: 0x101, idx: 0x291}, + 256: {cur: 0x58, idx: 0x0}, + 257: {cur: 0xd0, idx: 0x4f}, + 258: {cur: 0xf6, idx: 0xc7}, + 259: {cur: 0x58, idx: 0x33}, + 260: {cur: 0x61, idx: 0x268}, + 261: {cur: 0xe4, idx: 0x37b}, + 262: {cur: 0xe9, idx: 0x248}, + 263: {cur: 0x104, idx: 0x380}, + 264: {cur: 0x37, idx: 0x384}, + 265: {cur: 0x61, idx: 0x3f}, + 266: {cur: 0xd0, idx: 0xae}, + 267: {cur: 0xe4, idx: 0x3f}, + 268: {cur: 0xe9, idx: 0x3f}, + 269: {cur: 0x61, idx: 0x3f}, + 270: {cur: 0xd0, idx: 0xae}, + 271: {cur: 0xe4, idx: 0x3f}, + 272: {cur: 0xe9, idx: 0x3f}, + 273: {cur: 0x104, idx: 0x392}, + 274: {cur: 0xf6, idx: 0xc7}, + 275: {cur: 0xf6, idx: 0xc7}, + 276: {cur: 0x9, idx: 0x0}, + 277: {cur: 0x11, idx: 0x0}, + 278: {cur: 0x13, idx: 0x0}, + 279: {cur: 0x18, idx: 0x0}, + 280: {cur: 0x1a, idx: 0x0}, + 281: {cur: 0x1b, idx: 0x0}, + 282: {cur: 0x25, idx: 0x0}, + 283: {cur: 0x26, idx: 0x0}, + 284: {cur: 0x27, idx: 0x0}, + 285: {cur: 0x2e, idx: 0x0}, + 286: {cur: 0x32, idx: 0x0}, + 287: {cur: 0x35, idx: 0x0}, + 288: {cur: 0x37, idx: 0x0}, + 289: {cur: 0x39, idx: 0x0}, + 290: {cur: 0x3a, idx: 0x0}, + 291: {cur: 0x41, idx: 0x0}, + 292: {cur: 0x44, idx: 0x0}, + 293: {cur: 0x45, idx: 0x0}, + 294: {cur: 0x47, idx: 0x0}, + 295: {cur: 0x4a, idx: 0x0}, + 296: {cur: 0x4b, idx: 0x0}, + 297: {cur: 0x4e, idx: 0x0}, + 298: {cur: 0x52, idx: 0x0}, + 299: {cur: 0x53, idx: 0x0}, + 300: {cur: 0x58, idx: 0x0}, + 301: {cur: 0x5c, idx: 0x0}, + 302: {cur: 0x60, idx: 0x0}, + 303: {cur: 0x61, idx: 0x0}, + 304: {cur: 0x65, idx: 0x0}, + 305: {cur: 0x68, idx: 0x0}, + 306: {cur: 0x6a, idx: 0x0}, + 307: {cur: 0x6e, idx: 0x0}, + 308: {cur: 0x71, idx: 0x0}, + 309: {cur: 0x72, idx: 0x0}, + 310: {cur: 0x73, idx: 0x0}, + 311: {cur: 0x75, idx: 0x0}, + 312: {cur: 0x77, idx: 0x0}, + 313: {cur: 0x78, idx: 0x0}, + 314: {cur: 0x7c, idx: 0x0}, + 315: {cur: 0x7d, idx: 0x0}, + 316: {cur: 0x81, idx: 0x0}, + 317: {cur: 0x83, idx: 0x0}, + 318: {cur: 0x88, idx: 0x0}, + 319: {cur: 0x89, idx: 0x0}, + 320: {cur: 0x8a, idx: 0x0}, + 321: {cur: 0x8d, idx: 0x0}, + 322: {cur: 0x8f, idx: 0x0}, + 323: {cur: 0x90, idx: 0x0}, + 324: {cur: 0x91, idx: 0x0}, + 325: {cur: 0x92, idx: 0x0}, + 326: {cur: 0x93, idx: 0x0}, + 327: {cur: 0x94, idx: 0x0}, + 328: {cur: 0x96, idx: 0x0}, + 329: {cur: 0x9b, idx: 0x0}, + 330: {cur: 0xa3, idx: 0x0}, + 331: {cur: 0xa8, idx: 0x0}, + 332: {cur: 0xa9, idx: 0x0}, + 333: {cur: 0xae, idx: 0x0}, + 334: {cur: 0xb2, idx: 0x0}, + 335: {cur: 0xb5, idx: 0x0}, + 336: {cur: 0xb9, idx: 0x0}, + 337: {cur: 0xba, idx: 0x0}, + 338: {cur: 0xbc, idx: 0x0}, + 339: {cur: 0xbe, idx: 0x0}, + 340: {cur: 0xbf, idx: 0x0}, + 341: {cur: 0xc0, idx: 0x0}, + 342: {cur: 0xc7, idx: 0x0}, + 343: {cur: 0xc8, idx: 0x0}, + 344: {cur: 0xc9, idx: 0x0}, + 345: {cur: 0xcc, idx: 0x0}, + 346: {cur: 0xd0, idx: 0x0}, + 347: {cur: 0xd3, idx: 0x0}, + 348: {cur: 0xd4, idx: 0x0}, + 349: {cur: 0xd6, idx: 0x0}, + 350: {cur: 0xdb, idx: 0x0}, + 351: {cur: 0xdc, idx: 0x0}, + 352: {cur: 0xdd, idx: 0x0}, + 353: {cur: 0xe2, idx: 0x0}, + 354: {cur: 0xe4, idx: 0x0}, + 355: {cur: 0xe5, idx: 0x0}, + 356: {cur: 0xe9, idx: 0x0}, + 357: {cur: 0xeb, idx: 0x0}, + 358: {cur: 0xf1, idx: 0x0}, + 359: {cur: 0xf4, idx: 0x0}, + 360: {cur: 0xf5, idx: 0x0}, + 361: {cur: 0xf6, idx: 0x0}, + 362: {cur: 0xf8, idx: 0x0}, + 363: {cur: 0x101, idx: 0x0}, + 364: {cur: 0x104, idx: 0x0}, + 365: {cur: 0x105, idx: 0x0}, + 366: {cur: 0x110, idx: 0x0}, + 367: {cur: 0x125, idx: 0x0}, + 368: {cur: 0x127, idx: 0x0}, + 369: {cur: 0xf6, idx: 0xc7}, + 370: {cur: 0x58, idx: 0x3e5}, + 371: {cur: 0x89, idx: 0x32a}, + 372: {cur: 0x92, idx: 0x2b8}, + 373: {cur: 0xbc, idx: 0x41a}, + 374: {cur: 0xd0, idx: 0x4f}, + 375: {cur: 0xd4, idx: 0x421}, + 376: {cur: 0xf6, idx: 0xc7}, + 377: {cur: 0x127, idx: 0x441}, + 378: {cur: 0x37, idx: 0x258}, + 379: {cur: 0x65, idx: 0x0}, + 380: {cur: 0x89, idx: 0x6b}, + 381: {cur: 0xbc, idx: 0x9b}, + 382: {cur: 0x127, idx: 0xeb}, + 383: {cur: 0xf6, idx: 0xc7}, + 384: {cur: 0xd0, idx: 0xee}, + 385: {cur: 0xf6, idx: 0xc7}, + 386: {cur: 0x89, idx: 0x32a}, + 387: {cur: 0xd2, idx: 0x46d}, + 388: {cur: 0xf6, idx: 0xc7}, + 389: {cur: 0xae, idx: 0x474}, + 390: {cur: 0xf6, idx: 0xc7}, + 391: {cur: 0xf6, idx: 0xc7}, + 392: {cur: 0xd0, idx: 0x48e}, + 393: {cur: 0xf6, idx: 0xc7}, + 394: {cur: 0xf6, idx: 0xc7}, + 395: {cur: 0xf6, idx: 0xc7}, + 396: {cur: 0xf6, idx: 0xc7}, + 397: {cur: 0xf6, idx: 0xc7}, + 398: {cur: 0xf6, idx: 0xc7}, + 399: {cur: 0x37, idx: 0x258}, + 400: {cur: 0x58, idx: 0x3e5}, + 401: {cur: 0xbe, idx: 0x49b}, + 402: {cur: 0xf6, idx: 0xc7}, + 403: {cur: 0x44, idx: 0x4a3}, + 404: {cur: 0x85, idx: 0x4a3}, + 405: {cur: 0xd0, idx: 0x4a7}, + 406: {cur: 0xf6, idx: 0xc7}, + 407: {cur: 0xf6, idx: 0xc7}, + 408: {cur: 0xf6, idx: 0xc7}, + 409: {cur: 0xd0, idx: 0x4b2}, + 410: {cur: 0xf6, idx: 0xc7}, + 411: {cur: 0xd0, idx: 0x4f}, + 412: {cur: 0xf6, idx: 0xc7}, + 413: {cur: 0x25, idx: 0x251}, + 414: {cur: 0x32, idx: 0x255}, + 415: {cur: 0x39, idx: 0x146}, + 416: {cur: 0x3a, idx: 0x9b}, + 417: {cur: 0x53, idx: 0x264}, + 418: {cur: 0x58, idx: 0x4b9}, + 419: {cur: 0x72, idx: 0x4b}, + 420: {cur: 0x75, idx: 0x4bc}, + 421: {cur: 0x83, idx: 0x275}, + 422: {cur: 0xf5, idx: 0x21b}, + 423: {cur: 0xf6, idx: 0xc7}, + 424: {cur: 0xf6, idx: 0xc7}, + 425: {cur: 0xf6, idx: 0xc7}, + 426: {cur: 0x1b, idx: 0x0}, + 427: {cur: 0x37, idx: 0x258}, + 428: {cur: 0x7c, idx: 0x0}, + 429: {cur: 0x7d, idx: 0x0}, + 430: {cur: 0x88, idx: 0x0}, + 431: {cur: 0x91, idx: 0x0}, + 432: {cur: 0xa9, idx: 0x0}, + 433: {cur: 0xc9, idx: 0x4c6}, + 434: {cur: 0xcc, idx: 0x352}, + 435: {cur: 0xd2, idx: 0x4c9}, + 436: {cur: 0x105, idx: 0x0}, + 437: {cur: 0xf6, idx: 0xc7}, + 438: {cur: 0xf6, idx: 0xc7}, + 439: {cur: 0xf6, idx: 0xc7}, + 440: {cur: 0xdb, idx: 0x4d7}, + 441: {cur: 0xf6, idx: 0xc7}, + 442: {cur: 0xf6, idx: 0xc7}, + 443: {cur: 0xf6, idx: 0xc7}, + 444: {cur: 0x1a, idx: 0x24c}, + 445: {cur: 0x32, idx: 0x255}, + 446: {cur: 0xd0, idx: 0x4f}, + 447: {cur: 0xf6, idx: 0xc7}, + 448: {cur: 0xbf, idx: 0x4f1}, + 449: {cur: 0xf6, idx: 0xc7}, + 450: {cur: 0xf6, idx: 0xc7}, + 451: {cur: 0xd0, idx: 0x500}, + 452: {cur: 0xf6, idx: 0xc7}, + 453: {cur: 0xd0, idx: 0x4f}, + 454: {cur: 0xf6, idx: 0xc7}, + 455: {cur: 0xf6, idx: 0xc7}, + 456: {cur: 0x65, idx: 0x515}, + 457: {cur: 0xd0, idx: 0x4f}, + 458: {cur: 0xf6, idx: 0xc7}, + 459: {cur: 0x37, idx: 0x258}, + 460: {cur: 0x93, idx: 0x52c}, + 461: {cur: 0xf6, idx: 0xc7}, + 462: {cur: 0xf6, idx: 0xc7}, + 463: {cur: 0xf6, idx: 0xc7}, + 464: {cur: 0x65, idx: 0x515}, + 465: {cur: 0xf6, idx: 0xc7}, + 466: {cur: 0x37, idx: 0x552}, + 467: {cur: 0x65, idx: 0x515}, + 468: {cur: 0xf6, idx: 0xc7}, + 469: {cur: 0x5c, idx: 0x0}, + 470: {cur: 0xd0, idx: 0x4f}, + 471: {cur: 0xf6, idx: 0xc7}, + 472: {cur: 0xf6, idx: 0xc7}, + 473: {cur: 0xf6, idx: 0xc7}, + 474: {cur: 0xf6, idx: 0xc7}, + 475: {cur: 0xf6, idx: 0xc7}, + 476: {cur: 0xd0, idx: 0x4f}, + 477: {cur: 0xf6, idx: 0xc7}, + 478: {cur: 0xf6, idx: 0xc7}, + 479: {cur: 0xf6, idx: 0xc7}, + 480: {cur: 0xf6, idx: 0xc7}, + 481: {cur: 0xf6, idx: 0xc7}, + 482: {cur: 0xd0, idx: 0x4f}, + 483: {cur: 0x37, idx: 0x59e}, + 484: {cur: 0x52, idx: 0x34f}, + 485: {cur: 0x75, idx: 0x4bc}, + 486: {cur: 0x81, idx: 0x34f}, + 487: {cur: 0xbe, idx: 0x34f}, + 488: {cur: 0xc9, idx: 0x5a1}, + 489: {cur: 0xdb, idx: 0x34f}, + 490: {cur: 0xf6, idx: 0xc7}, +} // Size: 1988 bytes + +// Total table size 18885 bytes (18KiB); checksum: BE08FD0B diff --git a/vendor/golang.org/x/text/internal/format/format.go b/vendor/golang.org/x/text/internal/format/format.go new file mode 100644 index 00000000000..ee1c57a3c58 --- /dev/null +++ b/vendor/golang.org/x/text/internal/format/format.go @@ -0,0 +1,41 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package format contains types for defining language-specific formatting of +// values. +// +// This package is internal now, but will eventually be exposed after the API +// settles. +package format // import "golang.org/x/text/internal/format" + +import ( + "fmt" + + "golang.org/x/text/language" +) + +// State represents the printer state passed to custom formatters. It provides +// access to the fmt.State interface and the sentence and language-related +// context. +type State interface { + fmt.State + + // Language reports the requested language in which to render a message. + Language() language.Tag + + // TODO: consider this and removing rune from the Format method in the + // Formatter interface. + // + // Verb returns the format variant to render, analogous to the types used + // in fmt. Use 'v' for the default or only variant. + // Verb() rune + + // TODO: more info: + // - sentence context such as linguistic features passed by the translator. +} + +// Formatter is analogous to fmt.Formatter. +type Formatter interface { + Format(state State, verb rune) +} diff --git a/vendor/golang.org/x/text/internal/format/parser.go b/vendor/golang.org/x/text/internal/format/parser.go new file mode 100644 index 00000000000..855aed71dbb --- /dev/null +++ b/vendor/golang.org/x/text/internal/format/parser.go @@ -0,0 +1,358 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package format + +import ( + "reflect" + "unicode/utf8" +) + +// A Parser parses a format string. The result from the parse are set in the +// struct fields. +type Parser struct { + Verb rune + + WidthPresent bool + PrecPresent bool + Minus bool + Plus bool + Sharp bool + Space bool + Zero bool + + // For the formats %+v %#v, we set the plusV/sharpV flags + // and clear the plus/sharp flags since %+v and %#v are in effect + // different, flagless formats set at the top level. + PlusV bool + SharpV bool + + HasIndex bool + + Width int + Prec int // precision + + // retain arguments across calls. + Args []interface{} + // retain current argument number across calls + ArgNum int + + // reordered records whether the format string used argument reordering. + Reordered bool + // goodArgNum records whether the most recent reordering directive was valid. + goodArgNum bool + + // position info + format string + startPos int + endPos int + Status Status +} + +// Reset initializes a parser to scan format strings for the given args. +func (p *Parser) Reset(args []interface{}) { + p.Args = args + p.ArgNum = 0 + p.startPos = 0 + p.Reordered = false +} + +// Text returns the part of the format string that was parsed by the last call +// to Scan. It returns the original substitution clause if the current scan +// parsed a substitution. +func (p *Parser) Text() string { return p.format[p.startPos:p.endPos] } + +// SetFormat sets a new format string to parse. It does not reset the argument +// count. +func (p *Parser) SetFormat(format string) { + p.format = format + p.startPos = 0 + p.endPos = 0 +} + +// Status indicates the result type of a call to Scan. +type Status int + +const ( + StatusText Status = iota + StatusSubstitution + StatusBadWidthSubstitution + StatusBadPrecSubstitution + StatusNoVerb + StatusBadArgNum + StatusMissingArg +) + +// ClearFlags reset the parser to default behavior. +func (p *Parser) ClearFlags() { + p.WidthPresent = false + p.PrecPresent = false + p.Minus = false + p.Plus = false + p.Sharp = false + p.Space = false + p.Zero = false + + p.PlusV = false + p.SharpV = false + + p.HasIndex = false +} + +// Scan scans the next part of the format string and sets the status to +// indicate whether it scanned a string literal, substitution or error. +func (p *Parser) Scan() bool { + p.Status = StatusText + format := p.format + end := len(format) + if p.endPos >= end { + return false + } + afterIndex := false // previous item in format was an index like [3]. + + p.startPos = p.endPos + p.goodArgNum = true + i := p.startPos + for i < end && format[i] != '%' { + i++ + } + if i > p.startPos { + p.endPos = i + return true + } + // Process one verb + i++ + + p.Status = StatusSubstitution + + // Do we have flags? + p.ClearFlags() + +simpleFormat: + for ; i < end; i++ { + c := p.format[i] + switch c { + case '#': + p.Sharp = true + case '0': + p.Zero = !p.Minus // Only allow zero padding to the left. + case '+': + p.Plus = true + case '-': + p.Minus = true + p.Zero = false // Do not pad with zeros to the right. + case ' ': + p.Space = true + default: + // Fast path for common case of ascii lower case simple verbs + // without precision or width or argument indices. + if 'a' <= c && c <= 'z' && p.ArgNum < len(p.Args) { + if c == 'v' { + // Go syntax + p.SharpV = p.Sharp + p.Sharp = false + // Struct-field syntax + p.PlusV = p.Plus + p.Plus = false + } + p.Verb = rune(c) + p.ArgNum++ + p.endPos = i + 1 + return true + } + // Format is more complex than simple flags and a verb or is malformed. + break simpleFormat + } + } + + // Do we have an explicit argument index? + i, afterIndex = p.updateArgNumber(format, i) + + // Do we have width? + if i < end && format[i] == '*' { + i++ + p.Width, p.WidthPresent = p.intFromArg() + + if !p.WidthPresent { + p.Status = StatusBadWidthSubstitution + } + + // We have a negative width, so take its value and ensure + // that the minus flag is set + if p.Width < 0 { + p.Width = -p.Width + p.Minus = true + p.Zero = false // Do not pad with zeros to the right. + } + afterIndex = false + } else { + p.Width, p.WidthPresent, i = parsenum(format, i, end) + if afterIndex && p.WidthPresent { // "%[3]2d" + p.goodArgNum = false + } + } + + // Do we have precision? + if i+1 < end && format[i] == '.' { + i++ + if afterIndex { // "%[3].2d" + p.goodArgNum = false + } + i, afterIndex = p.updateArgNumber(format, i) + if i < end && format[i] == '*' { + i++ + p.Prec, p.PrecPresent = p.intFromArg() + // Negative precision arguments don't make sense + if p.Prec < 0 { + p.Prec = 0 + p.PrecPresent = false + } + if !p.PrecPresent { + p.Status = StatusBadPrecSubstitution + } + afterIndex = false + } else { + p.Prec, p.PrecPresent, i = parsenum(format, i, end) + if !p.PrecPresent { + p.Prec = 0 + p.PrecPresent = true + } + } + } + + if !afterIndex { + i, afterIndex = p.updateArgNumber(format, i) + } + p.HasIndex = afterIndex + + if i >= end { + p.endPos = i + p.Status = StatusNoVerb + return true + } + + verb, w := utf8.DecodeRuneInString(format[i:]) + p.endPos = i + w + p.Verb = verb + + switch { + case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec. + p.startPos = p.endPos - 1 + p.Status = StatusText + case !p.goodArgNum: + p.Status = StatusBadArgNum + case p.ArgNum >= len(p.Args): // No argument left over to print for the current verb. + p.Status = StatusMissingArg + p.ArgNum++ + case verb == 'v': + // Go syntax + p.SharpV = p.Sharp + p.Sharp = false + // Struct-field syntax + p.PlusV = p.Plus + p.Plus = false + fallthrough + default: + p.ArgNum++ + } + return true +} + +// intFromArg gets the ArgNumth element of Args. On return, isInt reports +// whether the argument has integer type. +func (p *Parser) intFromArg() (num int, isInt bool) { + if p.ArgNum < len(p.Args) { + arg := p.Args[p.ArgNum] + num, isInt = arg.(int) // Almost always OK. + if !isInt { + // Work harder. + switch v := reflect.ValueOf(arg); v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n := v.Int() + if int64(int(n)) == n { + num = int(n) + isInt = true + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n := v.Uint() + if int64(n) >= 0 && uint64(int(n)) == n { + num = int(n) + isInt = true + } + default: + // Already 0, false. + } + } + p.ArgNum++ + if tooLarge(num) { + num = 0 + isInt = false + } + } + return +} + +// parseArgNumber returns the value of the bracketed number, minus 1 +// (explicit argument numbers are one-indexed but we want zero-indexed). +// The opening bracket is known to be present at format[0]. +// The returned values are the index, the number of bytes to consume +// up to the closing paren, if present, and whether the number parsed +// ok. The bytes to consume will be 1 if no closing paren is present. +func parseArgNumber(format string) (index int, wid int, ok bool) { + // There must be at least 3 bytes: [n]. + if len(format) < 3 { + return 0, 1, false + } + + // Find closing bracket. + for i := 1; i < len(format); i++ { + if format[i] == ']' { + width, ok, newi := parsenum(format, 1, i) + if !ok || newi != i { + return 0, i + 1, false + } + return width - 1, i + 1, true // arg numbers are one-indexed and skip paren. + } + } + return 0, 1, false +} + +// updateArgNumber returns the next argument to evaluate, which is either the value of the passed-in +// argNum or the value of the bracketed integer that begins format[i:]. It also returns +// the new value of i, that is, the index of the next byte of the format to process. +func (p *Parser) updateArgNumber(format string, i int) (newi int, found bool) { + if len(format) <= i || format[i] != '[' { + return i, false + } + p.Reordered = true + index, wid, ok := parseArgNumber(format[i:]) + if ok && 0 <= index && index < len(p.Args) { + p.ArgNum = index + return i + wid, true + } + p.goodArgNum = false + return i + wid, ok +} + +// tooLarge reports whether the magnitude of the integer is +// too large to be used as a formatting width or precision. +func tooLarge(x int) bool { + const max int = 1e6 + return x > max || x < -max +} + +// parsenum converts ASCII to integer. num is 0 (and isnum is false) if no number present. +func parsenum(s string, start, end int) (num int, isnum bool, newi int) { + if start >= end { + return 0, false, end + } + for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ { + if tooLarge(num) { + return 0, false, end // Overflow; crazy long number most likely. + } + num = num*10 + int(s[newi]-'0') + isnum = true + } + return +} diff --git a/vendor/golang.org/x/text/internal/number/common.go b/vendor/golang.org/x/text/internal/number/common.go new file mode 100644 index 00000000000..a6e9c8e0d54 --- /dev/null +++ b/vendor/golang.org/x/text/internal/number/common.go @@ -0,0 +1,55 @@ +// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. + +package number + +import ( + "unicode/utf8" + + "golang.org/x/text/internal/language/compact" +) + +// A system identifies a CLDR numbering system. +type system byte + +type systemData struct { + id system + digitSize byte // number of UTF-8 bytes per digit + zero [utf8.UTFMax]byte // UTF-8 sequence of zero digit. +} + +// A SymbolType identifies a symbol of a specific kind. +type SymbolType int + +const ( + SymDecimal SymbolType = iota + SymGroup + SymList + SymPercentSign + SymPlusSign + SymMinusSign + SymExponential + SymSuperscriptingExponent + SymPerMille + SymInfinity + SymNan + SymTimeSeparator + + NumSymbolTypes +) + +const hasNonLatnMask = 0x8000 + +// symOffset is an offset into altSymData if the bit indicated by hasNonLatnMask +// is not 0 (with this bit masked out), and an offset into symIndex otherwise. +// +// TODO: this type can be a byte again if we use an indirection into altsymData +// and introduce an alt -> offset slice (the length of this will be number of +// alternatives plus 1). This also allows getting rid of the compactTag field +// in altSymData. In total this will save about 1K. +type symOffset uint16 + +type altSymData struct { + compactTag compact.ID + symIndex symOffset + system system +} diff --git a/vendor/golang.org/x/text/internal/number/decimal.go b/vendor/golang.org/x/text/internal/number/decimal.go new file mode 100644 index 00000000000..e128cf34377 --- /dev/null +++ b/vendor/golang.org/x/text/internal/number/decimal.go @@ -0,0 +1,500 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate stringer -type RoundingMode + +package number + +import ( + "math" + "strconv" +) + +// RoundingMode determines how a number is rounded to the desired precision. +type RoundingMode byte + +const ( + ToNearestEven RoundingMode = iota // towards the nearest integer, or towards an even number if equidistant. + ToNearestZero // towards the nearest integer, or towards zero if equidistant. + ToNearestAway // towards the nearest integer, or away from zero if equidistant. + ToPositiveInf // towards infinity + ToNegativeInf // towards negative infinity + ToZero // towards zero + AwayFromZero // away from zero + numModes +) + +const maxIntDigits = 20 + +// A Decimal represents a floating point number in decimal format. +// Digits represents a number [0, 1.0), and the absolute value represented by +// Decimal is Digits * 10^Exp. Leading and trailing zeros may be omitted and Exp +// may point outside a valid position in Digits. +// +// Examples: +// +// Number Decimal +// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5 +// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2 +// 12000 Digits: [1, 2], Exp: 5 +// 12000.00 Digits: [1, 2], Exp: 5 +// 0.00123 Digits: [1, 2, 3], Exp: -2 +// 0 Digits: [], Exp: 0 +type Decimal struct { + digits + + buf [maxIntDigits]byte +} + +type digits struct { + Digits []byte // mantissa digits, big-endian + Exp int32 // exponent + Neg bool + Inf bool // Takes precedence over Digits and Exp. + NaN bool // Takes precedence over Inf. +} + +// Digits represents a floating point number represented in digits of the +// base in which a number is to be displayed. It is similar to Decimal, but +// keeps track of trailing fraction zeros and the comma placement for +// engineering notation. Digits must have at least one digit. +// +// Examples: +// +// Number Decimal +// decimal +// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5 End: 5 +// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2 End: 5 +// 12000 Digits: [1, 2], Exp: 5 End: 5 +// 12000.00 Digits: [1, 2], Exp: 5 End: 7 +// 0.00123 Digits: [1, 2, 3], Exp: -2 End: 3 +// 0 Digits: [], Exp: 0 End: 1 +// scientific (actual exp is Exp - Comma) +// 0e0 Digits: [0], Exp: 1, End: 1, Comma: 1 +// .0e0 Digits: [0], Exp: 0, End: 1, Comma: 0 +// 0.0e0 Digits: [0], Exp: 1, End: 2, Comma: 1 +// 1.23e4 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 1 +// .123e5 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 0 +// engineering +// 12.3e3 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 2 +type Digits struct { + digits + // End indicates the end position of the number. + End int32 // For decimals Exp <= End. For scientific len(Digits) <= End. + // Comma is used for the comma position for scientific (always 0 or 1) and + // engineering notation (always 0, 1, 2, or 3). + Comma uint8 + // IsScientific indicates whether this number is to be rendered as a + // scientific number. + IsScientific bool +} + +func (d *Digits) NumFracDigits() int { + if d.Exp >= d.End { + return 0 + } + return int(d.End - d.Exp) +} + +// normalize returns a new Decimal with leading and trailing zeros removed. +func (d *Decimal) normalize() (n Decimal) { + n = *d + b := n.Digits + // Strip leading zeros. Resulting number of digits is significant digits. + for len(b) > 0 && b[0] == 0 { + b = b[1:] + n.Exp-- + } + // Strip trailing zeros + for len(b) > 0 && b[len(b)-1] == 0 { + b = b[:len(b)-1] + } + if len(b) == 0 { + n.Exp = 0 + } + n.Digits = b + return n +} + +func (d *Decimal) clear() { + b := d.Digits + if b == nil { + b = d.buf[:0] + } + *d = Decimal{} + d.Digits = b[:0] +} + +func (x *Decimal) String() string { + if x.NaN { + return "NaN" + } + var buf []byte + if x.Neg { + buf = append(buf, '-') + } + if x.Inf { + buf = append(buf, "Inf"...) + return string(buf) + } + switch { + case len(x.Digits) == 0: + buf = append(buf, '0') + case x.Exp <= 0: + // 0.00ddd + buf = append(buf, "0."...) + buf = appendZeros(buf, -int(x.Exp)) + buf = appendDigits(buf, x.Digits) + + case /* 0 < */ int(x.Exp) < len(x.Digits): + // dd.ddd + buf = appendDigits(buf, x.Digits[:x.Exp]) + buf = append(buf, '.') + buf = appendDigits(buf, x.Digits[x.Exp:]) + + default: // len(x.Digits) <= x.Exp + // ddd00 + buf = appendDigits(buf, x.Digits) + buf = appendZeros(buf, int(x.Exp)-len(x.Digits)) + } + return string(buf) +} + +func appendDigits(buf []byte, digits []byte) []byte { + for _, c := range digits { + buf = append(buf, c+'0') + } + return buf +} + +// appendZeros appends n 0 digits to buf and returns buf. +func appendZeros(buf []byte, n int) []byte { + for ; n > 0; n-- { + buf = append(buf, '0') + } + return buf +} + +func (d *digits) round(mode RoundingMode, n int) { + if n >= len(d.Digits) { + return + } + // Make rounding decision: The result mantissa is truncated ("rounded down") + // by default. Decide if we need to increment, or "round up", the (unsigned) + // mantissa. + inc := false + switch mode { + case ToNegativeInf: + inc = d.Neg + case ToPositiveInf: + inc = !d.Neg + case ToZero: + // nothing to do + case AwayFromZero: + inc = true + case ToNearestEven: + inc = d.Digits[n] > 5 || d.Digits[n] == 5 && + (len(d.Digits) > n+1 || n == 0 || d.Digits[n-1]&1 != 0) + case ToNearestAway: + inc = d.Digits[n] >= 5 + case ToNearestZero: + inc = d.Digits[n] > 5 || d.Digits[n] == 5 && len(d.Digits) > n+1 + default: + panic("unreachable") + } + if inc { + d.roundUp(n) + } else { + d.roundDown(n) + } +} + +// roundFloat rounds a floating point number. +func (r RoundingMode) roundFloat(x float64) float64 { + // Make rounding decision: The result mantissa is truncated ("rounded down") + // by default. Decide if we need to increment, or "round up", the (unsigned) + // mantissa. + abs := x + if x < 0 { + abs = -x + } + i, f := math.Modf(abs) + if f == 0.0 { + return x + } + inc := false + switch r { + case ToNegativeInf: + inc = x < 0 + case ToPositiveInf: + inc = x >= 0 + case ToZero: + // nothing to do + case AwayFromZero: + inc = true + case ToNearestEven: + // TODO: check overflow + inc = f > 0.5 || f == 0.5 && int64(i)&1 != 0 + case ToNearestAway: + inc = f >= 0.5 + case ToNearestZero: + inc = f > 0.5 + default: + panic("unreachable") + } + if inc { + i += 1 + } + if abs != x { + i = -i + } + return i +} + +func (x *digits) roundUp(n int) { + if n < 0 || n >= len(x.Digits) { + return // nothing to do + } + // find first digit < 9 + for n > 0 && x.Digits[n-1] >= 9 { + n-- + } + + if n == 0 { + // all digits are 9s => round up to 1 and update exponent + x.Digits[0] = 1 // ok since len(x.Digits) > n + x.Digits = x.Digits[:1] + x.Exp++ + return + } + x.Digits[n-1]++ + x.Digits = x.Digits[:n] + // x already trimmed +} + +func (x *digits) roundDown(n int) { + if n < 0 || n >= len(x.Digits) { + return // nothing to do + } + x.Digits = x.Digits[:n] + trim(x) +} + +// trim cuts off any trailing zeros from x's mantissa; +// they are meaningless for the value of x. +func trim(x *digits) { + i := len(x.Digits) + for i > 0 && x.Digits[i-1] == 0 { + i-- + } + x.Digits = x.Digits[:i] + if i == 0 { + x.Exp = 0 + } +} + +// A Converter converts a number into decimals according to the given rounding +// criteria. +type Converter interface { + Convert(d *Decimal, r RoundingContext) +} + +const ( + signed = true + unsigned = false +) + +// Convert converts the given number to the decimal representation using the +// supplied RoundingContext. +func (d *Decimal) Convert(r RoundingContext, number interface{}) { + switch f := number.(type) { + case Converter: + d.clear() + f.Convert(d, r) + case float32: + d.ConvertFloat(r, float64(f), 32) + case float64: + d.ConvertFloat(r, f, 64) + case int: + d.ConvertInt(r, signed, uint64(f)) + case int8: + d.ConvertInt(r, signed, uint64(f)) + case int16: + d.ConvertInt(r, signed, uint64(f)) + case int32: + d.ConvertInt(r, signed, uint64(f)) + case int64: + d.ConvertInt(r, signed, uint64(f)) + case uint: + d.ConvertInt(r, unsigned, uint64(f)) + case uint8: + d.ConvertInt(r, unsigned, uint64(f)) + case uint16: + d.ConvertInt(r, unsigned, uint64(f)) + case uint32: + d.ConvertInt(r, unsigned, uint64(f)) + case uint64: + d.ConvertInt(r, unsigned, f) + + default: + d.NaN = true + // TODO: + // case string: if produced by strconv, allows for easy arbitrary pos. + // case reflect.Value: + // case big.Float + // case big.Int + // case big.Rat? + // catch underlyings using reflect or will this already be done by the + // message package? + } +} + +// ConvertInt converts an integer to decimals. +func (d *Decimal) ConvertInt(r RoundingContext, signed bool, x uint64) { + if r.Increment > 0 { + // TODO: if uint64 is too large, fall back to float64 + if signed { + d.ConvertFloat(r, float64(int64(x)), 64) + } else { + d.ConvertFloat(r, float64(x), 64) + } + return + } + d.clear() + if signed && int64(x) < 0 { + x = uint64(-int64(x)) + d.Neg = true + } + d.fillIntDigits(x) + d.Exp = int32(len(d.Digits)) +} + +// ConvertFloat converts a floating point number to decimals. +func (d *Decimal) ConvertFloat(r RoundingContext, x float64, size int) { + d.clear() + if math.IsNaN(x) { + d.NaN = true + return + } + // Simple case: decimal notation + if r.Increment > 0 { + scale := int(r.IncrementScale) + mult := 1.0 + if scale >= len(scales) { + mult = math.Pow(10, float64(scale)) + } else { + mult = scales[scale] + } + // We multiply x instead of dividing inc as it gives less rounding + // issues. + x *= mult + x /= float64(r.Increment) + x = r.Mode.roundFloat(x) + x *= float64(r.Increment) + x /= mult + } + + abs := x + if x < 0 { + d.Neg = true + abs = -x + } + if math.IsInf(abs, 1) { + d.Inf = true + return + } + + // By default we get the exact decimal representation. + verb := byte('g') + prec := -1 + // As the strconv API does not return the rounding accuracy, we can only + // round using ToNearestEven. + if r.Mode == ToNearestEven { + if n := r.RoundSignificantDigits(); n >= 0 { + prec = n + } else if n = r.RoundFractionDigits(); n >= 0 { + prec = n + verb = 'f' + } + } else { + // TODO: At this point strconv's rounding is imprecise to the point that + // it is not usable for this purpose. + // See https://github.com/golang/go/issues/21714 + // If rounding is requested, we ask for a large number of digits and + // round from there to simulate rounding only once. + // Ideally we would have strconv export an AppendDigits that would take + // a rounding mode and/or return an accuracy. Something like this would + // work: + // AppendDigits(dst []byte, x float64, base, size, prec int) (digits []byte, exp, accuracy int) + hasPrec := r.RoundSignificantDigits() >= 0 + hasScale := r.RoundFractionDigits() >= 0 + if hasPrec || hasScale { + // prec is the number of mantissa bits plus some extra for safety. + // We need at least the number of mantissa bits as decimals to + // accurately represent the floating point without rounding, as each + // bit requires one more decimal to represent: 0.5, 0.25, 0.125, ... + prec = 60 + } + } + + b := strconv.AppendFloat(d.Digits[:0], abs, verb, prec, size) + i := 0 + k := 0 + beforeDot := 1 + for i < len(b) { + if c := b[i]; '0' <= c && c <= '9' { + b[k] = c - '0' + k++ + d.Exp += int32(beforeDot) + } else if c == '.' { + beforeDot = 0 + d.Exp = int32(k) + } else { + break + } + i++ + } + d.Digits = b[:k] + if i != len(b) { + i += len("e") + pSign := i + exp := 0 + for i++; i < len(b); i++ { + exp *= 10 + exp += int(b[i] - '0') + } + if b[pSign] == '-' { + exp = -exp + } + d.Exp = int32(exp) + 1 + } +} + +func (d *Decimal) fillIntDigits(x uint64) { + if cap(d.Digits) < maxIntDigits { + d.Digits = d.buf[:] + } else { + d.Digits = d.buf[:maxIntDigits] + } + i := 0 + for ; x > 0; x /= 10 { + d.Digits[i] = byte(x % 10) + i++ + } + d.Digits = d.Digits[:i] + for p := 0; p < i; p++ { + i-- + d.Digits[p], d.Digits[i] = d.Digits[i], d.Digits[p] + } +} + +var scales [70]float64 + +func init() { + x := 1.0 + for i := range scales { + scales[i] = x + x *= 10 + } +} diff --git a/vendor/golang.org/x/text/internal/number/format.go b/vendor/golang.org/x/text/internal/number/format.go new file mode 100644 index 00000000000..1aadcf40777 --- /dev/null +++ b/vendor/golang.org/x/text/internal/number/format.go @@ -0,0 +1,533 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package number + +import ( + "strconv" + "unicode/utf8" + + "golang.org/x/text/language" +) + +// TODO: +// - grouping of fractions +// - allow user-defined superscript notation (such as 4) +// - same for non-breaking spaces, like   + +// A VisibleDigits computes digits, comma placement and trailing zeros as they +// will be shown to the user. +type VisibleDigits interface { + Digits(buf []byte, t language.Tag, scale int) Digits + // TODO: Do we also need to add the verb or pass a format.State? +} + +// Formatting proceeds along the following lines: +// 0) Compose rounding information from format and context. +// 1) Convert a number into a Decimal. +// 2) Sanitize Decimal by adding trailing zeros, removing leading digits, and +// (non-increment) rounding. The Decimal that results from this is suitable +// for determining the plural form. +// 3) Render the Decimal in the localized form. + +// Formatter contains all the information needed to render a number. +type Formatter struct { + Pattern + Info +} + +func (f *Formatter) init(t language.Tag, index []uint8) { + f.Info = InfoFromTag(t) + f.Pattern = formats[index[tagToID(t)]] +} + +// InitPattern initializes a Formatter for the given Pattern. +func (f *Formatter) InitPattern(t language.Tag, pat *Pattern) { + f.Info = InfoFromTag(t) + f.Pattern = *pat +} + +// InitDecimal initializes a Formatter using the default Pattern for the given +// language. +func (f *Formatter) InitDecimal(t language.Tag) { + f.init(t, tagToDecimal) +} + +// InitScientific initializes a Formatter using the default Pattern for the +// given language. +func (f *Formatter) InitScientific(t language.Tag) { + f.init(t, tagToScientific) + f.Pattern.MinFractionDigits = 0 + f.Pattern.MaxFractionDigits = -1 +} + +// InitEngineering initializes a Formatter using the default Pattern for the +// given language. +func (f *Formatter) InitEngineering(t language.Tag) { + f.init(t, tagToScientific) + f.Pattern.MinFractionDigits = 0 + f.Pattern.MaxFractionDigits = -1 + f.Pattern.MaxIntegerDigits = 3 + f.Pattern.MinIntegerDigits = 1 +} + +// InitPercent initializes a Formatter using the default Pattern for the given +// language. +func (f *Formatter) InitPercent(t language.Tag) { + f.init(t, tagToPercent) +} + +// InitPerMille initializes a Formatter using the default Pattern for the given +// language. +func (f *Formatter) InitPerMille(t language.Tag) { + f.init(t, tagToPercent) + f.Pattern.DigitShift = 3 +} + +func (f *Formatter) Append(dst []byte, x interface{}) []byte { + var d Decimal + r := f.RoundingContext + d.Convert(r, x) + return f.Render(dst, FormatDigits(&d, r)) +} + +func FormatDigits(d *Decimal, r RoundingContext) Digits { + if r.isScientific() { + return scientificVisibleDigits(r, d) + } + return decimalVisibleDigits(r, d) +} + +func (f *Formatter) Format(dst []byte, d *Decimal) []byte { + return f.Render(dst, FormatDigits(d, f.RoundingContext)) +} + +func (f *Formatter) Render(dst []byte, d Digits) []byte { + var result []byte + var postPrefix, preSuffix int + if d.IsScientific { + result, postPrefix, preSuffix = appendScientific(dst, f, &d) + } else { + result, postPrefix, preSuffix = appendDecimal(dst, f, &d) + } + if f.PadRune == 0 { + return result + } + width := int(f.FormatWidth) + if count := utf8.RuneCount(result); count < width { + insertPos := 0 + switch f.Flags & PadMask { + case PadAfterPrefix: + insertPos = postPrefix + case PadBeforeSuffix: + insertPos = preSuffix + case PadAfterSuffix: + insertPos = len(result) + } + num := width - count + pad := [utf8.UTFMax]byte{' '} + sz := 1 + if r := f.PadRune; r != 0 { + sz = utf8.EncodeRune(pad[:], r) + } + extra := sz * num + if n := len(result) + extra; n < cap(result) { + result = result[:n] + copy(result[insertPos+extra:], result[insertPos:]) + } else { + buf := make([]byte, n) + copy(buf, result[:insertPos]) + copy(buf[insertPos+extra:], result[insertPos:]) + result = buf + } + for ; num > 0; num-- { + insertPos += copy(result[insertPos:], pad[:sz]) + } + } + return result +} + +// decimalVisibleDigits converts d according to the RoundingContext. Note that +// the exponent may change as a result of this operation. +func decimalVisibleDigits(r RoundingContext, d *Decimal) Digits { + if d.NaN || d.Inf { + return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}} + } + n := Digits{digits: d.normalize().digits} + + exp := n.Exp + exp += int32(r.DigitShift) + + // Cap integer digits. Remove *most-significant* digits. + if r.MaxIntegerDigits > 0 { + if p := int(exp) - int(r.MaxIntegerDigits); p > 0 { + if p > len(n.Digits) { + p = len(n.Digits) + } + if n.Digits = n.Digits[p:]; len(n.Digits) == 0 { + exp = 0 + } else { + exp -= int32(p) + } + // Strip leading zeros. + for len(n.Digits) > 0 && n.Digits[0] == 0 { + n.Digits = n.Digits[1:] + exp-- + } + } + } + + // Rounding if not already done by Convert. + p := len(n.Digits) + if maxSig := int(r.MaxSignificantDigits); maxSig > 0 { + p = maxSig + } + if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 { + if cap := int(exp) + maxFrac; cap < p { + p = int(exp) + maxFrac + } + if p < 0 { + p = 0 + } + } + n.round(r.Mode, p) + + // set End (trailing zeros) + n.End = int32(len(n.Digits)) + if n.End == 0 { + exp = 0 + if r.MinFractionDigits > 0 { + n.End = int32(r.MinFractionDigits) + } + if p := int32(r.MinSignificantDigits) - 1; p > n.End { + n.End = p + } + } else { + if end := exp + int32(r.MinFractionDigits); end > n.End { + n.End = end + } + if n.End < int32(r.MinSignificantDigits) { + n.End = int32(r.MinSignificantDigits) + } + } + n.Exp = exp + return n +} + +// appendDecimal appends a formatted number to dst. It returns two possible +// insertion points for padding. +func appendDecimal(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) { + if dst, ok := f.renderSpecial(dst, n); ok { + return dst, 0, len(dst) + } + digits := n.Digits + exp := n.Exp + + // Split in integer and fraction part. + var intDigits, fracDigits []byte + numInt := 0 + numFrac := int(n.End - n.Exp) + if exp > 0 { + numInt = int(exp) + if int(exp) >= len(digits) { // ddddd | ddddd00 + intDigits = digits + } else { // ddd.dd + intDigits = digits[:exp] + fracDigits = digits[exp:] + } + } else { + fracDigits = digits + } + + neg := n.Neg + affix, suffix := f.getAffixes(neg) + dst = appendAffix(dst, f, affix, neg) + savedLen := len(dst) + + minInt := int(f.MinIntegerDigits) + if minInt == 0 && f.MinSignificantDigits > 0 { + minInt = 1 + } + // add leading zeros + for i := minInt; i > numInt; i-- { + dst = f.AppendDigit(dst, 0) + if f.needsSep(i) { + dst = append(dst, f.Symbol(SymGroup)...) + } + } + i := 0 + for ; i < len(intDigits); i++ { + dst = f.AppendDigit(dst, intDigits[i]) + if f.needsSep(numInt - i) { + dst = append(dst, f.Symbol(SymGroup)...) + } + } + for ; i < numInt; i++ { + dst = f.AppendDigit(dst, 0) + if f.needsSep(numInt - i) { + dst = append(dst, f.Symbol(SymGroup)...) + } + } + + if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 { + dst = append(dst, f.Symbol(SymDecimal)...) + } + // Add trailing zeros + i = 0 + for n := -int(n.Exp); i < n; i++ { + dst = f.AppendDigit(dst, 0) + } + for _, d := range fracDigits { + i++ + dst = f.AppendDigit(dst, d) + } + for ; i < numFrac; i++ { + dst = f.AppendDigit(dst, 0) + } + return appendAffix(dst, f, suffix, neg), savedLen, len(dst) +} + +func scientificVisibleDigits(r RoundingContext, d *Decimal) Digits { + if d.NaN || d.Inf { + return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}} + } + n := Digits{digits: d.normalize().digits, IsScientific: true} + + // Normalize to have at least one digit. This simplifies engineering + // notation. + if len(n.Digits) == 0 { + n.Digits = append(n.Digits, 0) + n.Exp = 1 + } + + // Significant digits are transformed by the parser for scientific notation + // and do not need to be handled here. + maxInt, numInt := int(r.MaxIntegerDigits), int(r.MinIntegerDigits) + if numInt == 0 { + numInt = 1 + } + + // If a maximum number of integers is specified, the minimum must be 1 + // and the exponent is grouped by this number (e.g. for engineering) + if maxInt > numInt { + // Correct the exponent to reflect a single integer digit. + numInt = 1 + // engineering + // 0.01234 ([12345]e-1) -> 1.2345e-2 12.345e-3 + // 12345 ([12345]e+5) -> 1.2345e4 12.345e3 + d := int(n.Exp-1) % maxInt + if d < 0 { + d += maxInt + } + numInt += d + } + + p := len(n.Digits) + if maxSig := int(r.MaxSignificantDigits); maxSig > 0 { + p = maxSig + } + if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 && numInt+maxFrac < p { + p = numInt + maxFrac + } + n.round(r.Mode, p) + + n.Comma = uint8(numInt) + n.End = int32(len(n.Digits)) + if minSig := int32(r.MinFractionDigits) + int32(numInt); n.End < minSig { + n.End = minSig + } + return n +} + +// appendScientific appends a formatted number to dst. It returns two possible +// insertion points for padding. +func appendScientific(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) { + if dst, ok := f.renderSpecial(dst, n); ok { + return dst, 0, 0 + } + digits := n.Digits + numInt := int(n.Comma) + numFrac := int(n.End) - int(n.Comma) + + var intDigits, fracDigits []byte + if numInt <= len(digits) { + intDigits = digits[:numInt] + fracDigits = digits[numInt:] + } else { + intDigits = digits + } + neg := n.Neg + affix, suffix := f.getAffixes(neg) + dst = appendAffix(dst, f, affix, neg) + savedLen := len(dst) + + i := 0 + for ; i < len(intDigits); i++ { + dst = f.AppendDigit(dst, intDigits[i]) + if f.needsSep(numInt - i) { + dst = append(dst, f.Symbol(SymGroup)...) + } + } + for ; i < numInt; i++ { + dst = f.AppendDigit(dst, 0) + if f.needsSep(numInt - i) { + dst = append(dst, f.Symbol(SymGroup)...) + } + } + + if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 { + dst = append(dst, f.Symbol(SymDecimal)...) + } + i = 0 + for ; i < len(fracDigits); i++ { + dst = f.AppendDigit(dst, fracDigits[i]) + } + for ; i < numFrac; i++ { + dst = f.AppendDigit(dst, 0) + } + + // exp + buf := [12]byte{} + // TODO: use exponential if superscripting is not available (no Latin + // numbers or no tags) and use exponential in all other cases. + exp := n.Exp - int32(n.Comma) + exponential := f.Symbol(SymExponential) + if exponential == "E" { + dst = append(dst, f.Symbol(SymSuperscriptingExponent)...) + dst = f.AppendDigit(dst, 1) + dst = f.AppendDigit(dst, 0) + switch { + case exp < 0: + dst = append(dst, superMinus...) + exp = -exp + case f.Flags&AlwaysExpSign != 0: + dst = append(dst, superPlus...) + } + b = strconv.AppendUint(buf[:0], uint64(exp), 10) + for i := len(b); i < int(f.MinExponentDigits); i++ { + dst = append(dst, superDigits[0]...) + } + for _, c := range b { + dst = append(dst, superDigits[c-'0']...) + } + } else { + dst = append(dst, exponential...) + switch { + case exp < 0: + dst = append(dst, f.Symbol(SymMinusSign)...) + exp = -exp + case f.Flags&AlwaysExpSign != 0: + dst = append(dst, f.Symbol(SymPlusSign)...) + } + b = strconv.AppendUint(buf[:0], uint64(exp), 10) + for i := len(b); i < int(f.MinExponentDigits); i++ { + dst = f.AppendDigit(dst, 0) + } + for _, c := range b { + dst = f.AppendDigit(dst, c-'0') + } + } + return appendAffix(dst, f, suffix, neg), savedLen, len(dst) +} + +const ( + superMinus = "\u207B" // SUPERSCRIPT HYPHEN-MINUS + superPlus = "\u207A" // SUPERSCRIPT PLUS SIGN +) + +var ( + // Note: the digits are not sequential!!! + superDigits = []string{ + "\u2070", // SUPERSCRIPT DIGIT ZERO + "\u00B9", // SUPERSCRIPT DIGIT ONE + "\u00B2", // SUPERSCRIPT DIGIT TWO + "\u00B3", // SUPERSCRIPT DIGIT THREE + "\u2074", // SUPERSCRIPT DIGIT FOUR + "\u2075", // SUPERSCRIPT DIGIT FIVE + "\u2076", // SUPERSCRIPT DIGIT SIX + "\u2077", // SUPERSCRIPT DIGIT SEVEN + "\u2078", // SUPERSCRIPT DIGIT EIGHT + "\u2079", // SUPERSCRIPT DIGIT NINE + } +) + +func (f *Formatter) getAffixes(neg bool) (affix, suffix string) { + str := f.Affix + if str != "" { + if f.NegOffset > 0 { + if neg { + str = str[f.NegOffset:] + } else { + str = str[:f.NegOffset] + } + } + sufStart := 1 + str[0] + affix = str[1:sufStart] + suffix = str[sufStart+1:] + } + // TODO: introduce a NeedNeg sign to indicate if the left pattern already + // has a sign marked? + if f.NegOffset == 0 && (neg || f.Flags&AlwaysSign != 0) { + affix = "-" + affix + } + return affix, suffix +} + +func (f *Formatter) renderSpecial(dst []byte, d *Digits) (b []byte, ok bool) { + if d.NaN { + return fmtNaN(dst, f), true + } + if d.Inf { + return fmtInfinite(dst, f, d), true + } + return dst, false +} + +func fmtNaN(dst []byte, f *Formatter) []byte { + return append(dst, f.Symbol(SymNan)...) +} + +func fmtInfinite(dst []byte, f *Formatter, d *Digits) []byte { + affix, suffix := f.getAffixes(d.Neg) + dst = appendAffix(dst, f, affix, d.Neg) + dst = append(dst, f.Symbol(SymInfinity)...) + dst = appendAffix(dst, f, suffix, d.Neg) + return dst +} + +func appendAffix(dst []byte, f *Formatter, affix string, neg bool) []byte { + quoting := false + escaping := false + for _, r := range affix { + switch { + case escaping: + // escaping occurs both inside and outside of quotes + dst = append(dst, string(r)...) + escaping = false + case r == '\\': + escaping = true + case r == '\'': + quoting = !quoting + case quoting: + dst = append(dst, string(r)...) + case r == '%': + if f.DigitShift == 3 { + dst = append(dst, f.Symbol(SymPerMille)...) + } else { + dst = append(dst, f.Symbol(SymPercentSign)...) + } + case r == '-' || r == '+': + if neg { + dst = append(dst, f.Symbol(SymMinusSign)...) + } else if f.Flags&ElideSign == 0 { + dst = append(dst, f.Symbol(SymPlusSign)...) + } else { + dst = append(dst, ' ') + } + default: + dst = append(dst, string(r)...) + } + } + return dst +} diff --git a/vendor/golang.org/x/text/internal/number/number.go b/vendor/golang.org/x/text/internal/number/number.go new file mode 100644 index 00000000000..e1d933c3f7e --- /dev/null +++ b/vendor/golang.org/x/text/internal/number/number.go @@ -0,0 +1,152 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go gen_common.go + +// Package number contains tools and data for formatting numbers. +package number + +import ( + "unicode/utf8" + + "golang.org/x/text/internal/language/compact" + "golang.org/x/text/language" +) + +// Info holds number formatting configuration data. +type Info struct { + system systemData // numbering system information + symIndex symOffset // index to symbols +} + +// InfoFromLangID returns a Info for the given compact language identifier and +// numbering system identifier. If system is the empty string, the default +// numbering system will be taken for that language. +func InfoFromLangID(compactIndex compact.ID, numberSystem string) Info { + p := langToDefaults[compactIndex] + // Lookup the entry for the language. + pSymIndex := symOffset(0) // Default: Latin, default symbols + system, ok := systemMap[numberSystem] + if !ok { + // Take the value for the default numbering system. This is by far the + // most common case as an alternative numbering system is hardly used. + if p&hasNonLatnMask == 0 { // Latn digits. + pSymIndex = p + } else { // Non-Latn or multiple numbering systems. + // Take the first entry from the alternatives list. + data := langToAlt[p&^hasNonLatnMask] + pSymIndex = data.symIndex + system = data.system + } + } else { + langIndex := compactIndex + ns := system + outerLoop: + for ; ; p = langToDefaults[langIndex] { + if p&hasNonLatnMask == 0 { + if ns == 0 { + // The index directly points to the symbol data. + pSymIndex = p + break + } + // Move to the parent and retry. + langIndex = langIndex.Parent() + } else { + // The index points to a list of symbol data indexes. + for _, e := range langToAlt[p&^hasNonLatnMask:] { + if e.compactTag != langIndex { + if langIndex == 0 { + // The CLDR root defines full symbol information for + // all numbering systems (even though mostly by + // means of aliases). Fall back to the default entry + // for Latn if there is no data for the numbering + // system of this language. + if ns == 0 { + break + } + // Fall back to Latin and start from the original + // language. See + // https://unicode.org/reports/tr35/#Locale_Inheritance. + ns = numLatn + langIndex = compactIndex + continue outerLoop + } + // Fall back to parent. + langIndex = langIndex.Parent() + } else if e.system == ns { + pSymIndex = e.symIndex + break outerLoop + } + } + } + } + } + if int(system) >= len(numSysData) { // algorithmic + // Will generate ASCII digits in case the user inadvertently calls + // WriteDigit or Digit on it. + d := numSysData[0] + d.id = system + return Info{ + system: d, + symIndex: pSymIndex, + } + } + return Info{ + system: numSysData[system], + symIndex: pSymIndex, + } +} + +// InfoFromTag returns a Info for the given language tag. +func InfoFromTag(t language.Tag) Info { + return InfoFromLangID(tagToID(t), t.TypeForKey("nu")) +} + +// IsDecimal reports if the numbering system can convert decimal to native +// symbols one-to-one. +func (n Info) IsDecimal() bool { + return int(n.system.id) < len(numSysData) +} + +// WriteDigit writes the UTF-8 sequence for n corresponding to the given ASCII +// digit to dst and reports the number of bytes written. dst must be large +// enough to hold the rune (can be up to utf8.UTFMax bytes). +func (n Info) WriteDigit(dst []byte, asciiDigit rune) int { + copy(dst, n.system.zero[:n.system.digitSize]) + dst[n.system.digitSize-1] += byte(asciiDigit - '0') + return int(n.system.digitSize) +} + +// AppendDigit appends the UTF-8 sequence for n corresponding to the given digit +// to dst and reports the number of bytes written. dst must be large enough to +// hold the rune (can be up to utf8.UTFMax bytes). +func (n Info) AppendDigit(dst []byte, digit byte) []byte { + dst = append(dst, n.system.zero[:n.system.digitSize]...) + dst[len(dst)-1] += digit + return dst +} + +// Digit returns the digit for the numbering system for the corresponding ASCII +// value. For example, ni.Digit('3') could return '三'. Note that the argument +// is the rune constant '3', which equals 51, not the integer constant 3. +func (n Info) Digit(asciiDigit rune) rune { + var x [utf8.UTFMax]byte + n.WriteDigit(x[:], asciiDigit) + r, _ := utf8.DecodeRune(x[:]) + return r +} + +// Symbol returns the string for the given symbol type. +func (n Info) Symbol(t SymbolType) string { + return symData.Elem(int(symIndex[n.symIndex][t])) +} + +func formatForLang(t language.Tag, index []byte) *Pattern { + return &formats[index[tagToID(t)]] +} + +func tagToID(t language.Tag) compact.ID { + id, _ := compact.RegionalID(compact.Tag(t)) + return id +} diff --git a/vendor/golang.org/x/text/internal/number/pattern.go b/vendor/golang.org/x/text/internal/number/pattern.go new file mode 100644 index 00000000000..06e59559a96 --- /dev/null +++ b/vendor/golang.org/x/text/internal/number/pattern.go @@ -0,0 +1,485 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package number + +import ( + "errors" + "unicode/utf8" +) + +// This file contains a parser for the CLDR number patterns as described in +// https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns. +// +// The following BNF is derived from this standard. +// +// pattern := subpattern (';' subpattern)? +// subpattern := affix? number exponent? affix? +// number := decimal | sigDigits +// decimal := '#'* '0'* ('.' fraction)? | '#' | '0' +// fraction := '0'* '#'* +// sigDigits := '#'* '@' '@'* '#'* +// exponent := 'E' '+'? '0'* '0' +// padSpec := '*' \L +// +// Notes: +// - An affix pattern may contain any runes, but runes with special meaning +// should be escaped. +// - Sequences of digits, '#', and '@' in decimal and sigDigits may have +// interstitial commas. + +// TODO: replace special characters in affixes (-, +, ¤) with control codes. + +// Pattern holds information for formatting numbers. It is designed to hold +// information from CLDR number patterns. +// +// This pattern is precompiled for all patterns for all languages. Even though +// the number of patterns is not very large, we want to keep this small. +// +// This type is only intended for internal use. +type Pattern struct { + RoundingContext + + Affix string // includes prefix and suffix. First byte is prefix length. + Offset uint16 // Offset into Affix for prefix and suffix + NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0. + PadRune rune + FormatWidth uint16 + + GroupingSize [2]uint8 + Flags PatternFlag +} + +// A RoundingContext indicates how a number should be converted to digits. +// It contains all information needed to determine the "visible digits" as +// required by the pluralization rules. +type RoundingContext struct { + // TODO: unify these two fields so that there is a more unambiguous meaning + // of how precision is handled. + MaxSignificantDigits int16 // -1 is unlimited + MaxFractionDigits int16 // -1 is unlimited + + Increment uint32 + IncrementScale uint8 // May differ from printed scale. + + Mode RoundingMode + + DigitShift uint8 // Number of decimals to shift. Used for % and ‰. + + // Number of digits. + MinIntegerDigits uint8 + + MaxIntegerDigits uint8 + MinFractionDigits uint8 + MinSignificantDigits uint8 + + MinExponentDigits uint8 +} + +// RoundSignificantDigits returns the number of significant digits an +// implementation of Convert may round to or n < 0 if there is no maximum or +// a maximum is not recommended. +func (r *RoundingContext) RoundSignificantDigits() (n int) { + if r.MaxFractionDigits == 0 && r.MaxSignificantDigits > 0 { + return int(r.MaxSignificantDigits) + } else if r.isScientific() && r.MaxIntegerDigits == 1 { + if r.MaxSignificantDigits == 0 || + int(r.MaxFractionDigits+1) == int(r.MaxSignificantDigits) { + // Note: don't add DigitShift: it is only used for decimals. + return int(r.MaxFractionDigits) + 1 + } + } + return -1 +} + +// RoundFractionDigits returns the number of fraction digits an implementation +// of Convert may round to or n < 0 if there is no maximum or a maximum is not +// recommended. +func (r *RoundingContext) RoundFractionDigits() (n int) { + if r.MinExponentDigits == 0 && + r.MaxSignificantDigits == 0 && + r.MaxFractionDigits >= 0 { + return int(r.MaxFractionDigits) + int(r.DigitShift) + } + return -1 +} + +// SetScale fixes the RoundingContext to a fixed number of fraction digits. +func (r *RoundingContext) SetScale(scale int) { + r.MinFractionDigits = uint8(scale) + r.MaxFractionDigits = int16(scale) +} + +func (r *RoundingContext) SetPrecision(prec int) { + r.MaxSignificantDigits = int16(prec) +} + +func (r *RoundingContext) isScientific() bool { + return r.MinExponentDigits > 0 +} + +func (f *Pattern) needsSep(pos int) bool { + p := pos - 1 + size := int(f.GroupingSize[0]) + if size == 0 || p == 0 { + return false + } + if p == size { + return true + } + if p -= size; p < 0 { + return false + } + // TODO: make second groupingsize the same as first if 0 so that we can + // avoid this check. + if x := int(f.GroupingSize[1]); x != 0 { + size = x + } + return p%size == 0 +} + +// A PatternFlag is a bit mask for the flag field of a Pattern. +type PatternFlag uint8 + +const ( + AlwaysSign PatternFlag = 1 << iota + ElideSign // Use space instead of plus sign. AlwaysSign must be true. + AlwaysExpSign + AlwaysDecimalSeparator + ParenthesisForNegative // Common pattern. Saves space. + + PadAfterNumber + PadAfterAffix + + PadBeforePrefix = 0 // Default + PadAfterPrefix = PadAfterAffix + PadBeforeSuffix = PadAfterNumber + PadAfterSuffix = PadAfterNumber | PadAfterAffix + PadMask = PadAfterNumber | PadAfterAffix +) + +type parser struct { + *Pattern + + leadingSharps int + + pos int + err error + doNotTerminate bool + groupingCount uint + hasGroup bool + buf []byte +} + +func (p *parser) setError(err error) { + if p.err == nil { + p.err = err + } +} + +func (p *parser) updateGrouping() { + if p.hasGroup && + 0 < p.groupingCount && p.groupingCount < 255 { + p.GroupingSize[1] = p.GroupingSize[0] + p.GroupingSize[0] = uint8(p.groupingCount) + } + p.groupingCount = 0 + p.hasGroup = true +} + +var ( + // TODO: more sensible and localizeable error messages. + errMultiplePadSpecifiers = errors.New("format: pattern has multiple pad specifiers") + errInvalidPadSpecifier = errors.New("format: invalid pad specifier") + errInvalidQuote = errors.New("format: invalid quote") + errAffixTooLarge = errors.New("format: prefix or suffix exceeds maximum UTF-8 length of 256 bytes") + errDuplicatePercentSign = errors.New("format: duplicate percent sign") + errDuplicatePermilleSign = errors.New("format: duplicate permille sign") + errUnexpectedEnd = errors.New("format: unexpected end of pattern") +) + +// ParsePattern extracts formatting information from a CLDR number pattern. +// +// See https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns. +func ParsePattern(s string) (f *Pattern, err error) { + p := parser{Pattern: &Pattern{}} + + s = p.parseSubPattern(s) + + if s != "" { + // Parse negative sub pattern. + if s[0] != ';' { + p.setError(errors.New("format: error parsing first sub pattern")) + return nil, p.err + } + neg := parser{Pattern: &Pattern{}} // just for extracting the affixes. + s = neg.parseSubPattern(s[len(";"):]) + p.NegOffset = uint16(len(p.buf)) + p.buf = append(p.buf, neg.buf...) + } + if s != "" { + p.setError(errors.New("format: spurious characters at end of pattern")) + } + if p.err != nil { + return nil, p.err + } + if affix := string(p.buf); affix == "\x00\x00" || affix == "\x00\x00\x00\x00" { + // No prefix or suffixes. + p.NegOffset = 0 + } else { + p.Affix = affix + } + if p.Increment == 0 { + p.IncrementScale = 0 + } + return p.Pattern, nil +} + +func (p *parser) parseSubPattern(s string) string { + s = p.parsePad(s, PadBeforePrefix) + s = p.parseAffix(s) + s = p.parsePad(s, PadAfterPrefix) + + s = p.parse(p.number, s) + p.updateGrouping() + + s = p.parsePad(s, PadBeforeSuffix) + s = p.parseAffix(s) + s = p.parsePad(s, PadAfterSuffix) + return s +} + +func (p *parser) parsePad(s string, f PatternFlag) (tail string) { + if len(s) >= 2 && s[0] == '*' { + r, sz := utf8.DecodeRuneInString(s[1:]) + if p.PadRune != 0 { + p.err = errMultiplePadSpecifiers + } else { + p.Flags |= f + p.PadRune = r + } + return s[1+sz:] + } + return s +} + +func (p *parser) parseAffix(s string) string { + x := len(p.buf) + p.buf = append(p.buf, 0) // placeholder for affix length + + s = p.parse(p.affix, s) + + n := len(p.buf) - x - 1 + if n > 0xFF { + p.setError(errAffixTooLarge) + } + p.buf[x] = uint8(n) + return s +} + +// state implements a state transition. It returns the new state. A state +// function may set an error on the parser or may simply return on an incorrect +// token and let the next phase fail. +type state func(r rune) state + +// parse repeatedly applies a state function on the given string until a +// termination condition is reached. +func (p *parser) parse(fn state, s string) (tail string) { + for i, r := range s { + p.doNotTerminate = false + if fn = fn(r); fn == nil || p.err != nil { + return s[i:] + } + p.FormatWidth++ + } + if p.doNotTerminate { + p.setError(errUnexpectedEnd) + } + return "" +} + +func (p *parser) affix(r rune) state { + switch r { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '#', '@', '.', '*', ',', ';': + return nil + case '\'': + p.FormatWidth-- + return p.escapeFirst + case '%': + if p.DigitShift != 0 { + p.setError(errDuplicatePercentSign) + } + p.DigitShift = 2 + case '\u2030': // ‰ Per mille + if p.DigitShift != 0 { + p.setError(errDuplicatePermilleSign) + } + p.DigitShift = 3 + // TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤ + } + p.buf = append(p.buf, string(r)...) + return p.affix +} + +func (p *parser) escapeFirst(r rune) state { + switch r { + case '\'': + p.buf = append(p.buf, "\\'"...) + return p.affix + default: + p.buf = append(p.buf, '\'') + p.buf = append(p.buf, string(r)...) + } + return p.escape +} + +func (p *parser) escape(r rune) state { + switch r { + case '\'': + p.FormatWidth-- + p.buf = append(p.buf, '\'') + return p.affix + default: + p.buf = append(p.buf, string(r)...) + } + return p.escape +} + +// number parses a number. The BNF says the integer part should always have +// a '0', but that does not appear to be the case according to the rest of the +// documentation. We will allow having only '#' numbers. +func (p *parser) number(r rune) state { + switch r { + case '#': + p.groupingCount++ + p.leadingSharps++ + case '@': + p.groupingCount++ + p.leadingSharps = 0 + p.MaxFractionDigits = -1 + return p.sigDigits(r) + case ',': + if p.leadingSharps == 0 { // no leading commas + return nil + } + p.updateGrouping() + case 'E': + p.MaxIntegerDigits = uint8(p.leadingSharps) + return p.exponent + case '.': // allow ".##" etc. + p.updateGrouping() + return p.fraction + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return p.integer(r) + default: + return nil + } + return p.number +} + +func (p *parser) integer(r rune) state { + if !('0' <= r && r <= '9') { + var next state + switch r { + case 'E': + if p.leadingSharps > 0 { + p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits + } + next = p.exponent + case '.': + next = p.fraction + case ',': + next = p.integer + } + p.updateGrouping() + return next + } + p.Increment = p.Increment*10 + uint32(r-'0') + p.groupingCount++ + p.MinIntegerDigits++ + return p.integer +} + +func (p *parser) sigDigits(r rune) state { + switch r { + case '@': + p.groupingCount++ + p.MaxSignificantDigits++ + p.MinSignificantDigits++ + case '#': + return p.sigDigitsFinal(r) + case 'E': + p.updateGrouping() + return p.normalizeSigDigitsWithExponent() + default: + p.updateGrouping() + return nil + } + return p.sigDigits +} + +func (p *parser) sigDigitsFinal(r rune) state { + switch r { + case '#': + p.groupingCount++ + p.MaxSignificantDigits++ + case 'E': + p.updateGrouping() + return p.normalizeSigDigitsWithExponent() + default: + p.updateGrouping() + return nil + } + return p.sigDigitsFinal +} + +func (p *parser) normalizeSigDigitsWithExponent() state { + p.MinIntegerDigits, p.MaxIntegerDigits = 1, 1 + p.MinFractionDigits = p.MinSignificantDigits - 1 + p.MaxFractionDigits = p.MaxSignificantDigits - 1 + p.MinSignificantDigits, p.MaxSignificantDigits = 0, 0 + return p.exponent +} + +func (p *parser) fraction(r rune) state { + switch r { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + p.Increment = p.Increment*10 + uint32(r-'0') + p.IncrementScale++ + p.MinFractionDigits++ + p.MaxFractionDigits++ + case '#': + p.MaxFractionDigits++ + case 'E': + if p.leadingSharps > 0 { + p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits + } + return p.exponent + default: + return nil + } + return p.fraction +} + +func (p *parser) exponent(r rune) state { + switch r { + case '+': + // Set mode and check it wasn't already set. + if p.Flags&AlwaysExpSign != 0 || p.MinExponentDigits > 0 { + break + } + p.Flags |= AlwaysExpSign + p.doNotTerminate = true + return p.exponent + case '0': + p.MinExponentDigits++ + return p.exponent + } + // termination condition + if p.MinExponentDigits == 0 { + p.setError(errors.New("format: need at least one digit")) + } + return nil +} diff --git a/vendor/golang.org/x/text/internal/number/roundingmode_string.go b/vendor/golang.org/x/text/internal/number/roundingmode_string.go new file mode 100644 index 00000000000..bcc22471db8 --- /dev/null +++ b/vendor/golang.org/x/text/internal/number/roundingmode_string.go @@ -0,0 +1,30 @@ +// Code generated by "stringer -type RoundingMode"; DO NOT EDIT. + +package number + +import "strconv" + +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[ToNearestEven-0] + _ = x[ToNearestZero-1] + _ = x[ToNearestAway-2] + _ = x[ToPositiveInf-3] + _ = x[ToNegativeInf-4] + _ = x[ToZero-5] + _ = x[AwayFromZero-6] + _ = x[numModes-7] +} + +const _RoundingMode_name = "ToNearestEvenToNearestZeroToNearestAwayToPositiveInfToNegativeInfToZeroAwayFromZeronumModes" + +var _RoundingMode_index = [...]uint8{0, 13, 26, 39, 52, 65, 71, 83, 91} + +func (i RoundingMode) String() string { + if i >= RoundingMode(len(_RoundingMode_index)-1) { + return "RoundingMode(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]] +} diff --git a/vendor/golang.org/x/text/internal/number/tables.go b/vendor/golang.org/x/text/internal/number/tables.go new file mode 100644 index 00000000000..8efce81b562 --- /dev/null +++ b/vendor/golang.org/x/text/internal/number/tables.go @@ -0,0 +1,1219 @@ +// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. + +package number + +import "golang.org/x/text/internal/stringset" + +// CLDRVersion is the CLDR version from which the tables in this package are derived. +const CLDRVersion = "32" + +var numSysData = []systemData{ // 59 elements + 0: {id: 0x0, digitSize: 0x1, zero: [4]uint8{0x30, 0x0, 0x0, 0x0}}, + 1: {id: 0x1, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9e, 0xa5, 0x90}}, + 2: {id: 0x2, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x9c, 0xb0}}, + 3: {id: 0x3, digitSize: 0x2, zero: [4]uint8{0xd9, 0xa0, 0x0, 0x0}}, + 4: {id: 0x4, digitSize: 0x2, zero: [4]uint8{0xdb, 0xb0, 0x0, 0x0}}, + 5: {id: 0x5, digitSize: 0x3, zero: [4]uint8{0xe1, 0xad, 0x90, 0x0}}, + 6: {id: 0x6, digitSize: 0x3, zero: [4]uint8{0xe0, 0xa7, 0xa6, 0x0}}, + 7: {id: 0x7, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0xb1, 0x90}}, + 8: {id: 0x8, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x81, 0xa6}}, + 9: {id: 0x9, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x84, 0xb6}}, + 10: {id: 0xa, digitSize: 0x3, zero: [4]uint8{0xea, 0xa9, 0x90, 0x0}}, + 11: {id: 0xb, digitSize: 0x3, zero: [4]uint8{0xe0, 0xa5, 0xa6, 0x0}}, + 12: {id: 0xc, digitSize: 0x3, zero: [4]uint8{0xef, 0xbc, 0x90, 0x0}}, + 13: {id: 0xd, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0xb5, 0x90}}, + 14: {id: 0xe, digitSize: 0x3, zero: [4]uint8{0xe0, 0xab, 0xa6, 0x0}}, + 15: {id: 0xf, digitSize: 0x3, zero: [4]uint8{0xe0, 0xa9, 0xa6, 0x0}}, + 16: {id: 0x10, digitSize: 0x4, zero: [4]uint8{0xf0, 0x96, 0xad, 0x90}}, + 17: {id: 0x11, digitSize: 0x3, zero: [4]uint8{0xea, 0xa7, 0x90, 0x0}}, + 18: {id: 0x12, digitSize: 0x3, zero: [4]uint8{0xea, 0xa4, 0x80, 0x0}}, + 19: {id: 0x13, digitSize: 0x3, zero: [4]uint8{0xe1, 0x9f, 0xa0, 0x0}}, + 20: {id: 0x14, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb3, 0xa6, 0x0}}, + 21: {id: 0x15, digitSize: 0x3, zero: [4]uint8{0xe1, 0xaa, 0x80, 0x0}}, + 22: {id: 0x16, digitSize: 0x3, zero: [4]uint8{0xe1, 0xaa, 0x90, 0x0}}, + 23: {id: 0x17, digitSize: 0x3, zero: [4]uint8{0xe0, 0xbb, 0x90, 0x0}}, + 24: {id: 0x18, digitSize: 0x3, zero: [4]uint8{0xe1, 0xb1, 0x80, 0x0}}, + 25: {id: 0x19, digitSize: 0x3, zero: [4]uint8{0xe1, 0xa5, 0x86, 0x0}}, + 26: {id: 0x1a, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0x8e}}, + 27: {id: 0x1b, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0x98}}, + 28: {id: 0x1c, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0xb6}}, + 29: {id: 0x1d, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0xac}}, + 30: {id: 0x1e, digitSize: 0x4, zero: [4]uint8{0xf0, 0x9d, 0x9f, 0xa2}}, + 31: {id: 0x1f, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb5, 0xa6, 0x0}}, + 32: {id: 0x20, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x99, 0x90}}, + 33: {id: 0x21, digitSize: 0x3, zero: [4]uint8{0xe1, 0xa0, 0x90, 0x0}}, + 34: {id: 0x22, digitSize: 0x4, zero: [4]uint8{0xf0, 0x96, 0xa9, 0xa0}}, + 35: {id: 0x23, digitSize: 0x3, zero: [4]uint8{0xea, 0xaf, 0xb0, 0x0}}, + 36: {id: 0x24, digitSize: 0x3, zero: [4]uint8{0xe1, 0x81, 0x80, 0x0}}, + 37: {id: 0x25, digitSize: 0x3, zero: [4]uint8{0xe1, 0x82, 0x90, 0x0}}, + 38: {id: 0x26, digitSize: 0x3, zero: [4]uint8{0xea, 0xa7, 0xb0, 0x0}}, + 39: {id: 0x27, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x91, 0x90}}, + 40: {id: 0x28, digitSize: 0x2, zero: [4]uint8{0xdf, 0x80, 0x0, 0x0}}, + 41: {id: 0x29, digitSize: 0x3, zero: [4]uint8{0xe1, 0xb1, 0x90, 0x0}}, + 42: {id: 0x2a, digitSize: 0x3, zero: [4]uint8{0xe0, 0xad, 0xa6, 0x0}}, + 43: {id: 0x2b, digitSize: 0x4, zero: [4]uint8{0xf0, 0x90, 0x92, 0xa0}}, + 44: {id: 0x2c, digitSize: 0x3, zero: [4]uint8{0xea, 0xa3, 0x90, 0x0}}, + 45: {id: 0x2d, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x87, 0x90}}, + 46: {id: 0x2e, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x8b, 0xb0}}, + 47: {id: 0x2f, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb7, 0xa6, 0x0}}, + 48: {id: 0x30, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x83, 0xb0}}, + 49: {id: 0x31, digitSize: 0x3, zero: [4]uint8{0xe1, 0xae, 0xb0, 0x0}}, + 50: {id: 0x32, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x9b, 0x80}}, + 51: {id: 0x33, digitSize: 0x3, zero: [4]uint8{0xe1, 0xa7, 0x90, 0x0}}, + 52: {id: 0x34, digitSize: 0x3, zero: [4]uint8{0xe0, 0xaf, 0xa6, 0x0}}, + 53: {id: 0x35, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb1, 0xa6, 0x0}}, + 54: {id: 0x36, digitSize: 0x3, zero: [4]uint8{0xe0, 0xb9, 0x90, 0x0}}, + 55: {id: 0x37, digitSize: 0x3, zero: [4]uint8{0xe0, 0xbc, 0xa0, 0x0}}, + 56: {id: 0x38, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0x93, 0x90}}, + 57: {id: 0x39, digitSize: 0x3, zero: [4]uint8{0xea, 0x98, 0xa0, 0x0}}, + 58: {id: 0x3a, digitSize: 0x4, zero: [4]uint8{0xf0, 0x91, 0xa3, 0xa0}}, +} // Size: 378 bytes + +const ( + numAdlm = 0x1 + numAhom = 0x2 + numArab = 0x3 + numArabext = 0x4 + numArmn = 0x3b + numArmnlow = 0x3c + numBali = 0x5 + numBeng = 0x6 + numBhks = 0x7 + numBrah = 0x8 + numCakm = 0x9 + numCham = 0xa + numCyrl = 0x3d + numDeva = 0xb + numEthi = 0x3e + numFullwide = 0xc + numGeor = 0x3f + numGonm = 0xd + numGrek = 0x40 + numGreklow = 0x41 + numGujr = 0xe + numGuru = 0xf + numHanidays = 0x42 + numHanidec = 0x43 + numHans = 0x44 + numHansfin = 0x45 + numHant = 0x46 + numHantfin = 0x47 + numHebr = 0x48 + numHmng = 0x10 + numJava = 0x11 + numJpan = 0x49 + numJpanfin = 0x4a + numKali = 0x12 + numKhmr = 0x13 + numKnda = 0x14 + numLana = 0x15 + numLanatham = 0x16 + numLaoo = 0x17 + numLatn = 0x0 + numLepc = 0x18 + numLimb = 0x19 + numMathbold = 0x1a + numMathdbl = 0x1b + numMathmono = 0x1c + numMathsanb = 0x1d + numMathsans = 0x1e + numMlym = 0x1f + numModi = 0x20 + numMong = 0x21 + numMroo = 0x22 + numMtei = 0x23 + numMymr = 0x24 + numMymrshan = 0x25 + numMymrtlng = 0x26 + numNewa = 0x27 + numNkoo = 0x28 + numOlck = 0x29 + numOrya = 0x2a + numOsma = 0x2b + numRoman = 0x4b + numRomanlow = 0x4c + numSaur = 0x2c + numShrd = 0x2d + numSind = 0x2e + numSinh = 0x2f + numSora = 0x30 + numSund = 0x31 + numTakr = 0x32 + numTalu = 0x33 + numTaml = 0x4d + numTamldec = 0x34 + numTelu = 0x35 + numThai = 0x36 + numTibt = 0x37 + numTirh = 0x38 + numVaii = 0x39 + numWara = 0x3a + numNumberSystems +) + +var systemMap = map[string]system{ + "adlm": numAdlm, + "ahom": numAhom, + "arab": numArab, + "arabext": numArabext, + "armn": numArmn, + "armnlow": numArmnlow, + "bali": numBali, + "beng": numBeng, + "bhks": numBhks, + "brah": numBrah, + "cakm": numCakm, + "cham": numCham, + "cyrl": numCyrl, + "deva": numDeva, + "ethi": numEthi, + "fullwide": numFullwide, + "geor": numGeor, + "gonm": numGonm, + "grek": numGrek, + "greklow": numGreklow, + "gujr": numGujr, + "guru": numGuru, + "hanidays": numHanidays, + "hanidec": numHanidec, + "hans": numHans, + "hansfin": numHansfin, + "hant": numHant, + "hantfin": numHantfin, + "hebr": numHebr, + "hmng": numHmng, + "java": numJava, + "jpan": numJpan, + "jpanfin": numJpanfin, + "kali": numKali, + "khmr": numKhmr, + "knda": numKnda, + "lana": numLana, + "lanatham": numLanatham, + "laoo": numLaoo, + "latn": numLatn, + "lepc": numLepc, + "limb": numLimb, + "mathbold": numMathbold, + "mathdbl": numMathdbl, + "mathmono": numMathmono, + "mathsanb": numMathsanb, + "mathsans": numMathsans, + "mlym": numMlym, + "modi": numModi, + "mong": numMong, + "mroo": numMroo, + "mtei": numMtei, + "mymr": numMymr, + "mymrshan": numMymrshan, + "mymrtlng": numMymrtlng, + "newa": numNewa, + "nkoo": numNkoo, + "olck": numOlck, + "orya": numOrya, + "osma": numOsma, + "roman": numRoman, + "romanlow": numRomanlow, + "saur": numSaur, + "shrd": numShrd, + "sind": numSind, + "sinh": numSinh, + "sora": numSora, + "sund": numSund, + "takr": numTakr, + "talu": numTalu, + "taml": numTaml, + "tamldec": numTamldec, + "telu": numTelu, + "thai": numThai, + "tibt": numTibt, + "tirh": numTirh, + "vaii": numVaii, + "wara": numWara, +} + +var symIndex = [][12]uint8{ // 81 elements + 0: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 1: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 2: [12]uint8{0x0, 0x1, 0x2, 0xd, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0x10, 0xb}, + 3: [12]uint8{0x1, 0x0, 0x2, 0xd, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0x10, 0xb}, + 4: [12]uint8{0x0, 0x1, 0x2, 0x11, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0x10, 0xb}, + 5: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x12, 0xb}, + 6: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 7: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x13, 0xb}, + 8: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 9: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0}, + 10: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x14, 0x8, 0x9, 0xa, 0xb}, + 11: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x14, 0x8, 0x9, 0xa, 0xb}, + 12: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x14, 0x8, 0x9, 0xa, 0xb}, + 13: [12]uint8{0x0, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 14: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x16, 0xb}, + 15: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb}, + 16: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0x0}, + 17: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb}, + 18: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0}, + 19: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x18, 0x7, 0x8, 0x9, 0xa, 0xb}, + 20: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x19, 0x1a, 0xa, 0xb}, + 21: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 22: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0xa, 0xb}, + 23: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 24: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0x1d, 0xb}, + 25: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0x1e, 0x0}, + 26: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 27: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 28: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x1f, 0xb}, + 29: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 30: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x20, 0xb}, + 31: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x21, 0x7, 0x8, 0x9, 0x22, 0xb}, + 32: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x23, 0xb}, + 33: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x14, 0x8, 0x9, 0x24, 0xb}, + 34: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0x24, 0xb}, + 35: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x25, 0xb}, + 36: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb}, + 37: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb}, + 38: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb}, + 39: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x29, 0xb}, + 40: [12]uint8{0x1, 0x0, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 41: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2a, 0xb}, + 42: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2b, 0xb}, + 43: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x2c, 0x14, 0x8, 0x9, 0x24, 0xb}, + 44: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0}, + 45: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb}, + 46: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb}, + 47: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2d, 0x0}, + 48: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2e, 0xb}, + 49: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2f, 0xb}, + 50: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x30, 0x7, 0x8, 0x9, 0xa, 0xb}, + 51: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x31, 0xb}, + 52: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x32, 0xb}, + 53: [12]uint8{0x1, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb}, + 54: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x33, 0xb}, + 55: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x34, 0xb}, + 56: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb}, + 57: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x7, 0x3c, 0x9, 0x3d, 0xb}, + 58: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x3e, 0x3f, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb}, + 59: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x39, 0x3a, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb}, + 60: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x39, 0x40, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb}, + 61: [12]uint8{0x35, 0x36, 0x37, 0x41, 0x3e, 0x3f, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb}, + 62: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x3e, 0x3f, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0xb}, + 63: [12]uint8{0x35, 0xc, 0x37, 0x38, 0x39, 0x42, 0x3b, 0x7, 0x3c, 0x9, 0xa, 0x0}, + 64: [12]uint8{0x35, 0xc, 0x37, 0x38, 0x39, 0x42, 0x43, 0x7, 0x44, 0x9, 0x24, 0xb}, + 65: [12]uint8{0x35, 0x36, 0x37, 0x38, 0x39, 0x5, 0x3b, 0x7, 0x3c, 0x9, 0x33, 0xb}, + 66: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x45, 0x46, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35}, + 67: [12]uint8{0x35, 0x36, 0x37, 0x11, 0xe, 0x1c, 0x43, 0x7, 0x3c, 0x9, 0x1d, 0xb}, + 68: [12]uint8{0x35, 0x36, 0x37, 0x11, 0xe, 0x1c, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35}, + 69: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x45, 0x5, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35}, + 70: [12]uint8{0x1, 0xc, 0x37, 0x11, 0x45, 0x47, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x0}, + 71: [12]uint8{0x35, 0x1, 0x37, 0x11, 0x4, 0x5, 0x43, 0x7, 0x3c, 0x9, 0xa, 0x35}, + 72: [12]uint8{0x1, 0xc, 0x37, 0x11, 0x45, 0x47, 0x43, 0x7, 0x3c, 0x9, 0x24, 0xb}, + 73: [12]uint8{0x35, 0x36, 0x2, 0x3, 0x45, 0x46, 0x43, 0x7, 0x8, 0x9, 0xa, 0x35}, + 74: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x4, 0x5, 0x43, 0x7, 0x3c, 0x9, 0x31, 0x35}, + 75: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x4, 0x5, 0x43, 0x7, 0x3c, 0x9, 0x32, 0x35}, + 76: [12]uint8{0x35, 0x36, 0x37, 0x11, 0x48, 0x46, 0x43, 0x7, 0x3c, 0x9, 0x33, 0x35}, + 77: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x49}, + 78: [12]uint8{0x0, 0x1, 0x4a, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb}, + 79: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x4b, 0xb}, + 80: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x4c, 0x4d, 0xb}, +} // Size: 996 bytes + +var symData = stringset.Set{ + Data: "" + // Size: 599 bytes + ".,;%+-E׉∞NaN:\u00a0\u200e%\u200e\u200e+\u200e-ليس\u00a0رقمًا٪NDТерхьаш" + + "\u00a0дац·’mnne×10^0/00INF−\u200e−ناعددepälukuՈչԹარ\u00a0არის\u00a0რიცხვ" + + "იZMdMсан\u00a0емес¤¤¤сан\u00a0эмесບໍ່\u200bແມ່ນ\u200bໂຕ\u200bເລກNSဂဏန်" + + "းမဟုတ်သောННне\u00a0числочыыһыла\u00a0буотах·10^epilohosan\u00a0dälTFЕs" + + "on\u00a0emasҳақиқий\u00a0сон\u00a0эмас非數值非数值٫٬؛٪\u061c\u061c+\u061c-اس؉ل" + + "يس\u00a0رقم\u200f+\u200f-\u200f−٪\u200f\u061c−×۱۰^؉\u200f\u200e+\u200e" + + "\u200e-\u200e\u200e−\u200e+\u200e:၊ཨང་མེན་གྲངས་མེདཨང་མད", + Index: []uint16{ // 79 elements + // Entry 0 - 3F + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0009, 0x000c, 0x000f, 0x0012, 0x0013, 0x0015, 0x001c, 0x0020, + 0x0024, 0x0036, 0x0038, 0x003a, 0x0050, 0x0052, 0x0055, 0x0058, + 0x0059, 0x005e, 0x0062, 0x0065, 0x0068, 0x006e, 0x0078, 0x0080, + 0x0086, 0x00ae, 0x00af, 0x00b2, 0x00c2, 0x00c8, 0x00d8, 0x0105, + 0x0107, 0x012e, 0x0132, 0x0142, 0x015e, 0x0163, 0x016a, 0x0173, + 0x0175, 0x0177, 0x0180, 0x01a0, 0x01a9, 0x01b2, 0x01b4, 0x01b6, + 0x01b8, 0x01bc, 0x01bf, 0x01c2, 0x01c6, 0x01c8, 0x01d6, 0x01da, + // Entry 40 - 7F + 0x01de, 0x01e4, 0x01e9, 0x01ee, 0x01f5, 0x01fa, 0x0201, 0x0208, + 0x0211, 0x0215, 0x0218, 0x021b, 0x0230, 0x0248, 0x0257, + }, +} // Size: 797 bytes + +// langToDefaults maps a compact language index to the default numbering system +// and default symbol set +var langToDefaults = [775]symOffset{ + // Entry 0 - 3F + 0x8000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8003, 0x0002, 0x0002, 0x0002, 0x0002, 0x0003, + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, + 0x0003, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, 0x0004, + 0x0002, 0x0004, 0x0002, 0x0002, 0x0002, 0x0003, 0x0002, 0x0000, + 0x8005, 0x0000, 0x0000, 0x0000, 0x8006, 0x0005, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, + // Entry 40 - 7F + 0x8009, 0x0000, 0x0000, 0x800a, 0x0000, 0x0000, 0x800c, 0x0001, + 0x0000, 0x0000, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x800e, 0x0000, 0x0000, 0x0007, + 0x0007, 0x0000, 0x0000, 0x0000, 0x0000, 0x800f, 0x0008, 0x0008, + 0x8011, 0x0001, 0x0001, 0x0001, 0x803c, 0x0000, 0x0009, 0x0009, + 0x0009, 0x0000, 0x0000, 0x000a, 0x000b, 0x000a, 0x000c, 0x000a, + 0x000a, 0x000c, 0x000a, 0x000d, 0x000d, 0x000a, 0x000a, 0x0001, + 0x0001, 0x0000, 0x0001, 0x0001, 0x803f, 0x0000, 0x0000, 0x0000, + // Entry 80 - BF + 0x000e, 0x000e, 0x000e, 0x000f, 0x000f, 0x000f, 0x0000, 0x0000, + 0x0006, 0x0000, 0x0000, 0x0000, 0x000a, 0x0010, 0x0000, 0x0006, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0011, 0x0000, 0x000a, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000a, 0x0000, 0x0009, 0x0000, + 0x0000, 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + // Entry C0 - FF + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0013, 0x0000, + 0x0000, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0015, + 0x0015, 0x0006, 0x0000, 0x0006, 0x0006, 0x0000, 0x0000, 0x0006, + 0x0006, 0x0001, 0x0000, 0x0000, 0x0006, 0x0006, 0x0006, 0x0006, + // Entry 100 - 13F + 0x0000, 0x0000, 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, + 0x0000, 0x0006, 0x0000, 0x0000, 0x0006, 0x0006, 0x0016, 0x0016, + 0x0017, 0x0017, 0x0001, 0x0001, 0x8041, 0x0018, 0x0018, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0019, 0x0019, 0x0000, 0x0000, + 0x0017, 0x0017, 0x0017, 0x8044, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0006, 0x0006, 0x0001, 0x0001, 0x0001, 0x0001, + // Entry 140 - 17F + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, + 0x8047, 0x0000, 0x0006, 0x0006, 0x001a, 0x001a, 0x001a, 0x001a, + 0x804a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x804c, 0x001b, 0x0000, + 0x0000, 0x0006, 0x0006, 0x0006, 0x000a, 0x000a, 0x0001, 0x0001, + 0x001c, 0x001c, 0x0009, 0x0009, 0x804f, 0x0000, 0x0000, 0x0000, + // Entry 180 - 1BF + 0x0000, 0x0000, 0x8052, 0x0006, 0x0006, 0x001d, 0x0006, 0x0006, + 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x001e, 0x001f, + 0x001f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, + 0x0001, 0x000d, 0x000d, 0x0000, 0x0000, 0x0020, 0x0020, 0x0006, + 0x0006, 0x0021, 0x0021, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000, + 0x0000, 0x8054, 0x0000, 0x0000, 0x0000, 0x0000, 0x8056, 0x001b, + 0x0000, 0x0000, 0x0001, 0x0001, 0x0022, 0x0022, 0x0000, 0x0000, + // Entry 1C0 - 1FF + 0x0000, 0x0023, 0x0023, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0024, 0x0024, 0x8058, 0x0000, 0x0000, 0x0016, 0x0016, 0x0006, + 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0025, 0x0025, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000d, 0x000d, 0x0000, 0x0000, + 0x0006, 0x0006, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x805a, 0x0000, 0x0000, 0x0006, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, 0x805b, 0x0026, 0x805d, + // Entry 200 - 23F + 0x0000, 0x0000, 0x0000, 0x0000, 0x805e, 0x0015, 0x0015, 0x0000, + 0x0000, 0x0006, 0x0006, 0x0006, 0x8061, 0x0000, 0x0000, 0x8062, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0001, + 0x0001, 0x0015, 0x0015, 0x0006, 0x0006, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0027, 0x0027, 0x0027, 0x8065, 0x8067, + 0x001b, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, + 0x8069, 0x0028, 0x0006, 0x0001, 0x0006, 0x0001, 0x0001, 0x0001, + // Entry 240 - 27F + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, + 0x0006, 0x0000, 0x0000, 0x001a, 0x001a, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0000, 0x0000, 0x0029, 0x0029, 0x0029, 0x0029, + 0x0029, 0x0029, 0x0029, 0x0006, 0x0006, 0x0000, 0x0000, 0x002a, + 0x002a, 0x0000, 0x0000, 0x0000, 0x0000, 0x806b, 0x0000, 0x0000, + 0x002b, 0x002b, 0x002b, 0x002b, 0x0006, 0x0006, 0x000d, 0x000d, + 0x0006, 0x0006, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x002c, 0x002c, 0x002d, 0x002d, 0x002e, 0x002e, 0x0000, 0x0000, + // Entry 280 - 2BF + 0x0000, 0x002f, 0x002f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0000, 0x0000, 0x0000, 0x806d, 0x0022, 0x0022, + 0x0022, 0x0000, 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0030, 0x0030, 0x0000, 0x0000, 0x8071, 0x0031, 0x0006, + // Entry 2C0 - 2FF + 0x0006, 0x0006, 0x0000, 0x0001, 0x0001, 0x000d, 0x000d, 0x0001, + 0x0001, 0x0000, 0x0000, 0x0032, 0x0032, 0x8074, 0x8076, 0x001b, + 0x8077, 0x8079, 0x0028, 0x807b, 0x0034, 0x0033, 0x0033, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0035, 0x0035, 0x0006, 0x0006, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0036, 0x0037, 0x0037, 0x0036, 0x0036, 0x0001, + 0x0001, 0x807d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, + // Entry 300 - 33F + 0x0036, 0x0036, 0x0036, 0x0000, 0x0000, 0x0006, 0x0014, +} // Size: 1550 bytes + +// langToAlt is a list of numbering system and symbol set pairs, sorted and +// marked by compact language index. +var langToAlt = []altSymData{ // 131 elements + 1: {compactTag: 0x0, symIndex: 0x38, system: 0x3}, + 2: {compactTag: 0x0, symIndex: 0x42, system: 0x4}, + 3: {compactTag: 0xa, symIndex: 0x39, system: 0x3}, + 4: {compactTag: 0xa, symIndex: 0x2, system: 0x0}, + 5: {compactTag: 0x28, symIndex: 0x0, system: 0x6}, + 6: {compactTag: 0x2c, symIndex: 0x5, system: 0x0}, + 7: {compactTag: 0x2c, symIndex: 0x3a, system: 0x3}, + 8: {compactTag: 0x2c, symIndex: 0x42, system: 0x4}, + 9: {compactTag: 0x40, symIndex: 0x0, system: 0x6}, + 10: {compactTag: 0x43, symIndex: 0x0, system: 0x0}, + 11: {compactTag: 0x43, symIndex: 0x4f, system: 0x37}, + 12: {compactTag: 0x46, symIndex: 0x1, system: 0x0}, + 13: {compactTag: 0x46, symIndex: 0x38, system: 0x3}, + 14: {compactTag: 0x54, symIndex: 0x0, system: 0x9}, + 15: {compactTag: 0x5d, symIndex: 0x3a, system: 0x3}, + 16: {compactTag: 0x5d, symIndex: 0x8, system: 0x0}, + 17: {compactTag: 0x60, symIndex: 0x1, system: 0x0}, + 18: {compactTag: 0x60, symIndex: 0x38, system: 0x3}, + 19: {compactTag: 0x60, symIndex: 0x42, system: 0x4}, + 20: {compactTag: 0x60, symIndex: 0x0, system: 0x5}, + 21: {compactTag: 0x60, symIndex: 0x0, system: 0x6}, + 22: {compactTag: 0x60, symIndex: 0x0, system: 0x8}, + 23: {compactTag: 0x60, symIndex: 0x0, system: 0x9}, + 24: {compactTag: 0x60, symIndex: 0x0, system: 0xa}, + 25: {compactTag: 0x60, symIndex: 0x0, system: 0xb}, + 26: {compactTag: 0x60, symIndex: 0x0, system: 0xc}, + 27: {compactTag: 0x60, symIndex: 0x0, system: 0xd}, + 28: {compactTag: 0x60, symIndex: 0x0, system: 0xe}, + 29: {compactTag: 0x60, symIndex: 0x0, system: 0xf}, + 30: {compactTag: 0x60, symIndex: 0x0, system: 0x11}, + 31: {compactTag: 0x60, symIndex: 0x0, system: 0x12}, + 32: {compactTag: 0x60, symIndex: 0x0, system: 0x13}, + 33: {compactTag: 0x60, symIndex: 0x0, system: 0x14}, + 34: {compactTag: 0x60, symIndex: 0x0, system: 0x15}, + 35: {compactTag: 0x60, symIndex: 0x0, system: 0x16}, + 36: {compactTag: 0x60, symIndex: 0x0, system: 0x17}, + 37: {compactTag: 0x60, symIndex: 0x0, system: 0x18}, + 38: {compactTag: 0x60, symIndex: 0x0, system: 0x19}, + 39: {compactTag: 0x60, symIndex: 0x0, system: 0x1f}, + 40: {compactTag: 0x60, symIndex: 0x0, system: 0x21}, + 41: {compactTag: 0x60, symIndex: 0x0, system: 0x23}, + 42: {compactTag: 0x60, symIndex: 0x0, system: 0x24}, + 43: {compactTag: 0x60, symIndex: 0x0, system: 0x25}, + 44: {compactTag: 0x60, symIndex: 0x0, system: 0x28}, + 45: {compactTag: 0x60, symIndex: 0x0, system: 0x29}, + 46: {compactTag: 0x60, symIndex: 0x0, system: 0x2a}, + 47: {compactTag: 0x60, symIndex: 0x0, system: 0x2b}, + 48: {compactTag: 0x60, symIndex: 0x0, system: 0x2c}, + 49: {compactTag: 0x60, symIndex: 0x0, system: 0x2d}, + 50: {compactTag: 0x60, symIndex: 0x0, system: 0x30}, + 51: {compactTag: 0x60, symIndex: 0x0, system: 0x31}, + 52: {compactTag: 0x60, symIndex: 0x0, system: 0x32}, + 53: {compactTag: 0x60, symIndex: 0x0, system: 0x33}, + 54: {compactTag: 0x60, symIndex: 0x0, system: 0x34}, + 55: {compactTag: 0x60, symIndex: 0x0, system: 0x35}, + 56: {compactTag: 0x60, symIndex: 0x0, system: 0x36}, + 57: {compactTag: 0x60, symIndex: 0x0, system: 0x37}, + 58: {compactTag: 0x60, symIndex: 0x0, system: 0x39}, + 59: {compactTag: 0x60, symIndex: 0x0, system: 0x43}, + 60: {compactTag: 0x64, symIndex: 0x0, system: 0x0}, + 61: {compactTag: 0x64, symIndex: 0x38, system: 0x3}, + 62: {compactTag: 0x64, symIndex: 0x42, system: 0x4}, + 63: {compactTag: 0x7c, symIndex: 0x50, system: 0x37}, + 64: {compactTag: 0x7c, symIndex: 0x0, system: 0x0}, + 65: {compactTag: 0x114, symIndex: 0x43, system: 0x4}, + 66: {compactTag: 0x114, symIndex: 0x18, system: 0x0}, + 67: {compactTag: 0x114, symIndex: 0x3b, system: 0x3}, + 68: {compactTag: 0x123, symIndex: 0x1, system: 0x0}, + 69: {compactTag: 0x123, symIndex: 0x3c, system: 0x3}, + 70: {compactTag: 0x123, symIndex: 0x44, system: 0x4}, + 71: {compactTag: 0x158, symIndex: 0x0, system: 0x0}, + 72: {compactTag: 0x158, symIndex: 0x3b, system: 0x3}, + 73: {compactTag: 0x158, symIndex: 0x45, system: 0x4}, + 74: {compactTag: 0x160, symIndex: 0x0, system: 0x0}, + 75: {compactTag: 0x160, symIndex: 0x38, system: 0x3}, + 76: {compactTag: 0x16d, symIndex: 0x1b, system: 0x0}, + 77: {compactTag: 0x16d, symIndex: 0x0, system: 0x9}, + 78: {compactTag: 0x16d, symIndex: 0x0, system: 0xa}, + 79: {compactTag: 0x17c, symIndex: 0x0, system: 0x0}, + 80: {compactTag: 0x17c, symIndex: 0x3d, system: 0x3}, + 81: {compactTag: 0x17c, symIndex: 0x42, system: 0x4}, + 82: {compactTag: 0x182, symIndex: 0x6, system: 0x0}, + 83: {compactTag: 0x182, symIndex: 0x38, system: 0x3}, + 84: {compactTag: 0x1b1, symIndex: 0x0, system: 0x0}, + 85: {compactTag: 0x1b1, symIndex: 0x3e, system: 0x3}, + 86: {compactTag: 0x1b6, symIndex: 0x42, system: 0x4}, + 87: {compactTag: 0x1b6, symIndex: 0x1b, system: 0x0}, + 88: {compactTag: 0x1d2, symIndex: 0x42, system: 0x4}, + 89: {compactTag: 0x1d2, symIndex: 0x0, system: 0x0}, + 90: {compactTag: 0x1f3, symIndex: 0x0, system: 0xb}, + 91: {compactTag: 0x1fd, symIndex: 0x4e, system: 0x24}, + 92: {compactTag: 0x1fd, symIndex: 0x26, system: 0x0}, + 93: {compactTag: 0x1ff, symIndex: 0x42, system: 0x4}, + 94: {compactTag: 0x204, symIndex: 0x15, system: 0x0}, + 95: {compactTag: 0x204, symIndex: 0x3f, system: 0x3}, + 96: {compactTag: 0x204, symIndex: 0x46, system: 0x4}, + 97: {compactTag: 0x20c, symIndex: 0x0, system: 0xb}, + 98: {compactTag: 0x20f, symIndex: 0x6, system: 0x0}, + 99: {compactTag: 0x20f, symIndex: 0x38, system: 0x3}, + 100: {compactTag: 0x20f, symIndex: 0x42, system: 0x4}, + 101: {compactTag: 0x22e, symIndex: 0x0, system: 0x0}, + 102: {compactTag: 0x22e, symIndex: 0x47, system: 0x4}, + 103: {compactTag: 0x22f, symIndex: 0x42, system: 0x4}, + 104: {compactTag: 0x22f, symIndex: 0x1b, system: 0x0}, + 105: {compactTag: 0x238, symIndex: 0x42, system: 0x4}, + 106: {compactTag: 0x238, symIndex: 0x28, system: 0x0}, + 107: {compactTag: 0x265, symIndex: 0x38, system: 0x3}, + 108: {compactTag: 0x265, symIndex: 0x0, system: 0x0}, + 109: {compactTag: 0x29d, symIndex: 0x22, system: 0x0}, + 110: {compactTag: 0x29d, symIndex: 0x40, system: 0x3}, + 111: {compactTag: 0x29d, symIndex: 0x48, system: 0x4}, + 112: {compactTag: 0x29d, symIndex: 0x4d, system: 0xc}, + 113: {compactTag: 0x2bd, symIndex: 0x31, system: 0x0}, + 114: {compactTag: 0x2bd, symIndex: 0x3e, system: 0x3}, + 115: {compactTag: 0x2bd, symIndex: 0x42, system: 0x4}, + 116: {compactTag: 0x2cd, symIndex: 0x1b, system: 0x0}, + 117: {compactTag: 0x2cd, symIndex: 0x49, system: 0x4}, + 118: {compactTag: 0x2ce, symIndex: 0x49, system: 0x4}, + 119: {compactTag: 0x2d0, symIndex: 0x33, system: 0x0}, + 120: {compactTag: 0x2d0, symIndex: 0x4a, system: 0x4}, + 121: {compactTag: 0x2d1, symIndex: 0x42, system: 0x4}, + 122: {compactTag: 0x2d1, symIndex: 0x28, system: 0x0}, + 123: {compactTag: 0x2d3, symIndex: 0x34, system: 0x0}, + 124: {compactTag: 0x2d3, symIndex: 0x4b, system: 0x4}, + 125: {compactTag: 0x2f9, symIndex: 0x0, system: 0x0}, + 126: {compactTag: 0x2f9, symIndex: 0x38, system: 0x3}, + 127: {compactTag: 0x2f9, symIndex: 0x42, system: 0x4}, + 128: {compactTag: 0x2ff, symIndex: 0x36, system: 0x0}, + 129: {compactTag: 0x2ff, symIndex: 0x41, system: 0x3}, + 130: {compactTag: 0x2ff, symIndex: 0x4c, system: 0x4}, +} // Size: 810 bytes + +var tagToDecimal = []uint8{ // 775 elements + // Entry 0 - 3F + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 40 - 7F + 0x05, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01, + // Entry 80 - BF + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry C0 - FF + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 100 - 13F + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 140 - 17F + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, + 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 180 - 1BF + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x05, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 1C0 - 1FF + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, + 0x01, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 200 - 23F + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x05, 0x01, + 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 240 - 27F + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 280 - 2BF + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, + 0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 2C0 - 2FF + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + // Entry 300 - 33F + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, +} // Size: 799 bytes + +var tagToScientific = []uint8{ // 775 elements + // Entry 0 - 3F + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 40 - 7F + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 80 - BF + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry C0 - FF + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 100 - 13F + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 140 - 17F + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c, + 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 180 - 1BF + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 1C0 - 1FF + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x0c, 0x0c, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 200 - 23F + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c, 0x02, + 0x02, 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 240 - 27F + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 280 - 2BF + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 2C0 - 2FF + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + // Entry 300 - 33F + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x09, +} // Size: 799 bytes + +var tagToPercent = []uint8{ // 775 elements + // Entry 0 - 3F + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + // Entry 40 - 7F + 0x06, 0x06, 0x06, 0x04, 0x04, 0x04, 0x03, 0x03, + 0x06, 0x06, 0x03, 0x04, 0x04, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x03, + 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, + 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, 0x03, + 0x03, 0x04, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, + 0x03, 0x04, 0x04, 0x04, 0x07, 0x07, 0x04, 0x04, + // Entry 80 - BF + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + // Entry C0 - FF + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + // Entry 100 - 13F + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x0b, 0x0b, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + // Entry 140 - 17F + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, + 0x06, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + // Entry 180 - 1BF + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, + 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, + // Entry 1C0 - 1FF + 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + // Entry 200 - 23F + 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x06, 0x04, + 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + // Entry 240 - 27F + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, + // Entry 280 - 2BF + 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, + 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, + 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x0e, + // Entry 2C0 - 2FF + 0x0e, 0x0e, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, + 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + // Entry 300 - 33F + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0a, +} // Size: 799 bytes + +var formats = []Pattern{Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x0, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x0, + GroupingSize: [2]uint8{0x0, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 3, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x9, + GroupingSize: [2]uint8{0x3, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x0, + MaxIntegerDigits: 0x1, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x1}, + Affix: "", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x3, + GroupingSize: [2]uint8{0x0, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x2, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "\x00\x03\u00a0%", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x7, + GroupingSize: [2]uint8{0x3, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x2, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "\x00\x01%", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x6, + GroupingSize: [2]uint8{0x3, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 3, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0xc, + GroupingSize: [2]uint8{0x3, + 0x2}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x2, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "\x00\x01%", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x9, + GroupingSize: [2]uint8{0x3, + 0x2}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x2, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "\x00\x03\u00a0%", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0xa, + GroupingSize: [2]uint8{0x3, + 0x2}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 6, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x8, + GroupingSize: [2]uint8{0x0, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 6, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x6, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x3}, + Affix: "", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0xd, + GroupingSize: [2]uint8{0x0, + 0x0}, + Flags: 0x4}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x2, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "\x00\x01%", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x2, + GroupingSize: [2]uint8{0x0, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x2, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "\x03%\u00a0\x00", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x7, + GroupingSize: [2]uint8{0x3, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x0, + MaxIntegerDigits: 0x1, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x1}, + Affix: "\x01[\x01]", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x5, + GroupingSize: [2]uint8{0x0, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x0, + MinIntegerDigits: 0x0, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x1, + GroupingSize: [2]uint8{0x0, + 0x0}, + Flags: 0x0}, + Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0, + MaxFractionDigits: 0, + Increment: 0x0, + IncrementScale: 0x0, + Mode: 0x0, + DigitShift: 0x2, + MinIntegerDigits: 0x1, + MaxIntegerDigits: 0x0, + MinFractionDigits: 0x0, + MinSignificantDigits: 0x0, + MinExponentDigits: 0x0}, + Affix: "\x01%\x00", + Offset: 0x0, + NegOffset: 0x0, + PadRune: 0, + FormatWidth: 0x6, + GroupingSize: [2]uint8{0x3, + 0x0}, + Flags: 0x0}} + +// Total table size 8634 bytes (8KiB); checksum: 8F23386D diff --git a/vendor/golang.org/x/text/internal/stringset/set.go b/vendor/golang.org/x/text/internal/stringset/set.go new file mode 100644 index 00000000000..bb2fffbc75b --- /dev/null +++ b/vendor/golang.org/x/text/internal/stringset/set.go @@ -0,0 +1,86 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package stringset provides a way to represent a collection of strings +// compactly. +package stringset + +import "sort" + +// A Set holds a collection of strings that can be looked up by an index number. +type Set struct { + // These fields are exported to allow for code generation. + + Data string + Index []uint16 +} + +// Elem returns the string with index i. It panics if i is out of range. +func (s *Set) Elem(i int) string { + return s.Data[s.Index[i]:s.Index[i+1]] +} + +// Len returns the number of strings in the set. +func (s *Set) Len() int { + return len(s.Index) - 1 +} + +// Search returns the index of the given string or -1 if it is not in the set. +// The Set must have been created with strings in sorted order. +func Search(s *Set, str string) int { + // TODO: optimize this if it gets used a lot. + n := len(s.Index) - 1 + p := sort.Search(n, func(i int) bool { + return s.Elem(i) >= str + }) + if p == n || str != s.Elem(p) { + return -1 + } + return p +} + +// A Builder constructs Sets. +type Builder struct { + set Set + index map[string]int +} + +// NewBuilder returns a new and initialized Builder. +func NewBuilder() *Builder { + return &Builder{ + set: Set{ + Index: []uint16{0}, + }, + index: map[string]int{}, + } +} + +// Set creates the set created so far. +func (b *Builder) Set() Set { + return b.set +} + +// Index returns the index for the given string, which must have been added +// before. +func (b *Builder) Index(s string) int { + return b.index[s] +} + +// Add adds a string to the index. Strings that are added by a single Add will +// be stored together, unless they match an existing string. +func (b *Builder) Add(ss ...string) { + // First check if the string already exists. + for _, s := range ss { + if _, ok := b.index[s]; ok { + continue + } + b.index[s] = len(b.set.Index) - 1 + b.set.Data += s + x := len(b.set.Data) + if x > 0xFFFF { + panic("Index too > 0xFFFF") + } + b.set.Index = append(b.set.Index, uint16(x)) + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 0d87a6c6f28..6c684effc58 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -173,7 +173,7 @@ github.com/andybalholm/brotli/matchfinder # github.com/armon/go-metrics v0.4.1 ## explicit; go 1.12 github.com/armon/go-metrics -# github.com/aws/aws-sdk-go-v2 v1.42.0 +# github.com/aws/aws-sdk-go-v2 v1.43.2 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/aws github.com/aws/aws-sdk-go-v2/aws/defaults @@ -199,11 +199,11 @@ github.com/aws/aws-sdk-go-v2/internal/shareddefaults github.com/aws/aws-sdk-go-v2/internal/strings github.com/aws/aws-sdk-go-v2/internal/sync/singleflight github.com/aws/aws-sdk-go-v2/internal/timeconv -# github.com/aws/aws-sdk-go-v2/config v1.32.26 +# github.com/aws/aws-sdk-go-v2/config v1.32.33 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/config github.com/aws/aws-sdk-go-v2/config/internal/ini -# github.com/aws/aws-sdk-go-v2/credentials v1.19.25 +# github.com/aws/aws-sdk-go-v2/credentials v1.19.32 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/credentials github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds @@ -213,17 +213,17 @@ github.com/aws/aws-sdk-go-v2/credentials/logincreds github.com/aws/aws-sdk-go-v2/credentials/processcreds github.com/aws/aws-sdk-go-v2/credentials/ssocreds github.com/aws/aws-sdk-go-v2/credentials/stscreds -# github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 +# github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.33 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/feature/ec2/imds github.com/aws/aws-sdk-go-v2/feature/ec2/imds/internal/config -# github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 +# github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.33 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/internal/configsources -# github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 +# github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.33 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 -# github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 +# github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.34 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/internal/v4a github.com/aws/aws-sdk-go-v2/internal/v4a/internal/crypto @@ -234,41 +234,41 @@ github.com/aws/aws-sdk-go-v2/service/dynamodb github.com/aws/aws-sdk-go-v2/service/dynamodb/internal/customizations github.com/aws/aws-sdk-go-v2/service/dynamodb/internal/endpoints github.com/aws/aws-sdk-go-v2/service/dynamodb/types -# github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 +# github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.14 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding # github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.12.6 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery -# github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 +# github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.33 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url -# github.com/aws/aws-sdk-go-v2/service/signin v1.2.1 +# github.com/aws/aws-sdk-go-v2/service/signin v1.5.2 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/signin github.com/aws/aws-sdk-go-v2/service/signin/internal/endpoints github.com/aws/aws-sdk-go-v2/service/signin/types -# github.com/aws/aws-sdk-go-v2/service/sns v1.39.17 +# github.com/aws/aws-sdk-go-v2/service/sns v1.42.2 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/sns github.com/aws/aws-sdk-go-v2/service/sns/internal/endpoints github.com/aws/aws-sdk-go-v2/service/sns/types -# github.com/aws/aws-sdk-go-v2/service/sso v1.31.4 +# github.com/aws/aws-sdk-go-v2/service/sso v1.33.2 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/sso github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints github.com/aws/aws-sdk-go-v2/service/sso/types -# github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.7 +# github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.2 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/ssooidc github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints github.com/aws/aws-sdk-go-v2/service/ssooidc/types -# github.com/aws/aws-sdk-go-v2/service/sts v1.43.4 +# github.com/aws/aws-sdk-go-v2/service/sts v1.45.2 ## explicit; go 1.24 github.com/aws/aws-sdk-go-v2/service/sts github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints github.com/aws/aws-sdk-go-v2/service/sts/types -# github.com/aws/smithy-go v1.27.1 +# github.com/aws/smithy-go v1.27.5 ## explicit; go 1.24 github.com/aws/smithy-go github.com/aws/smithy-go/auth @@ -327,9 +327,6 @@ github.com/bradfitz/gomemcache/memcache # github.com/caio/go-tdigest v3.1.0+incompatible ## explicit github.com/caio/go-tdigest -# github.com/cenkalti/backoff/v4 v4.3.0 -## explicit; go 1.18 -github.com/cenkalti/backoff/v4 # github.com/cenkalti/backoff/v5 v5.0.3 ## explicit; go 1.23 github.com/cenkalti/backoff/v5 @@ -349,9 +346,6 @@ github.com/cncf/xds/go/xds/data/orca/v3 github.com/cncf/xds/go/xds/service/orca/v3 github.com/cncf/xds/go/xds/type/matcher/v3 github.com/cncf/xds/go/xds/type/v3 -# github.com/coder/quartz v0.3.1 -## explicit; go 1.23.9 -github.com/coder/quartz # github.com/coreos/go-semver v0.3.0 ## explicit github.com/coreos/go-semver/semver @@ -459,7 +453,7 @@ github.com/felixge/fgprof # github.com/felixge/httpsnoop v1.0.4 ## explicit; go 1.13 github.com/felixge/httpsnoop -# github.com/fsnotify/fsnotify v1.10.0 +# github.com/fsnotify/fsnotify v1.10.1 ## explicit; go 1.23 github.com/fsnotify/fsnotify github.com/fsnotify/fsnotify/internal @@ -485,7 +479,7 @@ github.com/go-logr/logr/funcr # github.com/go-logr/stdr v1.2.2 ## explicit; go 1.16 github.com/go-logr/stdr -# github.com/go-openapi/analysis v0.25.0 +# github.com/go-openapi/analysis v0.25.5 ## explicit; go 1.25.0 github.com/go-openapi/analysis github.com/go-openapi/analysis/internal/debug @@ -497,76 +491,84 @@ github.com/go-openapi/analysis/internal/flatten/sortref # github.com/go-openapi/errors v0.22.8 ## explicit; go 1.25.0 github.com/go-openapi/errors -# github.com/go-openapi/jsonpointer v0.22.5 -## explicit; go 1.24.0 +# github.com/go-openapi/jsonpointer v1.0.0 +## explicit; go 1.25.0 github.com/go-openapi/jsonpointer -# github.com/go-openapi/jsonreference v0.21.5 -## explicit; go 1.24.0 +github.com/go-openapi/jsonpointer/jsonname +# github.com/go-openapi/jsonreference v1.0.0 +## explicit; go 1.25.0 github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference/internal -# github.com/go-openapi/loads v0.23.3 -## explicit; go 1.24.0 +# github.com/go-openapi/loads v0.25.0 +## explicit; go 1.25.0 github.com/go-openapi/loads -# github.com/go-openapi/runtime v0.29.4 +# github.com/go-openapi/runtime v0.33.0 ## explicit; go 1.25.0 github.com/go-openapi/runtime github.com/go-openapi/runtime/client +github.com/go-openapi/runtime/client/internal/request github.com/go-openapi/runtime/flagext github.com/go-openapi/runtime/logger github.com/go-openapi/runtime/middleware github.com/go-openapi/runtime/middleware/denco -github.com/go-openapi/runtime/middleware/header github.com/go-openapi/runtime/middleware/untyped github.com/go-openapi/runtime/security github.com/go-openapi/runtime/yamlpc -# github.com/go-openapi/spec v0.22.4 => github.com/go-openapi/spec v0.20.6 -## explicit; go 1.13 +# github.com/go-openapi/runtime/server-middleware v0.33.0 +## explicit; go 1.25.0 +github.com/go-openapi/runtime/server-middleware/docui +github.com/go-openapi/runtime/server-middleware/mediatype +github.com/go-openapi/runtime/server-middleware/negotiate +github.com/go-openapi/runtime/server-middleware/negotiate/header +# github.com/go-openapi/spec v0.22.9 +## explicit; go 1.25.0 github.com/go-openapi/spec -# github.com/go-openapi/strfmt v0.26.4 +# github.com/go-openapi/strfmt v0.27.0 ## explicit; go 1.25.0 github.com/go-openapi/strfmt github.com/go-openapi/strfmt/internal/bsonlite -# github.com/go-openapi/swag v0.26.0 +github.com/go-openapi/strfmt/internal/countries +# github.com/go-openapi/swag v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag -# github.com/go-openapi/swag/cmdutils v0.26.0 +# github.com/go-openapi/swag/cmdutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/cmdutils -# github.com/go-openapi/swag/conv v0.27.0 +# github.com/go-openapi/swag/conv v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/conv -# github.com/go-openapi/swag/fileutils v0.26.0 +# github.com/go-openapi/swag/fileutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/fileutils -# github.com/go-openapi/swag/jsonname v0.26.0 -## explicit; go 1.25.0 -github.com/go-openapi/swag/jsonname -# github.com/go-openapi/swag/jsonutils v0.27.0 +# github.com/go-openapi/swag/jsonutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/jsonutils github.com/go-openapi/swag/jsonutils/adapters github.com/go-openapi/swag/jsonutils/adapters/ifaces github.com/go-openapi/swag/jsonutils/adapters/stdlib/json -# github.com/go-openapi/swag/loading v0.26.0 +# github.com/go-openapi/swag/loading v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/loading -# github.com/go-openapi/swag/mangling v0.26.0 +# github.com/go-openapi/swag/mangling v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/mangling -# github.com/go-openapi/swag/netutils v0.26.0 +# github.com/go-openapi/swag/netutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/netutils -# github.com/go-openapi/swag/stringutils v0.26.0 +# github.com/go-openapi/swag/pools v0.28.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/pools +# github.com/go-openapi/swag/stringutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/stringutils -# github.com/go-openapi/swag/typeutils v0.27.0 +# github.com/go-openapi/swag/typeutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/typeutils -# github.com/go-openapi/swag/yamlutils v0.26.0 +# github.com/go-openapi/swag/yamlutils v0.28.0 ## explicit; go 1.25.0 github.com/go-openapi/swag/yamlutils -# github.com/go-openapi/validate v0.25.2 -## explicit; go 1.24.0 +# github.com/go-openapi/validate v0.26.1 +## explicit; go 1.25.0 github.com/go-openapi/validate # github.com/go-redis/redis/v8 v8.11.5 ## explicit; go 1.17 @@ -755,7 +757,7 @@ github.com/hashicorp/golang-lru/v2 github.com/hashicorp/golang-lru/v2/expirable github.com/hashicorp/golang-lru/v2/internal github.com/hashicorp/golang-lru/v2/simplelru -# github.com/hashicorp/memberlist v0.5.4 => github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe +# github.com/hashicorp/memberlist v0.6.0 => github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe ## explicit; go 1.12 github.com/hashicorp/memberlist # github.com/hashicorp/serf v0.10.1 @@ -779,7 +781,7 @@ github.com/julienschmidt/httprouter # github.com/kamstrup/intmap v0.5.2 ## explicit; go 1.23 github.com/kamstrup/intmap -# github.com/klauspost/compress v1.18.7 +# github.com/klauspost/compress v1.19.1 ## explicit; go 1.24 github.com/klauspost/compress github.com/klauspost/compress/flate @@ -839,16 +841,16 @@ github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.20 ## explicit; go 1.15 github.com/mattn/go-isatty -# github.com/mdlayher/socket v0.5.1 -## explicit; go 1.20 +# github.com/mdlayher/socket v0.6.0 +## explicit; go 1.25.0 github.com/mdlayher/socket -# github.com/mdlayher/vsock v1.2.1 -## explicit; go 1.20 +# github.com/mdlayher/vsock v1.3.0 +## explicit; go 1.25.0 github.com/mdlayher/vsock # github.com/metalmatze/signal v0.0.0-20210307161603-1c9aa721a97a ## explicit; go 1.14 github.com/metalmatze/signal/server/signalhttp -# github.com/miekg/dns v1.1.69 +# github.com/miekg/dns v1.1.72 ## explicit; go 1.24.0 github.com/miekg/dns # github.com/minio/crc64nvme v1.1.1 @@ -915,7 +917,7 @@ github.com/oklog/run # github.com/oklog/ulid v1.3.1 ## explicit github.com/oklog/ulid -# github.com/oklog/ulid/v2 v2.1.1 +# github.com/oklog/ulid/v2 v2.1.2 ## explicit; go 1.15 github.com/oklog/ulid/v2 # github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.142.0 @@ -1030,7 +1032,7 @@ github.com/prometheus-community/parquet-common/util # github.com/prometheus-community/prom-label-proxy v0.11.1 ## explicit; go 1.23.0 github.com/prometheus-community/prom-label-proxy/injectproxy -# github.com/prometheus/alertmanager v0.33.0 +# github.com/prometheus/alertmanager v0.34.0 ## explicit; go 1.25.0 github.com/prometheus/alertmanager/alert github.com/prometheus/alertmanager/api @@ -1095,8 +1097,8 @@ github.com/prometheus/alertmanager/template github.com/prometheus/alertmanager/timeinterval github.com/prometheus/alertmanager/tracing github.com/prometheus/alertmanager/types -# github.com/prometheus/client_golang v1.23.2 -## explicit; go 1.23.0 +# github.com/prometheus/client_golang v1.24.1 +## explicit; go 1.25.0 github.com/prometheus/client_golang/api github.com/prometheus/client_golang/api/prometheus/v1 github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil @@ -1119,7 +1121,7 @@ github.com/prometheus/client_golang/exp/internal/github.com/efficientgo/core/bac # github.com/prometheus/client_model v0.6.2 ## explicit; go 1.22.0 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.69.0 +# github.com/prometheus/common v0.70.1 ## explicit; go 1.25.0 github.com/prometheus/common/config github.com/prometheus/common/expfmt @@ -1128,13 +1130,13 @@ github.com/prometheus/common/model github.com/prometheus/common/promslog github.com/prometheus/common/route github.com/prometheus/common/version -# github.com/prometheus/exporter-toolkit v0.16.0 +# github.com/prometheus/exporter-toolkit v0.17.1 ## explicit; go 1.25.0 github.com/prometheus/exporter-toolkit/web # github.com/prometheus/otlptranslator v1.0.0 => github.com/prometheus/otlptranslator v1.0.0 ## explicit; go 1.23.0 github.com/prometheus/otlptranslator -# github.com/prometheus/procfs v0.21.0 +# github.com/prometheus/procfs v0.21.1 ## explicit; go 1.25.0 github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs @@ -1384,7 +1386,7 @@ github.com/tinylib/msgp/msgp/setof # github.com/tjhop/slog-gokit v0.2.0 ## explicit; go 1.21 github.com/tjhop/slog-gokit -# github.com/twmb/franz-go v1.21.2 +# github.com/twmb/franz-go v1.21.5 ## explicit; go 1.25.0 github.com/twmb/franz-go/pkg/kbin github.com/twmb/franz-go/pkg/kerr @@ -1562,11 +1564,11 @@ go.opentelemetry.io/contrib/detectors/gcp ## explicit; go 1.23.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal -# go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.68.0 +# go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.69.0 ## explicit; go 1.25.0 go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace/internal/semconv -# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 +# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 ## explicit; go 1.25.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request @@ -1604,10 +1606,8 @@ go.opentelemetry.io/otel/semconv/v1.21.0 go.opentelemetry.io/otel/semconv/v1.24.0 go.opentelemetry.io/otel/semconv/v1.30.0 go.opentelemetry.io/otel/semconv/v1.37.0 -go.opentelemetry.io/otel/semconv/v1.40.0 -go.opentelemetry.io/otel/semconv/v1.40.0/httpconv -go.opentelemetry.io/otel/semconv/v1.40.0/otelconv go.opentelemetry.io/otel/semconv/v1.41.0 +go.opentelemetry.io/otel/semconv/v1.41.0/httpconv go.opentelemetry.io/otel/semconv/v1.41.0/otelconv go.opentelemetry.io/otel/semconv/v1.43.0 # go.opentelemetry.io/otel/bridge/opentracing v1.45.0 @@ -1628,7 +1628,7 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/observ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/x -# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 +# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 ## explicit; go 1.25.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal @@ -1730,7 +1730,7 @@ golang.org/x/crypto/scrypt ## explicit; go 1.25.0 golang.org/x/exp/constraints golang.org/x/exp/slices -# golang.org/x/mod v0.37.0 +# golang.org/x/mod v0.38.0 ## explicit; go 1.25.0 golang.org/x/mod/semver # golang.org/x/net v0.57.0 @@ -1780,9 +1780,13 @@ golang.org/x/sys/windows/registry # golang.org/x/text v0.40.0 ## explicit; go 1.25.0 golang.org/x/text/cases +golang.org/x/text/currency golang.org/x/text/internal +golang.org/x/text/internal/format golang.org/x/text/internal/language golang.org/x/text/internal/language/compact +golang.org/x/text/internal/number +golang.org/x/text/internal/stringset golang.org/x/text/internal/tag golang.org/x/text/language golang.org/x/text/runes @@ -2118,7 +2122,6 @@ k8s.io/utils/clock # github.com/gocql/gocql => github.com/grafana/gocql v0.0.0-20200605141915-ba5dc39ece85 # github.com/hashicorp/memberlist => github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe # github.com/vimeo/galaxycache => github.com/thanos-community/galaxycache v0.0.0-20211122094458-3a32041a1f1e -# github.com/go-openapi/spec => github.com/go-openapi/spec v0.20.6 # github.com/ionos-cloud/sdk-go/v6 => github.com/ionos-cloud/sdk-go/v6 v6.0.4 # github.com/google/gnostic => github.com/googleapis/gnostic v0.6.9 # gopkg.in/alecthomas/kingpin.v2 => github.com/alecthomas/kingpin v1.3.8-0.20210301060133-17f40c25f497