diff --git a/go.mod b/go.mod
index 4864de88ff58..1fbae3ecaa2b 100644
--- a/go.mod
+++ b/go.mod
@@ -21,15 +21,15 @@ require (
github.com/dustin/go-humanize v1.0.1
github.com/filanov/stateswitch v1.0.1-0.20221122134945-bfa198e3a83a
github.com/go-gormigrate/gormigrate/v2 v2.1.2
- github.com/go-jose/go-jose/v4 v4.0.5
+ github.com/go-jose/go-jose/v4 v4.1.3
github.com/go-logr/logr v1.4.3
- github.com/go-openapi/errors v0.22.0
- github.com/go-openapi/loads v0.22.0
- github.com/go-openapi/runtime v0.19.24
- github.com/go-openapi/spec v0.21.0
- github.com/go-openapi/strfmt v0.23.0
- github.com/go-openapi/swag v0.23.0
- github.com/go-openapi/validate v0.24.0
+ github.com/go-openapi/errors v0.22.7
+ github.com/go-openapi/loads v0.23.3
+ github.com/go-openapi/runtime v0.29.3
+ github.com/go-openapi/spec v0.22.4
+ github.com/go-openapi/strfmt v0.26.1
+ github.com/go-openapi/swag v0.25.5
+ github.com/go-openapi/validate v0.25.2
github.com/golang-collections/go-datastructures v0.0.0-20150211160725-59788d5eb259
github.com/golang-jwt/jwt/v4 v4.5.2
github.com/google/go-cmp v0.7.0
@@ -44,7 +44,7 @@ require (
github.com/kennygrant/sanitize v1.2.4
github.com/krishicks/yaml-patch v0.0.10
github.com/metal3-io/baremetal-operator/apis v0.2.0
- github.com/moby/moby v27.2.1+incompatible
+ github.com/moby/moby/v2 v2.0.0-beta.11
github.com/nmstate/nmstate/rust/src/go/nmstate v0.0.0-20220811151154-801022633c42
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.35.1
@@ -65,21 +65,21 @@ require (
github.com/pelletier/go-toml v1.9.5
github.com/pkg/errors v0.9.1
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.57.0
- github.com/prometheus/client_golang v1.18.0
+ github.com/prometheus/client_golang v1.23.2
github.com/rs/cors v1.11.1
github.com/samber/lo v1.47.0
github.com/segmentio/kafka-go v0.4.38
- github.com/sirupsen/logrus v1.9.3
+ github.com/sirupsen/logrus v1.9.4
github.com/slok/go-http-metrics v0.11.0
github.com/stretchr/testify v1.11.1
github.com/thedevsaddam/retry v1.2.1
github.com/thoas/go-funk v0.9.3
github.com/vincent-petithory/dataurl v1.0.0
go.uber.org/mock v0.6.0
- golang.org/x/crypto v0.46.0
+ golang.org/x/crypto v0.50.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
- golang.org/x/sync v0.19.0
- golang.org/x/sys v0.39.0
+ golang.org/x/sync v0.20.0
+ golang.org/x/sys v0.43.0
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v2 v2.4.0
gorm.io/driver/postgres v1.3.5
@@ -98,14 +98,15 @@ require (
)
require (
- dario.cat/mergo v1.0.0 // indirect
+ dario.cat/mergo v1.0.2 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
- github.com/Microsoft/hcsshim v0.11.7 // indirect
+ github.com/Microsoft/hcsshim v0.14.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
+ github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/containerd/containerd v1.7.29 // indirect
github.com/containerd/log v0.1.0 // indirect
- github.com/containerd/platforms v0.2.1 // indirect
+ github.com/containerd/platforms v1.0.0-rc.2 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
@@ -114,7 +115,19 @@ require (
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
- github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/go-openapi/swag/cmdutils v0.25.5 // indirect
+ github.com/go-openapi/swag/conv v0.25.5 // indirect
+ github.com/go-openapi/swag/fileutils v0.25.5 // indirect
+ github.com/go-openapi/swag/jsonname v0.25.5 // indirect
+ github.com/go-openapi/swag/jsonutils v0.25.5 // indirect
+ github.com/go-openapi/swag/loading v0.25.5 // indirect
+ github.com/go-openapi/swag/mangling v0.25.5 // indirect
+ github.com/go-openapi/swag/netutils v0.25.5 // indirect
+ github.com/go-openapi/swag/stringutils v0.25.5 // indirect
+ github.com/go-openapi/swag/typeutils v0.25.5 // indirect
+ github.com/go-openapi/swag/yamlutils v0.25.5 // indirect
+ github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
+ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/cel-go v0.17.7 // indirect
@@ -122,23 +135,25 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
+ github.com/jonboulle/clockwork v0.5.0 // indirect
+ github.com/kylelemons/godebug v1.1.0 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
- github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
- github.com/moby/patternmatcher v0.6.0 // indirect
+ github.com/moby/patternmatcher v0.6.1 // indirect
github.com/moby/spdystream v0.5.0 // indirect
- github.com/moby/sys/sequential v0.5.0 // indirect
- github.com/moby/sys/user v0.3.0 // indirect
+ github.com/moby/sys/sequential v0.6.0 // indirect
+ github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
- github.com/morikuni/aec v1.0.0 // indirect
+ github.com/morikuni/aec v1.1.0 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
+ github.com/oklog/ulid/v2 v2.1.1 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
@@ -152,12 +167,14 @@ require (
github.com/xdg/stringprep v1.0.3 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
+ go.opentelemetry.io/auto/sdk v1.2.1 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
+ go.yaml.in/yaml/v3 v3.0.4 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect
k8s.io/apiserver v0.29.5 // indirect
k8s.io/cli-runtime v0.29.9 // indirect
k8s.io/component-base v0.29.9 // indirect
@@ -168,29 +185,29 @@ require (
)
require (
- github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
+ github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
- github.com/cenkalti/backoff/v4 v4.2.1 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coreos/go-json v0.0.0-20211020211907-c63f628265de // indirect
github.com/coreos/go-semver v0.3.1 // indirect
- github.com/coreos/go-systemd/v22 v22.5.0 // indirect
+ github.com/coreos/go-systemd/v22 v22.7.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/diskfs/go-diskfs v1.4.0 // indirect
github.com/docker/docker v25.0.6+incompatible // indirect
- github.com/docker/go-connections v0.5.0
+ github.com/docker/go-connections v0.7.0
github.com/docker/go-units v0.5.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
- github.com/fsnotify/fsnotify v1.7.0 // indirect
+ github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
- github.com/go-openapi/analysis v0.23.0 // indirect
- github.com/go-openapi/jsonpointer v0.21.0 // indirect
- github.com/go-openapi/jsonreference v0.21.0 // indirect
+ github.com/go-openapi/analysis v0.24.3 // indirect
+ github.com/go-openapi/jsonpointer v0.22.5 // indirect
+ github.com/go-openapi/jsonreference v0.21.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/glog v1.2.5 // indirect
@@ -210,56 +227,50 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect
- github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
- github.com/klauspost/compress v1.17.1 // indirect
+ github.com/klauspost/compress v1.18.5 // indirect
github.com/lib/pq v1.10.9
- github.com/mailru/easyjson v0.7.7 // indirect
github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.2.0 // indirect
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
- github.com/mitchellh/mapstructure v1.5.0 // indirect
- github.com/moby/term v0.5.0 // indirect
+ github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nxadm/tail v1.4.8 // indirect
- github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
- github.com/opencontainers/image-spec v1.1.0 // indirect
+ github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/openshift/machine-config-operator v0.0.1-0.20201023110058-6c8bd9b2915c
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/xattr v0.4.10
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.45.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
- github.com/spf13/cobra v1.8.0 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.66.1 // indirect
+ github.com/prometheus/procfs v0.17.0 // indirect
+ github.com/spf13/cobra v1.10.2 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/testcontainers/testcontainers-go v0.29.1
github.com/ulikunitz/xz v0.5.11 // indirect
- go.etcd.io/etcd/api/v3 v3.5.11 // indirect
- go.etcd.io/etcd/client/pkg/v3 v3.5.11 // indirect
- go.etcd.io/etcd/client/v3 v3.5.11 // indirect
- go.mongodb.org/mongo-driver v1.14.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
- go.opentelemetry.io/otel v1.21.0 // indirect
- go.opentelemetry.io/otel/metric v1.21.0 // indirect
- go.opentelemetry.io/otel/sdk v1.21.0 // indirect
- go.opentelemetry.io/otel/trace v1.21.0 // indirect
- go.opentelemetry.io/proto/otlp v1.0.0 // indirect
+ go.etcd.io/etcd/api/v3 v3.6.6 // indirect
+ go.etcd.io/etcd/client/pkg/v3 v3.6.6 // indirect
+ go.etcd.io/etcd/client/v3 v3.6.6 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
+ go.opentelemetry.io/otel v1.43.0 // indirect
+ go.opentelemetry.io/otel/metric v1.43.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.43.0 // indirect
+ go.opentelemetry.io/otel/trace v1.43.0 // indirect
+ go.opentelemetry.io/proto/otlp v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.26.0 // indirect
- golang.org/x/net v0.48.0 // indirect
- golang.org/x/oauth2 v0.30.0 // indirect
- golang.org/x/term v0.38.0 // indirect
- golang.org/x/text v0.32.0 // indirect
- golang.org/x/time v0.12.0 // indirect
+ go.uber.org/zap v1.27.1 // indirect
+ golang.org/x/net v0.53.0 // indirect
+ golang.org/x/oauth2 v0.36.0 // indirect
+ golang.org/x/term v0.42.0 // indirect
+ golang.org/x/text v0.36.0 // indirect
+ golang.org/x/time v0.15.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
- google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
- google.golang.org/grpc v1.60.1 // indirect
- google.golang.org/protobuf v1.36.5 // indirect
+ google.golang.org/grpc v1.80.0 // indirect
+ google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
diff --git a/go.sum b/go.sum
index 6547125f5820..11068d573f9d 100644
--- a/go.sum
+++ b/go.sum
@@ -12,15 +12,12 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.58.0/go.mod h1:W+9FnSUw6nhVwXlFcp1eL+krq5+HQUJeUogSeJZZiWg=
-cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
-cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
@@ -33,15 +30,15 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.9.0/go.mod h1:m+/etGaqZbylxaNT876QGXqEHp4PR2Rq5GMqICWb9bU=
-dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
-dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
+dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
@@ -73,8 +70,8 @@ github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tT
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
-github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ=
-github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
+github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs=
+github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
@@ -115,8 +112,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
-github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
-github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
@@ -149,16 +144,18 @@ github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e h1:hHg27A0RS
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
-github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
-github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+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=
github.com/cert-manager/cert-manager v1.14.7 h1:C2L59sMGMdSpd8SPx5qfPAL7ejZaNxJBRd24S7Ws5Ek=
github.com/cert-manager/cert-manager v1.14.7/go.mod h1:0QE/Hzfs2SxNrFFYgFh/d0c0cDfNv9qSrAev2LFt5nM=
github.com/certifi/gocertifi v0.0.0-20180905225744-ee1a9a0726d2/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
-github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
@@ -171,8 +168,6 @@ github.com/clarketm/json v1.14.1/go.mod h1:ynr2LRfb0fQU34l07csRNBTcivjySLLiY1YzQ
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
-github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
@@ -190,8 +185,8 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
-github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
+github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
+github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/containers/image v3.0.2+incompatible/go.mod h1:8Vtij257IWSanUQKe1tAeNOm2sRVkSqQTVQ1IlwI3+M=
@@ -215,8 +210,8 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
-github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA=
+github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
github.com/coreos/ign-converter v0.0.0-20200629171308-e40a44f244c5/go.mod h1:LNu0WTt8iVH/WJH15R/SjZw7AdyY2qAyf9ILZTCBvho=
github.com/coreos/ignition v0.35.0/go.mod h1:WJQapxzEn9DE0ryxsGvm8QnBajm/XsS/PkrDqSpz+bA=
github.com/coreos/ignition/v2 v2.1.1/go.mod h1:RqmqU64zxarUJa3l4cHtbhcSwfQLpUhv0WVziZwoXvE=
@@ -233,11 +228,11 @@ github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoY
github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
-github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
+github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
+github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/danielerez/go-dns-client v0.0.0-20200630114514-0b60d1703f0b h1:3Mkb/I9NauxsrV6kc6DaP3MspFFHsi06kA6jL8L8iBc=
github.com/danielerez/go-dns-client v0.0.0-20200630114514-0b60d1703f0b/go.mod h1:2l39JZ3DOxVtByPDmp0Zhh4xS7603UHmeRtLCKzqQdQ=
@@ -261,8 +256,8 @@ github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bc
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
-github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
-github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
+github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c=
+github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
@@ -296,8 +291,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
-github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -319,8 +312,8 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
-github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fsouza/go-dockerclient v0.0.0-20171004212419-da3951ba2e9e/go.mod h1:KpcjM623fQYE9MZiTGzKhjfxXAV9wbyX2C1cyRHfhl0=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/getsentry/raven-go v0.0.0-20190513200303-c977f96e1095/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -337,8 +330,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gormigrate/gormigrate/v2 v2.1.2 h1:F/d1hpHbRAvKezziV2CC5KUE82cVe9zTgHSBoOOZ4CY=
github.com/go-gormigrate/gormigrate/v2 v2.1.2/go.mod h1:9nHVX6z3FCMCQPA7PThGcA55t22yKQfK/Dnsf5i7hUo=
-github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
-github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
+github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
+github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
@@ -368,25 +361,21 @@ github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70t
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
-github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
-github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ=
-github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
-github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
+github.com/go-openapi/analysis v0.24.3 h1:a1hrvMr8X0Xt69KP5uVTu5jH62DscmDifrLzNglAayk=
+github.com/go-openapi/analysis v0.24.3/go.mod h1:Nc+dWJ/FxZbhSow5Yh3ozg5CLJioB+XXT6MdLvJUsUw=
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
-github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
-github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
-github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
-github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
+github.com/go-openapi/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA=
+github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
-github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
-github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
+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.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@@ -395,58 +384,75 @@ github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
-github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
-github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+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.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
-github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI=
github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
-github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY=
-github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
-github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
+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.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
-github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
-github.com/go-openapi/runtime v0.19.24 h1:TqagMVlRAOTwllE/7hNKx6rQ10O6T8ZzeJdMjSTKaD4=
-github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
+github.com/go-openapi/runtime v0.29.3 h1:h5twGaEqxtQg40ePiYm9vFFH1q06Czd7Ot6ufdK0w/Y=
+github.com/go-openapi/runtime v0.29.3/go.mod h1:8A1W0/L5eyNJvKciqZtvIVQvYO66NlB7INMSZ9bw/oI=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
-github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
-github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
-github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
-github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
+github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ=
+github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ=
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
-github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
-github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
-github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
-github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
-github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
+github.com/go-openapi/strfmt v0.26.1 h1:7zGCHji7zSYDC2tCXIusoxYQz/48jAf2q+sF6wXTG+c=
+github.com/go-openapi/strfmt v0.26.1/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
-github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU=
+github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA=
+github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c=
+github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
+github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g=
+github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k=
+github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk=
+github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc=
+github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo=
+github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU=
+github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo=
+github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4=
+github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5 h1:SX6sE4FrGb4sEnnxbFL/25yZBb5Hcg1inLeErd86Y1U=
+github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5/go.mod h1:/2KvOTrKWjVA5Xli3DZWdMCZDzz3uV/T7bXwrKWPquo=
+github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU=
+github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g=
+github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw=
+github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY=
+github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyOa7ZGfxDKlU=
+github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14=
+github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M=
+github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII=
+github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E=
+github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc=
+github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
+github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
+github.com/go-openapi/testify/enable/yaml/v2 v2.4.1 h1:NZOrZmIb6PTv5LTFxr5/mKV/FjbUzGE7E6gLz7vFoOQ=
+github.com/go-openapi/testify/enable/yaml/v2 v2.4.1/go.mod h1:r7dwsujEHawapMsxA69i+XMGZrQ5tRauhLAjV/sxg3Q=
+github.com/go-openapi/testify/v2 v2.4.1 h1:zB34HDKj4tHwyUQHrUkpV0Q0iXQ6dUCOQtIqn8hE6Iw=
+github.com/go-openapi/testify/v2 v2.4.1/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
-github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
-github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8=
-github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
-github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
+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-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -471,30 +477,8 @@ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoM
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
-github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
-github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
-github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
-github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
-github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
-github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
-github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
-github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
-github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
-github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
-github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
-github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
-github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
-github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
-github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
-github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
-github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
-github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
-github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
-github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
-github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
-github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
-github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
-github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
+github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
@@ -516,6 +500,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
+github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I=
@@ -525,8 +511,8 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -556,7 +542,6 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
@@ -659,15 +644,16 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:Fecb
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
-github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
+github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
+github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
+github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
+github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -765,11 +751,9 @@ github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
-github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
-github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
-github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
+github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -784,8 +768,6 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
-github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
-github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
@@ -797,12 +779,11 @@ github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7IL
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
-github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g=
-github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
+github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@@ -824,6 +805,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/krishicks/yaml-patch v0.0.10 h1:H4FcHpnNwVmw8u0MjPRjWyIXtco6zM2F78t+57oNM3E=
github.com/krishicks/yaml-patch v0.0.10/go.mod h1:Sm5TchwZS6sm7RJoyg87tzxm2ZcKzdRE4Q7TjNhPrME=
github.com/kubernetes-sigs/kube-storage-version-migrator v0.0.0-20191127225502-51849bc15f17/go.mod h1:enH0BVV+4+DAgWdwSlMefG8bBzTfVMTr1lApzdLZ/cc=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
@@ -848,12 +831,8 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
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.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
-github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
-github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@@ -868,8 +847,6 @@ github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/microcosm-cc/bluemonday v1.0.15/go.mod h1:ZLvAzeakRwrGnzQEvstVzVt3ZpqOF2+sdFr0Om+ce30=
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
@@ -888,26 +865,23 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
-github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/moby/moby v27.2.1+incompatible h1:mIRBoOsLr+Q6s+h65ZFyi6cXBEVy2RXCWS5HOHlxx54=
-github.com/moby/moby v27.2.1+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
-github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
-github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
+github.com/moby/moby/v2 v2.0.0-beta.11 h1:0s92vMOUn8H/MDXGeYyEqI/ulYlVpQ1Dh1zSgprgQ/Y=
+github.com/moby/moby/v2 v2.0.0-beta.11/go.mod h1:CJq/k6N+wkom/MTVsGVZfsB4FxrHt4sVS0yJZphif6w=
+github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U=
+github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
-github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
-github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
-github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
-github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
+github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
+github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
+github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
+github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
-github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
-github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
+github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -918,9 +892,9 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
-github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
-github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ=
+github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw=
github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
@@ -950,8 +924,9 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
-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/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -1014,8 +989,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
-github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
+github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
+github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -1071,10 +1046,10 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
@@ -1114,16 +1089,16 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
-github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
-github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+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_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@@ -1132,8 +1107,8 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
-github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
-github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
+github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
+github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -1143,8 +1118,8 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
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.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
+github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@@ -1153,7 +1128,6 @@ github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfm
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
@@ -1197,13 +1171,12 @@ github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOms
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
-github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
+github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
github.com/slok/go-http-metrics v0.11.0 h1:ABJUpekCZSkQT1wQrFvS4kGbhea/w6ndFJaWJeh3zL0=
github.com/slok/go-http-metrics v0.11.0/go.mod h1:ZGKeYG1ET6TEJpQx18BqAJAvxw9jBAZXCHU7bWQqqAc=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -1223,8 +1196,8 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
-github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
-github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
+github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
+github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@@ -1232,6 +1205,7 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
@@ -1307,10 +1281,8 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk=
github.com/vmware/vmw-guestinfo v0.0.0-20220317130741-510905f0efa3/go.mod h1:CSBTxrhePCm0cmXNKDGeu+6bOQzpaEklfCqEpn89JWk=
github.com/vmware/vmw-ovflib v0.0.0-20170608004843-1f217b9dc714/go.mod h1:jiPk45kn7klhByRvUq5i2vo1RtHKBHj+iWGFpxbXuuI=
-github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/scram v1.0.5 h1:TuS0RFmt5Is5qm9Tm2SoD89OPqe4IRiFtyFY4iwWXsw=
github.com/xdg/scram v1.0.5/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
-github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xdg/stringprep v1.0.3 h1:cmL5Enob4W83ti/ZHuZLuKD/xqJfus4fVPwE+/BDm+4=
github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -1338,32 +1310,26 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
-go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
-go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
+go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
+go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5 h1:Gqga3zA9tdAcfqobUGjSoCob5L3f8Dt5EuOp3ihNZko=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8=
-go.etcd.io/etcd/api/v3 v3.5.11 h1:B54KwXbWDHyD3XYAwprxNzTe7vlhR69LuBgZnMVvS7E=
-go.etcd.io/etcd/api/v3 v3.5.11/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
-go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A=
-go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
-go.etcd.io/etcd/client/v2 v2.305.10 h1:MrmRktzv/XF8CvtQt+P6wLUlURaNpSDJHFZhe//2QE4=
-go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA=
-go.etcd.io/etcd/client/v3 v3.5.11 h1:ajWtgoNSZJ1gmS8k+icvPtqsqEav+iUorF7b0qozgUU=
-go.etcd.io/etcd/client/v3 v3.5.11/go.mod h1:a6xQUEqFJ8vztO1agJh/KQKOMfFI8og52ZconzcDJwE=
-go.etcd.io/etcd/pkg/v3 v3.5.10 h1:WPR8K0e9kWl1gAhB5A7gEa5ZBTNkT9NdNWrR8Qpo1CM=
-go.etcd.io/etcd/pkg/v3 v3.5.10/go.mod h1:TKTuCKKcF1zxmfKWDkfz5qqYaE3JncKKZPFf8c1nFUs=
-go.etcd.io/etcd/raft/v3 v3.5.10 h1:cgNAYe7xrsrn/5kXMSaH8kM/Ky8mAdMqGOxyYwpP0LA=
-go.etcd.io/etcd/raft/v3 v3.5.10/go.mod h1:odD6kr8XQXTy9oQnyMPBOr0TVe+gT0neQhElQ6jbGRc=
-go.etcd.io/etcd/server/v3 v3.5.10 h1:4NOGyOwD5sUZ22PiWYKmfxqoeh72z6EhYjNosKGLmZg=
-go.etcd.io/etcd/server/v3 v3.5.10/go.mod h1:gBplPHfs6YI0L+RpGkTQO7buDbHv5HJGG/Bst0/zIPo=
+go.etcd.io/etcd/api/v3 v3.6.6 h1:mcaMp3+7JawWv69p6QShYWS8cIWUOl32bFLb6qf8pOQ=
+go.etcd.io/etcd/api/v3 v3.6.6/go.mod h1:f/om26iXl2wSkcTA1zGQv8reJRSLVdoEBsi4JdfMrx4=
+go.etcd.io/etcd/client/pkg/v3 v3.6.6 h1:uoqgzSOv2H9KlIF5O1Lsd8sW+eMLuV6wzE3q5GJGQNs=
+go.etcd.io/etcd/client/pkg/v3 v3.6.6/go.mod h1:YngfUVmvsvOJ2rRgStIyHsKtOt9SZI2aBJrZiWJhCbI=
+go.etcd.io/etcd/client/v3 v3.6.6 h1:G5z1wMf5B9SNexoxOHUGBaULurOZPIgGPsW6CN492ec=
+go.etcd.io/etcd/client/v3 v3.6.6/go.mod h1:36Qv6baQ07znPR3+n7t+Rk5VHEzVYPvFfGmfF4wBHV8=
+go.etcd.io/etcd/pkg/v3 v3.6.6 h1:wylOivS/UxXTZ0Le5fOdxCjatW5ql9dcWEggQQHSorw=
+go.etcd.io/etcd/pkg/v3 v3.6.6/go.mod h1:9TKZL7WUEVHXYM3srP3ESZfIms34s1G72eNtWA9YKg4=
+go.etcd.io/etcd/server/v3 v3.6.6 h1:YSRWGJPzU+lIREwUQI4MfyLZrkUyzjJOVpMxJvZePaY=
+go.etcd.io/etcd/server/v3 v3.6.6/go.mod h1:A1OQ1x3PaiENDLywMjCiMwV1pwJSpb0h9Z5ORP2dv6I=
+go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
+go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
-go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
-go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
-go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
-go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -1371,26 +1337,30 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
-go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
-go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
-go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
-go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
-go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
-go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
-go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
-go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
-go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
-go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo=
+go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
+go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk=
+go.opentelemetry.io/otel/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/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
+go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
+go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
+go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
+go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
+go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
+go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
+go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
+go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
+go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -1409,8 +1379,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
-go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
+go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@@ -1423,9 +1393,7 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
-golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1450,8 +1418,8 @@ golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
-golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
-golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
+golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
+golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1568,13 +1536,12 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
-golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
-golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
+golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
+golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1586,8 +1553,8 @@ golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-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.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1602,12 +1569,10 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1688,8 +1653,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
-golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
+golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1709,8 +1674,8 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
-golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
-golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
+golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
+golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1730,15 +1695,15 @@ golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
-golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
+golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
+golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
-golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
+golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
+golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1757,15 +1722,11 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
@@ -1826,8 +1787,8 @@ golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
-golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
-golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
+golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
+golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1836,6 +1797,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
+gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
+gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@@ -1888,12 +1851,10 @@ google.golang.org/genproto v0.0.0-20200603110839-e855014d5736/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200610104632-a5b850bcf112/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg=
-google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0=
-google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM=
-google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
+google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@@ -1910,8 +1871,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
-google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
+google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
+google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1927,8 +1888,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
-google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
-google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
@@ -1972,7 +1933,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20190502103701-55513cacd4ae/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20191010095647-fc94e3f71652/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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=
@@ -1985,8 +1945,8 @@ gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
-gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
-gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
+gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
+gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/pkg/s3wrapper/filesystem.go b/pkg/s3wrapper/filesystem.go
index 60fedbfa778f..adde71af4117 100644
--- a/pkg/s3wrapper/filesystem.go
+++ b/pkg/s3wrapper/filesystem.go
@@ -14,7 +14,7 @@ import (
"github.com/alecthomas/units"
"github.com/google/renameio"
- "github.com/moby/moby/pkg/ioutils"
+ "github.com/moby/moby/v2/pkg/ioutils"
"github.com/openshift/assisted-service/internal/common"
"github.com/openshift/assisted-service/internal/metrics"
logutil "github.com/openshift/assisted-service/pkg/log"
diff --git a/vendor/dario.cat/mergo/.gitignore b/vendor/dario.cat/mergo/.gitignore
index 529c3412ba95..45ad0f1ae309 100644
--- a/vendor/dario.cat/mergo/.gitignore
+++ b/vendor/dario.cat/mergo/.gitignore
@@ -13,6 +13,9 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
+# Golang/Intellij
+.idea
+
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
diff --git a/vendor/dario.cat/mergo/FUNDING.json b/vendor/dario.cat/mergo/FUNDING.json
new file mode 100644
index 000000000000..0585e1fe13f7
--- /dev/null
+++ b/vendor/dario.cat/mergo/FUNDING.json
@@ -0,0 +1,7 @@
+{
+ "drips": {
+ "ethereum": {
+ "ownedBy": "0x6160020e7102237aC41bdb156e94401692D76930"
+ }
+ }
+}
diff --git a/vendor/dario.cat/mergo/README.md b/vendor/dario.cat/mergo/README.md
index 7d0cf9f32afe..0e4a59afd9ac 100644
--- a/vendor/dario.cat/mergo/README.md
+++ b/vendor/dario.cat/mergo/README.md
@@ -44,13 +44,21 @@ Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the
## Status
-It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, Microsoft, etc](https://github.com/imdario/mergo#mergo-in-the-wild).
+Mergo is stable and frozen, ready for production. Check a short list of the projects using at large scale it [here](https://github.com/imdario/mergo#mergo-in-the-wild).
+
+No new features are accepted. They will be considered for a future v2 that improves the implementation and fixes bugs for corner cases.
### Important notes
#### 1.0.0
-In [1.0.0](//github.com/imdario/mergo/releases/tag/1.0.0) Mergo moves to a vanity URL `dario.cat/mergo`.
+In [1.0.0](//github.com/imdario/mergo/releases/tag/1.0.0) Mergo moves to a vanity URL `dario.cat/mergo`. No more v1 versions will be released.
+
+If the vanity URL is causing issues in your project due to a dependency pulling Mergo - it isn't a direct dependency in your project - it is recommended to use [replace](https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive) to pin the version to the last one with the old import URL:
+
+```
+replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
+```
#### 0.3.9
@@ -64,55 +72,23 @@ If you were using Mergo before April 6th, 2015, please check your project works
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
-
### Mergo in the wild
-- [moby/moby](https://github.com/moby/moby)
-- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
-- [vmware/dispatch](https://github.com/vmware/dispatch)
-- [Shopify/themekit](https://github.com/Shopify/themekit)
-- [imdario/zas](https://github.com/imdario/zas)
-- [matcornic/hermes](https://github.com/matcornic/hermes)
-- [OpenBazaar/openbazaar-go](https://github.com/OpenBazaar/openbazaar-go)
-- [kataras/iris](https://github.com/kataras/iris)
-- [michaelsauter/crane](https://github.com/michaelsauter/crane)
-- [go-task/task](https://github.com/go-task/task)
-- [sensu/uchiwa](https://github.com/sensu/uchiwa)
-- [ory/hydra](https://github.com/ory/hydra)
-- [sisatech/vcli](https://github.com/sisatech/vcli)
-- [dairycart/dairycart](https://github.com/dairycart/dairycart)
-- [projectcalico/felix](https://github.com/projectcalico/felix)
-- [resin-os/balena](https://github.com/resin-os/balena)
-- [go-kivik/kivik](https://github.com/go-kivik/kivik)
-- [Telefonica/govice](https://github.com/Telefonica/govice)
-- [supergiant/supergiant](supergiant/supergiant)
-- [SergeyTsalkov/brooce](https://github.com/SergeyTsalkov/brooce)
-- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
-- [ohsu-comp-bio/funnel](https://github.com/ohsu-comp-bio/funnel)
-- [EagerIO/Stout](https://github.com/EagerIO/Stout)
-- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
-- [russross/canvasassignments](https://github.com/russross/canvasassignments)
-- [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api)
-- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
-- [divshot/gitling](https://github.com/divshot/gitling)
-- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
-- [andrerocker/deploy42](https://github.com/andrerocker/deploy42)
-- [elwinar/rambler](https://github.com/elwinar/rambler)
-- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman)
-- [jfbus/impressionist](https://github.com/jfbus/impressionist)
-- [Jmeyering/zealot](https://github.com/Jmeyering/zealot)
-- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host)
-- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go)
-- [thoas/picfit](https://github.com/thoas/picfit)
-- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
-- [jnuthong/item_search](https://github.com/jnuthong/item_search)
-- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
-- [containerssh/containerssh](https://github.com/containerssh/containerssh)
-- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
-- [tjpnz/structbot](https://github.com/tjpnz/structbot)
+Mergo is used by [thousands](https://deps.dev/go/dario.cat%2Fmergo/v1.0.0/dependents) [of](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.16/dependents) [projects](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.12), including:
+
+* [containerd/containerd](https://github.com/containerd/containerd)
+* [datadog/datadog-agent](https://github.com/datadog/datadog-agent)
+* [docker/cli/](https://github.com/docker/cli/)
+* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
+* [go-micro/go-micro](https://github.com/go-micro/go-micro)
+* [grafana/loki](https://github.com/grafana/loki)
+* [masterminds/sprig](github.com/Masterminds/sprig)
+* [moby/moby](https://github.com/moby/moby)
+* [slackhq/nebula](https://github.com/slackhq/nebula)
+* [volcano-sh/volcano](https://github.com/volcano-sh/volcano)
## Install
@@ -141,6 +117,39 @@ if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil {
}
```
+If you need to override pointers, so the source pointer's value is assigned to the destination's pointer, you must use `WithoutDereference`:
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "dario.cat/mergo"
+)
+
+type Foo struct {
+ A *string
+ B int64
+}
+
+func main() {
+ first := "first"
+ second := "second"
+ src := Foo{
+ A: &first,
+ B: 2,
+ }
+
+ dest := Foo{
+ A: &second,
+ B: 1,
+ }
+
+ mergo.Merge(&dest, src, mergo.WithOverride, mergo.WithoutDereference)
+}
+```
+
Additionally, you can map a `map[string]interface{}` to a struct (and otherwise, from struct to map), following the same restrictions as in `Merge()`. Keys are capitalized to find each corresponding exported field.
```go
@@ -181,10 +190,6 @@ func main() {
}
```
-Note: if test are failing due missing package, please execute:
-
- go get gopkg.in/yaml.v3
-
### Transformers
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
diff --git a/vendor/dario.cat/mergo/SECURITY.md b/vendor/dario.cat/mergo/SECURITY.md
index a5de61f77ba7..3788fcc1c212 100644
--- a/vendor/dario.cat/mergo/SECURITY.md
+++ b/vendor/dario.cat/mergo/SECURITY.md
@@ -4,8 +4,8 @@
| Version | Supported |
| ------- | ------------------ |
-| 0.3.x | :white_check_mark: |
-| < 0.3 | :x: |
+| 1.x.x | :white_check_mark: |
+| < 1.0 | :x: |
## Security contact information
diff --git a/vendor/dario.cat/mergo/map.go b/vendor/dario.cat/mergo/map.go
index b50d5c2a4e7c..759b4f74fd5a 100644
--- a/vendor/dario.cat/mergo/map.go
+++ b/vendor/dario.cat/mergo/map.go
@@ -58,7 +58,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf
}
fieldName := field.Name
fieldName = changeInitialCase(fieldName, unicode.ToLower)
- if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v), !config.ShouldNotDereference) || overwrite) {
+ if _, ok := dstMap[fieldName]; !ok || (!isEmptyValue(reflect.ValueOf(src.Field(i).Interface()), !config.ShouldNotDereference) && overwrite) || config.overwriteWithEmptyValue {
dstMap[fieldName] = src.Field(i).Interface()
}
}
diff --git a/vendor/dario.cat/mergo/merge.go b/vendor/dario.cat/mergo/merge.go
index 0ef9b2138c15..fd47c95b2b84 100644
--- a/vendor/dario.cat/mergo/merge.go
+++ b/vendor/dario.cat/mergo/merge.go
@@ -269,7 +269,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return
}
- } else {
+ } else if src.Elem().Kind() != reflect.Struct {
if overwriteWithEmptySrc || (overwrite && !src.IsNil()) || dst.IsNil() {
dst.Set(src)
}
diff --git a/vendor/github.com/Azure/go-ansiterm/SECURITY.md b/vendor/github.com/Azure/go-ansiterm/SECURITY.md
new file mode 100644
index 000000000000..e138ec5d6a77
--- /dev/null
+++ b/vendor/github.com/Azure/go-ansiterm/SECURITY.md
@@ -0,0 +1,41 @@
+
+
+## Security
+
+Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
+
+If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
+
+## Reporting Security Issues
+
+**Please do not report security vulnerabilities through public GitHub issues.**
+
+Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
+
+If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
+
+You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
+
+Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
+
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
+ * Full paths of source file(s) related to the manifestation of the issue
+ * The location of the affected source code (tag/branch/commit or direct URL)
+ * Any special configuration required to reproduce the issue
+ * Step-by-step instructions to reproduce the issue
+ * Proof-of-concept or exploit code (if possible)
+ * Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Policy
+
+Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
+
+
diff --git a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
index 593b10ab6963..194d5e9c94d3 100644
--- a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
+++ b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
@@ -11,21 +11,13 @@ func (oscState oscStringState) Handle(b byte) (s state, e error) {
return nextState, err
}
- switch {
- case isOscStringTerminator(b):
+ // There are several control characters and sequences which can
+ // terminate an OSC string. Most of them are handled by the baseState
+ // handler. The ANSI_BEL character is a special case which behaves as a
+ // terminator only for an OSC string.
+ if b == ANSI_BEL {
return oscState.parser.ground, nil
}
return oscState, nil
}
-
-// See below for OSC string terminators for linux
-// http://man7.org/linux/man-pages/man4/console_codes.4.html
-func isOscStringTerminator(b byte) bool {
-
- if b == ANSI_BEL || b == 0x5C {
- return true
- }
-
- return false
-}
diff --git a/vendor/github.com/Microsoft/hcsshim/osversion/osversion_windows.go b/vendor/github.com/Microsoft/hcsshim/osversion/osversion_windows.go
index 6c435d2b6495..3227ebe89c06 100644
--- a/vendor/github.com/Microsoft/hcsshim/osversion/osversion_windows.go
+++ b/vendor/github.com/Microsoft/hcsshim/osversion/osversion_windows.go
@@ -5,6 +5,7 @@ import (
"sync"
"golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/registry"
)
// OSVersion is a wrapper for Windows version information
@@ -25,16 +26,15 @@ var (
// The calling application must be manifested to get the correct version information.
func Get() OSVersion {
once.Do(func() {
- var err error
+ v := *windows.RtlGetVersion()
osv = OSVersion{}
- osv.Version, err = windows.GetVersion()
- if err != nil {
- // GetVersion never fails.
- panic(err)
- }
- osv.MajorVersion = uint8(osv.Version & 0xFF)
- osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
- osv.Build = uint16(osv.Version >> 16)
+ osv.MajorVersion = uint8(v.MajorVersion)
+ osv.MinorVersion = uint8(v.MinorVersion)
+ osv.Build = uint16(v.BuildNumber)
+ // Fill version value so that existing clients don't break
+ osv.Version = v.BuildNumber << 16
+ osv.Version = osv.Version | (uint32(v.MinorVersion) << 8)
+ osv.Version = osv.Version | v.MajorVersion
})
return osv
}
@@ -57,3 +57,18 @@ func (osv OSVersion) String() string {
func (osv OSVersion) ToString() string {
return osv.String()
}
+
+// Running `cmd /c ver` shows something like "10.0.20348.1000". The last component ("1000") is the revision
+// number
+func BuildRevision() (uint32, error) {
+ k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
+ if err != nil {
+ return 0, fmt.Errorf("open `CurrentVersion` registry key: %w", err)
+ }
+ defer k.Close()
+ s, _, err := k.GetIntegerValue("UBR")
+ if err != nil {
+ return 0, fmt.Errorf("read `UBR` from registry: %w", err)
+ }
+ return uint32(s), nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/osversion/platform_compat_windows.go b/vendor/github.com/Microsoft/hcsshim/osversion/platform_compat_windows.go
index f8d411ad7e2a..a7860895c710 100644
--- a/vendor/github.com/Microsoft/hcsshim/osversion/platform_compat_windows.go
+++ b/vendor/github.com/Microsoft/hcsshim/osversion/platform_compat_windows.go
@@ -3,7 +3,8 @@ package osversion
// List of stable ABI compliant ltsc releases
// Note: List must be sorted in ascending order
var compatLTSCReleases = []uint16{
- V21H2Server,
+ LTSC2022,
+ LTSC2025,
}
// CheckHostAndContainerCompat checks if given host and container
@@ -20,16 +21,25 @@ func CheckHostAndContainerCompat(host, ctr OSVersion) bool {
}
// If host is < WS 2022, exact version match is required
- if host.Build < V21H2Server {
+ if host.Build < LTSC2022 {
return host.Build == ctr.Build
}
- var supportedLtscRelease uint16
+ // Find the latest LTSC version that is earlier than the host version.
+ // This is the earliest version of container that the host can run.
+ //
+ // If the host version is an LTSC, then it supports compatibility with
+ // everything from the previous LTSC up to itself, so we want supportedLTSCRelease
+ // to be the previous entry.
+ //
+ // If no match is found, then we know that the host is LTSC2022 exactly,
+ // since we already checked that it's not less than LTSC2022.
+ var supportedLTSCRelease uint16 = LTSC2022
for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
- if host.Build >= compatLTSCReleases[i] {
- supportedLtscRelease = compatLTSCReleases[i]
+ if host.Build > compatLTSCReleases[i] {
+ supportedLTSCRelease = compatLTSCReleases[i]
break
}
}
- return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build
+ return supportedLTSCRelease <= ctr.Build && ctr.Build <= host.Build
}
diff --git a/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go b/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
index 446369591a80..5392a4cea1af 100644
--- a/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
+++ b/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
@@ -81,4 +81,11 @@ const (
// V22H2Win11 corresponds to Windows 11 (2022 Update).
V22H2Win11 = 22621
+
+ // V23H2 is the 23H2 release in the Windows Server annual channel.
+ V23H2 = 25398
+
+ // Windows Server 2025 build 26100
+ V25H1Server = 26100
+ LTSC2025 = V25H1Server
)
diff --git a/vendor/github.com/cenkalti/backoff/v4/README.md b/vendor/github.com/cenkalti/backoff/v4/README.md
index 16abdfc084f7..9433004a2809 100644
--- a/vendor/github.com/cenkalti/backoff/v4/README.md
+++ b/vendor/github.com/cenkalti/backoff/v4/README.md
@@ -1,4 +1,4 @@
-# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
+# 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].
@@ -21,8 +21,6 @@ Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
-[travis]: https://travis-ci.org/cenkalti/backoff
-[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
diff --git a/vendor/github.com/cenkalti/backoff/v4/exponential.go b/vendor/github.com/cenkalti/backoff/v4/exponential.go
index 2c56c1e7189b..aac99f196ad5 100644
--- a/vendor/github.com/cenkalti/backoff/v4/exponential.go
+++ b/vendor/github.com/cenkalti/backoff/v4/exponential.go
@@ -71,6 +71,9 @@ 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
@@ -81,7 +84,7 @@ const (
)
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
-func NewExponentialBackOff() *ExponentialBackOff {
+func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff {
b := &ExponentialBackOff{
InitialInterval: DefaultInitialInterval,
RandomizationFactor: DefaultRandomizationFactor,
@@ -91,10 +94,62 @@ func NewExponentialBackOff() *ExponentialBackOff {
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 {
diff --git a/vendor/github.com/cenkalti/backoff/v5/.gitignore b/vendor/github.com/cenkalti/backoff/v5/.gitignore
new file mode 100644
index 000000000000..50d95c548b67
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/.gitignore
@@ -0,0 +1,25 @@
+# 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/v5/CHANGELOG.md b/vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md
new file mode 100644
index 000000000000..658c37436d9c
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md
@@ -0,0 +1,29 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [5.0.0] - 2024-12-19
+
+### Added
+
+- RetryAfterError can be returned from an operation to indicate how long to wait before the next retry.
+
+### Changed
+
+- Retry function now accepts additional options for specifying max number of tries and max elapsed time.
+- Retry function now accepts a context.Context.
+- Operation function signature changed to return result (any type) and error.
+
+### Removed
+
+- RetryNotify* and RetryWithData functions. Only single Retry function remains.
+- Optional arguments from ExponentialBackoff constructor.
+- Clock and Timer interfaces.
+
+### Fixed
+
+- The original error is returned from Retry if there's a PermanentError. (#144)
+- The Retry function respects the wrapped PermanentError. (#140)
diff --git a/vendor/github.com/cenkalti/backoff/v5/LICENSE b/vendor/github.com/cenkalti/backoff/v5/LICENSE
new file mode 100644
index 000000000000..89b817996558
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/LICENSE
@@ -0,0 +1,20 @@
+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/v5/README.md b/vendor/github.com/cenkalti/backoff/v5/README.md
new file mode 100644
index 000000000000..4611b1d1701a
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/README.md
@@ -0,0 +1,31 @@
+# Exponential Backoff [![GoDoc][godoc image]][godoc]
+
+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/v5`. Please note the version part at the end.
+
+For most cases, use `Retry` function. See [example_test.go][example] for an example.
+
+If you have specific needs, copy `Retry` function (from [retry.go][retry-src]) into your code and modify it as needed.
+
+## 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/v5
+[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
+
+[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
+
+[retry-src]: https://github.com/cenkalti/backoff/blob/v5/retry.go
+[example]: https://github.com/cenkalti/backoff/blob/v5/example_test.go
diff --git a/vendor/github.com/cenkalti/backoff/v5/backoff.go b/vendor/github.com/cenkalti/backoff/v5/backoff.go
new file mode 100644
index 000000000000..dd2b24ca7350
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/backoff.go
@@ -0,0 +1,66 @@
+// 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,
+ // 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/v5/error.go b/vendor/github.com/cenkalti/backoff/v5/error.go
new file mode 100644
index 000000000000..beb2b38a23d7
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/error.go
@@ -0,0 +1,46 @@
+package backoff
+
+import (
+ "fmt"
+ "time"
+)
+
+// PermanentError signals that the operation should not be retried.
+type PermanentError struct {
+ Err error
+}
+
+// Permanent wraps the given err in a *PermanentError.
+func Permanent(err error) error {
+ if err == nil {
+ return nil
+ }
+ return &PermanentError{
+ Err: err,
+ }
+}
+
+// Error returns a string representation of the Permanent error.
+func (e *PermanentError) Error() string {
+ return e.Err.Error()
+}
+
+// Unwrap returns the wrapped error.
+func (e *PermanentError) Unwrap() error {
+ return e.Err
+}
+
+// RetryAfterError signals that the operation should be retried after the given duration.
+type RetryAfterError struct {
+ Duration time.Duration
+}
+
+// RetryAfter returns a RetryAfter error that specifies how long to wait before retrying.
+func RetryAfter(seconds int) error {
+ return &RetryAfterError{Duration: time.Duration(seconds) * time.Second}
+}
+
+// Error returns a string representation of the RetryAfter error.
+func (e *RetryAfterError) Error() string {
+ return fmt.Sprintf("retry after %s", e.Duration)
+}
diff --git a/vendor/github.com/cenkalti/backoff/v5/exponential.go b/vendor/github.com/cenkalti/backoff/v5/exponential.go
new file mode 100644
index 000000000000..79d425e87469
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/exponential.go
@@ -0,0 +1,118 @@
+package backoff
+
+import (
+ "math/rand/v2"
+ "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.
+
+Example: Given the following default arguments, for 9 tries the sequence will be:
+
+ 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]
+
+Note: Implementation is not thread-safe.
+*/
+type ExponentialBackOff struct {
+ InitialInterval time.Duration
+ RandomizationFactor float64
+ Multiplier float64
+ MaxInterval time.Duration
+
+ currentInterval time.Duration
+}
+
+// Default values for ExponentialBackOff.
+const (
+ DefaultInitialInterval = 500 * time.Millisecond
+ DefaultRandomizationFactor = 0.5
+ DefaultMultiplier = 1.5
+ DefaultMaxInterval = 60 * time.Second
+)
+
+// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
+func NewExponentialBackOff() *ExponentialBackOff {
+ return &ExponentialBackOff{
+ InitialInterval: DefaultInitialInterval,
+ RandomizationFactor: DefaultRandomizationFactor,
+ Multiplier: DefaultMultiplier,
+ MaxInterval: DefaultMaxInterval,
+ }
+}
+
+// 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
+}
+
+// NextBackOff calculates the next backoff interval using the formula:
+//
+// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
+func (b *ExponentialBackOff) NextBackOff() time.Duration {
+ if b.currentInterval == 0 {
+ b.currentInterval = b.InitialInterval
+ }
+
+ next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
+ b.incrementCurrentInterval()
+ return next
+}
+
+// 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/v5/retry.go b/vendor/github.com/cenkalti/backoff/v5/retry.go
new file mode 100644
index 000000000000..32a7f988347d
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/retry.go
@@ -0,0 +1,139 @@
+package backoff
+
+import (
+ "context"
+ "errors"
+ "time"
+)
+
+// DefaultMaxElapsedTime sets a default limit for the total retry duration.
+const DefaultMaxElapsedTime = 15 * time.Minute
+
+// Operation is a function that attempts an operation and may be retried.
+type Operation[T any] func() (T, error)
+
+// Notify is a function called on operation error with the error and backoff duration.
+type Notify func(error, time.Duration)
+
+// retryOptions holds configuration settings for the retry mechanism.
+type retryOptions struct {
+ BackOff BackOff // Strategy for calculating backoff periods.
+ Timer timer // Timer to manage retry delays.
+ Notify Notify // Optional function to notify on each retry error.
+ MaxTries uint // Maximum number of retry attempts.
+ MaxElapsedTime time.Duration // Maximum total time for all retries.
+}
+
+type RetryOption func(*retryOptions)
+
+// WithBackOff configures a custom backoff strategy.
+func WithBackOff(b BackOff) RetryOption {
+ return func(args *retryOptions) {
+ args.BackOff = b
+ }
+}
+
+// withTimer sets a custom timer for managing delays between retries.
+func withTimer(t timer) RetryOption {
+ return func(args *retryOptions) {
+ args.Timer = t
+ }
+}
+
+// WithNotify sets a notification function to handle retry errors.
+func WithNotify(n Notify) RetryOption {
+ return func(args *retryOptions) {
+ args.Notify = n
+ }
+}
+
+// WithMaxTries limits the number of all attempts.
+func WithMaxTries(n uint) RetryOption {
+ return func(args *retryOptions) {
+ args.MaxTries = n
+ }
+}
+
+// WithMaxElapsedTime limits the total duration for retry attempts.
+func WithMaxElapsedTime(d time.Duration) RetryOption {
+ return func(args *retryOptions) {
+ args.MaxElapsedTime = d
+ }
+}
+
+// Retry attempts the operation until success, a permanent error, or backoff completion.
+// It ensures the operation is executed at least once.
+//
+// Returns the operation result or error if retries are exhausted or context is cancelled.
+func Retry[T any](ctx context.Context, operation Operation[T], opts ...RetryOption) (T, error) {
+ // Initialize default retry options.
+ args := &retryOptions{
+ BackOff: NewExponentialBackOff(),
+ Timer: &defaultTimer{},
+ MaxElapsedTime: DefaultMaxElapsedTime,
+ }
+
+ // Apply user-provided options to the default settings.
+ for _, opt := range opts {
+ opt(args)
+ }
+
+ defer args.Timer.Stop()
+
+ startedAt := time.Now()
+ args.BackOff.Reset()
+ for numTries := uint(1); ; numTries++ {
+ // Execute the operation.
+ res, err := operation()
+ if err == nil {
+ return res, nil
+ }
+
+ // Stop retrying if maximum tries exceeded.
+ if args.MaxTries > 0 && numTries >= args.MaxTries {
+ return res, err
+ }
+
+ // Handle permanent errors without retrying.
+ var permanent *PermanentError
+ if errors.As(err, &permanent) {
+ return res, permanent.Unwrap()
+ }
+
+ // Stop retrying if context is cancelled.
+ if cerr := context.Cause(ctx); cerr != nil {
+ return res, cerr
+ }
+
+ // Calculate next backoff duration.
+ next := args.BackOff.NextBackOff()
+ if next == Stop {
+ return res, err
+ }
+
+ // Reset backoff if RetryAfterError is encountered.
+ var retryAfter *RetryAfterError
+ if errors.As(err, &retryAfter) {
+ next = retryAfter.Duration
+ args.BackOff.Reset()
+ }
+
+ // Stop retrying if maximum elapsed time exceeded.
+ if args.MaxElapsedTime > 0 && time.Since(startedAt)+next > args.MaxElapsedTime {
+ return res, err
+ }
+
+ // Notify on error if a notifier function is provided.
+ if args.Notify != nil {
+ args.Notify(err, next)
+ }
+
+ // Wait for the next backoff period or context cancellation.
+ args.Timer.Start(next)
+ select {
+ case <-args.Timer.C():
+ case <-ctx.Done():
+ return res, context.Cause(ctx)
+ }
+ }
+}
diff --git a/vendor/github.com/cenkalti/backoff/v5/ticker.go b/vendor/github.com/cenkalti/backoff/v5/ticker.go
new file mode 100644
index 000000000000..f0d4b2ae7213
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/ticker.go
@@ -0,0 +1,83 @@
+package backoff
+
+import (
+ "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
+ 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 {
+ c := make(chan time.Time)
+ t := &Ticker{
+ C: c,
+ c: c,
+ b: b,
+ timer: &defaultTimer{},
+ 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
+ }
+ }
+}
+
+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/v5/timer.go b/vendor/github.com/cenkalti/backoff/v5/timer.go
new file mode 100644
index 000000000000..a895309747da
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/v5/timer.go
@@ -0,0 +1,35 @@
+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/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md
index 8bf0e5b78153..33c88305c46e 100644
--- a/vendor/github.com/cespare/xxhash/v2/README.md
+++ b/vendor/github.com/cespare/xxhash/v2/README.md
@@ -70,3 +70,5 @@ benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$')
- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics)
- [FreeCache](https://github.com/coocood/freecache)
- [FastCache](https://github.com/VictoriaMetrics/fastcache)
+- [Ristretto](https://github.com/dgraph-io/ristretto)
+- [Badger](https://github.com/dgraph-io/badger)
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go
index a9e0d45c9dcc..78bddf1ceed7 100644
--- a/vendor/github.com/cespare/xxhash/v2/xxhash.go
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash.go
@@ -19,10 +19,13 @@ const (
// Store the primes in an array as well.
//
// The consts are used when possible in Go code to avoid MOVs but we need a
-// contiguous array of the assembly code.
+// contiguous array for the assembly code.
var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5}
// Digest implements hash.Hash64.
+//
+// Note that a zero-valued Digest is not ready to receive writes.
+// Call Reset or create a Digest using New before calling other methods.
type Digest struct {
v1 uint64
v2 uint64
@@ -33,19 +36,31 @@ type Digest struct {
n int // how much of mem is used
}
-// New creates a new Digest that computes the 64-bit xxHash algorithm.
+// New creates a new Digest with a zero seed.
func New() *Digest {
+ return NewWithSeed(0)
+}
+
+// NewWithSeed creates a new Digest with the given seed.
+func NewWithSeed(seed uint64) *Digest {
var d Digest
- d.Reset()
+ d.ResetWithSeed(seed)
return &d
}
// Reset clears the Digest's state so that it can be reused.
+// It uses a seed value of zero.
func (d *Digest) Reset() {
- d.v1 = primes[0] + prime2
- d.v2 = prime2
- d.v3 = 0
- d.v4 = -primes[0]
+ d.ResetWithSeed(0)
+}
+
+// ResetWithSeed clears the Digest's state so that it can be reused.
+// It uses the given seed to initialize the state.
+func (d *Digest) ResetWithSeed(seed uint64) {
+ d.v1 = seed + prime1 + prime2
+ d.v2 = seed + prime2
+ d.v3 = seed
+ d.v4 = seed - prime1
d.total = 0
d.n = 0
}
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go
index 9216e0a40c1a..78f95f256103 100644
--- a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go
@@ -6,7 +6,7 @@
package xxhash
-// Sum64 computes the 64-bit xxHash digest of b.
+// Sum64 computes the 64-bit xxHash digest of b with a zero seed.
//
//go:noescape
func Sum64(b []byte) uint64
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go
index 26df13bba4b7..118e49e819e0 100644
--- a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go
@@ -3,7 +3,7 @@
package xxhash
-// Sum64 computes the 64-bit xxHash digest of b.
+// Sum64 computes the 64-bit xxHash digest of b with a zero seed.
func Sum64(b []byte) uint64 {
// A simpler version would be
// d := New()
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
index e86f1b5fd8e4..05f5e7dfe7b7 100644
--- a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
@@ -5,7 +5,7 @@
package xxhash
-// Sum64String computes the 64-bit xxHash digest of s.
+// Sum64String computes the 64-bit xxHash digest of s with a zero seed.
func Sum64String(s string) uint64 {
return Sum64([]byte(s))
}
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
index 1c1638fd88a1..cf9d42aed536 100644
--- a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
@@ -33,7 +33,7 @@ import (
//
// See https://github.com/golang/go/issues/42739 for discussion.
-// Sum64String computes the 64-bit xxHash digest of s.
+// Sum64String computes the 64-bit xxHash digest of s with a zero seed.
// It may be faster than Sum64([]byte(s)) by avoiding a copy.
func Sum64String(s string) uint64 {
b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))
diff --git a/vendor/github.com/containerd/platforms/.golangci.yml b/vendor/github.com/containerd/platforms/.golangci.yml
index a695775df49d..d574fe11d79f 100644
--- a/vendor/github.com/containerd/platforms/.golangci.yml
+++ b/vendor/github.com/containerd/platforms/.golangci.yml
@@ -1,6 +1,6 @@
linters:
enable:
- - exportloopref # Checks for pointers to enclosing loop variables
+ - copyloopvar
- gofmt
- goimports
- gosec
@@ -12,14 +12,16 @@ linters:
- tenv # Detects using os.Setenv instead of t.Setenv since Go 1.17
- unconvert
- unused
- - vet
+ - govet
- dupword # Checks for duplicate words in the source code
disable:
- errcheck
run:
timeout: 5m
- skip-dirs:
+
+issues:
+ exclude-dirs:
- api
- cluster
- design
diff --git a/vendor/github.com/containerd/platforms/compare.go b/vendor/github.com/containerd/platforms/compare.go
index 3913ef663731..24403f3b3d45 100644
--- a/vendor/github.com/containerd/platforms/compare.go
+++ b/vendor/github.com/containerd/platforms/compare.go
@@ -31,6 +31,34 @@ type MatchComparer interface {
Less(specs.Platform, specs.Platform) bool
}
+type platformVersions struct {
+ major []int
+ minor []int
+}
+
+var arm64variantToVersion = map[string]platformVersions{
+ "v8": {[]int{8}, []int{0}},
+ "v8.0": {[]int{8}, []int{0}},
+ "v8.1": {[]int{8}, []int{1}},
+ "v8.2": {[]int{8}, []int{2}},
+ "v8.3": {[]int{8}, []int{3}},
+ "v8.4": {[]int{8}, []int{4}},
+ "v8.5": {[]int{8}, []int{5}},
+ "v8.6": {[]int{8}, []int{6}},
+ "v8.7": {[]int{8}, []int{7}},
+ "v8.8": {[]int{8}, []int{8}},
+ "v8.9": {[]int{8}, []int{9}},
+ "v9": {[]int{9, 8}, []int{0, 5}},
+ "v9.0": {[]int{9, 8}, []int{0, 5}},
+ "v9.1": {[]int{9, 8}, []int{1, 6}},
+ "v9.2": {[]int{9, 8}, []int{2, 7}},
+ "v9.3": {[]int{9, 8}, []int{3, 8}},
+ "v9.4": {[]int{9, 8}, []int{4, 9}},
+ "v9.5": {[]int{9, 8}, []int{5, 9}},
+ "v9.6": {[]int{9, 8}, []int{6, 9}},
+ "v9.7": {[]int{9, 8}, []int{7, 9}},
+}
+
// platformVector returns an (ordered) vector of appropriate specs.Platform
// objects to try matching for the given platform object (see platforms.Only).
func platformVector(platform specs.Platform) []specs.Platform {
@@ -72,6 +100,33 @@ func platformVector(platform specs.Platform) []specs.Platform {
if variant == "" {
variant = "v8"
}
+
+ vector = []specs.Platform{} // Reset vector, the first variant will be added in loop.
+ arm64Versions, ok := arm64variantToVersion[variant]
+ if !ok {
+ break
+ }
+ for i, major := range arm64Versions.major {
+ for minor := arm64Versions.minor[i]; minor >= 0; minor-- {
+ arm64Variant := "v" + strconv.Itoa(major) + "." + strconv.Itoa(minor)
+ if minor == 0 {
+ arm64Variant = "v" + strconv.Itoa(major)
+ }
+ vector = append(vector, specs.Platform{
+ Architecture: "arm64",
+ OS: platform.OS,
+ OSVersion: platform.OSVersion,
+ OSFeatures: platform.OSFeatures,
+ Variant: arm64Variant,
+ })
+ }
+ }
+
+ // All arm64/v8.x and arm64/v9.x are compatible with arm/v8 (32-bits) and below.
+ // There's no arm64 v9 variant, so it's normalized to v8.
+ if strings.HasPrefix(variant, "v8") || strings.HasPrefix(variant, "v9") {
+ variant = "v8"
+ }
vector = append(vector, platformVector(specs.Platform{
Architecture: "arm",
OS: platform.OS,
@@ -87,6 +142,8 @@ func platformVector(platform specs.Platform) []specs.Platform {
// Only returns a match comparer for a single platform
// using default resolution logic for the platform.
//
+// For arm64/v9.x, will also match arm64/v9.{0..x-1} and arm64/v8.{0..x+5}
+// For arm64/v8.x, will also match arm64/v8.{0..x-1}
// For arm/v8, will also match arm/v7, arm/v6 and arm/v5
// For arm/v7, will also match arm/v6 and arm/v5
// For arm/v6, will also match arm/v5
diff --git a/vendor/github.com/containerd/platforms/database.go b/vendor/github.com/containerd/platforms/database.go
index 2e26fd3b4fae..7a6f0d98cdda 100644
--- a/vendor/github.com/containerd/platforms/database.go
+++ b/vendor/github.com/containerd/platforms/database.go
@@ -87,8 +87,10 @@ func normalizeArch(arch, variant string) (string, string) {
case "aarch64", "arm64":
arch = "arm64"
switch variant {
- case "8", "v8":
+ case "8", "v8", "v8.0":
variant = ""
+ case "9", "9.0", "v9.0":
+ variant = "v9"
}
case "armhf":
arch = "arm"
diff --git a/vendor/github.com/containerd/platforms/defaults_windows.go b/vendor/github.com/containerd/platforms/defaults_windows.go
index 427ed72eb617..64e284667480 100644
--- a/vendor/github.com/containerd/platforms/defaults_windows.go
+++ b/vendor/github.com/containerd/platforms/defaults_windows.go
@@ -19,8 +19,6 @@ package platforms
import (
"fmt"
"runtime"
- "strconv"
- "strings"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sys/windows"
@@ -38,81 +36,7 @@ func DefaultSpec() specs.Platform {
}
}
-type windowsmatcher struct {
- specs.Platform
- osVersionPrefix string
- defaultMatcher Matcher
-}
-
-// Match matches platform with the same windows major, minor
-// and build version.
-func (m windowsmatcher) Match(p specs.Platform) bool {
- match := m.defaultMatcher.Match(p)
-
- if match && m.OS == "windows" {
- // HPC containers do not have OS version filled
- if m.OSVersion == "" || p.OSVersion == "" {
- return true
- }
-
- hostOsVersion := getOSVersion(m.osVersionPrefix)
- ctrOsVersion := getOSVersion(p.OSVersion)
- return checkHostAndContainerCompat(hostOsVersion, ctrOsVersion)
- }
-
- return match
-}
-
-func getOSVersion(osVersionPrefix string) osVersion {
- parts := strings.Split(osVersionPrefix, ".")
- if len(parts) < 3 {
- return osVersion{}
- }
-
- majorVersion, _ := strconv.Atoi(parts[0])
- minorVersion, _ := strconv.Atoi(parts[1])
- buildNumber, _ := strconv.Atoi(parts[2])
-
- return osVersion{
- MajorVersion: uint8(majorVersion),
- MinorVersion: uint8(minorVersion),
- Build: uint16(buildNumber),
- }
-}
-
-// Less sorts matched platforms in front of other platforms.
-// For matched platforms, it puts platforms with larger revision
-// number in front.
-func (m windowsmatcher) Less(p1, p2 specs.Platform) bool {
- m1, m2 := m.Match(p1), m.Match(p2)
- if m1 && m2 {
- r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion)
- return r1 > r2
- }
- return m1 && !m2
-}
-
-func revision(v string) int {
- parts := strings.Split(v, ".")
- if len(parts) < 4 {
- return 0
- }
- r, err := strconv.Atoi(parts[3])
- if err != nil {
- return 0
- }
- return r
-}
-
-func prefix(v string) string {
- parts := strings.Split(v, ".")
- if len(parts) < 4 {
- return v
- }
- return strings.Join(parts[0:3], ".")
-}
-
// Default returns the current platform's default platform specification.
func Default() MatchComparer {
- return Only(DefaultSpec())
+ return &windowsMatchComparer{Matcher: NewMatcher(DefaultSpec())}
}
diff --git a/vendor/github.com/containerd/platforms/platform_compat_windows.go b/vendor/github.com/containerd/platforms/platform_compat_windows.go
deleted file mode 100644
index 89e66f0c0903..000000000000
--- a/vendor/github.com/containerd/platforms/platform_compat_windows.go
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- Copyright The containerd 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 platforms
-
-// osVersion is a wrapper for Windows version information
-// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
-type osVersion struct {
- Version uint32
- MajorVersion uint8
- MinorVersion uint8
- Build uint16
-}
-
-// Windows Client and Server build numbers.
-//
-// See:
-// https://learn.microsoft.com/en-us/windows/release-health/release-information
-// https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info
-// https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information
-const (
- // rs5 (version 1809, codename "Redstone 5") corresponds to Windows Server
- // 2019 (ltsc2019), and Windows 10 (October 2018 Update).
- rs5 = 17763
-
- // v21H2Server corresponds to Windows Server 2022 (ltsc2022).
- v21H2Server = 20348
-
- // v22H2Win11 corresponds to Windows 11 (2022 Update).
- v22H2Win11 = 22621
-)
-
-// List of stable ABI compliant ltsc releases
-// Note: List must be sorted in ascending order
-var compatLTSCReleases = []uint16{
- v21H2Server,
-}
-
-// CheckHostAndContainerCompat checks if given host and container
-// OS versions are compatible.
-// It includes support for stable ABI compliant versions as well.
-// Every release after WS 2022 will support the previous ltsc
-// container image. Stable ABI is in preview mode for windows 11 client.
-// Refer: https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-2022%2Cwindows-10#windows-server-host-os-compatibility
-func checkHostAndContainerCompat(host, ctr osVersion) bool {
- // check major minor versions of host and guest
- if host.MajorVersion != ctr.MajorVersion ||
- host.MinorVersion != ctr.MinorVersion {
- return false
- }
-
- // If host is < WS 2022, exact version match is required
- if host.Build < v21H2Server {
- return host.Build == ctr.Build
- }
-
- var supportedLtscRelease uint16
- for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
- if host.Build >= compatLTSCReleases[i] {
- supportedLtscRelease = compatLTSCReleases[i]
- break
- }
- }
- return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build
-}
diff --git a/vendor/github.com/containerd/platforms/platform_windows_compat.go b/vendor/github.com/containerd/platforms/platform_windows_compat.go
new file mode 100644
index 000000000000..f31ebe0c9e2e
--- /dev/null
+++ b/vendor/github.com/containerd/platforms/platform_windows_compat.go
@@ -0,0 +1,164 @@
+/*
+ Copyright The containerd 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 platforms
+
+import (
+ "strconv"
+ "strings"
+
+ specs "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+// windowsOSVersion is a wrapper for Windows version information
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
+type windowsOSVersion struct {
+ Version uint32
+ MajorVersion uint8
+ MinorVersion uint8
+ Build uint16
+}
+
+// Windows Client and Server build numbers.
+//
+// See:
+// https://learn.microsoft.com/en-us/windows/release-health/release-information
+// https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info
+// https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information
+const (
+ // rs5 (version 1809, codename "Redstone 5") corresponds to Windows Server
+ // 2019 (ltsc2019), and Windows 10 (October 2018 Update).
+ rs5 = 17763
+ // ltsc2019 (Windows Server 2019) is an alias for [RS5].
+ ltsc2019 = rs5
+
+ // v21H2Server corresponds to Windows Server 2022 (ltsc2022).
+ v21H2Server = 20348
+ // ltsc2022 (Windows Server 2022) is an alias for [v21H2Server]
+ ltsc2022 = v21H2Server
+
+ // v22H2Win11 corresponds to Windows 11 (2022 Update).
+ v22H2Win11 = 22621
+
+ // v23H2 is the 23H2 release in the Windows Server annual channel.
+ v23H2 = 25398
+
+ // Windows Server 2025 build 26100
+ v25H1Server = 26100
+ ltsc2025 = v25H1Server
+)
+
+// List of stable ABI compliant ltsc releases
+// Note: List must be sorted in ascending order
+var compatLTSCReleases = []uint16{
+ ltsc2022,
+ ltsc2025,
+}
+
+// CheckHostAndContainerCompat checks if given host and container
+// OS versions are compatible.
+// It includes support for stable ABI compliant versions as well.
+// Every release after WS 2022 will support the previous ltsc
+// container image. Stable ABI is in preview mode for windows 11 client.
+// Refer: https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-2022%2Cwindows-10#windows-server-host-os-compatibility
+func checkWindowsHostAndContainerCompat(host, ctr windowsOSVersion) bool {
+ // check major minor versions of host and guest
+ if host.MajorVersion != ctr.MajorVersion ||
+ host.MinorVersion != ctr.MinorVersion {
+ return false
+ }
+
+ // If host is < WS 2022, exact version match is required
+ if host.Build < ltsc2022 {
+ return host.Build == ctr.Build
+ }
+
+ // Find the latest LTSC version that is earlier than the host version.
+ // This is the earliest version of container that the host can run.
+ //
+ // If the host version is an LTSC, then it supports compatibility with
+ // everything from the previous LTSC up to itself, so we want supportedLTSCRelease
+ // to be the previous entry.
+ //
+ // If no match is found, then we know that the host is LTSC2022 exactly,
+ // since we already checked that it's not less than LTSC2022.
+ var supportedLTSCRelease uint16 = ltsc2022
+ for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
+ if host.Build > compatLTSCReleases[i] {
+ supportedLTSCRelease = compatLTSCReleases[i]
+ break
+ }
+ }
+ return supportedLTSCRelease <= ctr.Build && ctr.Build <= host.Build
+}
+
+func getWindowsOSVersion(osVersionPrefix string) windowsOSVersion {
+ if strings.Count(osVersionPrefix, ".") < 2 {
+ return windowsOSVersion{}
+ }
+
+ major, extra, _ := strings.Cut(osVersionPrefix, ".")
+ minor, extra, _ := strings.Cut(extra, ".")
+ build, _, _ := strings.Cut(extra, ".")
+
+ majorVersion, err := strconv.ParseUint(major, 10, 8)
+ if err != nil {
+ return windowsOSVersion{}
+ }
+
+ minorVersion, err := strconv.ParseUint(minor, 10, 8)
+ if err != nil {
+ return windowsOSVersion{}
+ }
+ buildNumber, err := strconv.ParseUint(build, 10, 16)
+ if err != nil {
+ return windowsOSVersion{}
+ }
+
+ return windowsOSVersion{
+ MajorVersion: uint8(majorVersion),
+ MinorVersion: uint8(minorVersion),
+ Build: uint16(buildNumber),
+ }
+}
+
+type windowsVersionMatcher struct {
+ windowsOSVersion
+}
+
+func (m windowsVersionMatcher) Match(v string) bool {
+ if m.isEmpty() || v == "" {
+ return true
+ }
+ osv := getWindowsOSVersion(v)
+ return checkWindowsHostAndContainerCompat(m.windowsOSVersion, osv)
+}
+
+func (m windowsVersionMatcher) isEmpty() bool {
+ return m.MajorVersion == 0 && m.MinorVersion == 0 && m.Build == 0
+}
+
+type windowsMatchComparer struct {
+ Matcher
+}
+
+func (c *windowsMatchComparer) Less(p1, p2 specs.Platform) bool {
+ m1, m2 := c.Match(p1), c.Match(p2)
+ if m1 && m2 {
+ return p1.OSVersion > p2.OSVersion
+ }
+ return m1 && !m2
+}
diff --git a/vendor/github.com/containerd/platforms/platforms.go b/vendor/github.com/containerd/platforms/platforms.go
index 1bbbdb91dbc2..14d65abd4f86 100644
--- a/vendor/github.com/containerd/platforms/platforms.go
+++ b/vendor/github.com/containerd/platforms/platforms.go
@@ -121,7 +121,7 @@ import (
)
var (
- specifierRe = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
+ specifierRe = regexp.MustCompile(`^[A-Za-z0-9_.-]+$`)
osAndVersionRe = regexp.MustCompile(`^([A-Za-z0-9_-]+)(?:\(([A-Za-z0-9_.-]*)\))?$`)
)
@@ -144,18 +144,51 @@ type Matcher interface {
//
// Applications should opt to use `Match` over directly parsing specifiers.
func NewMatcher(platform specs.Platform) Matcher {
- return newDefaultMatcher(platform)
+ m := &matcher{
+ Platform: Normalize(platform),
+ }
+
+ if platform.OS == "windows" {
+ m.osvM = &windowsVersionMatcher{
+ windowsOSVersion: getWindowsOSVersion(platform.OSVersion),
+ }
+ // In prior versions, on windows, the returned matcher implements a
+ // MatchComprarer interface.
+ // This preserves that behavior for backwards compatibility.
+ //
+ // TODO: This isn't actually used in this package, except for a test case,
+ // which may have been an unintended side of some refactor.
+ // It was likely intended to be used in `Ordered` but it is not since
+ // `Less` that is implemented here ends up getting masked due to wrapping.
+ if runtime.GOOS == "windows" {
+ return &windowsMatchComparer{m}
+ }
+ }
+ return m
+}
+
+type osVerMatcher interface {
+ Match(string) bool
}
type matcher struct {
specs.Platform
+ osvM osVerMatcher
}
func (m *matcher) Match(platform specs.Platform) bool {
normalized := Normalize(platform)
return m.OS == normalized.OS &&
m.Architecture == normalized.Architecture &&
- m.Variant == normalized.Variant
+ m.Variant == normalized.Variant &&
+ m.matchOSVersion(platform)
+}
+
+func (m *matcher) matchOSVersion(platform specs.Platform) bool {
+ if m.osvM != nil {
+ return m.osvM.Match(platform.OSVersion)
+ }
+ return true
}
func (m *matcher) String() string {
diff --git a/vendor/github.com/containerd/platforms/platforms_other.go b/vendor/github.com/containerd/platforms/platforms_other.go
deleted file mode 100644
index 03f4dcd99814..000000000000
--- a/vendor/github.com/containerd/platforms/platforms_other.go
+++ /dev/null
@@ -1,30 +0,0 @@
-//go:build !windows
-
-/*
- Copyright The containerd 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 platforms
-
-import (
- specs "github.com/opencontainers/image-spec/specs-go/v1"
-)
-
-// NewMatcher returns the default Matcher for containerd
-func newDefaultMatcher(platform specs.Platform) Matcher {
- return &matcher{
- Platform: Normalize(platform),
- }
-}
diff --git a/vendor/github.com/containerd/platforms/platforms_windows.go b/vendor/github.com/containerd/platforms/platforms_windows.go
deleted file mode 100644
index 950e2a2ddbb5..000000000000
--- a/vendor/github.com/containerd/platforms/platforms_windows.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- Copyright The containerd 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 platforms
-
-import (
- specs "github.com/opencontainers/image-spec/specs-go/v1"
-)
-
-// NewMatcher returns a Windows matcher that will match on osVersionPrefix if
-// the platform is Windows otherwise use the default matcher
-func newDefaultMatcher(platform specs.Platform) Matcher {
- prefix := prefix(platform.OSVersion)
- return windowsmatcher{
- Platform: platform,
- osVersionPrefix: prefix,
- defaultMatcher: &matcher{
- Platform: Normalize(platform),
- },
- }
-}
diff --git a/vendor/google.golang.org/genproto/internal/doc.go b/vendor/github.com/coreos/go-systemd/v22/daemon/sdnotify_other.go
similarity index 69%
rename from vendor/google.golang.org/genproto/internal/doc.go
rename to vendor/github.com/coreos/go-systemd/v22/daemon/sdnotify_other.go
index 90e89b4aa3ff..d6309495d4de 100644
--- a/vendor/google.golang.org/genproto/internal/doc.go
+++ b/vendor/github.com/coreos/go-systemd/v22/daemon/sdnotify_other.go
@@ -1,10 +1,10 @@
-// Copyright 2023 Google LLC
+// Copyright 2025
//
// 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
+// 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,
@@ -12,6 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// This file makes internal an importable go package
-// for use with backreferences from submodules.
-package internal
+//go:build !unix
+
+package daemon
+
+// SdNotifyMonotonicUsec returns the empty string on unsupported platforms.
+func SdNotifyMonotonicUsec() string {
+ return ""
+}
diff --git a/vendor/github.com/coreos/go-systemd/v22/daemon/sdnotify_unix.go b/vendor/github.com/coreos/go-systemd/v22/daemon/sdnotify_unix.go
new file mode 100644
index 000000000000..bdbe6b0c281f
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/v22/daemon/sdnotify_unix.go
@@ -0,0 +1,36 @@
+// Copyright 2025
+//
+// 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 unix
+
+package daemon
+
+import (
+ "strconv"
+
+ "golang.org/x/sys/unix"
+)
+
+// SdNotifyMonotonicUsec returns a MONOTONIC_USEC=... assignment for the current time
+// with a trailing newline included. This is typically used with [SdNotifyReloading].
+//
+// If the monotonic clock is not available on the system, the empty string is returned.
+func SdNotifyMonotonicUsec() string {
+ var ts unix.Timespec
+ if err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts); err != nil {
+ // Monotonic clock is not available on this system.
+ return ""
+ }
+ return "MONOTONIC_USEC=" + strconv.FormatInt(ts.Nano()/1000, 10) + "\n"
+}
diff --git a/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go b/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go
index 25d9c1aa9387..a93314d0ab8d 100644
--- a/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go
+++ b/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go
@@ -15,6 +15,7 @@
package daemon
import (
+ "errors"
"fmt"
"os"
"strconv"
@@ -51,10 +52,10 @@ func SdWatchdogEnabled(unsetEnvironment bool) (time.Duration, error) {
}
s, err := strconv.Atoi(wusec)
if err != nil {
- return 0, fmt.Errorf("error converting WATCHDOG_USEC: %s", err)
+ return 0, fmt.Errorf("error converting WATCHDOG_USEC: %w", err)
}
if s <= 0 {
- return 0, fmt.Errorf("error WATCHDOG_USEC must be a positive number")
+ return 0, errors.New("error WATCHDOG_USEC must be a positive number")
}
interval := time.Duration(s) * time.Microsecond
@@ -63,7 +64,7 @@ func SdWatchdogEnabled(unsetEnvironment bool) (time.Duration, error) {
}
p, err := strconv.Atoi(wpid)
if err != nil {
- return 0, fmt.Errorf("error converting WATCHDOG_PID: %s", err)
+ return 0, fmt.Errorf("error converting WATCHDOG_PID: %w", err)
}
if os.Getpid() != p {
return 0, nil
diff --git a/vendor/github.com/coreos/go-systemd/v22/journal/journal.go b/vendor/github.com/coreos/go-systemd/v22/journal/journal.go
index ac24c7767d35..16c4e47751c3 100644
--- a/vendor/github.com/coreos/go-systemd/v22/journal/journal.go
+++ b/vendor/github.com/coreos/go-systemd/v22/journal/journal.go
@@ -41,6 +41,6 @@ const (
)
// Print prints a message to the local systemd journal using Send().
-func Print(priority Priority, format string, a ...interface{}) error {
+func Print(priority Priority, format string, a ...any) error {
return Send(fmt.Sprintf(format, a...), priority, nil)
}
diff --git a/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go b/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go
index c5b23a81968f..55cb9eb26a1b 100644
--- a/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go
+++ b/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go
@@ -13,7 +13,6 @@
// limitations under the License.
//go:build !windows
-// +build !windows
// Package journal provides write bindings to the local systemd journal.
// It is implemented in pure Go and connects to the journal directly over its
@@ -31,7 +30,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net"
"os"
"strconv"
@@ -108,7 +106,7 @@ func fdIsJournalStream(fd int) (bool, error) {
var expectedStat syscall.Stat_t
_, err := fmt.Sscanf(journalStream, "%d:%d", &expectedStat.Dev, &expectedStat.Ino)
if err != nil {
- return false, fmt.Errorf("failed to parse JOURNAL_STREAM=%q: %v", journalStream, err)
+ return false, fmt.Errorf("failed to parse JOURNAL_STREAM=%q: %w", journalStream, err)
}
var stat syscall.Stat_t
@@ -194,7 +192,7 @@ func appendVariable(w io.Writer, name, value string) {
* - the data, followed by a newline
*/
fmt.Fprintln(w, name)
- binary.Write(w, binary.LittleEndian, uint64(len(value)))
+ _ = binary.Write(w, binary.LittleEndian, uint64(len(value)))
fmt.Fprintln(w, value)
} else {
/* just write the variable and value all on one line */
@@ -214,7 +212,7 @@ func validVarName(name string) error {
}
for _, c := range name {
- if !(('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_') {
+ if ('A' > c || c > 'Z') && ('0' > c || c > '9') && c != '_' {
return errors.New("Variable name contains invalid characters")
}
}
@@ -239,7 +237,7 @@ func isSocketSpaceError(err error) bool {
// tempFd creates a temporary, unlinked file under `/dev/shm`.
func tempFd() (*os.File, error) {
- file, err := ioutil.TempFile("/dev/shm/", "journal.XXXXX")
+ file, err := os.CreateTemp("/dev/shm/", "journal.XXXXX")
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/coreos/go-systemd/v22/unit/deserialize.go b/vendor/github.com/coreos/go-systemd/v22/unit/deserialize.go
index 283c1507713c..7796e1695639 100644
--- a/vendor/github.com/coreos/go-systemd/v22/unit/deserialize.go
+++ b/vendor/github.com/coreos/go-systemd/v22/unit/deserialize.go
@@ -38,10 +38,8 @@ const (
SYSTEMD_NEWLINE = "\r\n"
)
-var (
- // ErrLineTooLong gets returned when a line is too long for systemd to handle.
- ErrLineTooLong = fmt.Errorf("line too long (max %d bytes)", SYSTEMD_LINE_MAX)
-)
+// ErrLineTooLong gets returned when a line is too long for systemd to handle.
+var ErrLineTooLong = fmt.Errorf("line too long (max %d bytes)", SYSTEMD_LINE_MAX)
// DeserializeOptions parses a systemd unit file into a list of UnitOptions
func DeserializeOptions(f io.Reader) (opts []*UnitOption, err error) {
@@ -56,8 +54,8 @@ func DeserializeSections(f io.Reader) ([]*UnitSection, error) {
}
// Deserialize parses a systemd unit file into a list of UnitOptions.
-// Note: this function is deprecated in favor of DeserializeOptions
-// and will be removed at a future date.
+//
+// Deprecated: use [DeserializeOptions] instead.
func Deserialize(f io.Reader) (opts []*UnitOption, err error) {
return DeserializeOptions(f)
}
@@ -79,7 +77,6 @@ type lexData struct {
// deserializeAll deserializes into UnitSections and UnitOptions.
func deserializeAll(f io.Reader) ([]*UnitSection, []*UnitOption, error) {
-
lexer, lexchan, errchan := newLexer(f)
go lexer.lex()
@@ -92,13 +89,12 @@ func deserializeAll(f io.Reader) ([]*UnitSection, []*UnitOption, error) {
case optionKind:
if ld.Option != nil {
// add to options
- opt := ld.Option
- options = append(options, &(*opt))
+ opt := *ld.Option
+ options = append(options, &opt)
// sanity check. "should not happen" as sectionKind is first in code flow.
if len(sections) == 0 {
- return nil, nil, fmt.Errorf(
- "Unit file misparse: option before section")
+ return nil, nil, errors.New("unit file misparse: option before section")
}
// add to newest section entries.
@@ -255,7 +251,7 @@ func (l *lexer) lexNextSectionOrOptionFunc(section string) lexStep {
return l.ignoreLineFunc(l.lexNextSectionOrOptionFunc(section)), nil
}
- l.buf.UnreadRune()
+ _ = l.buf.UnreadRune() // This can't fail as we just called ReadRune.
return l.lexOptionNameFunc(section), nil
}
}
@@ -287,29 +283,23 @@ func (l *lexer) lexOptionNameFunc(section string) lexStep {
func (l *lexer) lexOptionValueFunc(section, name string, partial bytes.Buffer) lexStep {
return func() (lexStep, error) {
- for {
- line, eof, err := l.toEOL()
- if err != nil {
- return nil, err
- }
-
- if len(bytes.TrimSpace(line)) == 0 {
- break
- }
+ line, eof, err := l.toEOL()
+ if err != nil {
+ return nil, err
+ }
+ if len(bytes.TrimSpace(line)) != 0 {
partial.Write(line)
// lack of continuation means this value has been exhausted
- idx := bytes.LastIndex(line, []byte{'\\'})
- if idx == -1 || idx != (len(line)-1) {
- break
- }
+ if bytes.HasSuffix(line, []byte{'\\'}) {
+ // line ends with backslash, continue parsing
+ if !eof {
+ partial.WriteRune('\n')
+ }
- if !eof {
- partial.WriteRune('\n')
+ return l.lexOptionValueFunc(section, name, partial), nil
}
-
- return l.lexOptionValueFunc(section, name, partial), nil
}
val := partial.String()
diff --git a/vendor/github.com/coreos/go-systemd/v22/unit/doc.go b/vendor/github.com/coreos/go-systemd/v22/unit/doc.go
new file mode 100644
index 000000000000..1c265e4aa2d5
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/v22/unit/doc.go
@@ -0,0 +1,12 @@
+// Package unit provides utilities for parsing, serializing, and manipulating
+// systemd unit files. It supports both reading unit file content into Go data
+// structures and writing Go data structures back to unit file format.
+//
+// The package provides functionality to:
+// - Parse systemd unit files into [UnitOption] and [UnitSection] structures
+// - Serialize Go structures back into unit file format
+// - Escape and unescape unit names according to systemd conventions
+//
+// Unit files are configuration files that describe how systemd should manage
+// services, sockets, devices, and other system resources.
+package unit
diff --git a/vendor/github.com/coreos/go-systemd/v22/unit/escape.go b/vendor/github.com/coreos/go-systemd/v22/unit/escape.go
index 98e2044a7171..df9c8cc13f81 100644
--- a/vendor/github.com/coreos/go-systemd/v22/unit/escape.go
+++ b/vendor/github.com/coreos/go-systemd/v22/unit/escape.go
@@ -57,7 +57,7 @@ func escape(unescaped string, isPath bool) string {
if c == '/' {
e = append(e, '-')
} else if start && c == '.' || strings.IndexByte(allowed, c) == -1 {
- e = append(e, []byte(fmt.Sprintf(`\x%x`, c))...)
+ e = fmt.Appendf(e, `\x%x`, c)
} else {
e = append(e, c)
}
diff --git a/vendor/github.com/coreos/go-systemd/v22/unit/option.go b/vendor/github.com/coreos/go-systemd/v22/unit/option.go
index 98e1af5c99a7..800ecda44983 100644
--- a/vendor/github.com/coreos/go-systemd/v22/unit/option.go
+++ b/vendor/github.com/coreos/go-systemd/v22/unit/option.go
@@ -49,7 +49,7 @@ func AllMatch(u1 []*UnitOption, u2 []*UnitOption) bool {
return false
}
- for i := 0; i < length; i++ {
+ for i := range length {
if !u1[i].Match(u2[i]) {
return false
}
diff --git a/vendor/github.com/coreos/go-systemd/v22/unit/serialize.go b/vendor/github.com/coreos/go-systemd/v22/unit/serialize.go
index c1b79c02dc21..25577065935d 100644
--- a/vendor/github.com/coreos/go-systemd/v22/unit/serialize.go
+++ b/vendor/github.com/coreos/go-systemd/v22/unit/serialize.go
@@ -61,7 +61,6 @@ func Serialize(opts []*UnitOption) io.Reader {
// SerializeSections will serializes the unit file from the given
// UnitSections.
func SerializeSections(sections []*UnitSection) io.Reader {
-
var buf bytes.Buffer
for i, s := range sections {
diff --git a/vendor/github.com/docker/go-connections/nat/nat.go b/vendor/github.com/docker/go-connections/nat/nat.go
index 4049d780c54a..d46c06a27ef5 100644
--- a/vendor/github.com/docker/go-connections/nat/nat.go
+++ b/vendor/github.com/docker/go-connections/nat/nat.go
@@ -2,6 +2,7 @@
package nat
import (
+ "errors"
"fmt"
"net"
"strconv"
@@ -26,94 +27,96 @@ type PortSet map[Port]struct{}
type Port string
// NewPort creates a new instance of a Port given a protocol and port number or port range
-func NewPort(proto, port string) (Port, error) {
- // Check for parsing issues on "port" now so we can avoid having
- // to check it later on.
-
- portStartInt, portEndInt, err := ParsePortRangeToInt(port)
+func NewPort(proto, portOrRange string) (Port, error) {
+ start, end, err := parsePortRange(portOrRange)
if err != nil {
return "", err
}
-
- if portStartInt == portEndInt {
- return Port(fmt.Sprintf("%d/%s", portStartInt, proto)), nil
+ if start == end {
+ return Port(fmt.Sprintf("%d/%s", start, proto)), nil
}
- return Port(fmt.Sprintf("%d-%d/%s", portStartInt, portEndInt, proto)), nil
+ return Port(fmt.Sprintf("%d-%d/%s", start, end, proto)), nil
}
// ParsePort parses the port number string and returns an int
func ParsePort(rawPort string) (int, error) {
- if len(rawPort) == 0 {
+ if rawPort == "" {
return 0, nil
}
- port, err := strconv.ParseUint(rawPort, 10, 16)
+ port, err := parsePortNumber(rawPort)
if err != nil {
- return 0, err
+ return 0, fmt.Errorf("invalid port '%s': %w", rawPort, err)
}
- return int(port), nil
+ return port, nil
}
// ParsePortRangeToInt parses the port range string and returns start/end ints
-func ParsePortRangeToInt(rawPort string) (int, int, error) {
- if len(rawPort) == 0 {
+func ParsePortRangeToInt(rawPort string) (startPort, endPort int, _ error) {
+ if rawPort == "" {
+ // TODO(thaJeztah): consider making this an error; this was kept to keep existing behavior.
return 0, 0, nil
}
- start, end, err := ParsePortRange(rawPort)
- if err != nil {
- return 0, 0, err
- }
- return int(start), int(end), nil
+ return parsePortRange(rawPort)
}
// Proto returns the protocol of a Port
func (p Port) Proto() string {
- proto, _ := SplitProtoPort(string(p))
+ _, proto, _ := strings.Cut(string(p), "/")
+ if proto == "" {
+ proto = "tcp"
+ }
return proto
}
// Port returns the port number of a Port
func (p Port) Port() string {
- _, port := SplitProtoPort(string(p))
+ port, _, _ := strings.Cut(string(p), "/")
return port
}
-// Int returns the port number of a Port as an int
+// Int returns the port number of a Port as an int. It assumes [Port]
+// is valid, and returns 0 otherwise.
func (p Port) Int() int {
- portStr := p.Port()
// We don't need to check for an error because we're going to
- // assume that any error would have been found, and reported, in NewPort()
- port, _ := ParsePort(portStr)
+ // assume that any error would have been found, and reported, in [NewPort]
+ port, _ := parsePortNumber(p.Port())
return port
}
// Range returns the start/end port numbers of a Port range as ints
func (p Port) Range() (int, int, error) {
- return ParsePortRangeToInt(p.Port())
+ portRange := p.Port()
+ if portRange == "" {
+ return 0, 0, nil
+ }
+ return parsePortRange(portRange)
}
-// SplitProtoPort splits a port in the format of proto/port
-func SplitProtoPort(rawPort string) (string, string) {
- parts := strings.Split(rawPort, "/")
- l := len(parts)
- if len(rawPort) == 0 || l == 0 || len(parts[0]) == 0 {
+// SplitProtoPort splits a port(range) and protocol, formatted as "/[]"
+// "/[]". It returns an empty string for both if
+// no port(range) is provided. If a port(range) is provided, but no protocol,
+// the default ("tcp") protocol is returned.
+//
+// SplitProtoPort does not validate or normalize the returned values.
+func SplitProtoPort(rawPort string) (proto string, port string) {
+ port, proto, _ = strings.Cut(rawPort, "/")
+ if port == "" {
return "", ""
}
- if l == 1 {
- return "tcp", rawPort
- }
- if len(parts[1]) == 0 {
- return "tcp", parts[0]
+ if proto == "" {
+ proto = "tcp"
}
- return parts[1], parts[0]
+ return proto, port
}
-func validateProto(proto string) bool {
- for _, availableProto := range []string{"tcp", "udp", "sctp"} {
- if availableProto == proto {
- return true
- }
+func validateProto(proto string) error {
+ switch proto {
+ case "tcp", "udp", "sctp":
+ // All good
+ return nil
+ default:
+ return errors.New("invalid proto: " + proto)
}
- return false
}
// ParsePortSpecs receives port specs in the format of ip:public:private/proto and parses
@@ -123,22 +126,18 @@ func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding,
exposedPorts = make(map[Port]struct{}, len(ports))
bindings = make(map[Port][]PortBinding)
)
- for _, rawPort := range ports {
- portMappings, err := ParsePortSpec(rawPort)
+ for _, p := range ports {
+ portMappings, err := ParsePortSpec(p)
if err != nil {
return nil, nil, err
}
- for _, portMapping := range portMappings {
- port := portMapping.Port
- if _, exists := exposedPorts[port]; !exists {
+ for _, pm := range portMappings {
+ port := pm.Port
+ if _, ok := exposedPorts[port]; !ok {
exposedPorts[port] = struct{}{}
}
- bslice, exists := bindings[port]
- if !exists {
- bslice = []PortBinding{}
- }
- bindings[port] = append(bslice, portMapping.Binding)
+ bindings[port] = append(bindings[port], pm.Binding)
}
}
return exposedPorts, bindings, nil
@@ -150,28 +149,38 @@ type PortMapping struct {
Binding PortBinding
}
-func splitParts(rawport string) (string, string, string) {
+func (p *PortMapping) String() string {
+ return net.JoinHostPort(p.Binding.HostIP, p.Binding.HostPort+":"+string(p.Port))
+}
+
+func splitParts(rawport string) (hostIP, hostPort, containerPort string) {
parts := strings.Split(rawport, ":")
- n := len(parts)
- containerPort := parts[n-1]
- switch n {
+ switch len(parts) {
case 1:
- return "", "", containerPort
+ return "", "", parts[0]
case 2:
- return "", parts[0], containerPort
+ return "", parts[0], parts[1]
case 3:
- return parts[0], parts[1], containerPort
+ return parts[0], parts[1], parts[2]
default:
- return strings.Join(parts[:n-2], ":"), parts[n-2], containerPort
+ n := len(parts)
+ return strings.Join(parts[:n-2], ":"), parts[n-2], parts[n-1]
}
}
// ParsePortSpec parses a port specification string into a slice of PortMappings
func ParsePortSpec(rawPort string) ([]PortMapping, error) {
- var proto string
ip, hostPort, containerPort := splitParts(rawPort)
- proto, containerPort = SplitProtoPort(containerPort)
+ proto, containerPort := SplitProtoPort(containerPort)
+ if containerPort == "" {
+ return nil, fmt.Errorf("no port specified: %s", rawPort)
+ }
+
+ proto = strings.ToLower(proto)
+ if err := validateProto(proto); err != nil {
+ return nil, err
+ }
if ip != "" && ip[0] == '[' {
// Strip [] from IPV6 addresses
@@ -182,59 +191,47 @@ func ParsePortSpec(rawPort string) ([]PortMapping, error) {
ip = rawIP
}
if ip != "" && net.ParseIP(ip) == nil {
- return nil, fmt.Errorf("invalid IP address: %s", ip)
- }
- if containerPort == "" {
- return nil, fmt.Errorf("no port specified: %s", rawPort)
+ return nil, errors.New("invalid IP address: " + ip)
}
- startPort, endPort, err := ParsePortRange(containerPort)
+ startPort, endPort, err := parsePortRange(containerPort)
if err != nil {
- return nil, fmt.Errorf("invalid containerPort: %s", containerPort)
+ return nil, errors.New("invalid containerPort: " + containerPort)
}
- var startHostPort, endHostPort uint64 = 0, 0
- if len(hostPort) > 0 {
- startHostPort, endHostPort, err = ParsePortRange(hostPort)
+ var startHostPort, endHostPort int
+ if hostPort != "" {
+ startHostPort, endHostPort, err = parsePortRange(hostPort)
if err != nil {
- return nil, fmt.Errorf("invalid hostPort: %s", hostPort)
+ return nil, errors.New("invalid hostPort: " + hostPort)
}
- }
-
- if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) {
- // Allow host port range iff containerPort is not a range.
- // In this case, use the host port range as the dynamic
- // host port range to allocate into.
- if endPort != startPort {
- return nil, fmt.Errorf("invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
+ if (endPort - startPort) != (endHostPort - startHostPort) {
+ // Allow host port range iff containerPort is not a range.
+ // In this case, use the host port range as the dynamic
+ // host port range to allocate into.
+ if endPort != startPort {
+ return nil, fmt.Errorf("invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
+ }
}
}
- if !validateProto(strings.ToLower(proto)) {
- return nil, fmt.Errorf("invalid proto: %s", proto)
- }
+ count := endPort - startPort + 1
+ ports := make([]PortMapping, 0, count)
- ports := []PortMapping{}
- for i := uint64(0); i <= (endPort - startPort); i++ {
- containerPort = strconv.FormatUint(startPort+i, 10)
- if len(hostPort) > 0 {
- hostPort = strconv.FormatUint(startHostPort+i, 10)
- }
- // Set hostPort to a range only if there is a single container port
- // and a dynamic host port.
- if startPort == endPort && startHostPort != endHostPort {
- hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10))
- }
- port, err := NewPort(strings.ToLower(proto), containerPort)
- if err != nil {
- return nil, err
- }
-
- binding := PortBinding{
- HostIP: ip,
- HostPort: hostPort,
+ for i := range count {
+ hPort := ""
+ if hostPort != "" {
+ hPort = strconv.Itoa(startHostPort + i)
+ // Set hostPort to a range only if there is a single container port
+ // and a dynamic host port.
+ if count == 1 && startHostPort != endHostPort {
+ hPort += "-" + strconv.Itoa(endHostPort)
+ }
}
- ports = append(ports, PortMapping{Port: port, Binding: binding})
+ ports = append(ports, PortMapping{
+ Port: Port(strconv.Itoa(startPort+i) + "/" + proto),
+ Binding: PortBinding{HostIP: ip, HostPort: hPort},
+ })
}
return ports, nil
}
diff --git a/vendor/github.com/docker/go-connections/nat/parse.go b/vendor/github.com/docker/go-connections/nat/parse.go
index e4b53e8a3242..f6f86bd04fe3 100644
--- a/vendor/github.com/docker/go-connections/nat/parse.go
+++ b/vendor/github.com/docker/go-connections/nat/parse.go
@@ -1,33 +1,60 @@
package nat
import (
+ "errors"
"fmt"
"strconv"
"strings"
)
-// ParsePortRange parses and validates the specified string as a port-range (8000-9000)
-func ParsePortRange(ports string) (uint64, uint64, error) {
+// ParsePortRange parses and validates the specified string as a port range (e.g., "8000-9000").
+func ParsePortRange(ports string) (startPort, endPort uint64, _ error) {
+ start, end, err := parsePortRange(ports)
+ return uint64(start), uint64(end), err
+}
+
+// parsePortRange parses and validates the specified string as a port range (e.g., "8000-9000").
+func parsePortRange(ports string) (startPort, endPort int, _ error) {
if ports == "" {
- return 0, 0, fmt.Errorf("empty string specified for ports")
+ return 0, 0, errors.New("empty string specified for ports")
+ }
+ start, end, ok := strings.Cut(ports, "-")
+
+ startPort, err := parsePortNumber(start)
+ if err != nil {
+ return 0, 0, fmt.Errorf("invalid start port '%s': %w", start, err)
}
- if !strings.Contains(ports, "-") {
- start, err := strconv.ParseUint(ports, 10, 16)
- end := start
- return start, end, err
+ if !ok || start == end {
+ return startPort, startPort, nil
}
- parts := strings.Split(ports, "-")
- start, err := strconv.ParseUint(parts[0], 10, 16)
+ endPort, err = parsePortNumber(end)
if err != nil {
- return 0, 0, err
+ return 0, 0, fmt.Errorf("invalid end port '%s': %w", end, err)
}
- end, err := strconv.ParseUint(parts[1], 10, 16)
+ if endPort < startPort {
+ return 0, 0, errors.New("invalid port range: " + ports)
+ }
+ return startPort, endPort, nil
+}
+
+// parsePortNumber parses rawPort into an int, unwrapping strconv errors
+// and returning a single "out of range" error for any value outside 0–65535.
+func parsePortNumber(rawPort string) (int, error) {
+ if rawPort == "" {
+ return 0, errors.New("value is empty")
+ }
+ port, err := strconv.ParseInt(rawPort, 10, 0)
if err != nil {
- return 0, 0, err
+ var numErr *strconv.NumError
+ if errors.As(err, &numErr) {
+ err = numErr.Err
+ }
+ return 0, err
}
- if end < start {
- return 0, 0, fmt.Errorf("invalid range specified for port: %s", ports)
+ if port < 0 || port > 65535 {
+ return 0, errors.New("value out of range (0–65535)")
}
- return start, end, nil
+
+ return int(port), nil
}
diff --git a/vendor/github.com/docker/go-connections/nat/sort.go b/vendor/github.com/docker/go-connections/nat/sort.go
index b6eed145e1cc..b983d011485b 100644
--- a/vendor/github.com/docker/go-connections/nat/sort.go
+++ b/vendor/github.com/docker/go-connections/nat/sort.go
@@ -34,8 +34,10 @@ func Sort(ports []Port, predicate func(i, j Port) bool) {
}
type portMapEntry struct {
- port Port
- binding PortBinding
+ port Port
+ binding *PortBinding
+ portInt int
+ portProto string
}
type portMapSorter []portMapEntry
@@ -48,23 +50,36 @@ func (s portMapSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// 2. larger port
// 3. port with tcp protocol
func (s portMapSorter) Less(i, j int) bool {
- pi, pj := s[i].port, s[j].port
- hpi, hpj := toInt(s[i].binding.HostPort), toInt(s[j].binding.HostPort)
- return hpi > hpj || pi.Int() > pj.Int() || (pi.Int() == pj.Int() && strings.ToLower(pi.Proto()) == "tcp")
+ pi, pj := s[i].portInt, s[j].portInt
+ var hpi, hpj int
+ if s[i].binding != nil {
+ hpi = toInt(s[i].binding.HostPort)
+ }
+ if s[j].binding != nil {
+ hpj = toInt(s[j].binding.HostPort)
+ }
+ return hpi > hpj || pi > pj || (pi == pj && strings.EqualFold(s[i].portProto, "tcp"))
}
// SortPortMap sorts the list of ports and their respected mapping. The ports
// will explicit HostPort will be placed first.
-func SortPortMap(ports []Port, bindings PortMap) {
+func SortPortMap(ports []Port, bindings map[Port][]PortBinding) {
s := portMapSorter{}
for _, p := range ports {
+ portInt, portProto := p.Int(), p.Proto()
if binding, ok := bindings[p]; ok && len(binding) > 0 {
for _, b := range binding {
- s = append(s, portMapEntry{port: p, binding: b})
+ s = append(s, portMapEntry{
+ port: p, binding: &b,
+ portInt: portInt, portProto: portProto,
+ })
}
bindings[p] = []PortBinding{}
} else {
- s = append(s, portMapEntry{port: p})
+ s = append(s, portMapEntry{
+ port: p,
+ portInt: portInt, portProto: portProto,
+ })
}
}
@@ -81,16 +96,13 @@ func SortPortMap(ports []Port, bindings PortMap) {
i++
}
// reorder bindings for this port
- if _, ok := bindings[entry.port]; ok {
- bindings[entry.port] = append(bindings[entry.port], entry.binding)
+ if entry.binding != nil {
+ bindings[entry.port] = append(bindings[entry.port], *entry.binding)
}
}
}
-func toInt(s string) uint64 {
- i, _, err := ParsePortRange(s)
- if err != nil {
- i = 0
- }
+func toInt(s string) int {
+ i, _, _ := parsePortRange(s)
return i
}
diff --git a/vendor/github.com/docker/go-connections/sockets/README.md b/vendor/github.com/docker/go-connections/sockets/README.md
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/vendor/github.com/docker/go-connections/sockets/inmem_socket.go b/vendor/github.com/docker/go-connections/sockets/inmem_socket.go
index 99846ffddb1a..06fcf747ac4b 100644
--- a/vendor/github.com/docker/go-connections/sockets/inmem_socket.go
+++ b/vendor/github.com/docker/go-connections/sockets/inmem_socket.go
@@ -1,48 +1,57 @@
package sockets
import (
- "errors"
"net"
"sync"
)
-var errClosed = errors.New("use of closed network connection")
+// dummyAddr is used to satisfy net.Addr for the in-mem socket
+// it is just stored as a string and returns the string for all calls
+type dummyAddr string
+
+// Network returns the addr string, satisfies net.Addr
+func (a dummyAddr) Network() string {
+ return string(a)
+}
-// InmemSocket implements net.Listener using in-memory only connections.
+// String returns the string form
+func (a dummyAddr) String() string {
+ return string(a)
+}
+
+// InmemSocket implements [net.Listener] using in-memory only connections.
type InmemSocket struct {
chConn chan net.Conn
chClose chan struct{}
- addr string
+ addr dummyAddr
mu sync.Mutex
}
-// dummyAddr is used to satisfy net.Addr for the in-mem socket
-// it is just stored as a string and returns the string for all calls
-type dummyAddr string
-
-// NewInmemSocket creates an in-memory only net.Listener
-// The addr argument can be any string, but is used to satisfy the `Addr()` part
-// of the net.Listener interface
+// NewInmemSocket creates an in-memory only [net.Listener]. The addr argument
+// can be any string, but is used to satisfy the [net.Listener.Addr] part
+// of the [net.Listener] interface
func NewInmemSocket(addr string, bufSize int) *InmemSocket {
return &InmemSocket{
chConn: make(chan net.Conn, bufSize),
chClose: make(chan struct{}),
- addr: addr,
+ addr: dummyAddr(addr),
}
}
// Addr returns the socket's addr string to satisfy net.Listener
func (s *InmemSocket) Addr() net.Addr {
- return dummyAddr(s.addr)
+ return s.addr
}
-// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
+// Accept implements the Accept method in the Listener interface; it waits
+// for the next call and returns a generic Conn. It returns a [net.ErrClosed]
+// if the connection is already closed.
func (s *InmemSocket) Accept() (net.Conn, error) {
select {
case conn := <-s.chConn:
return conn, nil
case <-s.chClose:
- return nil, errClosed
+ return nil, net.ErrClosed
}
}
@@ -58,24 +67,15 @@ func (s *InmemSocket) Close() error {
return nil
}
-// Dial is used to establish a connection with the in-mem server
+// Dial is used to establish a connection with the in-mem server.
+// It returns a [net.ErrClosed] if the connection is already closed.
func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) {
srvConn, clientConn := net.Pipe()
select {
case s.chConn <- srvConn:
case <-s.chClose:
- return nil, errClosed
+ return nil, net.ErrClosed
}
return clientConn, nil
}
-
-// Network returns the addr string, satisfies net.Addr
-func (a dummyAddr) Network() string {
- return string(a)
-}
-
-// String returns the string form
-func (a dummyAddr) String() string {
- return string(a)
-}
diff --git a/vendor/github.com/docker/go-connections/sockets/proxy.go b/vendor/github.com/docker/go-connections/sockets/proxy.go
deleted file mode 100644
index c897cb02adea..000000000000
--- a/vendor/github.com/docker/go-connections/sockets/proxy.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package sockets
-
-import (
- "net"
- "os"
- "strings"
-)
-
-// GetProxyEnv allows access to the uppercase and the lowercase forms of
-// proxy-related variables. See the Go specification for details on these
-// variables. https://golang.org/pkg/net/http/
-func GetProxyEnv(key string) string {
- proxyValue := os.Getenv(strings.ToUpper(key))
- if proxyValue == "" {
- return os.Getenv(strings.ToLower(key))
- }
- return proxyValue
-}
-
-// DialerFromEnvironment was previously used to configure a net.Dialer to route
-// connections through a SOCKS proxy.
-// DEPRECATED: SOCKS proxies are now supported by configuring only
-// http.Transport.Proxy, and no longer require changing http.Transport.Dial.
-// Therefore, only sockets.ConfigureTransport() needs to be called, and any
-// sockets.DialerFromEnvironment() calls can be dropped.
-func DialerFromEnvironment(direct *net.Dialer) (*net.Dialer, error) {
- return direct, nil
-}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets.go b/vendor/github.com/docker/go-connections/sockets/sockets.go
index b0eae239d2c5..0d7789bbdbda 100644
--- a/vendor/github.com/docker/go-connections/sockets/sockets.go
+++ b/vendor/github.com/docker/go-connections/sockets/sockets.go
@@ -2,13 +2,19 @@
package sockets
import (
+ "context"
"errors"
+ "fmt"
"net"
"net/http"
+ "syscall"
"time"
)
-const defaultTimeout = 10 * time.Second
+const (
+ defaultTimeout = 10 * time.Second
+ maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
+)
// ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system.
var ErrProtocolNotAvailable = errors.New("protocol not available")
@@ -21,11 +27,19 @@ var ErrProtocolNotAvailable = errors.New("protocol not available")
// make sure you do it _after_ any subsequent calls to ConfigureTransport is made against the same
// [http.Transport].
func ConfigureTransport(tr *http.Transport, proto, addr string) error {
+ if tr.MaxIdleConns == 0 {
+ // prevent long-lived processes from leaking connections
+ // due to idle connections not being released.
+ //
+ // TODO: see if we can also address this from the server side; see: https://github.com/moby/moby/issues/45539
+ tr.MaxIdleConns = 6
+ tr.IdleConnTimeout = 30 * time.Second
+ }
switch proto {
case "unix":
- return configureUnixTransport(tr, proto, addr)
+ return configureUnixTransport(tr, addr)
case "npipe":
- return configureNpipeTransport(tr, proto, addr)
+ return configureNpipeTransport(tr, addr)
default:
tr.Proxy = http.ProxyFromEnvironment
tr.DisableCompression = false
@@ -35,3 +49,18 @@ func ConfigureTransport(tr *http.Transport, proto, addr string) error {
}
return nil
}
+
+func configureUnixTransport(tr *http.Transport, addr string) error {
+ if len(addr) > maxUnixSocketPathSize {
+ return fmt.Errorf("unix socket path %q is too long", addr)
+ }
+ // No need for compression in local communications.
+ tr.DisableCompression = true
+ dialer := &net.Dialer{
+ Timeout: defaultTimeout,
+ }
+ tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
+ return dialer.DialContext(ctx, "unix", addr)
+ }
+ return nil
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
index 78a34a980d28..b37c39eab828 100644
--- a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
+++ b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
@@ -2,38 +2,6 @@
package sockets
-import (
- "context"
- "fmt"
- "net"
- "net/http"
- "syscall"
- "time"
-)
-
-const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
-
-func configureUnixTransport(tr *http.Transport, proto, addr string) error {
- if len(addr) > maxUnixSocketPathSize {
- return fmt.Errorf("unix socket path %q is too long", addr)
- }
- // No need for compression in local communications.
- tr.DisableCompression = true
- dialer := &net.Dialer{
- Timeout: defaultTimeout,
- }
- tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
- return dialer.DialContext(ctx, proto, addr)
- }
- return nil
-}
-
-func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
+func configureNpipeTransport(any, string) error {
return ErrProtocolNotAvailable
}
-
-// DialPipe connects to a Windows named pipe.
-// This is not supported on other OSes.
-func DialPipe(_ string, _ time.Duration) (net.Conn, error) {
- return nil, syscall.EAFNOSUPPORT
-}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
index 7acafc5a2ad8..0863fc36a792 100644
--- a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
+++ b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
@@ -4,16 +4,11 @@ import (
"context"
"net"
"net/http"
- "time"
"github.com/Microsoft/go-winio"
)
-func configureUnixTransport(tr *http.Transport, proto, addr string) error {
- return ErrProtocolNotAvailable
-}
-
-func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
+func configureNpipeTransport(tr *http.Transport, addr string) error {
// No need for compression in local communications.
tr.DisableCompression = true
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
@@ -21,8 +16,3 @@ func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
}
return nil
}
-
-// DialPipe connects to a Windows named pipe.
-func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
- return winio.DialPipe(addr, &timeout)
-}
diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket.go b/vendor/github.com/docker/go-connections/sockets/unix_socket.go
index b9233521e49a..e736f71d38b1 100644
--- a/vendor/github.com/docker/go-connections/sockets/unix_socket.go
+++ b/vendor/github.com/docker/go-connections/sockets/unix_socket.go
@@ -1,5 +1,3 @@
-//go:build !windows
-
/*
Package sockets is a simple unix domain socket wrapper.
@@ -57,26 +55,6 @@ import (
// SockOption sets up socket file's creating option
type SockOption func(string) error
-// WithChown modifies the socket file's uid and gid
-func WithChown(uid, gid int) SockOption {
- return func(path string) error {
- if err := os.Chown(path, uid, gid); err != nil {
- return err
- }
- return nil
- }
-}
-
-// WithChmod modifies socket file's access mode.
-func WithChmod(mask os.FileMode) SockOption {
- return func(path string) error {
- if err := os.Chmod(path, mask); err != nil {
- return err
- }
- return nil
- }
-}
-
// NewUnixSocketWithOpts creates a unix socket with the specified options.
// By default, socket permissions are 0000 (i.e.: no access for anyone); pass
// WithChmod() and WithChown() to set the desired ownership and permissions.
@@ -90,22 +68,7 @@ func NewUnixSocketWithOpts(path string, opts ...SockOption) (net.Listener, error
return nil, err
}
- // net.Listen does not allow for permissions to be set. As a result, when
- // specifying custom permissions ("WithChmod()"), there is a short time
- // between creating the socket and applying the permissions, during which
- // the socket permissions are Less restrictive than desired.
- //
- // To work around this limitation of net.Listen(), we temporarily set the
- // umask to 0777, which forces the socket to be created with 000 permissions
- // (i.e.: no access for anyone). After that, WithChmod() must be used to set
- // the desired permissions.
- //
- // We don't use "defer" here, to reset the umask to its original value as soon
- // as possible. Ideally we'd be able to detect if WithChmod() was passed as
- // an option, and skip changing umask if default permissions are used.
- origUmask := syscall.Umask(0o777)
- l, err := net.Listen("unix", path)
- syscall.Umask(origUmask)
+ l, err := listenUnix(path)
if err != nil {
return nil, err
}
@@ -119,8 +82,3 @@ func NewUnixSocketWithOpts(path string, opts ...SockOption) (net.Listener, error
return l, nil
}
-
-// NewUnixSocket creates a unix socket with the specified path and group.
-func NewUnixSocket(path string, gid int) (net.Listener, error) {
- return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0o660))
-}
diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket_unix.go b/vendor/github.com/docker/go-connections/sockets/unix_socket_unix.go
new file mode 100644
index 000000000000..a41a71654742
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/unix_socket_unix.go
@@ -0,0 +1,54 @@
+//go:build !windows
+
+package sockets
+
+import (
+ "net"
+ "os"
+ "syscall"
+)
+
+// WithChown modifies the socket file's uid and gid
+func WithChown(uid, gid int) SockOption {
+ return func(path string) error {
+ if err := os.Chown(path, uid, gid); err != nil {
+ return err
+ }
+ return nil
+ }
+}
+
+// WithChmod modifies socket file's access mode.
+func WithChmod(mask os.FileMode) SockOption {
+ return func(path string) error {
+ if err := os.Chmod(path, mask); err != nil {
+ return err
+ }
+ return nil
+ }
+}
+
+// NewUnixSocket creates a unix socket with the specified path and group.
+func NewUnixSocket(path string, gid int) (net.Listener, error) {
+ return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0o660))
+}
+
+func listenUnix(path string) (net.Listener, error) {
+ // net.Listen does not allow for permissions to be set. As a result, when
+ // specifying custom permissions ("WithChmod()"), there is a short time
+ // between creating the socket and applying the permissions, during which
+ // the socket permissions are Less restrictive than desired.
+ //
+ // To work around this limitation of net.Listen(), we temporarily set the
+ // umask to 0777, which forces the socket to be created with 000 permissions
+ // (i.e.: no access for anyone). After that, WithChmod() must be used to set
+ // the desired permissions.
+ //
+ // We don't use "defer" here, to reset the umask to its original value as soon
+ // as possible. Ideally we'd be able to detect if WithChmod() was passed as
+ // an option, and skip changing umask if default permissions are used.
+ origUmask := syscall.Umask(0o777)
+ l, err := net.Listen("unix", path)
+ syscall.Umask(origUmask)
+ return l, err
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket_windows.go b/vendor/github.com/docker/go-connections/sockets/unix_socket_windows.go
new file mode 100644
index 000000000000..01aee5f11a5b
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/unix_socket_windows.go
@@ -0,0 +1,129 @@
+package sockets
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "strings"
+
+ "github.com/Microsoft/go-winio"
+ "golang.org/x/sys/windows"
+)
+
+// BasePermissions defines the default DACL, which allows Administrators
+// and LocalSystem full access (similar to defaults used in [moby]);
+//
+// - D:P: DACL without inheritance (protected, (P)).
+// - (A;;GA;;;BA): Allow full access (GA) for built-in Administrators (BA).
+// - (A;;GA;;;SY); Allow full access (GA) for LocalSystem (SY).
+// - Any other user is denied access.
+//
+// [moby]: https://github.com/moby/moby/blob/6b45c76a233b1b8b56465f76c21c09fd7920e82d/daemon/listeners/listeners_windows.go#L53-L59
+const BasePermissions = "D:P(A;;GA;;;BA)(A;;GA;;;SY)"
+
+// WithBasePermissions sets a default DACL, which allows Administrators
+// and LocalSystem full access (similar to defaults used in [moby]);
+//
+// - D:P: DACL without inheritance (protected, (P)).
+// - (A;;GA;;;BA): Allow full access (GA) for built-in Administrators (BA).
+// - (A;;GA;;;SY); Allow full access (GA) for LocalSystem (SY).
+// - Any other user is denied access.
+//
+// [moby]: https://github.com/moby/moby/blob/6b45c76a233b1b8b56465f76c21c09fd7920e82d/daemon/listeners/listeners_windows.go#L53-L59
+func WithBasePermissions() SockOption {
+ return withSDDL(BasePermissions)
+}
+
+// WithAdditionalUsersAndGroups modifies the socket file's DACL to grant
+// access to additional users and groups.
+//
+// It sets [BasePermissions] on the socket path and grants the given additional
+// users and groups to generic read (GR) and write (GW) access. It returns
+// an error if no groups were given, when failing to resolve any of the
+// additional users and groups, or when failing to apply the ACL.
+func WithAdditionalUsersAndGroups(additionalUsersAndGroups []string) SockOption {
+ return func(path string) error {
+ if len(additionalUsersAndGroups) == 0 {
+ return errors.New("no additional users specified")
+ }
+ sd, err := getSecurityDescriptor(additionalUsersAndGroups...)
+ if err != nil {
+ return fmt.Errorf("looking up SID: %w", err)
+ }
+ return withSDDL(sd)(path)
+ }
+}
+
+// withSDDL applies the given SDDL to the socket. It returns an error
+// when failing parse the SDDL, or if the DACL was defaulted.
+//
+// TODO(thaJeztah); this is not exported yet, as some of the checks may need review if they're not too opinionated.
+func withSDDL(sddl string) SockOption {
+ return func(path string) error {
+ sd, err := windows.SecurityDescriptorFromString(sddl)
+ if err != nil {
+ return fmt.Errorf("parsing SDDL: %w", err)
+ }
+ dacl, defaulted, err := sd.DACL()
+ if err != nil {
+ return fmt.Errorf("extracting DACL: %w", err)
+ }
+ if dacl == nil || defaulted {
+ // should never be hit with our [DefaultPermissions],
+ // as it contains "D:" and "P" (protected, don't inherit).
+ return errors.New("no DACL found in security descriptor or defaulted")
+ }
+ return windows.SetNamedSecurityInfo(
+ path,
+ windows.SE_FILE_OBJECT,
+ windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION,
+ nil, // do not change the owner
+ nil, // do not change the owner
+ dacl,
+ nil,
+ )
+ }
+}
+
+// NewUnixSocket creates a new unix socket.
+//
+// It sets [BasePermissions] on the socket path and grants the given additional
+// users and groups to generic read (GR) and write (GW) access. It returns
+// an error when failing to resolve any of the additional users and groups,
+// or when failing to apply the ACL.
+func NewUnixSocket(path string, additionalUsersAndGroups []string) (net.Listener, error) {
+ var opts []SockOption
+ if len(additionalUsersAndGroups) > 0 {
+ opts = append(opts, WithAdditionalUsersAndGroups(additionalUsersAndGroups))
+ } else {
+ opts = append(opts, WithBasePermissions())
+ }
+ return NewUnixSocketWithOpts(path, opts...)
+}
+
+// getSecurityDescriptor returns the DACL for the Unix socket.
+//
+// By default, it grants [BasePermissions], but allows for additional
+// users and groups to get generic read (GR) and write (GW) access. It
+// returns an error when failing to resolve any of the additional users
+// and groups.
+func getSecurityDescriptor(additionalUsersAndGroups ...string) (string, error) {
+ sddl := BasePermissions
+
+ // Grant generic read (GR) and write (GW) access to whatever
+ // additional users or groups were specified.
+ //
+ // TODO(thaJeztah): should we fail on, or remove duplicates?
+ for _, g := range additionalUsersAndGroups {
+ sid, err := winio.LookupSidByName(strings.TrimSpace(g))
+ if err != nil {
+ return "", fmt.Errorf("looking up SID: %w", err)
+ }
+ sddl += fmt.Sprintf("(A;;GRGW;;;%s)", sid)
+ }
+ return sddl, nil
+}
+
+func listenUnix(path string) (net.Listener, error) {
+ return net.Listen("unix", path)
+}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/certpool.go b/vendor/github.com/docker/go-connections/tlsconfig/certpool.go
index f84c624ba0ba..803f1e122ead 100644
--- a/vendor/github.com/docker/go-connections/tlsconfig/certpool.go
+++ b/vendor/github.com/docker/go-connections/tlsconfig/certpool.go
@@ -1,16 +1,12 @@
package tlsconfig
-import (
- "crypto/x509"
- "runtime"
-)
+import "crypto/x509"
-// SystemCertPool returns a copy of the system cert pool,
-// returns an error if failed to load or empty pool on windows.
+// SystemCertPool returns a copy of the system cert pool.
+//
+// Deprecated: use [x509.SystemCertPool] instead.
+//
+//go:fix inline
func SystemCertPool() (*x509.CertPool, error) {
- certpool, err := x509.SystemCertPool()
- if err != nil && runtime.GOOS == "windows" {
- return x509.NewCertPool(), nil
- }
- return certpool, err
+ return x509.SystemCertPool()
}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config.go b/vendor/github.com/docker/go-connections/tlsconfig/config.go
index 606c98a38b51..761b36bb825e 100644
--- a/vendor/github.com/docker/go-connections/tlsconfig/config.go
+++ b/vendor/github.com/docker/go-connections/tlsconfig/config.go
@@ -34,51 +34,42 @@ type Options struct {
// the system pool will be used.
ExclusiveRootPools bool
MinVersion uint16
- // If Passphrase is set, it will be used to decrypt a TLS private key
- // if the key is encrypted.
- //
- // Deprecated: Use of encrypted TLS private keys has been deprecated, and
- // will be removed in a future release. Golang has deprecated support for
- // legacy PEM encryption (as specified in RFC 1423), as it is insecure by
- // design (see https://go-review.googlesource.com/c/go/+/264159).
- Passphrase string
-}
-// Extra (server-side) accepted CBC cipher suites - will phase out in the future
-var acceptedCBCCiphers = []uint16{
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ // systemCertPool allows mocking the system cert-pool for testing.
+ systemCertPool func() (*x509.CertPool, error)
}
// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls
// options struct but wants to use a commonly accepted set of TLS cipher suites, with
// known weak algorithms removed.
-var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
+var DefaultServerAcceptedCiphers = defaultCipherSuites
+
+// defaultCipherSuites is shared by both client and server as the default set.
+var defaultCipherSuites = []uint16{
+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+}
// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
func ServerDefault(ops ...func(*tls.Config)) *tls.Config {
- tlsConfig := &tls.Config{
- // Avoid fallback by default to SSL protocols < TLS1.2
- MinVersion: tls.VersionTLS12,
- PreferServerCipherSuites: true,
- CipherSuites: DefaultServerAcceptedCiphers,
- }
-
- for _, op := range ops {
- op(tlsConfig)
- }
-
- return tlsConfig
+ return defaultConfig(ops...)
}
// ClientDefault returns a secure-enough TLS configuration for the client TLS configuration.
func ClientDefault(ops ...func(*tls.Config)) *tls.Config {
+ return defaultConfig(ops...)
+}
+
+// defaultConfig is the default config used by both client and server TLS configuration.
+func defaultConfig(ops ...func(*tls.Config)) *tls.Config {
tlsConfig := &tls.Config{
- // Prefer TLS1.2 as the client minimum
+ // Avoid fallback by default to SSL protocols < TLS1.2
MinVersion: tls.VersionTLS12,
- CipherSuites: clientCipherSuites,
+ CipherSuites: defaultCipherSuites,
}
for _, op := range ops {
@@ -89,28 +80,35 @@ func ClientDefault(ops ...func(*tls.Config)) *tls.Config {
}
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
-func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
+func certPool(opts Options) (*x509.CertPool, error) {
// If we should verify the server, we need to load a trusted ca
var (
- certPool *x509.CertPool
- err error
+ pool *x509.CertPool
+ err error
)
- if exclusivePool {
- certPool = x509.NewCertPool()
+ if opts.ExclusiveRootPools {
+ pool = x509.NewCertPool()
} else {
- certPool, err = SystemCertPool()
+ if opts.systemCertPool != nil {
+ pool, err = opts.systemCertPool()
+ } else {
+ pool, err = x509.SystemCertPool()
+ }
if err != nil {
return nil, fmt.Errorf("failed to read system certificates: %v", err)
}
}
- pemData, err := os.ReadFile(caFile)
+ if opts.CAFile == "" {
+ return pool, nil
+ }
+ pemData, err := os.ReadFile(opts.CAFile)
if err != nil {
- return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
+ return nil, fmt.Errorf("could not read CA certificate %q: %v", opts.CAFile, err)
}
- if !certPool.AppendCertsFromPEM(pemData) {
- return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
+ if !pool.AppendCertsFromPEM(pemData) {
+ return nil, fmt.Errorf("failed to append certificates from PEM file: %q", opts.CAFile)
}
- return certPool, nil
+ return pool, nil
}
// allTLSVersions lists all the TLS versions and is used by the code that validates
@@ -144,34 +142,32 @@ func adjustMinVersion(options Options, config *tls.Config) error {
return nil
}
-// IsErrEncryptedKey returns true if the 'err' is an error of incorrect
-// password when trying to decrypt a TLS private key.
+// errEncryptedKeyDeprecated is produced when we encounter an encrypted
+// (password-protected) key. From https://go-review.googlesource.com/c/go/+/264159;
//
-// Deprecated: Use of encrypted TLS private keys has been deprecated, and
-// will be removed in a future release. Golang has deprecated support for
-// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
-// design (see https://go-review.googlesource.com/c/go/+/264159).
-func IsErrEncryptedKey(err error) bool {
- return errors.Is(err, x509.IncorrectPasswordError)
-}
+// > Legacy PEM encryption as specified in RFC 1423 is insecure by design. Since
+// > it does not authenticate the ciphertext, it is vulnerable to padding oracle
+// > attacks that can let an attacker recover the plaintext
+// >
+// > It's unfortunate that we don't implement PKCS#8 encryption so we can't
+// > recommend an alternative but PEM encryption is so broken that it's worth
+// > deprecating outright.
+//
+// Also see https://docs.docker.com/go/deprecated/
+var errEncryptedKeyDeprecated = errors.New("private key is encrypted; encrypted private keys are obsolete, and not supported")
// getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format.
-// If the private key is encrypted, 'passphrase' is used to decrypted the
-// private key.
-func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) {
+// It returns an error if the file could not be decoded or was protected by
+// a passphrase.
+func getPrivateKey(keyBytes []byte) ([]byte, error) {
// this section makes some small changes to code from notary/tuf/utils/x509.go
pemBlock, _ := pem.Decode(keyBytes)
if pemBlock == nil {
return nil, fmt.Errorf("no valid private key found")
}
- var err error
if x509.IsEncryptedPEMBlock(pemBlock) { //nolint:staticcheck // Ignore SA1019 (IsEncryptedPEMBlock is deprecated)
- keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) //nolint:staticcheck // Ignore SA1019 (DecryptPEMBlock is deprecated)
- if err != nil {
- return nil, fmt.Errorf("private key is encrypted, but could not decrypt it: %w", err)
- }
- keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes})
+ return nil, errEncryptedKeyDeprecated
}
return keyBytes, nil
@@ -195,7 +191,7 @@ func getCert(options Options) ([]tls.Certificate, error) {
return nil, err
}
- prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase)
+ prKeyBytes, err = getPrivateKey(prKeyBytes)
if err != nil {
return nil, err
}
@@ -210,10 +206,10 @@ func getCert(options Options) ([]tls.Certificate, error) {
// Client returns a TLS configuration meant to be used by a client.
func Client(options Options) (*tls.Config, error) {
- tlsConfig := ClientDefault()
+ tlsConfig := defaultConfig()
tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
if !options.InsecureSkipVerify && options.CAFile != "" {
- CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
+ CAs, err := certPool(options)
if err != nil {
return nil, err
}
@@ -235,7 +231,7 @@ func Client(options Options) (*tls.Config, error) {
// Server returns a TLS configuration meant to be used by a server.
func Server(options Options) (*tls.Config, error) {
- tlsConfig := ServerDefault()
+ tlsConfig := defaultConfig()
tlsConfig.ClientAuth = options.ClientAuth
tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
if err != nil {
@@ -246,7 +242,7 @@ func Server(options Options) (*tls.Config, error) {
}
tlsConfig.Certificates = []tls.Certificate{tlsCert}
if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" {
- CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
+ CAs, err := certPool(options)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
deleted file mode 100644
index a82f9fa52e2e..000000000000
--- a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
-package tlsconfig
-
-import (
- "crypto/tls"
-)
-
-// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
-var clientCipherSuites = []uint16{
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-}
diff --git a/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
index ffc7b992b3c7..7f257e99ac9e 100644
--- a/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
+++ b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml
@@ -1,7 +1,7 @@
freebsd_task:
name: 'FreeBSD'
freebsd_instance:
- image_family: freebsd-13-2
+ image_family: freebsd-14-2
install_script:
- pkg update -f
- pkg install -y go
@@ -9,5 +9,6 @@ freebsd_task:
# run tests as user "cirrus" instead of root
- pw useradd cirrus -m
- chown -R cirrus:cirrus .
- - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
- - sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
+ - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
+ - sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
+ - FSNOTIFY_DEBUG=1 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./...
diff --git a/vendor/github.com/fsnotify/fsnotify/.gitattributes b/vendor/github.com/fsnotify/fsnotify/.gitattributes
deleted file mode 100644
index 32f1001be0a5..000000000000
--- a/vendor/github.com/fsnotify/fsnotify/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-go.sum linguist-generated
diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore
index 391cc076b126..daea9dd6d6d2 100644
--- a/vendor/github.com/fsnotify/fsnotify/.gitignore
+++ b/vendor/github.com/fsnotify/fsnotify/.gitignore
@@ -5,3 +5,6 @@
# Output of go build ./cmd/fsnotify
/fsnotify
/fsnotify.exe
+
+/test/kqueue
+/test/a.out
diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
index e0e57575496c..6468d2cf400f 100644
--- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
+++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
@@ -1,8 +1,69 @@
# Changelog
-Unreleased
-----------
-Nothing yet.
+1.9.0 2024-04-04
+----------------
+
+### Changes and fixes
+
+- all: make BufferedWatcher buffered again ([#657])
+
+- inotify: fix race when adding/removing watches while a watched path is being
+ deleted ([#678], [#686])
+
+- inotify: don't send empty event if a watched path is unmounted ([#655])
+
+- inotify: don't register duplicate watches when watching both a symlink and its
+ target; previously that would get "half-added" and removing the second would
+ panic ([#679])
+
+- kqueue: fix watching relative symlinks ([#681])
+
+- kqueue: correctly mark pre-existing entries when watching a link to a dir on
+ kqueue ([#682])
+
+- illumos: don't send error if changed file is deleted while processing the
+ event ([#678])
+
+
+[#657]: https://github.com/fsnotify/fsnotify/pull/657
+[#678]: https://github.com/fsnotify/fsnotify/pull/678
+[#686]: https://github.com/fsnotify/fsnotify/pull/686
+[#655]: https://github.com/fsnotify/fsnotify/pull/655
+[#681]: https://github.com/fsnotify/fsnotify/pull/681
+[#679]: https://github.com/fsnotify/fsnotify/pull/679
+[#682]: https://github.com/fsnotify/fsnotify/pull/682
+
+1.8.0 2024-10-31
+----------------
+
+### Additions
+
+- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619])
+
+### Changes and fixes
+
+- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610])
+
+- kqueue: ignore events with Ident=0 ([#590])
+
+- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617])
+
+- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625])
+
+- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620])
+
+- inotify: fix panic when calling Remove() in a goroutine ([#650])
+
+- fen: allow watching subdirectories of watched directories ([#621])
+
+[#590]: https://github.com/fsnotify/fsnotify/pull/590
+[#610]: https://github.com/fsnotify/fsnotify/pull/610
+[#617]: https://github.com/fsnotify/fsnotify/pull/617
+[#619]: https://github.com/fsnotify/fsnotify/pull/619
+[#620]: https://github.com/fsnotify/fsnotify/pull/620
+[#621]: https://github.com/fsnotify/fsnotify/pull/621
+[#625]: https://github.com/fsnotify/fsnotify/pull/625
+[#650]: https://github.com/fsnotify/fsnotify/pull/650
1.7.0 - 2023-10-22
------------------
diff --git a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
index ea379759d51a..4cc40fa597d8 100644
--- a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
+++ b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
@@ -1,7 +1,7 @@
Thank you for your interest in contributing to fsnotify! We try to review and
merge PRs in a reasonable timeframe, but please be aware that:
-- To avoid "wasted" work, please discus changes on the issue tracker first. You
+- To avoid "wasted" work, please discuss changes on the issue tracker first. You
can just send PRs, but they may end up being rejected for one reason or the
other.
@@ -20,6 +20,125 @@ platforms. Testing different platforms locally can be done with something like
Use the `-short` flag to make the "stress test" run faster.
+Writing new tests
+-----------------
+Scripts in the testdata directory allow creating test cases in a "shell-like"
+syntax. The basic format is:
+
+ script
+
+ Output:
+ desired output
+
+For example:
+
+ # Create a new empty file with some data.
+ watch /
+ echo data >/file
+
+ Output:
+ create /file
+ write /file
+
+Just create a new file to add a new test; select which tests to run with
+`-run TestScript/[path]`.
+
+script
+------
+The script is a "shell-like" script:
+
+ cmd arg arg
+
+Comments are supported with `#`:
+
+ # Comment
+ cmd arg arg # Comment
+
+All operations are done in a temp directory; a path like "/foo" is rewritten to
+"/tmp/TestFoo/foo".
+
+Arguments can be quoted with `"` or `'`; there are no escapes and they're
+functionally identical right now, but this may change in the future, so best to
+assume shell-like rules.
+
+ touch "/file with spaces"
+
+End-of-line escapes with `\` are not supported.
+
+### Supported commands
+
+ watch path [ops] # Watch the path, reporting events for it. Nothing is
+ # watched by default. Optionally a list of ops can be
+ # given, as with AddWith(path, WithOps(...)).
+ unwatch path # Stop watching the path.
+ watchlist n # Assert watchlist length.
+
+ stop # Stop running the script; for debugging.
+ debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in
+ parallel by default, so -parallel=1 is probably a good
+ idea).
+ print [any strings] # Print text to stdout; for debugging.
+
+ touch path
+ mkdir [-p] dir
+ ln -s target link # Only ln -s supported.
+ mkfifo path
+ mknod dev path
+ mv src dst
+ rm [-r] path
+ chmod mode path # Octal only
+ sleep time-in-ms
+
+ cat path # Read path (does nothing with the data; just reads it).
+ echo str >>path # Append "str" to "path".
+ echo str >path # Truncate "path" and write "str".
+
+ require reason # Skip the test if "reason" is true; "skip" and
+ skip reason # "require" behave identical; it supports both for
+ # readability. Possible reasons are:
+ #
+ # always Always skip this test.
+ # symlink Symlinks are supported (requires admin
+ # permissions on Windows).
+ # mkfifo Platform doesn't support FIFO named sockets.
+ # mknod Platform doesn't support device nodes.
+
+
+output
+------
+After `Output:` the desired output is given; this is indented by convention, but
+that's not required.
+
+The format of that is:
+
+ # Comment
+ event path # Comment
+
+ system:
+ event path
+ system2:
+ event path
+
+Every event is one line, and any whitespace between the event and path are
+ignored. The path can optionally be surrounded in ". Anything after a "#" is
+ignored.
+
+Platform-specific tests can be added after GOOS; for example:
+
+ watch /
+ touch /file
+
+ Output:
+ # Tested if nothing else matches
+ create /file
+
+ # Windows-specific test.
+ windows:
+ write /file
+
+You can specify multiple platforms with a comma (e.g. "windows, linux:").
+"kqueue" is a shortcut for all kqueue systems (BSD, macOS).
+
[goon]: https://github.com/arp242/goon
[Vagrant]: https://www.vagrantup.com/
diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md
index e480733d16cb..1f4eb583d50b 100644
--- a/vendor/github.com/fsnotify/fsnotify/README.md
+++ b/vendor/github.com/fsnotify/fsnotify/README.md
@@ -15,7 +15,6 @@ Platform support:
| ReadDirectoryChangesW | Windows | Supported |
| FEN | illumos | Supported |
| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) |
-| AHAFS | AIX | [aix branch]; experimental due to lack of maintainer and test environment |
| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] |
| USN Journals | Windows | [Needs support in x/sys/windows][usn] |
| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) |
@@ -25,7 +24,6 @@ untested.
[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120
[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847
-[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129
Usage
-----
diff --git a/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/vendor/github.com/fsnotify/fsnotify/backend_fen.go
index 28497f1dd8e6..57fc69284845 100644
--- a/vendor/github.com/fsnotify/fsnotify/backend_fen.go
+++ b/vendor/github.com/fsnotify/fsnotify/backend_fen.go
@@ -1,162 +1,44 @@
//go:build solaris
-// +build solaris
-// Note: the documentation on the Watcher type and methods is generated from
-// mkdoc.zsh
+// FEN backend for illumos (supported) and Solaris (untested, but should work).
+//
+// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create
package fsnotify
import (
"errors"
"fmt"
+ "io/fs"
"os"
"path/filepath"
"sync"
+ "time"
+ "github.com/fsnotify/fsnotify/internal"
"golang.org/x/sys/unix"
)
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-// fp := os.Open("file")
-// os.Remove("file") // Triggers Chmod
-// fp.Close() // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-// # Default values on Linux 5.18
-// sysctl fs.inotify.max_user_watches=124983
-// sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-// fs.inotify.max_user_watches=124983
-// fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # Windows notes
-//
-// Paths can be added as "C:\path\to\dir", but forward slashes
-// ("C:/path/to/dir") will also work.
-//
-// When a watched directory is removed it will always send an event for the
-// directory itself, but may not send events for all files in that directory.
-// Sometimes it will send events for all times, sometimes it will send no
-// events, and often only for some files.
-//
-// 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
-// [WithBufferSize] to increase the value.
-type Watcher struct {
- // Events sends the filesystem change events.
- //
- // fsnotify can send the following events; a "path" here can refer to a
- // file, directory, symbolic link, or special file like a FIFO.
- //
- // fsnotify.Create A new path was created; this may be followed by one
- // or more Write events if data also gets written to a
- // file.
- //
- // fsnotify.Remove A path was removed.
- //
- // fsnotify.Rename A path was renamed. A rename is always sent with the
- // old path as Event.Name, and a Create event will be
- // sent with the new name. Renames are only sent for
- // paths that are currently watched; e.g. moving an
- // unmonitored file into a monitored directory will
- // show up as just a Create. Similarly, renaming a file
- // to outside a monitored directory will show up as
- // only a Rename.
- //
- // fsnotify.Write A file or named pipe was written to. A Truncate will
- // also trigger a Write. A single "write action"
- // initiated by the user may show up as one or multiple
- // writes, depending on when the system syncs things to
- // disk. For example when compiling a large Go program
- // you may get hundreds of Write events, and you may
- // 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.
- //
- // fsnotify.Chmod Attributes were changed. On Linux this is also sent
- // when a file is removed (or more accurately, when a
- // link to an inode is removed). On kqueue it's sent
- // when a file is truncated. On Windows it's never
- // sent.
+type fen struct {
+ *shared
Events chan Event
-
- // Errors sends any errors.
- //
- // ErrEventOverflow is used to indicate there are too many events:
- //
- // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
- // - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
- // - kqueue, fen: Not used.
Errors chan error
mu sync.Mutex
port *unix.EventPort
- done chan struct{} // Channel for sending a "quit message" to the reader goroutine
- dirs map[string]struct{} // Explicitly watched directories
- watches map[string]struct{} // Explicitly watched non-directories
+ dirs map[string]Op // Explicitly watched directories
+ watches map[string]Op // Explicitly watched non-directories
}
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
- return NewBufferedWatcher(0)
-}
+var defaultBufferSize = 0
-// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
-// channel.
-//
-// The main use case for this is situations with a very large number of events
-// where the kernel buffer size can't be increased (e.g. due to lack of
-// permissions). An unbuffered Watcher will perform better for almost all use
-// cases, and whenever possible you will be better off increasing the kernel
-// buffers instead of adding a large userspace buffer.
-func NewBufferedWatcher(sz uint) (*Watcher, error) {
- w := &Watcher{
- Events: make(chan Event, sz),
- Errors: make(chan error),
- dirs: make(map[string]struct{}),
- watches: make(map[string]struct{}),
- done: make(chan struct{}),
+func newBackend(ev chan Event, errs chan error) (backend, error) {
+ w := &fen{
+ shared: newShared(ev, errs),
+ Events: ev,
+ Errors: errs,
+ dirs: make(map[string]Op),
+ watches: make(map[string]Op),
}
var err error
@@ -169,104 +51,28 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) {
return w, nil
}
-// sendEvent attempts to send an event to the user, returning true if the event
-// was put in the channel successfully and false if the watcher has been closed.
-func (w *Watcher) sendEvent(name string, op Op) (sent bool) {
- select {
- case w.Events <- Event{Name: name, Op: op}:
- return true
- case <-w.done:
- return false
- }
-}
-
-// sendError attempts to send an error to the user, returning true if the error
-// was put in the channel successfully and false if the watcher has been closed.
-func (w *Watcher) sendError(err error) (sent bool) {
- select {
- case w.Errors <- err:
- return true
- case <-w.done:
- return false
- }
-}
-
-func (w *Watcher) isClosed() bool {
- select {
- case <-w.done:
- return true
- default:
- return false
- }
-}
-
-// Close removes all watches and closes the Events channel.
-func (w *Watcher) Close() error {
- // Take the lock used by associateFile to prevent lingering events from
- // being processed after the close
- w.mu.Lock()
- defer w.mu.Unlock()
- if w.isClosed() {
+func (w *fen) Close() error {
+ if w.shared.close() {
return nil
}
- close(w.done)
return w.port.Close()
}
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; watching it more than once is a no-op and will
-// not return an error. Paths that do not yet exist on the filesystem cannot be
-// watched.
-//
-// A watch will be automatically removed if the watched path is deleted or
-// renamed. The exception is the Windows backend, which doesn't remove the
-// watcher on renames.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// Returns [ErrClosed] if [Watcher.Close] was called.
-//
-// See [Watcher.AddWith] for a version that allows adding options.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many programs (especially editors) update files atomically: it
-// will write to a temporary file which is then moved to to destination,
-// overwriting the original (or some variant thereof). The watcher on the
-// original file is now lost, as that no longer exists.
-//
-// The upshot of this is that a power failure or crash won't leave a
-// half-written file.
-//
-// Watch the parent directory and use Event.Name to filter out files you're not
-// interested in. There is an example of this in cmd/fsnotify/file.go.
-func (w *Watcher) Add(name string) error { return w.AddWith(name) }
+func (w *fen) Add(name string) error { return w.AddWith(name) }
-// AddWith is like [Watcher.Add], but allows adding options. When using Add()
-// the defaults described below are used.
-//
-// Possible options are:
-//
-// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
-// other platforms. The default is 64K (65536 bytes).
-func (w *Watcher) AddWith(name string, opts ...addOpt) error {
+func (w *fen) AddWith(name string, opts ...addOpt) error {
if w.isClosed() {
return ErrClosed
}
- if w.port.PathIsWatched(name) {
- return nil
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
+ time.Now().Format("15:04:05.000000000"), name)
}
- _ = getOptions(opts...)
+ with := getOptions(opts...)
+ if !w.xSupports(with.op) {
+ return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+ }
// Currently we resolve symlinks that were explicitly requested to be
// watched. Otherwise we would use LStat here.
@@ -283,7 +89,7 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
}
w.mu.Lock()
- w.dirs[name] = struct{}{}
+ w.dirs[name] = with.op
w.mu.Unlock()
return nil
}
@@ -294,26 +100,22 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
}
w.mu.Lock()
- w.watches[name] = struct{}{}
+ w.watches[name] = with.op
w.mu.Unlock()
return nil
}
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) Remove(name string) error {
+func (w *fen) Remove(name string) error {
if w.isClosed() {
return nil
}
if !w.port.PathIsWatched(name) {
return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
}
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
+ time.Now().Format("15:04:05.000000000"), name)
+ }
// The user has expressed an intent. Immediately remove this name from
// whichever watch list it might be in. If it's not in there the delete
@@ -346,7 +148,7 @@ func (w *Watcher) Remove(name string) error {
}
// readEvents contains the main loop that runs in a goroutine watching for events.
-func (w *Watcher) readEvents() {
+func (w *fen) readEvents() {
// If this function returns, the watcher has been closed and we can close
// these channels
defer func() {
@@ -367,7 +169,7 @@ func (w *Watcher) readEvents() {
return
}
// There was an error not caused by calling w.Close()
- if !w.sendError(err) {
+ if !w.sendError(fmt.Errorf("port.Get: %w", err)) {
return
}
}
@@ -382,17 +184,19 @@ func (w *Watcher) readEvents() {
continue
}
+ if debug {
+ internal.Debug(pevent.Path, pevent.Events)
+ }
+
err = w.handleEvent(&pevent)
- if err != nil {
- if !w.sendError(err) {
- return
- }
+ if !w.sendError(err) {
+ return
}
}
}
}
-func (w *Watcher) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error {
+func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error {
files, err := os.ReadDir(path)
if err != nil {
return err
@@ -418,7 +222,7 @@ func (w *Watcher) handleDirectory(path string, stat os.FileInfo, follow bool, ha
// bitmap matches more than one event type (e.g. the file was both modified and
// had the attributes changed between when the association was created and the
// when event was returned)
-func (w *Watcher) handleEvent(event *unix.PortEvent) error {
+func (w *fen) handleEvent(event *unix.PortEvent) error {
var (
events = event.Events
path = event.Path
@@ -433,13 +237,13 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
isWatched := watchedDir || watchedPath
if events&unix.FILE_DELETE != 0 {
- if !w.sendEvent(path, Remove) {
+ if !w.sendEvent(Event{Name: path, Op: Remove}) {
return nil
}
reRegister = false
}
if events&unix.FILE_RENAME_FROM != 0 {
- if !w.sendEvent(path, Rename) {
+ if !w.sendEvent(Event{Name: path, Op: Rename}) {
return nil
}
// Don't keep watching the new file name
@@ -453,7 +257,7 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
// inotify reports a Remove event in this case, so we simulate this
// here.
- if !w.sendEvent(path, Remove) {
+ if !w.sendEvent(Event{Name: path, Op: Remove}) {
return nil
}
// Don't keep watching the file that was removed
@@ -487,7 +291,7 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
// get here, the sudirectory is already gone. Clearly we were watching
// this path but now it is gone. Let's tell the user that it was
// removed.
- if !w.sendEvent(path, Remove) {
+ if !w.sendEvent(Event{Name: path, Op: Remove}) {
return nil
}
// Suppress extra write events on removed directories; they are not
@@ -502,7 +306,7 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
if err != nil {
// The symlink still exists, but the target is gone. Report the
// Remove similar to above.
- if !w.sendEvent(path, Remove) {
+ if !w.sendEvent(Event{Name: path, Op: Remove}) {
return nil
}
// Don't return the error
@@ -510,18 +314,12 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
}
if events&unix.FILE_MODIFIED != 0 {
- if fmode.IsDir() {
- if watchedDir {
- if err := w.updateDirectory(path); err != nil {
- return err
- }
- } else {
- if !w.sendEvent(path, Write) {
- return nil
- }
+ if fmode.IsDir() && watchedDir {
+ if err := w.updateDirectory(path); err != nil {
+ return err
}
} else {
- if !w.sendEvent(path, Write) {
+ if !w.sendEvent(Event{Name: path, Op: Write}) {
return nil
}
}
@@ -529,7 +327,7 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
if events&unix.FILE_ATTRIB != 0 && stat != nil {
// Only send Chmod if perms changed
if stat.Mode().Perm() != fmode.Perm() {
- if !w.sendEvent(path, Chmod) {
+ if !w.sendEvent(Event{Name: path, Op: Chmod}) {
return nil
}
}
@@ -538,17 +336,27 @@ func (w *Watcher) handleEvent(event *unix.PortEvent) error {
if stat != nil {
// If we get here, it means we've hit an event above that requires us to
// continue watching the file or directory
- return w.associateFile(path, stat, isWatched)
+ err := w.associateFile(path, stat, isWatched)
+ if errors.Is(err, fs.ErrNotExist) {
+ // Path may have been removed since the stat.
+ err = nil
+ }
+ return err
}
return nil
}
-func (w *Watcher) updateDirectory(path string) error {
- // The directory was modified, so we must find unwatched entities and watch
- // them. If something was removed from the directory, nothing will happen,
- // as everything else should still be watched.
+// The directory was modified, so we must find unwatched entities and watch
+// them. If something was removed from the directory, nothing will happen, as
+// everything else should still be watched.
+func (w *fen) updateDirectory(path string) error {
files, err := os.ReadDir(path)
if err != nil {
+ // Directory no longer exists: probably just deleted since we got the
+ // event.
+ if errors.Is(err, fs.ErrNotExist) {
+ return nil
+ }
return err
}
@@ -563,19 +371,22 @@ func (w *Watcher) updateDirectory(path string) error {
return err
}
err = w.associateFile(path, finfo, false)
- if err != nil {
- if !w.sendError(err) {
- return nil
- }
+ if errors.Is(err, fs.ErrNotExist) {
+ // File may have disappeared between getting the dir listing and
+ // adding the port: that's okay to ignore.
+ continue
}
- if !w.sendEvent(path, Create) {
+ if !w.sendError(err) {
+ return nil
+ }
+ if !w.sendEvent(Event{Name: path, Op: Create}) {
return nil
}
}
return nil
}
-func (w *Watcher) associateFile(path string, stat os.FileInfo, follow bool) error {
+func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error {
if w.isClosed() {
return ErrClosed
}
@@ -593,34 +404,42 @@ func (w *Watcher) associateFile(path string, stat os.FileInfo, follow bool) erro
// cleared up that discrepancy. The most likely cause is that the event
// has fired but we haven't processed it yet.
err := w.port.DissociatePath(path)
- if err != nil && err != unix.ENOENT {
- return err
+ if err != nil && !errors.Is(err, unix.ENOENT) {
+ return fmt.Errorf("port.DissociatePath(%q): %w", path, err)
}
}
- // FILE_NOFOLLOW means we watch symlinks themselves rather than their
- // targets.
- events := unix.FILE_MODIFIED | unix.FILE_ATTRIB | unix.FILE_NOFOLLOW
- if follow {
- // We *DO* follow symlinks for explicitly watched entries.
- events = unix.FILE_MODIFIED | unix.FILE_ATTRIB
+
+ var events int
+ if !follow {
+ // Watch symlinks themselves rather than their targets unless this entry
+ // is explicitly watched.
+ events |= unix.FILE_NOFOLLOW
+ }
+ if true { // TODO: implement withOps()
+ events |= unix.FILE_MODIFIED
+ }
+ if true {
+ events |= unix.FILE_ATTRIB
}
- return w.port.AssociatePath(path, stat,
- events,
- stat.Mode())
+ err := w.port.AssociatePath(path, stat, events, stat.Mode())
+ if err != nil {
+ return fmt.Errorf("port.AssociatePath(%q): %w", path, err)
+ }
+ return nil
}
-func (w *Watcher) dissociateFile(path string, stat os.FileInfo, unused bool) error {
+func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error {
if !w.port.PathIsWatched(path) {
return nil
}
- return w.port.DissociatePath(path)
+ err := w.port.DissociatePath(path)
+ if err != nil {
+ return fmt.Errorf("port.DissociatePath(%q): %w", path, err)
+ }
+ return nil
}
-// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
-// yet removed).
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) WatchList() []string {
+func (w *fen) WatchList() []string {
if w.isClosed() {
return nil
}
@@ -638,3 +457,11 @@ func (w *Watcher) WatchList() []string {
return entries
}
+
+func (w *fen) xSupports(op Op) bool {
+ if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+ op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+ return false
+ }
+ return true
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
index 921c1c1e4012..a36cb89d7361 100644
--- a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
+++ b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go
@@ -1,8 +1,4 @@
//go:build linux && !appengine
-// +build linux,!appengine
-
-// Note: the documentation on the Watcher type and methods is generated from
-// mkdoc.zsh
package fsnotify
@@ -10,127 +6,21 @@ import (
"errors"
"fmt"
"io"
+ "io/fs"
"os"
"path/filepath"
"strings"
"sync"
+ "time"
"unsafe"
+ "github.com/fsnotify/fsnotify/internal"
"golang.org/x/sys/unix"
)
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-// fp := os.Open("file")
-// os.Remove("file") // Triggers Chmod
-// fp.Close() // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-// # Default values on Linux 5.18
-// sysctl fs.inotify.max_user_watches=124983
-// sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-// fs.inotify.max_user_watches=124983
-// fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # Windows notes
-//
-// Paths can be added as "C:\path\to\dir", but forward slashes
-// ("C:/path/to/dir") will also work.
-//
-// When a watched directory is removed it will always send an event for the
-// directory itself, but may not send events for all files in that directory.
-// Sometimes it will send events for all times, sometimes it will send no
-// events, and often only for some files.
-//
-// 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
-// [WithBufferSize] to increase the value.
-type Watcher struct {
- // Events sends the filesystem change events.
- //
- // fsnotify can send the following events; a "path" here can refer to a
- // file, directory, symbolic link, or special file like a FIFO.
- //
- // fsnotify.Create A new path was created; this may be followed by one
- // or more Write events if data also gets written to a
- // file.
- //
- // fsnotify.Remove A path was removed.
- //
- // fsnotify.Rename A path was renamed. A rename is always sent with the
- // old path as Event.Name, and a Create event will be
- // sent with the new name. Renames are only sent for
- // paths that are currently watched; e.g. moving an
- // unmonitored file into a monitored directory will
- // show up as just a Create. Similarly, renaming a file
- // to outside a monitored directory will show up as
- // only a Rename.
- //
- // fsnotify.Write A file or named pipe was written to. A Truncate will
- // also trigger a Write. A single "write action"
- // initiated by the user may show up as one or multiple
- // writes, depending on when the system syncs things to
- // disk. For example when compiling a large Go program
- // you may get hundreds of Write events, and you may
- // 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.
- //
- // fsnotify.Chmod Attributes were changed. On Linux this is also sent
- // when a file is removed (or more accurately, when a
- // link to an inode is removed). On kqueue it's sent
- // when a file is truncated. On Windows it's never
- // sent.
+type inotify struct {
+ *shared
Events chan Event
-
- // Errors sends any errors.
- //
- // ErrEventOverflow is used to indicate there are too many events:
- //
- // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
- // - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
- // - kqueue, fen: Not used.
Errors chan error
// Store fd here as os.File.Read() will no longer return on close after
@@ -138,21 +28,41 @@ type Watcher struct {
fd int
inotifyFile *os.File
watches *watches
- done chan struct{} // Channel for sending a "quit message" to the reader goroutine
- closeMu sync.Mutex
doneResp chan struct{} // Channel to respond to Close
+
+ // Store rename cookies in an array, with the index wrapping to 0. Almost
+ // all of the time what we get is a MOVED_FROM to set the cookie and the
+ // next event inotify sends will be MOVED_TO to read it. However, this is
+ // not guaranteed – as described in inotify(7) – and we may get other events
+ // between the two MOVED_* events (including other MOVED_* ones).
+ //
+ // A second issue is that moving a file outside the watched directory will
+ // trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to
+ // read and delete it. So just storing it in a map would slowly leak memory.
+ //
+ // Doing it like this gives us a simple fast LRU-cache that won't allocate.
+ // Ten items should be more than enough for our purpose, and a loop over
+ // such a short array is faster than a map access anyway (not that it hugely
+ // matters since we're talking about hundreds of ns at the most, but still).
+ cookies [10]koekje
+ cookieIndex uint8
+ cookiesMu sync.Mutex
}
type (
watches struct {
- mu sync.RWMutex
wd map[uint32]*watch // wd → watch
path map[string]uint32 // pathname → wd
}
watch struct {
- wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
- flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
- path string // Watch path.
+ wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
+ flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
+ path string // Watch path.
+ recurse bool // Recursion with ./...?
+ }
+ koekje struct {
+ cookie uint32
+ path string
}
)
@@ -163,57 +73,43 @@ func newWatches() *watches {
}
}
-func (w *watches) len() int {
- w.mu.RLock()
- defer w.mu.RUnlock()
- return len(w.wd)
-}
-
-func (w *watches) add(ww *watch) {
- w.mu.Lock()
- defer w.mu.Unlock()
- w.wd[ww.wd] = ww
- w.path[ww.path] = ww.wd
-}
-
-func (w *watches) remove(wd uint32) {
- w.mu.Lock()
- defer w.mu.Unlock()
- delete(w.path, w.wd[wd].path)
- delete(w.wd, wd)
-}
-
-func (w *watches) removePath(path string) (uint32, bool) {
- w.mu.Lock()
- defer w.mu.Unlock()
+func (w *watches) byPath(path string) *watch { return w.wd[w.path[path]] }
+func (w *watches) byWd(wd uint32) *watch { return w.wd[wd] }
+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 (w *watches) removePath(path string) ([]uint32, error) {
+ path, recurse := recursivePath(path)
wd, ok := w.path[path]
if !ok {
- return 0, false
+ return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path)
+ }
+
+ watch := w.wd[wd]
+ if recurse && !watch.recurse {
+ return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path)
}
delete(w.path, path)
delete(w.wd, wd)
+ if !watch.recurse {
+ return []uint32{wd}, nil
+ }
- return wd, true
-}
-
-func (w *watches) byPath(path string) *watch {
- w.mu.RLock()
- defer w.mu.RUnlock()
- return w.wd[w.path[path]]
-}
-
-func (w *watches) byWd(wd uint32) *watch {
- w.mu.RLock()
- defer w.mu.RUnlock()
- return w.wd[wd]
+ wds := make([]uint32, 0, 8)
+ wds = append(wds, wd)
+ for p, rwd := range w.path {
+ if strings.HasPrefix(p, path) {
+ delete(w.path, p)
+ delete(w.wd, rwd)
+ wds = append(wds, rwd)
+ }
+ }
+ return wds, nil
}
func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error {
- w.mu.Lock()
- defer w.mu.Unlock()
-
var existing *watch
wd, ok := w.path[path]
if ok {
@@ -236,20 +132,9 @@ func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error
return nil
}
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
- return NewBufferedWatcher(0)
-}
+var defaultBufferSize = 0
-// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
-// channel.
-//
-// The main use case for this is situations with a very large number of events
-// where the kernel buffer size can't be increased (e.g. due to lack of
-// permissions). An unbuffered Watcher will perform better for almost all use
-// cases, and whenever possible you will be better off increasing the kernel
-// buffers instead of adding a large userspace buffer.
-func NewBufferedWatcher(sz uint) (*Watcher, error) {
+func newBackend(ev chan Event, errs chan error) (backend, error) {
// Need to set nonblocking mode for SetDeadline to work, otherwise blocking
// I/O operations won't terminate on close.
fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
@@ -257,13 +142,13 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) {
return nil, errno
}
- w := &Watcher{
+ w := &inotify{
+ shared: newShared(ev, errs),
+ Events: ev,
+ Errors: errs,
fd: fd,
inotifyFile: os.NewFile(uintptr(fd), ""),
watches: newWatches(),
- Events: make(chan Event, sz),
- Errors: make(chan error),
- done: make(chan struct{}),
doneResp: make(chan struct{}),
}
@@ -271,44 +156,10 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) {
return w, nil
}
-// Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
- select {
- case w.Events <- e:
- return true
- case <-w.done:
- return false
- }
-}
-
-// Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
- select {
- case w.Errors <- err:
- return true
- case <-w.done:
- return false
- }
-}
-
-func (w *Watcher) isClosed() bool {
- select {
- case <-w.done:
- return true
- default:
- return false
- }
-}
-
-// Close removes all watches and closes the Events channel.
-func (w *Watcher) Close() error {
- w.closeMu.Lock()
- if w.isClosed() {
- w.closeMu.Unlock()
+func (w *inotify) Close() error {
+ if w.shared.close() {
return nil
}
- close(w.done)
- w.closeMu.Unlock()
// Causes any blocking reads to return with an error, provided the file
// still supports deadline operations.
@@ -317,84 +168,114 @@ func (w *Watcher) Close() error {
return err
}
- // Wait for goroutine to close
- <-w.doneResp
-
+ <-w.doneResp // Wait for readEvents() to finish.
return nil
}
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; watching it more than once is a no-op and will
-// not return an error. Paths that do not yet exist on the filesystem cannot be
-// watched.
-//
-// A watch will be automatically removed if the watched path is deleted or
-// renamed. The exception is the Windows backend, which doesn't remove the
-// watcher on renames.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// Returns [ErrClosed] if [Watcher.Close] was called.
-//
-// See [Watcher.AddWith] for a version that allows adding options.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many programs (especially editors) update files atomically: it
-// will write to a temporary file which is then moved to to destination,
-// overwriting the original (or some variant thereof). The watcher on the
-// original file is now lost, as that no longer exists.
-//
-// The upshot of this is that a power failure or crash won't leave a
-// half-written file.
-//
-// Watch the parent directory and use Event.Name to filter out files you're not
-// interested in. There is an example of this in cmd/fsnotify/file.go.
-func (w *Watcher) Add(name string) error { return w.AddWith(name) }
-
-// AddWith is like [Watcher.Add], but allows adding options. When using Add()
-// the defaults described below are used.
-//
-// Possible options are:
-//
-// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
-// other platforms. The default is 64K (65536 bytes).
-func (w *Watcher) AddWith(name string, opts ...addOpt) error {
+func (w *inotify) Add(name string) error { return w.AddWith(name) }
+
+func (w *inotify) AddWith(path string, opts ...addOpt) error {
if w.isClosed() {
return ErrClosed
}
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
+ time.Now().Format("15:04:05.000000000"), path)
+ }
+
+ with := getOptions(opts...)
+ if !w.xSupports(with.op) {
+ return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+ }
+
+ add := func(path string, with withOpts, recurse bool) error {
+ var flags uint32
+ if with.noFollow {
+ flags |= unix.IN_DONT_FOLLOW
+ }
+ if with.op.Has(Create) {
+ flags |= unix.IN_CREATE
+ }
+ if with.op.Has(Write) {
+ flags |= unix.IN_MODIFY
+ }
+ if with.op.Has(Remove) {
+ flags |= unix.IN_DELETE | unix.IN_DELETE_SELF
+ }
+ if with.op.Has(Rename) {
+ flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF
+ }
+ if with.op.Has(Chmod) {
+ flags |= unix.IN_ATTRIB
+ }
+ if with.op.Has(xUnportableOpen) {
+ flags |= unix.IN_OPEN
+ }
+ if with.op.Has(xUnportableRead) {
+ flags |= unix.IN_ACCESS
+ }
+ if with.op.Has(xUnportableCloseWrite) {
+ flags |= unix.IN_CLOSE_WRITE
+ }
+ if with.op.Has(xUnportableCloseRead) {
+ flags |= unix.IN_CLOSE_NOWRITE
+ }
+ return w.register(path, flags, recurse)
+ }
+
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ path, recurse := recursivePath(path)
+ if recurse {
+ return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ if !d.IsDir() {
+ if root == path {
+ return fmt.Errorf("fsnotify: not a directory: %q", path)
+ }
+ return nil
+ }
+
+ // Send a Create event when adding new directory from a recursive
+ // watch; this is for "mkdir -p one/two/three". Usually all those
+ // directories will be created before we can set up watchers on the
+ // subdirectories, so only "one" would be sent as a Create event and
+ // not "one/two" and "one/two/three" (inotifywait -r has the same
+ // problem).
+ if with.sendCreate && root != path {
+ w.sendEvent(Event{Name: root, Op: Create})
+ }
- name = filepath.Clean(name)
- _ = getOptions(opts...)
+ return add(root, with, true)
+ })
+ }
- var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
- unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
- unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
+ return add(path, with, false)
+}
- return w.watches.updatePath(name, func(existing *watch) (*watch, error) {
+func (w *inotify) register(path string, flags uint32, recurse bool) error {
+ return w.watches.updatePath(path, func(existing *watch) (*watch, error) {
if existing != nil {
flags |= existing.flags | unix.IN_MASK_ADD
}
- wd, err := unix.InotifyAddWatch(w.fd, name, flags)
+ wd, err := unix.InotifyAddWatch(w.fd, path, flags)
if wd == -1 {
return nil, err
}
+ if e, ok := w.watches.wd[uint32(wd)]; ok {
+ return e, nil
+ }
+
if existing == nil {
return &watch{
- wd: uint32(wd),
- path: name,
- flags: flags,
+ wd: uint32(wd),
+ path: path,
+ flags: flags,
+ recurse: recurse,
}, nil
}
@@ -404,87 +285,80 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
})
}
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) Remove(name string) error {
+func (w *inotify) Remove(name string) error {
if w.isClosed() {
return nil
}
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
+ time.Now().Format("15:04:05.000000000"), name)
+ }
+
+ w.mu.Lock()
+ defer w.mu.Unlock()
return w.remove(filepath.Clean(name))
}
-func (w *Watcher) remove(name string) error {
- wd, ok := w.watches.removePath(name)
- if !ok {
- return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
- }
-
- success, errno := unix.InotifyRmWatch(w.fd, wd)
- if success == -1 {
- // TODO: Perhaps it's not helpful to return an error here in every case;
- // The only two possible errors are:
- //
- // - EBADF, which happens when w.fd is not a valid file descriptor
- // of any kind.
- // - EINVAL, which is when fd is not an inotify descriptor or wd
- // is not a valid watch descriptor. Watch descriptors are
- // invalidated when they are removed explicitly or implicitly;
- // explicitly by inotify_rm_watch, implicitly when the file they
- // are watching is deleted.
- return errno
+func (w *inotify) remove(name string) error {
+ wds, err := w.watches.removePath(name)
+ if err != nil {
+ return err
+ }
+
+ for _, wd := range wds {
+ _, err := unix.InotifyRmWatch(w.fd, wd)
+ if err != nil {
+ // TODO: Perhaps it's not helpful to return an error here in every
+ // case; the only two possible errors are:
+ //
+ // EBADF, which happens when w.fd is not a valid file descriptor of
+ // any kind.
+ //
+ // EINVAL, which is when fd is not an inotify descriptor or wd is
+ // not a valid watch descriptor. Watch descriptors are invalidated
+ // when they are removed explicitly or implicitly; explicitly by
+ // inotify_rm_watch, implicitly when the file they are watching is
+ // deleted.
+ return err
+ }
}
return nil
}
-// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
-// yet removed).
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) WatchList() []string {
+func (w *inotify) WatchList() []string {
if w.isClosed() {
return nil
}
+ w.mu.Lock()
+ defer w.mu.Unlock()
entries := make([]string, 0, w.watches.len())
- w.watches.mu.RLock()
for pathname := range w.watches.path {
entries = append(entries, pathname)
}
- w.watches.mu.RUnlock()
-
return entries
}
// readEvents reads from the inotify file descriptor, converts the
// received events into Event objects and sends them via the Events channel
-func (w *Watcher) readEvents() {
+func (w *inotify) readEvents() {
defer func() {
close(w.doneResp)
close(w.Errors)
close(w.Events)
}()
- var (
- buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
- errno error // Syscall errno
- )
+ var buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
for {
- // See if we have been closed.
if w.isClosed() {
return
}
n, err := w.inotifyFile.Read(buf[:])
- switch {
- case errors.Unwrap(err) == os.ErrClosed:
- return
- case err != nil:
+ if err != nil {
+ if errors.Is(err, os.ErrClosed) {
+ return
+ }
if !w.sendError(err) {
return
}
@@ -492,13 +366,9 @@ func (w *Watcher) readEvents() {
}
if n < unix.SizeofInotifyEvent {
- var err error
+ err := errors.New("notify: short read in readEvents()") // Read was too short.
if n == 0 {
err = io.EOF // If EOF is received. This should really never happen.
- } else if n < 0 {
- err = errno // If an error occurred while reading.
- } else {
- err = errors.New("notify: short read in readEvents()") // Read was too short.
}
if !w.sendError(err) {
return
@@ -506,74 +376,146 @@ func (w *Watcher) readEvents() {
continue
}
+ // We don't know how many events we just read into the buffer While the
+ // offset points to at least one whole event.
var offset uint32
- // We don't know how many events we just read into the buffer
- // While the offset points to at least one whole event...
for offset <= uint32(n-unix.SizeofInotifyEvent) {
- var (
- // Point "raw" to the event in the buffer
- raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
- mask = uint32(raw.Mask)
- nameLen = uint32(raw.Len)
- )
-
- if mask&unix.IN_Q_OVERFLOW != 0 {
+ // Point to the event in the buffer.
+ inEvent := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
+
+ if inEvent.Mask&unix.IN_Q_OVERFLOW != 0 {
if !w.sendError(ErrEventOverflow) {
return
}
}
- // If the event happened to the watched directory or the watched file, the kernel
- // doesn't append the filename to the event, but we would like to always fill the
- // the "Name" field with a valid filename. We retrieve the path of the watch from
- // the "paths" map.
- watch := w.watches.byWd(uint32(raw.Wd))
-
- // inotify will automatically remove the watch on deletes; just need
- // to clean our state here.
- if watch != nil && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
- w.watches.remove(watch.wd)
+ ev, ok := w.handleEvent(inEvent, &buf, offset)
+ if !ok {
+ return
}
- // We can't really update the state when a watched path is moved;
- // only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove
- // the watch.
- if watch != nil && mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
- err := w.remove(watch.path)
- if err != nil && !errors.Is(err, ErrNonExistentWatch) {
- if !w.sendError(err) {
- return
- }
- }
+ if !w.sendEvent(ev) {
+ return
}
- var name string
- if watch != nil {
- name = watch.path
- }
- if nameLen > 0 {
- // Point "bytes" at the first byte of the filename
- bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
- // The filename is padded with NULL bytes. TrimRight() gets rid of those.
- name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
+ // Move to the next event in the buffer
+ offset += unix.SizeofInotifyEvent + inEvent.Len
+ }
+ }
+}
+
+func (w *inotify) handleEvent(inEvent *unix.InotifyEvent, buf *[65536]byte, offset uint32) (Event, bool) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ /// If the event happened to the watched directory or the watched file, the
+ /// kernel doesn't append the filename to the event, but we would like to
+ /// always fill the the "Name" field with a valid filename. We retrieve the
+ /// path of the watch from the "paths" map.
+ ///
+ /// Can be nil if Remove() was called in another goroutine for this path
+ /// inbetween reading the events from the kernel and reading the internal
+ /// state. Not much we can do about it, so just skip. See #616.
+ watch := w.watches.byWd(uint32(inEvent.Wd))
+ if watch == nil {
+ return Event{}, true
+ }
+
+ var (
+ name = watch.path
+ nameLen = uint32(inEvent.Len)
+ )
+ if nameLen > 0 {
+ /// Point "bytes" at the first byte of the filename
+ bb := *buf
+ bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&bb[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
+ /// The filename is padded with NULL bytes. TrimRight() gets rid of those.
+ name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\x00")
+ }
+
+ if debug {
+ internal.Debug(name, inEvent.Mask, inEvent.Cookie)
+ }
+
+ if inEvent.Mask&unix.IN_IGNORED != 0 || inEvent.Mask&unix.IN_UNMOUNT != 0 {
+ w.watches.remove(watch)
+ return Event{}, true
+ }
+
+ // inotify will automatically remove the watch on deletes; just need
+ // to clean our state here.
+ if inEvent.Mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
+ w.watches.remove(watch)
+ }
+
+ // We can't really update the state when a watched path is moved; only
+ // IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove the watch.
+ if inEvent.Mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
+ if watch.recurse { // Do nothing
+ return Event{}, true
+ }
+
+ err := w.remove(watch.path)
+ if err != nil && !errors.Is(err, ErrNonExistentWatch) {
+ if !w.sendError(err) {
+ return Event{}, false
}
+ }
+ }
+
+ /// Skip if we're watching both this path and the parent; the parent will
+ /// already send a delete so no need to do it twice.
+ if inEvent.Mask&unix.IN_DELETE_SELF != 0 {
+ _, ok := w.watches.path[filepath.Dir(watch.path)]
+ if ok {
+ return Event{}, true
+ }
+ }
- event := w.newEvent(name, mask)
+ ev := w.newEvent(name, inEvent.Mask, inEvent.Cookie)
+ // Need to update watch path for recurse.
+ if watch.recurse {
+ isDir := inEvent.Mask&unix.IN_ISDIR == unix.IN_ISDIR
+ /// New directory created: set up watch on it.
+ if isDir && ev.Has(Create) {
+ err := w.register(ev.Name, watch.flags, true)
+ if !w.sendError(err) {
+ return Event{}, false
+ }
- // Send the events that are not ignored on the events channel
- if mask&unix.IN_IGNORED == 0 {
- if !w.sendEvent(event) {
- return
+ // This was a directory rename, so we need to update all the
+ // children.
+ //
+ // TODO: this is of course pretty slow; we should use a better data
+ // structure for storing all of this, e.g. store children in the
+ // watch. I have some code for this in my kqueue refactor we can use
+ // in the future. For now I'm okay with this as it's not publicly
+ // available. Correctness first, performance second.
+ if ev.renamedFrom != "" {
+ for k, ww := range w.watches.wd {
+ if k == watch.wd || ww.path == ev.Name {
+ continue
+ }
+ if strings.HasPrefix(ww.path, ev.renamedFrom) {
+ ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1)
+ w.watches.wd[k] = ww
+ }
}
}
-
- // Move to the next event in the buffer
- offset += unix.SizeofInotifyEvent + nameLen
}
}
+
+ return ev, true
+}
+
+func (w *inotify) isRecursive(path string) bool {
+ ww := w.watches.byPath(path)
+ if ww == nil { // path could be a file, so also check the Dir.
+ ww = w.watches.byPath(filepath.Dir(path))
+ }
+ return ww != nil && ww.recurse
}
-// newEvent returns an platform-independent Event based on an inotify mask.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *inotify) newEvent(name string, mask, cookie uint32) Event {
e := Event{Name: name}
if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
e.Op |= Create
@@ -584,11 +526,58 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
if mask&unix.IN_MODIFY == unix.IN_MODIFY {
e.Op |= Write
}
+ if mask&unix.IN_OPEN == unix.IN_OPEN {
+ e.Op |= xUnportableOpen
+ }
+ if mask&unix.IN_ACCESS == unix.IN_ACCESS {
+ e.Op |= xUnportableRead
+ }
+ if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE {
+ e.Op |= xUnportableCloseWrite
+ }
+ if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE {
+ e.Op |= xUnportableCloseRead
+ }
if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
e.Op |= Rename
}
if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
e.Op |= Chmod
}
+
+ if cookie != 0 {
+ if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
+ w.cookiesMu.Lock()
+ w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name}
+ w.cookieIndex++
+ if w.cookieIndex > 9 {
+ w.cookieIndex = 0
+ }
+ w.cookiesMu.Unlock()
+ } else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
+ w.cookiesMu.Lock()
+ var prev string
+ for _, c := range w.cookies {
+ if c.cookie == cookie {
+ prev = c.path
+ break
+ }
+ }
+ w.cookiesMu.Unlock()
+ e.renamedFrom = prev
+ }
+ }
return e
}
+
+func (w *inotify) xSupports(op Op) bool {
+ return true // Supports everything.
+}
+
+func (w *inotify) state() {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ for wd, ww := range w.watches.wd {
+ fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path)
+ }
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
index 063a0915a07a..340aeec061c1 100644
--- a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
+++ b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
@@ -1,8 +1,4 @@
//go:build freebsd || openbsd || netbsd || dragonfly || darwin
-// +build freebsd openbsd netbsd dragonfly darwin
-
-// Note: the documentation on the Watcher type and methods is generated from
-// mkdoc.zsh
package fsnotify
@@ -11,174 +7,196 @@ import (
"fmt"
"os"
"path/filepath"
+ "runtime"
"sync"
+ "time"
+ "github.com/fsnotify/fsnotify/internal"
"golang.org/x/sys/unix"
)
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-// fp := os.Open("file")
-// os.Remove("file") // Triggers Chmod
-// fp.Close() // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-// # Default values on Linux 5.18
-// sysctl fs.inotify.max_user_watches=124983
-// sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-// fs.inotify.max_user_watches=124983
-// fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # Windows notes
-//
-// Paths can be added as "C:\path\to\dir", but forward slashes
-// ("C:/path/to/dir") will also work.
-//
-// When a watched directory is removed it will always send an event for the
-// directory itself, but may not send events for all files in that directory.
-// Sometimes it will send events for all times, sometimes it will send no
-// events, and often only for some files.
-//
-// 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
-// [WithBufferSize] to increase the value.
-type Watcher struct {
- // Events sends the filesystem change events.
- //
- // fsnotify can send the following events; a "path" here can refer to a
- // file, directory, symbolic link, or special file like a FIFO.
- //
- // fsnotify.Create A new path was created; this may be followed by one
- // or more Write events if data also gets written to a
- // file.
- //
- // fsnotify.Remove A path was removed.
- //
- // fsnotify.Rename A path was renamed. A rename is always sent with the
- // old path as Event.Name, and a Create event will be
- // sent with the new name. Renames are only sent for
- // paths that are currently watched; e.g. moving an
- // unmonitored file into a monitored directory will
- // show up as just a Create. Similarly, renaming a file
- // to outside a monitored directory will show up as
- // only a Rename.
- //
- // fsnotify.Write A file or named pipe was written to. A Truncate will
- // also trigger a Write. A single "write action"
- // initiated by the user may show up as one or multiple
- // writes, depending on when the system syncs things to
- // disk. For example when compiling a large Go program
- // you may get hundreds of Write events, and you may
- // 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.
- //
- // fsnotify.Chmod Attributes were changed. On Linux this is also sent
- // when a file is removed (or more accurately, when a
- // link to an inode is removed). On kqueue it's sent
- // when a file is truncated. On Windows it's never
- // sent.
+type kqueue struct {
+ *shared
Events chan Event
-
- // Errors sends any errors.
- //
- // ErrEventOverflow is used to indicate there are too many events:
- //
- // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
- // - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
- // - kqueue, fen: Not used.
Errors chan error
- done chan struct{}
- kq int // File descriptor (as returned by the kqueue() syscall).
- closepipe [2]int // Pipe used for closing.
- mu sync.Mutex // Protects access to watcher data
- watches map[string]int // Watched file descriptors (key: path).
- watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)).
- userWatches map[string]struct{} // Watches added with Watcher.Add()
- dirFlags map[string]uint32 // Watched directories to fflags used in kqueue.
- paths map[int]pathInfo // File descriptors to path names for processing kqueue events.
- fileExists map[string]struct{} // Keep track of if we know this file exists (to stop duplicate create events).
- isClosed bool // Set to true when Close() is first called
+ kq int // File descriptor (as returned by the kqueue() syscall).
+ closepipe [2]int // Pipe used for closing kq.
+ watches *watches
}
-type pathInfo struct {
- name string
- isDir bool
+type (
+ watches struct {
+ mu sync.RWMutex
+ wd map[int]watch // wd → watch
+ path map[string]int // pathname → wd
+ byDir map[string]map[int]struct{} // dirname(path) → wd
+ seen map[string]struct{} // Keep track of if we know this file exists.
+ byUser map[string]struct{} // Watches added with Watcher.Add()
+ }
+ watch struct {
+ wd int
+ name string
+ linkName string // In case of links; name is the target, and this is the link.
+ isDir bool
+ dirFlags uint32
+ }
+)
+
+func newWatches() *watches {
+ return &watches{
+ wd: make(map[int]watch),
+ path: make(map[string]int),
+ byDir: make(map[string]map[int]struct{}),
+ seen: make(map[string]struct{}),
+ byUser: make(map[string]struct{}),
+ }
}
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
- return NewBufferedWatcher(0)
+func (w *watches) listPaths(userOnly bool) []string {
+ w.mu.RLock()
+ defer w.mu.RUnlock()
+
+ if userOnly {
+ l := make([]string, 0, len(w.byUser))
+ for p := range w.byUser {
+ l = append(l, p)
+ }
+ return l
+ }
+
+ l := make([]string, 0, len(w.path))
+ for p := range w.path {
+ l = append(l, p)
+ }
+ return l
}
-// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
-// channel.
-//
-// The main use case for this is situations with a very large number of events
-// where the kernel buffer size can't be increased (e.g. due to lack of
-// permissions). An unbuffered Watcher will perform better for almost all use
-// cases, and whenever possible you will be better off increasing the kernel
-// buffers instead of adding a large userspace buffer.
-func NewBufferedWatcher(sz uint) (*Watcher, error) {
+func (w *watches) watchesInDir(path string) []string {
+ w.mu.RLock()
+ defer w.mu.RUnlock()
+
+ l := make([]string, 0, 4)
+ for fd := range w.byDir[path] {
+ info := w.wd[fd]
+ if _, ok := w.byUser[info.name]; !ok {
+ l = append(l, info.name)
+ }
+ }
+ return l
+}
+
+// Mark path as added by the user.
+func (w *watches) addUserWatch(path string) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ w.byUser[path] = struct{}{}
+}
+
+func (w *watches) addLink(path string, fd int) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ w.path[path] = fd
+ w.seen[path] = struct{}{}
+}
+
+func (w *watches) add(path, linkPath string, fd int, isDir bool) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ w.path[path] = fd
+ w.wd[fd] = watch{wd: fd, name: path, linkName: linkPath, isDir: isDir}
+
+ parent := filepath.Dir(path)
+ byDir, ok := w.byDir[parent]
+ if !ok {
+ byDir = make(map[int]struct{}, 1)
+ w.byDir[parent] = byDir
+ }
+ byDir[fd] = struct{}{}
+}
+
+func (w *watches) byWd(fd int) (watch, bool) {
+ w.mu.RLock()
+ defer w.mu.RUnlock()
+ info, ok := w.wd[fd]
+ return info, ok
+}
+
+func (w *watches) byPath(path string) (watch, bool) {
+ w.mu.RLock()
+ defer w.mu.RUnlock()
+ info, ok := w.wd[w.path[path]]
+ return info, ok
+}
+
+func (w *watches) updateDirFlags(path string, flags uint32) bool {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ fd, ok := w.path[path]
+ if !ok { // Already deleted: don't re-set it here.
+ return false
+ }
+ info := w.wd[fd]
+ info.dirFlags = flags
+ w.wd[fd] = info
+ return true
+}
+
+func (w *watches) remove(fd int, path string) bool {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ isDir := w.wd[fd].isDir
+ delete(w.path, path)
+ delete(w.byUser, path)
+
+ parent := filepath.Dir(path)
+ delete(w.byDir[parent], fd)
+
+ if len(w.byDir[parent]) == 0 {
+ delete(w.byDir, parent)
+ }
+
+ delete(w.wd, fd)
+ delete(w.seen, path)
+ return isDir
+}
+
+func (w *watches) markSeen(path string, exists bool) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if exists {
+ w.seen[path] = struct{}{}
+ } else {
+ delete(w.seen, path)
+ }
+}
+
+func (w *watches) seenBefore(path string) bool {
+ w.mu.RLock()
+ defer w.mu.RUnlock()
+ _, ok := w.seen[path]
+ return ok
+}
+
+var defaultBufferSize = 0
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
kq, closepipe, err := newKqueue()
if err != nil {
return nil, err
}
- w := &Watcher{
- kq: kq,
- closepipe: closepipe,
- watches: make(map[string]int),
- watchesByDir: make(map[string]map[int]struct{}),
- dirFlags: make(map[string]uint32),
- paths: make(map[int]pathInfo),
- fileExists: make(map[string]struct{}),
- userWatches: make(map[string]struct{}),
- Events: make(chan Event, sz),
- Errors: make(chan error),
- done: make(chan struct{}),
+ w := &kqueue{
+ shared: newShared(ev, errs),
+ Events: ev,
+ Errors: errs,
+ kq: kq,
+ closepipe: closepipe,
+ watches: newWatches(),
}
go w.readEvents()
@@ -193,7 +211,7 @@ func NewBufferedWatcher(sz uint) (*Watcher, error) {
// all.
func newKqueue() (kq int, closepipe [2]int, err error) {
kq, err = unix.Kqueue()
- if kq == -1 {
+ if err != nil {
return kq, closepipe, err
}
@@ -203,6 +221,8 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
unix.Close(kq)
return kq, closepipe, err
}
+ unix.CloseOnExec(closepipe[0])
+ unix.CloseOnExec(closepipe[1])
// Register changes to listen on the closepipe.
changes := make([]unix.Kevent_t, 1)
@@ -220,167 +240,72 @@ func newKqueue() (kq int, closepipe [2]int, err error) {
return kq, closepipe, nil
}
-// Returns true if the event was sent, or false if watcher is closed.
-func (w *Watcher) sendEvent(e Event) bool {
- select {
- case w.Events <- e:
- return true
- case <-w.done:
- return false
- }
-}
-
-// Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
- select {
- case w.Errors <- err:
- return true
- case <-w.done:
- return false
- }
-}
-
-// Close removes all watches and closes the Events channel.
-func (w *Watcher) Close() error {
- w.mu.Lock()
- if w.isClosed {
- w.mu.Unlock()
+func (w *kqueue) Close() error {
+ if w.shared.close() {
return nil
}
- w.isClosed = true
- // copy paths to remove while locked
- pathsToRemove := make([]string, 0, len(w.watches))
- for name := range w.watches {
- pathsToRemove = append(pathsToRemove, name)
- }
- w.mu.Unlock() // Unlock before calling Remove, which also locks
+ pathsToRemove := w.watches.listPaths(false)
for _, name := range pathsToRemove {
w.Remove(name)
}
- // Send "quit" message to the reader goroutine.
- unix.Close(w.closepipe[1])
- close(w.done)
-
+ unix.Close(w.closepipe[1]) // Send "quit" message to readEvents
return nil
}
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; watching it more than once is a no-op and will
-// not return an error. Paths that do not yet exist on the filesystem cannot be
-// watched.
-//
-// A watch will be automatically removed if the watched path is deleted or
-// renamed. The exception is the Windows backend, which doesn't remove the
-// watcher on renames.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// Returns [ErrClosed] if [Watcher.Close] was called.
-//
-// See [Watcher.AddWith] for a version that allows adding options.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many programs (especially editors) update files atomically: it
-// will write to a temporary file which is then moved to to destination,
-// overwriting the original (or some variant thereof). The watcher on the
-// original file is now lost, as that no longer exists.
-//
-// The upshot of this is that a power failure or crash won't leave a
-// half-written file.
-//
-// Watch the parent directory and use Event.Name to filter out files you're not
-// interested in. There is an example of this in cmd/fsnotify/file.go.
-func (w *Watcher) Add(name string) error { return w.AddWith(name) }
+func (w *kqueue) Add(name string) error { return w.AddWith(name) }
-// AddWith is like [Watcher.Add], but allows adding options. When using Add()
-// the defaults described below are used.
-//
-// Possible options are:
-//
-// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
-// other platforms. The default is 64K (65536 bytes).
-func (w *Watcher) AddWith(name string, opts ...addOpt) error {
- _ = getOptions(opts...)
+func (w *kqueue) AddWith(name string, opts ...addOpt) error {
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
+ time.Now().Format("15:04:05.000000000"), name)
+ }
- w.mu.Lock()
- w.userWatches[name] = struct{}{}
- w.mu.Unlock()
- _, err := w.addWatch(name, noteAllEvents)
- return err
+ with := getOptions(opts...)
+ if !w.xSupports(with.op) {
+ return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+ }
+
+ _, err := w.addWatch(name, noteAllEvents, false)
+ if err != nil {
+ return err
+ }
+ w.watches.addUserWatch(name)
+ return nil
}
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) Remove(name string) error {
+func (w *kqueue) Remove(name string) error {
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
+ time.Now().Format("15:04:05.000000000"), name)
+ }
return w.remove(name, true)
}
-func (w *Watcher) remove(name string, unwatchFiles bool) error {
- name = filepath.Clean(name)
- w.mu.Lock()
- if w.isClosed {
- w.mu.Unlock()
+func (w *kqueue) remove(name string, unwatchFiles bool) error {
+ if w.isClosed() {
return nil
}
- watchfd, ok := w.watches[name]
- w.mu.Unlock()
+
+ name = filepath.Clean(name)
+ info, ok := w.watches.byPath(name)
if !ok {
return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
}
- err := w.register([]int{watchfd}, unix.EV_DELETE, 0)
+ err := w.register([]int{info.wd}, unix.EV_DELETE, 0)
if err != nil {
return err
}
- unix.Close(watchfd)
-
- w.mu.Lock()
- isDir := w.paths[watchfd].isDir
- delete(w.watches, name)
- delete(w.userWatches, name)
-
- parentName := filepath.Dir(name)
- delete(w.watchesByDir[parentName], watchfd)
-
- if len(w.watchesByDir[parentName]) == 0 {
- delete(w.watchesByDir, parentName)
- }
+ unix.Close(info.wd)
- delete(w.paths, watchfd)
- delete(w.dirFlags, name)
- delete(w.fileExists, name)
- w.mu.Unlock()
+ isDir := w.watches.remove(info.wd, name)
// Find all watched paths that are in this directory that are not external.
if unwatchFiles && isDir {
- var pathsToRemove []string
- w.mu.Lock()
- for fd := range w.watchesByDir[name] {
- path := w.paths[fd]
- if _, ok := w.userWatches[path.name]; !ok {
- pathsToRemove = append(pathsToRemove, path.name)
- }
- }
- w.mu.Unlock()
+ pathsToRemove := w.watches.watchesInDir(name)
for _, name := range pathsToRemove {
// Since these are internal, not much sense in propagating error to
// the user, as that will just confuse them with an error about a
@@ -391,23 +316,11 @@ func (w *Watcher) remove(name string, unwatchFiles bool) error {
return nil
}
-// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
-// yet removed).
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) WatchList() []string {
- w.mu.Lock()
- defer w.mu.Unlock()
- if w.isClosed {
+func (w *kqueue) WatchList() []string {
+ if w.isClosed() {
return nil
}
-
- entries := make([]string, 0, len(w.userWatches))
- for pathname := range w.userWatches {
- entries = append(entries, pathname)
- }
-
- return entries
+ return w.watches.listPaths(true)
}
// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
@@ -417,114 +330,93 @@ const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | un
// described in kevent(2).
//
// Returns the real path to the file which was added, with symlinks resolved.
-func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
- var isDir bool
- name = filepath.Clean(name)
-
- w.mu.Lock()
- if w.isClosed {
- w.mu.Unlock()
+func (w *kqueue) addWatch(name string, flags uint32, listDir bool) (string, error) {
+ if w.isClosed() {
return "", ErrClosed
}
- watchfd, alreadyWatching := w.watches[name]
- // We already have a watch, but we can still override flags.
- if alreadyWatching {
- isDir = w.paths[watchfd].isDir
- }
- w.mu.Unlock()
+ name = filepath.Clean(name)
+
+ info, alreadyWatching := w.watches.byPath(name)
if !alreadyWatching {
fi, err := os.Lstat(name)
if err != nil {
return "", err
}
- // Don't watch sockets or named pipes
+ // Don't watch sockets or named pipes.
if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) {
return "", nil
}
- // Follow Symlinks.
- if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
+ // Follow symlinks, but only for paths added with Add(), and not paths
+ // we're adding from internalWatch from a listdir.
+ if !listDir && fi.Mode()&os.ModeSymlink == os.ModeSymlink {
link, err := os.Readlink(name)
if err != nil {
- // Return nil because Linux can add unresolvable symlinks to the
- // watch list without problems, so maintain consistency with
- // that. There will be no file events for broken symlinks.
- // TODO: more specific check; returns os.PathError; ENOENT?
- return "", nil
+ return "", err
+ }
+ if !filepath.IsAbs(link) {
+ link = filepath.Join(filepath.Dir(name), link)
}
- w.mu.Lock()
- _, alreadyWatching = w.watches[link]
- w.mu.Unlock()
-
+ _, alreadyWatching = w.watches.byPath(link)
if alreadyWatching {
// Add to watches so we don't get spurious Create events later
// on when we diff the directories.
- w.watches[name] = 0
- w.fileExists[name] = struct{}{}
+ w.watches.addLink(name, 0)
return link, nil
}
+ info.linkName = name
name = link
fi, err = os.Lstat(name)
if err != nil {
- return "", nil
+ return "", err
}
}
// Retry on EINTR; open() can return EINTR in practice on macOS.
// See #354, and Go issues 11180 and 39237.
for {
- watchfd, err = unix.Open(name, openMode, 0)
+ info.wd, err = unix.Open(name, openMode, 0)
if err == nil {
break
}
if errors.Is(err, unix.EINTR) {
continue
}
-
return "", err
}
- isDir = fi.IsDir()
+ info.isDir = fi.IsDir()
}
- err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
+ err := w.register([]int{info.wd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
if err != nil {
- unix.Close(watchfd)
+ unix.Close(info.wd)
return "", err
}
if !alreadyWatching {
- w.mu.Lock()
- parentName := filepath.Dir(name)
- w.watches[name] = watchfd
-
- watchesByDir, ok := w.watchesByDir[parentName]
- if !ok {
- watchesByDir = make(map[int]struct{}, 1)
- w.watchesByDir[parentName] = watchesByDir
- }
- watchesByDir[watchfd] = struct{}{}
- w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
- w.mu.Unlock()
+ w.watches.add(name, info.linkName, info.wd, info.isDir)
}
- if isDir {
- // Watch the directory if it has not been watched before, or if it was
- // watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
- w.mu.Lock()
-
+ // Watch the directory if it has not been watched before, or if it was
+ // watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
+ if info.isDir {
watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
- (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
- // Store flags so this watch can be updated later
- w.dirFlags[name] = flags
- w.mu.Unlock()
+ (!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE)
+ if !w.watches.updateDirFlags(name, flags) {
+ return "", nil
+ }
if watchDir {
- if err := w.watchDirectoryFiles(name); err != nil {
+ d := name
+ if info.linkName != "" {
+ d = info.linkName
+ }
+ if err := w.watchDirectoryFiles(d); err != nil {
return "", err
}
}
@@ -534,7 +426,7 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
// readEvents reads from kqueue and converts the received kevents into
// Event values that it sends down the Events channel.
-func (w *Watcher) readEvents() {
+func (w *kqueue) readEvents() {
defer func() {
close(w.Events)
close(w.Errors)
@@ -543,50 +435,65 @@ func (w *Watcher) readEvents() {
}()
eventBuffer := make([]unix.Kevent_t, 10)
- for closed := false; !closed; {
+ for {
kevents, err := w.read(eventBuffer)
// EINTR is okay, the syscall was interrupted before timeout expired.
if err != nil && err != unix.EINTR {
if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) {
- closed = true
+ return
}
- continue
}
- // Flush the events we received to the Events channel
for _, kevent := range kevents {
var (
- watchfd = int(kevent.Ident)
- mask = uint32(kevent.Fflags)
+ wd = int(kevent.Ident)
+ mask = uint32(kevent.Fflags)
)
// Shut down the loop when the pipe is closed, but only after all
// other events have been processed.
- if watchfd == w.closepipe[0] {
- closed = true
- continue
+ if wd == w.closepipe[0] {
+ return
+ }
+
+ path, ok := w.watches.byWd(wd)
+ if debug {
+ internal.Debug(path.name, &kevent)
}
- w.mu.Lock()
- path := w.paths[watchfd]
- w.mu.Unlock()
+ // On macOS it seems that sometimes an event with Ident=0 is
+ // delivered, and no other flags/information beyond that, even
+ // though we never saw such a file descriptor. For example in
+ // TestWatchSymlink/277 (usually at the end, but sometimes sooner):
+ //
+ // fmt.Printf("READ: %2d %#v\n", kevent.Ident, kevent)
+ // unix.Kevent_t{Ident:0x2a, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+ // unix.Kevent_t{Ident:0x0, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)}
+ //
+ // The first is a normal event, the second with Ident 0. No error
+ // flag, no data, no ... nothing.
+ //
+ // I read a bit through bsd/kern_event.c from the xnu source, but I
+ // don't really see an obvious location where this is triggered –
+ // this doesn't seem intentional, but idk...
+ //
+ // Technically fd 0 is a valid descriptor, so only skip it if
+ // there's no path, and if we're on macOS.
+ if !ok && kevent.Ident == 0 && runtime.GOOS == "darwin" {
+ continue
+ }
- event := w.newEvent(path.name, mask)
+ event := w.newEvent(path.name, path.linkName, mask)
if event.Has(Rename) || event.Has(Remove) {
w.remove(event.Name, false)
- w.mu.Lock()
- delete(w.fileExists, event.Name)
- w.mu.Unlock()
+ w.watches.markSeen(event.Name, false)
}
if path.isDir && event.Has(Write) && !event.Has(Remove) {
- w.sendDirectoryChangeEvents(event.Name)
- } else {
- if !w.sendEvent(event) {
- closed = true
- continue
- }
+ w.dirChange(event.Name)
+ } else if !w.sendEvent(event) {
+ return
}
if event.Has(Remove) {
@@ -594,25 +501,34 @@ func (w *Watcher) readEvents() {
// mv f1 f2 will delete f2, then create f2.
if path.isDir {
fileDir := filepath.Clean(event.Name)
- w.mu.Lock()
- _, found := w.watches[fileDir]
- w.mu.Unlock()
+ _, found := w.watches.byPath(fileDir)
if found {
- err := w.sendDirectoryChangeEvents(fileDir)
- if err != nil {
- if !w.sendError(err) {
- closed = true
- }
+ // TODO: this branch is never triggered in any test.
+ // Added in d6220df (2012).
+ // isDir check added in 8611c35 (2016): https://github.com/fsnotify/fsnotify/pull/111
+ //
+ // I don't really get how this can be triggered either.
+ // And it wasn't triggered in the patch that added it,
+ // either.
+ //
+ // Original also had a comment:
+ // make sure the directory exists before we watch for
+ // changes. When we do a recursive watch and perform
+ // rm -rf, the parent directory might have gone
+ // missing, ignore the missing directory and let the
+ // upcoming delete event remove the watch from the
+ // parent directory.
+ err := w.dirChange(fileDir)
+ if !w.sendError(err) {
+ return
}
}
} else {
- filePath := filepath.Clean(event.Name)
- if fi, err := os.Lstat(filePath); err == nil {
- err := w.sendFileCreatedEventIfNew(filePath, fi)
- if err != nil {
- if !w.sendError(err) {
- closed = true
- }
+ path := filepath.Clean(event.Name)
+ if fi, err := os.Lstat(path); err == nil {
+ err := w.sendCreateIfNew(path, fi)
+ if !w.sendError(err) {
+ return
}
}
}
@@ -622,8 +538,14 @@ func (w *Watcher) readEvents() {
}
// newEvent returns an platform-independent Event based on kqueue Fflags.
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *kqueue) newEvent(name, linkName string, mask uint32) Event {
e := Event{Name: name}
+ if linkName != "" {
+ // If the user watched "/path/link" then emit events as "/path/link"
+ // rather than "/path/target".
+ e.Name = linkName
+ }
+
if mask&unix.NOTE_DELETE == unix.NOTE_DELETE {
e.Op |= Remove
}
@@ -645,8 +567,7 @@ func (w *Watcher) newEvent(name string, mask uint32) Event {
}
// watchDirectoryFiles to mimic inotify when adding a watch on a directory
-func (w *Watcher) watchDirectoryFiles(dirPath string) error {
- // Get all files
+func (w *kqueue) watchDirectoryFiles(dirPath string) error {
files, err := os.ReadDir(dirPath)
if err != nil {
return err
@@ -674,9 +595,7 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
}
}
- w.mu.Lock()
- w.fileExists[cleanPath] = struct{}{}
- w.mu.Unlock()
+ w.watches.markSeen(cleanPath, true)
}
return nil
@@ -686,7 +605,7 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error {
//
// This functionality is to have the BSD watcher match the inotify, which sends
// a create event for files created in a watched directory.
-func (w *Watcher) sendDirectoryChangeEvents(dir string) error {
+func (w *kqueue) dirChange(dir string) error {
files, err := os.ReadDir(dir)
if err != nil {
// Directory no longer exists: we can ignore this safely. kqueue will
@@ -694,69 +613,62 @@ func (w *Watcher) sendDirectoryChangeEvents(dir string) error {
if errors.Is(err, os.ErrNotExist) {
return nil
}
- return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)
+ return fmt.Errorf("fsnotify.dirChange %q: %w", dir, err)
}
for _, f := range files {
fi, err := f.Info()
if err != nil {
- return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)
+ if errors.Is(err, os.ErrNotExist) {
+ return nil
+ }
+ return fmt.Errorf("fsnotify.dirChange: %w", err)
}
- err = w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi)
+ err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi)
if err != nil {
// Don't need to send an error if this file isn't readable.
- if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) {
+ if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) || errors.Is(err, os.ErrNotExist) {
return nil
}
- return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)
+ return fmt.Errorf("fsnotify.dirChange: %w", err)
}
}
return nil
}
-// sendFileCreatedEvent sends a create event if the file isn't already being tracked.
-func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fi os.FileInfo) (err error) {
- w.mu.Lock()
- _, doesExist := w.fileExists[filePath]
- w.mu.Unlock()
- if !doesExist {
- if !w.sendEvent(Event{Name: filePath, Op: Create}) {
- return
+// Send a create event if the file isn't already being tracked, and start
+// watching this file.
+func (w *kqueue) sendCreateIfNew(path string, fi os.FileInfo) error {
+ if !w.watches.seenBefore(path) {
+ if !w.sendEvent(Event{Name: path, Op: Create}) {
+ return nil
}
}
- // like watchDirectoryFiles (but without doing another ReadDir)
- filePath, err = w.internalWatch(filePath, fi)
+ // Like watchDirectoryFiles, but without doing another ReadDir.
+ path, err := w.internalWatch(path, fi)
if err != nil {
return err
}
-
- w.mu.Lock()
- w.fileExists[filePath] = struct{}{}
- w.mu.Unlock()
-
+ w.watches.markSeen(path, true)
return nil
}
-func (w *Watcher) internalWatch(name string, fi os.FileInfo) (string, error) {
+func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) {
if fi.IsDir() {
// mimic Linux providing delete events for subdirectories, but preserve
// the flags used if currently watching subdirectory
- w.mu.Lock()
- flags := w.dirFlags[name]
- w.mu.Unlock()
-
- flags |= unix.NOTE_DELETE | unix.NOTE_RENAME
- return w.addWatch(name, flags)
+ info, _ := w.watches.byPath(name)
+ return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME, true)
}
- // watch file to mimic Linux inotify
- return w.addWatch(name, noteAllEvents)
+ // Watch file to mimic Linux inotify.
+ return w.addWatch(name, noteAllEvents, true)
}
// Register events with the queue.
-func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
+func (w *kqueue) register(fds []int, flags int, fflags uint32) error {
changes := make([]unix.Kevent_t, len(fds))
for i, fd := range fds {
// SetKevent converts int to the platform-specific types.
@@ -773,10 +685,21 @@ func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
}
// read retrieves pending events, or waits until an event occurs.
-func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
+func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
n, err := unix.Kevent(w.kq, nil, events, nil)
if err != nil {
return nil, err
}
return events[0:n], nil
}
+
+func (w *kqueue) xSupports(op Op) bool {
+ //if runtime.GOOS == "freebsd" {
+ // return true // Supports everything.
+ //}
+ if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+ op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+ return false
+ }
+ return true
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/backend_other.go b/vendor/github.com/fsnotify/fsnotify/backend_other.go
index d34a23c015f8..b8c0ad722675 100644
--- a/vendor/github.com/fsnotify/fsnotify/backend_other.go
+++ b/vendor/github.com/fsnotify/fsnotify/backend_other.go
@@ -1,205 +1,22 @@
//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
-// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
-
-// Note: the documentation on the Watcher type and methods is generated from
-// mkdoc.zsh
package fsnotify
import "errors"
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-// fp := os.Open("file")
-// os.Remove("file") // Triggers Chmod
-// fp.Close() // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-// # Default values on Linux 5.18
-// sysctl fs.inotify.max_user_watches=124983
-// sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-// fs.inotify.max_user_watches=124983
-// fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # Windows notes
-//
-// Paths can be added as "C:\path\to\dir", but forward slashes
-// ("C:/path/to/dir") will also work.
-//
-// When a watched directory is removed it will always send an event for the
-// directory itself, but may not send events for all files in that directory.
-// Sometimes it will send events for all times, sometimes it will send no
-// events, and often only for some files.
-//
-// 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
-// [WithBufferSize] to increase the value.
-type Watcher struct {
- // Events sends the filesystem change events.
- //
- // fsnotify can send the following events; a "path" here can refer to a
- // file, directory, symbolic link, or special file like a FIFO.
- //
- // fsnotify.Create A new path was created; this may be followed by one
- // or more Write events if data also gets written to a
- // file.
- //
- // fsnotify.Remove A path was removed.
- //
- // fsnotify.Rename A path was renamed. A rename is always sent with the
- // old path as Event.Name, and a Create event will be
- // sent with the new name. Renames are only sent for
- // paths that are currently watched; e.g. moving an
- // unmonitored file into a monitored directory will
- // show up as just a Create. Similarly, renaming a file
- // to outside a monitored directory will show up as
- // only a Rename.
- //
- // fsnotify.Write A file or named pipe was written to. A Truncate will
- // also trigger a Write. A single "write action"
- // initiated by the user may show up as one or multiple
- // writes, depending on when the system syncs things to
- // disk. For example when compiling a large Go program
- // you may get hundreds of Write events, and you may
- // 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.
- //
- // fsnotify.Chmod Attributes were changed. On Linux this is also sent
- // when a file is removed (or more accurately, when a
- // link to an inode is removed). On kqueue it's sent
- // when a file is truncated. On Windows it's never
- // sent.
+type other struct {
Events chan Event
-
- // Errors sends any errors.
- //
- // ErrEventOverflow is used to indicate there are too many events:
- //
- // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
- // - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
- // - kqueue, fen: Not used.
Errors chan error
}
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
+var defaultBufferSize = 0
+
+func newBackend(ev chan Event, errs chan error) (backend, error) {
return nil, errors.New("fsnotify not supported on the current platform")
}
-
-// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
-// channel.
-//
-// The main use case for this is situations with a very large number of events
-// where the kernel buffer size can't be increased (e.g. due to lack of
-// permissions). An unbuffered Watcher will perform better for almost all use
-// cases, and whenever possible you will be better off increasing the kernel
-// buffers instead of adding a large userspace buffer.
-func NewBufferedWatcher(sz uint) (*Watcher, error) { return NewWatcher() }
-
-// Close removes all watches and closes the Events channel.
-func (w *Watcher) Close() error { return nil }
-
-// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
-// yet removed).
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) WatchList() []string { return nil }
-
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; watching it more than once is a no-op and will
-// not return an error. Paths that do not yet exist on the filesystem cannot be
-// watched.
-//
-// A watch will be automatically removed if the watched path is deleted or
-// renamed. The exception is the Windows backend, which doesn't remove the
-// watcher on renames.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// Returns [ErrClosed] if [Watcher.Close] was called.
-//
-// See [Watcher.AddWith] for a version that allows adding options.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many programs (especially editors) update files atomically: it
-// will write to a temporary file which is then moved to to destination,
-// overwriting the original (or some variant thereof). The watcher on the
-// original file is now lost, as that no longer exists.
-//
-// The upshot of this is that a power failure or crash won't leave a
-// half-written file.
-//
-// Watch the parent directory and use Event.Name to filter out files you're not
-// interested in. There is an example of this in cmd/fsnotify/file.go.
-func (w *Watcher) Add(name string) error { return nil }
-
-// AddWith is like [Watcher.Add], but allows adding options. When using Add()
-// the defaults described below are used.
-//
-// Possible options are:
-//
-// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
-// other platforms. The default is 64K (65536 bytes).
-func (w *Watcher) AddWith(name string, opts ...addOpt) error { return nil }
-
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) Remove(name string) error { return nil }
+func (w *other) Close() error { return nil }
+func (w *other) WatchList() []string { return nil }
+func (w *other) Add(name string) error { return nil }
+func (w *other) AddWith(name string, opts ...addOpt) error { return nil }
+func (w *other) Remove(name string) error { return nil }
+func (w *other) xSupports(op Op) bool { return false }
diff --git a/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/vendor/github.com/fsnotify/fsnotify/backend_windows.go
index 9bc91e5d613f..3433642d6419 100644
--- a/vendor/github.com/fsnotify/fsnotify/backend_windows.go
+++ b/vendor/github.com/fsnotify/fsnotify/backend_windows.go
@@ -1,12 +1,8 @@
//go:build windows
-// +build windows
// Windows backend based on ReadDirectoryChangesW()
//
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
-//
-// Note: the documentation on the Watcher type and methods is generated from
-// mkdoc.zsh
package fsnotify
@@ -19,196 +15,80 @@ import (
"runtime"
"strings"
"sync"
+ "time"
"unsafe"
+ "github.com/fsnotify/fsnotify/internal"
"golang.org/x/sys/windows"
)
-// Watcher watches a set of paths, delivering events on a channel.
-//
-// A watcher should not be copied (e.g. pass it by pointer, rather than by
-// value).
-//
-// # Linux notes
-//
-// When a file is removed a Remove event won't be emitted until all file
-// descriptors are closed, and deletes will always emit a Chmod. For example:
-//
-// fp := os.Open("file")
-// os.Remove("file") // Triggers Chmod
-// fp.Close() // Triggers Remove
-//
-// This is the event that inotify sends, so not much can be changed about this.
-//
-// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
-// for the number of watches per user, and fs.inotify.max_user_instances
-// specifies the maximum number of inotify instances per user. Every Watcher you
-// create is an "instance", and every path you add is a "watch".
-//
-// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
-// /proc/sys/fs/inotify/max_user_instances
-//
-// To increase them you can use sysctl or write the value to the /proc file:
-//
-// # Default values on Linux 5.18
-// sysctl fs.inotify.max_user_watches=124983
-// sysctl fs.inotify.max_user_instances=128
-//
-// To make the changes persist on reboot edit /etc/sysctl.conf or
-// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
-// your distro's documentation):
-//
-// fs.inotify.max_user_watches=124983
-// fs.inotify.max_user_instances=128
-//
-// Reaching the limit will result in a "no space left on device" or "too many open
-// files" error.
-//
-// # kqueue notes (macOS, BSD)
-//
-// kqueue requires opening a file descriptor for every file that's being watched;
-// so if you're watching a directory with five files then that's six file
-// descriptors. You will run in to your system's "max open files" limit faster on
-// these platforms.
-//
-// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
-// control the maximum number of open files, as well as /etc/login.conf on BSD
-// systems.
-//
-// # Windows notes
-//
-// Paths can be added as "C:\path\to\dir", but forward slashes
-// ("C:/path/to/dir") will also work.
-//
-// When a watched directory is removed it will always send an event for the
-// directory itself, but may not send events for all files in that directory.
-// Sometimes it will send events for all times, sometimes it will send no
-// events, and often only for some files.
-//
-// 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
-// [WithBufferSize] to increase the value.
-type Watcher struct {
- // Events sends the filesystem change events.
- //
- // fsnotify can send the following events; a "path" here can refer to a
- // file, directory, symbolic link, or special file like a FIFO.
- //
- // fsnotify.Create A new path was created; this may be followed by one
- // or more Write events if data also gets written to a
- // file.
- //
- // fsnotify.Remove A path was removed.
- //
- // fsnotify.Rename A path was renamed. A rename is always sent with the
- // old path as Event.Name, and a Create event will be
- // sent with the new name. Renames are only sent for
- // paths that are currently watched; e.g. moving an
- // unmonitored file into a monitored directory will
- // show up as just a Create. Similarly, renaming a file
- // to outside a monitored directory will show up as
- // only a Rename.
- //
- // fsnotify.Write A file or named pipe was written to. A Truncate will
- // also trigger a Write. A single "write action"
- // initiated by the user may show up as one or multiple
- // writes, depending on when the system syncs things to
- // disk. For example when compiling a large Go program
- // you may get hundreds of Write events, and you may
- // 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.
- //
- // fsnotify.Chmod Attributes were changed. On Linux this is also sent
- // when a file is removed (or more accurately, when a
- // link to an inode is removed). On kqueue it's sent
- // when a file is truncated. On Windows it's never
- // sent.
+type readDirChangesW struct {
Events chan Event
-
- // Errors sends any errors.
- //
- // ErrEventOverflow is used to indicate there are too many events:
- //
- // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
- // - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
- // - kqueue, fen: Not used.
Errors chan error
port windows.Handle // Handle to completion port
input chan *input // Inputs to the reader are sent on this channel
- quit chan chan<- error
+ done chan chan<- error
mu sync.Mutex // Protects access to watches, closed
watches watchMap // Map of watches (key: i-number)
closed bool // Set to true when Close() is first called
}
-// NewWatcher creates a new Watcher.
-func NewWatcher() (*Watcher, error) {
- return NewBufferedWatcher(50)
-}
+var defaultBufferSize = 50
-// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
-// channel.
-//
-// The main use case for this is situations with a very large number of events
-// where the kernel buffer size can't be increased (e.g. due to lack of
-// permissions). An unbuffered Watcher will perform better for almost all use
-// cases, and whenever possible you will be better off increasing the kernel
-// buffers instead of adding a large userspace buffer.
-func NewBufferedWatcher(sz uint) (*Watcher, error) {
+func newBackend(ev chan Event, errs chan error) (backend, error) {
port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
if err != nil {
return nil, os.NewSyscallError("CreateIoCompletionPort", err)
}
- w := &Watcher{
+ w := &readDirChangesW{
+ Events: ev,
+ Errors: errs,
port: port,
watches: make(watchMap),
input: make(chan *input, 1),
- Events: make(chan Event, sz),
- Errors: make(chan error),
- quit: make(chan chan<- error, 1),
+ done: make(chan chan<- error, 1),
}
go w.readEvents()
return w, nil
}
-func (w *Watcher) isClosed() bool {
+func (w *readDirChangesW) isClosed() bool {
w.mu.Lock()
defer w.mu.Unlock()
return w.closed
}
-func (w *Watcher) sendEvent(name string, mask uint64) bool {
+func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool {
if mask == 0 {
return false
}
event := w.newEvent(name, uint32(mask))
+ event.renamedFrom = renamedFrom
select {
- case ch := <-w.quit:
- w.quit <- ch
+ case ch := <-w.done:
+ w.done <- ch
case w.Events <- event:
}
return true
}
// Returns true if the error was sent, or false if watcher is closed.
-func (w *Watcher) sendError(err error) bool {
+func (w *readDirChangesW) sendError(err error) bool {
+ if err == nil {
+ return true
+ }
select {
+ case <-w.done:
+ return false
case w.Errors <- err:
return true
- case <-w.quit:
}
- return false
}
-// Close removes all watches and closes the Events channel.
-func (w *Watcher) Close() error {
+func (w *readDirChangesW) Close() error {
if w.isClosed() {
return nil
}
@@ -217,66 +97,30 @@ func (w *Watcher) Close() error {
w.closed = true
w.mu.Unlock()
- // Send "quit" message to the reader goroutine
+ // Send "done" message to the reader goroutine
ch := make(chan error)
- w.quit <- ch
+ w.done <- ch
if err := w.wakeupReader(); err != nil {
return err
}
return <-ch
}
-// Add starts monitoring the path for changes.
-//
-// A path can only be watched once; watching it more than once is a no-op and will
-// not return an error. Paths that do not yet exist on the filesystem cannot be
-// watched.
-//
-// A watch will be automatically removed if the watched path is deleted or
-// renamed. The exception is the Windows backend, which doesn't remove the
-// watcher on renames.
-//
-// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
-// filesystems (/proc, /sys, etc.) generally don't work.
-//
-// Returns [ErrClosed] if [Watcher.Close] was called.
-//
-// See [Watcher.AddWith] for a version that allows adding options.
-//
-// # Watching directories
-//
-// All files in a directory are monitored, including new files that are created
-// after the watcher is started. Subdirectories are not watched (i.e. it's
-// non-recursive).
-//
-// # Watching files
-//
-// Watching individual files (rather than directories) is generally not
-// recommended as many programs (especially editors) update files atomically: it
-// will write to a temporary file which is then moved to to destination,
-// overwriting the original (or some variant thereof). The watcher on the
-// original file is now lost, as that no longer exists.
-//
-// The upshot of this is that a power failure or crash won't leave a
-// half-written file.
-//
-// Watch the parent directory and use Event.Name to filter out files you're not
-// interested in. There is an example of this in cmd/fsnotify/file.go.
-func (w *Watcher) Add(name string) error { return w.AddWith(name) }
+func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) }
-// AddWith is like [Watcher.Add], but allows adding options. When using Add()
-// the defaults described below are used.
-//
-// Possible options are:
-//
-// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
-// other platforms. The default is 64K (65536 bytes).
-func (w *Watcher) AddWith(name string, opts ...addOpt) error {
+func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error {
if w.isClosed() {
return ErrClosed
}
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n",
+ time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+ }
with := getOptions(opts...)
+ if !w.xSupports(with.op) {
+ return fmt.Errorf("%w: %s", xErrUnsupported, with.op)
+ }
if with.bufsize < 4096 {
return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes")
}
@@ -295,18 +139,14 @@ func (w *Watcher) AddWith(name string, opts ...addOpt) error {
return <-in.reply
}
-// Remove stops monitoring the path for changes.
-//
-// Directories are always removed non-recursively. For example, if you added
-// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
-//
-// Removing a path that has not yet been added returns [ErrNonExistentWatch].
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) Remove(name string) error {
+func (w *readDirChangesW) Remove(name string) error {
if w.isClosed() {
return nil
}
+ if debug {
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n",
+ time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name))
+ }
in := &input{
op: opRemoveWatch,
@@ -320,11 +160,7 @@ func (w *Watcher) Remove(name string) error {
return <-in.reply
}
-// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
-// yet removed).
-//
-// Returns nil if [Watcher.Close] was called.
-func (w *Watcher) WatchList() []string {
+func (w *readDirChangesW) WatchList() []string {
if w.isClosed() {
return nil
}
@@ -335,7 +171,13 @@ func (w *Watcher) WatchList() []string {
entries := make([]string, 0, len(w.watches))
for _, entry := range w.watches {
for _, watchEntry := range entry {
- entries = append(entries, watchEntry.path)
+ for name := range watchEntry.names {
+ entries = append(entries, filepath.Join(watchEntry.path, name))
+ }
+ // the directory itself is being watched
+ if watchEntry.mask != 0 {
+ entries = append(entries, watchEntry.path)
+ }
}
}
@@ -361,7 +203,7 @@ const (
sysFSIGNORED = 0x8000
)
-func (w *Watcher) newEvent(name string, mask uint32) Event {
+func (w *readDirChangesW) newEvent(name string, mask uint32) Event {
e := Event{Name: name}
if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
e.Op |= Create
@@ -417,7 +259,7 @@ type (
watchMap map[uint32]indexMap
)
-func (w *Watcher) wakeupReader() error {
+func (w *readDirChangesW) wakeupReader() error {
err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil)
if err != nil {
return os.NewSyscallError("PostQueuedCompletionStatus", err)
@@ -425,7 +267,7 @@ func (w *Watcher) wakeupReader() error {
return nil
}
-func (w *Watcher) getDir(pathname string) (dir string, err error) {
+func (w *readDirChangesW) getDir(pathname string) (dir string, err error) {
attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname))
if err != nil {
return "", os.NewSyscallError("GetFileAttributes", err)
@@ -439,7 +281,7 @@ func (w *Watcher) getDir(pathname string) (dir string, err error) {
return
}
-func (w *Watcher) getIno(path string) (ino *inode, err error) {
+func (w *readDirChangesW) getIno(path string) (ino *inode, err error) {
h, err := windows.CreateFile(windows.StringToUTF16Ptr(path),
windows.FILE_LIST_DIRECTORY,
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
@@ -482,9 +324,8 @@ func (m watchMap) set(ino *inode, watch *watch) {
}
// Must run within the I/O thread.
-func (w *Watcher) addWatch(pathname string, flags uint64, bufsize int) error {
- //pathname, recurse := recursivePath(pathname)
- recurse := false
+func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error {
+ pathname, recurse := recursivePath(pathname)
dir, err := w.getDir(pathname)
if err != nil {
@@ -538,7 +379,7 @@ func (w *Watcher) addWatch(pathname string, flags uint64, bufsize int) error {
}
// Must run within the I/O thread.
-func (w *Watcher) remWatch(pathname string) error {
+func (w *readDirChangesW) remWatch(pathname string) error {
pathname, recurse := recursivePath(pathname)
dir, err := w.getDir(pathname)
@@ -566,11 +407,11 @@ func (w *Watcher) remWatch(pathname string) error {
return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname)
}
if pathname == dir {
- w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+ w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
watch.mask = 0
} else {
name := filepath.Base(pathname)
- w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED)
+ w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED)
delete(watch.names, name)
}
@@ -578,23 +419,23 @@ func (w *Watcher) remWatch(pathname string) error {
}
// Must run within the I/O thread.
-func (w *Watcher) deleteWatch(watch *watch) {
+func (w *readDirChangesW) deleteWatch(watch *watch) {
for name, mask := range watch.names {
if mask&provisional == 0 {
- w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED)
+ w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED)
}
delete(watch.names, name)
}
if watch.mask != 0 {
if watch.mask&provisional == 0 {
- w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
+ w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED)
}
watch.mask = 0
}
}
// Must run within the I/O thread.
-func (w *Watcher) startRead(watch *watch) error {
+func (w *readDirChangesW) startRead(watch *watch) error {
err := windows.CancelIo(watch.ino.handle)
if err != nil {
w.sendError(os.NewSyscallError("CancelIo", err))
@@ -624,7 +465,7 @@ func (w *Watcher) startRead(watch *watch) error {
err := os.NewSyscallError("ReadDirectoryChanges", rdErr)
if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
// Watched directory was probably removed
- w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+ w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
err = nil
}
w.deleteWatch(watch)
@@ -637,7 +478,7 @@ func (w *Watcher) startRead(watch *watch) error {
// readEvents reads from the I/O completion port, converts the
// received events into Event objects and sends them via the Events channel.
// Entry point to the I/O thread.
-func (w *Watcher) readEvents() {
+func (w *readDirChangesW) readEvents() {
var (
n uint32
key uintptr
@@ -652,7 +493,7 @@ func (w *Watcher) readEvents() {
watch := (*watch)(unsafe.Pointer(ov))
if watch == nil {
select {
- case ch := <-w.quit:
+ case ch := <-w.done:
w.mu.Lock()
var indexes []indexMap
for _, index := range w.watches {
@@ -700,7 +541,7 @@ func (w *Watcher) readEvents() {
}
case windows.ERROR_ACCESS_DENIED:
// Watched directory was probably removed
- w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
+ w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF)
w.deleteWatch(watch)
w.startRead(watch)
continue
@@ -733,6 +574,10 @@ func (w *Watcher) readEvents() {
name := windows.UTF16ToString(buf)
fullname := filepath.Join(watch.path, name)
+ if debug {
+ internal.Debug(fullname, raw.Action)
+ }
+
var mask uint64
switch raw.Action {
case windows.FILE_ACTION_REMOVED:
@@ -761,21 +606,22 @@ func (w *Watcher) readEvents() {
}
}
- sendNameEvent := func() {
- w.sendEvent(fullname, watch.names[name]&mask)
- }
if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME {
- sendNameEvent()
+ w.sendEvent(fullname, "", watch.names[name]&mask)
}
if raw.Action == windows.FILE_ACTION_REMOVED {
- w.sendEvent(fullname, watch.names[name]&sysFSIGNORED)
+ w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED)
delete(watch.names, name)
}
- w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action))
+ if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
+ w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action))
+ } else {
+ w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action))
+ }
+
if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME {
- fullname = filepath.Join(watch.path, watch.rename)
- sendNameEvent()
+ w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask)
}
// Move to the next event in the buffer
@@ -787,8 +633,7 @@ func (w *Watcher) readEvents() {
// Error!
if offset >= n {
//lint:ignore ST1005 Windows should be capitalized
- w.sendError(errors.New(
- "Windows system assumed buffer larger than it is, events have likely been missed"))
+ w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed"))
break
}
}
@@ -799,7 +644,7 @@ func (w *Watcher) readEvents() {
}
}
-func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
+func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 {
var m uint32
if mask&sysFSMODIFY != 0 {
m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE
@@ -810,7 +655,7 @@ func (w *Watcher) toWindowsFlags(mask uint64) uint32 {
return m
}
-func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
+func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 {
switch action {
case windows.FILE_ACTION_ADDED:
return sysFSCREATE
@@ -825,3 +670,11 @@ func (w *Watcher) toFSnotifyFlags(action uint32) uint64 {
}
return 0
}
+
+func (w *readDirChangesW) xSupports(op Op) bool {
+ if op.Has(xUnportableOpen) || op.Has(xUnportableRead) ||
+ op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) {
+ return false
+ }
+ return true
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go
index 24c99cc4999e..f64be4bf98ee 100644
--- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go
+++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go
@@ -3,19 +3,146 @@
//
// Currently supported systems:
//
-// Linux 2.6.32+ via inotify
-// BSD, macOS via kqueue
-// Windows via ReadDirectoryChangesW
-// illumos via FEN
+// - Linux via inotify
+// - BSD, macOS via kqueue
+// - Windows via ReadDirectoryChangesW
+// - illumos via FEN
+//
+// # FSNOTIFY_DEBUG
+//
+// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to
+// stderr. This can be useful to track down some problems, especially in cases
+// where fsnotify is used as an indirect dependency.
+//
+// Every event will be printed as soon as there's something useful to print,
+// with as little processing from fsnotify.
+//
+// Example output:
+//
+// FSNOTIFY_DEBUG: 11:34:23.633087586 256:IN_CREATE → "/tmp/file-1"
+// FSNOTIFY_DEBUG: 11:34:23.633202319 4:IN_ATTRIB → "/tmp/file-1"
+// FSNOTIFY_DEBUG: 11:34:28.989728764 512:IN_DELETE → "/tmp/file-1"
package fsnotify
import (
"errors"
"fmt"
+ "os"
"path/filepath"
"strings"
)
+// Watcher watches a set of paths, delivering events on a channel.
+//
+// A watcher should not be copied (e.g. pass it by pointer, rather than by
+// value).
+//
+// # Linux notes
+//
+// When a file is removed a Remove event won't be emitted until all file
+// descriptors are closed, and deletes will always emit a Chmod. For example:
+//
+// fp := os.Open("file")
+// os.Remove("file") // Triggers Chmod
+// fp.Close() // Triggers Remove
+//
+// This is the event that inotify sends, so not much can be changed about this.
+//
+// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
+// for the number of watches per user, and fs.inotify.max_user_instances
+// specifies the maximum number of inotify instances per user. Every Watcher you
+// create is an "instance", and every path you add is a "watch".
+//
+// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
+// /proc/sys/fs/inotify/max_user_instances
+//
+// To increase them you can use sysctl or write the value to the /proc file:
+//
+// # Default values on Linux 5.18
+// sysctl fs.inotify.max_user_watches=124983
+// sysctl fs.inotify.max_user_instances=128
+//
+// To make the changes persist on reboot edit /etc/sysctl.conf or
+// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
+// your distro's documentation):
+//
+// fs.inotify.max_user_watches=124983
+// fs.inotify.max_user_instances=128
+//
+// Reaching the limit will result in a "no space left on device" or "too many open
+// files" error.
+//
+// # kqueue notes (macOS, BSD)
+//
+// kqueue requires opening a file descriptor for every file that's being watched;
+// so if you're watching a directory with five files then that's six file
+// descriptors. You will run in to your system's "max open files" limit faster on
+// these platforms.
+//
+// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
+// control the maximum number of open files, as well as /etc/login.conf on BSD
+// systems.
+//
+// # Windows notes
+//
+// Paths can be added as "C:\\path\\to\\dir", but forward slashes
+// ("C:/path/to/dir") will also work.
+//
+// When a watched directory is removed it will always send an event for the
+// directory itself, but may not send events for all files in that directory.
+// Sometimes it will send events for all files, sometimes it will send no
+// events, and often only for some files.
+//
+// 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
+// [WithBufferSize] to increase the value.
+type Watcher struct {
+ b backend
+
+ // Events sends the filesystem change events.
+ //
+ // fsnotify can send the following events; a "path" here can refer to a
+ // file, directory, symbolic link, or special file like a FIFO.
+ //
+ // fsnotify.Create A new path was created; this may be followed by one
+ // or more Write events if data also gets written to a
+ // file.
+ //
+ // fsnotify.Remove A path was removed.
+ //
+ // fsnotify.Rename A path was renamed. A rename is always sent with the
+ // old path as Event.Name, and a Create event will be
+ // sent with the new name. Renames are only sent for
+ // paths that are currently watched; e.g. moving an
+ // unmonitored file into a monitored directory will
+ // show up as just a Create. Similarly, renaming a file
+ // to outside a monitored directory will show up as
+ // only a Rename.
+ //
+ // fsnotify.Write A file or named pipe was written to. A Truncate will
+ // also trigger a Write. A single "write action"
+ // initiated by the user may show up as one or multiple
+ // writes, depending on when the system syncs things to
+ // disk. For example when compiling a large Go program
+ // you may get hundreds of Write events, and you may
+ // 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.
+ //
+ // fsnotify.Chmod Attributes were changed. On Linux this is also sent
+ // when a file is removed (or more accurately, when a
+ // link to an inode is removed). On kqueue it's sent
+ // when a file is truncated. On Windows it's never
+ // sent.
+ Events chan Event
+
+ // Errors sends any errors.
+ Errors chan error
+}
+
// Event represents a file system notification.
type Event struct {
// Path to the file or directory.
@@ -30,6 +157,16 @@ type Event struct {
// This is a bitmask and some systems may send multiple operations at once.
// Use the Event.Has() method instead of comparing with ==.
Op Op
+
+ // Create events will have this set to the old path if it's a rename. This
+ // only works when both the source and destination are watched. It's not
+ // reliable when watching individual files, only directories.
+ //
+ // For example "mv /tmp/file /tmp/rename" will emit:
+ //
+ // Event{Op: Rename, Name: "/tmp/file"}
+ // Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"}
+ renamedFrom string
}
// Op describes a set of file operations.
@@ -50,7 +187,7 @@ const (
// example "remove to trash" is often a rename).
Remove
- // The path was renamed to something else; any watched on it will be
+ // The path was renamed to something else; any watches on it will be
// removed.
Rename
@@ -60,15 +197,157 @@ const (
// get triggered very frequently by some software. For example, Spotlight
// indexing on macOS, anti-virus software, backup software, etc.
Chmod
+
+ // File descriptor was opened.
+ //
+ // Only works on Linux and FreeBSD.
+ xUnportableOpen
+
+ // File was read from.
+ //
+ // Only works on Linux and FreeBSD.
+ xUnportableRead
+
+ // File opened for writing was closed.
+ //
+ // Only works on Linux and FreeBSD.
+ //
+ // The advantage of using this over Write is that it's more reliable than
+ // waiting for Write events to stop. It's also faster (if you're not
+ // listening to Write events): copying a file of a few GB can easily
+ // generate tens of thousands of Write events in a short span of time.
+ xUnportableCloseWrite
+
+ // File opened for reading was closed.
+ //
+ // Only works on Linux and FreeBSD.
+ xUnportableCloseRead
)
-// Common errors that can be reported.
var (
+ // ErrNonExistentWatch is used when Remove() is called on a path that's not
+ // added.
ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch")
- ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow")
- ErrClosed = errors.New("fsnotify: watcher already closed")
+
+ // ErrClosed is used when trying to operate on a closed Watcher.
+ ErrClosed = errors.New("fsnotify: watcher already closed")
+
+ // ErrEventOverflow is reported from the Errors channel when there are too
+ // many events:
+ //
+ // - inotify: inotify returns IN_Q_OVERFLOW – because there are too
+ // many queued events (the fs.inotify.max_queued_events
+ // sysctl can be used to increase this).
+ // - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
+ // - kqueue, fen: Not used.
+ ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow")
+
+ // ErrUnsupported is returned by AddWith() when WithOps() specified an
+ // Unportable event that's not supported on this platform.
+ //lint:ignore ST1012 not relevant
+ xErrUnsupported = errors.New("fsnotify: not supported with this backend")
)
+// NewWatcher creates a new Watcher.
+func NewWatcher() (*Watcher, error) {
+ ev, errs := make(chan Event, defaultBufferSize), make(chan error)
+ b, err := newBackend(ev, errs)
+ if err != nil {
+ return nil, err
+ }
+ return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
+// channel.
+//
+// The main use case for this is situations with a very large number of events
+// where the kernel buffer size can't be increased (e.g. due to lack of
+// permissions). An unbuffered Watcher will perform better for almost all use
+// cases, and whenever possible you will be better off increasing the kernel
+// buffers instead of adding a large userspace buffer.
+func NewBufferedWatcher(sz uint) (*Watcher, error) {
+ ev, errs := make(chan Event, sz), make(chan error)
+ b, err := newBackend(ev, errs)
+ if err != nil {
+ return nil, err
+ }
+ return &Watcher{b: b, Events: ev, Errors: errs}, nil
+}
+
+// Add starts monitoring the path for changes.
+//
+// A path can only be watched once; watching it more than once is a no-op and will
+// not return an error. Paths that do not yet exist on the filesystem cannot be
+// watched.
+//
+// A watch will be automatically removed if the watched path is deleted or
+// renamed. The exception is the Windows backend, which doesn't remove the
+// watcher on renames.
+//
+// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
+// filesystems (/proc, /sys, etc.) generally don't work.
+//
+// Returns [ErrClosed] if [Watcher.Close] was called.
+//
+// See [Watcher.AddWith] for a version that allows adding options.
+//
+// # Watching directories
+//
+// All files in a directory are monitored, including new files that are created
+// after the watcher is started. Subdirectories are not watched (i.e. it's
+// non-recursive).
+//
+// # Watching files
+//
+// Watching individual files (rather than directories) is generally not
+// recommended as many programs (especially editors) update files atomically: it
+// will write to a temporary file which is then moved to destination,
+// overwriting the original (or some variant thereof). The watcher on the
+// original file is now lost, as that no longer exists.
+//
+// The upshot of this is that a power failure or crash won't leave a
+// half-written file.
+//
+// Watch the parent directory and use Event.Name to filter out files you're not
+// interested in. There is an example of this in cmd/fsnotify/file.go.
+func (w *Watcher) Add(path string) error { return w.b.Add(path) }
+
+// AddWith is like [Watcher.Add], but allows adding options. When using Add()
+// the defaults described below are used.
+//
+// Possible options are:
+//
+// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
+// other platforms. The default is 64K (65536 bytes).
+func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) }
+
+// Remove stops monitoring the path for changes.
+//
+// Directories are always removed non-recursively. For example, if you added
+// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
+//
+// Removing a path that has not yet been added returns [ErrNonExistentWatch].
+//
+// Returns nil if [Watcher.Close] was called.
+func (w *Watcher) Remove(path string) error { return w.b.Remove(path) }
+
+// Close removes all watches and closes the Events channel.
+func (w *Watcher) Close() error { return w.b.Close() }
+
+// WatchList returns all paths explicitly added with [Watcher.Add] (and are not
+// yet removed).
+//
+// The order is undefined, and may differ per call. Returns nil if
+// [Watcher.Close] was called.
+func (w *Watcher) WatchList() []string { return w.b.WatchList() }
+
+// Supports reports if all the listed operations are supported by this platform.
+//
+// Create, Write, Remove, Rename, and Chmod are always supported. It can only
+// return false for an Op starting with Unportable.
+func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) }
+
func (o Op) String() string {
var b strings.Builder
if o.Has(Create) {
@@ -80,6 +359,18 @@ func (o Op) String() string {
if o.Has(Write) {
b.WriteString("|WRITE")
}
+ if o.Has(xUnportableOpen) {
+ b.WriteString("|OPEN")
+ }
+ if o.Has(xUnportableRead) {
+ b.WriteString("|READ")
+ }
+ if o.Has(xUnportableCloseWrite) {
+ b.WriteString("|CLOSE_WRITE")
+ }
+ if o.Has(xUnportableCloseRead) {
+ b.WriteString("|CLOSE_READ")
+ }
if o.Has(Rename) {
b.WriteString("|RENAME")
}
@@ -100,24 +391,48 @@ func (e Event) Has(op Op) bool { return e.Op.Has(op) }
// String returns a string representation of the event with their path.
func (e Event) String() string {
+ if e.renamedFrom != "" {
+ return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom)
+ }
return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name)
}
type (
+ backend interface {
+ Add(string) error
+ AddWith(string, ...addOpt) error
+ Remove(string) error
+ WatchList() []string
+ Close() error
+ xSupports(Op) bool
+ }
addOpt func(opt *withOpts)
withOpts struct {
- bufsize int
+ bufsize int
+ op Op
+ noFollow bool
+ sendCreate bool
}
)
+var debug = func() bool {
+ // Check for exactly "1" (rather than mere existence) so we can add
+ // options/flags in the future. I don't know if we ever want that, but it's
+ // nice to leave the option open.
+ return os.Getenv("FSNOTIFY_DEBUG") == "1"
+}()
+
var defaultOpts = withOpts{
bufsize: 65536, // 64K
+ op: Create | Write | Remove | Rename | Chmod,
}
func getOptions(opts ...addOpt) withOpts {
with := defaultOpts
for _, o := range opts {
- o(&with)
+ if o != nil {
+ o(&with)
+ }
}
return with
}
@@ -136,9 +451,44 @@ func WithBufferSize(bytes int) addOpt {
return func(opt *withOpts) { opt.bufsize = bytes }
}
+// WithOps sets which operations to listen for. The default is [Create],
+// [Write], [Remove], [Rename], and [Chmod].
+//
+// Excluding operations you're not interested in can save quite a bit of CPU
+// time; in some use cases there may be hundreds of thousands of useless Write
+// or Chmod operations per second.
+//
+// This can also be used to add unportable operations not supported by all
+// platforms; unportable operations all start with "Unportable":
+// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and
+// [UnportableCloseRead].
+//
+// AddWith returns an error when using an unportable operation that's not
+// supported. Use [Watcher.Support] to check for support.
+func withOps(op Op) addOpt {
+ return func(opt *withOpts) { opt.op = op }
+}
+
+// WithNoFollow disables following symlinks, so the symlinks themselves are
+// watched.
+func withNoFollow() addOpt {
+ return func(opt *withOpts) { opt.noFollow = true }
+}
+
+// "Internal" option for recursive watches on inotify.
+func withCreate() addOpt {
+ return func(opt *withOpts) { opt.sendCreate = true }
+}
+
+var enableRecurse = false
+
// Check if this path is recursive (ends with "/..." or "\..."), and return the
// path with the /... stripped.
func recursivePath(path string) (string, bool) {
+ path = filepath.Clean(path)
+ if !enableRecurse { // Only enabled in tests for now.
+ return path, false
+ }
if filepath.Base(path) == "..." {
return filepath.Dir(path), true
}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/darwin.go b/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
new file mode 100644
index 000000000000..0b01bc182a1e
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/darwin.go
@@ -0,0 +1,39 @@
+//go:build darwin
+
+package internal
+
+import (
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+var (
+ ErrSyscallEACCES = syscall.EACCES
+ ErrUnixEACCES = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+ // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+ var l syscall.Rlimit
+ err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+ if err == nil && l.Cur != l.Max {
+ l.Cur = l.Max
+ syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+ }
+ maxfiles = l.Cur
+
+ if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles {
+ maxfiles = uint64(n)
+ }
+
+ if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles {
+ maxfiles = uint64(n)
+ }
+}
+
+func Maxfiles() uint64 { return maxfiles }
+func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
new file mode 100644
index 000000000000..928319fb09ab
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go
@@ -0,0 +1,57 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+ n string
+ m uint32
+}{
+ {"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE},
+ {"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+ {"NOTE_BACKGROUND", unix.NOTE_BACKGROUND},
+ {"NOTE_CHILD", unix.NOTE_CHILD},
+ {"NOTE_CRITICAL", unix.NOTE_CRITICAL},
+ {"NOTE_DELETE", unix.NOTE_DELETE},
+ {"NOTE_EXEC", unix.NOTE_EXEC},
+ {"NOTE_EXIT", unix.NOTE_EXIT},
+ {"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS},
+ {"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR},
+ {"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL},
+ {"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL},
+ {"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK},
+ {"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY},
+ {"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED},
+ {"NOTE_EXTEND", unix.NOTE_EXTEND},
+ {"NOTE_FFAND", unix.NOTE_FFAND},
+ {"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+ {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+ {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+ {"NOTE_FFNOP", unix.NOTE_FFNOP},
+ {"NOTE_FFOR", unix.NOTE_FFOR},
+ {"NOTE_FORK", unix.NOTE_FORK},
+ {"NOTE_FUNLOCK", unix.NOTE_FUNLOCK},
+ {"NOTE_LEEWAY", unix.NOTE_LEEWAY},
+ {"NOTE_LINK", unix.NOTE_LINK},
+ {"NOTE_LOWAT", unix.NOTE_LOWAT},
+ {"NOTE_MACHTIME", unix.NOTE_MACHTIME},
+ {"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME},
+ {"NOTE_NONE", unix.NOTE_NONE},
+ {"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+ {"NOTE_OOB", unix.NOTE_OOB},
+ //{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!)
+ {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+ {"NOTE_REAP", unix.NOTE_REAP},
+ {"NOTE_RENAME", unix.NOTE_RENAME},
+ {"NOTE_REVOKE", unix.NOTE_REVOKE},
+ {"NOTE_SECONDS", unix.NOTE_SECONDS},
+ {"NOTE_SIGNAL", unix.NOTE_SIGNAL},
+ {"NOTE_TRACK", unix.NOTE_TRACK},
+ {"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+ {"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+ {"NOTE_USECONDS", unix.NOTE_USECONDS},
+ {"NOTE_VM_ERROR", unix.NOTE_VM_ERROR},
+ {"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE},
+ {"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE},
+ {"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE},
+ {"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
new file mode 100644
index 000000000000..3186b0c3491d
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go
@@ -0,0 +1,33 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+ n string
+ m uint32
+}{
+ {"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+ {"NOTE_CHILD", unix.NOTE_CHILD},
+ {"NOTE_DELETE", unix.NOTE_DELETE},
+ {"NOTE_EXEC", unix.NOTE_EXEC},
+ {"NOTE_EXIT", unix.NOTE_EXIT},
+ {"NOTE_EXTEND", unix.NOTE_EXTEND},
+ {"NOTE_FFAND", unix.NOTE_FFAND},
+ {"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+ {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+ {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+ {"NOTE_FFNOP", unix.NOTE_FFNOP},
+ {"NOTE_FFOR", unix.NOTE_FFOR},
+ {"NOTE_FORK", unix.NOTE_FORK},
+ {"NOTE_LINK", unix.NOTE_LINK},
+ {"NOTE_LOWAT", unix.NOTE_LOWAT},
+ {"NOTE_OOB", unix.NOTE_OOB},
+ {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+ {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+ {"NOTE_RENAME", unix.NOTE_RENAME},
+ {"NOTE_REVOKE", unix.NOTE_REVOKE},
+ {"NOTE_TRACK", unix.NOTE_TRACK},
+ {"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+ {"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+ {"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
new file mode 100644
index 000000000000..f69fdb930f5f
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go
@@ -0,0 +1,42 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+ n string
+ m uint32
+}{
+ {"NOTE_ABSTIME", unix.NOTE_ABSTIME},
+ {"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+ {"NOTE_CHILD", unix.NOTE_CHILD},
+ {"NOTE_CLOSE", unix.NOTE_CLOSE},
+ {"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE},
+ {"NOTE_DELETE", unix.NOTE_DELETE},
+ {"NOTE_EXEC", unix.NOTE_EXEC},
+ {"NOTE_EXIT", unix.NOTE_EXIT},
+ {"NOTE_EXTEND", unix.NOTE_EXTEND},
+ {"NOTE_FFAND", unix.NOTE_FFAND},
+ {"NOTE_FFCOPY", unix.NOTE_FFCOPY},
+ {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK},
+ {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK},
+ {"NOTE_FFNOP", unix.NOTE_FFNOP},
+ {"NOTE_FFOR", unix.NOTE_FFOR},
+ {"NOTE_FILE_POLL", unix.NOTE_FILE_POLL},
+ {"NOTE_FORK", unix.NOTE_FORK},
+ {"NOTE_LINK", unix.NOTE_LINK},
+ {"NOTE_LOWAT", unix.NOTE_LOWAT},
+ {"NOTE_MSECONDS", unix.NOTE_MSECONDS},
+ {"NOTE_NSECONDS", unix.NOTE_NSECONDS},
+ {"NOTE_OPEN", unix.NOTE_OPEN},
+ {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+ {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+ {"NOTE_READ", unix.NOTE_READ},
+ {"NOTE_RENAME", unix.NOTE_RENAME},
+ {"NOTE_REVOKE", unix.NOTE_REVOKE},
+ {"NOTE_SECONDS", unix.NOTE_SECONDS},
+ {"NOTE_TRACK", unix.NOTE_TRACK},
+ {"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+ {"NOTE_TRIGGER", unix.NOTE_TRIGGER},
+ {"NOTE_USECONDS", unix.NOTE_USECONDS},
+ {"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
new file mode 100644
index 000000000000..607e683bd731
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go
@@ -0,0 +1,32 @@
+//go:build freebsd || openbsd || netbsd || dragonfly || darwin
+
+package internal
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+func Debug(name string, kevent *unix.Kevent_t) {
+ mask := uint32(kevent.Fflags)
+
+ var (
+ l []string
+ unknown = mask
+ )
+ for _, n := range names {
+ if mask&n.m == n.m {
+ l = append(l, n.n)
+ unknown ^= n.m
+ }
+ }
+ if unknown > 0 {
+ l = append(l, fmt.Sprintf("0x%x", unknown))
+ }
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-60s → %q\n",
+ time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
new file mode 100644
index 000000000000..35c734be4311
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go
@@ -0,0 +1,56 @@
+package internal
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask, cookie uint32) {
+ names := []struct {
+ n string
+ m uint32
+ }{
+ {"IN_ACCESS", unix.IN_ACCESS},
+ {"IN_ATTRIB", unix.IN_ATTRIB},
+ {"IN_CLOSE", unix.IN_CLOSE},
+ {"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE},
+ {"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE},
+ {"IN_CREATE", unix.IN_CREATE},
+ {"IN_DELETE", unix.IN_DELETE},
+ {"IN_DELETE_SELF", unix.IN_DELETE_SELF},
+ {"IN_IGNORED", unix.IN_IGNORED},
+ {"IN_ISDIR", unix.IN_ISDIR},
+ {"IN_MODIFY", unix.IN_MODIFY},
+ {"IN_MOVE", unix.IN_MOVE},
+ {"IN_MOVED_FROM", unix.IN_MOVED_FROM},
+ {"IN_MOVED_TO", unix.IN_MOVED_TO},
+ {"IN_MOVE_SELF", unix.IN_MOVE_SELF},
+ {"IN_OPEN", unix.IN_OPEN},
+ {"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW},
+ {"IN_UNMOUNT", unix.IN_UNMOUNT},
+ }
+
+ var (
+ l []string
+ unknown = mask
+ )
+ for _, n := range names {
+ if mask&n.m == n.m {
+ l = append(l, n.n)
+ unknown ^= n.m
+ }
+ }
+ if unknown > 0 {
+ l = append(l, fmt.Sprintf("0x%x", unknown))
+ }
+ var c string
+ if cookie > 0 {
+ c = fmt.Sprintf("(cookie: %d) ", cookie)
+ }
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-30s → %s%q\n",
+ time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name)
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
new file mode 100644
index 000000000000..e5b3b6f69433
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go
@@ -0,0 +1,25 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+ n string
+ m uint32
+}{
+ {"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+ {"NOTE_CHILD", unix.NOTE_CHILD},
+ {"NOTE_DELETE", unix.NOTE_DELETE},
+ {"NOTE_EXEC", unix.NOTE_EXEC},
+ {"NOTE_EXIT", unix.NOTE_EXIT},
+ {"NOTE_EXTEND", unix.NOTE_EXTEND},
+ {"NOTE_FORK", unix.NOTE_FORK},
+ {"NOTE_LINK", unix.NOTE_LINK},
+ {"NOTE_LOWAT", unix.NOTE_LOWAT},
+ {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+ {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+ {"NOTE_RENAME", unix.NOTE_RENAME},
+ {"NOTE_REVOKE", unix.NOTE_REVOKE},
+ {"NOTE_TRACK", unix.NOTE_TRACK},
+ {"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+ {"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
new file mode 100644
index 000000000000..1dd455bc5a4e
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go
@@ -0,0 +1,28 @@
+package internal
+
+import "golang.org/x/sys/unix"
+
+var names = []struct {
+ n string
+ m uint32
+}{
+ {"NOTE_ATTRIB", unix.NOTE_ATTRIB},
+ // {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386?
+ {"NOTE_CHILD", unix.NOTE_CHILD},
+ {"NOTE_DELETE", unix.NOTE_DELETE},
+ {"NOTE_EOF", unix.NOTE_EOF},
+ {"NOTE_EXEC", unix.NOTE_EXEC},
+ {"NOTE_EXIT", unix.NOTE_EXIT},
+ {"NOTE_EXTEND", unix.NOTE_EXTEND},
+ {"NOTE_FORK", unix.NOTE_FORK},
+ {"NOTE_LINK", unix.NOTE_LINK},
+ {"NOTE_LOWAT", unix.NOTE_LOWAT},
+ {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK},
+ {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK},
+ {"NOTE_RENAME", unix.NOTE_RENAME},
+ {"NOTE_REVOKE", unix.NOTE_REVOKE},
+ {"NOTE_TRACK", unix.NOTE_TRACK},
+ {"NOTE_TRACKERR", unix.NOTE_TRACKERR},
+ {"NOTE_TRUNCATE", unix.NOTE_TRUNCATE},
+ {"NOTE_WRITE", unix.NOTE_WRITE},
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
new file mode 100644
index 000000000000..f1b2e73bd5ba
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go
@@ -0,0 +1,45 @@
+package internal
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+func Debug(name string, mask int32) {
+ names := []struct {
+ n string
+ m int32
+ }{
+ {"FILE_ACCESS", unix.FILE_ACCESS},
+ {"FILE_MODIFIED", unix.FILE_MODIFIED},
+ {"FILE_ATTRIB", unix.FILE_ATTRIB},
+ {"FILE_TRUNC", unix.FILE_TRUNC},
+ {"FILE_NOFOLLOW", unix.FILE_NOFOLLOW},
+ {"FILE_DELETE", unix.FILE_DELETE},
+ {"FILE_RENAME_TO", unix.FILE_RENAME_TO},
+ {"FILE_RENAME_FROM", unix.FILE_RENAME_FROM},
+ {"UNMOUNTED", unix.UNMOUNTED},
+ {"MOUNTEDOVER", unix.MOUNTEDOVER},
+ {"FILE_EXCEPTION", unix.FILE_EXCEPTION},
+ }
+
+ var (
+ l []string
+ unknown = mask
+ )
+ for _, n := range names {
+ if mask&n.m == n.m {
+ l = append(l, n.n)
+ unknown ^= n.m
+ }
+ }
+ if unknown > 0 {
+ l = append(l, fmt.Sprintf("0x%x", unknown))
+ }
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-30s → %q\n",
+ time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name)
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
new file mode 100644
index 000000000000..52bf4ce53b56
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go
@@ -0,0 +1,40 @@
+package internal
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "golang.org/x/sys/windows"
+)
+
+func Debug(name string, mask uint32) {
+ names := []struct {
+ n string
+ m uint32
+ }{
+ {"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED},
+ {"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED},
+ {"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED},
+ {"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME},
+ {"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME},
+ }
+
+ var (
+ l []string
+ unknown = mask
+ )
+ for _, n := range names {
+ if mask&n.m == n.m {
+ l = append(l, n.n)
+ unknown ^= n.m
+ }
+ }
+ if unknown > 0 {
+ l = append(l, fmt.Sprintf("0x%x", unknown))
+ }
+ fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-65s → %q\n",
+ time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name))
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go b/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
new file mode 100644
index 000000000000..5ac8b507978f
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go
@@ -0,0 +1,31 @@
+//go:build freebsd
+
+package internal
+
+import (
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+var (
+ ErrSyscallEACCES = syscall.EACCES
+ ErrUnixEACCES = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+ // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+ var l syscall.Rlimit
+ err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+ if err == nil && l.Cur != l.Max {
+ l.Cur = l.Max
+ syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+ }
+ maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64 { return maxfiles }
+func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) }
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/internal.go b/vendor/github.com/fsnotify/fsnotify/internal/internal.go
new file mode 100644
index 000000000000..7daa45e19eec
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/internal.go
@@ -0,0 +1,2 @@
+// Package internal contains some helpers.
+package internal
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/unix.go b/vendor/github.com/fsnotify/fsnotify/internal/unix.go
new file mode 100644
index 000000000000..b251fb803869
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/unix.go
@@ -0,0 +1,31 @@
+//go:build !windows && !darwin && !freebsd && !plan9
+
+package internal
+
+import (
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+var (
+ ErrSyscallEACCES = syscall.EACCES
+ ErrUnixEACCES = unix.EACCES
+)
+
+var maxfiles uint64
+
+func SetRlimit() {
+ // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/
+ var l syscall.Rlimit
+ err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
+ if err == nil && l.Cur != l.Max {
+ l.Cur = l.Max
+ syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l)
+ }
+ maxfiles = uint64(l.Cur)
+}
+
+func Maxfiles() uint64 { return maxfiles }
+func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) }
+func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) }
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/unix2.go b/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
new file mode 100644
index 000000000000..37dfeddc2896
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/unix2.go
@@ -0,0 +1,7 @@
+//go:build !windows
+
+package internal
+
+func HasPrivilegesForSymlink() bool {
+ return true
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/internal/windows.go b/vendor/github.com/fsnotify/fsnotify/internal/windows.go
new file mode 100644
index 000000000000..896bc2e5a2f3
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/internal/windows.go
@@ -0,0 +1,41 @@
+//go:build windows
+
+package internal
+
+import (
+ "errors"
+
+ "golang.org/x/sys/windows"
+)
+
+// Just a dummy.
+var (
+ ErrSyscallEACCES = errors.New("dummy")
+ ErrUnixEACCES = errors.New("dummy")
+)
+
+func SetRlimit() {}
+func Maxfiles() uint64 { return 1<<64 - 1 }
+func Mkfifo(path string, mode uint32) error { return errors.New("no FIFOs on Windows") }
+func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") }
+
+func HasPrivilegesForSymlink() bool {
+ var sid *windows.SID
+ err := windows.AllocateAndInitializeSid(
+ &windows.SECURITY_NT_AUTHORITY,
+ 2,
+ windows.SECURITY_BUILTIN_DOMAIN_RID,
+ windows.DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &sid)
+ if err != nil {
+ return false
+ }
+ defer windows.FreeSid(sid)
+ token := windows.Token(0)
+ member, err := token.IsMember(sid)
+ if err != nil {
+ return false
+ }
+ return member || token.IsElevated()
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
deleted file mode 100644
index 99012ae6539e..000000000000
--- a/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/usr/bin/env zsh
-[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1
-setopt err_exit no_unset pipefail extended_glob
-
-# Simple script to update the godoc comments on all watchers so you don't need
-# to update the same comment 5 times.
-
-watcher=$(</tmp/x
- print -r -- $cmt >>/tmp/x
- tail -n+$(( end + 1 )) $file >>/tmp/x
- mv /tmp/x $file
- done
-}
-
-set-cmt '^type Watcher struct ' $watcher
-set-cmt '^func NewWatcher(' $new
-set-cmt '^func NewBufferedWatcher(' $newbuffered
-set-cmt '^func (w \*Watcher) Add(' $add
-set-cmt '^func (w \*Watcher) AddWith(' $addwith
-set-cmt '^func (w \*Watcher) Remove(' $remove
-set-cmt '^func (w \*Watcher) Close(' $close
-set-cmt '^func (w \*Watcher) WatchList(' $watchlist
-set-cmt '^[[:space:]]*Events *chan Event$' $events
-set-cmt '^[[:space:]]*Errors *chan error$' $errors
diff --git a/vendor/github.com/fsnotify/fsnotify/shared.go b/vendor/github.com/fsnotify/fsnotify/shared.go
new file mode 100644
index 000000000000..3ee9b58f1d2b
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/shared.go
@@ -0,0 +1,64 @@
+package fsnotify
+
+import "sync"
+
+type shared struct {
+ Events chan Event
+ Errors chan error
+ done chan struct{}
+ mu sync.Mutex
+}
+
+func newShared(ev chan Event, errs chan error) *shared {
+ return &shared{
+ Events: ev,
+ Errors: errs,
+ done: make(chan struct{}),
+ }
+}
+
+// Returns true if the event was sent, or false if watcher is closed.
+func (w *shared) sendEvent(e Event) bool {
+ if e.Op == 0 {
+ return true
+ }
+ select {
+ case <-w.done:
+ return false
+ case w.Events <- e:
+ return true
+ }
+}
+
+// Returns true if the error was sent, or false if watcher is closed.
+func (w *shared) sendError(err error) bool {
+ if err == nil {
+ return true
+ }
+ select {
+ case <-w.done:
+ return false
+ case w.Errors <- err:
+ return true
+ }
+}
+
+func (w *shared) isClosed() bool {
+ select {
+ case <-w.done:
+ return true
+ default:
+ return false
+ }
+}
+
+// Mark as closed; returns true if it was already closed.
+func (w *shared) close() bool {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.isClosed() {
+ return true
+ }
+ close(w.done)
+ return false
+}
diff --git a/vendor/github.com/fsnotify/fsnotify/staticcheck.conf b/vendor/github.com/fsnotify/fsnotify/staticcheck.conf
new file mode 100644
index 000000000000..8fa7351f0c24
--- /dev/null
+++ b/vendor/github.com/fsnotify/fsnotify/staticcheck.conf
@@ -0,0 +1,3 @@
+checks = ['all',
+ '-U1000', # Don't complain about unused functions.
+]
diff --git a/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/vendor/github.com/fsnotify/fsnotify/system_bsd.go
index 4322b0b88557..f65e8fe3edce 100644
--- a/vendor/github.com/fsnotify/fsnotify/system_bsd.go
+++ b/vendor/github.com/fsnotify/fsnotify/system_bsd.go
@@ -1,5 +1,4 @@
//go:build freebsd || openbsd || netbsd || dragonfly
-// +build freebsd openbsd netbsd dragonfly
package fsnotify
diff --git a/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/vendor/github.com/fsnotify/fsnotify/system_darwin.go
index 5da5ffa78fe7..a29fc7aab620 100644
--- a/vendor/github.com/fsnotify/fsnotify/system_darwin.go
+++ b/vendor/github.com/fsnotify/fsnotify/system_darwin.go
@@ -1,5 +1,4 @@
//go:build darwin
-// +build darwin
package fsnotify
diff --git a/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md b/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md
deleted file mode 100644
index 6f717dbd86e3..000000000000
--- a/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# v4.0.4
-
-## Fixed
-
- - Reverted "Allow unmarshalling JSONWebKeySets with unsupported key types" as a
- breaking change. See #136 / #137.
-
-# v4.0.3
-
-## Changed
-
- - Allow unmarshalling JSONWebKeySets with unsupported key types (#130)
- - Document that OpaqueKeyEncrypter can't be implemented (for now) (#129)
- - Dependency updates
-
-# v4.0.2
-
-## Changed
-
- - Improved documentation of Verify() to note that JSONWebKeySet is a supported
- argument type (#104)
- - Defined exported error values for missing x5c header and unsupported elliptic
- curves error cases (#117)
-
-# v4.0.1
-
-## Fixed
-
- - An attacker could send a JWE containing compressed data that used large
- amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`.
- Those functions now return an error if the decompressed data would exceed
- 250kB or 10x the compressed size (whichever is larger). Thanks to
- Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj)
- for reporting.
-
-# v4.0.0
-
-This release makes some breaking changes in order to more thoroughly
-address the vulnerabilities discussed in [Three New Attacks Against JSON Web
-Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot
-token".
-
-## Changed
-
- - Limit JWT encryption types (exclude password or public key types) (#78)
- - Enforce minimum length for HMAC keys (#85)
- - jwt: match any audience in a list, rather than requiring all audiences (#81)
- - jwt: accept only Compact Serialization (#75)
- - jws: Add expected algorithms for signatures (#74)
- - Require specifying expected algorithms for ParseEncrypted,
- ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned,
- jwt.ParseSignedAndEncrypted (#69, #74)
- - Usually there is a small, known set of appropriate algorithms for a program
- to use and it's a mistake to allow unexpected algorithms. For instance the
- "billion hash attack" relies in part on programs accepting the PBES2
- encryption algorithm and doing the necessary work even if they weren't
- specifically configured to allow PBES2.
- - Revert "Strip padding off base64 strings" (#82)
- - The specs require base64url encoding without padding.
- - Minimum supported Go version is now 1.21
-
-## Added
-
- - ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON.
- - These allow parsing a specific serialization, as opposed to ParseSigned and
- ParseEncrypted, which try to automatically detect which serialization was
- provided. It's common to require a specific serialization for a specific
- protocol - for instance JWT requires Compact serialization.
-
-[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
-
-# v3.0.2
-
-## Fixed
-
- - DecryptMulti: handle decompression error (#19)
-
-## Changed
-
- - jwe/CompactSerialize: improve performance (#67)
- - Increase the default number of PBKDF2 iterations to 600k (#48)
- - Return the proper algorithm for ECDSA keys (#45)
-
-## Added
-
- - Add Thumbprint support for opaque signers (#38)
-
-# v3.0.1
-
-## Fixed
-
- - Security issue: an attacker specifying a large "p2c" value can cause
- JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
- amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the
- disclosure and to Tom Tervoort for originally publishing the category of attack.
- https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
diff --git a/vendor/github.com/go-jose/go-jose/v4/README.md b/vendor/github.com/go-jose/go-jose/v4/README.md
index 02b5749546b2..55c5509176b3 100644
--- a/vendor/github.com/go-jose/go-jose/v4/README.md
+++ b/vendor/github.com/go-jose/go-jose/v4/README.md
@@ -3,7 +3,6 @@
[](https://pkg.go.dev/github.com/go-jose/go-jose/v4)
[](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt)
[](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE)
-[](https://github.com/go-jose/go-jose/actions)
Package jose aims to provide an implementation of the Javascript Object Signing
and Encryption set of standards. This includes support for JSON Web Encryption,
@@ -29,17 +28,20 @@ libraries in other languages.
### Versions
-[Version 4](https://github.com/go-jose/go-jose)
-([branch](https://github.com/go-jose/go-jose/tree/main),
-[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
+The forthcoming Version 5 will be released with several breaking API changes,
+and will require Golang's `encoding/json/v2`, which is currently requires
+Go 1.25 built with GOEXPERIMENT=jsonv2.
+
+Version 4 is the current stable version:
import "github.com/go-jose/go-jose/v4"
-The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
-are still useable but not actively developed anymore.
+It supports at least the current and previous Golang release. Currently it
+requires Golang 1.24.
+
+Version 3 is only receiving critical security updates. Migration to Version 4 is recommended.
-Version 3, in this repo, is still receiving security fixes but not functionality
-updates.
+Versions 1 and 2 are obsolete, but can be found in the old repository, [square/go-jose](https://github.com/square/go-jose).
### Supported algorithms
@@ -47,36 +49,36 @@ See below for a table of supported algorithms. Algorithm identifiers match
the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518)
standard where possible. The Godoc reference has a list of constants.
- Key encryption | Algorithm identifier(s)
- :------------------------- | :------------------------------
- RSA-PKCS#1v1.5 | RSA1_5
- RSA-OAEP | RSA-OAEP, RSA-OAEP-256
- AES key wrap | A128KW, A192KW, A256KW
- AES-GCM key wrap | A128GCMKW, A192GCMKW, A256GCMKW
- ECDH-ES + AES key wrap | ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW
- ECDH-ES (direct) | ECDH-ES1
- Direct encryption | dir1
+| Key encryption | Algorithm identifier(s) |
+|:-----------------------|:-----------------------------------------------|
+| RSA-PKCS#1v1.5 | RSA1_5 |
+| RSA-OAEP | RSA-OAEP, RSA-OAEP-256 |
+| AES key wrap | A128KW, A192KW, A256KW |
+| AES-GCM key wrap | A128GCMKW, A192GCMKW, A256GCMKW |
+| ECDH-ES + AES key wrap | ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW |
+| ECDH-ES (direct) | ECDH-ES1 |
+| Direct encryption | dir1 |
1. Not supported in multi-recipient mode
- Signing / MAC | Algorithm identifier(s)
- :------------------------- | :------------------------------
- RSASSA-PKCS#1v1.5 | RS256, RS384, RS512
- RSASSA-PSS | PS256, PS384, PS512
- HMAC | HS256, HS384, HS512
- ECDSA | ES256, ES384, ES512
- Ed25519 | EdDSA2
+| Signing / MAC | Algorithm identifier(s) |
+|:------------------|:------------------------|
+| RSASSA-PKCS#1v1.5 | RS256, RS384, RS512 |
+| RSASSA-PSS | PS256, PS384, PS512 |
+| HMAC | HS256, HS384, HS512 |
+| ECDSA | ES256, ES384, ES512 |
+| Ed25519 | EdDSA2 |
2. Only available in version 2 of the package
- Content encryption | Algorithm identifier(s)
- :------------------------- | :------------------------------
- AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512
- AES-GCM | A128GCM, A192GCM, A256GCM
+| Content encryption | Algorithm identifier(s) |
+|:-------------------|:--------------------------------------------|
+| AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 |
+| AES-GCM | A128GCM, A192GCM, A256GCM |
- Compression | Algorithm identifiers(s)
- :------------------------- | -------------------------------
- DEFLATE (RFC 1951) | DEF
+| Compression | Algorithm identifiers(s) |
+|:-------------------|--------------------------|
+| DEFLATE (RFC 1951) | DEF |
### Supported key types
@@ -85,12 +87,12 @@ library, and can be passed to corresponding functions such as `NewEncrypter` or
`NewSigner`. Each of these keys can also be wrapped in a JWK if desired, which
allows attaching a key id.
- Algorithm(s) | Corresponding types
- :------------------------- | -------------------------------
- RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey)
- ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey)
- EdDSA1 | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey)
- AES, HMAC | []byte
+| Algorithm(s) | Corresponding types |
+|:------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey) |
+| ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey) |
+| EdDSA1 | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey) |
+| AES, HMAC | []byte |
1. Only available in version 2 or later of the package
diff --git a/vendor/github.com/go-jose/go-jose/v4/crypter.go b/vendor/github.com/go-jose/go-jose/v4/crypter.go
index d81b03b44740..31290fc87157 100644
--- a/vendor/github.com/go-jose/go-jose/v4/crypter.go
+++ b/vendor/github.com/go-jose/go-jose/v4/crypter.go
@@ -286,6 +286,10 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey
return newSymmetricRecipient(alg, encryptionKey)
case string:
return newSymmetricRecipient(alg, []byte(encryptionKey))
+ case JSONWebKey:
+ recipient, err := makeJWERecipient(alg, encryptionKey.Key)
+ recipient.keyID = encryptionKey.KeyID
+ return recipient, err
case *JSONWebKey:
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
recipient.keyID = encryptionKey.KeyID
@@ -450,13 +454,9 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one")
}
- critical, err := headers.getCritical()
+ err := headers.checkNoCritical()
if err != nil {
- return nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
- }
-
- if len(critical) > 0 {
- return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
+ return nil, err
}
key, err := tryJWKS(decryptionKey, obj.Header)
@@ -523,13 +523,9 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
globalHeaders := obj.mergedHeaders(nil)
- critical, err := globalHeaders.getCritical()
+ err := globalHeaders.checkNoCritical()
if err != nil {
- return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
- }
-
- if len(critical) > 0 {
- return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
+ return -1, Header{}, nil, err
}
key, err := tryJWKS(decryptionKey, obj.Header)
diff --git a/vendor/github.com/go-jose/go-jose/v4/jwe.go b/vendor/github.com/go-jose/go-jose/v4/jwe.go
index 9f1322dccc9c..6102f9100053 100644
--- a/vendor/github.com/go-jose/go-jose/v4/jwe.go
+++ b/vendor/github.com/go-jose/go-jose/v4/jwe.go
@@ -274,7 +274,7 @@ func validateAlgEnc(headers rawHeader, keyAlgorithms []KeyAlgorithm, contentEncr
if alg != "" && !containsKeyAlgorithm(keyAlgorithms, alg) {
return fmt.Errorf("unexpected key algorithm %q; expected %q", alg, keyAlgorithms)
}
- if alg != "" && !containsContentEncryption(contentEncryption, enc) {
+ if enc != "" && !containsContentEncryption(contentEncryption, enc) {
return fmt.Errorf("unexpected content encryption algorithm %q; expected %q", enc, contentEncryption)
}
return nil
@@ -288,11 +288,20 @@ func ParseEncryptedCompact(
keyAlgorithms []KeyAlgorithm,
contentEncryption []ContentEncryption,
) (*JSONWebEncryption, error) {
- // Five parts is four separators
- if strings.Count(input, ".") != 4 {
- return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
+ var parts [5]string
+ var ok bool
+
+ for i := range 4 {
+ parts[i], input, ok = strings.Cut(input, ".")
+ if !ok {
+ return nil, errors.New("go-jose/go-jose: compact JWE format must have five parts")
+ }
+ }
+ // Validate that the last part does not contain more dots
+ if strings.ContainsRune(input, '.') {
+ return nil, errors.New("go-jose/go-jose: compact JWE format must have five parts")
}
- parts := strings.SplitN(input, ".", 5)
+ parts[4] = input
rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil {
diff --git a/vendor/github.com/go-jose/go-jose/v4/jwk.go b/vendor/github.com/go-jose/go-jose/v4/jwk.go
index 9e57e93ba2e5..164d6a161972 100644
--- a/vendor/github.com/go-jose/go-jose/v4/jwk.go
+++ b/vendor/github.com/go-jose/go-jose/v4/jwk.go
@@ -175,6 +175,8 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
}
// UnmarshalJSON reads a key from its JSON representation.
+//
+// Returns ErrUnsupportedKeyType for unrecognized or unsupported "kty" header values.
func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
var raw rawJSONWebKey
err = json.Unmarshal(data, &raw)
@@ -228,7 +230,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
}
key, err = raw.symmetricKey()
case "OKP":
- if raw.Crv == "Ed25519" && raw.X != nil {
+ if raw.Crv == "Ed25519" {
if raw.D != nil {
key, err = raw.edPrivateKey()
if err == nil {
@@ -238,17 +240,27 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
key, err = raw.edPublicKey()
keyPub = key
}
- } else {
- return fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv)
}
- default:
- return fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty)
+ case "":
+ // kty MUST be present
+ err = fmt.Errorf("go-jose/go-jose: missing json web key type")
}
if err != nil {
return
}
+ if key == nil {
+ // RFC 7517:
+ // 5. JWK Set Format
+ // ...
+ // Implementations SHOULD ignore JWKs within a JWK Set that use "kty"
+ // (key type) values that are not understood by them, that are missing
+ // required members, or for which values are out of the supported
+ // ranges.
+ return ErrUnsupportedKeyType
+ }
+
if certPub != nil && keyPub != nil {
if !reflect.DeepEqual(certPub, keyPub) {
return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields do not match")
@@ -581,10 +593,10 @@ func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
var missing []string
- switch {
- case key.D == nil:
+ if key.D == nil {
missing = append(missing, "D")
- case key.X == nil:
+ }
+ if key.X == nil {
missing = append(missing, "X")
}
@@ -611,19 +623,21 @@ func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) {
func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
var missing []string
- switch {
- case key.N == nil:
+ if key.N == nil {
missing = append(missing, "N")
- case key.E == nil:
+ }
+ if key.E == nil {
missing = append(missing, "E")
- case key.D == nil:
+ }
+ if key.D == nil {
missing = append(missing, "D")
- case key.P == nil:
+ }
+ if key.P == nil {
missing = append(missing, "P")
- case key.Q == nil:
+ }
+ if key.Q == nil {
missing = append(missing, "Q")
}
-
if len(missing) > 0 {
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
}
@@ -698,8 +712,19 @@ func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) {
return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
}
- if key.X == nil || key.Y == nil || key.D == nil {
- return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, missing x/y/d values")
+ var missing []string
+ if key.X == nil {
+ missing = append(missing, "X")
+ }
+ if key.Y == nil {
+ missing = append(missing, "Y")
+ }
+ if key.D == nil {
+ missing = append(missing, "D")
+ }
+
+ if len(missing) > 0 {
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, missing %s value(s)", strings.Join(missing, ", "))
}
// The length of this octet string MUST be the full size of a coordinate for
diff --git a/vendor/github.com/go-jose/go-jose/v4/jws.go b/vendor/github.com/go-jose/go-jose/v4/jws.go
index d09d8ba5078c..c40bd3ec10a6 100644
--- a/vendor/github.com/go-jose/go-jose/v4/jws.go
+++ b/vendor/github.com/go-jose/go-jose/v4/jws.go
@@ -75,7 +75,14 @@ type Signature struct {
original *rawSignatureInfo
}
-// ParseSigned parses a signed message in JWS Compact or JWS JSON Serialization.
+// ParseSigned parses a signed message in JWS Compact or JWS JSON Serialization. Validation fails if
+// the JWS is signed with an algorithm that isn't in the provided list of signature algorithms.
+// Applications should decide for themselves which signature algorithms are acceptable. If you're
+// not sure which signature algorithms your application might receive, consult the documentation of
+// the program which provides them or the protocol that you are implementing. You can also try
+// getting an example JWS and decoding it with a tool like https://jwt.io to see what its "alg"
+// header parameter indicates. The signature on the JWS does not get validated during parsing. Call
+// Verify() after parsing to validate the signature and obtain the payload.
//
// https://datatracker.ietf.org/doc/html/rfc7515#section-7
func ParseSigned(
@@ -90,7 +97,14 @@ func ParseSigned(
return parseSignedCompact(signature, nil, signatureAlgorithms)
}
-// ParseSignedCompact parses a message in JWS Compact Serialization.
+// ParseSignedCompact parses a message in JWS Compact Serialization. Validation fails if the JWS is
+// signed with an algorithm that isn't in the provided list of signature algorithms. Applications
+// should decide for themselves which signature algorithms are acceptable.If you're not sure which
+// signature algorithms your application might receive, consult the documentation of the program
+// which provides them or the protocol that you are implementing. You can also try getting an
+// example JWS and decoding it with a tool like https://jwt.io to see what its "alg" header
+// parameter indicates. The signature on the JWS does not get validated during parsing. Call
+// Verify() after parsing to validate the signature and obtain the payload.
//
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.1
func ParseSignedCompact(
@@ -101,6 +115,15 @@ func ParseSignedCompact(
}
// ParseDetached parses a signed message in compact serialization format with detached payload.
+// Validation fails if the JWS is signed with an algorithm that isn't in the provided list of
+// signature algorithms. Applications should decide for themselves which signature algorithms are
+// acceptable. If you're not sure which signature algorithms your application might receive, consult
+// the documentation of the program which provides them or the protocol that you are implementing.
+// You can also try getting an example JWS and decoding it with a tool like https://jwt.io to see
+// what its "alg" header parameter indicates. The signature on the JWS does not get validated during
+// parsing. Call Verify() after parsing to validate the signature and obtain the payload.
+//
+// https://datatracker.ietf.org/doc/html/rfc7515#appendix-F
func ParseDetached(
signature string,
payload []byte,
@@ -181,6 +204,25 @@ func containsSignatureAlgorithm(haystack []SignatureAlgorithm, needle SignatureA
return false
}
+// ErrUnexpectedSignatureAlgorithm is returned when the signature algorithm in
+// the JWS header does not match one of the expected algorithms.
+type ErrUnexpectedSignatureAlgorithm struct {
+ // Got is the signature algorithm found in the JWS header.
+ Got SignatureAlgorithm
+ expected []SignatureAlgorithm
+}
+
+func (e *ErrUnexpectedSignatureAlgorithm) Error() string {
+ return fmt.Sprintf("unexpected signature algorithm %q; expected %q", e.Got, e.expected)
+}
+
+func newErrUnexpectedSignatureAlgorithm(got SignatureAlgorithm, expected []SignatureAlgorithm) error {
+ return &ErrUnexpectedSignatureAlgorithm{
+ Got: got,
+ expected: expected,
+ }
+}
+
// sanitized produces a cleaned-up JWS object from the raw JSON.
func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgorithm) (*JSONWebSignature, error) {
if len(signatureAlgorithms) == 0 {
@@ -236,8 +278,7 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
alg := SignatureAlgorithm(signature.Header.Algorithm)
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
- return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
- alg, signatureAlgorithms)
+ return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms)
}
if signature.header != nil {
@@ -285,8 +326,7 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
alg := SignatureAlgorithm(obj.Signatures[i].Header.Algorithm)
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
- return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
- alg, signatureAlgorithms)
+ return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms)
}
if obj.Signatures[i].header != nil {
@@ -321,35 +361,43 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
return obj, nil
}
+const tokenDelim = "."
+
// parseSignedCompact parses a message in compact format.
func parseSignedCompact(
input string,
payload []byte,
signatureAlgorithms []SignatureAlgorithm,
) (*JSONWebSignature, error) {
- // Three parts is two separators
- if strings.Count(input, ".") != 2 {
+ protected, s, ok := strings.Cut(input, tokenDelim)
+ if !ok { // no period found
+ return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
+ }
+ claims, sig, ok := strings.Cut(s, tokenDelim)
+ if !ok { // only one period found
+ return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
+ }
+ if strings.ContainsRune(sig, '.') { // too many periods found
return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
}
- parts := strings.SplitN(input, ".", 3)
- if parts[1] != "" && payload != nil {
+ if claims != "" && payload != nil {
return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
}
- rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
+ rawProtected, err := base64.RawURLEncoding.DecodeString(protected)
if err != nil {
return nil, err
}
if payload == nil {
- payload, err = base64.RawURLEncoding.DecodeString(parts[1])
+ payload, err = base64.RawURLEncoding.DecodeString(claims)
if err != nil {
return nil, err
}
}
- signature, err := base64.RawURLEncoding.DecodeString(parts[2])
+ signature, err := base64.RawURLEncoding.DecodeString(sig)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/go-jose/go-jose/v4/shared.go b/vendor/github.com/go-jose/go-jose/v4/shared.go
index 1ec33961265b..35130b3aa876 100644
--- a/vendor/github.com/go-jose/go-jose/v4/shared.go
+++ b/vendor/github.com/go-jose/go-jose/v4/shared.go
@@ -77,6 +77,9 @@ var (
// ErrUnsupportedEllipticCurve indicates unsupported or unknown elliptic curve has been found.
ErrUnsupportedEllipticCurve = errors.New("go-jose/go-jose: unsupported/unknown elliptic curve")
+
+ // ErrUnsupportedCriticalHeader is returned when a header is marked critical but not supported by go-jose.
+ ErrUnsupportedCriticalHeader = errors.New("go-jose/go-jose: unsupported critical header")
)
// Key management algorithms
@@ -167,8 +170,8 @@ const (
)
// supportedCritical is the set of supported extensions that are understood and processed.
-var supportedCritical = map[string]bool{
- headerB64: true,
+var supportedCritical = map[string]struct{}{
+ headerB64: {},
}
// rawHeader represents the JOSE header for JWE/JWS objects (used for parsing).
@@ -346,6 +349,32 @@ func (parsed rawHeader) getCritical() ([]string, error) {
return q, nil
}
+// checkNoCritical verifies there are no critical headers present.
+func (parsed rawHeader) checkNoCritical() error {
+ if _, ok := parsed[headerCritical]; ok {
+ return ErrUnsupportedCriticalHeader
+ }
+
+ return nil
+}
+
+// checkSupportedCritical verifies there are no unsupported critical headers.
+// Supported headers are passed in as a set: map of names to empty structs
+func (parsed rawHeader) checkSupportedCritical(supported map[string]struct{}) error {
+ crit, err := parsed.getCritical()
+ if err != nil {
+ return err
+ }
+
+ for _, name := range crit {
+ if _, ok := supported[name]; !ok {
+ return ErrUnsupportedCriticalHeader
+ }
+ }
+
+ return nil
+}
+
// getS2C extracts parsed "p2c" from the raw JSON.
func (parsed rawHeader) getP2C() (int, error) {
v := parsed[headerP2C]
diff --git a/vendor/github.com/go-jose/go-jose/v4/signing.go b/vendor/github.com/go-jose/go-jose/v4/signing.go
index 3dec0112b6f9..5dbd04c2788a 100644
--- a/vendor/github.com/go-jose/go-jose/v4/signing.go
+++ b/vendor/github.com/go-jose/go-jose/v4/signing.go
@@ -404,15 +404,23 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
}
signature := obj.Signatures[0]
- headers := signature.mergedHeaders()
- critical, err := headers.getCritical()
- if err != nil {
- return err
+
+ if signature.header != nil {
+ // Per https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.11,
+ // 4.1.11. "crit" (Critical) Header Parameter
+ // "When used, this Header Parameter MUST be integrity
+ // protected; therefore, it MUST occur only within the JWS
+ // Protected Header."
+ err = signature.header.checkNoCritical()
+ if err != nil {
+ return err
+ }
}
- for _, name := range critical {
- if !supportedCritical[name] {
- return ErrCryptoFailure
+ if signature.protected != nil {
+ err = signature.protected.checkSupportedCritical(supportedCritical)
+ if err != nil {
+ return err
}
}
@@ -421,6 +429,7 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
return ErrCryptoFailure
}
+ headers := signature.mergedHeaders()
alg := headers.getSignatureAlgorithm()
err = verifier.verifyPayload(input, signature.Signature, alg)
if err == nil {
@@ -469,14 +478,22 @@ func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey
outer:
for i, signature := range obj.Signatures {
- headers := signature.mergedHeaders()
- critical, err := headers.getCritical()
- if err != nil {
- continue
+ if signature.header != nil {
+ // Per https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.11,
+ // 4.1.11. "crit" (Critical) Header Parameter
+ // "When used, this Header Parameter MUST be integrity
+ // protected; therefore, it MUST occur only within the JWS
+ // Protected Header."
+ err = signature.header.checkNoCritical()
+ if err != nil {
+ continue outer
+ }
}
- for _, name := range critical {
- if !supportedCritical[name] {
+ if signature.protected != nil {
+ // Check for only supported critical headers
+ err = signature.protected.checkSupportedCritical(supportedCritical)
+ if err != nil {
continue outer
}
}
@@ -486,6 +503,7 @@ outer:
continue
}
+ headers := signature.mergedHeaders()
alg := headers.getSignatureAlgorithm()
err = verifier.verifyPayload(input, signature.Signature, alg)
if err == nil {
diff --git a/vendor/github.com/go-jose/go-jose/v4/symmetric.go b/vendor/github.com/go-jose/go-jose/v4/symmetric.go
index a69103b084e7..09efefb265c0 100644
--- a/vendor/github.com/go-jose/go-jose/v4/symmetric.go
+++ b/vendor/github.com/go-jose/go-jose/v4/symmetric.go
@@ -21,6 +21,7 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
+ "crypto/pbkdf2"
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
@@ -30,8 +31,6 @@ import (
"hash"
"io"
- "golang.org/x/crypto/pbkdf2"
-
josecipher "github.com/go-jose/go-jose/v4/cipher"
)
@@ -330,7 +329,10 @@ func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipie
// derive key
keyLen, h := getPbkdf2Params(alg)
- key := pbkdf2.Key(ctx.key, salt, ctx.p2c, keyLen, h)
+ key, err := pbkdf2.Key(h, string(ctx.key), salt, ctx.p2c, keyLen)
+ if err != nil {
+ return recipientInfo{}, nil
+ }
// use AES cipher with derived key
block, err := aes.NewCipher(key)
@@ -432,7 +434,10 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
// derive key
keyLen, h := getPbkdf2Params(alg)
- key := pbkdf2.Key(ctx.key, salt, p2c, keyLen, h)
+ key, err := pbkdf2.Key(h, string(ctx.key), salt, p2c, keyLen)
+ if err != nil {
+ return nil, err
+ }
// use AES cipher with derived key
block, err := aes.NewCipher(key)
diff --git a/vendor/github.com/go-openapi/analysis/.editorconfig b/vendor/github.com/go-openapi/analysis/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/analysis/.gitignore b/vendor/github.com/go-openapi/analysis/.gitignore
index 87c3bd3e66e0..885dc27ab0bc 100644
--- a/vendor/github.com/go-openapi/analysis/.gitignore
+++ b/vendor/github.com/go-openapi/analysis/.gitignore
@@ -1,5 +1,6 @@
-secrets.yml
-coverage.out
-coverage.txt
+*.out
*.cov
.idea
+.env
+.mcp.json
+.claude/
diff --git a/vendor/github.com/go-openapi/analysis/.golangci.yml b/vendor/github.com/go-openapi/analysis/.golangci.yml
index 22f8d21cca19..02edc1b9fa96 100644
--- a/vendor/github.com/go-openapi/analysis/.golangci.yml
+++ b/vendor/github.com/go-openapi/analysis/.golangci.yml
@@ -1,61 +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: 3
-
+version: "2"
linters:
- enable-all: true
+ default: all
disable:
- - maligned
- - unparam
- - lll
- - gochecknoinits
- - gochecknoglobals
+ - depguard
- funlen
- godox
- - gocognit
- - whitespace
- - wsl
- - wrapcheck
- - testpackage
+ - gomoddirectives
+ - exhaustruct
- nlreturn
- - gomnd
- - exhaustivestruct
- - goerr113
- - errorlint
- - nestif
- - godot
- - gofumpt
+ - nonamedreturns
+ - noinlineerr
- paralleltest
- - tparallel
+ - recvcheck
+ - testpackage
- thelper
- - ifshort
- - exhaustruct
+ - tparallel
- varnamelen
- - gci
- - depguard
- - errchkjson
- - inamedparam
- - nonamedreturns
- - musttag
- - ireturn
- - forcetypeassert
- - cyclop
- # deprecated linters
- - deadcode
- - interfacer
- - scopelint
- - varcheck
- - structcheck
- - golint
- - nosnakecase
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ cyclop:
+ max-complexity: 25
+ gocyclo:
+ min-complexity: 25
+ gocognit:
+ min-complexity: 35
+ 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/analysis/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 100644
--- a/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md
+++ b/vendor/github.com/go-openapi/analysis/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/analysis/CONTRIBUTORS.md b/vendor/github.com/go-openapi/analysis/CONTRIBUTORS.md
new file mode 100644
index 000000000000..cf8fcaa7dc17
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/CONTRIBUTORS.md
@@ -0,0 +1,27 @@
+# Contributors
+
+- Repository: ['go-openapi/analysis']
+
+| Total Contributors | Total Contributions |
+| --- | --- |
+| 15 | 202 |
+
+| Username | All Time Contribution Count | All Commits |
+| --- | --- | --- |
+| @fredbi | 99 | |
+| @casualjim | 70 | |
+| @keramix | 9 | |
+| @youyuanwu | 8 | |
+| @msample | 3 | |
+| @kul-amr | 3 | |
+| @mbohlool | 2 | |
+| @Copilot | 1 | |
+| @danielfbm | 1 | |
+| @gregmarr | 1 | |
+| @guillemj | 1 | |
+| @knweiss | 1 | |
+| @tklauser | 1 | |
+| @cuishuang | 1 | |
+| @ujjwalsh | 1 | |
+
+ _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_
diff --git a/vendor/github.com/go-openapi/analysis/README.md b/vendor/github.com/go-openapi/analysis/README.md
index e005d4b37b7f..96821d3e437e 100644
--- a/vendor/github.com/go-openapi/analysis/README.md
+++ b/vendor/github.com/go-openapi/analysis/README.md
@@ -1,22 +1,46 @@
-# OpenAPI analysis [](https://github.com/go-openapi/analysis/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/analysis)
+# analysis
-[](https://slackin.goswagger.io)
-[](https://raw.githubusercontent.com/go-openapi/analysis/master/LICENSE)
-[](https://pkg.go.dev/github.com/go-openapi/analysis)
-[](https://goreportcard.com/report/github.com/go-openapi/analysis)
+
+[![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]
+---
A foundational library to analyze an OAI specification document for easier reasoning about the content.
-## What's inside?
+## 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.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/analysis
+```
+
+## What's inside
* 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 merger ("mixin") to merge several spec documents into a primary spec
* A spec "fixer" ensuring that response descriptions are non empty
-[Documentation](https://pkg.go.dev/github.com/go-openapi/analysis)
-
## FAQ
* Does this library support OpenAPI 3?
@@ -25,3 +49,79 @@ A foundational library to analyze an OAI specification document for easier reaso
> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
> 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.
+
+## Change log
+
+See
+
+
+
+## Licensing
+
+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)
+
+## Cutting a new release
+
+Maintainers can cut a new release by either:
+
+* running [this workflow](https://github.com/go-openapi/analysis/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/analysis/actions/workflows/go-test.yml/badge.svg
+[test-url]: https://github.com/go-openapi/analysis/actions/workflows/go-test.yml
+[cov-badge]: https://codecov.io/gh/go-openapi/analysis/branch/master/graph/badge.svg
+[cov-url]: https://codecov.io/gh/go-openapi/analysis
+[vuln-scan-badge]: https://github.com/go-openapi/analysis/actions/workflows/scanner.yml/badge.svg
+[vuln-scan-url]: https://github.com/go-openapi/analysis/actions/workflows/scanner.yml
+[codeql-badge]: https://github.com/go-openapi/analysis/actions/workflows/codeql.yml/badge.svg
+[codeql-url]: https://github.com/go-openapi/analysis/actions/workflows/codeql.yml
+
+[release-badge]: https://badge.fury.io/gh/go-openapi%2Fanalysis.svg
+[release-url]: https://badge.fury.io/gh/go-openapi%2Fanalysis
+
+[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/analysis
+[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/analysis
+[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/analysis
+[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/analysis
+
+[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/twZ9BwT3
+
+
+[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
+[license-url]: https://github.com/go-openapi/analysis/?tab=Apache-2.0-1-ov-file#readme
+
+[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/analysis
+[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
diff --git a/vendor/github.com/go-openapi/analysis/SECURITY.md b/vendor/github.com/go-openapi/analysis/SECURITY.md
new file mode 100644
index 000000000000..6ceb159ca229
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/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 |
+| ------- | ------------------ |
+| 0.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/analysis/analyzer.go b/vendor/github.com/go-openapi/analysis/analyzer.go
index c17aee1b6173..1c91b8c55077 100644
--- a/vendor/github.com/go-openapi/analysis/analyzer.go
+++ b/vendor/github.com/go-openapi/analysis/analyzer.go
@@ -1,28 +1,24 @@
-// 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 analysis
import (
"fmt"
+ "maps"
slashpath "path"
"strconv"
"strings"
"github.com/go-openapi/jsonpointer"
"github.com/go-openapi/spec"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/mangling"
+)
+
+const (
+ allocLargeMap = 150
+ allocMediumMap = 64
+ allocSmallMap = 10
)
type referenceAnalysis struct {
@@ -105,54 +101,37 @@ func (p *patternAnalysis) addSchemaPattern(key, pattern string) {
}
type enumAnalysis struct {
- parameters map[string][]interface{}
- headers map[string][]interface{}
- items map[string][]interface{}
- schemas map[string][]interface{}
- allEnums map[string][]interface{}
+ parameters map[string][]any
+ headers map[string][]any
+ items map[string][]any
+ schemas map[string][]any
+ allEnums map[string][]any
}
-func (p *enumAnalysis) addEnum(key string, enum []interface{}) {
+func (p *enumAnalysis) addEnum(key string, enum []any) {
p.allEnums["#"+key] = enum
}
-func (p *enumAnalysis) addParameterEnum(key string, enum []interface{}) {
+func (p *enumAnalysis) addParameterEnum(key string, enum []any) {
p.parameters["#"+key] = enum
p.addEnum(key, enum)
}
-func (p *enumAnalysis) addHeaderEnum(key string, enum []interface{}) {
+func (p *enumAnalysis) addHeaderEnum(key string, enum []any) {
p.headers["#"+key] = enum
p.addEnum(key, enum)
}
-func (p *enumAnalysis) addItemsEnum(key string, enum []interface{}) {
+func (p *enumAnalysis) addItemsEnum(key string, enum []any) {
p.items["#"+key] = enum
p.addEnum(key, enum)
}
-func (p *enumAnalysis) addSchemaEnum(key string, enum []interface{}) {
+func (p *enumAnalysis) addSchemaEnum(key string, enum []any) {
p.schemas["#"+key] = enum
p.addEnum(key, enum)
}
-// 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 {
- a := &Spec{
- spec: doc,
- references: referenceAnalysis{},
- patterns: patternAnalysis{},
- enums: enumAnalysis{},
- }
- a.reset()
- a.initialize()
-
- return a
-}
-
// Spec is an analyzed specification object. It takes a swagger spec object and turns it into a registry
// with a bunch of utility methods to act on the information in the spec.
type Spec struct {
@@ -168,494 +147,522 @@ type Spec struct {
allOfs map[string]SchemaRef
}
-func (s *Spec) reset() {
- s.consumes = make(map[string]struct{}, 150)
- s.produces = make(map[string]struct{}, 150)
- s.authSchemes = make(map[string]struct{}, 150)
- s.operations = make(map[string]map[string]*spec.Operation, 150)
- s.allSchemas = make(map[string]SchemaRef, 150)
- s.allOfs = make(map[string]SchemaRef, 150)
- s.references.schemas = make(map[string]spec.Ref, 150)
- s.references.pathItems = make(map[string]spec.Ref, 150)
- s.references.responses = make(map[string]spec.Ref, 150)
- s.references.parameters = make(map[string]spec.Ref, 150)
- s.references.items = make(map[string]spec.Ref, 150)
- s.references.headerItems = make(map[string]spec.Ref, 150)
- s.references.parameterItems = make(map[string]spec.Ref, 150)
- s.references.allRefs = make(map[string]spec.Ref, 150)
- s.patterns.parameters = make(map[string]string, 150)
- s.patterns.headers = make(map[string]string, 150)
- s.patterns.items = make(map[string]string, 150)
- s.patterns.schemas = make(map[string]string, 150)
- s.patterns.allPatterns = make(map[string]string, 150)
- s.enums.parameters = make(map[string][]interface{}, 150)
- s.enums.headers = make(map[string][]interface{}, 150)
- s.enums.items = make(map[string][]interface{}, 150)
- s.enums.schemas = make(map[string][]interface{}, 150)
- s.enums.allEnums = make(map[string][]interface{}, 150)
+// 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 {
+ a := &Spec{
+ spec: doc,
+ references: referenceAnalysis{},
+ patterns: patternAnalysis{},
+ enums: enumAnalysis{},
+ }
+ a.reset()
+ a.initialize()
+
+ return a
}
-func (s *Spec) reload() {
- s.reset()
- s.initialize()
+// SecurityRequirement is a representation of a security requirement for an operation.
+type SecurityRequirement struct {
+ Name string
+ Scopes []string
}
-func (s *Spec) initialize() {
- for _, c := range s.spec.Consumes {
- s.consumes[c] = struct{}{}
- }
- for _, c := range s.spec.Produces {
- s.produces[c] = struct{}{}
- }
- for _, ss := range s.spec.Security {
- for k := range ss {
- s.authSchemes[k] = struct{}{}
- }
+// SecurityRequirementsFor gets the security requirements for the operation.
+func (s *Spec) SecurityRequirementsFor(operation *spec.Operation) [][]SecurityRequirement {
+ if s.spec.Security == nil && operation.Security == nil {
+ return nil
}
- for path, pathItem := range s.AllPaths() {
- s.analyzeOperations(path, &pathItem) //#nosec
+
+ schemes := s.spec.Security
+ if operation.Security != nil {
+ schemes = operation.Security
}
- for name, parameter := range s.spec.Parameters {
- refPref := slashpath.Join("/parameters", jsonpointer.Escape(name))
- if parameter.Items != nil {
- s.analyzeItems("items", parameter.Items, refPref, "parameter")
- }
- if parameter.In == "body" && parameter.Schema != nil {
- s.analyzeSchema("schema", parameter.Schema, refPref)
- }
- if parameter.Pattern != "" {
- s.patterns.addParameterPattern(refPref, parameter.Pattern)
- }
- if len(parameter.Enum) > 0 {
- s.enums.addParameterEnum(refPref, parameter.Enum)
+ result := [][]SecurityRequirement{}
+ for _, scheme := range schemes {
+ if len(scheme) == 0 {
+ // append a zero object for anonymous
+ result = append(result, []SecurityRequirement{{}})
+
+ continue
}
- }
- for name, response := range s.spec.Responses {
- refPref := slashpath.Join("/responses", jsonpointer.Escape(name))
- for k, v := range response.Headers {
- hRefPref := slashpath.Join(refPref, "headers", k)
- if v.Items != nil {
- s.analyzeItems("items", v.Items, hRefPref, "header")
- }
- if v.Pattern != "" {
- s.patterns.addHeaderPattern(hRefPref, v.Pattern)
- }
- if len(v.Enum) > 0 {
- s.enums.addHeaderEnum(hRefPref, v.Enum)
+ var reqs []SecurityRequirement
+ for k, v := range scheme {
+ if v == nil {
+ v = []string{}
}
+ reqs = append(reqs, SecurityRequirement{Name: k, Scopes: v})
}
- if response.Schema != nil {
- s.analyzeSchema("schema", response.Schema, refPref)
- }
- }
- for name := range s.spec.Definitions {
- schema := s.spec.Definitions[name]
- s.analyzeSchema(name, &schema, "/definitions")
+ result = append(result, reqs)
}
- // TODO: after analyzing all things and flattening schemas etc
- // resolve all the collected references to their final representations
- // best put in a separate method because this could get expensive
+
+ return result
}
-func (s *Spec) analyzeOperations(path string, pi *spec.PathItem) {
- // TODO: resolve refs here?
- // Currently, operations declared via pathItem $ref are known only after expansion
- op := pi
- if pi.Ref.String() != "" {
- key := slashpath.Join("/paths", jsonpointer.Escape(path))
- s.references.addPathItemRef(key, pi)
- }
- s.analyzeOperation("GET", path, op.Get)
- s.analyzeOperation("PUT", path, op.Put)
- s.analyzeOperation("POST", path, op.Post)
- s.analyzeOperation("PATCH", path, op.Patch)
- s.analyzeOperation("DELETE", path, op.Delete)
- s.analyzeOperation("HEAD", path, op.Head)
- s.analyzeOperation("OPTIONS", path, op.Options)
- for i, param := range op.Parameters {
- refPref := slashpath.Join("/paths", jsonpointer.Escape(path), "parameters", strconv.Itoa(i))
- if param.Ref.String() != "" {
- s.references.addParamRef(refPref, ¶m) //#nosec
- }
- if param.Pattern != "" {
- s.patterns.addParameterPattern(refPref, param.Pattern)
- }
- if len(param.Enum) > 0 {
- s.enums.addParameterEnum(refPref, param.Enum)
- }
- if param.Items != nil {
- s.analyzeItems("items", param.Items, refPref, "parameter")
- }
- if param.Schema != nil {
- s.analyzeSchema("schema", param.Schema, refPref)
+// SecurityDefinitionsForRequirements gets the matching security definitions for a set of requirements.
+func (s *Spec) SecurityDefinitionsForRequirements(requirements []SecurityRequirement) map[string]spec.SecurityScheme {
+ result := make(map[string]spec.SecurityScheme)
+
+ for _, v := range requirements {
+ if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
+ if definition != nil {
+ result[v.Name] = *definition
+ }
}
}
-}
-func (s *Spec) analyzeItems(name string, items *spec.Items, prefix, location string) {
- if items == nil {
- return
- }
- refPref := slashpath.Join(prefix, name)
- s.analyzeItems(name, items.Items, refPref, location)
- if items.Ref.String() != "" {
- s.references.addItemsRef(refPref, items, location)
- }
- if items.Pattern != "" {
- s.patterns.addItemsPattern(refPref, items.Pattern)
- }
- if len(items.Enum) > 0 {
- s.enums.addItemsEnum(refPref, items.Enum)
- }
+ return result
}
-func (s *Spec) analyzeParameter(prefix string, i int, param spec.Parameter) {
- refPref := slashpath.Join(prefix, "parameters", strconv.Itoa(i))
- if param.Ref.String() != "" {
- s.references.addParamRef(refPref, ¶m) //#nosec
+// SecurityDefinitionsFor gets the matching security definitions for a set of requirements.
+func (s *Spec) SecurityDefinitionsFor(operation *spec.Operation) map[string]spec.SecurityScheme {
+ requirements := s.SecurityRequirementsFor(operation)
+ if len(requirements) == 0 {
+ return nil
}
- if param.Pattern != "" {
- s.patterns.addParameterPattern(refPref, param.Pattern)
- }
+ result := make(map[string]spec.SecurityScheme)
+ for _, reqs := range requirements {
+ for _, v := range reqs {
+ if v.Name == "" {
+ // optional requirement
+ continue
+ }
- if len(param.Enum) > 0 {
- s.enums.addParameterEnum(refPref, param.Enum)
- }
+ if _, ok := result[v.Name]; ok {
+ // duplicate requirement
+ continue
+ }
- s.analyzeItems("items", param.Items, refPref, "parameter")
- if param.In == "body" && param.Schema != nil {
- s.analyzeSchema("schema", param.Schema, refPref)
+ if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
+ if definition != nil {
+ result[v.Name] = *definition
+ }
+ }
+ }
}
+
+ return result
}
-func (s *Spec) analyzeOperation(method, path string, op *spec.Operation) {
- if op == nil {
- return
- }
+// ConsumesFor gets the mediatypes for the operation.
+func (s *Spec) ConsumesFor(operation *spec.Operation) []string {
+ if len(operation.Consumes) == 0 {
+ cons := make(map[string]struct{}, len(s.spec.Consumes))
+ for _, k := range s.spec.Consumes {
+ cons[k] = struct{}{}
+ }
- for _, c := range op.Consumes {
- s.consumes[c] = struct{}{}
+ return s.structMapKeys(cons)
}
- for _, c := range op.Produces {
- s.produces[c] = struct{}{}
+ cons := make(map[string]struct{}, len(operation.Consumes))
+ for _, c := range operation.Consumes {
+ cons[c] = struct{}{}
}
- for _, ss := range op.Security {
- for k := range ss {
- s.authSchemes[k] = struct{}{}
- }
- }
+ return s.structMapKeys(cons)
+}
- if _, ok := s.operations[method]; !ok {
- s.operations[method] = make(map[string]*spec.Operation)
- }
+// ProducesFor gets the mediatypes for the operation.
+func (s *Spec) ProducesFor(operation *spec.Operation) []string {
+ if len(operation.Produces) == 0 {
+ prod := make(map[string]struct{}, len(s.spec.Produces))
+ for _, k := range s.spec.Produces {
+ prod[k] = struct{}{}
+ }
- s.operations[method][path] = op
- prefix := slashpath.Join("/paths", jsonpointer.Escape(path), strings.ToLower(method))
- for i, param := range op.Parameters {
- s.analyzeParameter(prefix, i, param)
+ return s.structMapKeys(prod)
}
- if op.Responses == nil {
- return
+ prod := make(map[string]struct{}, len(operation.Produces))
+ for _, c := range operation.Produces {
+ prod[c] = struct{}{}
}
- if op.Responses.Default != nil {
- s.analyzeDefaultResponse(prefix, op.Responses.Default)
- }
+ return s.structMapKeys(prod)
+}
- for k, res := range op.Responses.StatusCodeResponses {
- s.analyzeResponse(prefix, k, res)
- }
+func mapKeyFromParam(param *spec.Parameter) string {
+ return fmt.Sprintf("%s#%s", param.In, fieldNameFromParam(param))
}
-func (s *Spec) analyzeDefaultResponse(prefix string, res *spec.Response) {
- refPref := slashpath.Join(prefix, "responses", "default")
- if res.Ref.String() != "" {
- s.references.addResponseRef(refPref, res)
+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()
- for k, v := range res.Headers {
- hRefPref := slashpath.Join(refPref, "headers", k)
- s.analyzeItems("items", v.Items, hRefPref, "header")
- if v.Pattern != "" {
- s.patterns.addHeaderPattern(hRefPref, v.Pattern)
+ return mangler.ToGoName(param.Name)
+}
+
+// ErrorOnParamFunc is a callback function to be invoked
+// whenever an error is encountered while resolving references
+// on parameters.
+//
+// This function takes as input the [spec.Parameter] which triggered the
+// error and the error itself.
+//
+// If the callback function returns false, the calling function should bail.
+//
+// If it returns true, the calling function should continue evaluating parameters.
+// A nil ErrorOnParamFunc must be evaluated as equivalent to panic().
+type ErrorOnParamFunc func(spec.Parameter, error) bool
+
+// ParametersFor the specified operation id.
+//
+// Assumes parameters properly resolve references if any and that
+// such references actually resolve to a parameter object.
+// Otherwise, panics.
+func (s *Spec) ParametersFor(operationID string) []spec.Parameter {
+ return s.SafeParametersFor(operationID, nil)
+}
+
+// SafeParametersFor the specified operation id.
+//
+// Does not assume parameters properly resolve references or that
+// such references actually resolve to a parameter object.
+//
+// Upon error, invoke a [ErrorOnParamFunc] callback with the erroneous
+// parameters. If the callback is set to nil, panics upon errors.
+func (s *Spec) SafeParametersFor(operationID string, callmeOnError ErrorOnParamFunc) []spec.Parameter {
+ gatherParams := func(pi *spec.PathItem, op *spec.Operation) []spec.Parameter {
+ bag := make(map[string]spec.Parameter)
+ s.paramsAsMap(pi.Parameters, bag, callmeOnError)
+ s.paramsAsMap(op.Parameters, bag, callmeOnError)
+
+ res := make([]spec.Parameter, 0, len(bag))
+ for _, v := range bag {
+ res = append(res, v)
}
+
+ return res
}
- if res.Schema != nil {
- s.analyzeSchema("schema", res.Schema, refPref)
+ for _, pi := range s.spec.Paths.Paths {
+ if pi.Get != nil && pi.Get.ID == operationID {
+ return gatherParams(&pi, pi.Get) //#nosec
+ }
+ if pi.Head != nil && pi.Head.ID == operationID {
+ return gatherParams(&pi, pi.Head) //#nosec
+ }
+ if pi.Options != nil && pi.Options.ID == operationID {
+ return gatherParams(&pi, pi.Options) //#nosec
+ }
+ if pi.Post != nil && pi.Post.ID == operationID {
+ return gatherParams(&pi, pi.Post) //#nosec
+ }
+ if pi.Patch != nil && pi.Patch.ID == operationID {
+ return gatherParams(&pi, pi.Patch) //#nosec
+ }
+ if pi.Put != nil && pi.Put.ID == operationID {
+ return gatherParams(&pi, pi.Put) //#nosec
+ }
+ if pi.Delete != nil && pi.Delete.ID == operationID {
+ return gatherParams(&pi, pi.Delete) //#nosec
+ }
}
+
+ return nil
}
-func (s *Spec) analyzeResponse(prefix string, k int, res spec.Response) {
- refPref := slashpath.Join(prefix, "responses", strconv.Itoa(k))
- if res.Ref.String() != "" {
- s.references.addResponseRef(refPref, &res) //#nosec
+// ParamsFor the specified method and path. Aggregates them with the defaults etc, so it's all the params that
+// apply for the method and path.
+//
+// Assumes parameters properly resolve references if any and that
+// such references actually resolve to a parameter object.
+// Otherwise, panics.
+func (s *Spec) ParamsFor(method, path string) map[string]spec.Parameter {
+ return s.SafeParamsFor(method, path, nil)
+}
+
+// SafeParamsFor the specified method and path. Aggregates them with the defaults etc, so it's all the params that
+// apply for the method and path.
+//
+// Does not assume parameters properly resolve references or that
+// such references actually resolve to a parameter object.
+//
+// Upon error, invoke a [ErrorOnParamFunc] callback with the erroneous
+// parameters. If the callback is set to nil, panics upon errors.
+func (s *Spec) SafeParamsFor(method, path string, callmeOnError ErrorOnParamFunc) map[string]spec.Parameter {
+ res := make(map[string]spec.Parameter)
+ if pi, ok := s.spec.Paths.Paths[path]; ok {
+ s.paramsAsMap(pi.Parameters, res, callmeOnError)
+ s.paramsAsMap(s.operations[strings.ToUpper(method)][path].Parameters, res, callmeOnError)
}
- for k, v := range res.Headers {
- hRefPref := slashpath.Join(refPref, "headers", k)
- s.analyzeItems("items", v.Items, hRefPref, "header")
- if v.Pattern != "" {
- s.patterns.addHeaderPattern(hRefPref, v.Pattern)
- }
+ return res
+}
- if len(v.Enum) > 0 {
- s.enums.addHeaderEnum(hRefPref, v.Enum)
+// OperationForName gets the operation for the given id.
+func (s *Spec) OperationForName(operationID string) (string, string, *spec.Operation, bool) {
+ for method, pathItem := range s.operations {
+ for path, op := range pathItem {
+ if operationID == op.ID {
+ return method, path, op, true
+ }
}
}
- if res.Schema != nil {
- s.analyzeSchema("schema", res.Schema, refPref)
- }
+ return "", "", nil, false
}
-func (s *Spec) analyzeSchema(name string, schema *spec.Schema, prefix string) {
- refURI := slashpath.Join(prefix, jsonpointer.Escape(name))
- schRef := SchemaRef{
- Name: name,
- Schema: schema,
- Ref: spec.MustCreateRef("#" + refURI),
- TopLevel: prefix == "/definitions",
+// OperationFor the given method and path.
+func (s *Spec) OperationFor(method, path string) (*spec.Operation, bool) {
+ if mp, ok := s.operations[strings.ToUpper(method)]; ok {
+ op, fn := mp[path]
+
+ return op, fn
}
- s.allSchemas["#"+refURI] = schRef
+ return nil, false
+}
- if schema.Ref.String() != "" {
- s.references.addSchemaRef(refURI, schRef)
- }
+// Operations gathers all the operations specified in the spec document.
+func (s *Spec) Operations() map[string]map[string]*spec.Operation {
+ return s.operations
+}
- if schema.Pattern != "" {
- s.patterns.addSchemaPattern(refURI, schema.Pattern)
+// AllPaths returns all the paths in the swagger spec.
+func (s *Spec) AllPaths() map[string]spec.PathItem {
+ if s.spec == nil || s.spec.Paths == nil {
+ return nil
}
- if len(schema.Enum) > 0 {
- s.enums.addSchemaEnum(refURI, schema.Enum)
- }
+ return s.spec.Paths.Paths
+}
- for k, v := range schema.Definitions {
- v := v
- s.analyzeSchema(k, &v, slashpath.Join(refURI, "definitions"))
+// OperationIDs gets all the operation ids based on method an dpath.
+func (s *Spec) OperationIDs() []string {
+ if len(s.operations) == 0 {
+ return nil
}
- for k, v := range schema.Properties {
- v := v
- s.analyzeSchema(k, &v, slashpath.Join(refURI, "properties"))
+ result := make([]string, 0, len(s.operations))
+ for method, v := range s.operations {
+ for p, o := range v {
+ if o.ID != "" {
+ result = append(result, o.ID)
+ } else {
+ result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
+ }
+ }
}
- for k, v := range schema.PatternProperties {
- v := v
- // NOTE: swagger 2.0 does not support PatternProperties.
- // However it is possible to analyze this in a schema
- s.analyzeSchema(k, &v, slashpath.Join(refURI, "patternProperties"))
- }
+ return result
+}
- for i := range schema.AllOf {
- v := &schema.AllOf[i]
- s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "allOf"))
+// OperationMethodPaths gets all the operation ids based on method an dpath.
+func (s *Spec) OperationMethodPaths() []string {
+ if len(s.operations) == 0 {
+ return nil
}
- if len(schema.AllOf) > 0 {
- s.allOfs["#"+refURI] = schRef
+ result := make([]string, 0, len(s.operations))
+ for method, v := range s.operations {
+ for p := range v {
+ result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
+ }
}
- for i := range schema.AnyOf {
- v := &schema.AnyOf[i]
- // NOTE: swagger 2.0 does not support anyOf constructs.
- // However it is possible to analyze this in a schema
- s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "anyOf"))
- }
+ return result
+}
- for i := range schema.OneOf {
- v := &schema.OneOf[i]
- // NOTE: swagger 2.0 does not support oneOf constructs.
- // However it is possible to analyze this in a schema
- s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "oneOf"))
- }
+// RequiredConsumes gets all the distinct consumes that are specified in the specification document.
+func (s *Spec) RequiredConsumes() []string {
+ return s.structMapKeys(s.consumes)
+}
- if schema.Not != nil {
- // NOTE: swagger 2.0 does not support "not" constructs.
- // However it is possible to analyze this in a schema
- s.analyzeSchema("not", schema.Not, refURI)
- }
+// RequiredProduces gets all the distinct produces that are specified in the specification document.
+func (s *Spec) RequiredProduces() []string {
+ return s.structMapKeys(s.produces)
+}
- if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
- s.analyzeSchema("additionalProperties", schema.AdditionalProperties.Schema, refURI)
- }
+// RequiredSecuritySchemes gets all the distinct security schemes that are specified in the swagger spec.
+func (s *Spec) RequiredSecuritySchemes() []string {
+ return s.structMapKeys(s.authSchemes)
+}
- if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
- // NOTE: swagger 2.0 does not support AdditionalItems.
- // However it is possible to analyze this in a schema
- s.analyzeSchema("additionalItems", schema.AdditionalItems.Schema, refURI)
+// SchemaRef is a reference to a schema.
+type SchemaRef struct {
+ Name string
+ Ref spec.Ref
+ Schema *spec.Schema
+ TopLevel bool
+}
+
+// SchemasWithAllOf returns schema references to all schemas that are defined
+// with an allOf key.
+func (s *Spec) SchemasWithAllOf() (result []SchemaRef) {
+ for _, v := range s.allOfs {
+ result = append(result, v)
}
- if schema.Items != nil {
- if schema.Items.Schema != nil {
- s.analyzeSchema("items", schema.Items.Schema, refURI)
- }
+ return
+}
- for i := range schema.Items.Schemas {
- sch := &schema.Items.Schemas[i]
- s.analyzeSchema(strconv.Itoa(i), sch, slashpath.Join(refURI, "items"))
- }
+// AllDefinitions returns schema references for all the definitions that were discovered.
+func (s *Spec) AllDefinitions() (result []SchemaRef) {
+ for _, v := range s.allSchemas {
+ result = append(result, v)
}
-}
-// SecurityRequirement is a representation of a security requirement for an operation
-type SecurityRequirement struct {
- Name string
- Scopes []string
+ return
}
-// SecurityRequirementsFor gets the security requirements for the operation
-func (s *Spec) SecurityRequirementsFor(operation *spec.Operation) [][]SecurityRequirement {
- if s.spec.Security == nil && operation.Security == nil {
- return nil
+// AllDefinitionReferences returns JSON references for all the discovered schemas.
+func (s *Spec) AllDefinitionReferences() (result []string) {
+ for _, v := range s.references.schemas {
+ result = append(result, v.String())
}
- schemes := s.spec.Security
- if operation.Security != nil {
- schemes = operation.Security
+ return
+}
+
+// AllParameterReferences returns JSON references for all the discovered parameters.
+func (s *Spec) AllParameterReferences() (result []string) {
+ for _, v := range s.references.parameters {
+ result = append(result, v.String())
}
- result := [][]SecurityRequirement{}
- for _, scheme := range schemes {
- if len(scheme) == 0 {
- // append a zero object for anonymous
- result = append(result, []SecurityRequirement{{}})
+ return
+}
- continue
- }
+// AllResponseReferences returns JSON references for all the discovered responses.
+func (s *Spec) AllResponseReferences() (result []string) {
+ for _, v := range s.references.responses {
+ result = append(result, v.String())
+ }
- var reqs []SecurityRequirement
- for k, v := range scheme {
- if v == nil {
- v = []string{}
- }
- reqs = append(reqs, SecurityRequirement{Name: k, Scopes: v})
- }
+ return
+}
- result = append(result, reqs)
+// AllPathItemReferences returns the references for all the items.
+func (s *Spec) AllPathItemReferences() (result []string) {
+ for _, v := range s.references.pathItems {
+ result = append(result, v.String())
}
- return result
+ return
}
-// SecurityDefinitionsForRequirements gets the matching security definitions for a set of requirements
-func (s *Spec) SecurityDefinitionsForRequirements(requirements []SecurityRequirement) map[string]spec.SecurityScheme {
- result := make(map[string]spec.SecurityScheme)
-
- for _, v := range requirements {
- if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
- if definition != nil {
- result[v.Name] = *definition
- }
- }
+// AllItemsReferences returns the references for all the items in simple schemas (parameters or headers).
+//
+// NOTE: since Swagger 2.0 forbids $ref in simple params, this should always yield an empty slice for a valid
+// Swagger 2.0 spec.
+func (s *Spec) AllItemsReferences() (result []string) {
+ for _, v := range s.references.items {
+ result = append(result, v.String())
}
- return result
+ return
}
-// SecurityDefinitionsFor gets the matching security definitions for a set of requirements
-func (s *Spec) SecurityDefinitionsFor(operation *spec.Operation) map[string]spec.SecurityScheme {
- requirements := s.SecurityRequirementsFor(operation)
- if len(requirements) == 0 {
- return nil
+// AllReferences returns all the references found in the document, with possible duplicates.
+func (s *Spec) AllReferences() (result []string) {
+ for _, v := range s.references.allRefs {
+ result = append(result, v.String())
}
- result := make(map[string]spec.SecurityScheme)
- for _, reqs := range requirements {
- for _, v := range reqs {
- if v.Name == "" {
- // optional requirement
- continue
- }
+ return
+}
- if _, ok := result[v.Name]; ok {
- // duplicate requirement
- continue
- }
+// AllRefs returns all the unique references found in the document.
+func (s *Spec) AllRefs() (result []spec.Ref) {
+ set := make(map[string]struct{})
+ for _, v := range s.references.allRefs {
+ a := v.String()
+ if a == "" {
+ continue
+ }
- if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
- if definition != nil {
- result[v.Name] = *definition
- }
- }
+ if _, ok := set[a]; !ok {
+ set[a] = struct{}{}
+ result = append(result, v)
}
}
- return result
+ return
}
-// ConsumesFor gets the mediatypes for the operation
-func (s *Spec) ConsumesFor(operation *spec.Operation) []string {
- if len(operation.Consumes) == 0 {
- cons := make(map[string]struct{}, len(s.spec.Consumes))
- for _, k := range s.spec.Consumes {
- cons[k] = struct{}{}
- }
+// ParameterPatterns returns all the patterns found in parameters
+// the map is cloned to avoid accidental changes.
+func (s *Spec) ParameterPatterns() map[string]string {
+ return cloneStringMap(s.patterns.parameters)
+}
- return s.structMapKeys(cons)
- }
+// HeaderPatterns returns all the patterns found in response headers
+// the map is cloned to avoid accidental changes.
+func (s *Spec) HeaderPatterns() map[string]string {
+ return cloneStringMap(s.patterns.headers)
+}
- cons := make(map[string]struct{}, len(operation.Consumes))
- for _, c := range operation.Consumes {
- cons[c] = struct{}{}
- }
+// ItemsPatterns returns all the patterns found in simple array items
+// the map is cloned to avoid accidental changes.
+func (s *Spec) ItemsPatterns() map[string]string {
+ return cloneStringMap(s.patterns.items)
+}
- return s.structMapKeys(cons)
+// SchemaPatterns returns all the patterns found in schemas
+// the map is cloned to avoid accidental changes.
+func (s *Spec) SchemaPatterns() map[string]string {
+ return cloneStringMap(s.patterns.schemas)
+}
+
+// AllPatterns returns all the patterns found in the spec
+// the map is cloned to avoid accidental changes.
+func (s *Spec) AllPatterns() map[string]string {
+ return cloneStringMap(s.patterns.allPatterns)
}
-// ProducesFor gets the mediatypes for the operation
-func (s *Spec) ProducesFor(operation *spec.Operation) []string {
- if len(operation.Produces) == 0 {
- prod := make(map[string]struct{}, len(s.spec.Produces))
- for _, k := range s.spec.Produces {
- prod[k] = struct{}{}
- }
+// ParameterEnums returns all the enums found in parameters
+// the map is cloned to avoid accidental changes.
+func (s *Spec) ParameterEnums() map[string][]any {
+ return cloneEnumMap(s.enums.parameters)
+}
- return s.structMapKeys(prod)
- }
+// HeaderEnums returns all the enums found in response headers
+// the map is cloned to avoid accidental changes.
+func (s *Spec) HeaderEnums() map[string][]any {
+ return cloneEnumMap(s.enums.headers)
+}
- prod := make(map[string]struct{}, len(operation.Produces))
- for _, c := range operation.Produces {
- prod[c] = struct{}{}
- }
+// ItemsEnums returns all the enums found in simple array items
+// the map is cloned to avoid accidental changes.
+func (s *Spec) ItemsEnums() map[string][]any {
+ return cloneEnumMap(s.enums.items)
+}
- return s.structMapKeys(prod)
+// SchemaEnums returns all the enums found in schemas
+// the map is cloned to avoid accidental changes.
+func (s *Spec) SchemaEnums() map[string][]any {
+ return cloneEnumMap(s.enums.schemas)
}
-func mapKeyFromParam(param *spec.Parameter) string {
- return fmt.Sprintf("%s#%s", param.In, fieldNameFromParam(param))
+// AllEnums returns all the enums found in the spec
+// the map is cloned to avoid accidental changes.
+func (s *Spec) AllEnums() map[string][]any {
+ return cloneEnumMap(s.enums.allEnums)
}
-func fieldNameFromParam(param *spec.Parameter) string {
- // TODO: this should be x-go-name
- if nm, ok := param.Extensions.GetString("go-name"); ok {
- return nm
+func (s *Spec) structMapKeys(mp map[string]struct{}) []string {
+ if len(mp) == 0 {
+ return nil
}
- return swag.ToGoName(param.Name)
-}
+ result := make([]string, 0, len(mp))
+ for k := range mp {
+ result = append(result, k)
+ }
-// ErrorOnParamFunc is a callback function to be invoked
-// whenever an error is encountered while resolving references
-// on parameters.
-//
-// This function takes as input the spec.Parameter which triggered the
-// error and the error itself.
-//
-// If the callback function returns false, the calling function should bail.
-//
-// If it returns true, the calling function should continue evaluating parameters.
-// A nil ErrorOnParamFunc must be evaluated as equivalent to panic().
-type ErrorOnParamFunc func(spec.Parameter, error) bool
+ return result
+}
func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Parameter, callmeOnError ErrorOnParamFunc) {
for _, param := range parameters {
@@ -675,7 +682,7 @@ func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Para
obj, _, err := pr.Ref.GetPointer().Get(s.spec)
if err != nil {
- if callmeOnError(param, fmt.Errorf("invalid reference: %q", pr.Ref.String())) {
+ if callmeOnError(param, ErrInvalidRef(pr.Ref.String())) {
continue
}
@@ -684,7 +691,7 @@ func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Para
objAsParam, ok := obj.(spec.Parameter)
if !ok {
- if callmeOnError(param, fmt.Errorf("resolved reference is not a parameter: %q", pr.Ref.String())) {
+ if callmeOnError(param, ErrInvalidParameterRef(pr.Ref.String())) {
continue
}
@@ -696,369 +703,352 @@ func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Para
}
}
-// ParametersFor the specified operation id.
-//
-// Assumes parameters properly resolve references if any and that
-// such references actually resolve to a parameter object.
-// Otherwise, panics.
-func (s *Spec) ParametersFor(operationID string) []spec.Parameter {
- return s.SafeParametersFor(operationID, nil)
+func (s *Spec) reset() {
+ s.consumes = make(map[string]struct{}, allocLargeMap)
+ s.produces = make(map[string]struct{}, allocLargeMap)
+ s.authSchemes = make(map[string]struct{}, allocLargeMap)
+ s.operations = make(map[string]map[string]*spec.Operation, allocLargeMap)
+ s.allSchemas = make(map[string]SchemaRef, allocLargeMap)
+ s.allOfs = make(map[string]SchemaRef, allocLargeMap)
+ s.references.schemas = make(map[string]spec.Ref, allocLargeMap)
+ s.references.pathItems = make(map[string]spec.Ref, allocLargeMap)
+ s.references.responses = make(map[string]spec.Ref, allocLargeMap)
+ s.references.parameters = make(map[string]spec.Ref, allocLargeMap)
+ s.references.items = make(map[string]spec.Ref, allocLargeMap)
+ s.references.headerItems = make(map[string]spec.Ref, allocLargeMap)
+ s.references.parameterItems = make(map[string]spec.Ref, allocLargeMap)
+ s.references.allRefs = make(map[string]spec.Ref, allocLargeMap)
+ s.patterns.parameters = make(map[string]string, allocLargeMap)
+ s.patterns.headers = make(map[string]string, allocLargeMap)
+ s.patterns.items = make(map[string]string, allocLargeMap)
+ s.patterns.schemas = make(map[string]string, allocLargeMap)
+ s.patterns.allPatterns = make(map[string]string, allocLargeMap)
+ s.enums.parameters = make(map[string][]any, allocLargeMap)
+ s.enums.headers = make(map[string][]any, allocLargeMap)
+ s.enums.items = make(map[string][]any, allocLargeMap)
+ s.enums.schemas = make(map[string][]any, allocLargeMap)
+ s.enums.allEnums = make(map[string][]any, allocLargeMap)
}
-// SafeParametersFor the specified operation id.
-//
-// Does not assume parameters properly resolve references or that
-// such references actually resolve to a parameter object.
-//
-// Upon error, invoke a ErrorOnParamFunc callback with the erroneous
-// parameters. If the callback is set to nil, panics upon errors.
-func (s *Spec) SafeParametersFor(operationID string, callmeOnError ErrorOnParamFunc) []spec.Parameter {
- gatherParams := func(pi *spec.PathItem, op *spec.Operation) []spec.Parameter {
- bag := make(map[string]spec.Parameter)
- s.paramsAsMap(pi.Parameters, bag, callmeOnError)
- s.paramsAsMap(op.Parameters, bag, callmeOnError)
+func (s *Spec) reload() {
+ s.reset()
+ s.initialize()
+}
- var res []spec.Parameter
- for _, v := range bag {
- res = append(res, v)
+func (s *Spec) initialize() {
+ for _, c := range s.spec.Consumes {
+ s.consumes[c] = struct{}{}
+ }
+ for _, c := range s.spec.Produces {
+ s.produces[c] = struct{}{}
+ }
+ for _, ss := range s.spec.Security {
+ for k := range ss {
+ s.authSchemes[k] = struct{}{}
}
-
- return res
+ }
+ for path, pathItem := range s.AllPaths() {
+ s.analyzeOperations(path, &pathItem) //#nosec
}
- for _, pi := range s.spec.Paths.Paths {
- if pi.Get != nil && pi.Get.ID == operationID {
- return gatherParams(&pi, pi.Get) //#nosec
- }
- if pi.Head != nil && pi.Head.ID == operationID {
- return gatherParams(&pi, pi.Head) //#nosec
+ for name, parameter := range s.spec.Parameters {
+ refPref := slashpath.Join("/parameters", jsonpointer.Escape(name))
+ if parameter.Items != nil {
+ s.analyzeItems("items", parameter.Items, refPref, "parameter")
}
- if pi.Options != nil && pi.Options.ID == operationID {
- return gatherParams(&pi, pi.Options) //#nosec
+ if parameter.In == "body" && parameter.Schema != nil {
+ s.analyzeSchema("schema", parameter.Schema, refPref)
}
- if pi.Post != nil && pi.Post.ID == operationID {
- return gatherParams(&pi, pi.Post) //#nosec
+ if parameter.Pattern != "" {
+ s.patterns.addParameterPattern(refPref, parameter.Pattern)
}
- if pi.Patch != nil && pi.Patch.ID == operationID {
- return gatherParams(&pi, pi.Patch) //#nosec
+ if len(parameter.Enum) > 0 {
+ s.enums.addParameterEnum(refPref, parameter.Enum)
}
- if pi.Put != nil && pi.Put.ID == operationID {
- return gatherParams(&pi, pi.Put) //#nosec
+ }
+
+ for name, response := range s.spec.Responses {
+ refPref := slashpath.Join("/responses", jsonpointer.Escape(name))
+ for k, v := range response.Headers {
+ hRefPref := slashpath.Join(refPref, "headers", k)
+ if v.Items != nil {
+ s.analyzeItems("items", v.Items, hRefPref, "header")
+ }
+ if v.Pattern != "" {
+ s.patterns.addHeaderPattern(hRefPref, v.Pattern)
+ }
+ if len(v.Enum) > 0 {
+ s.enums.addHeaderEnum(hRefPref, v.Enum)
+ }
}
- if pi.Delete != nil && pi.Delete.ID == operationID {
- return gatherParams(&pi, pi.Delete) //#nosec
+ if response.Schema != nil {
+ s.analyzeSchema("schema", response.Schema, refPref)
}
}
- return nil
+ for name := range s.spec.Definitions {
+ schema := s.spec.Definitions[name]
+ s.analyzeSchema(name, &schema, "/definitions")
+ }
+ // TODO: after analyzing all things and flattening schemas etc
+ // resolve all the collected references to their final representations
+ // best put in a separate method because this could get expensive
}
-// ParamsFor the specified method and path. Aggregates them with the defaults etc, so it's all the params that
-// apply for the method and path.
-//
-// Assumes parameters properly resolve references if any and that
-// such references actually resolve to a parameter object.
-// Otherwise, panics.
-func (s *Spec) ParamsFor(method, path string) map[string]spec.Parameter {
- return s.SafeParamsFor(method, path, nil)
+func (s *Spec) analyzeOperations(path string, pi *spec.PathItem) {
+ // TODO: resolve refs here?
+ // Currently, operations declared via pathItem $ref are known only after expansion
+ op := pi
+ if pi.Ref.String() != "" {
+ key := slashpath.Join("/paths", jsonpointer.Escape(path))
+ s.references.addPathItemRef(key, pi)
+ }
+ s.analyzeOperation("GET", path, op.Get)
+ s.analyzeOperation("PUT", path, op.Put)
+ s.analyzeOperation("POST", path, op.Post)
+ s.analyzeOperation("PATCH", path, op.Patch)
+ s.analyzeOperation("DELETE", path, op.Delete)
+ s.analyzeOperation("HEAD", path, op.Head)
+ s.analyzeOperation("OPTIONS", path, op.Options)
+ for i, param := range op.Parameters {
+ refPref := slashpath.Join("/paths", jsonpointer.Escape(path), "parameters", strconv.Itoa(i))
+ if param.Ref.String() != "" {
+ s.references.addParamRef(refPref, ¶m) //#nosec
+ }
+ if param.Pattern != "" {
+ s.patterns.addParameterPattern(refPref, param.Pattern)
+ }
+ if len(param.Enum) > 0 {
+ s.enums.addParameterEnum(refPref, param.Enum)
+ }
+ if param.Items != nil {
+ s.analyzeItems("items", param.Items, refPref, "parameter")
+ }
+ if param.Schema != nil {
+ s.analyzeSchema("schema", param.Schema, refPref)
+ }
+ }
}
-// SafeParamsFor the specified method and path. Aggregates them with the defaults etc, so it's all the params that
-// apply for the method and path.
-//
-// Does not assume parameters properly resolve references or that
-// such references actually resolve to a parameter object.
-//
-// Upon error, invoke a ErrorOnParamFunc callback with the erroneous
-// parameters. If the callback is set to nil, panics upon errors.
-func (s *Spec) SafeParamsFor(method, path string, callmeOnError ErrorOnParamFunc) map[string]spec.Parameter {
- res := make(map[string]spec.Parameter)
- if pi, ok := s.spec.Paths.Paths[path]; ok {
- s.paramsAsMap(pi.Parameters, res, callmeOnError)
- s.paramsAsMap(s.operations[strings.ToUpper(method)][path].Parameters, res, callmeOnError)
+func (s *Spec) analyzeItems(name string, items *spec.Items, prefix, location string) {
+ if items == nil {
+ return
+ }
+ refPref := slashpath.Join(prefix, name)
+ s.analyzeItems(name, items.Items, refPref, location)
+ if items.Ref.String() != "" {
+ s.references.addItemsRef(refPref, items, location)
+ }
+ if items.Pattern != "" {
+ s.patterns.addItemsPattern(refPref, items.Pattern)
+ }
+ if len(items.Enum) > 0 {
+ s.enums.addItemsEnum(refPref, items.Enum)
}
-
- return res
}
-// OperationForName gets the operation for the given id
-func (s *Spec) OperationForName(operationID string) (string, string, *spec.Operation, bool) {
- for method, pathItem := range s.operations {
- for path, op := range pathItem {
- if operationID == op.ID {
- return method, path, op, true
- }
- }
+func (s *Spec) analyzeParameter(prefix string, i int, param spec.Parameter) {
+ refPref := slashpath.Join(prefix, "parameters", strconv.Itoa(i))
+ if param.Ref.String() != "" {
+ s.references.addParamRef(refPref, ¶m) //#nosec
}
- return "", "", nil, false
-}
-
-// OperationFor the given method and path
-func (s *Spec) OperationFor(method, path string) (*spec.Operation, bool) {
- if mp, ok := s.operations[strings.ToUpper(method)]; ok {
- op, fn := mp[path]
+ if param.Pattern != "" {
+ s.patterns.addParameterPattern(refPref, param.Pattern)
+ }
- return op, fn
+ if len(param.Enum) > 0 {
+ s.enums.addParameterEnum(refPref, param.Enum)
}
- return nil, false
+ s.analyzeItems("items", param.Items, refPref, "parameter")
+ if param.In == "body" && param.Schema != nil {
+ s.analyzeSchema("schema", param.Schema, refPref)
+ }
}
-// Operations gathers all the operations specified in the spec document
-func (s *Spec) Operations() map[string]map[string]*spec.Operation {
- return s.operations
-}
+func (s *Spec) analyzeOperation(method, path string, op *spec.Operation) {
+ if op == nil {
+ return
+ }
-func (s *Spec) structMapKeys(mp map[string]struct{}) []string {
- if len(mp) == 0 {
- return nil
+ for _, c := range op.Consumes {
+ s.consumes[c] = struct{}{}
}
- result := make([]string, 0, len(mp))
- for k := range mp {
- result = append(result, k)
+ for _, c := range op.Produces {
+ s.produces[c] = struct{}{}
}
- return result
-}
+ for _, ss := range op.Security {
+ for k := range ss {
+ s.authSchemes[k] = struct{}{}
+ }
+ }
-// AllPaths returns all the paths in the swagger spec
-func (s *Spec) AllPaths() map[string]spec.PathItem {
- if s.spec == nil || s.spec.Paths == nil {
- return nil
+ if _, ok := s.operations[method]; !ok {
+ s.operations[method] = make(map[string]*spec.Operation)
}
- return s.spec.Paths.Paths
-}
+ s.operations[method][path] = op
+ prefix := slashpath.Join("/paths", jsonpointer.Escape(path), strings.ToLower(method))
+ for i, param := range op.Parameters {
+ s.analyzeParameter(prefix, i, param)
+ }
-// OperationIDs gets all the operation ids based on method an dpath
-func (s *Spec) OperationIDs() []string {
- if len(s.operations) == 0 {
- return nil
+ if op.Responses == nil {
+ return
}
- result := make([]string, 0, len(s.operations))
- for method, v := range s.operations {
- for p, o := range v {
- if o.ID != "" {
- result = append(result, o.ID)
- } else {
- result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
- }
- }
+ if op.Responses.Default != nil {
+ s.analyzeDefaultResponse(prefix, op.Responses.Default)
}
- return result
+ for k, res := range op.Responses.StatusCodeResponses {
+ s.analyzeResponse(prefix, k, res)
+ }
}
-// OperationMethodPaths gets all the operation ids based on method an dpath
-func (s *Spec) OperationMethodPaths() []string {
- if len(s.operations) == 0 {
- return nil
+func (s *Spec) analyzeDefaultResponse(prefix string, res *spec.Response) {
+ refPref := slashpath.Join(prefix, "responses", "default")
+ if res.Ref.String() != "" {
+ s.references.addResponseRef(refPref, res)
}
- result := make([]string, 0, len(s.operations))
- for method, v := range s.operations {
- for p := range v {
- result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
+ for k, v := range res.Headers {
+ hRefPref := slashpath.Join(refPref, "headers", k)
+ s.analyzeItems("items", v.Items, hRefPref, "header")
+ if v.Pattern != "" {
+ s.patterns.addHeaderPattern(hRefPref, v.Pattern)
}
}
- return result
+ if res.Schema != nil {
+ s.analyzeSchema("schema", res.Schema, refPref)
+ }
}
-// RequiredConsumes gets all the distinct consumes that are specified in the specification document
-func (s *Spec) RequiredConsumes() []string {
- return s.structMapKeys(s.consumes)
-}
+func (s *Spec) analyzeResponse(prefix string, k int, res spec.Response) {
+ refPref := slashpath.Join(prefix, "responses", strconv.Itoa(k))
+ if res.Ref.String() != "" {
+ s.references.addResponseRef(refPref, &res) //#nosec
+ }
-// RequiredProduces gets all the distinct produces that are specified in the specification document
-func (s *Spec) RequiredProduces() []string {
- return s.structMapKeys(s.produces)
-}
+ for k, v := range res.Headers {
+ hRefPref := slashpath.Join(refPref, "headers", k)
+ s.analyzeItems("items", v.Items, hRefPref, "header")
+ if v.Pattern != "" {
+ s.patterns.addHeaderPattern(hRefPref, v.Pattern)
+ }
-// RequiredSecuritySchemes gets all the distinct security schemes that are specified in the swagger spec
-func (s *Spec) RequiredSecuritySchemes() []string {
- return s.structMapKeys(s.authSchemes)
-}
+ if len(v.Enum) > 0 {
+ s.enums.addHeaderEnum(hRefPref, v.Enum)
+ }
+ }
-// SchemaRef is a reference to a schema
-type SchemaRef struct {
- Name string
- Ref spec.Ref
- Schema *spec.Schema
- TopLevel bool
+ if res.Schema != nil {
+ s.analyzeSchema("schema", res.Schema, refPref)
+ }
}
-// SchemasWithAllOf returns schema references to all schemas that are defined
-// with an allOf key
-func (s *Spec) SchemasWithAllOf() (result []SchemaRef) {
- for _, v := range s.allOfs {
- result = append(result, v)
+func (s *Spec) analyzeSchema(name string, schema *spec.Schema, prefix string) {
+ refURI := slashpath.Join(prefix, jsonpointer.Escape(name))
+ schRef := SchemaRef{
+ Name: name,
+ Schema: schema,
+ Ref: spec.MustCreateRef("#" + refURI),
+ TopLevel: prefix == "/definitions",
}
- return
-}
+ s.allSchemas["#"+refURI] = schRef
-// AllDefinitions returns schema references for all the definitions that were discovered
-func (s *Spec) AllDefinitions() (result []SchemaRef) {
- for _, v := range s.allSchemas {
- result = append(result, v)
+ if schema.Ref.String() != "" {
+ s.references.addSchemaRef(refURI, schRef)
}
- return
-}
-
-// AllDefinitionReferences returns json refs for all the discovered schemas
-func (s *Spec) AllDefinitionReferences() (result []string) {
- for _, v := range s.references.schemas {
- result = append(result, v.String())
+ if schema.Pattern != "" {
+ s.patterns.addSchemaPattern(refURI, schema.Pattern)
}
- return
-}
+ if len(schema.Enum) > 0 {
+ s.enums.addSchemaEnum(refURI, schema.Enum)
+ }
-// AllParameterReferences returns json refs for all the discovered parameters
-func (s *Spec) AllParameterReferences() (result []string) {
- for _, v := range s.references.parameters {
- result = append(result, v.String())
+ for k, v := range schema.Definitions {
+ s.analyzeSchema(k, &v, slashpath.Join(refURI, "definitions"))
}
- return
-}
+ for k, v := range schema.Properties {
+ s.analyzeSchema(k, &v, slashpath.Join(refURI, "properties"))
+ }
-// AllResponseReferences returns json refs for all the discovered responses
-func (s *Spec) AllResponseReferences() (result []string) {
- for _, v := range s.references.responses {
- result = append(result, v.String())
+ for k, v := range schema.PatternProperties {
+ // NOTE: swagger 2.0 does not support PatternProperties.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema(k, &v, slashpath.Join(refURI, "patternProperties"))
}
- return
-}
+ for i := range schema.AllOf {
+ v := &schema.AllOf[i]
+ s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "allOf"))
+ }
-// AllPathItemReferences returns the references for all the items
-func (s *Spec) AllPathItemReferences() (result []string) {
- for _, v := range s.references.pathItems {
- result = append(result, v.String())
+ if len(schema.AllOf) > 0 {
+ s.allOfs["#"+refURI] = schRef
}
- return
-}
+ for i := range schema.AnyOf {
+ v := &schema.AnyOf[i]
+ // NOTE: swagger 2.0 does not support anyOf constructs.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "anyOf"))
+ }
-// AllItemsReferences returns the references for all the items in simple schemas (parameters or headers).
-//
-// NOTE: since Swagger 2.0 forbids $ref in simple params, this should always yield an empty slice for a valid
-// Swagger 2.0 spec.
-func (s *Spec) AllItemsReferences() (result []string) {
- for _, v := range s.references.items {
- result = append(result, v.String())
+ for i := range schema.OneOf {
+ v := &schema.OneOf[i]
+ // NOTE: swagger 2.0 does not support oneOf constructs.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "oneOf"))
}
- return
-}
+ if schema.Not != nil {
+ // NOTE: swagger 2.0 does not support "not" constructs.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema("not", schema.Not, refURI)
+ }
-// AllReferences returns all the references found in the document, with possible duplicates
-func (s *Spec) AllReferences() (result []string) {
- for _, v := range s.references.allRefs {
- result = append(result, v.String())
+ if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
+ s.analyzeSchema("additionalProperties", schema.AdditionalProperties.Schema, refURI)
}
- return
-}
+ if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
+ // NOTE: swagger 2.0 does not support AdditionalItems.
+ // However it is possible to analyze this in a schema
+ s.analyzeSchema("additionalItems", schema.AdditionalItems.Schema, refURI)
+ }
-// AllRefs returns all the unique references found in the document
-func (s *Spec) AllRefs() (result []spec.Ref) {
- set := make(map[string]struct{})
- for _, v := range s.references.allRefs {
- a := v.String()
- if a == "" {
- continue
+ if schema.Items != nil {
+ if schema.Items.Schema != nil {
+ s.analyzeSchema("items", schema.Items.Schema, refURI)
}
- if _, ok := set[a]; !ok {
- set[a] = struct{}{}
- result = append(result, v)
+ for i := range schema.Items.Schemas {
+ sch := &schema.Items.Schemas[i]
+ s.analyzeSchema(strconv.Itoa(i), sch, slashpath.Join(refURI, "items"))
}
}
-
- return
}
func cloneStringMap(source map[string]string) map[string]string {
res := make(map[string]string, len(source))
- for k, v := range source {
- res[k] = v
- }
+ maps.Copy(res, source)
return res
}
-func cloneEnumMap(source map[string][]interface{}) map[string][]interface{} {
- res := make(map[string][]interface{}, len(source))
- for k, v := range source {
- res[k] = v
- }
+func cloneEnumMap(source map[string][]any) map[string][]any {
+ res := make(map[string][]any, len(source))
+ maps.Copy(res, source)
return res
}
-
-// ParameterPatterns returns all the patterns found in parameters
-// the map is cloned to avoid accidental changes
-func (s *Spec) ParameterPatterns() map[string]string {
- return cloneStringMap(s.patterns.parameters)
-}
-
-// HeaderPatterns returns all the patterns found in response headers
-// the map is cloned to avoid accidental changes
-func (s *Spec) HeaderPatterns() map[string]string {
- return cloneStringMap(s.patterns.headers)
-}
-
-// ItemsPatterns returns all the patterns found in simple array items
-// the map is cloned to avoid accidental changes
-func (s *Spec) ItemsPatterns() map[string]string {
- return cloneStringMap(s.patterns.items)
-}
-
-// SchemaPatterns returns all the patterns found in schemas
-// the map is cloned to avoid accidental changes
-func (s *Spec) SchemaPatterns() map[string]string {
- return cloneStringMap(s.patterns.schemas)
-}
-
-// AllPatterns returns all the patterns found in the spec
-// the map is cloned to avoid accidental changes
-func (s *Spec) AllPatterns() map[string]string {
- return cloneStringMap(s.patterns.allPatterns)
-}
-
-// ParameterEnums returns all the enums found in parameters
-// the map is cloned to avoid accidental changes
-func (s *Spec) ParameterEnums() map[string][]interface{} {
- return cloneEnumMap(s.enums.parameters)
-}
-
-// HeaderEnums returns all the enums found in response headers
-// the map is cloned to avoid accidental changes
-func (s *Spec) HeaderEnums() map[string][]interface{} {
- return cloneEnumMap(s.enums.headers)
-}
-
-// ItemsEnums returns all the enums found in simple array items
-// the map is cloned to avoid accidental changes
-func (s *Spec) ItemsEnums() map[string][]interface{} {
- return cloneEnumMap(s.enums.items)
-}
-
-// SchemaEnums returns all the enums found in schemas
-// the map is cloned to avoid accidental changes
-func (s *Spec) SchemaEnums() map[string][]interface{} {
- return cloneEnumMap(s.enums.schemas)
-}
-
-// AllEnums returns all the enums found in the spec
-// the map is cloned to avoid accidental changes
-func (s *Spec) AllEnums() map[string][]interface{} {
- return cloneEnumMap(s.enums.allEnums)
-}
diff --git a/vendor/github.com/go-openapi/analysis/debug.go b/vendor/github.com/go-openapi/analysis/debug.go
index 33c15704ecb5..8e777c432aae 100644
--- a/vendor/github.com/go-openapi/analysis/debug.go
+++ b/vendor/github.com/go-openapi/analysis/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 analysis
@@ -20,4 +9,4 @@ import (
"github.com/go-openapi/analysis/internal/debug"
)
-var debugLog = debug.GetLogger("analysis", os.Getenv("SWAGGER_DEBUG") != "")
+var debugLog = debug.GetLogger("analysis", os.Getenv("SWAGGER_DEBUG") != "") //nolint:gochecknoglobals // it's okay to use a private global for logging
diff --git a/vendor/github.com/go-openapi/analysis/doc.go b/vendor/github.com/go-openapi/analysis/doc.go
index e8d9f9b13120..9c4b165c6f55 100644
--- a/vendor/github.com/go-openapi/analysis/doc.go
+++ b/vendor/github.com/go-openapi/analysis/doc.go
@@ -1,43 +1,31 @@
-// Copyright 2015 go-swagger maintainers
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package analysis provides methods to work with a Swagger specification document from
+// package go-openapi/spec.
//
-// 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
+// # Analyzing a specification
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// An analysed specification object (type Spec) provides methods to work with swagger definition.
//
-// 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 analysis provides methods to work with a Swagger specification document from
-package go-openapi/spec.
-
-## Analyzing a specification
-
-An analysed specification object (type Spec) provides methods to work with swagger definition.
-
-## Flattening or expanding a specification
-
-Flattening a specification bundles all remote $ref in the main spec document.
-Depending on flattening options, additional preprocessing may take place:
- - full flattening: replacing all inline complex constructs by a named entry in #/definitions
- - expand: replace all $ref's in the document by their expanded content
-
-## Merging several specifications
-
-Mixin several specifications merges all Swagger constructs, and warns about found conflicts.
-
-## Fixing a specification
-
-Unmarshalling a specification with golang json unmarshalling may lead to
-some unwanted result on present but empty fields.
-
-## Analyzing a Swagger schema
-
-Swagger schemas are analyzed to determine their complexity and qualify their content.
-*/
+// # Flattening or expanding a specification
+//
+// Flattening a specification bundles all remote $ref in the main spec document.
+// Depending on flattening options, additional preprocessing may take place:
+//
+// - full flattening: replacing all inline complex constructs by a named entry in #/definitions
+// - expand: replace all $ref's in the document by their expanded content
+//
+// # Merging several specifications
+//
+// [Mixin] several specifications merges all Swagger constructs, and warns about found conflicts.
+//
+// # Fixing a specification
+//
+// Unmarshalling a specification with golang [json] unmarshalling may lead to
+// some unwanted result on present but empty fields.
+//
+// # Analyzing a Swagger schema
+//
+// Swagger schemas are analyzed to determine their complexity and qualify their content.
package analysis
diff --git a/vendor/github.com/go-openapi/analysis/errors.go b/vendor/github.com/go-openapi/analysis/errors.go
new file mode 100644
index 000000000000..540e159a23ce
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/errors.go
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package analysis
+
+import (
+ "errors"
+ "fmt"
+)
+
+type analysisError string
+
+const (
+ ErrAnalysis analysisError = "analysis error"
+ ErrNoSchema analysisError = "no schema to analyze"
+)
+
+func (e analysisError) Error() string {
+ return string(e)
+}
+
+func ErrAtKey(key string, err error) error {
+ return errors.Join(
+ fmt.Errorf("key %s: %w", key, err),
+ ErrAnalysis,
+ )
+}
+
+func ErrInvalidRef(key string) error {
+ return fmt.Errorf("invalid reference: %q: %w", key, ErrAnalysis)
+}
+
+func ErrInvalidParameterRef(key string) error {
+ return fmt.Errorf("resolved reference is not a parameter: %q: %w", key, ErrAnalysis)
+}
+
+func ErrResolveSchema(err error) error {
+ return errors.Join(
+ fmt.Errorf("could not resolve schema: %w", err),
+ ErrAnalysis,
+ )
+}
+
+func ErrRewriteRef(key string, target any, err error) error {
+ return errors.Join(
+ fmt.Errorf("failed to rewrite ref for key %q at %v: %w", key, target, err),
+ ErrAnalysis,
+ )
+}
+
+func ErrInlineDefinition(key string, err error) error {
+ return errors.Join(
+ fmt.Errorf("error while creating definition %q from inline schema: %w", key, err),
+ ErrAnalysis,
+ )
+}
diff --git a/vendor/github.com/go-openapi/analysis/fixer.go b/vendor/github.com/go-openapi/analysis/fixer.go
index 7c2ca084162e..74becbbe4962 100644
--- a/vendor/github.com/go-openapi/analysis/fixer.go
+++ b/vendor/github.com/go-openapi/analysis/fixer.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 analysis
@@ -72,7 +61,7 @@ func FixEmptyDescs(rs *spec.Responses) {
// Response object if it doesn't already have one and isn't a
// ref. No-op on nil input.
func FixEmptyDesc(rs *spec.Response) {
- if rs == nil || rs.Description != "" || rs.Ref.Ref.GetURL() != nil {
+ if rs == nil || rs.Description != "" || rs.Ref.GetURL() != nil {
return
}
rs.Description = "(empty)"
diff --git a/vendor/github.com/go-openapi/analysis/flatten.go b/vendor/github.com/go-openapi/analysis/flatten.go
index ebedcc9df325..d7ee0064b6f2 100644
--- a/vendor/github.com/go-openapi/analysis/flatten.go
+++ b/vendor/github.com/go-openapi/analysis/flatten.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 analysis
import (
- "fmt"
"log"
"path"
+ "slices"
"sort"
"strings"
@@ -32,7 +21,7 @@ import (
const definitionsPath = "#/definitions"
-// newRef stores information about refs created during the flattening process
+// newRef stores information about refs created during the flattening process.
type newRef struct {
key string
newName string
@@ -43,7 +32,7 @@ type newRef struct {
parents []string
}
-// context stores intermediary results from flatten
+// context stores intermediary results from flatten.
type context struct {
newRefs map[string]*newRef
warnings []string
@@ -52,9 +41,9 @@ type context struct {
func newContext() *context {
return &context{
- newRefs: make(map[string]*newRef, 150),
+ newRefs: make(map[string]*newRef, allocMediumMap),
warnings: make([]string, 0),
- resolved: make(map[string]string, 50),
+ resolved: make(map[string]string, allocMediumMap),
}
}
@@ -63,13 +52,15 @@ func newContext() *context {
// There is a minimal and a full flattening mode.
//
// Minimally flattening a spec means:
+//
// - Expanding parameters, responses, path items, parameter items and header items (references to schemas are left
// unscathed)
-// - Importing external (http, file) references so they become internal to the document
+// - Importing external ([http], file) references so they become internal to the document
// - Moving every JSON pointer to a $ref to a named definition (i.e. the reworked spec does not contain pointers
// like "$ref": "#/definitions/myObject/allOfs/1")
//
// A minimally flattened spec thus guarantees the following properties:
+//
// - all $refs point to a local definition (i.e. '#/definitions/...')
// - definitions are unique
//
@@ -81,6 +72,7 @@ func newContext() *context {
// Minimal flattening is necessary and sufficient for codegen rendering using go-swagger.
//
// Fully flattening a spec means:
+//
// - Moving every complex inline schema to be a definition with an auto-generated name in a depth-first fashion.
//
// By complex, we mean every JSON object with some properties.
@@ -91,6 +83,7 @@ func newContext() *context {
// have been created.
//
// Available flattening options:
+//
// - Minimal: stops flattening after minimal $ref processing, leaving schema constructs untouched
// - Expand: expand all $ref's in the document (inoperant if Minimal set to true)
// - Verbose: croaks about name conflicts detected
@@ -98,8 +91,9 @@ func newContext() *context {
//
// NOTE: expansion removes all $ref save circular $ref, which remain in place
//
-// TODO: additional options
-// - ProgagateNameExtensions: ensure that created entries properly follow naming rules when their parent have set a
+// Desirable future additions: additional options.
+//
+// - PropagateNameExtensions: ensure that created entries properly follow naming rules when their parent have set a
// x-go-name extension
// - LiftAllOfs:
// - limit the flattening of allOf members when simple objects
@@ -180,7 +174,7 @@ func expand(opts *FlattenOpts) error {
}
// normalizeRef strips the current file from any absolute file $ref. This works around issue go-openapi/spec#76:
-// leading absolute file in $ref is stripped
+// leading absolute file in $ref is stripped.
func normalizeRef(opts *FlattenOpts) error {
debugLog("normalizeRef")
@@ -251,7 +245,7 @@ func nameInlinedSchemas(opts *FlattenOpts) error {
asch, err := Schema(SchemaOpts{Schema: sch.Schema, Root: opts.Swagger(), BasePath: opts.BasePath})
if err != nil {
- return fmt.Errorf("schema analysis [%s]: %w", key, err)
+ return ErrAtKey(key, err)
}
if asch.isAnalyzedAsComplex() { // move complex schemas to definitions
@@ -320,7 +314,7 @@ func importNewRef(entry sortref.RefRevIdx, refStr string, opts *FlattenOpts) err
sch, err := spec.ResolveRefWithBase(opts.Swagger(), &entry.Ref, opts.ExpandOpts(false))
if err != nil {
- return fmt.Errorf("could not resolve schema: %w", err)
+ return ErrResolveSchema(err)
}
// at this stage only $ref analysis matters
@@ -335,7 +329,7 @@ func importNewRef(entry sortref.RefRevIdx, refStr string, opts *FlattenOpts) err
// now rewrite those refs with rebase
for key, ref := range partialAnalyzer.references.allRefs {
if err := replace.UpdateRef(sch, key, spec.MustCreateRef(normalize.RebaseRef(entry.Ref.String(), ref.String()))); err != nil {
- return fmt.Errorf("failed to rewrite ref for key %q at %s: %w", key, entry.Ref.String(), err)
+ return ErrRewriteRef(key, entry.Ref.String(), err)
}
}
@@ -429,7 +423,7 @@ func importExternalReferences(opts *FlattenOpts) (bool, error) {
ref := spec.MustCreateRef(r.path)
sch, err := spec.ResolveRefWithBase(opts.Swagger(), &ref, opts.ExpandOpts(false))
if err != nil {
- return false, fmt.Errorf("could not resolve schema: %w", err)
+ return false, ErrResolveSchema(err)
}
r.schema = sch
@@ -502,14 +496,25 @@ func stripPointersAndOAIGen(opts *FlattenOpts) error {
// pointer and name resolution again.
func stripOAIGen(opts *FlattenOpts) (bool, error) {
debugLog("stripOAIGen")
+ // Ensure the spec analysis is fresh, as previous steps (namePointers, etc.) might have modified refs.
+ opts.Spec.reload()
+
replacedWithComplex := false
// figure out referers of OAIGen definitions (doing it before the ref start mutating)
- for _, r := range opts.flattenContext.newRefs {
+ // Sort keys to ensure deterministic processing order
+ sortedKeys := make([]string, 0, len(opts.flattenContext.newRefs))
+ for k := range opts.flattenContext.newRefs {
+ sortedKeys = append(sortedKeys, k)
+ }
+ sort.Strings(sortedKeys)
+
+ for _, k := range sortedKeys {
+ r := opts.flattenContext.newRefs[k]
updateRefParents(opts.Spec.references.allRefs, r)
}
- for k := range opts.flattenContext.newRefs {
+ for _, k := range sortedKeys {
r := opts.flattenContext.newRefs[k]
debugLog("newRefs[%s]: isOAIGen: %t, resolved: %t, name: %s, path:%s, #parents: %d, parents: %v, ref: %s",
k, r.isOAIGen, r.resolved, r.newName, r.path, len(r.parents), r.parents, r.schema.Ref.String())
@@ -532,7 +537,7 @@ func stripOAIGen(opts *FlattenOpts) (bool, error) {
return replacedWithComplex, nil
}
-// updateRefParents updates all parents of an updated $ref
+// updateRefParents updates all parents of an updated $ref.
func updateRefParents(allRefs map[string]spec.Ref, r *newRef) {
if !r.isOAIGen || r.resolved { // bail on already resolved entries (avoid looping)
return
@@ -542,14 +547,7 @@ func updateRefParents(allRefs map[string]spec.Ref, r *newRef) {
continue
}
- found := false
- for _, p := range r.parents {
- if p == k {
- found = true
-
- break
- }
- }
+ found := slices.Contains(r.parents, k)
if !found {
r.parents = append(r.parents, k)
}
@@ -598,6 +596,19 @@ func stripOAIGenForRef(opts *FlattenOpts, k string, r *newRef) (bool, error) {
replacedWithComplex = true
}
}
+
+ // update parents of the target ref (pr[0]) if it is also a newRef (OAIGen)
+ // This ensures that if the target is later deleted/merged, it knows about these new referers.
+ for _, nr := range opts.flattenContext.newRefs {
+ if nr.path == pr[0] && nr.isOAIGen && !nr.resolved {
+ for _, p := range pr[1:] {
+ if !slices.Contains(nr.parents, p) {
+ nr.parents = append(nr.parents, p)
+ }
+ }
+ break
+ }
+ }
}
// remove OAIGen definition
@@ -605,7 +616,15 @@ func stripOAIGenForRef(opts *FlattenOpts, k string, r *newRef) (bool, error) {
delete(opts.Swagger().Definitions, path.Base(r.path))
// propagate changes in ref index for keys which have this one as a parent
- for kk, value := range opts.flattenContext.newRefs {
+ // Sort keys to ensure deterministic update order
+ propagateKeys := make([]string, 0, len(opts.flattenContext.newRefs))
+ for k := range opts.flattenContext.newRefs {
+ propagateKeys = append(propagateKeys, k)
+ }
+ sort.Strings(propagateKeys)
+
+ for _, kk := range propagateKeys {
+ value := opts.flattenContext.newRefs[kk]
if kk == k || !value.isOAIGen || value.resolved {
continue
}
@@ -643,7 +662,7 @@ func stripOAIGenForRef(opts *FlattenOpts, k string, r *newRef) (bool, error) {
}
debugLog("re-inlined schema: parent: %s, %t", pr[0], asch.isAnalyzedAsComplex())
- replacedWithComplex = replacedWithComplex || !(path.Dir(pr[0]) == definitionsPath) && asch.isAnalyzedAsComplex()
+ replacedWithComplex = replacedWithComplex || path.Dir(pr[0]) != definitionsPath && asch.isAnalyzedAsComplex()
}
return replacedWithComplex, nil
@@ -666,7 +685,7 @@ func namePointers(opts *FlattenOpts) error {
result, err := replace.DeepestRef(opts.Swagger(), opts.ExpandOpts(false), ref)
if err != nil {
- return fmt.Errorf("at %s, %w", k, err)
+ return ErrAtKey(k, err)
}
replacingRef := result.Ref
@@ -697,7 +716,7 @@ func namePointers(opts *FlattenOpts) error {
// update current replacement, which may have been updated by previous changes of deeper elements
result, erd := replace.DeepestRef(opts.Swagger(), opts.ExpandOpts(false), v.Ref)
if erd != nil {
- return fmt.Errorf("at %s, %w", key, erd)
+ return ErrAtKey(key, erd)
}
if opts.flattenContext != nil {
@@ -743,9 +762,9 @@ func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]Schema
// qualify the expanded schema
asch, ers := Schema(SchemaOpts{Schema: v.Schema, Root: opts.Swagger(), BasePath: opts.BasePath})
if ers != nil {
- return fmt.Errorf("schema analysis [%s]: %w", key, ers)
+ return ErrAtKey(key, ers)
}
- callers := make([]string, 0, 64)
+ callers := make([]string, 0, allocMediumMap)
debugLog("looking for callers")
@@ -753,7 +772,7 @@ func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]Schema
for k, w := range an.references.allRefs {
r, err := replace.DeepestRef(opts.Swagger(), opts.ExpandOpts(false), w)
if err != nil {
- return fmt.Errorf("at %s, %w", key, err)
+ return ErrAtKey(key, err)
}
if opts.flattenContext != nil {
diff --git a/vendor/github.com/go-openapi/analysis/flatten_name.go b/vendor/github.com/go-openapi/analysis/flatten_name.go
index c7d7938ebe6b..922cae55c5e4 100644
--- a/vendor/github.com/go-openapi/analysis/flatten_name.go
+++ b/vendor/github.com/go-openapi/analysis/flatten_name.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package analysis
import (
@@ -11,10 +14,10 @@ import (
"github.com/go-openapi/analysis/internal/flatten/schutils"
"github.com/go-openapi/analysis/internal/flatten/sortref"
"github.com/go-openapi/spec"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/mangling"
)
-// InlineSchemaNamer finds a new name for an inlined type
+// InlineSchemaNamer finds a new name for an inlined type.
type InlineSchemaNamer struct {
Spec *spec.Swagger
Operations map[string]operations.OpRef
@@ -22,7 +25,7 @@ type InlineSchemaNamer struct {
opts *FlattenOpts
}
-// Name yields a new name for the inline schema
+// Name yields a new name for the inline schema.
func (isn *InlineSchemaNamer) Name(key string, schema *spec.Schema, aschema *AnalyzedSchema) error {
debugLog("naming inlined schema at %s", key)
@@ -43,7 +46,7 @@ func (isn *InlineSchemaNamer) Name(key string, schema *spec.Schema, aschema *Ana
debugLog("rewriting schema to ref: key=%s with new name: %s", key, newName)
if err := replace.RewriteSchemaToRef(isn.Spec, key,
spec.MustCreateRef(path.Join(definitionsPath, newName))); err != nil {
- return fmt.Errorf("error while creating definition %q from inline schema: %w", newName, err)
+ return ErrInlineDefinition(newName, err)
}
// rewrite any dependent $ref pointing to this place,
@@ -54,7 +57,7 @@ func (isn *InlineSchemaNamer) Name(key string, schema *spec.Schema, aschema *Ana
for k, v := range an.references.allRefs {
r, erd := replace.DeepestRef(isn.opts.Swagger(), isn.opts.ExpandOpts(false), v)
if erd != nil {
- return fmt.Errorf("at %s, %w", k, erd)
+ return ErrAtKey(k, erd)
}
if isn.opts.flattenContext != nil {
@@ -105,7 +108,7 @@ func (isn *InlineSchemaNamer) Name(key string, schema *spec.Schema, aschema *Ana
return nil
}
-// uniqifyName yields a unique name for a definition
+// uniqifyName yields a unique name for a definition.
func uniqifyName(definitions spec.Definitions, name string) (string, bool) {
isOAIGen := false
if name == "" {
@@ -227,19 +230,24 @@ func namesForOperation(parts sortref.SplitKey, operations map[string]operations.
return baseNames, startIndex
}
+const (
+ minStartIndex = 2
+ minSegments = 2
+)
+
func namesForDefinition(parts sortref.SplitKey) ([][]string, int) {
nm := parts.DefinitionName()
if nm != "" {
- return [][]string{{parts.DefinitionName()}}, 2
+ return [][]string{{parts.DefinitionName()}}, minStartIndex
}
return [][]string{}, 0
}
-// partAdder knows how to interpret a schema when it comes to build a name from parts
+// partAdder knows how to interpret a schema when it comes to build a name from parts.
func partAdder(aschema *AnalyzedSchema) sortref.PartAdder {
return func(part string) []string {
- segments := make([]string, 0, 2)
+ segments := make([]string, 0, minSegments)
if part == "items" || part == "additionalItems" {
if aschema.IsTuple || aschema.IsTupleWithExtra {
@@ -265,8 +273,9 @@ func mangler(o *FlattenOpts) func(string) string {
if o.KeepNames {
return func(in string) string { return in }
}
+ mangler := mangling.NewNameMangler()
- return swag.ToJSONName
+ return mangler.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 c943fe1e84a3..23a57ea1aca5 100644
--- a/vendor/github.com/go-openapi/analysis/flatten_options.go
+++ b/vendor/github.com/go-openapi/analysis/flatten_options.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package analysis
import (
@@ -32,7 +35,7 @@ type FlattenOpts struct {
_ struct{} // require keys
}
-// ExpandOpts creates a spec.ExpandOptions to configure expanding a specification document.
+// 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,
@@ -41,13 +44,13 @@ func (f *FlattenOpts) ExpandOpts(skipSchemas bool) *spec.ExpandOptions {
}
}
-// Swagger gets the swagger specification for this flatten operation
+// Swagger gets the swagger specification for this flatten operation.
func (f *FlattenOpts) Swagger() *spec.Swagger {
return f.Spec.spec
}
// croak logs notifications and warnings about valid, but possibly unwanted constructs resulting
-// from flattening a spec
+// from flattening a spec.
func (f *FlattenOpts) croak() {
if !f.Verbose {
return
diff --git a/vendor/github.com/go-openapi/analysis/internal/debug/debug.go b/vendor/github.com/go-openapi/analysis/internal/debug/debug.go
index 39f55a97bfdc..d3fa08d3ba34 100644
--- a/vendor/github.com/go-openapi/analysis/internal/debug/debug.go
+++ b/vendor/github.com/go-openapi/analysis/internal/debug/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 debug
@@ -22,20 +11,18 @@ import (
"runtime"
)
-var (
- output = os.Stdout
-)
+var output = os.Stdout //nolint:gochecknoglobals // this is on purpose to be overridable during tests
-// GetLogger provides a prefix debug logger
-func GetLogger(prefix string, debug bool) func(string, ...interface{}) {
+// GetLogger provides a prefix debug logger.
+func GetLogger(prefix string, debug bool) func(string, ...any) {
if debug {
logger := log.New(output, prefix+":", log.LstdFlags)
- return func(msg string, args ...interface{}) {
+ return func(msg string, args ...any) {
_, file1, pos1, _ := runtime.Caller(1)
logger.Printf("%s:%d: %s", filepath.Base(file1), pos1, fmt.Sprintf(msg, args...))
}
}
- return func(_ string, _ ...interface{}) {}
+ return func(_ string, _ ...any) {}
}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/normalize/normalize.go b/vendor/github.com/go-openapi/analysis/internal/flatten/normalize/normalize.go
index 8c9df0580da7..afeef20ea679 100644
--- a/vendor/github.com/go-openapi/analysis/internal/flatten/normalize/normalize.go
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/normalize/normalize.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package normalize
import (
@@ -14,8 +17,9 @@ import (
// NOTE: does not support JSONschema ID for $ref (we assume we are working with swagger specs here).
//
// NOTE(windows):
-// * refs are assumed to have been normalized with drive letter lower cased (from go-openapi/spec)
-// * "/ in paths may appear as escape sequences
+//
+// - refs are assumed to have been normalized with drive letter lower cased (from go-openapi/spec)
+// - "/ in paths may appear as escape sequences.
func RebaseRef(baseRef string, ref string) string {
baseRef, _ = url.PathUnescape(baseRef)
ref, _ = url.PathUnescape(ref)
@@ -66,8 +70,9 @@ func RebaseRef(baseRef string, ref string) string {
// Path renders absolute path on remote file refs
//
// NOTE(windows):
-// * refs are assumed to have been normalized with drive letter lower cased (from go-openapi/spec)
-// * "/ in paths may appear as escape sequences
+//
+// - refs are assumed to have been normalized with drive letter lower cased (from go-openapi/spec)
+// - "/ in paths may appear as escape sequences.
func Path(ref spec.Ref, basePath string) string {
uri, _ := url.PathUnescape(ref.String())
if ref.HasFragmentOnly || filepath.IsAbs(uri) {
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/operations/operations.go b/vendor/github.com/go-openapi/analysis/internal/flatten/operations/operations.go
index 7f3a2b8717f2..325e2751f836 100644
--- a/vendor/github.com/go-openapi/analysis/internal/flatten/operations/operations.go
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/operations/operations.go
@@ -1,21 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package operations
import (
"path"
+ "slices"
"sort"
"strings"
"github.com/go-openapi/jsonpointer"
"github.com/go-openapi/spec"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/mangling"
)
-// AllOpRefsByRef returns an index of sortable operations
+// AllOpRefsByRef returns an index of sortable operations.
func AllOpRefsByRef(specDoc Provider, operationIDs []string) map[string]OpRef {
return OpRefsByRef(GatherOperations(specDoc, operationIDs))
}
-// OpRefsByRef indexes a map of sortable operations
+// OpRefsByRef indexes a map of sortable operations.
func OpRefsByRef(oprefs map[string]OpRef) map[string]OpRef {
result := make(map[string]OpRef, len(oprefs))
for _, v := range oprefs {
@@ -25,7 +29,7 @@ func OpRefsByRef(oprefs map[string]OpRef) map[string]OpRef {
return result
}
-// OpRef is an indexable, sortable operation
+// OpRef is an indexable, sortable operation.
type OpRef struct {
Method string
Path string
@@ -35,27 +39,28 @@ type OpRef struct {
Ref spec.Ref
}
-// OpRefs is a sortable collection of operations
+// OpRefs is a sortable collection of operations.
type OpRefs []OpRef
func (o OpRefs) Len() int { return len(o) }
func (o OpRefs) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
func (o OpRefs) Less(i, j int) bool { return o[i].Key < o[j].Key }
-// Provider knows how to collect operations from a spec
+// Provider knows how to collect operations from a spec.
type Provider interface {
Operations() map[string]map[string]*spec.Operation
}
-// GatherOperations builds a map of sorted operations from a spec
+// GatherOperations builds a map of sorted operations from a spec.
func GatherOperations(specDoc Provider, operationIDs []string) map[string]OpRef {
var oprefs OpRefs
+ mangler := mangling.NewNameMangler()
for method, pathItem := range specDoc.Operations() {
for pth, operation := range pathItem {
vv := *operation
oprefs = append(oprefs, OpRef{
- Key: swag.ToGoName(strings.ToLower(method) + " " + pth),
+ Key: mangler.ToGoName(strings.ToLower(method) + " " + pth),
Method: method,
Path: pth,
ID: vv.ID,
@@ -79,7 +84,7 @@ func GatherOperations(specDoc Provider, operationIDs []string) map[string]OpRef
nm = opr.Key
}
- if len(operationIDs) == 0 || swag.ContainsStrings(operationIDs, opr.ID) || swag.ContainsStrings(operationIDs, nm) {
+ if len(operationIDs) == 0 || slices.Contains(operationIDs, opr.ID) || slices.Contains(operationIDs, nm) {
opr.ID = nm
opr.Op.ID = nm
operations[nm] = opr
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/replace/errors.go b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/errors.go
new file mode 100644
index 000000000000..b2a8a93ba679
--- /dev/null
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/errors.go
@@ -0,0 +1,64 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package replace
+
+import (
+ "errors"
+ "fmt"
+)
+
+type replaceError string
+
+const (
+ ErrReplace replaceError = "flatten replace error"
+ ErrUnexpectedType replaceError = "unexpected type used in getPointerFromKey"
+)
+
+func (e replaceError) Error() string {
+ return string(e)
+}
+
+func ErrNoSchemaWithRef(key string, value any) error {
+ return fmt.Errorf("no schema with ref found at %s for %T: %w", key, value, ErrReplace)
+}
+
+func ErrNoSchema(key string) error {
+ return fmt.Errorf("no schema found at %s: %w", key, ErrReplace)
+}
+
+func ErrNotANumber(key string, err error) error {
+ return errors.Join(
+ ErrReplace,
+ fmt.Errorf("%s not a number: %w", key, err),
+ )
+}
+
+func ErrUnhandledParentRewrite(key string, value any) error {
+ return fmt.Errorf("unhandled parent schema rewrite %s: %T: %w", key, value, ErrReplace)
+}
+
+func ErrUnhandledParentType(key string, value any) error {
+ return fmt.Errorf("unhandled type for parent of %s: %T: %w", key, value, ErrReplace)
+}
+
+func ErrNoParent(key string, err error) error {
+ return errors.Join(
+ fmt.Errorf("can't get parent for %s: %w", key, err),
+ ErrReplace,
+ )
+}
+
+func ErrUnhandledContainerType(key string, value any) error {
+ return fmt.Errorf("unhandled container type at %s: %T: %w", key, value, ErrReplace)
+}
+
+func ErrCyclicChain(key string) error {
+ return fmt.Errorf("cannot resolve cyclic chain of pointers under %s: %w", key, ErrReplace)
+}
+
+func ErrInvalidPointerType(key string, value any, err error) error {
+ return fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T (%w): %w",
+ key, value, err, ErrReplace,
+ )
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/replace/replace.go b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/replace.go
index c0f43e728a3f..b4c0fdd44a1e 100644
--- a/vendor/github.com/go-openapi/analysis/internal/flatten/replace/replace.go
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/replace/replace.go
@@ -1,7 +1,11 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package replace
import (
"encoding/json"
+ "errors"
"fmt"
"net/url"
"os"
@@ -13,11 +17,15 @@ import (
"github.com/go-openapi/spec"
)
-const definitionsPath = "#/definitions"
+const (
+ definitionsPath = "#/definitions"
+ allocMediumMap = 64
+)
+//nolint:gochecknoglobals // it's okay to use a private global for logging
var debugLog = debug.GetLogger("analysis/flatten/replace", os.Getenv("SWAGGER_DEBUG") != "")
-// RewriteSchemaToRef replaces a schema with a Ref
+// RewriteSchemaToRef replaces a schema with a Ref.
func RewriteSchemaToRef(sp *spec.Swagger, key string, ref spec.Ref) error {
debugLog("rewriting schema to ref for %s with %s", key, ref.String())
_, value, err := getPointerFromKey(sp, key)
@@ -41,10 +49,10 @@ func RewriteSchemaToRef(sp *spec.Swagger, key string, ref spec.Ref) error {
if refable.Schema != nil {
refable.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
}
- case map[string]interface{}: // this happens e.g. if a schema points to an extension unmarshaled as map[string]interface{}
+ case map[string]any: // this happens e.g. if a schema points to an extension unmarshaled as map[string]interface{}
return rewriteParentRef(sp, key, ref)
default:
- return fmt.Errorf("no schema with ref found at %s for %T", key, value)
+ return ErrNoSchemaWithRef(key, value)
}
return nil
@@ -69,7 +77,7 @@ func rewriteParentRef(sp *spec.Swagger, key string, ref spec.Ref) error {
case *spec.Responses:
statusCode, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", key[1:], err)
+ return ErrNotANumber(key[1:], err)
}
resp := container.StatusCodeResponses[statusCode]
resp.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
@@ -93,7 +101,7 @@ func rewriteParentRef(sp *spec.Swagger, key string, ref spec.Ref) error {
case []spec.Parameter:
idx, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", key[1:], err)
+ return ErrNotANumber(key[1:], err)
}
param := container[idx]
param.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
@@ -108,7 +116,7 @@ func rewriteParentRef(sp *spec.Swagger, key string, ref spec.Ref) error {
case []spec.Schema:
idx, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", key[1:], err)
+ return ErrNotANumber(key[1:], err)
}
container[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
@@ -116,60 +124,63 @@ func rewriteParentRef(sp *spec.Swagger, key string, ref spec.Ref) error {
// NOTE: this is necessarily an array - otherwise, the parent would be *Schema
idx, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", key[1:], err)
+ return ErrNotANumber(key[1:], err)
}
container.Schemas[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
case spec.SchemaProperties:
container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
- case *interface{}:
+ case *any:
*container = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
// NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
default:
- return fmt.Errorf("unhandled parent schema rewrite %s (%T)", key, pvalue)
+ return ErrUnhandledParentRewrite(key, pvalue)
}
return nil
}
-// getPointerFromKey retrieves the content of the JSON pointer "key"
-func getPointerFromKey(sp interface{}, key string) (string, interface{}, error) {
+// getPointerFromKey retrieves the content of the JSON pointer "key".
+func getPointerFromKey(sp any, key string) (string, any, error) {
switch sp.(type) {
case *spec.Schema:
case *spec.Swagger:
default:
- panic("unexpected type used in getPointerFromKey")
+ panic(ErrUnexpectedType)
}
if key == "#/" {
return "", sp, nil
}
// unescape chars in key, e.g. "{}" from path params
- pth, _ := url.PathUnescape(key[1:])
+ pth, err := url.PathUnescape(key[1:])
+ if err != nil {
+ return "", nil, errors.Join(err, ErrReplace)
+ }
ptr, err := jsonpointer.New(pth)
if err != nil {
- return "", nil, err
+ return "", nil, errors.Join(err, ErrReplace)
}
value, _, err := ptr.Get(sp)
if err != nil {
debugLog("error when getting key: %s with path: %s", key, pth)
- return "", nil, err
+ return "", nil, errors.Join(err, ErrReplace)
}
return pth, value, nil
}
-// getParentFromKey retrieves the container of the JSON pointer "key"
-func getParentFromKey(sp interface{}, key string) (string, string, interface{}, error) {
+// getParentFromKey retrieves the container of the JSON pointer "key".
+func getParentFromKey(sp any, key string) (string, string, any, error) {
switch sp.(type) {
case *spec.Schema:
case *spec.Swagger:
default:
- panic("unexpected type used in getPointerFromKey")
+ panic(ErrUnexpectedType)
}
// unescape chars in key, e.g. "{}" from path params
pth, _ := url.PathUnescape(key[1:])
@@ -179,23 +190,23 @@ func getParentFromKey(sp interface{}, key string) (string, string, interface{},
pptr, err := jsonpointer.New(parent)
if err != nil {
- return "", "", nil, err
+ return "", "", nil, errors.Join(err, ErrReplace)
}
pvalue, _, err := pptr.Get(sp)
if err != nil {
- return "", "", nil, fmt.Errorf("can't get parent for %s: %w", parent, err)
+ return "", "", nil, ErrNoParent(parent, err)
}
return parent, entry, pvalue, nil
}
-// UpdateRef replaces a ref by another one
-func UpdateRef(sp interface{}, key string, ref spec.Ref) error {
+// UpdateRef replaces a ref by another one.
+func UpdateRef(sp any, key string, ref spec.Ref) error {
switch sp.(type) {
case *spec.Schema:
case *spec.Swagger:
default:
- panic("unexpected type used in getPointerFromKey")
+ panic(ErrUnexpectedType)
}
debugLog("updating ref for %s with %s", key, ref.String())
pth, value, err := getPointerFromKey(sp, key)
@@ -218,7 +229,7 @@ func UpdateRef(sp interface{}, key string, ref spec.Ref) error {
debugLog("rewriting holder for %T", refable)
_, entry, pvalue, erp := getParentFromKey(sp, key)
if erp != nil {
- return err
+ return erp
}
switch container := pvalue.(type) {
case spec.Definitions:
@@ -230,7 +241,7 @@ func UpdateRef(sp interface{}, key string, ref spec.Ref) error {
case []spec.Schema:
idx, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", pth, err)
+ return ErrNotANumber(pth, err)
}
container[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
@@ -238,7 +249,7 @@ func UpdateRef(sp interface{}, key string, ref spec.Ref) error {
// NOTE: this is necessarily an array - otherwise, the parent would be *Schema
idx, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", pth, err)
+ return ErrNotANumber(pth, err)
}
container.Schemas[idx] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
@@ -248,17 +259,17 @@ func UpdateRef(sp interface{}, key string, ref spec.Ref) error {
// NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
default:
- return fmt.Errorf("unhandled container type at %s: %T", key, value)
+ return ErrUnhandledContainerType(key, value)
}
default:
- return fmt.Errorf("no schema with ref found at %s for %T", key, value)
+ return ErrNoSchemaWithRef(key, value)
}
return nil
}
-// UpdateRefWithSchema replaces a ref with a schema (i.e. re-inline schema)
+// UpdateRefWithSchema replaces a ref with a schema (i.e. re-inline schema).
func UpdateRefWithSchema(sp *spec.Swagger, key string, sch *spec.Schema) error {
debugLog("updating ref for %s with schema", key)
pth, value, err := getPointerFromKey(sp, key)
@@ -272,8 +283,9 @@ func UpdateRefWithSchema(sp *spec.Swagger, key string, sch *spec.Schema) error {
case spec.Schema:
_, entry, pvalue, erp := getParentFromKey(sp, key)
if erp != nil {
- return err
+ return erp
}
+
switch container := pvalue.(type) {
case spec.Definitions:
container[entry] = *sch
@@ -284,7 +296,7 @@ func UpdateRefWithSchema(sp *spec.Swagger, key string, sch *spec.Schema) error {
case []spec.Schema:
idx, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", pth, err)
+ return ErrNotANumber(pth, err)
}
container[idx] = *sch
@@ -292,7 +304,7 @@ func UpdateRefWithSchema(sp *spec.Swagger, key string, sch *spec.Schema) error {
// NOTE: this is necessarily an array - otherwise, the parent would be *Schema
idx, err := strconv.Atoi(entry)
if err != nil {
- return fmt.Errorf("%s not a number: %w", pth, err)
+ return ErrNotANumber(pth, err)
}
container.Schemas[idx] = *sch
@@ -302,7 +314,7 @@ func UpdateRefWithSchema(sp *spec.Swagger, key string, sch *spec.Schema) error {
// NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
default:
- return fmt.Errorf("unhandled type for parent of [%s]: %T", key, value)
+ return ErrUnhandledParentType(key, value)
}
case *spec.SchemaOrArray:
*refable.Schema = *sch
@@ -310,13 +322,13 @@ func UpdateRefWithSchema(sp *spec.Swagger, key string, sch *spec.Schema) error {
case *spec.SchemaOrBool:
*refable.Schema = *sch
default:
- return fmt.Errorf("no schema with ref found at %s for %T", key, value)
+ return ErrNoSchemaWithRef(key, value)
}
return nil
}
-// DeepestRefResult holds the results from DeepestRef analysis
+// DeepestRefResult holds the results from [DeepestRef] analysis.
type DeepestRefResult struct {
Ref spec.Ref
Schema *spec.Schema
@@ -324,10 +336,13 @@ type DeepestRefResult struct {
}
// DeepestRef finds the first definition ref, from a cascade of nested refs which are not definitions.
+//
// - if no definition is found, returns the deepest ref.
// - pointers to external files are expanded
//
// NOTE: all external $ref's are assumed to be already expanded at this stage.
+//
+//nolint:gocognit,gocyclo,cyclop // definitely needs a refactoring, in a follow-up PR
func DeepestRef(sp *spec.Swagger, opts *spec.ExpandOptions, ref spec.Ref) (*DeepestRefResult, error) {
if !ref.HasFragmentOnly {
// we found an external $ref, which is odd at this stage:
@@ -336,8 +351,8 @@ func DeepestRef(sp *spec.Swagger, opts *spec.ExpandOptions, ref spec.Ref) (*Deep
}
currentRef := ref
- visited := make(map[string]bool, 64)
- warnings := make([]string, 0, 2)
+ visited := make(map[string]bool, allocMediumMap)
+ warnings := make([]string, 0)
DOWNREF:
for currentRef.String() != "" {
@@ -347,8 +362,7 @@ DOWNREF:
}
if _, beenThere := visited[currentRef.String()]; beenThere {
- return nil,
- fmt.Errorf("cannot resolve cyclic chain of pointers under %s", currentRef.String())
+ return nil, ErrCyclicChain(currentRef.String())
}
visited[currentRef.String()] = true
@@ -385,15 +399,14 @@ DOWNREF:
case spec.Response:
// a pointer points to a schema initially marshalled in responses section...
// Attempt to convert this to a schema. If this fails, the spec is invalid
- asJSON, _ := refable.MarshalJSON()
+ asJSON, err := refable.MarshalJSON()
+ if err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
+ }
var asSchema spec.Schema
- err := asSchema.UnmarshalJSON(asJSON)
- if err != nil {
- return nil,
- fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T (%v)",
- currentRef.String(), value, err,
- )
+ if err = asSchema.UnmarshalJSON(asJSON); err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
}
warnings = append(warnings, fmt.Sprintf("found $ref %q (response) interpreted as schema", currentRef.String()))
@@ -405,13 +418,13 @@ DOWNREF:
case spec.Parameter:
// a pointer points to a schema initially marshalled in parameters section...
// Attempt to convert this to a schema. If this fails, the spec is invalid
- asJSON, _ := refable.MarshalJSON()
+ asJSON, err := refable.MarshalJSON()
+ if err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
+ }
var asSchema spec.Schema
- if err := asSchema.UnmarshalJSON(asJSON); err != nil {
- return nil,
- fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T (%v)",
- currentRef.String(), value, err,
- )
+ if err = asSchema.UnmarshalJSON(asJSON); err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
}
warnings = append(warnings, fmt.Sprintf("found $ref %q (parameter) interpreted as schema", currentRef.String()))
@@ -427,13 +440,13 @@ DOWNREF:
break DOWNREF
}
- asJSON, _ := json.Marshal(refable)
+ asJSON, err := json.Marshal(refable)
+ if err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
+ }
var asSchema spec.Schema
- if err := asSchema.UnmarshalJSON(asJSON); err != nil {
- return nil,
- fmt.Errorf("unhandled type to resolve JSON pointer %s. Expected a Schema, got: %T (%v)",
- currentRef.String(), value, err,
- )
+ if err = asSchema.UnmarshalJSON(asJSON); err != nil {
+ return nil, ErrInvalidPointerType(currentRef.String(), value, err)
}
warnings = append(warnings, fmt.Sprintf("found $ref %q (%T) interpreted as schema", currentRef.String(), refable))
@@ -451,7 +464,7 @@ DOWNREF:
}
if sch == nil {
- return nil, fmt.Errorf("no schema found at %s", currentRef.String())
+ return nil, ErrNoSchema(currentRef.String())
}
return &DeepestRefResult{Ref: currentRef, Schema: sch, Warnings: warnings}, nil
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/schutils/flatten_schema.go b/vendor/github.com/go-openapi/analysis/internal/flatten/schutils/flatten_schema.go
index 4590236e683c..59855ef0727e 100644
--- a/vendor/github.com/go-openapi/analysis/internal/flatten/schutils/flatten_schema.go
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/schutils/flatten_schema.go
@@ -1,29 +1,34 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
// Package schutils provides tools to save or clone a schema
// when flattening a spec.
package schutils
import (
"github.com/go-openapi/spec"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/jsonutils"
)
-// Save registers a schema as an entry in spec #/definitions
+const allocLargeMap = 150
+
+// Save registers a schema as an entry in spec #/definitions.
func Save(sp *spec.Swagger, name string, schema *spec.Schema) {
if schema == nil {
return
}
if sp.Definitions == nil {
- sp.Definitions = make(map[string]spec.Schema, 150)
+ sp.Definitions = make(map[string]spec.Schema, allocLargeMap)
}
sp.Definitions[name] = *schema
}
-// Clone deep-clones a schema
+// Clone deep-clones a schema.
func Clone(schema *spec.Schema) *spec.Schema {
var sch spec.Schema
- _ = swag.FromDynamicJSON(schema, &sch)
+ _ = jsonutils.FromDynamicJSON(schema, &sch)
return &sch
}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/keys.go b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/keys.go
index ac80fc2e8320..363bb19efaf6 100644
--- a/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/keys.go
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/keys.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package sortref
import (
@@ -17,12 +20,8 @@ const (
definitions = "definitions"
)
+//nolint:gochecknoglobals // it's okay to store small indexes like this as private globals
var (
- ignoredKeys map[string]struct{}
- validMethods map[string]struct{}
-)
-
-func init() {
ignoredKeys = map[string]struct{}{
"schema": {},
"properties": {},
@@ -40,15 +39,15 @@ func init() {
"PUT": {},
"DELETE": {},
}
-}
+)
-// Key represent a key item constructed from /-separated segments
+// Key represent a key item constructed from /-separated segments.
type Key struct {
Segments int
Key string
}
-// Keys is a sortable collable collection of Keys
+// Keys is a sortable collable collection of Keys.
type Keys []Key
func (k Keys) Len() int { return len(k) }
@@ -57,10 +56,10 @@ func (k Keys) Less(i, j int) bool {
return k[i].Segments > k[j].Segments || (k[i].Segments == k[j].Segments && k[i].Key < k[j].Key)
}
-// KeyParts construct a SplitKey with all its /-separated segments decomposed. It is sortable.
+// KeyParts construct a [SplitKey] with all its /-separated segments decomposed. It is sortable.
func KeyParts(key string) SplitKey {
var res []string
- for _, part := range strings.Split(key[1:], "/") {
+ for part := range strings.SplitSeq(key[1:], "/") {
if part != "" {
res = append(res, jsonpointer.Unescape(part))
}
@@ -72,12 +71,12 @@ func KeyParts(key string) SplitKey {
// SplitKey holds of the parts of a /-separated key, so that their location may be determined.
type SplitKey []string
-// IsDefinition is true when the split key is in the #/definitions section of a spec
+// IsDefinition is true when the split key is in the #/definitions section of a spec.
func (s SplitKey) IsDefinition() bool {
return len(s) > 1 && s[0] == definitions
}
-// DefinitionName yields the name of the definition
+// DefinitionName yields the name of the definition.
func (s SplitKey) DefinitionName() string {
if !s.IsDefinition() {
return ""
@@ -86,26 +85,10 @@ func (s SplitKey) DefinitionName() string {
return s[1]
}
-func (s SplitKey) isKeyName(i int) bool {
- if i <= 0 {
- return false
- }
-
- count := 0
- for idx := i - 1; idx > 0; idx-- {
- if s[idx] != "properties" {
- break
- }
- count++
- }
-
- return count%2 != 0
-}
-
-// PartAdder know how to construct the components of a new name
+// PartAdder know how to construct the components of a new name.
type PartAdder func(string) []string
-// BuildName builds a name from segments
+// BuildName builds a name from segments.
func (s SplitKey) BuildName(segments []string, startIndex int, adder PartAdder) string {
for i, part := range s[startIndex:] {
if _, ignored := ignoredKeys[part]; !ignored || s.isKeyName(startIndex+i) {
@@ -116,42 +99,42 @@ func (s SplitKey) BuildName(segments []string, startIndex int, adder PartAdder)
return strings.Join(segments, " ")
}
-// IsOperation is true when the split key is in the operations section
+// IsOperation is true when the split key is in the operations section.
func (s SplitKey) IsOperation() bool {
return len(s) > 1 && s[0] == paths
}
-// IsSharedOperationParam is true when the split key is in the parameters section of a path
+// IsSharedOperationParam is true when the split key is in the parameters section of a path.
func (s SplitKey) IsSharedOperationParam() bool {
return len(s) > 2 && s[0] == paths && s[2] == parameters
}
-// IsSharedParam is true when the split key is in the #/parameters section of a spec
+// IsSharedParam is true when the split key is in the #/parameters section of a spec.
func (s SplitKey) IsSharedParam() bool {
return len(s) > 1 && s[0] == parameters
}
-// IsOperationParam is true when the split key is in the parameters section of an operation
+// IsOperationParam is true when the split key is in the parameters section of an operation.
func (s SplitKey) IsOperationParam() bool {
return len(s) > 3 && s[0] == paths && s[3] == parameters
}
-// IsOperationResponse is true when the split key is in the responses section of an operation
+// IsOperationResponse is true when the split key is in the responses section of an operation.
func (s SplitKey) IsOperationResponse() bool {
return len(s) > 3 && s[0] == paths && s[3] == responses
}
-// IsSharedResponse is true when the split key is in the #/responses section of a spec
+// IsSharedResponse is true when the split key is in the #/responses section of a spec.
func (s SplitKey) IsSharedResponse() bool {
return len(s) > 1 && s[0] == responses
}
-// IsDefaultResponse is true when the split key is the default response for an operation
+// IsDefaultResponse is true when the split key is the default response for an operation.
func (s SplitKey) IsDefaultResponse() bool {
return len(s) > 4 && s[0] == paths && s[3] == responses && s[4] == "default"
}
-// IsStatusCodeResponse is true when the split key is an operation response with a status code
+// IsStatusCodeResponse is true when the split key is an operation response with a status code.
func (s SplitKey) IsStatusCodeResponse() bool {
isInt := func() bool {
_, err := strconv.Atoi(s[4])
@@ -162,7 +145,7 @@ func (s SplitKey) IsStatusCodeResponse() bool {
return len(s) > 4 && s[0] == paths && s[3] == responses && isInt()
}
-// ResponseName yields either the status code or "Default" for a response
+// ResponseName yields either the status code or "Default" for a response.
func (s SplitKey) ResponseName() string {
if s.IsStatusCodeResponse() {
code, _ := strconv.Atoi(s[4])
@@ -177,9 +160,10 @@ func (s SplitKey) ResponseName() string {
return ""
}
-// PathItemRef constructs a $ref object from a split key of the form /{path}/{method}
+// PathItemRef constructs a $ref object from a split key of the form /{path}/{method}.
func (s SplitKey) PathItemRef() spec.Ref {
- if len(s) < 3 {
+ const minValidPathItems = 3
+ if len(s) < minValidPathItems {
return spec.Ref{}
}
@@ -191,7 +175,7 @@ func (s SplitKey) PathItemRef() spec.Ref {
return spec.MustCreateRef("#" + path.Join("/", paths, jsonpointer.Escape(pth), strings.ToUpper(method)))
}
-// PathRef constructs a $ref object from a split key of the form /paths/{reference}
+// PathRef constructs a $ref object from a split key of the form /paths/{reference}.
func (s SplitKey) PathRef() spec.Ref {
if !s.IsOperation() {
return spec.Ref{}
@@ -199,3 +183,19 @@ func (s SplitKey) PathRef() spec.Ref {
return spec.MustCreateRef("#" + path.Join("/", paths, jsonpointer.Escape(s[1])))
}
+
+func (s SplitKey) isKeyName(i int) bool {
+ if i <= 0 {
+ return false
+ }
+
+ count := 0
+ for idx := i - 1; idx > 0; idx-- {
+ if s[idx] != "properties" {
+ break
+ }
+ count++
+ }
+
+ return count%2 != 0
+}
diff --git a/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/sort_ref.go b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/sort_ref.go
index 73243df87f03..e4ad07b09600 100644
--- a/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/sort_ref.go
+++ b/vendor/github.com/go-openapi/analysis/internal/flatten/sortref/sort_ref.go
@@ -1,7 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package sortref
import (
+ "iter"
"reflect"
+ "slices"
"sort"
"strings"
@@ -9,10 +14,6 @@ import (
"github.com/go-openapi/spec"
)
-var depthGroupOrder = []string{
- "sharedParam", "sharedResponse", "sharedOpParam", "opParam", "codeResponse", "defaultResponse", "definition",
-}
-
type mapIterator struct {
len int
mapIter *reflect.MapIter
@@ -30,7 +31,7 @@ func (i *mapIterator) Key() string {
return i.mapIter.Key().String()
}
-func mustMapIterator(anyMap interface{}) *mapIterator {
+func mustMapIterator(anyMap any) *mapIterator {
val := reflect.ValueOf(anyMap)
return &mapIterator{mapIter: val.MapRange(), len: val.Len()}
@@ -39,8 +40,8 @@ func mustMapIterator(anyMap interface{}) *mapIterator {
// DepthFirst sorts a map of anything. It groups keys by category
// (shared params, op param, statuscode response, default response, definitions)
// sort groups internally by number of parts in the key and lexical names
-// flatten groups into a single list of keys
-func DepthFirst(in interface{}) []string {
+// flatten groups into a single list of keys.
+func DepthFirst(in any) []string {
iterator := mustMapIterator(in)
sorted := make([]string, 0, iterator.Len())
grouped := make(map[string]Keys, iterator.Len())
@@ -74,7 +75,7 @@ func DepthFirst(in interface{}) []string {
grouped[pk] = append(grouped[pk], Key{Segments: len(split), Key: k})
}
- for _, pk := range depthGroupOrder {
+ for pk := range depthGroupOrder() {
res := grouped[pk]
sort.Sort(res)
@@ -86,6 +87,12 @@ func DepthFirst(in interface{}) []string {
return sorted
}
+func depthGroupOrder() iter.Seq[string] {
+ return slices.Values([]string{
+ "sharedParam", "sharedResponse", "sharedOpParam", "opParam", "codeResponse", "defaultResponse", "definition",
+ })
+}
+
// topMostRefs is able to sort refs by hierarchical then lexicographic order,
// yielding refs ordered breadth-first.
type topmostRefs []string
@@ -101,7 +108,7 @@ func (k topmostRefs) Less(i, j int) bool {
return li < lj
}
-// TopmostFirst sorts references by depth
+// TopmostFirst sorts references by depth.
func TopmostFirst(refs []string) []string {
res := topmostRefs(refs)
sort.Sort(res)
@@ -109,13 +116,13 @@ func TopmostFirst(refs []string) []string {
return res
}
-// RefRevIdx is a reverse index for references
+// RefRevIdx is a reverse index for references.
type RefRevIdx struct {
Ref spec.Ref
Keys []string
}
-// ReverseIndex builds a reverse index for references in schemas
+// ReverseIndex builds a reverse index for references in schemas.
func ReverseIndex(schemas map[string]spec.Ref, basePath string) map[string]RefRevIdx {
collected := make(map[string]RefRevIdx)
for key, schRef := range schemas {
diff --git a/vendor/github.com/go-openapi/analysis/mixin.go b/vendor/github.com/go-openapi/analysis/mixin.go
index 7785a29b27dd..a7a9306cb372 100644
--- a/vendor/github.com/go-openapi/analysis/mixin.go
+++ b/vendor/github.com/go-openapi/analysis/mixin.go
@@ -1,22 +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 analysis
import (
"fmt"
"reflect"
+ "slices"
"github.com/go-openapi/spec"
)
@@ -28,12 +18,13 @@ import (
// needed.
//
// The following parts of primary are subject to merge, filling empty details
+//
// - Info
// - BasePath
// - Host
// - ExternalDocs
//
-// Consider calling FixEmptyResponseDescriptions() on the modified primary
+// Consider calling [FixEmptyResponseDescriptions]() on the modified primary
// if you read them from storage and they are valid to start with.
//
// Entries in "paths", "definitions", "parameters" and "responses" are
@@ -49,7 +40,7 @@ import (
// etc). Ensure they are canonical if your downstream tools do
// key normalization of any form.
//
-// Merging schemes (http, https), and consumers/producers do not account for
+// Merging schemes ([http], https), and consumers/producers do not account for
// collisions.
func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string {
skipped := make([]string, 0, len(mixins))
@@ -248,14 +239,7 @@ func mergeResponses(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
func mergeConsumes(primary *spec.Swagger, m *spec.Swagger) []string {
for _, v := range m.Consumes {
- found := false
- for _, vv := range primary.Consumes {
- if v == vv {
- found = true
-
- break
- }
- }
+ found := slices.Contains(primary.Consumes, v)
if found {
// no warning here: we just skip it
@@ -269,14 +253,7 @@ func mergeConsumes(primary *spec.Swagger, m *spec.Swagger) []string {
func mergeProduces(primary *spec.Swagger, m *spec.Swagger) []string {
for _, v := range m.Produces {
- found := false
- for _, vv := range primary.Produces {
- if v == vv {
- found = true
-
- break
- }
- }
+ found := slices.Contains(primary.Produces, v)
if found {
// no warning here: we just skip it
@@ -317,14 +294,7 @@ func mergeTags(primary *spec.Swagger, m *spec.Swagger) (skipped []string) {
func mergeSchemes(primary *spec.Swagger, m *spec.Swagger) []string {
for _, v := range m.Schemes {
- found := false
- for _, vv := range primary.Schemes {
- if v == vv {
- found = true
-
- break
- }
- }
+ found := slices.Contains(primary.Schemes, v)
if found {
// no warning here: we just skip it
@@ -391,7 +361,7 @@ func mergeInfo(primary *spec.Info, m *spec.Info) []string {
}
if primary.Title == "" {
- primary.Description = m.Description
+ primary.Title = m.Title
}
if primary.TermsOfService == "" {
@@ -474,23 +444,23 @@ func initPrimary(primary *spec.Swagger) {
}
if primary.Security == nil {
- primary.Security = make([]map[string][]string, 0, 10)
+ primary.Security = make([]map[string][]string, 0, allocSmallMap)
}
if primary.Produces == nil {
- primary.Produces = make([]string, 0, 10)
+ primary.Produces = make([]string, 0, allocSmallMap)
}
if primary.Consumes == nil {
- primary.Consumes = make([]string, 0, 10)
+ primary.Consumes = make([]string, 0, allocSmallMap)
}
if primary.Tags == nil {
- primary.Tags = make([]spec.Tag, 0, 10)
+ primary.Tags = make([]spec.Tag, 0, allocSmallMap)
}
if primary.Schemes == nil {
- primary.Schemes = make([]string, 0, 10)
+ primary.Schemes = make([]string, 0, allocSmallMap)
}
if primary.Paths == nil {
diff --git a/vendor/github.com/go-openapi/analysis/schema.go b/vendor/github.com/go-openapi/analysis/schema.go
index ab190db5b785..bedea652acf0 100644
--- a/vendor/github.com/go-openapi/analysis/schema.go
+++ b/vendor/github.com/go-openapi/analysis/schema.go
@@ -1,16 +1,17 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package analysis
import (
- "errors"
-
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
)
-// SchemaOpts configures the schema analyzer
+// SchemaOpts configures the schema analyzer.
type SchemaOpts struct {
Schema *spec.Schema
- Root interface{}
+ Root any
BasePath string
_ struct{}
}
@@ -19,7 +20,7 @@ type SchemaOpts struct {
// patterns.
func Schema(opts SchemaOpts) (*AnalyzedSchema, error) {
if opts.Schema == nil {
- return nil, errors.New("no schema to analyze")
+ return nil, ErrNoSchema
}
a := &AnalyzedSchema{
@@ -51,10 +52,10 @@ func Schema(opts SchemaOpts) (*AnalyzedSchema, error) {
return a, nil
}
-// AnalyzedSchema indicates what the schema represents
+// AnalyzedSchema indicates what the schema represents.
type AnalyzedSchema struct {
schema *spec.Schema
- root interface{}
+ root any
basePath string
hasProps bool
@@ -77,7 +78,7 @@ type AnalyzedSchema struct {
IsEnum bool
}
-// Inherits copies value fields from other onto this schema
+// Inherits copies value fields from other onto this schema.
func (a *AnalyzedSchema) inherits(other *AnalyzedSchema) {
if other == nil {
return
diff --git a/vendor/github.com/go-openapi/errors/.editorconfig b/vendor/github.com/go-openapi/errors/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/errors/.gitignore b/vendor/github.com/go-openapi/errors/.gitignore
index dd91ed6a04e6..9364443a6f0a 100644
--- a/vendor/github.com/go-openapi/errors/.gitignore
+++ b/vendor/github.com/go-openapi/errors/.gitignore
@@ -1,2 +1,7 @@
-secrets.yml
-coverage.out
+*.out
+*.cov
+.idea
+.env
+.mcp.json
+.claude/
+settings.local.json
diff --git a/vendor/github.com/go-openapi/errors/.golangci.yml b/vendor/github.com/go-openapi/errors/.golangci.yml
index cf88ead324d9..e2c14be86d61 100644
--- a/vendor/github.com/go-openapi/errors/.golangci.yml
+++ b/vendor/github.com/go-openapi/errors/.golangci.yml
@@ -1,62 +1,71 @@
-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: 3
-
+version: "2"
linters:
- enable-all: true
+ default: all
disable:
- - errname # this repo doesn't follow the convention advised by this linter
- - maligned
- - unparam
- - lll
- - gochecknoinits
- - gochecknoglobals
+ - depguard
- funlen
- godox
- - gocognit
- - whitespace
- - wsl
- - wrapcheck
- - testpackage
+ - exhaustruct
- nlreturn
- - gomnd
- - exhaustivestruct
- - goerr113
- - errorlint
- - nestif
- - godot
- - gofumpt
+ - nonamedreturns
+ - noinlineerr
- paralleltest
- - tparallel
+ - recvcheck
+ - testpackage
- thelper
- - ifshort
- - exhaustruct
+ - tparallel
- varnamelen
- - gci
- - depguard
- - errchkjson
- - inamedparam
- - nonamedreturns
- - musttag
- - ireturn
- - forcetypeassert
- - cyclop
- # deprecated linters
- - deadcode
- - interfacer
- - scopelint
- - varcheck
- - structcheck
- - golint
- - nosnakecase
+ - 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
+ rules:
+ - linters:
+ - revive
+ text: "avoid package names that conflict with Go standard library package names"
+ 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/errors/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 100644
--- a/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md
+++ b/vendor/github.com/go-openapi/errors/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/errors/CONTRIBUTORS.md b/vendor/github.com/go-openapi/errors/CONTRIBUTORS.md
new file mode 100644
index 000000000000..d49e377a1356
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/CONTRIBUTORS.md
@@ -0,0 +1,25 @@
+# Contributors
+
+- Repository: ['go-openapi/errors']
+
+| Total Contributors | Total Contributions |
+| --- | --- |
+| 13 | 110 |
+
+| Username | All Time Contribution Count | All Commits |
+| --- | --- | --- |
+| @casualjim | 58 | |
+| @fredbi | 36 | |
+| @youyuanwu | 5 | |
+| @alexandear | 2 | |
+| @fiorix | 1 | |
+| @ligustah | 1 | |
+| @artemseleznev | 1 | |
+| @gautierdelorme | 1 | |
+| @guillemj | 1 | |
+| @maxatome | 1 | |
+| @Simon-Li | 1 | |
+| @aokumasan | 1 | |
+| @ujjwalsh | 1 | |
+
+ _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_
diff --git a/vendor/github.com/go-openapi/errors/README.md b/vendor/github.com/go-openapi/errors/README.md
index 6d57ea55c7c1..d9f4a3f15144 100644
--- a/vendor/github.com/go-openapi/errors/README.md
+++ b/vendor/github.com/go-openapi/errors/README.md
@@ -1,8 +1,118 @@
-# OpenAPI errors [](https://github.com/go-openapi/errors/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/errors)
+# errors
-[](https://slackin.goswagger.io)
-[](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE)
-[](https://pkg.go.dev/github.com/go-openapi/errors)
-[](https://goreportcard.com/report/github.com/go-openapi/errors)
+
+[![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]
+
+---
Shared errors and error interface used throughout the various libraries found in the go-openapi toolkit.
+
+## 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.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/errors
+```
+
+## Basic usage
+
+```go
+const url = "https://www.example.com/#"
+
+errGeneric := New(401,"onvalid argument: %s", url)
+
+errNotFound := NotFound("resource not found: %s", url)
+
+errNotImplemented := NotImplemented("method: %s", url)
+```
+
+## Change log
+
+See
+
+
+
+## Licensing
+
+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)
+
+## Cutting a new release
+
+Maintainers can cut a new release by either:
+
+* running [this workflow](https://github.com/go-openapi/errors/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/errors/actions/workflows/go-test.yml/badge.svg
+[test-url]: https://github.com/go-openapi/errors/actions/workflows/go-test.yml
+[cov-badge]: https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg
+[cov-url]: https://codecov.io/gh/go-openapi/errors
+[vuln-scan-badge]: https://github.com/go-openapi/errors/actions/workflows/scanner.yml/badge.svg
+[vuln-scan-url]: https://github.com/go-openapi/errors/actions/workflows/scanner.yml
+[codeql-badge]: https://github.com/go-openapi/errors/actions/workflows/codeql.yml/badge.svg
+[codeql-url]: https://github.com/go-openapi/errors/actions/workflows/codeql.yml
+
+[release-badge]: https://badge.fury.io/gh/go-openapi%2Ferrors.svg
+[release-url]: https://badge.fury.io/gh/go-openapi%2Ferrors
+
+[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/errors
+[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/errors
+[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/errors
+[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/errors
+
+[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/errors
+[godoc-url]: http://pkg.go.dev/github.com/go-openapi/errors
+[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
+
+
+[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
+[license-url]: https://github.com/go-openapi/errors/?tab=Apache-2.0-1-ov-file#readme
+
+[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/errors
+[goversion-url]: https://github.com/go-openapi/errors/blob/master/go.mod
+[top-badge]: https://img.shields.io/github/languages/top/go-openapi/errors
+[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/errors/latest
diff --git a/vendor/github.com/go-openapi/errors/SECURITY.md b/vendor/github.com/go-openapi/errors/SECURITY.md
new file mode 100644
index 000000000000..6ceb159ca229
--- /dev/null
+++ b/vendor/github.com/go-openapi/errors/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 |
+| ------- | ------------------ |
+| 0.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/errors/api.go b/vendor/github.com/go-openapi/errors/api.go
index 5320cb963044..d2b4427aac55 100644
--- a/vendor/github.com/go-openapi/errors/api.go
+++ b/vendor/github.com/go-openapi/errors/api.go
@@ -1,21 +1,11 @@
-// 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 errors
import (
"encoding/json"
+ "errors"
"fmt"
"net/http"
"reflect"
@@ -23,9 +13,11 @@ import (
)
// DefaultHTTPCode is used when the error Code cannot be used as an HTTP code.
+//
+//nolint:gochecknoglobals // it should have been a constant in the first place, but now it is mutable so we have to leave it here or introduce a breaking change.
var DefaultHTTPCode = http.StatusUnprocessableEntity
-// Error represents a error interface all swagger framework errors implement
+// Error represents a error interface all swagger framework errors implement.
type Error interface {
error
Code() int32
@@ -36,24 +28,26 @@ type apiError struct {
message string
}
+// Error implements the standard error interface.
func (a *apiError) Error() string {
return a.message
}
+// Code returns the HTTP status code associated with this error.
func (a *apiError) Code() int32 {
return a.code
}
-// MarshalJSON implements the JSON encoding interface
+// MarshalJSON implements the JSON encoding interface.
func (a apiError) MarshalJSON() ([]byte, error) {
- return json.Marshal(map[string]interface{}{
+ return json.Marshal(map[string]any{
"code": a.code,
"message": a.message,
})
}
-// New creates a new API error with a code and a message
-func New(code int32, message string, args ...interface{}) Error {
+// New creates a new API error with a code and a message.
+func New(code int32, message string, args ...any) Error {
if len(args) > 0 {
return &apiError{
code: code,
@@ -66,38 +60,39 @@ func New(code int32, message string, args ...interface{}) Error {
}
}
-// NotFound creates a new not found error
-func NotFound(message string, args ...interface{}) Error {
+// NotFound creates a new not found error.
+func NotFound(message string, args ...any) Error {
if message == "" {
message = "Not found"
}
- return New(http.StatusNotFound, fmt.Sprintf(message, args...))
+ return New(http.StatusNotFound, message, args...)
}
-// NotImplemented creates a new not implemented error
+// NotImplemented creates a new not implemented error.
func NotImplemented(message string) Error {
- return New(http.StatusNotImplemented, message)
+ return New(http.StatusNotImplemented, "%s", message)
}
-// MethodNotAllowedError represents an error for when the path matches but the method doesn't
+// MethodNotAllowedError represents an error for when the path matches but the method doesn't.
type MethodNotAllowedError struct {
code int32
Allowed []string
message string
}
+// Error implements the standard error interface.
func (m *MethodNotAllowedError) Error() string {
return m.message
}
-// Code the error code
+// Code returns 405 (Method Not Allowed) as the HTTP status code.
func (m *MethodNotAllowedError) Code() int32 {
return m.code
}
-// MarshalJSON implements the JSON encoding interface
+// MarshalJSON implements the JSON encoding interface.
func (m MethodNotAllowedError) MarshalJSON() ([]byte, error) {
- return json.Marshal(map[string]interface{}{
+ return json.Marshal(map[string]any{
"code": m.code,
"message": m.message,
"allowed": m.Allowed,
@@ -115,25 +110,33 @@ func errorAsJSON(err Error) []byte {
func flattenComposite(errs *CompositeError) *CompositeError {
var res []error
- for _, er := range errs.Errors {
- switch e := er.(type) {
- case *CompositeError:
- if e != nil && len(e.Errors) > 0 {
- flat := flattenComposite(e)
- if len(flat.Errors) > 0 {
- res = append(res, flat.Errors...)
- }
- }
- default:
- if e != nil {
- res = append(res, e)
- }
+
+ for _, err := range errs.Errors {
+ if err == nil {
+ continue
+ }
+
+ e := &CompositeError{}
+ if !errors.As(err, &e) {
+ res = append(res, err)
+
+ continue
}
+
+ if len(e.Errors) == 0 {
+ res = append(res, e)
+
+ continue
+ }
+
+ flat := flattenComposite(e)
+ res = append(res, flat.Errors...)
}
+
return CompositeValidationError(res...)
}
-// MethodNotAllowed creates a new method not allowed error
+// MethodNotAllowed creates a new method not allowed error.
func MethodNotAllowed(requested string, allow []string) Error {
msg := fmt.Sprintf("method %s is not allowed, but [%s] are", requested, strings.Join(allow, ","))
return &MethodNotAllowedError{
@@ -143,49 +146,65 @@ func MethodNotAllowed(requested string, allow []string) Error {
}
}
-// ServeError implements the http error handler interface
+// ServeError implements the [http] error handler interface.
func ServeError(rw http.ResponseWriter, r *http.Request, err error) {
rw.Header().Set("Content-Type", "application/json")
- switch e := err.(type) {
- case *CompositeError:
- er := flattenComposite(e)
+
+ if err == nil {
+ rw.WriteHeader(http.StatusInternalServerError)
+ _, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
+
+ return
+ }
+
+ errComposite := &CompositeError{}
+ errMethodNotAllowed := &MethodNotAllowedError{}
+ var errError Error
+
+ switch {
+ case errors.As(err, &errComposite):
+ er := flattenComposite(errComposite)
// strips composite errors to first element only
if len(er.Errors) > 0 {
ServeError(rw, r, er.Errors[0])
- } else {
- // guard against empty CompositeError (invalid construct)
- ServeError(rw, r, nil)
+
+ return
}
- case *MethodNotAllowedError:
- rw.Header().Add("Allow", strings.Join(e.Allowed, ","))
- rw.WriteHeader(asHTTPCode(int(e.Code())))
+
+ // guard against empty CompositeError (invalid construct)
+ ServeError(rw, r, nil)
+
+ case errors.As(err, &errMethodNotAllowed):
+ rw.Header().Add("Allow", strings.Join(errMethodNotAllowed.Allowed, ","))
+ rw.WriteHeader(asHTTPCode(int(errMethodNotAllowed.Code())))
if r == nil || r.Method != http.MethodHead {
- _, _ = rw.Write(errorAsJSON(e))
+ _, _ = rw.Write(errorAsJSON(errMethodNotAllowed))
}
- case Error:
- value := reflect.ValueOf(e)
+
+ case errors.As(err, &errError):
+ value := reflect.ValueOf(errError)
if value.Kind() == reflect.Ptr && value.IsNil() {
rw.WriteHeader(http.StatusInternalServerError)
_, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
+
return
}
- rw.WriteHeader(asHTTPCode(int(e.Code())))
+
+ rw.WriteHeader(asHTTPCode(int(errError.Code())))
if r == nil || r.Method != http.MethodHead {
- _, _ = rw.Write(errorAsJSON(e))
+ _, _ = rw.Write(errorAsJSON(errError))
}
- case nil:
- rw.WriteHeader(http.StatusInternalServerError)
- _, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
+
default:
rw.WriteHeader(http.StatusInternalServerError)
if r == nil || r.Method != http.MethodHead {
- _, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, err.Error())))
+ _, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "%v", err)))
}
}
}
func asHTTPCode(input int) int {
- if input >= 600 {
+ if input >= maximumValidHTTPCode {
return DefaultHTTPCode
}
return input
diff --git a/vendor/github.com/go-openapi/errors/auth.go b/vendor/github.com/go-openapi/errors/auth.go
index 0545b501bd7c..1173b5642cc6 100644
--- a/vendor/github.com/go-openapi/errors/auth.go
+++ b/vendor/github.com/go-openapi/errors/auth.go
@@ -1,22 +1,11 @@
-// 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 errors
import "net/http"
-// Unauthenticated returns an unauthenticated error
+// Unauthenticated returns an unauthenticated error.
func Unauthenticated(scheme string) Error {
return New(http.StatusUnauthorized, "unauthenticated for %s", scheme)
}
diff --git a/vendor/github.com/go-openapi/errors/doc.go b/vendor/github.com/go-openapi/errors/doc.go
index af01190ce610..208c740590e6 100644
--- a/vendor/github.com/go-openapi/errors/doc.go
+++ b/vendor/github.com/go-openapi/errors/doc.go
@@ -1,26 +1,13 @@
-// 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
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package errors provides an Error interface and several concrete types
+// implementing this interface to manage API errors and JSON-schema validation
+// errors.
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// A middleware handler [ServeError]() is provided to serve the errors types
+// it defines.
//
-// 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 errors provides an Error interface and several concrete types
-implementing this interface to manage API errors and JSON-schema validation
-errors.
-
-A middleware handler ServeError() is provided to serve the errors types
-it defines.
-
-It is used throughout the various go-openapi toolkit libraries
-(https://github.com/go-openapi).
-*/
+// It is used throughout the various go-openapi toolkit libraries.
+// (https://github.com/go-openapi).
package errors
diff --git a/vendor/github.com/go-openapi/errors/headers.go b/vendor/github.com/go-openapi/errors/headers.go
index dfebe8f95f08..717a51ac4344 100644
--- a/vendor/github.com/go-openapi/errors/headers.go
+++ b/vendor/github.com/go-openapi/errors/headers.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 errors
@@ -20,28 +9,30 @@ import (
"net/http"
)
-// Validation represents a failure of a precondition
-type Validation struct {
+// Validation represents a failure of a precondition.
+type Validation struct { //nolint: errname // changing the name to abide by the naming rule would bring a breaking change.
code int32
Name string
In string
- Value interface{}
+ Value any
message string
- Values []interface{}
+ Values []any
}
+// Error implements the standard error interface.
func (e *Validation) Error() string {
return e.message
}
-// Code the error code
+// Code returns the HTTP status code for this validation error.
+// Returns 422 (Unprocessable Entity) by default.
func (e *Validation) Code() int32 {
return e.code
}
-// MarshalJSON implements the JSON encoding interface
+// MarshalJSON implements the JSON encoding interface.
func (e Validation) MarshalJSON() ([]byte, error) {
- return json.Marshal(map[string]interface{}{
+ return json.Marshal(map[string]any{
"code": e.code,
"message": e.message,
"in": e.In,
@@ -51,7 +42,7 @@ func (e Validation) MarshalJSON() ([]byte, error) {
})
}
-// ValidateName sets the name for a validation or updates it for a nested property
+// ValidateName sets the name for a validation or updates it for a nested property.
func (e *Validation) ValidateName(name string) *Validation {
if name != "" {
if e.Name == "" {
@@ -70,9 +61,9 @@ const (
responseFormatFail = `unsupported media type requested, only %v are available`
)
-// InvalidContentType error for an invalid content type
+// InvalidContentType error for an invalid content type.
func InvalidContentType(value string, allowed []string) *Validation {
- values := make([]interface{}, 0, len(allowed))
+ values := make([]any, 0, len(allowed))
for _, v := range allowed {
values = append(values, v)
}
@@ -86,9 +77,9 @@ func InvalidContentType(value string, allowed []string) *Validation {
}
}
-// InvalidResponseFormat error for an unacceptable response format request
+// InvalidResponseFormat error for an unacceptable response format request.
func InvalidResponseFormat(value string, allowed []string) *Validation {
- values := make([]interface{}, 0, len(allowed))
+ values := make([]any, 0, len(allowed))
for _, v := range allowed {
values = append(values, v)
}
diff --git a/vendor/github.com/go-openapi/errors/middleware.go b/vendor/github.com/go-openapi/errors/middleware.go
index 963472d1f34b..f89275f9c1d1 100644
--- a/vendor/github.com/go-openapi/errors/middleware.go
+++ b/vendor/github.com/go-openapi/errors/middleware.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 errors
@@ -21,13 +10,14 @@ import (
)
// APIVerificationFailed is an error that contains all the missing info for a mismatched section
-// between the api registrations and the api spec
-type APIVerificationFailed struct {
+// between the api registrations and the api spec.
+type APIVerificationFailed struct { //nolint: errname
Section string `json:"section,omitempty"`
MissingSpecification []string `json:"missingSpecification,omitempty"`
MissingRegistration []string `json:"missingRegistration,omitempty"`
}
+// Error implements the standard error interface.
func (v *APIVerificationFailed) Error() string {
buf := bytes.NewBuffer(nil)
@@ -35,7 +25,7 @@ func (v *APIVerificationFailed) Error() string {
hasSpecMissing := len(v.MissingSpecification) > 0
if hasRegMissing {
- buf.WriteString(fmt.Sprintf("missing [%s] %s registrations", strings.Join(v.MissingRegistration, ", "), v.Section))
+ fmt.Fprintf(buf, "missing [%s] %s registrations", strings.Join(v.MissingRegistration, ", "), v.Section)
}
if hasRegMissing && hasSpecMissing {
@@ -43,7 +33,7 @@ func (v *APIVerificationFailed) Error() string {
}
if hasSpecMissing {
- buf.WriteString(fmt.Sprintf("missing from spec file [%s] %s", strings.Join(v.MissingSpecification, ", "), v.Section))
+ fmt.Fprintf(buf, "missing from spec file [%s] %s", strings.Join(v.MissingSpecification, ", "), v.Section)
}
return buf.String()
diff --git a/vendor/github.com/go-openapi/errors/parsing.go b/vendor/github.com/go-openapi/errors/parsing.go
index 5096e1ea7be5..46e6612cdfa7 100644
--- a/vendor/github.com/go-openapi/errors/parsing.go
+++ b/vendor/github.com/go-openapi/errors/parsing.go
@@ -1,25 +1,15 @@
-// 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 errors
import (
"encoding/json"
"fmt"
+ "net/http"
)
-// ParseError represents a parsing error
+// ParseError represents a parsing error.
type ParseError struct {
code int32
Name string
@@ -29,22 +19,41 @@ type ParseError struct {
message string
}
+// NewParseError creates a new parse error.
+func NewParseError(name, in, value string, reason error) *ParseError {
+ var msg string
+ if in == "" {
+ msg = fmt.Sprintf(parseErrorTemplContentNoIn, name, value, reason)
+ } else {
+ msg = fmt.Sprintf(parseErrorTemplContent, name, in, value, reason)
+ }
+ return &ParseError{
+ code: http.StatusBadRequest,
+ Name: name,
+ In: in,
+ Value: value,
+ Reason: reason,
+ message: msg,
+ }
+}
+
+// Error implements the standard error interface.
func (e *ParseError) Error() string {
return e.message
}
-// Code returns the http status code for this error
+// Code returns 400 (Bad Request) as the HTTP status code for parsing errors.
func (e *ParseError) Code() int32 {
return e.code
}
-// MarshalJSON implements the JSON encoding interface
+// MarshalJSON implements the JSON encoding interface.
func (e ParseError) MarshalJSON() ([]byte, error) {
var reason string
if e.Reason != nil {
reason = e.Reason.Error()
}
- return json.Marshal(map[string]interface{}{
+ return json.Marshal(map[string]any{
"code": e.code,
"message": e.message,
"in": e.In,
@@ -58,21 +67,3 @@ const (
parseErrorTemplContent = `parsing %s %s from %q failed, because %s`
parseErrorTemplContentNoIn = `parsing %s from %q failed, because %s`
)
-
-// NewParseError creates a new parse error
-func NewParseError(name, in, value string, reason error) *ParseError {
- var msg string
- if in == "" {
- msg = fmt.Sprintf(parseErrorTemplContentNoIn, name, value, reason)
- } else {
- msg = fmt.Sprintf(parseErrorTemplContent, name, in, value, reason)
- }
- return &ParseError{
- code: 400,
- Name: name,
- In: in,
- Value: value,
- Reason: reason,
- message: msg,
- }
-}
diff --git a/vendor/github.com/go-openapi/errors/schema.go b/vendor/github.com/go-openapi/errors/schema.go
index cf7ac2ed4da5..2378bae67f3c 100644
--- a/vendor/github.com/go-openapi/errors/schema.go
+++ b/vendor/github.com/go-openapi/errors/schema.go
@@ -1,22 +1,13 @@
-// 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 errors
import (
"encoding/json"
+ "errors"
"fmt"
+ "net/http"
"strings"
)
@@ -32,12 +23,12 @@ const (
patternFail = "%s in %s should match '%s'"
enumFail = "%s in %s should be one of %v"
multipleOfFail = "%s in %s should be a multiple of %v"
- maxIncFail = "%s in %s should be less than or equal to %v"
- maxExcFail = "%s in %s should be less than %v"
+ maximumIncFail = "%s in %s should be less than or equal to %v"
+ maximumExcFail = "%s in %s should be less than %v"
minIncFail = "%s in %s should be greater than or equal to %v"
minExcFail = "%s in %s should be greater than %v"
uniqueFail = "%s in %s shouldn't contain duplicates"
- maxItemsFail = "%s in %s should have at most %d items"
+ maximumItemsFail = "%s in %s should have at most %d items"
minItemsFail = "%s in %s should have at least %d items"
typeFailNoIn = "%s must be of type %s"
typeFailWithDataNoIn = "%s must be of type %s: %q"
@@ -49,12 +40,12 @@ const (
patternFailNoIn = "%s should match '%s'"
enumFailNoIn = "%s should be one of %v"
multipleOfFailNoIn = "%s should be a multiple of %v"
- maxIncFailNoIn = "%s should be less than or equal to %v"
- maxExcFailNoIn = "%s should be less than %v"
+ maximumIncFailNoIn = "%s should be less than or equal to %v"
+ maximumExcFailNoIn = "%s should be less than %v"
minIncFailNoIn = "%s should be greater than or equal to %v"
minExcFailNoIn = "%s should be greater than %v"
uniqueFailNoIn = "%s shouldn't contain duplicates"
- maxItemsFailNoIn = "%s should have at most %d items"
+ maximumItemsFailNoIn = "%s should have at most %d items"
minItemsFailNoIn = "%s should have at least %d items"
noAdditionalItems = "%s in %s can't have additional items"
noAdditionalItemsNoIn = "%s can't have additional items"
@@ -69,14 +60,18 @@ const (
multipleOfMustBePositive = "factor MultipleOf declared for %s must be positive: %v"
)
+const maximumValidHTTPCode = 600
+
// All code responses can be used to differentiate errors for different handling
-// by the consuming program
+// by the consuming program.
const (
// CompositeErrorCode remains 422 for backwards-compatibility
- // and to separate it from validation errors with cause
- CompositeErrorCode = 422
- // InvalidTypeCode is used for any subclass of invalid types
- InvalidTypeCode = 600 + iota
+ // and to separate it from validation errors with cause.
+ CompositeErrorCode = http.StatusUnprocessableEntity
+
+ // InvalidTypeCode is used for any subclass of invalid types.
+ InvalidTypeCode = maximumValidHTTPCode + iota
+ // RequiredFailCode indicates a required field is missing.
RequiredFailCode
TooLongFailCode
TooShortFailCode
@@ -97,22 +92,26 @@ const (
ReadOnlyFailCode
)
-// CompositeError is an error that groups several errors together
+// CompositeError is an error that groups several errors together.
type CompositeError struct {
Errors []error
code int32
message string
}
-// Code for this error
+// Code returns the HTTP status code for this composite error.
func (c *CompositeError) Code() int32 {
return c.code
}
+// Error implements the standard error interface.
func (c *CompositeError) Error() string {
if len(c.Errors) > 0 {
msgs := []string{c.message + ":"}
for _, e := range c.Errors {
+ if e == nil {
+ continue
+ }
msgs = append(msgs, e.Error())
}
return strings.Join(msgs, "\n")
@@ -120,20 +119,21 @@ func (c *CompositeError) Error() string {
return c.message
}
+// Unwrap implements the [errors.Unwrap] interface.
func (c *CompositeError) Unwrap() []error {
return c.Errors
}
-// MarshalJSON implements the JSON encoding interface
+// MarshalJSON implements the JSON encoding interface.
func (c CompositeError) MarshalJSON() ([]byte, error) {
- return json.Marshal(map[string]interface{}{
+ return json.Marshal(map[string]any{
"code": c.code,
"message": c.message,
"errors": c.Errors,
})
}
-// CompositeValidationError an error to wrap a bunch of other errors
+// CompositeValidationError an error to wrap a bunch of other errors.
func CompositeValidationError(errors ...error) *CompositeError {
return &CompositeError{
code: CompositeErrorCode,
@@ -142,20 +142,33 @@ func CompositeValidationError(errors ...error) *CompositeError {
}
}
-// ValidateName recursively sets the name for all validations or updates them for nested properties
+// ValidateName recursively sets the name for all validations or updates them for nested properties.
func (c *CompositeError) ValidateName(name string) *CompositeError {
for i, e := range c.Errors {
- if ve, ok := e.(*Validation); ok {
- c.Errors[i] = ve.ValidateName(name)
- } else if ce, ok := e.(*CompositeError); ok {
+ if e == nil {
+ continue
+ }
+
+ ce := &CompositeError{}
+ if errors.As(e, &ce) {
c.Errors[i] = ce.ValidateName(name)
+
+ continue
}
+
+ ve := &Validation{}
+ if errors.As(e, &ve) {
+ c.Errors[i] = ve.ValidateName(name)
+
+ continue
+ }
+
}
return c
}
-// FailedAllPatternProperties an error for when the property doesn't match a pattern
+// FailedAllPatternProperties an error for when the property doesn't match a pattern.
func FailedAllPatternProperties(name, in, key string) *Validation {
msg := fmt.Sprintf(failedAllPatternProps, name, key, in)
if in == "" {
@@ -170,7 +183,7 @@ func FailedAllPatternProperties(name, in, key string) *Validation {
}
}
-// PropertyNotAllowed an error for when the property doesn't match a pattern
+// PropertyNotAllowed an error for when the property doesn't match a pattern.
func PropertyNotAllowed(name, in, key string) *Validation {
msg := fmt.Sprintf(unallowedProperty, name, key, in)
if in == "" {
@@ -185,7 +198,7 @@ func PropertyNotAllowed(name, in, key string) *Validation {
}
}
-// TooFewProperties an error for an object with too few properties
+// TooFewProperties an error for an object with too few properties.
func TooFewProperties(name, in string, n int64) *Validation {
msg := fmt.Sprintf(tooFewProperties, name, in, n)
if in == "" {
@@ -200,7 +213,7 @@ func TooFewProperties(name, in string, n int64) *Validation {
}
}
-// TooManyProperties an error for an object with too many properties
+// TooManyProperties an error for an object with too many properties.
func TooManyProperties(name, in string, n int64) *Validation {
msg := fmt.Sprintf(tooManyProperties, name, in, n)
if in == "" {
@@ -215,7 +228,7 @@ func TooManyProperties(name, in string, n int64) *Validation {
}
}
-// AdditionalItemsNotAllowed an error for invalid additional items
+// AdditionalItemsNotAllowed an error for invalid additional items.
func AdditionalItemsNotAllowed(name, in string) *Validation {
msg := fmt.Sprintf(noAdditionalItems, name, in)
if in == "" {
@@ -229,7 +242,7 @@ func AdditionalItemsNotAllowed(name, in string) *Validation {
}
}
-// InvalidCollectionFormat another flavor of invalid type error
+// InvalidCollectionFormat another flavor of invalid type error.
func InvalidCollectionFormat(name, in, format string) *Validation {
return &Validation{
code: InvalidTypeCode,
@@ -240,7 +253,7 @@ func InvalidCollectionFormat(name, in, format string) *Validation {
}
}
-// InvalidTypeName an error for when the type is invalid
+// InvalidTypeName an error for when the type is invalid.
func InvalidTypeName(typeName string) *Validation {
return &Validation{
code: InvalidTypeCode,
@@ -249,8 +262,8 @@ func InvalidTypeName(typeName string) *Validation {
}
}
-// InvalidType creates an error for when the type is invalid
-func InvalidType(name, in, typeName string, value interface{}) *Validation {
+// InvalidType creates an error for when the type is invalid.
+func InvalidType(name, in, typeName string, value any) *Validation {
var message string
if in != "" {
@@ -280,10 +293,9 @@ func InvalidType(name, in, typeName string, value interface{}) *Validation {
Value: value,
message: message,
}
-
}
-// DuplicateItems error for when an array contains duplicates
+// DuplicateItems error for when an array contains duplicates.
func DuplicateItems(name, in string) *Validation {
msg := fmt.Sprintf(uniqueFail, name, in)
if in == "" {
@@ -297,11 +309,11 @@ func DuplicateItems(name, in string) *Validation {
}
}
-// TooManyItems error for when an array contains too many items
-func TooManyItems(name, in string, max int64, value interface{}) *Validation {
- msg := fmt.Sprintf(maxItemsFail, name, in, max)
+// TooManyItems error for when an array contains too many items.
+func TooManyItems(name, in string, maximum int64, value any) *Validation {
+ msg := fmt.Sprintf(maximumItemsFail, name, in, maximum)
if in == "" {
- msg = fmt.Sprintf(maxItemsFailNoIn, name, max)
+ msg = fmt.Sprintf(maximumItemsFailNoIn, name, maximum)
}
return &Validation{
@@ -313,11 +325,11 @@ func TooManyItems(name, in string, max int64, value interface{}) *Validation {
}
}
-// TooFewItems error for when an array contains too few items
-func TooFewItems(name, in string, min int64, value interface{}) *Validation {
- msg := fmt.Sprintf(minItemsFail, name, in, min)
+// TooFewItems error for when an array contains too few items.
+func TooFewItems(name, in string, minimum int64, value any) *Validation {
+ msg := fmt.Sprintf(minItemsFail, name, in, minimum)
if in == "" {
- msg = fmt.Sprintf(minItemsFailNoIn, name, min)
+ msg = fmt.Sprintf(minItemsFailNoIn, name, minimum)
}
return &Validation{
code: MinItemsFailCode,
@@ -328,21 +340,21 @@ func TooFewItems(name, in string, min int64, value interface{}) *Validation {
}
}
-// ExceedsMaximumInt error for when maximum validation fails
-func ExceedsMaximumInt(name, in string, max int64, exclusive bool, value interface{}) *Validation {
+// ExceedsMaximumInt error for when maximum validation fails.
+func ExceedsMaximumInt(name, in string, maximum int64, exclusive bool, value any) *Validation {
var message string
if in == "" {
- m := maxIncFailNoIn
+ m := maximumIncFailNoIn
if exclusive {
- m = maxExcFailNoIn
+ m = maximumExcFailNoIn
}
- message = fmt.Sprintf(m, name, max)
+ message = fmt.Sprintf(m, name, maximum)
} else {
- m := maxIncFail
+ m := maximumIncFail
if exclusive {
- m = maxExcFail
+ m = maximumExcFail
}
- message = fmt.Sprintf(m, name, in, max)
+ message = fmt.Sprintf(m, name, in, maximum)
}
return &Validation{
code: MaxFailCode,
@@ -353,21 +365,21 @@ func ExceedsMaximumInt(name, in string, max int64, exclusive bool, value interfa
}
}
-// ExceedsMaximumUint error for when maximum validation fails
-func ExceedsMaximumUint(name, in string, max uint64, exclusive bool, value interface{}) *Validation {
+// ExceedsMaximumUint error for when maximum validation fails.
+func ExceedsMaximumUint(name, in string, maximum uint64, exclusive bool, value any) *Validation {
var message string
if in == "" {
- m := maxIncFailNoIn
+ m := maximumIncFailNoIn
if exclusive {
- m = maxExcFailNoIn
+ m = maximumExcFailNoIn
}
- message = fmt.Sprintf(m, name, max)
+ message = fmt.Sprintf(m, name, maximum)
} else {
- m := maxIncFail
+ m := maximumIncFail
if exclusive {
- m = maxExcFail
+ m = maximumExcFail
}
- message = fmt.Sprintf(m, name, in, max)
+ message = fmt.Sprintf(m, name, in, maximum)
}
return &Validation{
code: MaxFailCode,
@@ -378,21 +390,21 @@ func ExceedsMaximumUint(name, in string, max uint64, exclusive bool, value inter
}
}
-// ExceedsMaximum error for when maximum validation fails
-func ExceedsMaximum(name, in string, max float64, exclusive bool, value interface{}) *Validation {
+// ExceedsMaximum error for when maximum validation fails.
+func ExceedsMaximum(name, in string, maximum float64, exclusive bool, value any) *Validation {
var message string
if in == "" {
- m := maxIncFailNoIn
+ m := maximumIncFailNoIn
if exclusive {
- m = maxExcFailNoIn
+ m = maximumExcFailNoIn
}
- message = fmt.Sprintf(m, name, max)
+ message = fmt.Sprintf(m, name, maximum)
} else {
- m := maxIncFail
+ m := maximumIncFail
if exclusive {
- m = maxExcFail
+ m = maximumExcFail
}
- message = fmt.Sprintf(m, name, in, max)
+ message = fmt.Sprintf(m, name, in, maximum)
}
return &Validation{
code: MaxFailCode,
@@ -403,21 +415,21 @@ func ExceedsMaximum(name, in string, max float64, exclusive bool, value interfac
}
}
-// ExceedsMinimumInt error for when minimum validation fails
-func ExceedsMinimumInt(name, in string, min int64, exclusive bool, value interface{}) *Validation {
+// ExceedsMinimumInt error for when minimum validation fails.
+func ExceedsMinimumInt(name, in string, minimum int64, exclusive bool, value any) *Validation {
var message string
if in == "" {
m := minIncFailNoIn
if exclusive {
m = minExcFailNoIn
}
- message = fmt.Sprintf(m, name, min)
+ message = fmt.Sprintf(m, name, minimum)
} else {
m := minIncFail
if exclusive {
m = minExcFail
}
- message = fmt.Sprintf(m, name, in, min)
+ message = fmt.Sprintf(m, name, in, minimum)
}
return &Validation{
code: MinFailCode,
@@ -428,21 +440,21 @@ func ExceedsMinimumInt(name, in string, min int64, exclusive bool, value interfa
}
}
-// ExceedsMinimumUint error for when minimum validation fails
-func ExceedsMinimumUint(name, in string, min uint64, exclusive bool, value interface{}) *Validation {
+// ExceedsMinimumUint error for when minimum validation fails.
+func ExceedsMinimumUint(name, in string, minimum uint64, exclusive bool, value any) *Validation {
var message string
if in == "" {
m := minIncFailNoIn
if exclusive {
m = minExcFailNoIn
}
- message = fmt.Sprintf(m, name, min)
+ message = fmt.Sprintf(m, name, minimum)
} else {
m := minIncFail
if exclusive {
m = minExcFail
}
- message = fmt.Sprintf(m, name, in, min)
+ message = fmt.Sprintf(m, name, in, minimum)
}
return &Validation{
code: MinFailCode,
@@ -453,21 +465,21 @@ func ExceedsMinimumUint(name, in string, min uint64, exclusive bool, value inter
}
}
-// ExceedsMinimum error for when minimum validation fails
-func ExceedsMinimum(name, in string, min float64, exclusive bool, value interface{}) *Validation {
+// ExceedsMinimum error for when minimum validation fails.
+func ExceedsMinimum(name, in string, minimum float64, exclusive bool, value any) *Validation {
var message string
if in == "" {
m := minIncFailNoIn
if exclusive {
m = minExcFailNoIn
}
- message = fmt.Sprintf(m, name, min)
+ message = fmt.Sprintf(m, name, minimum)
} else {
m := minIncFail
if exclusive {
m = minExcFail
}
- message = fmt.Sprintf(m, name, in, min)
+ message = fmt.Sprintf(m, name, in, minimum)
}
return &Validation{
code: MinFailCode,
@@ -478,8 +490,8 @@ func ExceedsMinimum(name, in string, min float64, exclusive bool, value interfac
}
}
-// NotMultipleOf error for when multiple of validation fails
-func NotMultipleOf(name, in string, multiple, value interface{}) *Validation {
+// NotMultipleOf error for when multiple of validation fails.
+func NotMultipleOf(name, in string, multiple, value any) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(multipleOfFailNoIn, name, multiple)
@@ -495,8 +507,8 @@ func NotMultipleOf(name, in string, multiple, value interface{}) *Validation {
}
}
-// EnumFail error for when an enum validation fails
-func EnumFail(name, in string, value interface{}, values []interface{}) *Validation {
+// EnumFail error for when an enum validation fails.
+func EnumFail(name, in string, value any, values []any) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(enumFailNoIn, name, values)
@@ -514,8 +526,8 @@ func EnumFail(name, in string, value interface{}, values []interface{}) *Validat
}
}
-// Required error for when a value is missing
-func Required(name, in string, value interface{}) *Validation {
+// Required error for when a value is missing.
+func Required(name, in string, value any) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(requiredFailNoIn, name)
@@ -531,8 +543,8 @@ func Required(name, in string, value interface{}) *Validation {
}
}
-// ReadOnly error for when a value is present in request
-func ReadOnly(name, in string, value interface{}) *Validation {
+// ReadOnly error for when a value is present in request.
+func ReadOnly(name, in string, value any) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(readOnlyFailNoIn, name)
@@ -548,13 +560,13 @@ func ReadOnly(name, in string, value interface{}) *Validation {
}
}
-// TooLong error for when a string is too long
-func TooLong(name, in string, max int64, value interface{}) *Validation {
+// TooLong error for when a string is too long.
+func TooLong(name, in string, maximum int64, value any) *Validation {
var msg string
if in == "" {
- msg = fmt.Sprintf(tooLongMessageNoIn, name, max)
+ msg = fmt.Sprintf(tooLongMessageNoIn, name, maximum)
} else {
- msg = fmt.Sprintf(tooLongMessage, name, in, max)
+ msg = fmt.Sprintf(tooLongMessage, name, in, maximum)
}
return &Validation{
code: TooLongFailCode,
@@ -565,13 +577,13 @@ func TooLong(name, in string, max int64, value interface{}) *Validation {
}
}
-// TooShort error for when a string is too short
-func TooShort(name, in string, min int64, value interface{}) *Validation {
+// TooShort error for when a string is too short.
+func TooShort(name, in string, minimum int64, value any) *Validation {
var msg string
if in == "" {
- msg = fmt.Sprintf(tooShortMessageNoIn, name, min)
+ msg = fmt.Sprintf(tooShortMessageNoIn, name, minimum)
} else {
- msg = fmt.Sprintf(tooShortMessage, name, in, min)
+ msg = fmt.Sprintf(tooShortMessage, name, in, minimum)
}
return &Validation{
@@ -585,7 +597,7 @@ func TooShort(name, in string, min int64, value interface{}) *Validation {
// FailedPattern error for when a string fails a regex pattern match
// the pattern that is returned is the ECMA syntax version of the pattern not the golang version.
-func FailedPattern(name, in, pattern string, value interface{}) *Validation {
+func FailedPattern(name, in, pattern string, value any) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(patternFailNoIn, name, pattern)
@@ -603,8 +615,8 @@ func FailedPattern(name, in, pattern string, value interface{}) *Validation {
}
// MultipleOfMustBePositive error for when a
-// multipleOf factor is negative
-func MultipleOfMustBePositive(name, in string, factor interface{}) *Validation {
+// multipleOf factor is negative.
+func MultipleOfMustBePositive(name, in string, factor any) *Validation {
return &Validation{
code: MultipleOfMustBePositiveCode,
Name: name,
diff --git a/vendor/github.com/go-openapi/jsonpointer/.cliff.toml b/vendor/github.com/go-openapi/jsonpointer/.cliff.toml
new file mode 100644
index 000000000000..702629f5dc30
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/.cliff.toml
@@ -0,0 +1,181 @@
+# 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 769c244007b5..885dc27ab0bc 100644
--- a/vendor/github.com/go-openapi/jsonpointer/.gitignore
+++ b/vendor/github.com/go-openapi/jsonpointer/.gitignore
@@ -1 +1,6 @@
-secrets.yml
+*.out
+*.cov
+.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 22f8d21cca19..dc7c96053de0 100644
--- a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml
+++ b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml
@@ -1,61 +1,67 @@
-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: 3
-
+version: "2"
linters:
- enable-all: true
+ default: all
disable:
- - maligned
- - unparam
- - lll
- - gochecknoinits
- - gochecknoglobals
+ - depguard
- funlen
- godox
- - gocognit
- - whitespace
- - wsl
- - wrapcheck
- - testpackage
+ - exhaustruct
- nlreturn
- - gomnd
- - exhaustivestruct
- - goerr113
- - errorlint
- - nestif
- - godot
- - gofumpt
+ - nonamedreturns
+ - noinlineerr
- paralleltest
- - tparallel
+ - recvcheck
+ - testpackage
- thelper
- - ifshort
- - exhaustruct
+ - tparallel
- varnamelen
- - gci
- - depguard
- - errchkjson
- - inamedparam
- - nonamedreturns
- - musttag
- - ireturn
- - forcetypeassert
- - cyclop
- # deprecated linters
- - deadcode
- - interfacer
- - scopelint
- - varcheck
- - structcheck
- - golint
- - nosnakecase
+ - 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/jsonpointer/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 100644
--- a/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md
+++ b/vendor/github.com/go-openapi/jsonpointer/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/jsonpointer/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md
new file mode 100644
index 000000000000..2ebebedc150f
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md
@@ -0,0 +1,24 @@
+# Contributors
+
+- Repository: ['go-openapi/jsonpointer']
+
+| Total Contributors | Total Contributions |
+| --- | --- |
+| 12 | 101 |
+
+| Username | All Time Contribution Count | All Commits |
+| --- | --- | --- |
+| @fredbi | 54 | |
+| @casualjim | 33 | |
+| @magodo | 3 | |
+| @youyuanwu | 3 | |
+| @gaiaz-iusipov | 1 | |
+| @gbjk | 1 | |
+| @gordallott | 1 | |
+| @ianlancetaylor | 1 | |
+| @mfleader | 1 | |
+| @Neo2308 | 1 | |
+| @olivierlemasle | 1 | |
+| @testwill | 1 | |
+
+ _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_
diff --git a/vendor/github.com/go-openapi/jsonpointer/LICENSE b/vendor/github.com/go-openapi/jsonpointer/LICENSE
index d64569567334..261eeb9e9f8b 100644
--- a/vendor/github.com/go-openapi/jsonpointer/LICENSE
+++ b/vendor/github.com/go-openapi/jsonpointer/LICENSE
@@ -1,4 +1,3 @@
-
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
diff --git a/vendor/github.com/go-openapi/jsonpointer/NOTICE b/vendor/github.com/go-openapi/jsonpointer/NOTICE
new file mode 100644
index 000000000000..f3b51939a95b
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/NOTICE
@@ -0,0 +1,39 @@
+Copyright 2015-2025 go-swagger maintainers
+
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+This software library, github.com/go-openapi/jsonpointer, includes software developed
+by the go-swagger and go-openapi maintainers ("go-swagger maintainers").
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software except in compliance with the License.
+
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0.
+
+This software is copied from, derived from, and inspired by other original software products.
+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
+===========================
+
+// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
+// SPDX-License-Identifier: Apache-2.0
+
+Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
+
+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/jsonpointer/README.md b/vendor/github.com/go-openapi/jsonpointer/README.md
index 0108f1d572d7..c52803e2e8f9 100644
--- a/vendor/github.com/go-openapi/jsonpointer/README.md
+++ b/vendor/github.com/go-openapi/jsonpointer/README.md
@@ -1,19 +1,158 @@
-# gojsonpointer [](https://github.com/go-openapi/jsonpointer/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/jsonpointer)
+# jsonpointer
-[](https://slackin.goswagger.io)
-[](https://raw.githubusercontent.com/go-openapi/jsonpointer/master/LICENSE)
-[](https://pkg.go.dev/github.com/go-openapi/jsonpointer)
-[](https://goreportcard.com/report/github.com/go-openapi/jsonpointer)
+
+[![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]
-An implementation of JSON Pointer - Go language
+---
+
+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]
## Status
-Completed YES
-Tested YES
+API is stable.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/jsonpointer
+```
+
+## Basic usage
+
+See also some [examples](./examples_test.go)
+
+### Retrieving a value
+
+```go
+ import (
+ "github.com/go-openapi/jsonpointer"
+ )
+
+
+ var doc any
+
+ ...
+
+ pointer, err := jsonpointer.New("/foo/1")
+ if err != nil {
+ ... // error: e.g. invalid JSON pointer specification
+ }
+
+ value, kind, err := pointer.Get(doc)
+ if err != nil {
+ ... // error: e.g. key not found, index out of bounds, etc.
+ }
+
+ ...
+```
+
+### Setting a value
+
+```go
+ ...
+ var doc any
+ ...
+ pointer, err := jsonpointer.New("/foo/1")
+ if err != nil {
+ ... // error: e.g. invalid JSON pointer specification
+ }
+
+ doc, err = p.Set(doc, "value")
+ if err != nil {
+ ... // error: e.g. key not found, index out of bounds, etc.
+ }
+```
+
+## Change log
+
+See
## References
-http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
-### Note
-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.
+
+
+also known as [RFC6901](https://www.rfc-editor.org/rfc/rfc6901)
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
+
+See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software
+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.
+
+## Other documentation
+
+* [All-time contributors](./CONTRIBUTORS.md)
+* [Contributing guidelines](.github/CONTRIBUTING.md)
+* [Maintainers documentation](docs/MAINTAINERS.md)
+* [Code style](docs/STYLE.md)
+
+## Cutting a new release
+
+Maintainers can cut a new release by either:
+
+* running [this workflow](https://github.com/go-openapi/jsonpointer/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/jsonpointer/actions/workflows/go-test.yml/badge.svg
+[test-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml
+[cov-badge]: https://codecov.io/gh/go-openapi/jsonpointer/branch/master/graph/badge.svg
+[cov-url]: https://codecov.io/gh/go-openapi/jsonpointer
+[vuln-scan-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/scanner.yml/badge.svg
+[vuln-scan-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/scanner.yml
+[codeql-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/codeql.yml/badge.svg
+[codeql-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/codeql.yml
+
+[release-badge]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer.svg
+[release-url]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer
+
+[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/jsonpointer
+[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonpointer
+[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/jsonpointer
+[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonpointer
+
+[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
+
+
+[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
+[license-url]: https://github.com/go-openapi/jsonpointer/?tab=Apache-2.0-1-ov-file#readme
+
+[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/jsonpointer
+[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
diff --git a/vendor/github.com/go-openapi/jsonpointer/SECURITY.md b/vendor/github.com/go-openapi/jsonpointer/SECURITY.md
new file mode 100644
index 000000000000..1fea2c5736a5
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/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/jsonpointer/errors.go b/vendor/github.com/go-openapi/jsonpointer/errors.go
new file mode 100644
index 000000000000..8c50dde8bcf3
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonpointer/errors.go
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package jsonpointer
+
+import "fmt"
+
+type pointerError string
+
+func (e pointerError) Error() string {
+ return string(e)
+}
+
+const (
+ // ErrPointer is a sentinel error raised by all errors from this package.
+ 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
+
+ // 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"
+)
+
+func errNoKey(key string) error {
+ return fmt.Errorf("object has no key %q: %w", key, ErrPointer)
+}
+
+func errOutOfBounds(length, idx int) error {
+ return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", length-1, idx, ErrPointer)
+}
+
+func errInvalidReference(token string) error {
+ return fmt.Errorf("invalid token reference %q: %w", token, ErrPointer)
+}
diff --git a/vendor/github.com/go-openapi/jsonpointer/pointer.go b/vendor/github.com/go-openapi/jsonpointer/pointer.go
index d970c7cf448e..7df49af3b96a 100644
--- a/vendor/github.com/go-openapi/jsonpointer/pointer.go
+++ b/vendor/github.com/go-openapi/jsonpointer/pointer.go
@@ -1,28 +1,7 @@
-// Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
-//
-// 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.
-
-// author sigu-399
-// author-github https://github.com/sigu-399
-// author-mail sigu.399@gmail.com
-//
-// repository-name jsonpointer
-// repository-desc An implementation of JSON Pointer - Go language
-//
-// description Main and unique file.
-//
-// created 25-02-2013
+// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+// Package jsonpointer provides a golang implementation for json pointers.
package jsonpointer
import (
@@ -33,81 +12,281 @@ import (
"strconv"
"strings"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/jsonname"
)
const (
emptyPointer = ``
pointerSeparator = `/`
-
- invalidStart = `JSON pointer must be empty or start with a "` + pointerSeparator
- notFound = `Can't find the pointer in the document`
)
-var jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem()
-var jsonSetableType = reflect.TypeOf(new(JSONSetable)).Elem()
-
-// JSONPointable is an interface for structs to implement when they need to customize the
-// json pointer process
+// 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(string) (any, error)
+ // 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
+// 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(string, any) error
+ // JSONSet sets the value pointed at the (unescaped) key.
+ JSONSet(key string, value any) error
}
-// New creates a new json pointer for the given string
-func New(jsonPointerString string) (Pointer, error) {
+// Pointer is a representation of a json pointer.
+//
+// Use [Pointer.Get] to retrieve a value or [Pointer.Set] to set a value.
+//
+// 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]
+// - 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
+// - promoted fields from an embedded struct are traversed
+// - scalars (e.g. int, float64 ...), channels, functions and go arrays cannot be traversed
+//
+// 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.
+//
+// # Limitations
+//
+// - Unlike go standard marshaling, untagged fields do not default to the go field name and are ignored.
+// - anonymous fields are not traversed if untagged
+type Pointer struct {
+ referenceTokens []string
+}
+// New creates a new json pointer from its string representation.
+func New(jsonPointerString string) (Pointer, error) {
var p Pointer
err := p.parse(jsonPointerString)
+
return p, err
+}
+// 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)
}
-// Pointer the json pointer reprsentation
-type Pointer struct {
- referenceTokens []string
+// Set uses the pointer to set a value from a data type
+// that represent a JSON document.
+//
+// It returns the updated document.
+func (p *Pointer) Set(document any, value any) (any, error) {
+ return document, p.set(document, value, jsonname.DefaultJSONNameProvider)
}
-// "Constructor", parses the given string JSON pointer
-func (p *Pointer) parse(jsonPointerString string) error {
+// DecodedTokens returns the decoded (unescaped) tokens of this JSON pointer.
+func (p *Pointer) DecodedTokens() []string {
+ result := make([]string, 0, len(p.referenceTokens))
+ for _, token := range p.referenceTokens {
+ result = append(result, Unescape(token))
+ }
- var err error
+ return result
+}
- if jsonPointerString != emptyPointer {
- if !strings.HasPrefix(jsonPointerString, pointerSeparator) {
- err = errors.New(invalidStart)
- } else {
- referenceTokens := strings.Split(jsonPointerString, pointerSeparator)
- p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...)
- }
+// IsEmpty returns true if this is an empty json pointer.
+//
+// This indicates that it points to the root document.
+func (p *Pointer) IsEmpty() bool {
+ return len(p.referenceTokens) == 0
+}
+
+// String representation of a pointer.
+func (p *Pointer) String() string {
+ if len(p.referenceTokens) == 0 {
+ return emptyPointer
}
- return err
+ return pointerSeparator + strings.Join(p.referenceTokens, pointerSeparator)
}
-// Get uses the pointer to retrieve a value from a JSON document
-func (p *Pointer) Get(document any) (any, reflect.Kind, error) {
- return p.get(document, swag.DefaultJSONNameProvider)
+func (p *Pointer) Offset(document string) (int64, error) {
+ dec := json.NewDecoder(strings.NewReader(document))
+ var offset int64
+ for _, ttk := range p.DecodedTokens() {
+ tk, err := dec.Token()
+ if err != nil {
+ return 0, err
+ }
+ switch tk := tk.(type) {
+ case json.Delim:
+ switch tk {
+ case '{':
+ offset, err = offsetSingleObject(dec, ttk)
+ if err != nil {
+ return 0, err
+ }
+ case '[':
+ offset, err = offsetSingleArray(dec, ttk)
+ if err != nil {
+ return 0, err
+ }
+ default:
+ return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
+ }
+ default:
+ return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
+ }
+ }
+ return offset, nil
}
-// Set uses the pointer to set a value from a JSON document
-func (p *Pointer) Set(document any, value any) (any, error) {
- return document, p.set(document, value, swag.DefaultJSONNameProvider)
+// "Constructor", parses the given string JSON pointer.
+func (p *Pointer) parse(jsonPointerString string) error {
+ if jsonPointerString == emptyPointer {
+ return nil
+ }
+
+ if !strings.HasPrefix(jsonPointerString, pointerSeparator) {
+ // non empty pointer must start with "/"
+ return errors.Join(ErrInvalidStart, ErrPointer)
+ }
+
+ referenceTokens := strings.Split(jsonPointerString, pointerSeparator)
+ p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...)
+
+ return nil
}
-// 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, swag.DefaultJSONNameProvider)
+func (p *Pointer) get(node any, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) {
+ if nameProvider == nil {
+ nameProvider = jsonname.DefaultJSONNameProvider
+ }
+
+ kind := reflect.Invalid
+
+ // full document when empty
+ if len(p.referenceTokens) == 0 {
+ return node, kind, nil
+ }
+
+ for _, token := range p.referenceTokens {
+ decodedToken := Unescape(token)
+
+ r, knd, err := getSingleImpl(node, decodedToken, nameProvider)
+ if err != nil {
+ return nil, knd, err
+ }
+ node = r
+ }
+
+ rValue := reflect.ValueOf(node)
+ kind = rValue.Kind()
+
+ return node, kind, nil
}
-// SetForToken gets 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, swag.DefaultJSONNameProvider)
+func (p *Pointer) set(node, data any, nameProvider *jsonname.NameProvider) 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(
+ 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 nameProvider == nil {
+ nameProvider = jsonname.DefaultJSONNameProvider
+ }
+
+ var decodedToken string
+ lastIndex := l - 1
+
+ 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
+ }
+
+ node = next
+ }
+ }
+
+ // last token
+ decodedToken = Unescape(p.referenceTokens[lastIndex])
+
+ return setSingleImpl(node, data, decodedToken, nameProvider)
+}
+
+func (p *Pointer) resolveNodeForToken(node any, decodedToken string, nameProvider *jsonname.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)
+ }
+
+ pointable, ok := node.(JSONPointable)
+ if ok {
+ r, err := pointable.JSONLookup(decodedToken)
+ if err != nil {
+ return nil, err
+ }
+
+ fld := reflect.ValueOf(r)
+ if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer {
+ return fld.Addr().Interface(), nil
+ }
+
+ return r, nil
+ }
+
+ rValue := reflect.Indirect(reflect.ValueOf(node))
+ kind := rValue.Kind()
+
+ switch kind {
+ case reflect.Struct:
+ nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
+ if !ok {
+ return nil, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
+ }
+
+ return typeFromValue(rValue.FieldByName(nm)), nil
+
+ case reflect.Map:
+ kv := reflect.ValueOf(decodedToken)
+ mv := rValue.MapIndex(kv)
+
+ if !mv.IsValid() {
+ return nil, errNoKey(decodedToken)
+ }
+
+ return typeFromValue(mv), nil
+
+ case reflect.Slice:
+ tokenIndex, err := strconv.Atoi(decodedToken)
+ if err != nil {
+ return nil, errors.Join(err, ErrPointer)
+ }
+
+ sLength := rValue.Len()
+ if tokenIndex < 0 || tokenIndex >= sLength {
+ return nil, errOutOfBounds(sLength, tokenIndex)
+ }
+
+ return typeFromValue(rValue.Index(tokenIndex)), nil
+
+ default:
+ return nil, errInvalidReference(decodedToken)
+ }
}
func isNil(input any) bool {
@@ -116,19 +295,37 @@ func isNil(input any) bool {
}
kind := reflect.TypeOf(input).Kind()
- switch kind { //nolint:exhaustive
- case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Chan:
+ switch kind {
+ case reflect.Pointer, reflect.Map, reflect.Slice, reflect.Chan:
return reflect.ValueOf(input).IsNil()
default:
return false
}
}
-func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvider) (any, reflect.Kind, error) {
+func typeFromValue(v reflect.Value) any {
+ if v.CanAddr() && v.Kind() != reflect.Interface && v.Kind() != reflect.Map && v.Kind() != reflect.Slice && v.Kind() != reflect.Pointer {
+ return v.Addr().Interface()
+ }
+
+ return v.Interface()
+}
+
+// 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)
+}
+
+// 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)
+}
+
+func getSingleImpl(node any, decodedToken string, nameProvider *jsonname.NameProvider) (any, reflect.Kind, error) {
rValue := reflect.Indirect(reflect.ValueOf(node))
kind := rValue.Kind()
if isNil(node) {
- return nil, kind, fmt.Errorf("nil value has not field %q", decodedToken)
+ return nil, kind, fmt.Errorf("nil value has no field %q: %w", decodedToken, ErrPointer)
}
switch typed := node.(type) {
@@ -142,13 +339,15 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide
return getSingleImpl(*typed, decodedToken, nameProvider)
}
- switch kind { //nolint:exhaustive
+ switch kind {
case reflect.Struct:
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
if !ok {
- return nil, kind, fmt.Errorf("object has no field %q", decodedToken)
+ return nil, kind, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
}
+
fld := rValue.FieldByName(nm)
+
return fld.Interface(), kind, nil
case reflect.Map:
@@ -158,259 +357,100 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide
if mv.IsValid() {
return mv.Interface(), kind, nil
}
- return nil, kind, fmt.Errorf("object has no key %q", decodedToken)
+
+ return nil, kind, errNoKey(decodedToken)
case reflect.Slice:
tokenIndex, err := strconv.Atoi(decodedToken)
if err != nil {
- return nil, kind, err
+ return nil, kind, errors.Join(err, ErrPointer)
}
sLength := rValue.Len()
if tokenIndex < 0 || tokenIndex >= sLength {
- return nil, kind, fmt.Errorf("index out of bounds array[0,%d] index '%d'", sLength-1, tokenIndex)
+ return nil, kind, errOutOfBounds(sLength, tokenIndex)
}
elem := rValue.Index(tokenIndex)
return elem.Interface(), kind, nil
default:
- return nil, kind, fmt.Errorf("invalid token reference %q", decodedToken)
+ return nil, kind, errInvalidReference(decodedToken)
}
-
}
-func setSingleImpl(node, data any, decodedToken string, nameProvider *swag.NameProvider) error {
- rValue := reflect.Indirect(reflect.ValueOf(node))
+func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.NameProvider) 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)
+ }
- if ns, ok := node.(JSONSetable); ok { // pointer impl
+ if ns, ok := node.(JSONSetable); ok {
return ns.JSONSet(decodedToken, data)
}
- if rValue.Type().Implements(jsonSetableType) {
- return node.(JSONSetable).JSONSet(decodedToken, data)
- }
+ rValue := reflect.Indirect(reflect.ValueOf(node))
- switch rValue.Kind() { //nolint:exhaustive
+ switch rValue.Kind() {
case reflect.Struct:
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
if !ok {
- return fmt.Errorf("object has no field %q", decodedToken)
+ return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
}
+
fld := rValue.FieldByName(nm)
- if fld.IsValid() {
- fld.Set(reflect.ValueOf(data))
+ if !fld.CanSet() {
+ return fmt.Errorf("can't set struct field %s to %v: %w", nm, data, ErrPointer)
}
+
+ value := reflect.ValueOf(data)
+ valueType := value.Type()
+ 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)
+ }
+
+ fld.Set(value)
+
return nil
case reflect.Map:
kv := reflect.ValueOf(decodedToken)
rValue.SetMapIndex(kv, reflect.ValueOf(data))
+
return nil
case reflect.Slice:
tokenIndex, err := strconv.Atoi(decodedToken)
if err != nil {
- return err
+ return errors.Join(err, ErrPointer)
}
+
sLength := rValue.Len()
if tokenIndex < 0 || tokenIndex >= sLength {
- return fmt.Errorf("index out of bounds array[0,%d] index '%d'", sLength, tokenIndex)
+ return errOutOfBounds(sLength, tokenIndex)
}
elem := rValue.Index(tokenIndex)
if !elem.CanSet() {
- return fmt.Errorf("can't set slice index %s to %v", decodedToken, data)
+ return fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer)
}
- elem.Set(reflect.ValueOf(data))
- return nil
-
- default:
- return fmt.Errorf("invalid token reference %q", decodedToken)
- }
-}
+ value := reflect.ValueOf(data)
+ valueType := value.Type()
+ assignedType := elem.Type()
-func (p *Pointer) get(node any, nameProvider *swag.NameProvider) (any, reflect.Kind, error) {
-
- if nameProvider == nil {
- nameProvider = swag.DefaultJSONNameProvider
- }
-
- kind := reflect.Invalid
-
- // Full document when empty
- if len(p.referenceTokens) == 0 {
- return node, kind, nil
- }
-
- for _, token := range p.referenceTokens {
-
- decodedToken := Unescape(token)
-
- r, knd, err := getSingleImpl(node, decodedToken, nameProvider)
- if err != nil {
- return nil, knd, err
+ 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)
}
- node = r
- }
-
- rValue := reflect.ValueOf(node)
- kind = rValue.Kind()
- return node, kind, nil
-}
-
-func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error {
- knd := reflect.ValueOf(node).Kind()
-
- if knd != reflect.Ptr && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array {
- return errors.New("only structs, pointers, maps and slices are supported for setting values")
- }
+ elem.Set(value)
- if nameProvider == nil {
- nameProvider = swag.DefaultJSONNameProvider
- }
-
- // Full document when empty
- if len(p.referenceTokens) == 0 {
return nil
- }
-
- lastI := len(p.referenceTokens) - 1
- for i, token := range p.referenceTokens {
- isLastToken := i == lastI
- decodedToken := Unescape(token)
-
- if isLastToken {
-
- return setSingleImpl(node, data, decodedToken, nameProvider)
- }
-
- rValue := reflect.Indirect(reflect.ValueOf(node))
- kind := rValue.Kind()
- if rValue.Type().Implements(jsonPointableType) {
- r, err := node.(JSONPointable).JSONLookup(decodedToken)
- if err != nil {
- return err
- }
- fld := reflect.ValueOf(r)
- if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Ptr {
- node = fld.Addr().Interface()
- continue
- }
- node = r
- continue
- }
-
- switch kind { //nolint:exhaustive
- case reflect.Struct:
- nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
- if !ok {
- return fmt.Errorf("object has no field %q", decodedToken)
- }
- fld := rValue.FieldByName(nm)
- if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Ptr {
- node = fld.Addr().Interface()
- continue
- }
- node = fld.Interface()
-
- case reflect.Map:
- kv := reflect.ValueOf(decodedToken)
- mv := rValue.MapIndex(kv)
-
- if !mv.IsValid() {
- return fmt.Errorf("object has no key %q", decodedToken)
- }
- if mv.CanAddr() && mv.Kind() != reflect.Interface && mv.Kind() != reflect.Map && mv.Kind() != reflect.Slice && mv.Kind() != reflect.Ptr {
- node = mv.Addr().Interface()
- continue
- }
- node = mv.Interface()
-
- case reflect.Slice:
- tokenIndex, err := strconv.Atoi(decodedToken)
- if err != nil {
- return err
- }
- sLength := rValue.Len()
- if tokenIndex < 0 || tokenIndex >= sLength {
- return fmt.Errorf("index out of bounds array[0,%d] index '%d'", sLength, tokenIndex)
- }
-
- elem := rValue.Index(tokenIndex)
- if elem.CanAddr() && elem.Kind() != reflect.Interface && elem.Kind() != reflect.Map && elem.Kind() != reflect.Slice && elem.Kind() != reflect.Ptr {
- node = elem.Addr().Interface()
- continue
- }
- node = elem.Interface()
-
- default:
- return fmt.Errorf("invalid token reference %q", decodedToken)
- }
-
- }
-
- return nil
-}
-
-// DecodedTokens returns the decoded tokens
-func (p *Pointer) DecodedTokens() []string {
- result := make([]string, 0, len(p.referenceTokens))
- for _, t := range p.referenceTokens {
- result = append(result, Unescape(t))
- }
- return result
-}
-
-// IsEmpty returns true if this is an empty json pointer
-// this indicates that it points to the root document
-func (p *Pointer) IsEmpty() bool {
- return len(p.referenceTokens) == 0
-}
-
-// Pointer to string representation function
-func (p *Pointer) String() string {
-
- if len(p.referenceTokens) == 0 {
- return emptyPointer
- }
-
- pointerString := pointerSeparator + strings.Join(p.referenceTokens, pointerSeparator)
-
- return pointerString
-}
-
-func (p *Pointer) Offset(document string) (int64, error) {
- dec := json.NewDecoder(strings.NewReader(document))
- var offset int64
- for _, ttk := range p.DecodedTokens() {
- tk, err := dec.Token()
- if err != nil {
- return 0, err
- }
- switch tk := tk.(type) {
- case json.Delim:
- switch tk {
- case '{':
- offset, err = offsetSingleObject(dec, ttk)
- if err != nil {
- return 0, err
- }
- case '[':
- offset, err = offsetSingleArray(dec, ttk)
- if err != nil {
- return 0, err
- }
- default:
- return 0, fmt.Errorf("invalid token %#v", tk)
- }
- default:
- return 0, fmt.Errorf("invalid token %#v", tk)
- }
+ default:
+ return errInvalidReference(decodedToken)
}
- return offset, nil
}
func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) {
@@ -437,16 +477,17 @@ func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) {
return offset, nil
}
default:
- return 0, fmt.Errorf("invalid token %#v", tk)
+ return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
}
}
- return 0, fmt.Errorf("token reference %q not found", decodedToken)
+
+ return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer)
}
func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) {
idx, err := strconv.Atoi(decodedToken)
if err != nil {
- return 0, fmt.Errorf("token reference %q is not a number: %v", decodedToken, err)
+ return 0, fmt.Errorf("token reference %q is not a number: %w: %w", decodedToken, err, ErrPointer)
}
var i int
for i = 0; i < idx && dec.More(); i++ {
@@ -470,12 +511,14 @@ func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) {
}
if !dec.More() {
- return 0, fmt.Errorf("token reference %q not found", decodedToken)
+ return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer)
}
+
return dec.InputOffset(), nil
}
// drainSingle drains a single level of object or array.
+//
// The decoder has to guarantee the beginning delim (i.e. '{' or '[') has been consumed.
func drainSingle(dec *json.Decoder) error {
for dec.More() {
@@ -497,14 +540,15 @@ func drainSingle(dec *json.Decoder) error {
}
}
- // Consumes the ending delim
+ // consumes the ending delim
if _, err := dec.Token(); err != nil {
return err
}
+
return nil
}
-// Specific JSON pointer encoding here
+// JSON pointer encoding:
// ~0 => ~
// ~1 => /
// ... and vice versa
@@ -516,16 +560,24 @@ const (
decRefTok1 = `/`
)
-// Unescape unescapes a json pointer reference token string to the original representation
+var (
+ encRefTokReplacer = strings.NewReplacer(encRefTok1, decRefTok1, encRefTok0, decRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global
+ decRefTokReplacer = strings.NewReplacer(decRefTok1, encRefTok1, decRefTok0, encRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global
+)
+
+// Unescape unescapes a json pointer reference token string to the original representation.
func Unescape(token string) string {
- step1 := strings.ReplaceAll(token, encRefTok1, decRefTok1)
- step2 := strings.ReplaceAll(step1, encRefTok0, decRefTok0)
- return step2
+ return encRefTokReplacer.Replace(token)
}
-// Escape escapes a pointer reference token string
+// Escape escapes a pointer reference token string.
+//
+// The JSONPointer specification defines "/" as a separator and "~" as an escape prefix.
+//
+// Keys containing such characters are escaped with the following rules:
+//
+// - "~" is escaped as "~0"
+// - "/" is escaped as "~1"
func Escape(token string) string {
- step1 := strings.ReplaceAll(token, decRefTok0, encRefTok0)
- step2 := strings.ReplaceAll(step1, decRefTok1, encRefTok1)
- return step2
+ return decRefTokReplacer.Replace(token)
}
diff --git a/vendor/github.com/go-openapi/jsonreference/.editorconfig b/vendor/github.com/go-openapi/jsonreference/.editorconfig
new file mode 100644
index 000000000000..3152da69a5d7
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/vendor/github.com/go-openapi/jsonreference/.gitignore b/vendor/github.com/go-openapi/jsonreference/.gitignore
index 769c244007b5..885dc27ab0bc 100644
--- a/vendor/github.com/go-openapi/jsonreference/.gitignore
+++ b/vendor/github.com/go-openapi/jsonreference/.gitignore
@@ -1 +1,6 @@
-secrets.yml
+*.out
+*.cov
+.idea
+.env
+.mcp.json
+.claude/
diff --git a/vendor/github.com/go-openapi/jsonreference/.golangci.yml b/vendor/github.com/go-openapi/jsonreference/.golangci.yml
index 22f8d21cca19..dc7c96053de0 100644
--- a/vendor/github.com/go-openapi/jsonreference/.golangci.yml
+++ b/vendor/github.com/go-openapi/jsonreference/.golangci.yml
@@ -1,61 +1,67 @@
-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: 3
-
+version: "2"
linters:
- enable-all: true
+ default: all
disable:
- - maligned
- - unparam
- - lll
- - gochecknoinits
- - gochecknoglobals
+ - depguard
- funlen
- godox
- - gocognit
- - whitespace
- - wsl
- - wrapcheck
- - testpackage
+ - exhaustruct
- nlreturn
- - gomnd
- - exhaustivestruct
- - goerr113
- - errorlint
- - nestif
- - godot
- - gofumpt
+ - nonamedreturns
+ - noinlineerr
- paralleltest
- - tparallel
+ - recvcheck
+ - testpackage
- thelper
- - ifshort
- - exhaustruct
+ - tparallel
- varnamelen
- - gci
- - depguard
- - errchkjson
- - inamedparam
- - nonamedreturns
- - musttag
- - ireturn
- - forcetypeassert
- - cyclop
- # deprecated linters
- - deadcode
- - interfacer
- - scopelint
- - varcheck
- - structcheck
- - golint
- - nosnakecase
+ - 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/jsonreference/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 100644
--- a/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md
+++ b/vendor/github.com/go-openapi/jsonreference/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/jsonreference/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md
new file mode 100644
index 000000000000..7faeb83a77d8
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md
@@ -0,0 +1,21 @@
+# Contributors
+
+- Repository: ['go-openapi/jsonreference']
+
+| Total Contributors | Total Contributions |
+| --- | --- |
+| 9 | 73 |
+
+| 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 |
+
+ _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_
diff --git a/vendor/github.com/go-openapi/jsonreference/NOTICE b/vendor/github.com/go-openapi/jsonreference/NOTICE
new file mode 100644
index 000000000000..814e87ef8c4c
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/NOTICE
@@ -0,0 +1,39 @@
+Copyright 2015-2025 go-swagger maintainers
+
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+This software library, github.com/go-openapi/jsonreference, includes software developed
+by the go-swagger and go-openapi maintainers ("go-swagger maintainers").
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software except in compliance with the License.
+
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0.
+
+This software is copied from, derived from, and inspired by other original software products.
+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/jsonreference
+===========================
+
+// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
+// SPDX-License-Identifier: Apache-2.0
+
+Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
+
+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/jsonreference/README.md b/vendor/github.com/go-openapi/jsonreference/README.md
index c7fc2049c1d8..adea16061976 100644
--- a/vendor/github.com/go-openapi/jsonreference/README.md
+++ b/vendor/github.com/go-openapi/jsonreference/README.md
@@ -1,19 +1,127 @@
-# gojsonreference [](https://github.com/go-openapi/jsonreference/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/jsonreference)
+# jsonreference
-[](https://slackin.goswagger.io)
-[](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE)
-[](https://pkg.go.dev/github.com/go-openapi/jsonreference)
-[](https://goreportcard.com/report/github.com/go-openapi/jsonreference)
+
+[![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]
-An implementation of JSON Reference - Go language
+---
+
+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]
## Status
-Feature complete. Stable API
+
+API is stable.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/jsonreference
+```
## Dependencies
-* https://github.com/go-openapi/jsonpointer
+
+*
+
+## Basic usage
+
+```go
+// Creating a new reference
+ref, err := jsonreference.New("http://example.com/doc.json#/definitions/Pet")
+
+// Fragment-only reference
+fragRef := jsonreference.MustCreateRef("#/definitions/Pet")
+
+// Resolving references
+parent, _ := jsonreference.New("http://example.com/base.json")
+child, _ := jsonreference.New("#/definitions/Pet")
+resolved, _ := parent.Inherits(child)
+// Result: "http://example.com/base.json#/definitions/Pet"
+```
+
+
+## Change log
+
+See
## References
-* http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
-* http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
+*
+*
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
+
+See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software
+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)
+
+## Cutting a new release
+
+Maintainers can cut a new release by either:
+
+* running [this workflow](https://github.com/go-openapi/jsonreference/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/jsonreference/actions/workflows/go-test.yml/badge.svg
+[test-url]: https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml
+[cov-badge]: https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg
+[cov-url]: https://codecov.io/gh/go-openapi/jsonreference
+[vuln-scan-badge]: https://github.com/go-openapi/jsonreference/actions/workflows/scanner.yml/badge.svg
+[vuln-scan-url]: https://github.com/go-openapi/jsonreference/actions/workflows/scanner.yml
+[codeql-badge]: https://github.com/go-openapi/jsonreference/actions/workflows/codeql.yml/badge.svg
+[codeql-url]: https://github.com/go-openapi/jsonreference/actions/workflows/codeql.yml
+
+[release-badge]: https://badge.fury.io/gh/go-openapi%2Fjsonreference.svg
+[release-url]: https://badge.fury.io/gh/go-openapi%2Fjsonreference
+[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonreference.svg
+[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonreference
+
+[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/jsonreference
+[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonreference
+[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/jsonreference
+[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonreference
+
+[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/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
+
+
+[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
+[license-url]: https://github.com/go-openapi/jsonreference/?tab=Apache-2.0-1-ov-file#readme
+
+[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/jsonreference
+[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
diff --git a/vendor/github.com/go-openapi/jsonreference/SECURITY.md b/vendor/github.com/go-openapi/jsonreference/SECURITY.md
new file mode 100644
index 000000000000..1fea2c5736a5
--- /dev/null
+++ b/vendor/github.com/go-openapi/jsonreference/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/jsonreference/internal/normalize_url.go b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go
index f0610cf1e577..a08b47320e7d 100644
--- a/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go
+++ b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package internal
import (
@@ -11,9 +14,11 @@ const (
defaultHTTPSPort = ":443"
)
-// Regular expressions used by the normalizations
-var rxPort = regexp.MustCompile(`(:\d+)/?$`)
-var rxDupSlashes = regexp.MustCompile(`/{2,}`)
+// Regular expressions used by the normalizations.
+var (
+ rxPort = regexp.MustCompile(`(:\d+)/?$`)
+ rxDupSlashes = regexp.MustCompile(`/{2,}`)
+)
// NormalizeURL will normalize the specified URL
// This was added to replace a previous call to the no longer maintained purell library:
diff --git a/vendor/github.com/go-openapi/jsonreference/reference.go b/vendor/github.com/go-openapi/jsonreference/reference.go
index cfdef03e5d94..003ba7a838c4 100644
--- a/vendor/github.com/go-openapi/jsonreference/reference.go
+++ b/vendor/github.com/go-openapi/jsonreference/reference.go
@@ -1,27 +1,5 @@
-// Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
-//
-// 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.
-
-// author sigu-399
-// author-github https://github.com/sigu-399
-// author-mail sigu.399@gmail.com
-//
-// repository-name jsonreference
-// repository-desc An implementation of JSON Reference - Go language
-//
-// description Main and unique file.
-//
-// created 26-02-2013
+// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
package jsonreference
@@ -38,50 +16,51 @@ const (
fragmentRune = `#`
)
-// New creates a new reference for the given string
-func New(jsonReferenceString string) (Ref, error) {
+// ErrChildURL is raised when there is no child.
+var ErrChildURL = errors.New("child url is nil")
+
+// Ref represents a json reference object.
+type Ref struct {
+ referenceURL *url.URL
+ referencePointer jsonpointer.Pointer
+
+ HasFullURL bool
+ HasURLPathOnly bool
+ HasFragmentOnly bool
+ HasFileScheme bool
+ HasFullFilePath bool
+}
+// New creates a new reference for the given string.
+func New(jsonReferenceString string) (Ref, error) {
var r Ref
err := r.parse(jsonReferenceString)
return r, err
-
}
// MustCreateRef parses the ref string and panics when it's invalid.
-// Use the New method for a version that returns an error
+// Use the New method for a version that returns an error.
func MustCreateRef(ref string) Ref {
r, err := New(ref)
if err != nil {
panic(err)
}
- return r
-}
-// Ref represents a json reference object
-type Ref struct {
- referenceURL *url.URL
- referencePointer jsonpointer.Pointer
-
- HasFullURL bool
- HasURLPathOnly bool
- HasFragmentOnly bool
- HasFileScheme bool
- HasFullFilePath bool
+ return r
}
-// GetURL gets the URL for this reference
+// GetURL gets the URL for this reference.
func (r *Ref) GetURL() *url.URL {
return r.referenceURL
}
-// GetPointer gets the json pointer for this reference
+// GetPointer gets the json pointer for this reference.
func (r *Ref) GetPointer() *jsonpointer.Pointer {
return &r.referencePointer
}
-// String returns the best version of the url for this reference
+// String returns the best version of the url for this reference.
func (r *Ref) String() string {
-
if r.referenceURL != nil {
return r.referenceURL.String()
}
@@ -93,7 +72,7 @@ func (r *Ref) String() string {
return r.referencePointer.String()
}
-// IsRoot returns true if this reference is a root document
+// IsRoot returns true if this reference is a root document.
func (r *Ref) IsRoot() bool {
return r.referenceURL != nil &&
!r.IsCanonical() &&
@@ -101,14 +80,32 @@ func (r *Ref) IsRoot() bool {
r.referenceURL.Fragment == ""
}
-// IsCanonical returns true when this pointer starts with http(s):// or file://
+// IsCanonical returns true when this pointer starts with http(s):// or file://.
func (r *Ref) IsCanonical() bool {
return (r.HasFileScheme && r.HasFullFilePath) || (!r.HasFileScheme && r.HasFullURL)
}
-// "Constructor", parses the given string JSON reference
-func (r *Ref) parse(jsonReferenceString string) error {
+// Inherits creates a new reference from a parent and a child
+// If the child cannot inherit from the parent, an error is returned.
+func (r *Ref) Inherits(child Ref) (*Ref, error) {
+ childURL := child.GetURL()
+ parentURL := r.GetURL()
+ if childURL == nil {
+ return nil, ErrChildURL
+ }
+ if parentURL == nil {
+ return &child, nil
+ }
+
+ ref, err := New(parentURL.ResolveReference(childURL).String())
+ if err != nil {
+ return nil, err
+ }
+ return &ref, nil
+}
+// "Constructor", parses the given string JSON reference.
+func (r *Ref) parse(jsonReferenceString string) error {
parsed, err := url.Parse(jsonReferenceString)
if err != nil {
return err
@@ -137,22 +134,3 @@ func (r *Ref) parse(jsonReferenceString string) error {
return nil
}
-
-// Inherits creates a new reference from a parent and a child
-// If the child cannot inherit from the parent, an error is returned
-func (r *Ref) Inherits(child Ref) (*Ref, error) {
- childURL := child.GetURL()
- parentURL := r.GetURL()
- if childURL == nil {
- return nil, errors.New("child url is nil")
- }
- if parentURL == nil {
- return &child, nil
- }
-
- ref, err := New(parentURL.ResolveReference(childURL).String())
- if err != nil {
- return nil, err
- }
- return &ref, nil
-}
diff --git a/vendor/github.com/go-openapi/loads/.gitignore b/vendor/github.com/go-openapi/loads/.gitignore
index e4f15f17bfc2..d8f4186fe59c 100644
--- a/vendor/github.com/go-openapi/loads/.gitignore
+++ b/vendor/github.com/go-openapi/loads/.gitignore
@@ -1,4 +1,5 @@
-secrets.yml
-coverage.out
-profile.cov
-profile.out
+*.out
+*.cov
+.idea
+.env
+.mcp.json
diff --git a/vendor/github.com/go-openapi/loads/.golangci.yml b/vendor/github.com/go-openapi/loads/.golangci.yml
index 22f8d21cca19..83968f3faeb8 100644
--- a/vendor/github.com/go-openapi/loads/.golangci.yml
+++ b/vendor/github.com/go-openapi/loads/.golangci.yml
@@ -1,61 +1,69 @@
-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: 3
-
+version: "2"
linters:
- enable-all: true
+ default: all
disable:
- - maligned
- - unparam
- - lll
- - gochecknoinits
- - gochecknoglobals
+ - depguard
- funlen
+ - gochecknoglobals # on this repo, it is hard to refactor without globals/inits and no breaking change
+ - gochecknoinits
- godox
- - gocognit
- - whitespace
- - wsl
- - wrapcheck
- - testpackage
+ - exhaustruct
- nlreturn
- - gomnd
- - exhaustivestruct
- - goerr113
- - errorlint
- - nestif
- - godot
- - gofumpt
+ - nonamedreturns
+ - noinlineerr
- paralleltest
- - tparallel
+ - recvcheck
+ - testpackage
- thelper
- - ifshort
- - exhaustruct
+ - tparallel
- varnamelen
- - gci
- - depguard
- - errchkjson
- - inamedparam
- - nonamedreturns
- - musttag
- - ireturn
- - forcetypeassert
- - cyclop
- # deprecated linters
- - deadcode
- - interfacer
- - scopelint
- - varcheck
- - structcheck
- - golint
- - nosnakecase
+ - 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/loads/.travis.yml b/vendor/github.com/go-openapi/loads/.travis.yml
deleted file mode 100644
index cd4a7c331bc7..000000000000
--- a/vendor/github.com/go-openapi/loads/.travis.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-after_success:
-- bash <(curl -s https://codecov.io/bash)
-go:
-- 1.16.x
-- 1.x
-install:
-- go get gotest.tools/gotestsum
-language: go
-arch:
-- amd64
-- ppc64le
-jobs:
- include:
- # 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
-notifications:
- slack:
- secure: OxkPwVp35qBTUilgWC8xykSj+sGMcj0h8IIOKD+Rflx2schZVlFfdYdyVBM+s9OqeOfvtuvnR9v1Ye2rPKAvcjWdC4LpRGUsgmItZaI6Um8Aj6+K9udCw5qrtZVfOVmRu8LieH//XznWWKdOultUuniW0MLqw5+II87Gd00RWbCGi0hk0PykHe7uK+PDA2BEbqyZ2WKKYCvfB3j+0nrFOHScXqnh0V05l2E83J4+Sgy1fsPy+1WdX58ZlNBG333ibaC1FS79XvKSmTgKRkx3+YBo97u6ZtUmJa5WZjf2OdLG3KIckGWAv6R5xgxeU31N0Ng8L332w/Edpp2O/M2bZwdnKJ8hJQikXIAQbICbr+lTDzsoNzMdEIYcHpJ5hjPbiUl3Bmd+Jnsjf5McgAZDiWIfpCKZ29tPCEkVwRsOCqkyPRMNMzHHmoja495P5jR+ODS7+J8RFg5xgcnOgpP9D4Wlhztlf5WyZMpkLxTUD+bZq2SRf50HfHFXTkfq22zPl3d1eq0yrLwh/Z/fWKkfb6SyysROL8y6s8u3dpFX1YHSg0BR6i913h4aoZw9B2BG27cafLLTwKYsp2dFo1PWl4O6u9giFJIeqwloZHLKKrwh0cBFhB7RH0I58asxkZpCH6uWjJierahmHe7iS+E6i+9oCHkOZ59hmCYNimIs3hM=
-script:
-- gotestsum -f short-verbose -- -race -timeout=20m -coverprofile=coverage.txt -covermode=atomic ./...
diff --git a/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 100644
--- a/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md
+++ b/vendor/github.com/go-openapi/loads/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/loads/CONTRIBUTORS.md b/vendor/github.com/go-openapi/loads/CONTRIBUTORS.md
new file mode 100644
index 000000000000..36b836a3d5ab
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/CONTRIBUTORS.md
@@ -0,0 +1,26 @@
+# Contributors
+
+- Repository: ['go-openapi/loads']
+
+| Total Contributors | Total Contributions |
+| --- | --- |
+| 14 | 123 |
+
+| Username | All Time Contribution Count | All Commits |
+| --- | --- | --- |
+| @casualjim | 48 | |
+| @fredbi | 45 | |
+| @youyuanwu | 6 | |
+| @vburenin | 4 | |
+| @keramix | 4 | |
+| @orisano | 3 | |
+| @GlenDC | 3 | |
+| @pengsrc | 2 | |
+| @a2800276 | 2 | |
+| @tklauser | 2 | |
+| @hypnoglow | 1 | |
+| @koron | 1 | |
+| @kreativka | 1 | |
+| @petrkotas | 1 | |
+
+ _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_
diff --git a/vendor/github.com/go-openapi/loads/README.md b/vendor/github.com/go-openapi/loads/README.md
index f8bd440dfc27..d92e62a040d3 100644
--- a/vendor/github.com/go-openapi/loads/README.md
+++ b/vendor/github.com/go-openapi/loads/README.md
@@ -1,6 +1,118 @@
-# Loads OAI specs [](https://github.com/go-openapi/loads/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/loads)
+# Loads OAI specs
-[](https://raw.githubusercontent.com/go-openapi/loads/master/LICENSE) [](http://godoc.org/github.com/go-openapi/loads)
-[](https://goreportcard.com/report/github.com/go-openapi/loads)
+
+[![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]
-Loading of OAI specification documents from local or remote locations. Supports JSON and YAML documents.
+---
+
+Loads OAI v2 API specification documents from local or remote locations.
+
+Supports JSON and YAML 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
+ * 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.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/loads
+```
+
+## Basic usage
+
+```go
+ import (
+ "github.com/go-openapi/loads"
+ )
+
+ ...
+
+ // loads a YAML spec from a http file
+ doc, err := loads.Spec(ts.URL)
+
+ ...
+
+ // retrieves the object model for the API specification
+ spec := doc.Spec()
+
+ ...
+```
+
+See also the provided [examples](https://pkg.go.dev/github.com/go-openapi/loads#pkg-examples).
+
+## Change log
+
+See
+
+## Licensing
+
+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)
+
+## Cutting a new release
+
+Maintainers can cut a new release by either:
+
+* running [this workflow](https://github.com/go-openapi/loads/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/loads/actions/workflows/go-test.yml/badge.svg
+[test-url]: https://github.com/go-openapi/loads/actions/workflows/go-test.yml
+[cov-badge]: https://codecov.io/gh/go-openapi/loads/branch/master/graph/badge.svg
+[cov-url]: https://codecov.io/gh/go-openapi/loads
+[vuln-scan-badge]: https://github.com/go-openapi/loads/actions/workflows/scanner.yml/badge.svg
+[vuln-scan-url]: https://github.com/go-openapi/loads/actions/workflows/scanner.yml
+[codeql-badge]: https://github.com/go-openapi/loads/actions/workflows/codeql.yml/badge.svg
+[codeql-url]: https://github.com/go-openapi/loads/actions/workflows/codeql.yml
+
+[release-badge]: https://badge.fury.io/gh/go-openapi%2Floads.svg
+[release-url]: https://badge.fury.io/gh/go-openapi%2Floads
+
+[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/loads
+[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/loads
+[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/loads
+[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/loads
+
+[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
+
+
+[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
+[license-url]: https://github.com/go-openapi/loads/?tab=Apache-2.0-1-ov-file#readme
+
+[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/loads
+[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
diff --git a/vendor/github.com/go-openapi/loads/SECURITY.md b/vendor/github.com/go-openapi/loads/SECURITY.md
new file mode 100644
index 000000000000..6ceb159ca229
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/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 |
+| ------- | ------------------ |
+| 0.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/loads/doc.go b/vendor/github.com/go-openapi/loads/doc.go
index 5bcaef5dbccb..67a5e2f8d954 100644
--- a/vendor/github.com/go-openapi/loads/doc.go
+++ b/vendor/github.com/go-openapi/loads/doc.go
@@ -1,18 +1,9 @@
-// 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 loads provides document loading methods for swagger (OAI) specifications.
+// Package loads provides document loading methods for swagger (OAI v2) API specifications.
//
// 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.
package loads
diff --git a/vendor/github.com/go-openapi/loads/errors.go b/vendor/github.com/go-openapi/loads/errors.go
new file mode 100644
index 000000000000..14a8186b6ca8
--- /dev/null
+++ b/vendor/github.com/go-openapi/loads/errors.go
@@ -0,0 +1,18 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package loads
+
+type loaderError string
+
+func (e loaderError) Error() string {
+ return string(e)
+}
+
+const (
+ // ErrLoads is an error returned by the loads package.
+ ErrLoads loaderError = "loaderrs error"
+
+ // ErrNoLoader indicates that no configured loader matched the input.
+ ErrNoLoader loaderError = "no loader matched"
+)
diff --git a/vendor/github.com/go-openapi/loads/loaders.go b/vendor/github.com/go-openapi/loads/loaders.go
index b2d1e034c523..ac8adfe8b205 100644
--- a/vendor/github.com/go-openapi/loads/loaders.go
+++ b/vendor/github.com/go-openapi/loads/loaders.go
@@ -1,22 +1,24 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package loads
import (
"encoding/json"
"errors"
"net/url"
+ "slices"
"github.com/go-openapi/spec"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/loading"
)
-var (
- // Default chain of loaders, defined at the package level.
- //
- // By default this matches json and yaml documents.
- //
- // May be altered with AddLoader().
- loaders *loader
-)
+// Default chain of loaders, defined at the package level.
+//
+// By default this matches json and yaml documents.
+//
+// May be altered with AddLoader().
+var loaders *loader
func init() {
jsonLoader := &loader{
@@ -30,8 +32,8 @@ func init() {
loaders = jsonLoader.WithHead(&loader{
DocLoaderWithMatch: DocLoaderWithMatch{
- Match: swag.YAMLMatcher,
- Fn: swag.YAMLDoc,
+ Match: loading.YAMLMatcher,
+ Fn: loading.YAMLDoc,
},
})
@@ -39,10 +41,10 @@ func init() {
spec.PathLoader = loaders.Load
}
-// DocLoader represents a doc loader type
-type DocLoader func(string) (json.RawMessage, error)
+// DocLoader represents a doc loader type.
+type DocLoader func(string, ...loading.Option) (json.RawMessage, error)
-// DocMatcher represents a predicate to check if a loader matches
+// DocMatcher represents a predicate to check if a loader matches.
type DocMatcher func(string) bool
// DocLoaderWithMatch describes a loading function for a given extension match.
@@ -51,7 +53,7 @@ type DocLoaderWithMatch struct {
Match DocMatcher
}
-// NewDocLoaderWithMatch builds a DocLoaderWithMatch to be used in load options
+// NewDocLoaderWithMatch builds a [DocLoaderWithMatch] to be used in load options.
func NewDocLoaderWithMatch(fn DocLoader, matcher DocMatcher) DocLoaderWithMatch {
return DocLoaderWithMatch{
Fn: fn,
@@ -61,10 +63,13 @@ func NewDocLoaderWithMatch(fn DocLoader, matcher DocMatcher) DocLoaderWithMatch
type loader struct {
DocLoaderWithMatch
+
+ loadingOptions []loading.Option
+
Next *loader
}
-// WithHead adds a loader at the head of the current stack
+// WithHead adds a loader at the head of the current stack.
func (l *loader) WithHead(head *loader) *loader {
if head == nil {
return l
@@ -73,27 +78,27 @@ func (l *loader) WithHead(head *loader) *loader {
return head
}
-// WithNext adds a loader at the trail of the current stack
+// WithNext adds a loader at the trail of the current stack.
func (l *loader) WithNext(next *loader) *loader {
l.Next = next
return next
}
-// Load the raw document from path
+// Load the raw document from path.
func (l *loader) Load(path string) (json.RawMessage, error) {
_, erp := url.Parse(path)
if erp != nil {
- return nil, erp
+ return nil, errors.Join(erp, ErrLoads)
}
- lastErr := errors.New("no loader matched") // default error if no match was found
+ var lastErr error = ErrNoLoader // default error if no match was found
for ldr := l; ldr != nil; ldr = ldr.Next {
if ldr.Match != nil && !ldr.Match(path) {
continue
}
// try then move to next one if there is an error
- b, err := ldr.Fn(path)
+ b, err := ldr.Fn(path, l.loadingOptions...)
if err == nil {
return b, nil
}
@@ -101,14 +106,29 @@ func (l *loader) Load(path string) (json.RawMessage, error) {
lastErr = err
}
- return nil, lastErr
+ return nil, errors.Join(lastErr, ErrLoads)
}
-// JSONDoc loads a json document from either a file or a remote url
-func JSONDoc(path string) (json.RawMessage, error) {
- data, err := swag.LoadFromFileOrHTTP(path)
+func (l *loader) clone() *loader {
+ if l == nil {
+ return nil
+ }
+
+ return &loader{
+ DocLoaderWithMatch: l.DocLoaderWithMatch,
+ loadingOptions: slices.Clone(l.loadingOptions),
+ Next: l.Next.clone(),
+ }
+}
+
+// JSONDoc loads a json document from either a file or a remote URL.
+//
+// See [loading.Option] for available options (e.g. configuring authentication,
+// headers or using embedded file system resources).
+func JSONDoc(path string, opts ...loading.Option) (json.RawMessage, error) {
+ data, err := loading.LoadFromFileOrHTTP(path, opts...)
if err != nil {
- return nil, err
+ return nil, errors.Join(err, ErrLoads)
}
return json.RawMessage(data), nil
}
@@ -117,9 +137,10 @@ func JSONDoc(path string) (json.RawMessage, error) {
//
// This sets the configuration at the package level.
//
-// NOTE:
-// - this updates the default loader used by github.com/go-openapi/spec
-// - since this sets package level globals, you shouln't call this concurrently
+// # Concurrency
+//
+// 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.
func AddLoader(predicate DocMatcher, load DocLoader) {
loaders = loaders.WithHead(&loader{
DocLoaderWithMatch: DocLoaderWithMatch{
diff --git a/vendor/github.com/go-openapi/loads/options.go b/vendor/github.com/go-openapi/loads/options.go
index f8305d5607cc..045ece5e095a 100644
--- a/vendor/github.com/go-openapi/loads/options.go
+++ b/vendor/github.com/go-openapi/loads/options.go
@@ -1,7 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package loads
+import "github.com/go-openapi/swag/loading"
+
type options struct {
- loader *loader
+ loader *loader
+ loadingOptions []loading.Option
}
func defaultOptions() *options {
@@ -16,13 +22,16 @@ func loaderFromOptions(options []LoaderOption) *loader {
apply(opts)
}
- return opts.loader
+ l := opts.loader.clone()
+ l.loadingOptions = opts.loadingOptions
+
+ return l
}
-// LoaderOption allows to fine-tune the spec loader behavior
+// LoaderOption allows to fine-tune the spec loader behavior.
type LoaderOption func(*options)
-// WithDocLoader sets a custom loader for loading specs
+// WithDocLoader sets a custom loader for loading specs.
func WithDocLoader(l DocLoader) LoaderOption {
return func(opt *options) {
if l == nil {
@@ -39,7 +48,7 @@ func WithDocLoader(l DocLoader) LoaderOption {
// WithDocLoaderMatches sets a chain of custom loaders for loading specs
// for different extension matches.
//
-// Loaders are executed in the order of provided DocLoaderWithMatch'es.
+// Loaders are executed in the order of provided [DocLoaderWithMatch] 'es.
func WithDocLoaderMatches(l ...DocLoaderWithMatch) LoaderOption {
return func(opt *options) {
var final, prev *loader
@@ -59,3 +68,10 @@ func WithDocLoaderMatches(l ...DocLoaderWithMatch) LoaderOption {
opt.loader = final
}
}
+
+// WithLoadingOptions adds some [loading.Option] to be added when calling a registered loader.
+func WithLoadingOptions(loadingOptions ...loading.Option) LoaderOption {
+ return func(opt *options) {
+ opt.loadingOptions = loadingOptions
+ }
+}
diff --git a/vendor/github.com/go-openapi/loads/spec.go b/vendor/github.com/go-openapi/loads/spec.go
index c9039cd5d7ed..606a01d8e9f8 100644
--- a/vendor/github.com/go-openapi/loads/spec.go
+++ b/vendor/github.com/go-openapi/loads/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 loads
@@ -18,19 +7,21 @@ import (
"bytes"
"encoding/gob"
"encoding/json"
+ "errors"
"fmt"
+ "maps"
"github.com/go-openapi/analysis"
"github.com/go-openapi/spec"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/yamlutils"
)
func init() {
- gob.Register(map[string]interface{}{})
- gob.Register([]interface{}{})
+ gob.Register(map[string]any{})
+ gob.Register([]any{})
}
-// Document represents a swagger spec document
+// Document represents a swagger spec document.
type Document struct {
// specAnalyzer
Analyzer *analysis.Spec
@@ -42,14 +33,21 @@ type Document struct {
raw json.RawMessage
}
-// JSONSpec loads a spec from a json document
-func JSONSpec(path string, options ...LoaderOption) (*Document, error) {
- data, err := JSONDoc(path)
+// JSONSpec loads a spec from a JSON document, using the [JSONDoc] loader.
+//
+// A set of [loading.Option] may be passed to this loader using [WithLoadingOptions].
+func JSONSpec(path string, opts ...LoaderOption) (*Document, error) {
+ var o options
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ data, err := JSONDoc(path, o.loadingOptions...)
if err != nil {
return nil, err
}
// convert to json
- doc, err := Analyzed(data, "", options...)
+ doc, err := Analyzed(data, "", opts...)
if err != nil {
return nil, err
}
@@ -59,8 +57,8 @@ func JSONSpec(path string, options ...LoaderOption) (*Document, error) {
return doc, nil
}
-// Embedded returns a Document based on embedded specs. No analysis is required
-func Embedded(orig, flat json.RawMessage, options ...LoaderOption) (*Document, error) {
+// Embedded returns a Document based on embedded specs (i.e. as a [json.RawMessage]). No analysis is required.
+func Embedded(orig, flat json.RawMessage, opts ...LoaderOption) (*Document, error) {
var origSpec, flatSpec spec.Swagger
if err := json.Unmarshal(orig, &origSpec); err != nil {
return nil, err
@@ -72,20 +70,22 @@ func Embedded(orig, flat json.RawMessage, options ...LoaderOption) (*Document, e
raw: orig,
origSpec: &origSpec,
spec: &flatSpec,
- pathLoader: loaderFromOptions(options),
+ pathLoader: loaderFromOptions(opts),
}, nil
}
-// Spec loads a new spec document from a local or remote path
-func Spec(path string, options ...LoaderOption) (*Document, error) {
- ldr := loaderFromOptions(options)
+// 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.
+func Spec(path string, opts ...LoaderOption) (*Document, error) {
+ ldr := loaderFromOptions(opts)
b, err := ldr.Load(path)
if err != nil {
return nil, err
}
- document, err := Analyzed(b, "", options...)
+ document, err := Analyzed(b, "", opts...)
if err != nil {
return nil, err
}
@@ -96,13 +96,13 @@ func Spec(path string, options ...LoaderOption) (*Document, error) {
return document, nil
}
-// Analyzed creates a new analyzed spec document for a root json.RawMessage.
+// Analyzed creates a new analyzed spec document for a root [json.RawMessage].
func Analyzed(data json.RawMessage, version string, options ...LoaderOption) (*Document, error) {
if version == "" {
version = "2.0"
}
if version != "2.0" {
- return nil, fmt.Errorf("spec version %q is not supported", version)
+ return nil, fmt.Errorf("spec version %q is not supported: %w", version, ErrLoads)
}
raw, err := trimData(data) // trim blanks, then convert yaml docs into json
@@ -112,12 +112,12 @@ func Analyzed(data json.RawMessage, version string, options ...LoaderOption) (*D
swspec := new(spec.Swagger)
if err = json.Unmarshal(raw, swspec); err != nil {
- return nil, err
+ return nil, errors.Join(err, ErrLoads)
}
origsqspec, err := cloneSpec(swspec)
if err != nil {
- return nil, err
+ return nil, errors.Join(err, ErrLoads)
}
d := &Document{
@@ -143,20 +143,20 @@ func trimData(in json.RawMessage) (json.RawMessage, error) {
}
// assume yaml doc: convert it to json
- yml, err := swag.BytesToYAMLDoc(trimmed)
+ yml, err := yamlutils.BytesToYAMLDoc(trimmed)
if err != nil {
- return nil, fmt.Errorf("analyzed: %v", err)
+ return nil, fmt.Errorf("analyzed: %w: %w", err, ErrLoads)
}
- d, err := swag.YAMLToJSON(yml)
+ d, err := yamlutils.YAMLToJSON(yml)
if err != nil {
- return nil, fmt.Errorf("analyzed: %v", err)
+ return nil, fmt.Errorf("analyzed: %w: %w", err, ErrLoads)
}
return d, nil
}
-// Expanded expands the $ref fields in the spec document and returns a new spec document
+// Expanded expands the $ref fields in the spec [Document] and returns a new expanded [Document].
func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
swspec := new(spec.Swagger)
if err := json.Unmarshal(d.raw, swspec); err != nil {
@@ -200,55 +200,55 @@ func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
return dd, nil
}
-// BasePath the base path for the API specified by this spec
+// BasePath the base path for the API specified by this spec.
func (d *Document) BasePath() string {
+ if d.spec == nil {
+ return ""
+ }
return d.spec.BasePath
}
-// Version returns the version of this spec
+// Version returns the OpenAPI version of this spec (e.g. 2.0).
func (d *Document) Version() string {
return d.spec.Swagger
}
-// Schema returns the swagger 2.0 schema
+// Schema returns the swagger 2.0 meta-schema.
func (d *Document) Schema() *spec.Schema {
return d.schema
}
-// Spec returns the swagger spec object model
+// Spec returns the swagger object model for this API specification.
func (d *Document) Spec() *spec.Swagger {
return d.spec
}
-// Host returns the host for the API
+// Host returns the host for the API.
func (d *Document) Host() string {
return d.spec.Host
}
-// Raw returns the raw swagger spec as json bytes
+// Raw returns the raw swagger spec as json bytes.
func (d *Document) Raw() json.RawMessage {
return d.raw
}
-// OrigSpec yields the original spec
+// OrigSpec yields the original spec.
func (d *Document) OrigSpec() *spec.Swagger {
return d.origSpec
}
-// ResetDefinitions gives a shallow copy with the models reset to the original spec
+// ResetDefinitions yields a shallow copy with the models reset to the original spec.
func (d *Document) ResetDefinitions() *Document {
- defs := make(map[string]spec.Schema, len(d.origSpec.Definitions))
- for k, v := range d.origSpec.Definitions {
- defs[k] = v
- }
+ d.spec.Definitions = make(map[string]spec.Schema, len(d.origSpec.Definitions))
+ maps.Copy(d.spec.Definitions, d.origSpec.Definitions)
- d.spec.Definitions = defs
return d
}
-// Pristine creates a new pristine document instance based on the input data
+// Pristine creates a new pristine document instance based on the input data.
func (d *Document) Pristine() *Document {
- raw, _ := json.Marshal(d.Spec())
+ raw, _ := json.Marshal(d.Spec()) //nolint:errchkjson // the spec always marshals to JSON
dd, _ := Analyzed(raw, d.Version())
dd.pathLoader = d.pathLoader
dd.specFilePath = d.specFilePath
@@ -256,7 +256,7 @@ func (d *Document) Pristine() *Document {
return dd
}
-// SpecFilePath returns the file path of the spec if one is defined
+// SpecFilePath returns the file path of the spec if one is defined.
func (d *Document) SpecFilePath() string {
return d.specFilePath
}
@@ -271,5 +271,6 @@ func cloneSpec(src *spec.Swagger) (*spec.Swagger, error) {
if err := gob.NewDecoder(&b).Decode(&dst); err != nil {
return nil, err
}
+
return &dst, nil
}
diff --git a/vendor/github.com/go-openapi/runtime/.gitattributes b/vendor/github.com/go-openapi/runtime/.gitattributes
new file mode 100644
index 000000000000..d207b1802b20
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/.gitattributes
@@ -0,0 +1 @@
+*.go text eol=lf
diff --git a/vendor/github.com/go-openapi/runtime/.gitignore b/vendor/github.com/go-openapi/runtime/.gitignore
index fea8b84eca99..d8f4186fe59c 100644
--- a/vendor/github.com/go-openapi/runtime/.gitignore
+++ b/vendor/github.com/go-openapi/runtime/.gitignore
@@ -1,5 +1,5 @@
-secrets.yml
-coverage.out
-*.cov
*.out
-playground
+*.cov
+.idea
+.env
+.mcp.json
diff --git a/vendor/github.com/go-openapi/runtime/.golangci.yml b/vendor/github.com/go-openapi/runtime/.golangci.yml
new file mode 100644
index 000000000000..0087ed311303
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/.golangci.yml
@@ -0,0 +1,77 @@
+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
+ - gocognit
+ - godot
+ - godox
+ - gomoddirectives # moved to mono-repo, multi-modules, so replace directives are needed
+ - gosmopolitan
+ - inamedparam
+ - ireturn
+ - lll
+ - musttag
+ - nestif
+ - nilerr # nilerr crashes on this repo
+ - nlreturn
+ - noinlineerr
+ - nonamedreturns
+ - paralleltest
+ - recvcheck
+ - testpackage
+ - thelper
+ - tparallel
+ - unparam
+ - varnamelen
+ - whitespace
+ - wrapcheck
+ - wsl
+ - wsl_v5
+ settings:
+ dupl:
+ threshold: 200
+ goconst:
+ min-len: 2
+ min-occurrences: 3
+ gocyclo:
+ min-complexity: 45
+ exclusions:
+ generated: lax
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ paths:
+ - third_party$
+ - builtin$
+ - examples$
+formatters:
+ enable:
+ - gofmt
+ - goimports
+ 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/runtime/.travis.yml b/vendor/github.com/go-openapi/runtime/.travis.yml
deleted file mode 100644
index e36276ab3fa7..000000000000
--- a/vendor/github.com/go-openapi/runtime/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-after_success:
-- bash <(curl -s https://codecov.io/bash)
-go:
-- 1.13.x
-- 1.14.x
-install:
-- GO111MODULE=off go get -u gotest.tools/gotestsum
-language: go
-notifications:
- slack:
- secure: EmObnQuM9Mw8J9vpFaKKHqSMN4Wsr/A9+v7ewAD5cEhA0T1P4m7MbJMiJOhxUhj/X+BFh2DamW+P2lT8mybj5wg8wnkQ2BteKA8Tawi6f9PRw2NRheO8tAi8o/npLnlmet0kc93mn+oLuqHw36w4+j5mkOl2FghkfGiUVhwrhkCP7KXQN+3TU87e+/HzQumlJ3nsE+6terVxkH3PmaUTsS5ONaODZfuxFpfb7RsoEl3skHf6d+tr+1nViLxxly7558Nc33C+W1mr0qiEvMLZ+kJ/CpGWBJ6CUJM3jm6hNe2eMuIPwEK2hxZob8c7n22VPap4K6a0bBRoydoDXaba+2sD7Ym6ivDO/DVyL44VeBBLyIiIBylDGQdZH+6SoWm90Qe/i7tnY/T5Ao5igT8f3cfQY1c3EsTfqmlDfrhmACBmwSlgkdVBLTprHL63JMY24LWmh4jhxsmMRZhCL4dze8su1w6pLN/pD1pGHtKYCEVbdTmaM3PblNRFf12XB7qosmQsgUndH4Vq3bTbU0s1pKjeDhRyLvFzvR0TBbo0pDLEoF1A/i5GVFWa7yLZNUDudQERRh7qv/xBl2excIaQ1sV4DSVm7bAE9l6Kp+yeHQJW2uN6Y3X8wu9gB9nv9l5HBze7wh8KE6PyWAOLYYqZg9/sAtsv/2GcQqXcKFF1zcA=
-script:
-- gotestsum -f short-verbose -- -race -timeout=20m -coverprofile=coverage.txt -covermode=atomic ./...
diff --git a/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 100644
--- a/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md
+++ b/vendor/github.com/go-openapi/runtime/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/runtime/NOTICE b/vendor/github.com/go-openapi/runtime/NOTICE
new file mode 100644
index 000000000000..b9153aae9ebb
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/NOTICE
@@ -0,0 +1,45 @@
+Copyright 2015-2025 go-swagger maintainers
+
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+This software library, github.com/go-openapi/jsonpointer, includes software developed
+by the go-swagger and go-openapi maintainers ("go-swagger maintainers").
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software except in compliance with the License.
+
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0.
+
+This software is copied from, derived from, and inspired by other original software products.
+It ships with copies of other software which license terms are recalled below.
+
+The original software was authored in 2014 by Naoya Inada
+
+https://github.com/naoina/denco
+===========================
+
+// SPDX-FileCopyrightText: Copyright (c) 2014 Naoya Inada
+// SPDX-License-Identifier: MIT
+
+Copyright (c) 2014 Naoya Inada
+
+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/go-openapi/runtime/README.md b/vendor/github.com/go-openapi/runtime/README.md
index 5b1ec6494541..dd7f5039a79d 100644
--- a/vendor/github.com/go-openapi/runtime/README.md
+++ b/vendor/github.com/go-openapi/runtime/README.md
@@ -1,7 +1,113 @@
-# runtime [](https://travis-ci.org/go-openapi/runtime) [](https://codecov.io/gh/go-openapi/runtime) [](https://slackin.goswagger.io)
+# runtime
-[](https://raw.githubusercontent.com/go-openapi/runtime/master/LICENSE) [](http://godoc.org/github.com/go-openapi/runtime)
+
+[![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]
-# golang Open-API toolkit - runtime
+---
-The runtime component for use in codegeneration or as untyped usage.
+A runtime for go OpenAPI toolkit.
+
+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**
+
+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.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/runtime
+```
+
+## Change log
+
+See
+
+For pre-v0.30.0 releases see [release notes](docs/NOTES.md).
+
+**What coming next?**
+
+Moving forward, we want to :
+
+* [ ] continue narrowing down the scope of dependencies:
+ * yaml support in an independent module
+ * 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)
+
+## Licensing
+
+This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
+
+See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software
+on top of which it has been built.
+
+## Other documentation
+
+* [FAQ](docs/FAQ.md)
+* [All-time contributors](./CONTRIBUTORS.md)
+* [Contributing guidelines](.github/CONTRIBUTING.md)
+* [Maintainers documentation](docs/MAINTAINERS.md)
+* [Code style](docs/STYLE.md)
+
+## Cutting a new release
+
+Maintainers can cut a new release by either:
+
+* running [this workflow](https://github.com/go-openapi/runtime/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/runtime/actions/workflows/go-test.yml/badge.svg
+[test-url]: https://github.com/go-openapi/runtime/actions/workflows/go-test.yml
+[cov-badge]: https://codecov.io/gh/go-openapi/runtime/branch/master/graph/badge.svg
+[cov-url]: https://codecov.io/gh/go-openapi/runtime
+[vuln-scan-badge]: https://github.com/go-openapi/runtime/actions/workflows/scanner.yml/badge.svg
+[vuln-scan-url]: https://github.com/go-openapi/runtime/actions/workflows/scanner.yml
+[codeql-badge]: https://github.com/go-openapi/runtime/actions/workflows/codeql.yml/badge.svg
+[codeql-url]: https://github.com/go-openapi/runtime/actions/workflows/codeql.yml
+
+[release-badge]: https://badge.fury.io/gh/go-openapi%2Fruntime.svg
+[release-url]: https://badge.fury.io/gh/go-openapi%2Fruntime
+
+[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/runtime
+[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/runtime
+[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/runtime
+[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/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/twZ9BwT3
+
+
+[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
+[license-url]: https://github.com/go-openapi/runtime/?tab=Apache-2.0-1-ov-file#readme
+
+[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/runtime
+[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
diff --git a/vendor/github.com/go-openapi/runtime/SECURITY.md b/vendor/github.com/go-openapi/runtime/SECURITY.md
new file mode 100644
index 000000000000..1fea2c5736a5
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/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/runtime/bytestream.go b/vendor/github.com/go-openapi/runtime/bytestream.go
index 4459025b9279..8701c8e3d661 100644
--- a/vendor/github.com/go-openapi/runtime/bytestream.go
+++ b/vendor/github.com/go-openapi/runtime/bytestream.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 runtime
@@ -22,14 +11,14 @@ import (
"io"
"reflect"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/jsonutils"
)
func defaultCloser() error { return nil }
type byteStreamOpt func(opts *byteStreamOpts)
-// ClosesStream when the bytestream consumer or producer is finished
+// ClosesStream when the bytestream consumer or producer is finished.
func ClosesStream(opts *byteStreamOpts) {
opts.Close = true
}
@@ -38,49 +27,91 @@ type byteStreamOpts struct {
Close bool
}
-// ByteStreamConsumer creates a consmer for byte streams,
-// takes a Writer/BinaryUnmarshaler interface or binary slice by reference,
-// and reads from the provided reader
+// ByteStreamConsumer creates a consumer for byte streams.
+//
+// The consumer consumes from a provided reader into the data passed by reference.
+//
+// Supported output underlying types and interfaces, prioritized in this order:
+//
+// - [io.ReaderFrom] (for maximum control)
+// - [io.Writer] (performs [io.Copy])
+// - [encoding.BinaryUnmarshaler]
+// - *string
+// - *[]byte
func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
var vals byteStreamOpts
for _, opt := range opts {
opt(&vals)
}
- return ConsumerFunc(func(reader io.Reader, data interface{}) error {
+ return ConsumerFunc(func(reader io.Reader, data any) error {
if reader == nil {
return errors.New("ByteStreamConsumer requires a reader") // early exit
}
+ if data == nil {
+ return errors.New("nil destination for ByteStreamConsumer")
+ }
- close := defaultCloser
+ closer := defaultCloser
if vals.Close {
- if cl, ok := reader.(io.Closer); ok {
- close = cl.Close
+ if cl, isReaderCloser := reader.(io.Closer); isReaderCloser {
+ closer = cl.Close
}
}
- defer close()
+ defer func() {
+ _ = closer()
+ }()
+
+ if readerFrom, isReaderFrom := data.(io.ReaderFrom); isReaderFrom {
+ _, err := readerFrom.ReadFrom(reader)
+ return err
+ }
- if wrtr, ok := data.(io.Writer); ok {
- _, err := io.Copy(wrtr, reader)
+ if writer, isDataWriter := data.(io.Writer); isDataWriter {
+ _, err := io.Copy(writer, reader)
return err
}
- buf := new(bytes.Buffer)
+ // buffers input before writing to data
+ var buf bytes.Buffer
_, err := buf.ReadFrom(reader)
if err != nil {
return err
}
b := buf.Bytes()
- if bu, ok := data.(encoding.BinaryUnmarshaler); ok {
- return bu.UnmarshalBinary(b)
- }
+ switch destinationPointer := data.(type) {
+ case encoding.BinaryUnmarshaler:
+ return destinationPointer.UnmarshalBinary(b)
+ case *any:
+ switch (*destinationPointer).(type) {
+ case string:
+ *destinationPointer = string(b)
+
+ return nil
+
+ case []byte:
+ *destinationPointer = b
+
+ return nil
+ }
+ default:
+ // check for the underlying type to be pointer to []byte or string,
+ if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr {
+ return errors.New("destination must be a pointer")
+ }
- if t := reflect.TypeOf(data); data != nil && t.Kind() == reflect.Ptr {
v := reflect.Indirect(reflect.ValueOf(data))
- if t = v.Type(); t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
v.SetBytes(b)
return nil
+
+ case t.Kind() == reflect.String:
+ v.SetString(string(b))
+ return nil
}
}
@@ -89,61 +120,88 @@ func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
})
}
-// ByteStreamProducer creates a producer for byte streams,
-// takes a Reader/BinaryMarshaler interface or binary slice,
-// and writes to a writer (essentially a pipe)
+// ByteStreamProducer creates a producer for byte streams.
+//
+// The producer takes input data then writes to an output writer (essentially as a pipe).
+//
+// 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.
func ByteStreamProducer(opts ...byteStreamOpt) Producer {
var vals byteStreamOpts
for _, opt := range opts {
opt(&vals)
}
- return ProducerFunc(func(writer io.Writer, data interface{}) error {
+
+ return ProducerFunc(func(writer io.Writer, data any) error {
if writer == nil {
return errors.New("ByteStreamProducer requires a writer") // early exit
}
- close := defaultCloser
+ if data == nil {
+ return errors.New("nil data for ByteStreamProducer")
+ }
+
+ closer := defaultCloser
if vals.Close {
- if cl, ok := writer.(io.Closer); ok {
- close = cl.Close
+ if cl, isWriterCloser := writer.(io.Closer); isWriterCloser {
+ closer = cl.Close
}
}
- defer close()
+ defer func() {
+ _ = closer()
+ }()
- if rc, ok := data.(io.ReadCloser); ok {
+ if rc, isDataCloser := data.(io.ReadCloser); isDataCloser {
defer rc.Close()
}
- if rdr, ok := data.(io.Reader); ok {
- _, err := io.Copy(writer, rdr)
+ switch origin := data.(type) {
+ case io.WriterTo:
+ _, err := origin.WriteTo(writer)
+ return err
+
+ case io.Reader:
+ _, err := io.Copy(writer, origin)
return err
- }
- if bm, ok := data.(encoding.BinaryMarshaler); ok {
- bytes, err := bm.MarshalBinary()
+ case encoding.BinaryMarshaler:
+ bytes, err := origin.MarshalBinary()
if err != nil {
return err
}
_, err = writer.Write(bytes)
return err
- }
- if data != nil {
- if e, ok := data.(error); ok {
- _, err := writer.Write([]byte(e.Error()))
- return err
- }
+ case error:
+ _, err := writer.Write([]byte(origin.Error()))
+ return err
+ default:
v := reflect.Indirect(reflect.ValueOf(data))
- if t := v.Type(); t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
_, err := writer.Write(v.Bytes())
return err
- }
- if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice {
- b, err := swag.WriteJSON(data)
+
+ case t.Kind() == reflect.String:
+ _, err := writer.Write([]byte(v.String()))
+ return err
+
+ case t.Kind() == reflect.Struct || t.Kind() == reflect.Slice:
+ b, err := jsonutils.WriteJSON(data)
if err != nil {
return err
}
+
_, err = writer.Write(b)
return err
}
diff --git a/vendor/github.com/go-openapi/runtime/client/auth_info.go b/vendor/github.com/go-openapi/runtime/client/auth_info.go
index bbe1479c35d2..fdaa08f2743b 100644
--- a/vendor/github.com/go-openapi/runtime/client/auth_info.go
+++ b/vendor/github.com/go-openapi/runtime/client/auth_info.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 client
@@ -22,22 +11,22 @@ import (
"github.com/go-openapi/runtime"
)
-// PassThroughAuth never manipulates the request
+// PassThroughAuth never manipulates the request.
var PassThroughAuth runtime.ClientAuthInfoWriter
func init() {
PassThroughAuth = runtime.ClientAuthInfoWriterFunc(func(_ runtime.ClientRequest, _ strfmt.Registry) error { return nil })
}
-// BasicAuth provides a basic auth info writer
+// BasicAuth provides a basic auth info writer.
func BasicAuth(username, password string) runtime.ClientAuthInfoWriter {
return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
encoded := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
- return r.SetHeaderParam("Authorization", "Basic "+encoded)
+ return r.SetHeaderParam(runtime.HeaderAuthorization, "Basic "+encoded)
})
}
-// APIKeyAuth provides an API key auth info writer
+// APIKeyAuth provides an API key auth info writer.
func APIKeyAuth(name, in, value string) runtime.ClientAuthInfoWriter {
if in == "query" {
return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
@@ -53,9 +42,25 @@ func APIKeyAuth(name, in, value string) runtime.ClientAuthInfoWriter {
return nil
}
-// BearerToken provides a header based oauth2 bearer access token auth info writer
+// BearerToken provides a header based oauth2 bearer access token auth info writer.
func BearerToken(token string) runtime.ClientAuthInfoWriter {
return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
- return r.SetHeaderParam("Authorization", "Bearer "+token)
+ return r.SetHeaderParam(runtime.HeaderAuthorization, "Bearer "+token)
+ })
+}
+
+// Compose combines multiple ClientAuthInfoWriters into a single one.
+// Useful when multiple auth headers are needed.
+func Compose(auths ...runtime.ClientAuthInfoWriter) runtime.ClientAuthInfoWriter {
+ return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
+ for _, auth := range auths {
+ if auth == nil {
+ continue
+ }
+ if err := auth.AuthenticateRequest(r, nil); err != nil {
+ return err
+ }
+ }
+ return nil
})
}
diff --git a/vendor/github.com/go-openapi/runtime/client/keepalive.go b/vendor/github.com/go-openapi/runtime/client/keepalive.go
index f83254515ba9..3bac5e272cf0 100644
--- a/vendor/github.com/go-openapi/runtime/client/keepalive.go
+++ b/vendor/github.com/go-openapi/runtime/client/keepalive.go
@@ -1,8 +1,10 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package client
import (
"io"
- "io/ioutil"
"net/http"
"sync/atomic"
)
@@ -11,7 +13,7 @@ import (
// so that go will reuse the TCP connections.
// This is not enabled by default because there are servers where
// the response never gets closed and that would make the code hang forever.
-// So instead it's provided as a http client middleware that can be used to override
+// So instead it's provided as a [http] client [middleware] that can be used to override
// any request.
func KeepAliveTransport(rt http.RoundTripper) http.RoundTripper {
return &keepAliveTransport{wrapped: rt}
@@ -46,8 +48,10 @@ func (d *drainingReadCloser) Read(p []byte) (n int, err error) {
func (d *drainingReadCloser) Close() error {
// drain buffer
if atomic.LoadUint32(&d.seenEOF) != 1 {
- //#nosec
- io.Copy(ioutil.Discard, d.rdr)
+ // 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.
+ _, _ = io.Copy(io.Discard, d.rdr)
}
return d.rdr.Close()
}
diff --git a/vendor/github.com/go-openapi/runtime/client/opentelemetry.go b/vendor/github.com/go-openapi/runtime/client/opentelemetry.go
new file mode 100644
index 000000000000..5054878c06c5
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/client/opentelemetry.go
@@ -0,0 +1,218 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package client
+
+import (
+ "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"
+)
+
+const (
+ instrumentationVersion = "1.0.0"
+ tracerName = "go-openapi"
+)
+
+type config struct {
+ Tracer trace.Tracer
+ Propagator propagation.TextMapPropagator
+ SpanStartOptions []trace.SpanStartOption
+ SpanNameFormatter func(*runtime.ClientOperation) string
+ TracerProvider trace.TracerProvider
+}
+
+type OpenTelemetryOpt interface {
+ apply(*config)
+}
+
+type optionFunc func(*config)
+
+func (o optionFunc) apply(c *config) {
+ o(c)
+}
+
+// WithTracerProvider specifies a tracer provider to use for creating a tracer.
+// If none is specified, the global provider is used.
+func WithTracerProvider(provider trace.TracerProvider) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ if provider != nil {
+ c.TracerProvider = provider
+ }
+ })
+}
+
+// WithPropagators configures specific propagators. If this
+// option isn't specified, then the global TextMapPropagator is used.
+func WithPropagators(ps propagation.TextMapPropagator) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ if ps != nil {
+ c.Propagator = ps
+ }
+ })
+}
+
+// WithSpanOptions configures an additional set of
+// trace.SpanOptions, which are applied to each new span.
+func WithSpanOptions(opts ...trace.SpanStartOption) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ c.SpanStartOptions = append(c.SpanStartOptions, opts...)
+ })
+}
+
+// WithSpanNameFormatter takes a function that will be called on every
+// request and the returned string will become the Span Name.
+func WithSpanNameFormatter(f func(op *runtime.ClientOperation) string) OpenTelemetryOpt {
+ return optionFunc(func(c *config) {
+ c.SpanNameFormatter = f
+ })
+}
+
+func defaultTransportFormatter(op *runtime.ClientOperation) string {
+ if op.ID != "" {
+ return op.ID
+ }
+
+ return fmt.Sprintf("%s_%s", strings.ToLower(op.Method), op.PathPattern)
+}
+
+type openTelemetryTransport struct {
+ transport runtime.ClientTransport
+ host string
+ tracer trace.Tracer
+ config *config
+}
+
+func newOpenTelemetryTransport(transport runtime.ClientTransport, host string, opts []OpenTelemetryOpt) *openTelemetryTransport {
+ tr := &openTelemetryTransport{
+ transport: transport,
+ host: host,
+ }
+
+ const baseOptions = 4
+ defaultOpts := make([]OpenTelemetryOpt, 0, len(opts)+baseOptions)
+ defaultOpts = append(defaultOpts,
+ WithSpanOptions(trace.WithSpanKind(trace.SpanKindClient)),
+ WithSpanNameFormatter(defaultTransportFormatter),
+ WithPropagators(otel.GetTextMapPropagator()),
+ WithTracerProvider(otel.GetTracerProvider()),
+ )
+
+ c := newConfig(append(defaultOpts, opts...)...)
+ tr.config = c
+
+ return tr
+}
+
+func (t *openTelemetryTransport) Submit(op *runtime.ClientOperation) (any, error) {
+ if op.Context == nil {
+ return t.transport.Submit(op)
+ }
+
+ params := op.Params
+ reader := op.Reader
+
+ var span trace.Span
+ defer func() {
+ if span != nil {
+ span.End()
+ }
+ }()
+
+ op.Params = runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
+ span = t.newOpenTelemetrySpan(op, req.GetHeaderParams())
+ return params.WriteToRequest(req, reg)
+ })
+
+ op.Reader = runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (any, error) {
+ if span != nil {
+ statusCode := response.Code()
+ // NOTE: this is replaced by semconv.HTTPResponseStatusCode in semconv v1.21
+ span.SetAttributes(semconv.HTTPResponseStatusCode(statusCode))
+ // NOTE: the conversion from HTTP status code to trace code is no longer available with
+ // semconv v1.21
+ const minHTTPStatusIsError = 400
+ if statusCode >= minHTTPStatusIsError {
+ span.SetStatus(codes.Error, http.StatusText(statusCode))
+ }
+ }
+
+ return reader.ReadResponse(response, consumer)
+ })
+
+ submit, err := t.transport.Submit(op)
+ if err != nil && span != nil {
+ span.RecordError(err)
+ span.SetStatus(codes.Error, err.Error())
+ }
+
+ return submit, err
+}
+
+func (t *openTelemetryTransport) newOpenTelemetrySpan(op *runtime.ClientOperation, header http.Header) trace.Span {
+ ctx := op.Context
+
+ tracer := t.tracer
+ if tracer == nil {
+ if span := trace.SpanFromContext(ctx); span.SpanContext().IsValid() {
+ tracer = newTracer(span.TracerProvider())
+ } else {
+ tracer = newTracer(otel.GetTracerProvider())
+ }
+ }
+
+ ctx, span := tracer.Start(ctx, t.config.SpanNameFormatter(op), t.config.SpanStartOptions...)
+
+ var scheme string
+ if len(op.Schemes) > 0 {
+ scheme = op.Schemes[0]
+ }
+
+ span.SetAttributes(
+ attribute.String("net.peer.name", t.host),
+ attribute.String(string(semconv.HTTPRouteKey), op.PathPattern),
+ attribute.String(string(semconv.HTTPRequestMethodKey), op.Method),
+ attribute.String("span.kind", trace.SpanKindClient.String()),
+ attribute.String("http.scheme", scheme),
+ )
+
+ carrier := propagation.HeaderCarrier(header)
+ t.config.Propagator.Inject(ctx, carrier)
+
+ return span
+}
+
+func newTracer(tp trace.TracerProvider) trace.Tracer {
+ return tp.Tracer(tracerName, trace.WithInstrumentationVersion(version()))
+}
+
+func newConfig(opts ...OpenTelemetryOpt) *config {
+ c := &config{
+ Propagator: otel.GetTextMapPropagator(),
+ }
+
+ for _, opt := range opts {
+ opt.apply(c)
+ }
+
+ // Tracer is only initialized if manually specified. Otherwise, can be passed with the tracing context.
+ if c.TracerProvider != nil {
+ c.Tracer = newTracer(c.TracerProvider)
+ }
+
+ return c
+}
+
+// Version is the current release version of the go-runtime instrumentation.
+func version() string {
+ return instrumentationVersion
+}
diff --git a/vendor/github.com/go-openapi/runtime/client/request.go b/vendor/github.com/go-openapi/runtime/client/request.go
index b7ea8b811b5b..f16ee487bab6 100644
--- a/vendor/github.com/go-openapi/runtime/client/request.go
+++ b/vendor/github.com/go-openapi/runtime/client/request.go
@@ -1,21 +1,11 @@
-// 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 client
import (
"bytes"
+ "context"
"fmt"
"io"
"log"
@@ -29,23 +19,11 @@ import (
"strings"
"time"
- "github.com/go-openapi/strfmt"
-
"github.com/go-openapi/runtime"
+ "github.com/go-openapi/strfmt"
)
-// NewRequest creates a new swagger http client request
-func newRequest(method, pathPattern string, writer runtime.ClientRequestWriter) (*request, error) {
- return &request{
- pathPattern: pathPattern,
- method: method,
- writer: writer,
- header: make(http.Header),
- query: make(url.Values),
- timeout: DefaultTimeout,
- getBody: getRequestBuffer,
- }, nil
-}
+var _ runtime.ClientRequest = new(request) // ensure compliance to the interface
// Request represents a swagger client request.
//
@@ -66,17 +44,149 @@ type request struct {
query url.Values
formFields url.Values
fileFields map[string][]runtime.NamedReadCloser
- payload interface{}
+ payload any
timeout time.Duration
buf *bytes.Buffer
getBody func(r *request) []byte
}
-var (
- // ensure interface compliance
- _ runtime.ClientRequest = new(request)
-)
+// 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 {
@@ -86,14 +196,7 @@ func (r *request) isMultipart(mediaType string) bool {
return runtime.MultipartFormMime == mediaType
}
-// 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 escapeQuotes(s string) string {
- return strings.NewReplacer("\\", "\\\\", `"`, "\\\"").Replace(s)
-}
-func (r *request) buildHTTP(mediaType, basePath string, producers map[string]runtime.Producer, registry strfmt.Registry, auth runtime.ClientAuthInfoWriter) (*http.Request, error) {
+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
@@ -137,8 +240,8 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
for fn, v := range r.formFields {
for _, vi := range v {
if err := mp.WriteField(fn, vi); err != nil {
- pw.CloseWithError(err)
- log.Println(err)
+ logClose(err, pw)
+ return
}
}
}
@@ -152,18 +255,23 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
}()
for fn, f := range r.fileFields {
for _, fi := range f {
- buf := bytes.NewBuffer([]byte{})
-
- // Need to read the data so that we can detect the content type
- _, err := io.Copy(buf, fi)
- if err != nil {
- _ = pw.CloseWithError(err)
- log.Println(err)
+ 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))
}
- fileBytes := buf.Bytes()
- fileContentType := http.DetectContentType(fileBytes)
-
- newFi := runtime.NamedReader(fi.Name(), buf)
// Create the MIME headers for the new part
h := make(textproto.MIMEHeader)
@@ -174,11 +282,11 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
wrtr, err := mp.CreatePart(h)
if err != nil {
- pw.CloseWithError(err)
- log.Println(err)
- } else if _, err := io.Copy(wrtr, newFi); err != nil {
- pw.CloseWithError(err)
- log.Println(err)
+ logClose(err, pw)
+ return
+ }
+ if _, err := io.Copy(wrtr, fi); err != nil {
+ logClose(err, pw)
}
}
}
@@ -190,8 +298,7 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
// 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 {
- // TODO: infer most appropriate content type based on the producer used,
- // and the `consumers` section of the spec/operation
+ // 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
@@ -211,7 +318,7 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
DoneChoosingBodySource:
- if runtime.CanHaveBody(r.method) && body == nil && r.header.Get(runtime.HeaderContentType) == "" {
+ if runtime.CanHaveBody(r.method) && body != nil && r.header.Get(runtime.HeaderContentType) == "" {
r.header.Set(runtime.HeaderContentType, mediaType)
}
@@ -273,51 +380,69 @@ DoneChoosingBodySource:
}
}
+ // 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 r.pathPattern != "" && r.pathPattern != "/" && r.pathPattern[len(r.pathPattern)-1] == '/' {
+ if pathPatternURL.Path != "" && pathPatternURL.Path != "/" && pathPatternURL.Path[len(pathPatternURL.Path)-1] == '/' {
reinstateSlash = true
}
- urlPath := path.Join(basePath, r.pathPattern)
+
+ urlPath := path.Join(basePathURL.Path, pathPatternURL.Path)
for k, v := range r.pathParams {
- urlPath = strings.Replace(urlPath, "{"+k+"}", url.PathEscape(v), -1)
+ urlPath = strings.ReplaceAll(urlPath, "{"+k+"}", url.PathEscape(v))
}
if reinstateSlash {
- urlPath = urlPath + "/"
+ urlPath += "/"
}
- req, err := http.NewRequest(r.method, urlPath, body)
+ req, err := http.NewRequestWithContext(context.Background(), r.method, urlPath, body)
if err != nil {
return nil, err
}
- req.URL.RawQuery = r.query.Encode()
- req.Header = r.header
+ originalParams := r.GetQueryParams()
- return req, nil
-}
-
-func mangleContentType(mediaType, boundary string) string {
- if strings.ToLower(mediaType) == runtime.URLencodedFormMime {
- return fmt.Sprintf("%s; boundary=%s", mediaType, boundary)
+ // 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
+ }
+ }
}
- return "multipart/form-data; boundary=" + boundary
-}
-func (r *request) GetMethod() string {
- return r.method
-}
+ req.URL.RawQuery = r.query.Encode()
+ req.Header = r.header
-func (r *request) GetPath() string {
- path := r.pathPattern
- for k, v := range r.pathParams {
- path = strings.Replace(path, "{"+k+"}", v, -1)
- }
- return path
+ return req, nil
}
-func (r *request) GetBody() []byte {
- return r.getBody(r)
+func escapeQuotes(s string) string {
+ return strings.NewReplacer("\\", "\\\\", `"`, "\\\"").Replace(s)
}
func getRequestBuffer(r *request) []byte {
@@ -327,105 +452,17 @@ func getRequestBuffer(r *request) []byte {
return r.buf.Bytes()
}
-// 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)
+func logClose(err error, pw *io.PipeWriter) {
+ log.Println(err)
+ closeErr := pw.CloseWithError(err)
+ if closeErr != nil {
+ log.Println(closeErr)
}
- 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)
+func mangleContentType(mediaType, boundary string) string {
+ if strings.ToLower(mediaType) == runtime.URLencodedFormMime {
+ return fmt.Sprintf("%s; boundary=%s", mediaType, boundary)
}
-
- 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 interface{}) error {
- r.payload = payload
- return nil
-}
-
-func (r *request) GetBodyParam() interface{} {
- return r.payload
-}
-
-// SetTimeout sets the timeout for a request
-func (r *request) SetTimeout(timeout time.Duration) error {
- r.timeout = timeout
- return nil
+ return "multipart/form-data; boundary=" + boundary
}
diff --git a/vendor/github.com/go-openapi/runtime/client/response.go b/vendor/github.com/go-openapi/runtime/client/response.go
index bd238588b7d0..59abc3b549a3 100644
--- a/vendor/github.com/go-openapi/runtime/client/response.go
+++ b/vendor/github.com/go-openapi/runtime/client/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 client
@@ -23,6 +12,8 @@ import (
var _ runtime.ClientResponse = response{}
+func newResponse(resp *http.Response) runtime.ClientResponse { return response{resp: resp} }
+
type response struct {
resp *http.Response
}
@@ -39,6 +30,10 @@ func (r response) GetHeader(name string) string {
return r.resp.Header.Get(name)
}
+func (r response) GetHeaders(name string) []string {
+ return r.resp.Header.Values(name)
+}
+
func (r response) Body() io.ReadCloser {
return r.resp.Body
}
diff --git a/vendor/github.com/go-openapi/runtime/client/runtime.go b/vendor/github.com/go-openapi/runtime/client/runtime.go
index 083d751e3cae..eeb17dfb24e8 100644
--- a/vendor/github.com/go-openapi/runtime/client/runtime.go
+++ b/vendor/github.com/go-openapi/runtime/client/runtime.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 client
@@ -22,24 +11,32 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
+ "errors"
"fmt"
- "io/ioutil"
"mime"
"net/http"
"net/http/httputil"
+ "os"
"strings"
"sync"
"time"
- "github.com/go-openapi/strfmt"
-
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/logger"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/runtime/yamlpc"
+ "github.com/go-openapi/strfmt"
)
-// TLSClientOptions to configure client authentication with mutual TLS
+const (
+ schemeHTTP = "http"
+ schemeHTTPS = "https"
+)
+
+// 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.
@@ -69,7 +66,7 @@ type TLSClientOptions struct {
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 the other loaded certificates (see LoadedCA and CA).
+ // 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.
@@ -81,7 +78,7 @@ type TLSClientOptions struct {
ServerName string
// InsecureSkipVerify controls whether the certificate chain and hostname presented
- // by the server are validated. If false, any certificate is accepted.
+ // by the server are validated. If true, any certificate is accepted.
InsecureSkipVerify bool
// VerifyPeerCertificate, if not nil, is called after normal
@@ -95,6 +92,17 @@ type TLSClientOptions struct {
// 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.
@@ -108,10 +116,12 @@ type TLSClientOptions struct {
_ struct{}
}
-// TLSClientAuth creates a tls.Config for mutual auth
+// TLSClientAuth creates a [tls.Config] for mutual auth.
func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
// create client tls config
- cfg := &tls.Config{}
+ cfg := &tls.Config{
+ MinVersion: tls.VersionTLS12,
+ }
// load client cert if specified
if opts.Certificate != "" {
@@ -135,7 +145,7 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
return nil, fmt.Errorf("tls client priv key: %v", err)
}
default:
- return nil, fmt.Errorf("tls client priv key: unsupported key type")
+ return nil, errors.New("tls client priv key: unsupported key type")
}
block = pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes}
@@ -151,26 +161,28 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
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
- if opts.LoadedCA != nil {
+ switch {
+ case opts.LoadedCA != nil:
caCertPool := basePool(opts.LoadedCAPool)
caCertPool.AddCert(opts.LoadedCA)
cfg.RootCAs = caCertPool
- } else if opts.CA != "" {
+ case opts.CA != "":
// load ca cert
- caCert, err := ioutil.ReadFile(opts.CA)
+ 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
- } else if opts.LoadedCAPool != nil {
+ case opts.LoadedCAPool != nil:
cfg.RootCAs = opts.LoadedCAPool
}
@@ -180,19 +192,10 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) {
cfg.ServerName = opts.ServerName
}
- cfg.BuildNameToCertificate()
-
return cfg, nil
}
-func basePool(pool *x509.CertPool) *x509.CertPool {
- if pool == nil {
- return x509.NewCertPool()
- }
- return pool
-}
-
-// TLSTransport creates a http client transport suitable for mutual tls auth
+// 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 {
@@ -202,7 +205,7 @@ func TLSTransport(opts TLSClientOptions) (http.RoundTripper, error) {
return &http.Transport{TLSClientConfig: cfg}, nil
}
-// TLSClient creates a http.Client for mutual auth
+// TLSClient creates a [http.Client] for mutual auth.
func TLSClient(opts TLSClientOptions) (*http.Client, error) {
transport, err := TLSTransport(opts)
if err != nil {
@@ -211,11 +214,8 @@ func TLSClient(opts TLSClientOptions) (*http.Client, error) {
return &http.Client{Transport: transport}, nil
}
-// DefaultTimeout the default request timeout
-var DefaultTimeout = 30 * time.Second
-
// Runtime represents an API client that uses the transport
-// to make http requests based on a swagger specification.
+// to make [http] requests based on a swagger specification.
type Runtime struct {
DefaultMediaType string
DefaultAuthentication runtime.ClientAuthInfoWriter
@@ -224,11 +224,11 @@ type Runtime struct {
Transport http.RoundTripper
Jar http.CookieJar
- //Spec *spec.Document
+ // Spec *spec.Document
Host string
BasePath string
Formats strfmt.Registry
- Context context.Context
+ Context context.Context //nolint:containedctx // we precisely want this type to contain the request context
Debug bool
logger logger.Logger
@@ -236,14 +236,15 @@ type Runtime struct {
clientOnce *sync.Once
client *http.Client
schemes []string
+ response ClientResponseFunc
}
-// New creates a new default runtime for a swagger api runtime.Client
+// New creates a new default runtime for a swagger api runtime.Client.
func New(host, basePath string, schemes []string) *Runtime {
var rt Runtime
rt.DefaultMediaType = runtime.JSONMime
- // TODO: actually infer this stuff from the spec
+ // Enhancement proposal: https://github.com/go-openapi/runtime/issues/385
rt.Consumers = map[string]runtime.Consumer{
runtime.YAMLMime: yamlpc.YAMLConsumer(),
runtime.JSONMime: runtime.JSONConsumer(),
@@ -274,6 +275,7 @@ func New(host, basePath string, schemes []string) *Runtime {
rt.Debug = logger.DebugEnabled()
rt.logger = logger.StandardLogger{}
+ rt.response = newResponse
if len(schemes) > 0 {
rt.schemes = schemes
@@ -281,7 +283,7 @@ func New(host, basePath string, schemes []string) *Runtime {
return &rt
}
-// NewWithClient allows you to create a new transport with a configured http.Client
+// NewWithClient allows you to create a new transport with a configured [http.Client].
func NewWithClient(host, basePath string, schemes []string, client *http.Client) *Runtime {
rt := New(host, basePath, schemes)
if client != nil {
@@ -292,39 +294,45 @@ func NewWithClient(host, basePath string, schemes []string, client *http.Client)
return rt
}
-func (r *Runtime) pickScheme(schemes []string) string {
- if v := r.selectScheme(r.schemes); v != "" {
- return v
- }
- if v := r.selectScheme(schemes); v != "" {
- return v
- }
- return "http"
-}
-
-func (r *Runtime) selectScheme(schemes []string) string {
- schLen := len(schemes)
- if schLen == 0 {
- return ""
- }
-
- scheme := schemes[0]
- // prefer https, but skip when not possible
- if scheme != "https" && schLen > 1 {
- for _, sch := range schemes {
- if sch == "https" {
- scheme = sch
- break
- }
+// 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 scheme
+
+ return r.WithOpenTelemetry(otelOpts...)
}
-func transportOrDefault(left, right http.RoundTripper) http.RoundTripper {
- if left == nil {
- return right
- }
- return left
+
+// 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
@@ -332,7 +340,7 @@ func transportOrDefault(left, right http.RoundTripper) http.RoundTripper {
//
// This is not enabled by default because there are servers where
// the response never gets closed and that would make the code hang forever.
-// So instead it's provided as a http client middleware that can be used to override
+// So instead it's provided as a [http] client [middleware] that can be used to override
// any request.
func (r *Runtime) EnableConnectionReuse() {
if r.client == nil {
@@ -349,52 +357,20 @@ func (r *Runtime) EnableConnectionReuse() {
)
}
-// 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
-func (r *Runtime) Submit(operation *runtime.ClientOperation) (interface{}, error) {
- params, readResponse, auth := operation.Params, operation.Reader, operation.AuthInfo
-
- request, err := newRequest(operation.Method, operation.PathPattern, params)
- if err != nil {
- return nil, err
- }
-
- var accept []string
- accept = append(accept, operation.ProducesMediaTypes...)
- if err = request.SetHeaderParam(runtime.HeaderAccept, accept...); err != nil {
- return nil, err
- }
-
- if auth == nil && r.DefaultAuthentication != nil {
- auth = r.DefaultAuthentication
- }
- //if auth != nil {
- // if err := auth.AuthenticateRequest(request, r.Formats); err != nil {
- // return nil, err
- // }
- //}
-
- // TODO: pick appropriate media type
- cmt := r.DefaultMediaType
- for _, mediaType := range operation.ConsumesMediaTypes {
- // Pick first non-empty media type
- if mediaType != "" {
- cmt = mediaType
- break
- }
- }
+func (r *Runtime) CreateHttpRequest(operation *runtime.ClientOperation) (req *http.Request, err error) { //nolint:revive
+ _, req, err = r.createHttpRequest(operation)
+ return
+}
- if _, ok := r.Producers[cmt]; !ok && cmt != runtime.MultipartFormMime && cmt != runtime.URLencodedFormMime {
- return nil, fmt.Errorf("none of producers: %v registered. try %s", r.Producers, cmt)
- }
+// 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.
+func (r *Runtime) Submit(operation *runtime.ClientOperation) (any, error) {
+ _, readResponse, _ := operation.Params, operation.Reader, operation.AuthInfo
- req, err := request.buildHTTP(cmt, r.BasePath, r.Producers, r.Formats, auth)
+ request, req, err := r.createHttpRequest(operation)
if err != nil {
return nil, err
}
- req.URL.Scheme = r.pickScheme(operation.Schemes)
- req.URL.Host = r.Host
- req.Host = r.Host
r.clientOnce.Do(func() {
r.client = &http.Client{
@@ -411,27 +387,36 @@ func (r *Runtime) Submit(operation *runtime.ClientOperation) (interface{}, error
r.logger.Debugf("%s\n", string(b))
}
- var hasTimeout bool
- pctx := operation.Context
- if pctx == nil {
- pctx = r.Context
- } else {
- hasTimeout = true
- }
- if pctx == nil {
- pctx = context.Background()
+ var parentCtx context.Context
+ switch {
+ case operation.Context != nil:
+ parentCtx = operation.Context
+ case r.Context != nil:
+ parentCtx = r.Context
+ default:
+ parentCtx = context.Background()
}
- var ctx context.Context
- var cancel context.CancelFunc
- if hasTimeout {
- ctx, cancel = context.WithCancel(pctx)
+
+ 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 {
- ctx, cancel = context.WithTimeout(pctx, request.timeout)
+ // 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)
}
defer cancel()
- client := operation.Client
- if client == nil {
+ var client *http.Client
+ if operation.Client != nil {
+ client = operation.Client
+ } else {
client = r.client
}
req = req.WithContext(ctx)
@@ -441,19 +426,23 @@ func (r *Runtime) Submit(operation *runtime.ClientOperation) (interface{}, error
}
defer res.Body.Close()
+ ct := res.Header.Get(runtime.HeaderContentType)
+ if ct == "" { // this should really never occur
+ ct = r.DefaultMediaType
+ }
+
if r.Debug {
- b, err2 := httputil.DumpResponse(res, true)
+ 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))
}
- ct := res.Header.Get(runtime.HeaderContentType)
- if ct == "" { // this should really really never occur
- ct = r.DefaultMediaType
- }
-
mt, _, err := mime.ParseMediaType(ct)
if err != nil {
return nil, fmt.Errorf("parse content type: %s", err)
@@ -466,7 +455,7 @@ func (r *Runtime) Submit(operation *runtime.ClientOperation) (interface{}, error
return nil, fmt.Errorf("no consumer: %q", ct)
}
}
- return readResponse.ReadResponse(response{res}, cons)
+ return readResponse.ReadResponse(r.response(res), cons)
}
// SetDebug changes the debug flag.
@@ -482,3 +471,106 @@ func (r *Runtime) SetLogger(logger logger.Logger) {
r.logger = logger
middleware.Logger = logger
}
+
+type ClientResponseFunc = func(*http.Response) runtime.ClientResponse //nolint:revive
+
+// SetResponseReader changes the response reader implementation.
+func (r *Runtime) SetResponseReader(f ClientResponseFunc) {
+ if f == nil {
+ return
+ }
+ r.response = f
+}
+
+func (r *Runtime) pickScheme(schemes []string) string {
+ if v := r.selectScheme(r.schemes); v != "" {
+ return v
+ }
+ if v := r.selectScheme(schemes); v != "" {
+ return v
+ }
+ return schemeHTTP
+}
+
+func (r *Runtime) selectScheme(schemes []string) string {
+ schLen := len(schemes)
+ if schLen == 0 {
+ return ""
+ }
+
+ scheme := schemes[0]
+ // prefer https, but skip when not possible
+ if scheme != schemeHTTPS && schLen > 1 {
+ for _, sch := range schemes {
+ if sch == schemeHTTPS {
+ scheme = sch
+ break
+ }
+ }
+ }
+ return scheme
+}
+
+func transportOrDefault(left, right http.RoundTripper) http.RoundTripper {
+ if left == nil {
+ return right
+ }
+ return left
+}
+
+// takes a client operation and creates equivalent http.Request.
+func (r *Runtime) createHttpRequest(operation *runtime.ClientOperation) (*request, *http.Request, error) { //nolint:revive
+ params, _, auth := operation.Params, operation.Reader, operation.AuthInfo
+
+ request := newRequest(operation.Method, operation.PathPattern, params)
+
+ 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 auth == nil && r.DefaultAuthentication != nil {
+ auth = runtime.ClientAuthInfoWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error {
+ if req.GetHeaderParams().Get(runtime.HeaderAuthorization) != "" {
+ return nil
+ }
+ 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)
+ }
+
+ 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
+}
+
+func basePool(pool *x509.CertPool) *x509.CertPool {
+ if pool == nil {
+ return x509.NewCertPool()
+ }
+ return pool
+}
diff --git a/vendor/github.com/go-openapi/runtime/client_auth_info.go b/vendor/github.com/go-openapi/runtime/client_auth_info.go
index c6c97d9a7c34..5ef59c88bf49 100644
--- a/vendor/github.com/go-openapi/runtime/client_auth_info.go
+++ b/vendor/github.com/go-openapi/runtime/client_auth_info.go
@@ -1,30 +1,19 @@
-// 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 runtime
import "github.com/go-openapi/strfmt"
-// A ClientAuthInfoWriterFunc converts a function to a request writer interface
+// A ClientAuthInfoWriterFunc converts a function to a request writer interface.
type ClientAuthInfoWriterFunc func(ClientRequest, strfmt.Registry) error
-// AuthenticateRequest adds authentication data to the request
+// AuthenticateRequest adds authentication data to the request.
func (fn ClientAuthInfoWriterFunc) AuthenticateRequest(req ClientRequest, reg strfmt.Registry) error {
return fn(req, reg)
}
-// A ClientAuthInfoWriter implementor knows how to write authentication info to a request
+// A ClientAuthInfoWriter implementor knows how to write authentication info to a request.
type ClientAuthInfoWriter interface {
AuthenticateRequest(ClientRequest, strfmt.Registry) error
}
diff --git a/vendor/github.com/go-openapi/runtime/client_operation.go b/vendor/github.com/go-openapi/runtime/client_operation.go
index fa21eacf3301..ad7277e091fd 100644
--- a/vendor/github.com/go-openapi/runtime/client_operation.go
+++ b/vendor/github.com/go-openapi/runtime/client_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 runtime
@@ -19,7 +8,7 @@ import (
"net/http"
)
-// ClientOperation represents the context for a swagger operation to be submitted to the transport
+// ClientOperation represents the context for a swagger operation to be submitted to the transport.
type ClientOperation struct {
ID string
Method string
@@ -30,12 +19,12 @@ type ClientOperation struct {
AuthInfo ClientAuthInfoWriter
Params ClientRequestWriter
Reader ClientResponseReader
- Context context.Context
+ 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
+// A ClientTransport implementor knows how to submit Request objects to some destination.
type ClientTransport interface {
- //Submit(string, RequestWriter, ResponseReader, AuthInfoWriter) (interface{}, error)
- Submit(*ClientOperation) (interface{}, error)
+ // Submit(string, RequestWriter, ResponseReader, AuthInfoWriter) (interface{}, error)
+ Submit(*ClientOperation) (any, error)
}
diff --git a/vendor/github.com/go-openapi/runtime/client_request.go b/vendor/github.com/go-openapi/runtime/client_request.go
index 6215e0a1c1fc..844f57b3ce9b 100644
--- a/vendor/github.com/go-openapi/runtime/client_request.go
+++ b/vendor/github.com/go-openapi/runtime/client_request.go
@@ -1,22 +1,10 @@
-// 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 runtime
import (
"io"
- "io/ioutil"
"net/http"
"net/url"
"time"
@@ -24,22 +12,22 @@ import (
"github.com/go-openapi/strfmt"
)
-// ClientRequestWriterFunc converts a function to a request writer interface
+// ClientRequestWriterFunc converts a function to a request writer interface.
type ClientRequestWriterFunc func(ClientRequest, strfmt.Registry) error
-// WriteToRequest adds data to the request
+// WriteToRequest adds data to the request.
func (fn ClientRequestWriterFunc) WriteToRequest(req ClientRequest, reg strfmt.Registry) error {
return fn(req, reg)
}
-// ClientRequestWriter is an interface for things that know how to write to a request
+// ClientRequestWriter is an interface for things that know how to write to a request.
type ClientRequestWriter interface {
WriteToRequest(ClientRequest, strfmt.Registry) error
}
// ClientRequest is an interface for things that know how to
-// add information to a swagger client request
-type ClientRequest interface {
+// add information to a swagger client request.
+type ClientRequest interface { //nolint:interfacebloat // a swagger-capable request is quite rich, hence the many getter/setters
SetHeaderParam(string, ...string) error
GetHeaderParams() http.Header
@@ -54,7 +42,7 @@ type ClientRequest interface {
SetFileParam(string, ...NamedReadCloser) error
- SetBodyParam(interface{}) error
+ SetBodyParam(any) error
SetTimeout(time.Duration) error
@@ -64,22 +52,22 @@ type ClientRequest interface {
GetBody() []byte
- GetBodyParam() interface{}
+ GetBodyParam() any
GetFileParam() map[string][]NamedReadCloser
}
-// NamedReadCloser represents a named ReadCloser interface
+// NamedReadCloser represents a named ReadCloser interface.
type NamedReadCloser interface {
io.ReadCloser
Name() string
}
-// NamedReader creates a NamedReadCloser for use as file upload
+// NamedReader creates a [NamedReadCloser] for use as file upload.
func NamedReader(name string, rdr io.Reader) NamedReadCloser {
rc, ok := rdr.(io.ReadCloser)
if !ok {
- rc = ioutil.NopCloser(rdr)
+ rc = io.NopCloser(rdr)
}
return &namedReadCloser{
name: name,
@@ -101,3 +89,53 @@ func (n *namedReadCloser) Read(p []byte) (int, error) {
func (n *namedReadCloser) Name() string {
return n.name
}
+
+type TestClientRequest struct {
+ Headers http.Header
+ Body any
+}
+
+func (t *TestClientRequest) SetHeaderParam(name string, values ...string) error {
+ if t.Headers == nil {
+ t.Headers = make(http.Header)
+ }
+ t.Headers.Set(name, values[0])
+ return nil
+}
+
+func (t *TestClientRequest) SetQueryParam(_ string, _ ...string) error { return nil }
+
+func (t *TestClientRequest) SetFormParam(_ string, _ ...string) error { return nil }
+
+func (t *TestClientRequest) SetPathParam(_ string, _ string) error { return nil }
+
+func (t *TestClientRequest) SetFileParam(_ string, _ ...NamedReadCloser) error { return nil }
+
+func (t *TestClientRequest) SetBodyParam(body any) error {
+ t.Body = body
+ return nil
+}
+
+func (t *TestClientRequest) SetTimeout(time.Duration) error {
+ return nil
+}
+
+func (t *TestClientRequest) GetQueryParams() url.Values { return nil }
+
+func (t *TestClientRequest) GetMethod() string { return "" }
+
+func (t *TestClientRequest) GetPath() string { return "" }
+
+func (t *TestClientRequest) GetBody() []byte { return nil }
+
+func (t *TestClientRequest) GetBodyParam() any {
+ return t.Body
+}
+
+func (t *TestClientRequest) GetFileParam() map[string][]NamedReadCloser {
+ return nil
+}
+
+func (t *TestClientRequest) GetHeaderParams() http.Header {
+ return t.Headers
+}
diff --git a/vendor/github.com/go-openapi/runtime/client_response.go b/vendor/github.com/go-openapi/runtime/client_response.go
index d97e0ac64fce..92668db4ece8 100644
--- a/vendor/github.com/go-openapi/runtime/client_response.go
+++ b/vendor/github.com/go-openapi/runtime/client_response.go
@@ -1,51 +1,49 @@
-// 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 runtime
import (
+ "encoding/json"
"fmt"
"io"
-
- "encoding/json"
+ "strings"
)
-// A ClientResponse represents a client response
-// This bridges between responses obtained from different transports
+// A ClientResponse represents a client response.
+//
+// This bridges between responses obtained from different transports.
type ClientResponse interface {
Code() int
Message() string
GetHeader(string) string
+ GetHeaders(string) []string
Body() io.ReadCloser
}
-// A ClientResponseReaderFunc turns a function into a ClientResponseReader interface implementation
-type ClientResponseReaderFunc func(ClientResponse, Consumer) (interface{}, error)
+// A ClientResponseReaderFunc turns a function into a [ClientResponseReader] interface implementation.
+type ClientResponseReaderFunc func(ClientResponse, Consumer) (any, error)
-// ReadResponse reads the response
-func (read ClientResponseReaderFunc) ReadResponse(resp ClientResponse, consumer Consumer) (interface{}, error) {
+// ReadResponse reads the response.
+func (read ClientResponseReaderFunc) ReadResponse(resp ClientResponse, consumer Consumer) (any, error) {
return read(resp, consumer)
}
// A ClientResponseReader is an interface for things want to read a response.
-// An application of this is to create structs from response values
+// An application of this is to create structs from response values.
type ClientResponseReader interface {
- ReadResponse(ClientResponse, Consumer) (interface{}, error)
+ ReadResponse(ClientResponse, Consumer) (any, error)
}
-// NewAPIError creates a new API error
-func NewAPIError(opName string, payload interface{}, code int) *APIError {
+// APIError wraps an error model and captures the status code.
+type APIError struct {
+ OperationName string
+ Response any
+ Code int
+}
+
+// NewAPIError creates a new API error.
+func NewAPIError(opName string, payload any, code int) *APIError {
return &APIError{
OperationName: opName,
Response: payload,
@@ -53,18 +51,59 @@ func NewAPIError(opName string, payload interface{}, code int) *APIError {
}
}
-// APIError wraps an error model and captures the status code
-type APIError struct {
- OperationName string
- Response interface{}
- Code int
+// sanitizer ensures that single quotes are escaped.
+var sanitizer = strings.NewReplacer(`\`, `\\`, `'`, `\'`)
+
+func (o *APIError) Error() string {
+ var resp []byte
+ if err, ok := o.Response.(error); ok {
+ resp = []byte("'" + sanitizer.Replace(err.Error()) + "'")
+ } else {
+ resp, _ = json.Marshal(o.Response)
+ }
+
+ return fmt.Sprintf("%s (status %d): %s", o.OperationName, o.Code, resp)
+}
+
+func (o *APIError) String() string {
+ return o.Error()
+}
+
+// IsSuccess returns true when this API response returns a 2xx status code.
+func (o *APIError) IsSuccess() bool {
+ const statusOK = 2
+ return o.Code/100 == statusOK
+}
+
+// IsRedirect returns true when this API response returns a 3xx status code.
+func (o *APIError) IsRedirect() bool {
+ const statusRedirect = 3
+ return o.Code/100 == statusRedirect
+}
+
+// IsClientError returns true when this API response returns a 4xx status code.
+func (o *APIError) IsClientError() bool {
+ const statusClientError = 4
+ return o.Code/100 == statusClientError
+}
+
+// IsServerError returns true when this API response returns a 5xx status code.
+func (o *APIError) IsServerError() bool {
+ const statusServerError = 5
+ return o.Code/100 == statusServerError
}
-func (a *APIError) Error() string {
- resp, _ := json.Marshal(a.Response)
- return fmt.Sprintf("%s (status %d): %s", a.OperationName, a.Code, resp)
+// IsCode returns true when this API response returns a given status code.
+func (o *APIError) IsCode(code int) bool {
+ return o.Code == code
}
-func (a *APIError) String() string {
- return a.Error()
+// A ClientResponseStatus is a common interface implemented by all responses on the generated code
+// You can use this to treat any client response based on status code.
+type ClientResponseStatus interface {
+ IsSuccess() bool
+ IsRedirect() bool
+ IsClientError() bool
+ IsServerError() bool
+ IsCode(int) bool
}
diff --git a/vendor/github.com/go-openapi/runtime/constants.go b/vendor/github.com/go-openapi/runtime/constants.go
index a4de897adcdf..80de6c808684 100644
--- a/vendor/github.com/go-openapi/runtime/constants.go
+++ b/vendor/github.com/go-openapi/runtime/constants.go
@@ -1,47 +1,38 @@
-// 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 runtime
const (
- // HeaderContentType represents a http content-type header, it's value is supposed to be a mime type
+ // HeaderContentType represents a [http] content-type header, it's value is supposed to be a mime type.
HeaderContentType = "Content-Type"
- // HeaderTransferEncoding represents a http transfer-encoding header.
+ // HeaderTransferEncoding represents a [http] transfer-encoding header.
HeaderTransferEncoding = "Transfer-Encoding"
- // HeaderAccept the Accept header
+ // HeaderAccept the Accept header.
HeaderAccept = "Accept"
+ // HeaderAuthorization the Authorization header.
+ HeaderAuthorization = "Authorization"
charsetKey = "charset"
- // DefaultMime the default fallback mime type
+ // DefaultMime the default fallback mime type.
DefaultMime = "application/octet-stream"
- // JSONMime the json mime type
+ // JSONMime the json mime type.
JSONMime = "application/json"
- // YAMLMime the yaml mime type
+ // YAMLMime the [yaml] mime type.
YAMLMime = "application/x-yaml"
- // XMLMime the xml mime type
+ // XMLMime the [xml] mime type.
XMLMime = "application/xml"
- // TextMime the text mime type
+ // TextMime the text mime type.
TextMime = "text/plain"
- // HTMLMime the html mime type
+ // HTMLMime the html mime type.
HTMLMime = "text/html"
- // CSVMime the csv mime type
+ // CSVMime the [csv] mime type.
CSVMime = "text/csv"
- // MultipartFormMime the multipart form mime type
+ // MultipartFormMime the multipart form mime type.
MultipartFormMime = "multipart/form-data"
- // URLencodedFormMime the url encoded form mime type
+ // URLencodedFormMime is the [url] encoded form mime type.
URLencodedFormMime = "application/x-www-form-urlencoded"
)
diff --git a/vendor/github.com/go-openapi/runtime/csv.go b/vendor/github.com/go-openapi/runtime/csv.go
index d807bd915b44..558d0cb99aa1 100644
--- a/vendor/github.com/go-openapi/runtime/csv.go
+++ b/vendor/github.com/go-openapi/runtime/csv.go
@@ -1,77 +1,341 @@
-// 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 runtime
import (
"bytes"
+ "context"
+ "encoding"
"encoding/csv"
"errors"
+ "fmt"
"io"
+ "reflect"
+
+ "golang.org/x/sync/errgroup"
)
-// CSVConsumer creates a new CSV consumer
-func CSVConsumer() Consumer {
- return ConsumerFunc(func(reader io.Reader, data interface{}) error {
+// CSVConsumer creates a new CSV consumer.
+//
+// The consumer consumes CSV records from a provided reader into the data passed by reference.
+//
+// CSVOpts options may be specified to alter the default CSV behavior on the reader and the writer side (e.g. separator, skip header, ...).
+// The defaults are those of the standard library's [csv.Reader] and [csv.Writer].
+//
+// Supported output underlying types and interfaces, prioritized in this order:
+//
+// - *[csv.Writer]
+// - [CSVWriter] (writer options are ignored)
+// - [io.Writer] (as raw bytes)
+// - [io.ReaderFrom] (as raw bytes)
+// - [encoding.BinaryUnmarshaler] (as raw bytes)
+// - *[][]string (as a collection of records)
+// - *[]byte (as raw bytes)
+// - *string (a raw bytes)
+//
+// The consumer prioritizes situations where buffering the input is not required.
+func CSVConsumer(opts ...CSVOpt) Consumer {
+ o := csvOptsWithDefaults(opts)
+
+ return ConsumerFunc(func(reader io.Reader, data any) error {
if reader == nil {
return errors.New("CSVConsumer requires a reader")
}
+ if data == nil {
+ return errors.New("nil destination for CSVConsumer")
+ }
csvReader := csv.NewReader(reader)
- writer, ok := data.(io.Writer)
- if !ok {
- return errors.New("data type must be io.Writer")
+ o.applyToReader(csvReader)
+ closer := defaultCloser
+ if o.closeStream {
+ if cl, isReaderCloser := reader.(io.Closer); isReaderCloser {
+ closer = cl.Close
+ }
}
- csvWriter := csv.NewWriter(writer)
- records, err := csvReader.ReadAll()
- if err != nil {
+ defer func() {
+ _ = closer()
+ }()
+
+ switch destination := data.(type) {
+ case *csv.Writer:
+ csvWriter := destination
+ o.applyToWriter(csvWriter)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case CSVWriter:
+ csvWriter := destination
+ // no writer options available
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.Writer:
+ csvWriter := csv.NewWriter(destination)
+ o.applyToWriter(csvWriter)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.ReaderFrom:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+ _, err := destination.ReadFrom(&buf)
+
return err
- }
- for _, r := range records {
- if err := csvWriter.Write(r); err != nil {
+
+ case encoding.BinaryUnmarshaler:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
return err
}
+
+ return destination.UnmarshalBinary(buf.Bytes())
+
+ default:
+ // support *[][]string, *[]byte, *string
+ if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr {
+ return errors.New("destination must be a pointer")
+ }
+
+ v := reflect.Indirect(reflect.ValueOf(data))
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Slice && t.Elem().Elem().Kind() == reflect.String:
+ csvWriter := &csvRecordsWriter{}
+ // writer options are ignored
+ if err := pipeCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+
+ v.Grow(len(csvWriter.records))
+ v.SetCap(len(csvWriter.records)) // in case Grow was unnessary, trim down the capacity
+ v.SetLen(len(csvWriter.records))
+ reflect.Copy(v, reflect.ValueOf(csvWriter.records))
+
+ return nil
+
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+ v.SetBytes(buf.Bytes())
+
+ return nil
+
+ case t.Kind() == reflect.String:
+ var buf bytes.Buffer
+ csvWriter := csv.NewWriter(&buf)
+ o.applyToWriter(csvWriter)
+ if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
+ return err
+ }
+ v.SetString(buf.String())
+
+ return nil
+
+ default:
+ return fmt.Errorf("%v (%T) is not supported by the CSVConsumer, %s",
+ data, data, "can be resolved by supporting CSVWriter/Writer/BinaryUnmarshaler interface",
+ )
+ }
}
- csvWriter.Flush()
- return nil
})
}
-// CSVProducer creates a new CSV producer
-func CSVProducer() Producer {
- return ProducerFunc(func(writer io.Writer, data interface{}) error {
+// CSVProducer creates a new CSV producer.
+//
+// The producer takes input data then writes as CSV to an output writer (essentially as a pipe).
+//
+// 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
+//
+// The producer prioritizes situations where buffering the input is not required.
+func CSVProducer(opts ...CSVOpt) Producer {
+ o := csvOptsWithDefaults(opts)
+
+ return ProducerFunc(func(writer io.Writer, data any) error {
if writer == nil {
return errors.New("CSVProducer requires a writer")
}
+ if data == nil {
+ return errors.New("nil data for CSVProducer")
+ }
- dataBytes, ok := data.([]byte)
- if !ok {
- return errors.New("data type must be byte array")
+ csvWriter := csv.NewWriter(writer)
+ o.applyToWriter(csvWriter)
+ closer := defaultCloser
+ if o.closeStream {
+ if cl, isWriterCloser := writer.(io.Closer); isWriterCloser {
+ closer = cl.Close
+ }
}
+ defer func() {
+ _ = closer()
+ }()
- csvReader := csv.NewReader(bytes.NewBuffer(dataBytes))
- records, err := csvReader.ReadAll()
- if err != nil {
- return err
+ if rc, isDataCloser := data.(io.ReadCloser); isDataCloser {
+ defer rc.Close()
}
- csvWriter := csv.NewWriter(writer)
- for _, r := range records {
- if err := csvWriter.Write(r); err != nil {
+
+ switch origin := data.(type) {
+ case *csv.Reader:
+ csvReader := origin
+ o.applyToReader(csvReader)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case CSVReader:
+ csvReader := origin
+ // no reader options available
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.Reader:
+ csvReader := csv.NewReader(origin)
+ o.applyToReader(csvReader)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case io.WriterTo:
+ // async piping of the writes performed by WriteTo
+ r, w := io.Pipe()
+ csvReader := csv.NewReader(r)
+ o.applyToReader(csvReader)
+
+ pipe, _ := errgroup.WithContext(context.Background())
+ pipe.Go(func() error {
+ _, err := origin.WriteTo(w)
+ _ = w.Close()
+ return err
+ })
+
+ pipe.Go(func() error {
+ defer func() {
+ _ = r.Close()
+ }()
+
+ return pipeCSV(csvWriter, csvReader, o)
+ })
+
+ return pipe.Wait()
+
+ case encoding.BinaryMarshaler:
+ buf, err := origin.MarshalBinary()
+ if err != nil {
return err
}
+ rdr := bytes.NewBuffer(buf)
+ csvReader := csv.NewReader(rdr)
+
+ return bufferedCSV(csvWriter, csvReader, o)
+
+ default:
+ // support [][]string, []byte, string (or pointers to those)
+ v := reflect.Indirect(reflect.ValueOf(data))
+ t := v.Type()
+
+ switch {
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Slice && t.Elem().Elem().Kind() == reflect.String:
+ csvReader := &csvRecordsWriter{
+ records: make([][]string, v.Len()),
+ }
+ reflect.Copy(reflect.ValueOf(csvReader.records), v)
+
+ return pipeCSV(csvWriter, csvReader, o)
+
+ case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
+ buf := bytes.NewBuffer(v.Bytes())
+ csvReader := csv.NewReader(buf)
+ o.applyToReader(csvReader)
+
+ return bufferedCSV(csvWriter, csvReader, o)
+
+ case t.Kind() == reflect.String:
+ buf := bytes.NewBufferString(v.String())
+ csvReader := csv.NewReader(buf)
+ o.applyToReader(csvReader)
+
+ return bufferedCSV(csvWriter, csvReader, o)
+
+ default:
+ return fmt.Errorf("%v (%T) is not supported by the CSVProducer, %s",
+ data, data, "can be resolved by supporting CSVReader/Reader/BinaryMarshaler interface",
+ )
+ }
}
- csvWriter.Flush()
- return nil
})
}
+
+// pipeCSV copies CSV records from a CSV reader to a CSV writer.
+func pipeCSV(csvWriter CSVWriter, csvReader CSVReader, opts csvOpts) error {
+ for ; opts.skippedLines > 0; opts.skippedLines-- {
+ _, err := csvReader.Read()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return nil
+ }
+
+ return err
+ }
+ }
+
+ for {
+ record, err := csvReader.Read()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+
+ return err
+ }
+
+ if err := csvWriter.Write(record); err != nil {
+ return err
+ }
+ }
+
+ csvWriter.Flush()
+
+ return csvWriter.Error()
+}
+
+// bufferedCSV copies CSV records from a CSV reader to a CSV writer,
+// by first reading all records then writing them at once.
+func bufferedCSV(csvWriter *csv.Writer, csvReader *csv.Reader, opts csvOpts) error {
+ for ; opts.skippedLines > 0; opts.skippedLines-- {
+ _, err := csvReader.Read()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return nil
+ }
+
+ return err
+ }
+ }
+
+ records, err := csvReader.ReadAll()
+ if err != nil {
+ return err
+ }
+
+ return csvWriter.WriteAll(records)
+}
diff --git a/vendor/github.com/go-openapi/runtime/csv_options.go b/vendor/github.com/go-openapi/runtime/csv_options.go
new file mode 100644
index 000000000000..e778c64d1f72
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/csv_options.go
@@ -0,0 +1,124 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package runtime
+
+import (
+ "encoding/csv"
+ "io"
+)
+
+// CSVOpt alter the behavior of the CSV consumer or producer.
+type CSVOpt func(*csvOpts)
+
+type csvOpts struct {
+ csvReader csv.Reader
+ csvWriter csv.Writer
+ skippedLines int
+ closeStream bool
+}
+
+// WithCSVReaderOpts specifies the options to [csv.Reader]
+// when reading CSV.
+func WithCSVReaderOpts(reader csv.Reader) CSVOpt {
+ return func(o *csvOpts) {
+ o.csvReader = reader
+ }
+}
+
+// WithCSVWriterOpts specifies the options to [csv.Writer]
+// when writing CSV.
+func WithCSVWriterOpts(writer csv.Writer) CSVOpt {
+ return func(o *csvOpts) {
+ o.csvWriter = writer
+ }
+}
+
+// WithCSVSkipLines will skip header lines.
+func WithCSVSkipLines(skipped int) CSVOpt {
+ return func(o *csvOpts) {
+ o.skippedLines = skipped
+ }
+}
+
+func WithCSVClosesStream() CSVOpt {
+ return func(o *csvOpts) {
+ o.closeStream = true
+ }
+}
+
+func (o csvOpts) applyToReader(in *csv.Reader) {
+ if o.csvReader.Comma != 0 {
+ in.Comma = o.csvReader.Comma
+ }
+ if o.csvReader.Comment != 0 {
+ in.Comment = o.csvReader.Comment
+ }
+ if o.csvReader.FieldsPerRecord != 0 {
+ in.FieldsPerRecord = o.csvReader.FieldsPerRecord
+ }
+
+ in.LazyQuotes = o.csvReader.LazyQuotes
+ in.TrimLeadingSpace = o.csvReader.TrimLeadingSpace
+ in.ReuseRecord = o.csvReader.ReuseRecord
+}
+
+func (o csvOpts) applyToWriter(in *csv.Writer) {
+ if o.csvWriter.Comma != 0 {
+ in.Comma = o.csvWriter.Comma
+ }
+ in.UseCRLF = o.csvWriter.UseCRLF
+}
+
+func csvOptsWithDefaults(opts []CSVOpt) csvOpts {
+ var o csvOpts
+ for _, apply := range opts {
+ apply(&o)
+ }
+
+ return o
+}
+
+type CSVWriter interface {
+ Write([]string) error
+ Flush()
+ Error() error
+}
+
+type CSVReader interface {
+ Read() ([]string, error)
+}
+
+var (
+ _ CSVWriter = &csvRecordsWriter{}
+ _ CSVReader = &csvRecordsWriter{}
+)
+
+// csvRecordsWriter is an internal container to move CSV records back and forth.
+type csvRecordsWriter struct {
+ i int
+ records [][]string
+}
+
+func (w *csvRecordsWriter) Write(record []string) error {
+ w.records = append(w.records, record)
+
+ return nil
+}
+
+func (w *csvRecordsWriter) Read() ([]string, error) {
+ if w.i >= len(w.records) {
+ return nil, io.EOF
+ }
+ defer func() {
+ w.i++
+ }()
+
+ return w.records[w.i], nil
+}
+
+func (w *csvRecordsWriter) Flush() {}
+
+func (w *csvRecordsWriter) Error() error {
+ return nil
+}
diff --git a/vendor/github.com/go-openapi/runtime/discard.go b/vendor/github.com/go-openapi/runtime/discard.go
index 0d390cfd64c0..b05678becd9a 100644
--- a/vendor/github.com/go-openapi/runtime/discard.go
+++ b/vendor/github.com/go-openapi/runtime/discard.go
@@ -1,9 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package runtime
import "io"
// DiscardConsumer does absolutely nothing, it's a black hole.
-var DiscardConsumer = ConsumerFunc(func(_ io.Reader, _ interface{}) error { return nil })
+var DiscardConsumer = ConsumerFunc(func(_ io.Reader, _ any) error { return nil })
// DiscardProducer does absolutely nothing, it's a black hole.
-var DiscardProducer = ProducerFunc(func(_ io.Writer, _ interface{}) error { return nil })
+var DiscardProducer = ProducerFunc(func(_ io.Writer, _ any) error { return nil })
diff --git a/vendor/github.com/go-openapi/runtime/doc.go b/vendor/github.com/go-openapi/runtime/doc.go
new file mode 100644
index 000000000000..300c6b15f07e
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/doc.go
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package runtime exposes runtime client and server components
+// for go-openapi toolkit.
+package runtime
diff --git a/vendor/github.com/go-openapi/runtime/file.go b/vendor/github.com/go-openapi/runtime/file.go
index 85971c18c4b5..2a85379a748f 100644
--- a/vendor/github.com/go-openapi/runtime/file.go
+++ b/vendor/github.com/go-openapi/runtime/file.go
@@ -1,33 +1,8 @@
-// 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 runtime
-import "mime/multipart"
+import "github.com/go-openapi/swag/fileutils"
-// File represents an uploaded file.
-type File struct {
- Data multipart.File
- Header *multipart.FileHeader
-}
-
-// Read bytes from the file
-func (f *File) Read(p []byte) (n int, err error) {
- return f.Data.Read(p)
-}
-
-// Close the file
-func (f *File) Close() error {
- return f.Data.Close()
-}
+type File = fileutils.File
diff --git a/vendor/github.com/go-openapi/runtime/headers.go b/vendor/github.com/go-openapi/runtime/headers.go
index 4d111db4fec0..4eb2b9254aa1 100644
--- a/vendor/github.com/go-openapi/runtime/headers.go
+++ b/vendor/github.com/go-openapi/runtime/headers.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 runtime
@@ -21,7 +10,7 @@ import (
"github.com/go-openapi/errors"
)
-// ContentType parses a content type header
+// ContentType parses a content type header.
func ContentType(headers http.Header) (string, string, error) {
ct := headers.Get(HeaderContentType)
orig := ct
diff --git a/vendor/github.com/go-openapi/runtime/interfaces.go b/vendor/github.com/go-openapi/runtime/interfaces.go
index e33412868347..a8b4b318d9c4 100644
--- a/vendor/github.com/go-openapi/runtime/interfaces.go
+++ b/vendor/github.com/go-openapi/runtime/interfaces.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 runtime
@@ -22,83 +11,83 @@ import (
"github.com/go-openapi/strfmt"
)
-// OperationHandlerFunc an adapter for a function to the OperationHandler interface
-type OperationHandlerFunc func(interface{}) (interface{}, error)
+// OperationHandlerFunc an adapter for a function to the [OperationHandler] interface.
+type OperationHandlerFunc func(any) (any, error)
-// Handle implements the operation handler interface
-func (s OperationHandlerFunc) Handle(data interface{}) (interface{}, error) {
+// Handle implements the operation handler interface.
+func (s OperationHandlerFunc) Handle(data any) (any, error) {
return s(data)
}
-// OperationHandler a handler for a swagger operation
+// OperationHandler a handler for a swagger operation.
type OperationHandler interface {
- Handle(interface{}) (interface{}, error)
+ Handle(any) (any, error)
}
-// ConsumerFunc represents a function that can be used as a consumer
-type ConsumerFunc func(io.Reader, interface{}) error
+// ConsumerFunc represents a function that can be used as a consumer.
+type ConsumerFunc func(io.Reader, any) error
-// Consume consumes the reader into the data parameter
-func (fn ConsumerFunc) Consume(reader io.Reader, data interface{}) error {
+// Consume consumes the reader into the data parameter.
+func (fn ConsumerFunc) Consume(reader io.Reader, data any) error {
return fn(reader, data)
}
// Consumer implementations know how to bind the values on the provided interface to
-// data provided by the request body
+// data provided by the request body.
type Consumer interface {
// Consume performs the binding of request values
- Consume(io.Reader, interface{}) error
+ Consume(io.Reader, any) error
}
-// ProducerFunc represents a function that can be used as a producer
-type ProducerFunc func(io.Writer, interface{}) error
+// ProducerFunc represents a function that can be used as a producer.
+type ProducerFunc func(io.Writer, any) error
-// Produce produces the response for the provided data
-func (f ProducerFunc) Produce(writer io.Writer, data interface{}) error {
+// Produce produces the response for the provided data.
+func (f ProducerFunc) Produce(writer io.Writer, data any) error {
return f(writer, data)
}
// Producer implementations know how to turn the provided interface into a valid
-// HTTP response
+// HTTP response.
type Producer interface {
// Produce writes to the http response
- Produce(io.Writer, interface{}) error
+ Produce(io.Writer, any) error
}
-// AuthenticatorFunc turns a function into an authenticator
-type AuthenticatorFunc func(interface{}) (bool, interface{}, error)
+// AuthenticatorFunc turns a function into an authenticator.
+type AuthenticatorFunc func(any) (bool, any, error)
-// Authenticate authenticates the request with the provided data
-func (f AuthenticatorFunc) Authenticate(params interface{}) (bool, interface{}, error) {
+// Authenticate authenticates the request with the provided data.
+func (f AuthenticatorFunc) Authenticate(params any) (bool, any, error) {
return f(params)
}
// Authenticator represents an authentication strategy
// implementations of Authenticator know how to authenticate the
-// request data and translate that into a valid principal object or an error
+// request data and translate that into a valid principal object or an error.
type Authenticator interface {
- Authenticate(interface{}) (bool, interface{}, error)
+ Authenticate(any) (bool, any, error)
}
-// AuthorizerFunc turns a function into an authorizer
-type AuthorizerFunc func(*http.Request, interface{}) error
+// AuthorizerFunc turns a function into an authorizer.
+type AuthorizerFunc func(*http.Request, any) error
-// Authorize authorizes the processing of the request for the principal
-func (f AuthorizerFunc) Authorize(r *http.Request, principal interface{}) error {
+// Authorize authorizes the processing of the request for the principal.
+func (f AuthorizerFunc) Authorize(r *http.Request, principal any) error {
return f(r, principal)
}
// Authorizer represents an authorization strategy
// implementations of Authorizer know how to authorize the principal object
-// using the request data and returns error if unauthorized
+// using the request data and returns error if unauthorized.
type Authorizer interface {
- Authorize(*http.Request, interface{}) error
+ Authorize(*http.Request, any) error
}
// Validatable types implementing this interface allow customizing their validation
// this will be used instead of the reflective validation based on the spec document.
// the implementations are assumed to have been generated by the swagger tool so they should
-// contain all the validations obtained from the spec
+// contain all the validations obtained from the spec.
type Validatable interface {
Validate(strfmt.Registry) error
}
@@ -106,7 +95,7 @@ type Validatable interface {
// ContextValidatable types implementing this interface allow customizing their validation
// this will be used instead of the reflective validation based on the spec document.
// the implementations are assumed to have been generated by the swagger tool so they should
-// contain all the context validations obtained from the spec
+// contain all the context validations obtained from the spec.
type ContextValidatable interface {
ContextValidate(context.Context, strfmt.Registry) error
}
diff --git a/vendor/github.com/go-openapi/runtime/json.go b/vendor/github.com/go-openapi/runtime/json.go
index 5a690559cc59..2af5dcfe464a 100644
--- a/vendor/github.com/go-openapi/runtime/json.go
+++ b/vendor/github.com/go-openapi/runtime/json.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 runtime
@@ -19,18 +8,18 @@ import (
"io"
)
-// JSONConsumer creates a new JSON consumer
+// JSONConsumer creates a new JSON consumer.
func JSONConsumer() Consumer {
- return ConsumerFunc(func(reader io.Reader, data interface{}) error {
+ return ConsumerFunc(func(reader io.Reader, data any) error {
dec := json.NewDecoder(reader)
dec.UseNumber() // preserve number formats
return dec.Decode(data)
})
}
-// JSONProducer creates a new JSON producer
+// JSONProducer creates a new JSON producer.
func JSONProducer() Producer {
- return ProducerFunc(func(writer io.Writer, data interface{}) error {
+ return ProducerFunc(func(writer io.Writer, data any) error {
enc := json.NewEncoder(writer)
enc.SetEscapeHTML(false)
return enc.Encode(data)
diff --git a/vendor/github.com/go-openapi/runtime/logger/logger.go b/vendor/github.com/go-openapi/runtime/logger/logger.go
index 6f4debcc1454..45484deb5938 100644
--- a/vendor/github.com/go-openapi/runtime/logger/logger.go
+++ b/vendor/github.com/go-openapi/runtime/logger/logger.go
@@ -1,10 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package logger
import "os"
type Logger interface {
- Printf(format string, args ...interface{})
- Debugf(format string, args ...interface{})
+ Printf(format string, args ...any)
+ Debugf(format string, args ...any)
}
func DebugEnabled() bool {
diff --git a/vendor/github.com/go-openapi/runtime/logger/standard.go b/vendor/github.com/go-openapi/runtime/logger/standard.go
index f7e67ebb9e75..48ba27f4a3d4 100644
--- a/vendor/github.com/go-openapi/runtime/logger/standard.go
+++ b/vendor/github.com/go-openapi/runtime/logger/standard.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package logger
import (
@@ -5,16 +8,18 @@ import (
"os"
)
+var _ Logger = StandardLogger{}
+
type StandardLogger struct{}
-func (StandardLogger) Printf(format string, args ...interface{}) {
+func (StandardLogger) Printf(format string, args ...any) {
if len(format) == 0 || format[len(format)-1] != '\n' {
format += "\n"
}
fmt.Fprintf(os.Stderr, format, args...)
}
-func (StandardLogger) Debugf(format string, args ...interface{}) {
+func (StandardLogger) Debugf(format string, args ...any) {
if len(format) == 0 || format[len(format)-1] != '\n' {
format += "\n"
}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/context.go b/vendor/github.com/go-openapi/runtime/middleware/context.go
index 250e35fb0e14..1f85e86b5383 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/context.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/context.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 middleware
@@ -18,6 +7,8 @@ import (
stdContext "context"
"fmt"
"net/http"
+ "net/url"
+ "path"
"strings"
"sync"
@@ -33,50 +24,62 @@ import (
"github.com/go-openapi/runtime/security"
)
-// Debug when true turns on verbose logging
+// 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 debugLog(format string, args ...interface{}) {
- if Debug {
- Logger.Printf(format, args...)
+func debugLogfFunc(lg logger.Logger) func(string, ...any) {
+ if logger.DebugEnabled() {
+ if lg == nil {
+ return Logger.Debugf
+ }
+
+ return lg.Debugf
}
+
+ // muted logger
+ return func(_ string, _ ...any) {}
}
-// A Builder can create middlewares
+// A Builder can create middlewares.
type Builder func(http.Handler) http.Handler
-// PassthroughBuilder returns the handler, aka the builder identity function
+// PassthroughBuilder returns the handler, aka the builder identity function.
func PassthroughBuilder(handler http.Handler) http.Handler { return handler }
// RequestBinder is an interface for types to implement
-// when they want to be able to bind from a request
+// when they want to be able to bind from a request.
type RequestBinder interface {
BindRequest(*http.Request, *MatchedRoute) error
}
// Responder is an interface for types to implement
-// when they want to be considered for writing HTTP responses
+// when they want to be considered for writing HTTP responses.
type Responder interface {
WriteResponse(http.ResponseWriter, runtime.Producer)
}
-// ResponderFunc wraps a func as a Responder interface
+// ResponderFunc wraps a func as a Responder interface.
type ResponderFunc func(http.ResponseWriter, runtime.Producer)
-// WriteResponse writes to the response
+// WriteResponse writes to the response.
func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Producer) {
fn(rw, pr)
}
-// Context is a type safe wrapper around an untyped request context
+// Context is a type safe wrapper around an [untyped] request context
// used throughout to store request context with the standard context attached
-// to the http.Request
+// to the [http.Request].
type Context struct {
- spec *loads.Document
- analyzer *analysis.Spec
- api RoutableAPI
- router Router
+ 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
}
type routableUntypedAPI struct {
@@ -114,7 +117,7 @@ func newRoutableUntypedAPI(spec *loads.Document, api *untyped.API, context *Cont
}
// bind and validate the request using reflection
- var bound interface{}
+ var bound any
var validation error
bound, r, validation = context.BindAndValidate(r, route)
if validation != nil {
@@ -162,7 +165,7 @@ func (r *routableUntypedAPI) HandlerFor(method, path string) (http.Handler, bool
r.hlock.Unlock()
return handler, ok
}
-func (r *routableUntypedAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) {
+func (r *routableUntypedAPI) ServeErrorFor(_ string) func(http.ResponseWriter, *http.Request, error) {
return r.api.ServeError
}
func (r *routableUntypedAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
@@ -189,35 +192,62 @@ func (r *routableUntypedAPI) DefaultConsumes() string {
return r.defaultConsumes
}
-// NewRoutableContext creates a new context for a routable API
+// 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())
}
- ctx := &Context{spec: spec, api: routableAPI, analyzer: an, router: routes}
- return ctx
+
+ 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
+// 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}
+ ctx := &Context{
+ spec: spec,
+ analyzer: an,
+ router: routes,
+ debugLogf: debugLogfFunc(nil),
+ }
ctx.api = newRoutableUntypedAPI(spec, api, ctx)
- ctx.router = routes
+
return ctx
}
-// Serve serves the specified spec with the specified api registrations as a http.Handler
+// 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
+// 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 {
context := NewContext(spec, api, nil)
return context.APIHandler(builder)
@@ -248,7 +278,7 @@ func MatchedRouteFrom(req *http.Request) *MatchedRoute {
}
// SecurityPrincipalFrom request context value.
-func SecurityPrincipalFrom(req *http.Request) interface{} {
+func SecurityPrincipalFrom(req *http.Request) any {
return req.Context().Value(ctxSecurityPrincipal)
}
@@ -266,18 +296,28 @@ type contentTypeValue struct {
Charset string
}
-// BasePath returns the base path for this API
+// BasePath returns the base path for this API.
func (c *Context) BasePath() string {
+ if c.spec == nil {
+ return ""
+ }
return c.spec.BasePath()
}
-// RequiredProduces returns the accepted content types for responses
+// SetLogger allows for injecting a logger to catch debug entries.
+//
+// The logger is enabled in DEBUG mode only.
+func (c *Context) SetLogger(lg logger.Logger) {
+ c.debugLogf = debugLogfFunc(lg)
+}
+
+// RequiredProduces returns the accepted content types for responses.
func (c *Context) RequiredProduces() []string {
return c.analyzer.RequiredProduces()
}
// 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
+// 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
@@ -288,13 +328,14 @@ func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, b
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(500, "no consumer registered for %s", ct))
+ res = append(res, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct))
} else {
route.Consumer = cons
requestContentType = ct
@@ -335,7 +376,7 @@ func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, b
// Returns the media type, its charset and a shallow copy of the request
// when its context doesn't contain the content type value, otherwise it returns
// the same request
-// Returns the error that runtime.ContentType may retunrs.
+// Returns the error that [runtime.ContentType] may returns.
func (c *Context) ContentType(request *http.Request) (string, string, *http.Request, error) {
var rCtx = request.Context()
@@ -351,7 +392,7 @@ func (c *Context) ContentType(request *http.Request) (string, string, *http.Requ
return mt, cs, request.WithContext(rCtx), nil
}
-// LookupRoute looks a route up and returns true when it is found
+// LookupRoute looks a route up and returns true when it is found.
func (c *Context) LookupRoute(request *http.Request) (*MatchedRoute, bool) {
if route, ok := c.router.Lookup(request.Method, request.URL.EscapedPath()); ok {
return route, ok
@@ -363,7 +404,7 @@ func (c *Context) LookupRoute(request *http.Request) (*MatchedRoute, bool) {
// Returns the matched route, a shallow copy of the request if its context
// contains the matched router, otherwise the same request, and a bool to
// indicate if it the request matches one of the routes, if it doesn't
-// then it returns false and nil for the other two return values
+// then it returns false and nil for the other two return values.
func (c *Context) RouteInfo(request *http.Request) (*MatchedRoute, *http.Request, bool) {
var rCtx = request.Context()
@@ -381,30 +422,30 @@ func (c *Context) RouteInfo(request *http.Request) (*MatchedRoute, *http.Request
// ResponseFormat negotiates the response content type
// Returns the response format and a shallow copy of the request if its context
-// doesn't contain the response format, otherwise the same request
+// doesn't contain the response format, otherwise the same request.
func (c *Context) ResponseFormat(r *http.Request, offers []string) (string, *http.Request) {
var rCtx = r.Context()
if v, ok := rCtx.Value(ctxResponseFormat).(string); ok {
- debugLog("[%s %s] found response format %q in context", r.Method, r.URL.Path, v)
+ c.debugLogf("[%s %s] found response format %q in context", r.Method, r.URL.Path, v)
return v, r
}
format := NegotiateContentType(r, offers, "")
if format != "" {
- debugLog("[%s %s] set response format %q in context", r.Method, r.URL.Path, 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))
}
- debugLog("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format)
+ c.debugLogf("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format)
return format, r
}
-// AllowedMethods gets the allowed methods for the path of this request
+// AllowedMethods gets the allowed methods for the path of this request.
func (c *Context) AllowedMethods(request *http.Request) []string {
return c.router.OtherMethods(request.Method, request.URL.EscapedPath())
}
-// ResetAuth removes the current principal from the request context
+// ResetAuth removes the current principal from the request context.
func (c *Context) ResetAuth(request *http.Request) *http.Request {
rctx := request.Context()
rctx = stdContext.WithValue(rctx, ctxSecurityPrincipal, nil)
@@ -415,8 +456,8 @@ func (c *Context) ResetAuth(request *http.Request) *http.Request {
// 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) (interface{}, *http.Request, 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
}
@@ -439,7 +480,7 @@ func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (interfa
return nil, nil, err
}
- return nil, nil, errors.New(http.StatusForbidden, err.Error())
+ return nil, nil, errors.New(http.StatusForbidden, "%v", err)
}
}
@@ -453,12 +494,12 @@ func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (interfa
// 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
-// CompositeValidationError error
-func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute) (interface{}, *http.Request, error) {
+// CompositeValidationError error.
+func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute) (any, *http.Request, error) {
var rCtx = request.Context()
if v, ok := rCtx.Value(ctxBoundParams).(*validation); ok {
- debugLog("got cached validation (valid: %t)", len(v.result) == 0)
+ c.debugLogf("got cached validation (valid: %t)", len(v.result) == 0)
if len(v.result) > 0 {
return v.bound, request, errors.CompositeValidationError(v.result...)
}
@@ -470,18 +511,18 @@ func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute)
if len(result.result) > 0 {
return result.bound, request, errors.CompositeValidationError(result.result...)
}
- debugLog("no validation errors found")
+ c.debugLogf("no validation errors found")
return result.bound, request, nil
}
-// NotFound the default not found responder for when no route has been matched yet
+// NotFound the default not found responder for when no route has been matched yet.
func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) {
c.Respond(rw, r, []string{c.api.DefaultProduces()}, nil, errors.NotFound("not found"))
}
-// Respond renders the response after doing some content negotiation
-func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data interface{}) {
- debugLog("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces)
+// 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() {
@@ -490,7 +531,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
}
// the default producer is last so more specific producers take precedence
offers = append(offers, c.api.DefaultProduces())
- debugLog("offers: %v", offers)
+ c.debugLogf("offers: %v", offers)
var format string
format, r = c.ResponseFormat(r, offers)
@@ -498,12 +539,14 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
if resp, ok := data.(Responder); ok {
producers := route.Producers
- prod, ok := producers[format]
+ // 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(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
+ panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format)))
}
prod = pr
}
@@ -529,14 +572,14 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
}
if route == nil || route.Operation == nil {
- rw.WriteHeader(200)
- if r.Method == "HEAD" {
+ rw.WriteHeader(http.StatusOK)
+ if r.Method == http.MethodHead {
return
}
producers := c.api.ProducersFor(normalizeOffers(offers))
prod, ok := producers[format]
if !ok {
- panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
+ 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
@@ -546,7 +589,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
if _, code, ok := route.Operation.SuccessResponse(); ok {
rw.WriteHeader(code)
- if code == 204 || r.Method == "HEAD" {
+ if code == http.StatusNoContent || r.Method == http.MethodHead {
return
}
@@ -557,7 +600,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
pr, ok := prods[c.api.DefaultProduces()]
if !ok {
- panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
+ panic(fmt.Errorf("%d: %s", http.StatusInternalServerError, cantFindProducer(format)))
}
prod = pr
}
@@ -568,55 +611,108 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
return
}
- c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response"))
+ c.api.ServeErrorFor(route.Operation.ID)(rw, r, fmt.Errorf("%d: %s", http.StatusInternalServerError, "can't produce response"))
}
-func (c *Context) APIHandlerSwaggerUI(builder Builder) http.Handler {
+// APIHandlerSwaggerUI 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 ([SwaggerUI]) is served at {API base path}/docs and the spec document at /swagger.json
+// (these can be modified with uiOptions).
+func (c *Context) APIHandlerSwaggerUI(builder Builder, opts ...UIOption) http.Handler {
b := builder
if b == nil {
b = PassthroughBuilder
}
- var title string
- sp := c.spec.Spec()
- if sp != nil && sp.Info != nil && sp.Info.Title != "" {
- title = sp.Info.Title
+ specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
+ var swaggerUIOpts SwaggerUIOpts
+ fromCommonToAnyOptions(uiOpts, &swaggerUIOpts)
+
+ return Spec(specPath, c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)), specOpts...)
+}
+
+// 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).
+func (c *Context) APIHandlerRapiDoc(builder Builder, opts ...UIOption) http.Handler {
+ b := builder
+ if b == nil {
+ b = PassthroughBuilder
}
- swaggerUIOpts := SwaggerUIOpts{
- BasePath: c.BasePath(),
- Title: title,
+ specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
+ var rapidocUIOpts RapiDocOpts
+ fromCommonToAnyOptions(uiOpts, &rapidocUIOpts)
+
+ return Spec(specPath, c.spec.Raw(), RapiDoc(rapidocUIOpts, c.RoutesHandler(b)), specOpts...)
+}
+
+// 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).
+func (c *Context) APIHandler(builder Builder, opts ...UIOption) http.Handler {
+ b := builder
+ if b == nil {
+ b = PassthroughBuilder
}
- return Spec("", c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)))
+ specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
+ var redocOpts RedocOpts
+ fromCommonToAnyOptions(uiOpts, &redocOpts)
+
+ return Spec(specPath, c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)), specOpts...)
}
-// APIHandler returns a handler to serve the API, this includes a swagger spec, router and the contract defined in the swagger spec
-func (c *Context) APIHandler(builder Builder) http.Handler {
+// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec.
+func (c *Context) RoutesHandler(builder Builder) http.Handler {
b := builder
if b == nil {
b = PassthroughBuilder
}
+ 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
}
- redocOpts := RedocOpts{
- BasePath: c.BasePath(),
- Title: title,
+ // 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)
+
+ // 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
}
- return Spec("", c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)))
+ pth, doc := path.Split(specPath)
+ if pth == "." {
+ pth = ""
+ }
+
+ return pth, uiOpts, []SpecOption{WithSpecDocument(doc)}
}
-// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec
-func (c *Context) RoutesHandler(builder Builder) http.Handler {
- b := builder
- if b == nil {
- b = PassthroughBuilder
- }
- return NewRouter(c, b(NewOperationExecutor(c)))
+func cantFindProducer(format string) string {
+ return "can't find a producer for " + format
}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/README.md b/vendor/github.com/go-openapi/runtime/middleware/denco/README.md
index 30109e17d5ed..03e0b7f4e377 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/denco/README.md
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/README.md
@@ -8,7 +8,7 @@ However, Denco is optimized and some features added.
## Features
* Fast (See [go-http-routing-benchmark](https://github.com/naoina/go-http-routing-benchmark))
-* [URL patterns](#url-patterns) (`/foo/:bar` and `/foo/*wildcard`)
+*[URL patterns](#url-patterns) (`/foo/:bar` and `/foo/*wildcard`)
* Small (but enough) URL router API
* HTTP request multiplexer like `http.ServeMux`
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 5d2691ec3698..f89d761cf2af 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go
@@ -1,7 +1,13 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2014 Naoya Inada
+// SPDX-License-Identifier: MIT
+
// Package denco provides fast URL router.
package denco
import (
+ "errors"
"fmt"
"sort"
"strings"
@@ -20,38 +26,38 @@ const (
// SeparatorCharacter separates path segments.
SeparatorCharacter = '/'
- // PathParamCharacter indicates a RESTCONF path param
+ // PathParamCharacter indicates a RESTCONF path param.
PathParamCharacter = '='
// MaxSize is max size of records and internal slice.
- MaxSize = (1 << 22) - 1
+ MaxSize = (1 << 22) - 1 //nolint:mnd
)
// Router represents a URL router.
type Router struct {
+ param *doubleArray
// SizeHint expects the maximum number of path parameters in records to Build.
// SizeHint will be used to determine the capacity of the memory to allocate.
// By default, SizeHint will be determined from given records to Build.
SizeHint int
- static map[string]interface{}
- param *doubleArray
+ static map[string]any
}
// New returns a new Router.
func New() *Router {
return &Router{
SizeHint: -1,
- static: make(map[string]interface{}),
+ static: make(map[string]any),
param: newDoubleArray(),
}
}
// Lookup returns data and path parameters that associated with path.
-// params is a slice of the Param that arranged in the order in which parameters appeared.
+// 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"}].
-func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) {
- if data, found := rt.static[path]; found {
+func (rt *Router) Lookup(path string) (data any, params Params, found bool) {
+ if data, found = rt.static[path]; found {
return data, nil, true
}
if len(rt.param.node) == 1 {
@@ -61,7 +67,7 @@ func (rt *Router) Lookup(path string) (data interface{}, params Params, found bo
if !found {
return nil, nil, false
}
- for i := 0; i < len(params); i++ {
+ for i := range params {
params[i].Name = nd.paramNames[i]
}
return nd.data, params, true
@@ -71,7 +77,7 @@ func (rt *Router) Lookup(path string) (data interface{}, params Params, found bo
func (rt *Router) Build(records []Record) error {
statics, params := makeRecords(records)
if len(params) > MaxSize {
- return fmt.Errorf("denco: too many records")
+ return errors.New("denco: too many records")
}
if rt.SizeHint < 0 {
rt.SizeHint = 0
@@ -131,21 +137,27 @@ func newDoubleArray() *doubleArray {
// baseCheck contains BASE, CHECK and Extra flags.
// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
//
-// BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
+// BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
+//
// |----------------------|--|--------|
-// 32 10 8 0
+// 32 10 8 0.
type baseCheck uint32
+const (
+ flagsBits = 10
+ checkBits = 8
+)
+
func (bc baseCheck) Base() int {
- return int(bc >> 10)
+ return int(bc >> flagsBits)
}
func (bc *baseCheck) SetBase(base int) {
- *bc |= baseCheck(base) << 10
+ *bc |= baseCheck(base) << flagsBits //nolint:gosec // integer conversion is ok
}
func (bc baseCheck) Check() byte {
- return byte(bc)
+ return byte(bc) //nolint:gosec // integer conversion is ok
}
func (bc *baseCheck) SetCheck(check byte) {
@@ -169,24 +181,27 @@ func (bc baseCheck) IsAnyParam() bool {
}
func (bc *baseCheck) SetSingleParam() {
- *bc |= (1 << 8)
+ *bc |= (1 << checkBits)
}
func (bc *baseCheck) SetWildcardParam() {
- *bc |= (1 << 9)
+ *bc |= (1 << (checkBits + 1))
}
const (
paramTypeSingle = 0x0100
paramTypeWildcard = 0x0200
paramTypeAny = 0x0300
+
+ indexOffset = 32
+ indexMask = uint64(0xffffffff)
)
func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) {
indices := make([]uint64, 0, 1)
- for i := 0; i < len(path); i++ {
+ for i := range len(path) {
if da.bc[idx].IsAnyParam() {
- indices = append(indices, (uint64(i)<<32)|(uint64(idx)&0xffffffff))
+ indices = append(indices, (uint64(i)<= len(da.bc) || da.bc[idx].Check() != c {
@@ -196,24 +211,29 @@ func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Pa
if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
return da.node[da.bc[next].Base()], params, true
}
+
BACKTRACKING:
for j := len(indices) - 1; j >= 0; j-- {
- i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff)
+ i, idx := int(indices[j]>>indexOffset), int(indices[j]&indexMask)
if da.bc[idx].IsSingleParam() {
- idx := nextIndex(da.bc[idx].Base(), ParamCharacter)
- if idx >= len(da.bc) {
+ nextIdx := nextIndex(da.bc[idx].Base(), ParamCharacter)
+ if nextIdx >= len(da.bc) {
break
}
+
next := NextSeparator(path, i)
- params := append(params, Param{Value: path[i:next]})
- if nd, params, found := da.lookup(path[next:], params, idx); found {
- return nd, params, true
+ nextParams := params
+ nextParams = append(nextParams, Param{Value: path[i:next]})
+ if nd, nextNextParams, found := da.lookup(path[next:], nextParams, nextIdx); found {
+ return nd, nextNextParams, true
}
}
+
if da.bc[idx].IsWildcardParam() {
- idx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
- params := append(params, Param{Value: path[i:]})
- return da.node[da.bc[idx].Base()], params, true
+ nextIdx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
+ nextParams := params
+ nextParams = append(nextParams, Param{Value: path[i:]})
+ return da.node[da.bc[nextIdx].Base()], nextParams, true
}
}
return nil, nil, false
@@ -325,7 +345,7 @@ func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[i
}
base = da.findBase(siblings, idx, usedBase)
if base > MaxSize {
- return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice")
+ return -1, nil, nil, errors.New("denco: too many elements of internal slice")
}
da.setBase(idx, base)
return base, siblings, leaf, err
@@ -333,7 +353,7 @@ func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[i
// node represents a node of Double-Array.
type node struct {
- data interface{}
+ data any
// Names of path parameters.
paramNames []string
@@ -386,7 +406,7 @@ func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, er
case pc == c:
continue
default:
- return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted")
+ return nil, nil, errors.New("denco: BUG: routing table hasn't been sorted")
}
if n > 0 {
sib[n-1].end = i
@@ -407,11 +427,11 @@ type Record struct {
Key string
// Result value for Key.
- Value interface{}
+ Value any
}
// NewRecord returns a new Record.
-func NewRecord(key string, value interface{}) Record {
+func NewRecord(key string, value any) Record {
return Record{
Key: key,
Value: value,
@@ -421,6 +441,7 @@ func NewRecord(key string, value interface{}) Record {
// record represents a record that use to build the Double-Array.
type record struct {
Record
+
paramNames []string
}
@@ -431,7 +452,7 @@ func makeRecords(srcs []Record) (statics, params []*record) {
wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter)
restconfPrefix := string(PathParamCharacter) + string(ParamCharacter)
for _, r := range srcs {
- if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) ||strings.Contains(r.Key, restconfPrefix){
+ if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) || strings.Contains(r.Key, restconfPrefix) {
r.Key += termChar
params = append(params, &record{Record: r})
} else {
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 0886713c181d..e6c0976d8b22 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/denco/server.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/server.go
@@ -1,3 +1,8 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2014 Naoya Inada
+// SPDX-License-Identifier: MIT
+
package denco
import (
@@ -7,27 +12,27 @@ import (
// Mux represents a multiplexer for HTTP request.
type Mux struct{}
-// NewMux returns a new Mux.
+// NewMux returns a new [Mux].
func NewMux() *Mux {
return &Mux{}
}
-// GET is shorthand of Mux.Handler("GET", path, handler).
+// GET is shorthand of [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 of [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 of [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 of [Mux].Handler("HEAD", path, handler).
func (m *Mux) HEAD(path string, handler HandlerFunc) Handler {
return m.Handler("HEAD", path, handler)
}
@@ -41,7 +46,7 @@ func (m *Mux) Handler(method, path string, handler HandlerFunc) Handler {
}
}
-// Build builds a http.Handler.
+// Build builds a [http.Handler].
func (m *Mux) Build(handlers []Handler) (http.Handler, error) {
recordMap := make(map[string][]Record)
for _, h := range handlers {
@@ -70,7 +75,7 @@ type Handler struct {
Func HandlerFunc
}
-// The HandlerFunc type is aliased to type of handler function.
+// HandlerFunc is aliased to type of handler function.
type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params)
type serveMux struct {
diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/util.go b/vendor/github.com/go-openapi/runtime/middleware/denco/util.go
index edc1f6ab80a9..e7da422623c2 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/denco/util.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/denco/util.go
@@ -1,3 +1,8 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2014 Naoya Inada
+// SPDX-License-Identifier: MIT
+
package denco
// NextSeparator returns an index of next separator in path.
diff --git a/vendor/github.com/go-openapi/runtime/middleware/doc.go b/vendor/github.com/go-openapi/runtime/middleware/doc.go
index eaf90606ac32..f78ec52c7980 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/doc.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/doc.go
@@ -1,62 +1,50 @@
-// Copyright 2015 go-swagger maintainers
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+// Package middleware provides the library with helper functions for serving swagger APIs.
//
-// 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
+// Pseudo middleware handler.
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// import (
+// "net/http"
//
-// 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 middleware provides the library with helper functions for serving swagger APIs.
-
-Pseudo middleware handler
-
- import (
- "net/http"
-
- "github.com/go-openapi/errors"
- )
-
- func newCompleteMiddleware(ctx *Context) http.Handler {
- return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- // use context to lookup routes
- if matched, ok := ctx.RouteInfo(r); ok {
-
- if matched.NeedsAuth() {
- if _, err := ctx.Authorize(r, matched); err != nil {
- ctx.Respond(rw, r, matched.Produces, matched, err)
- return
- }
- }
-
- bound, validation := ctx.BindAndValidate(r, matched)
- if validation != nil {
- ctx.Respond(rw, r, matched.Produces, matched, validation)
- return
- }
-
- result, err := matched.Handler.Handle(bound)
- if err != nil {
- ctx.Respond(rw, r, matched.Produces, matched, err)
- return
- }
-
- ctx.Respond(rw, r, matched.Produces, matched, result)
- return
- }
-
- // Not found, check if it exists in the other methods first
- if others := ctx.AllowedMethods(r); len(others) > 0 {
- ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
- return
- }
- ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path))
- })
- }
-*/
+// "github.com/go-openapi/errors"
+// )
+//
+// func newCompleteMiddleware(ctx *Context) http.Handler {
+// return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+// // use context to lookup routes
+// if matched, ok := ctx.RouteInfo(r); ok {
+//
+// if matched.NeedsAuth() {
+// if _, err := ctx.Authorize(r, matched); err != nil {
+// ctx.Respond(rw, r, matched.Produces, matched, err)
+// return
+// }
+// }
+//
+// bound, validation := ctx.BindAndValidate(r, matched)
+// if validation != nil {
+// ctx.Respond(rw, r, matched.Produces, matched, validation)
+// return
+// }
+//
+// result, err := matched.Handler.Handle(bound)
+// if err != nil {
+// ctx.Respond(rw, r, matched.Produces, matched, err)
+// return
+// }
+//
+// ctx.Respond(rw, r, matched.Produces, matched, result)
+// return
+// }
+//
+// // Not found, check if it exists in the other methods first
+// if others := ctx.AllowedMethods(r); len(others) > 0 {
+// ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
+// return
+// }
+// ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path))
+// })
+// }
package middleware
diff --git a/vendor/github.com/go-openapi/runtime/middleware/go18.go b/vendor/github.com/go-openapi/runtime/middleware/go18.go
deleted file mode 100644
index 75c762c09486..000000000000
--- a/vendor/github.com/go-openapi/runtime/middleware/go18.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build go1.8
-
-package middleware
-
-import "net/url"
-
-func pathUnescape(path string) (string, error) {
- return url.PathUnescape(path)
-}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/header/header.go b/vendor/github.com/go-openapi/runtime/middleware/header/header.go
index 3e342258bca6..6ce870d89364 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/header/header.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/header/header.go
@@ -1,3 +1,6 @@
+// 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
@@ -10,6 +13,7 @@
package header
import (
+ "maps"
"net/http"
"strings"
"time"
@@ -25,6 +29,11 @@ const (
isSpace
)
+const (
+ asciiMaxControlChar = 31
+ asciiMaxChar = 127
+)
+
func init() {
// OCTET =
// CHAR =
@@ -42,10 +51,10 @@ func init() {
// token = 1*
// qdtext = >
- for c := 0; c < 256; c++ {
+ for c := range 256 {
var t octetType
- isCtl := c <= 31 || c == 127
- isChar := 0 <= c && c <= 127
+ isCtl := c <= asciiMaxControlChar || c == asciiMaxChar
+ isChar := 0 <= c && c <= asciiMaxChar
isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c))
if strings.ContainsRune(" \t\r\n", rune(c)) {
t |= isSpace
@@ -60,9 +69,7 @@ func init() {
// Copy returns a shallow copy of the header.
func Copy(header http.Header) http.Header {
h := make(http.Header)
- for k, vs := range header {
- h[k] = vs
- }
+ maps.Copy(h, header)
return h
}
@@ -92,7 +99,7 @@ func ParseList(header http.Header, key string) []string {
end := 0
escape := false
quote := false
- for i := 0; i < len(s); i++ {
+ for i := range len(s) {
b := s[i]
switch {
case escape:
@@ -195,7 +202,8 @@ func ParseAccept2(header http.Header, key string) (specs []AcceptSpec) {
}
// ParseAccept parses Accept* headers.
-func ParseAccept(header http.Header, key string) (specs []AcceptSpec) {
+func ParseAccept(header http.Header, key string) []AcceptSpec {
+ var specs []AcceptSpec
loop:
for _, s := range header[key] {
for {
@@ -218,6 +226,7 @@ loop:
}
}
}
+
specs = append(specs, spec)
s = skipSpace(s)
if !strings.HasPrefix(s, ",") {
@@ -226,7 +235,8 @@ loop:
s = skipSpace(s[1:])
}
}
- return
+
+ return specs
}
func skipSpace(s string) (rest string) {
@@ -265,13 +275,16 @@ func expectQuality(s string) (q float64, rest string) {
case len(s) == 0:
return -1, ""
case s[0] == '0':
- q = 0
+ // q is already 0
+ s = s[1:]
case s[0] == '1':
+ s = s[1:]
q = 1
+ case s[0] == '.':
+ // q is already 0
default:
return -1, ""
}
- s = s[1:]
if !strings.HasPrefix(s, ".") {
return q, s
}
@@ -303,7 +316,7 @@ func expectTokenOrQuoted(s string) (value string, rest string) {
p := make([]byte, len(s)-1)
j := copy(p, s[:i])
escape := true
- for i = i + 1; i < len(s); i++ {
+ for i++; i < len(s); i++ {
b := s[i]
switch {
case escape:
diff --git a/vendor/github.com/go-openapi/runtime/middleware/negotiate.go b/vendor/github.com/go-openapi/runtime/middleware/negotiate.go
index a9b6f27d3d37..cb0a85283c13 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/negotiate.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/negotiate.go
@@ -1,3 +1,6 @@
+// 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
@@ -94,5 +97,6 @@ func normalizeOffers(orig []string) (norm []string) {
}
func normalizeOffer(orig string) string {
- return strings.SplitN(orig, ";", 2)[0]
+ const maxParts = 2
+ return strings.SplitN(orig, ";", maxParts)[0]
}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
index bc6942a0f1b3..4d286a6c8c75 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.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 middleware
@@ -22,7 +11,7 @@ import (
type errorResp struct {
code int
- response interface{}
+ response any
headers http.Header
}
@@ -42,14 +31,14 @@ func (e *errorResp) WriteResponse(rw http.ResponseWriter, producer runtime.Produ
}
}
-// NotImplemented the error response when the response is not implemented
+// NotImplemented the error response when the response is not implemented.
func NotImplemented(message string) Responder {
return Error(http.StatusNotImplemented, message)
}
// Error creates a generic responder for returning errors, the data will be serialized
-// with the matching producer for the request
-func Error(code int, data interface{}, headers ...http.Header) Responder {
+// with the matching producer for the request.
+func Error(code int, data any, headers ...http.Header) Responder {
var hdr http.Header
for _, h := range headers {
for k, v := range h {
diff --git a/vendor/github.com/go-openapi/runtime/middleware/operation.go b/vendor/github.com/go-openapi/runtime/middleware/operation.go
index 1175a63cf29b..24f466b597d7 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/operation.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/operation.go
@@ -1,22 +1,11 @@
-// 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 middleware
import "net/http"
-// NewOperationExecutor creates a context aware middleware that handles the operations after routing
+// NewOperationExecutor creates a context aware [middleware] that handles the operations after routing.
func NewOperationExecutor(ctx *Context) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// use context to lookup routes
diff --git a/vendor/github.com/go-openapi/runtime/middleware/parameter.go b/vendor/github.com/go-openapi/runtime/middleware/parameter.go
index 8fa0cf4e464d..a9d2a36460ba 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/parameter.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/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 middleware
@@ -24,17 +13,22 @@ import (
"strconv"
"github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/conv"
+ "github.com/go-openapi/swag/stringutils"
"github.com/go-openapi/validate"
-
- "github.com/go-openapi/runtime"
)
const defaultMaxMemory = 32 << 20
-var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
+const (
+ typeString = "string"
+ typeArray = "array"
+)
+
+var textUnmarshalType = reflect.TypeFor[encoding.TextUnmarshaler]()
func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder {
binder := new(untypedParamBinder)
@@ -61,85 +55,6 @@ func (p *untypedParamBinder) Type() reflect.Type {
return p.typeForSchema(p.parameter.Type, p.parameter.Format, p.parameter.Items)
}
-func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type {
- switch tpe {
- case "boolean":
- return reflect.TypeOf(true)
-
- case "string":
- if tt, ok := p.formats.GetType(format); ok {
- return tt
- }
- return reflect.TypeOf("")
-
- case "integer":
- switch format {
- case "int8":
- return reflect.TypeOf(int8(0))
- case "int16":
- return reflect.TypeOf(int16(0))
- case "int32":
- return reflect.TypeOf(int32(0))
- case "int64":
- return reflect.TypeOf(int64(0))
- default:
- return reflect.TypeOf(int64(0))
- }
-
- case "number":
- switch format {
- case "float":
- return reflect.TypeOf(float32(0))
- case "double":
- return reflect.TypeOf(float64(0))
- }
-
- case "array":
- if items == nil {
- return nil
- }
- itemsType := p.typeForSchema(items.Type, items.Format, items.Items)
- if itemsType == nil {
- return nil
- }
- return reflect.MakeSlice(reflect.SliceOf(itemsType), 0, 0).Type()
-
- case "file":
- return reflect.TypeOf(&runtime.File{}).Elem()
-
- case "object":
- return reflect.TypeOf(map[string]interface{}{})
- }
- return nil
-}
-
-func (p *untypedParamBinder) allowsMulti() bool {
- return p.parameter.In == "query" || p.parameter.In == "formData"
-}
-
-func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
- name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
- if tpe == "array" {
- if cf == "multi" {
- if !p.allowsMulti() {
- return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
- }
- vv, hasKey, _ := values.GetOK(name)
- return vv, false, hasKey, nil
- }
-
- v, hk, hv := values.GetOK(name)
- if !hv {
- return nil, false, hk, nil
- }
- d, c, e := p.readFormattedSliceFieldValue(v[len(v)-1], target)
- return d, c, hk, e
- }
-
- vv, hk, _ := values.GetOK(name)
- return vv, false, hk, nil
-}
-
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 {
@@ -206,8 +121,13 @@ func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams
if p.parameter.Type == "file" {
file, header, ffErr := request.FormFile(p.parameter.Name)
if ffErr != nil {
- return errors.NewParseError(p.Name, p.parameter.In, "", ffErr)
+ if p.parameter.Required {
+ return errors.NewParseError(p.Name, p.parameter.In, "", ffErr)
+ }
+
+ return nil
}
+
target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header}))
return nil
}
@@ -254,12 +174,91 @@ func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams
target.Set(reflect.Indirect(newValue))
return nil
default:
- return errors.New(500, fmt.Sprintf("invalid parameter location %q", p.parameter.In))
+ return fmt.Errorf("%d: invalid parameter location %q", http.StatusInternalServerError, p.parameter.In)
}
}
+func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type {
+ switch tpe {
+ case "boolean":
+ return reflect.TypeFor[bool]()
+
+ case typeString:
+ if tt, ok := p.formats.GetType(format); ok {
+ return tt
+ }
+ return reflect.TypeFor[string]()
+
+ case "integer":
+ switch format {
+ case "int8":
+ return reflect.TypeFor[int8]()
+ case "int16":
+ return reflect.TypeFor[int16]()
+ case "int32":
+ return reflect.TypeFor[int32]()
+ case "int64":
+ return reflect.TypeFor[int64]()
+ default:
+ return reflect.TypeFor[int64]()
+ }
+
+ case "number":
+ switch format {
+ case "float":
+ return reflect.TypeFor[float32]()
+ case "double":
+ return reflect.TypeFor[float64]()
+ }
+
+ case typeArray:
+ if items == nil {
+ return nil
+ }
+ itemsType := p.typeForSchema(items.Type, items.Format, items.Items)
+ if itemsType == nil {
+ return nil
+ }
+ return reflect.MakeSlice(reflect.SliceOf(itemsType), 0, 0).Type()
+
+ case "file":
+ return reflect.TypeFor[runtime.File]()
+
+ case "object":
+ return reflect.TypeFor[map[string]any]()
+ }
+ return nil
+}
+
+func (p *untypedParamBinder) allowsMulti() bool {
+ return p.parameter.In == "query" || p.parameter.In == "formData"
+}
+
+func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
+ name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
+ if tpe == typeArray {
+ if cf == "multi" {
+ if !p.allowsMulti() {
+ return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
+ }
+ vv, hasKey, _ := values.GetOK(name)
+ return vv, false, hasKey, nil
+ }
+
+ v, hk, hv := values.GetOK(name)
+ if !hv {
+ return nil, false, hk, nil
+ }
+ d, c, e := p.readFormattedSliceFieldValue(v[len(v)-1], target)
+ return d, c, hk, e
+ }
+
+ vv, hk, _ := values.GetOK(name)
+ return vv, false, hk, nil
+}
+
func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error {
- if p.parameter.Type == "array" {
+ if p.parameter.Type == typeArray {
return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey)
}
var d string
@@ -269,7 +268,7 @@ func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflec
return p.setFieldValue(target, p.parameter.Default, d, hasKey)
}
-func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string, hasKey bool) error {
+func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue any, data string, hasKey bool) error { //nolint:gocyclo
tpe := p.parameter.Type
if p.parameter.Format != "" {
tpe = p.parameter.Format
@@ -313,7 +312,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
return nil
}
- switch target.Kind() {
+ switch target.Kind() { //nolint:exhaustive // we want to check only types that map from a swagger parameter
case reflect.Bool:
if data == "" {
if target.CanSet() {
@@ -321,7 +320,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
}
return nil
}
- b, err := swag.ConvertBool(data)
+ b, err := conv.ConvertBool(data)
if err != nil {
return err
}
@@ -331,7 +330,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if data == "" {
if target.CanSet() {
- rd := defVal.Convert(reflect.TypeOf(int64(0)))
+ rd := defVal.Convert(reflect.TypeFor[int64]())
target.SetInt(rd.Int())
}
return nil
@@ -350,7 +349,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if data == "" {
if target.CanSet() {
- rd := defVal.Convert(reflect.TypeOf(uint64(0)))
+ rd := defVal.Convert(reflect.TypeFor[uint64]())
target.SetUint(rd.Uint())
}
return nil
@@ -369,7 +368,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
case reflect.Float32, reflect.Float64:
if data == "" {
if target.CanSet() {
- rd := defVal.Convert(reflect.TypeOf(float64(0)))
+ rd := defVal.Convert(reflect.TypeFor[float64]())
target.SetFloat(rd.Float())
}
return nil
@@ -416,12 +415,12 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
return nil
}
-func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue interface{}, data string) (bool, error) {
+func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue any, data string) (bool, error) {
if !target.CanSet() {
return false, nil
}
// When a type implements encoding.TextUnmarshaler we'll use that instead of reflecting some more
- if reflect.PtrTo(target.Type()).Implements(textUnmarshalType) {
+ if reflect.PointerTo(target.Type()).Implements(textUnmarshalType) {
if defaultValue != nil && len(data) == 0 {
target.Set(reflect.ValueOf(defaultValue))
return true, nil
@@ -445,10 +444,10 @@ func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target re
return nil, true, nil
}
- return swag.SplitByFormat(data, p.parameter.CollectionFormat), false, nil
+ return stringutils.SplitByFormat(data, p.parameter.CollectionFormat), false, nil
}
-func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultValue interface{}, data []string, hasKey bool) error {
+func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultValue any, data []string, hasKey bool) error {
sz := len(data)
if (!hasKey || (!p.parameter.AllowEmptyValue && (sz == 0 || (sz == 1 && data[0] == "")))) && p.parameter.Required && defaultValue == nil {
return errors.Required(p.Name, p.parameter.In, data)
@@ -469,7 +468,7 @@ func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultVal
value := reflect.MakeSlice(reflect.SliceOf(target.Type().Elem()), sz, sz)
- for i := 0; i < sz; i++ {
+ for i := range sz {
if err := p.setFieldValue(value.Index(i), nil, data[i], hasKey); err != nil {
return err
}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go b/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go
deleted file mode 100644
index 03385251e195..000000000000
--- a/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build !go1.8
-
-package middleware
-
-import "net/url"
-
-func pathUnescape(path string) (string, error) {
- return url.QueryUnescape(path)
-}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go b/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go
index 4be330d6dc34..1574defb41ab 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/rapidoc.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package middleware
import (
@@ -8,69 +11,59 @@ import (
"path"
)
-// RapiDocOpts configures the RapiDoc middlewares
+// RapiDocOpts configures the [RapiDoc] middlewares.
type RapiDocOpts struct {
- // BasePath for the UI path, defaults to: /
+ // BasePath for the UI, defaults to: /
BasePath string
- // Path combines with BasePath for the full UI path, defaults to: docs
+
+ // Path combines with BasePath to construct the path to the UI, defaults to: "docs".
Path string
- // SpecURL the url to find the spec for
+
+ // SpecURL is the URL of the spec document.
+ //
+ // Defaults to: /swagger.json
SpecURL string
- // RapiDocURL for the js that generates the rapidoc site, defaults to: https://cdn.jsdelivr.net/npm/rapidoc/bundles/rapidoc.standalone.js
- RapiDocURL 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
}
-// EnsureDefaults in case some options are missing
func (r *RapiDocOpts) EnsureDefaults() {
- if r.BasePath == "" {
- r.BasePath = "/"
- }
- if r.Path == "" {
- r.Path = "docs"
- }
- if r.SpecURL == "" {
- r.SpecURL = "/swagger.json"
- }
+ common := toCommonUIOptions(r)
+ common.EnsureDefaults()
+ fromCommonToAnyOptions(common, r)
+
+ // rapidoc-specifics
if r.RapiDocURL == "" {
r.RapiDocURL = rapidocLatest
}
- if r.Title == "" {
- r.Title = "API documentation"
+ 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.
+// 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(rapidocTemplate))
-
- buf := bytes.NewBuffer(nil)
- _ = tmpl.Execute(buf, opts)
- b := buf.Bytes()
-
- return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- if r.URL.Path == pth {
- rw.Header().Set("Content-Type", "text/html; charset=utf-8")
- rw.WriteHeader(http.StatusOK)
-
- _, _ = rw.Write(b)
- return
- }
+ 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))
+ }
- if next == nil {
- rw.Header().Set("Content-Type", "text/plain")
- rw.WriteHeader(http.StatusNotFound)
- _, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
- return
- }
- next.ServeHTTP(rw, r)
- })
+ return serveUI(pth, assets.Bytes(), next)
}
const (
@@ -79,7 +72,7 @@ const (
{{ .Title }}
-
+
diff --git a/vendor/github.com/go-openapi/runtime/middleware/redoc.go b/vendor/github.com/go-openapi/runtime/middleware/redoc.go
index 019c854295be..1007409a30bb 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/redoc.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/redoc.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package middleware
import (
@@ -8,69 +11,60 @@ import (
"path"
)
-// RedocOpts configures the Redoc middlewares
+// RedocOpts configures the [Redoc] middlewares.
type RedocOpts struct {
- // BasePath for the UI path, defaults to: /
+ // BasePath for the UI, defaults to: /
BasePath string
- // Path combines with BasePath for the full UI path, defaults to: docs
+
+ // Path combines with BasePath to construct the path to the UI, defaults to: "docs".
Path string
- // SpecURL the url to find the spec for
+
+ // SpecURL is the URL of the spec document.
+ //
+ // Defaults to: /swagger.json
SpecURL string
- // RedocURL for the js that generates the redoc site, defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js
- RedocURL 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
+// EnsureDefaults in case some options are missing.
func (r *RedocOpts) EnsureDefaults() {
- if r.BasePath == "" {
- r.BasePath = "/"
- }
- if r.Path == "" {
- r.Path = "docs"
- }
- if r.SpecURL == "" {
- r.SpecURL = "/swagger.json"
- }
+ common := toCommonUIOptions(r)
+ common.EnsureDefaults()
+ fromCommonToAnyOptions(common, r)
+
+ // redoc-specifics
if r.RedocURL == "" {
r.RedocURL = redocLatest
}
- if r.Title == "" {
- r.Title = "API documentation"
+ 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.
+// 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(redocTemplate))
-
- buf := bytes.NewBuffer(nil)
- _ = tmpl.Execute(buf, opts)
- b := buf.Bytes()
-
- return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- if r.URL.Path == pth {
- rw.Header().Set("Content-Type", "text/html; charset=utf-8")
- rw.WriteHeader(http.StatusOK)
-
- _, _ = rw.Write(b)
- return
- }
+ 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))
+ }
- if next == nil {
- rw.Header().Set("Content-Type", "text/plain")
- rw.WriteHeader(http.StatusNotFound)
- _, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
- return
- }
- next.ServeHTTP(rw, r)
- })
+ return serveUI(pth, assets.Bytes(), next)
}
const (
diff --git a/vendor/github.com/go-openapi/runtime/middleware/request.go b/vendor/github.com/go-openapi/runtime/middleware/request.go
index 760c37861d0f..ad781663b8b7 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/request.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/request.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 middleware
@@ -19,18 +8,19 @@ import (
"reflect"
"github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/logger"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
-
- "github.com/go-openapi/runtime"
)
-// UntypedRequestBinder binds and validates the data from a http request
+// UntypedRequestBinder binds and validates the data from a [http] request.
type UntypedRequestBinder struct {
Spec *spec.Swagger
Parameters map[string]spec.Parameter
Formats strfmt.Registry
paramBinders map[string]*untypedParamBinder
+ debugLogf func(string, ...any) // a logging function to debug context and all components using it
}
// NewUntypedRequestBinder creates a new binder for reading a request.
@@ -44,18 +34,19 @@ func NewUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Sw
paramBinders: binders,
Spec: spec,
Formats: formats,
+ debugLogf: debugLogfFunc(nil),
}
}
-// Bind perform the databinding and validation
-func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data interface{}) error {
+// Bind perform the databinding and validation.
+func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data any) error {
val := reflect.Indirect(reflect.ValueOf(data))
isMap := val.Kind() == reflect.Map
var result []error
- debugLog("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
+ o.debugLogf("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
for fieldName, param := range o.Parameters {
binder := o.paramBinders[fieldName]
- debugLog("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
+ o.debugLogf("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
var target reflect.Value
if !isMap {
binder.Name = fieldName
@@ -65,17 +56,17 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara
if isMap {
tpe := binder.Type()
if tpe == nil {
- if param.Schema.Type.Contains("array") {
- tpe = reflect.TypeOf([]interface{}{})
+ if param.Schema.Type.Contains(typeArray) {
+ tpe = reflect.TypeFor[[]any]()
} else {
- tpe = reflect.TypeOf(map[string]interface{}{})
+ tpe = reflect.TypeFor[map[string]any]()
}
}
target = reflect.Indirect(reflect.New(tpe))
}
if !target.IsValid() {
- result = append(result, errors.New(500, "parameter name %q is an unknown field", binder.Name))
+ result = append(result, errors.New(http.StatusInternalServerError, "parameter name %q is an unknown field", binder.Name))
continue
}
@@ -102,3 +93,14 @@ 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 02768bade28d..e828653be7ad 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/router.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/router.go
@@ -1,50 +1,40 @@
-// 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 middleware
import (
"fmt"
"net/http"
+ "net/url"
fpath "path"
"regexp"
"strings"
- "github.com/go-openapi/runtime/security"
-
"github.com/go-openapi/analysis"
"github.com/go-openapi/errors"
"github.com/go-openapi/loads"
- "github.com/go-openapi/spec"
- "github.com/go-openapi/strfmt"
-
"github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/logger"
"github.com/go-openapi/runtime/middleware/denco"
+ "github.com/go-openapi/runtime/security"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag/stringutils"
)
// RouteParam is a object to capture route params in a framework agnostic way.
// implementations of the muxer should use these route params to communicate with the
-// swagger framework
+// swagger framework.
type RouteParam struct {
Name string
Value string
}
-// RouteParams the collection of route params
+// RouteParams the collection of route params.
type RouteParams []RouteParam
-// Get gets the value for the route param for the specified key
+// Get gets the value for the route param for the specified key.
func (r RouteParams) Get(name string) string {
vv, _, _ := r.GetOK(name)
if len(vv) > 0 {
@@ -54,9 +44,9 @@ func (r RouteParams) Get(name string) string {
}
// GetOK gets the value but also returns booleans to indicate if a key or value
-// is present. This aids in validation and satisfies an interface in use there
+// is present. This aids in validation and satisfies an interface in use there.
//
-// The returned values are: data, has key, has value
+// The returned values are: data, has key, has value.
func (r RouteParams) GetOK(name string) ([]string, bool, bool) {
for _, p := range r {
if p.Name == name {
@@ -66,10 +56,10 @@ func (r RouteParams) GetOK(name string) ([]string, bool, bool) {
return nil, false, false
}
-// NewRouter creates a new context aware router middleware
+// NewRouter creates a new context-aware router [middleware].
func NewRouter(ctx *Context, next http.Handler) http.Handler {
if ctx.router == nil {
- ctx.router = DefaultRouter(ctx.spec, ctx.api)
+ ctx.router = DefaultRouter(ctx.spec, ctx.api, WithDefaultRouterLoggerFunc(ctx.debugLogf))
}
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
@@ -78,18 +68,22 @@ func NewRouter(ctx *Context, next http.Handler) http.Handler {
return
}
+ // Always use the default producer Content-Type for Method not
+ // allowed and Not found responses
+ produces := []string{ctx.api.DefaultProduces()}
+
// Not found, check if it exists in the other methods first
if others := ctx.AllowedMethods(r); len(others) > 0 {
- ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
+ ctx.Respond(rw, r, produces, nil, errors.MethodNotAllowed(r.Method, others))
return
}
- ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.EscapedPath()))
+ ctx.Respond(rw, r, produces, nil, errors.NotFound("path %s was not found", r.URL.EscapedPath()))
})
}
// RoutableAPI represents an interface for things that can serve
-// as a provider of implementations for the swagger router
+// as a provider of implementations for the swagger router.
type RoutableAPI interface {
HandlerFor(string, string) (http.Handler, bool)
ServeErrorFor(string) func(http.ResponseWriter, *http.Request, error)
@@ -102,41 +96,75 @@ type RoutableAPI interface {
DefaultConsumes() string
}
-// Router represents a swagger aware router
+// Router represents a swagger-aware router.
type Router interface {
Lookup(method, path string) (*MatchedRoute, bool)
OtherMethods(method, path string) []string
}
type defaultRouteBuilder struct {
- spec *loads.Document
- analyzer *analysis.Spec
- api RoutableAPI
- records map[string][]denco.Record
+ spec *loads.Document
+ analyzer *analysis.Spec
+ api RoutableAPI
+ records map[string][]denco.Record
+ debugLogf func(string, ...any) // a logging function to debug context and all components using it
}
type defaultRouter struct {
- spec *loads.Document
- routers map[string]*denco.Router
+ spec *loads.Document
+ routers map[string]*denco.Router
+ debugLogf func(string, ...any) // a logging function to debug context and all components using it
}
-func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI) *defaultRouteBuilder {
+func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) *defaultRouteBuilder {
+ var o defaultRouterOpts
+ for _, apply := range opts {
+ apply(&o)
+ }
+ if o.debugLogf == nil {
+ o.debugLogf = debugLogfFunc(nil) // defaults to standard logger
+ }
+
return &defaultRouteBuilder{
- spec: spec,
- analyzer: analysis.New(spec.Spec()),
- api: api,
- records: make(map[string][]denco.Record),
+ spec: spec,
+ analyzer: analysis.New(spec.Spec()),
+ api: api,
+ records: make(map[string][]denco.Record),
+ debugLogf: o.debugLogf,
}
}
-// DefaultRouter creates a default implemenation of the router
-func DefaultRouter(spec *loads.Document, api RoutableAPI) Router {
- builder := newDefaultRouteBuilder(spec, api)
+// DefaultRouterOpt allows to inject optional behavior to the default router.
+type DefaultRouterOpt func(*defaultRouterOpts)
+
+type defaultRouterOpts struct {
+ debugLogf func(string, ...any)
+}
+
+// WithDefaultRouterLogger sets the debug logger for the default router.
+//
+// This is enabled only in DEBUG mode.
+func WithDefaultRouterLogger(lg logger.Logger) DefaultRouterOpt {
+ return func(o *defaultRouterOpts) {
+ o.debugLogf = debugLogfFunc(lg)
+ }
+}
+
+// WithDefaultRouterLoggerFunc sets a logging debug method for the default router.
+func WithDefaultRouterLoggerFunc(fn func(string, ...any)) DefaultRouterOpt {
+ return func(o *defaultRouterOpts) {
+ o.debugLogf = fn
+ }
+}
+
+// DefaultRouter creates a default implementation of the router.
+func DefaultRouter(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) Router {
+ builder := newDefaultRouteBuilder(spec, api, opts...)
if spec != nil {
for method, paths := range builder.analyzer.Operations() {
for path, operation := range paths {
fp := fpath.Join(spec.BasePath(), path)
- debugLog("adding route %s %s %q", method, fp, operation.ID)
+ builder.debugLogf("adding route %s %s %q", method, fp, operation.ID)
builder.AddRoute(method, fp, operation)
}
}
@@ -146,7 +174,7 @@ func DefaultRouter(spec *loads.Document, api RoutableAPI) Router {
// RouteAuthenticator is an authenticator that can compose several authenticators together.
// It also knows when it contains an authenticator that allows for anonymous pass through.
-// Contains a group of 1 or more authenticators that have a logical AND relationship
+// Contains a group of 1 or more authenticators that have a logical AND relationship.
type RouteAuthenticator struct {
Authenticator map[string]runtime.Authenticator
Schemes []string
@@ -161,25 +189,25 @@ func (ra *RouteAuthenticator) AllowsAnonymous() bool {
}
// AllScopes returns a list of unique scopes that is the combination
-// of all the scopes in the requirements
+// of all the scopes in the requirements.
func (ra *RouteAuthenticator) AllScopes() []string {
return ra.allScopes
}
// CommonScopes returns a list of unique scopes that are common in all the
-// scopes in the requirements
+// scopes in the requirements.
func (ra *RouteAuthenticator) CommonScopes() []string {
return ra.commonScopes
}
-// Authenticate Authenticator interface implementation
-func (ra *RouteAuthenticator) Authenticate(req *http.Request, route *MatchedRoute) (bool, interface{}, error) {
+// Authenticate Authenticator interface implementation.
+func (ra *RouteAuthenticator) Authenticate(req *http.Request, route *MatchedRoute) (bool, any, error) {
if ra.allowAnonymous {
route.Authenticator = ra
return true, nil, nil
}
// iterate in proper order
- var lastResult interface{}
+ var lastResult any
for _, scheme := range ra.Schemes {
if authenticator, ok := ra.Authenticator[scheme]; ok {
applies, princ, err := authenticator.Authenticate(&security.ScopedAuthRequest{
@@ -238,10 +266,10 @@ func stringSliceIntersection(slices ...[]string) []string {
return intersection
}
-// RouteAuthenticators represents a group of authenticators that represent a logical OR
+// RouteAuthenticators represents a group of authenticators that represent a logical OR.
type RouteAuthenticators []RouteAuthenticator
-// AllowsAnonymous returns true when there is an authenticator that means optional auth
+// AllowsAnonymous returns true when there is an authenticator that means optional auth.
func (ras RouteAuthenticators) AllowsAnonymous() bool {
for _, ra := range ras {
if ra.AllowsAnonymous() {
@@ -251,8 +279,8 @@ func (ras RouteAuthenticators) AllowsAnonymous() bool {
return false
}
-// Authenticate method implemention so this collection can be used as authenticator
-func (ras RouteAuthenticators) Authenticate(req *http.Request, route *MatchedRoute) (bool, interface{}, error) {
+// Authenticate method implementation so this collection can be used as authenticator.
+func (ras RouteAuthenticators) Authenticate(req *http.Request, route *MatchedRoute) (bool, any, error) {
var lastError error
var allowsAnon bool
var anonAuth RouteAuthenticator
@@ -296,51 +324,53 @@ type routeEntry struct {
Authorizer runtime.Authorizer
}
-// MatchedRoute represents the route that was matched in this request
+// MatchedRoute represents the route that was matched in this request.
type MatchedRoute struct {
routeEntry
+
Params RouteParams
Consumer runtime.Consumer
Producer runtime.Producer
Authenticator *RouteAuthenticator
}
-// HasAuth returns true when the route has a security requirement defined
+// HasAuth returns true when the route has a security requirement defined.
func (m *MatchedRoute) HasAuth() bool {
return len(m.Authenticators) > 0
}
// NeedsAuth returns true when the request still
-// needs to perform authentication
+// needs to perform authentication.
func (m *MatchedRoute) NeedsAuth() bool {
return m.HasAuth() && m.Authenticator == nil
}
func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
mth := strings.ToUpper(method)
- debugLog("looking up route for %s %s", method, path)
+ d.debugLogf("looking up route for %s %s", method, path)
if Debug {
if len(d.routers) == 0 {
- debugLog("there are no known routers")
+ d.debugLogf("there are no known routers")
}
for meth := range d.routers {
- debugLog("got a router for %s", meth)
+ 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 {
- debugLog("found a route for %s %s with %d parameters", method, path, len(entry.Parameters))
+ 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 := pathUnescape(p.Value)
+ v, err := url.PathUnescape(p.Value)
if err != nil {
- debugLog("failed to escape %q: %v", p.Value, err)
+ 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
- if xpos := strings.Index(entry.PathPattern, fmt.Sprintf("{%s}", p.Name)) + len(p.Name) + 2; xpos < len(entry.PathPattern) && entry.PathPattern[xpos] != '/' {
+ 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)
@@ -355,10 +385,10 @@ func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
return &MatchedRoute{routeEntry: *entry, Params: params}, true
}
} else {
- debugLog("couldn't find a route by path for %s %s", method, path)
+ d.debugLogf("couldn't find a route by path for %s %s", method, path)
}
} else {
- debugLog("couldn't find a route by method for %s %s", method, path)
+ d.debugLogf("couldn't find a route by method for %s %s", method, path)
}
return nil, false
}
@@ -377,7 +407,11 @@ func (d *defaultRouter) OtherMethods(method, path string) []string {
return methods
}
-// convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco
+func (d *defaultRouter) SetLogger(lg logger.Logger) {
+ d.debugLogf = debugLogfFunc(lg)
+}
+
+// convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco.
var pathConverter = regexp.MustCompile(`{(.+?)}([^/]*)`)
func decodeCompositParams(name string, value string, pattern string, names []string, values []string) ([]string, []string) {
@@ -412,12 +446,23 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
bp = bp[:len(bp)-1]
}
- debugLog("operation: %#v", *operation)
+ d.debugLogf("operation: %#v", *operation)
if handler, ok := d.api.HandlerFor(method, strings.TrimPrefix(path, bp)); ok {
consumes := d.analyzer.ConsumesFor(operation)
produces := d.analyzer.ProducesFor(operation)
parameters := d.analyzer.ParamsFor(method, strings.TrimPrefix(path, bp))
+ // add API defaults if not part of the spec
+ if defConsumes := d.api.DefaultConsumes(); defConsumes != "" && !stringutils.ContainsStringsCI(consumes, defConsumes) {
+ consumes = append(consumes, defConsumes)
+ }
+
+ if defProduces := d.api.DefaultProduces(); defProduces != "" && !stringutils.ContainsStringsCI(produces, defProduces) {
+ produces = append(produces, defProduces)
+ }
+
+ requestBinder := NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats())
+ requestBinder.setDebugLogf(d.debugLogf)
record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{
BasePath: bp,
PathPattern: path,
@@ -429,7 +474,7 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
Producers: d.api.ProducersFor(normalizeOffers(produces)),
Parameters: parameters,
Formats: d.api.Formats(),
- Binder: NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()),
+ Binder: requestBinder,
Authenticators: d.buildAuthenticators(operation),
Authorizer: d.api.Authorizer(),
})
@@ -437,13 +482,27 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
}
}
+func (d *defaultRouteBuilder) Build() *defaultRouter {
+ routers := make(map[string]*denco.Router)
+ for method, records := range d.records {
+ router := denco.New()
+ _ = router.Build(records)
+ routers[method] = router
+ }
+ return &defaultRouter{
+ spec: d.spec,
+ routers: routers,
+ debugLogf: d.debugLogf,
+ }
+}
+
func (d *defaultRouteBuilder) buildAuthenticators(operation *spec.Operation) RouteAuthenticators {
requirements := d.analyzer.SecurityRequirementsFor(operation)
- var auths []RouteAuthenticator
+ auths := make([]RouteAuthenticator, 0, len(requirements))
for _, reqs := range requirements {
- var schemes []string
+ schemes := make([]string, 0, len(reqs))
scopes := make(map[string][]string, len(reqs))
- var scopeSlices [][]string
+ scopeSlices := make([][]string, 0, len(reqs))
for _, req := range reqs {
schemes = append(schemes, req.Name)
scopes[req.Name] = req.Scopes
@@ -463,16 +522,3 @@ func (d *defaultRouteBuilder) buildAuthenticators(operation *spec.Operation) Rou
}
return auths
}
-
-func (d *defaultRouteBuilder) Build() *defaultRouter {
- routers := make(map[string]*denco.Router)
- for method, records := range d.records {
- router := denco.New()
- _ = router.Build(records)
- routers[method] = router
- }
- return &defaultRouter{
- spec: d.spec,
- routers: routers,
- }
-}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/security.go b/vendor/github.com/go-openapi/runtime/middleware/security.go
index 2b061caefcb3..37ecfa6fd4e7 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/security.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/security.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 middleware
diff --git a/vendor/github.com/go-openapi/runtime/middleware/spec.go b/vendor/github.com/go-openapi/runtime/middleware/spec.go
index f02914298060..0a64a9572b5c 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/spec.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/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 middleware
@@ -19,30 +8,84 @@ import (
"path"
)
-// Spec creates a middleware to serve a swagger spec.
-// This allows for altering the spec before starting the http listener.
-// This can be useful if you want to serve the swagger spec from another path than /swagger.json
+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.
//
-func Spec(basePath string, b []byte, next http.Handler) http.Handler {
+// 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 = "/"
}
- pth := path.Join(basePath, "swagger.json")
+ o := specOptionsWithDefaults(opts)
+ pth := path.Join(basePath, o.Path, o.Document)
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- if r.URL.Path == pth {
- rw.Header().Set("Content-Type", "application/json")
+ if path.Clean(r.URL.Path) == pth {
+ rw.Header().Set(contentTypeHeader, applicationJSON)
rw.WriteHeader(http.StatusOK)
- //#nosec
_, _ = rw.Write(b)
+
return
}
- if next == nil {
- rw.Header().Set("Content-Type", "application/json")
- rw.WriteHeader(http.StatusNotFound)
+ if next != nil {
+ next.ServeHTTP(rw, r)
+
return
}
- next.ServeHTTP(rw, r)
+
+ 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
index 2c92f5c91f3a..14ed37ced69e 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/swaggerui.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package middleware
import (
@@ -8,37 +11,67 @@ import (
"path"
)
-// SwaggerUIOpts configures the Swaggerui middlewares
+// SwaggerUIOpts configures the [SwaggerUI] [middleware].
type SwaggerUIOpts struct {
- // BasePath for the UI path, defaults to: /
+ // BasePath for the API, defaults to: /
BasePath string
- // Path combines with BasePath for the full UI path, defaults to: docs
+
+ // Path combines with BasePath to construct the path to the UI, defaults to: "docs".
Path string
- // SpecURL the url to find the spec for
+
+ // 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 string
+
+ // 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
-
- // Title for the documentation site, default to: API documentation
- Title string
}
-// EnsureDefaults in case some options are missing
+// EnsureDefaults in case some options are missing.
func (r *SwaggerUIOpts) EnsureDefaults() {
- if r.BasePath == "" {
- r.BasePath = "/"
+ r.ensureDefaults()
+
+ if r.Template == "" {
+ r.Template = swaggeruiTemplate
}
- if r.Path == "" {
- r.Path = "docs"
+}
+
+func (r *SwaggerUIOpts) EnsureDefaultsOauth2() {
+ r.ensureDefaults()
+
+ if r.Template == "" {
+ r.Template = swaggerOAuthTemplate
}
- if r.SpecURL == "" {
- r.SpecURL = "/swagger.json"
+}
+
+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
@@ -55,40 +88,22 @@ func (r *SwaggerUIOpts) EnsureDefaults() {
if r.Favicon32 == "" {
r.Favicon32 = swaggerFavicon32Latest
}
- if r.Title == "" {
- r.Title = "API documentation"
- }
}
-// SwaggerUI creates a middleware to serve a documentation site for a swagger spec.
-// This allows for altering the spec before starting the http listener.
+// 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(swaggeruiTemplate))
-
- buf := bytes.NewBuffer(nil)
- _ = tmpl.Execute(buf, &opts)
- b := buf.Bytes()
-
- return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- if r.URL.Path == pth {
- rw.Header().Set("Content-Type", "text/html; charset=utf-8")
- rw.WriteHeader(http.StatusOK)
-
- _, _ = rw.Write(b)
- return
- }
-
- if next == nil {
- rw.Header().Set("Content-Type", "text/plain")
- rw.WriteHeader(http.StatusNotFound)
- _, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
- return
- }
- next.ServeHTTP(rw, r)
- })
+ 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 (
@@ -149,7 +164,8 @@ const (
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
- layout: "StandaloneLayout"
+ layout: "StandaloneLayout",
+ oauth2RedirectUrl: '{{ .OAuthCallbackURL }}'
})
// End Swagger UI call region
diff --git a/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go b/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go
new file mode 100644
index 000000000000..879bdbaadea7
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/swaggerui_oauth2.go
@@ -0,0 +1,108 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "text/template"
+)
+
+func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler {
+ opts.EnsureDefaultsOauth2()
+
+ pth := opts.OAuthCallbackURL
+ tmpl := template.Must(template.New("swaggeroauth").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 (
+ swaggerOAuthTemplate = `
+
+
+
+ {{ .Title }}
+
+
+
+
+
+`
+)
diff --git a/vendor/github.com/go-openapi/runtime/middleware/ui_options.go b/vendor/github.com/go-openapi/runtime/middleware/ui_options.go
new file mode 100644
index 000000000000..ed255426ad8a
--- /dev/null
+++ b/vendor/github.com/go-openapi/runtime/middleware/ui_options.go
@@ -0,0 +1,176 @@
+// 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/untyped/api.go b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
index 39a85f7d9e89..f4c966bacdc8 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.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 untyped
@@ -29,7 +18,28 @@ import (
"github.com/go-openapi/runtime"
)
-// NewAPI creates the default untyped API
+const (
+ smallPreallocatedSlots = 10
+ mediumPreallocatedSlots = 30
+)
+
+// API represents an untyped mux for a swagger spec.
+type API struct {
+ spec *loads.Document
+ analyzer *analysis.Spec
+ DefaultProduces string
+ DefaultConsumes string
+ consumers map[string]runtime.Consumer
+ producers map[string]runtime.Producer
+ authenticators map[string]runtime.Authenticator
+ authorizer runtime.Authorizer
+ operations map[string]map[string]runtime.OperationHandler
+ ServeError func(http.ResponseWriter, *http.Request, error)
+ Models map[string]func() any
+ formats strfmt.Registry
+}
+
+// NewAPI creates the default untyped API.
func NewAPI(spec *loads.Document) *API {
var an *analysis.Spec
if spec != nil && spec.Spec() != nil {
@@ -38,34 +48,19 @@ func NewAPI(spec *loads.Document) *API {
api := &API{
spec: spec,
analyzer: an,
- consumers: make(map[string]runtime.Consumer, 10),
- producers: make(map[string]runtime.Producer, 10),
+ consumers: make(map[string]runtime.Consumer, smallPreallocatedSlots),
+ producers: make(map[string]runtime.Producer, smallPreallocatedSlots),
authenticators: make(map[string]runtime.Authenticator),
operations: make(map[string]map[string]runtime.OperationHandler),
ServeError: errors.ServeError,
- Models: make(map[string]func() interface{}),
+ Models: make(map[string]func() any),
formats: strfmt.NewFormats(),
}
- return api.WithJSONDefaults()
-}
-// API represents an untyped mux for a swagger spec
-type API struct {
- spec *loads.Document
- analyzer *analysis.Spec
- DefaultProduces string
- DefaultConsumes string
- consumers map[string]runtime.Consumer
- producers map[string]runtime.Producer
- authenticators map[string]runtime.Authenticator
- authorizer runtime.Authorizer
- operations map[string]map[string]runtime.OperationHandler
- ServeError func(http.ResponseWriter, *http.Request, error)
- Models map[string]func() interface{}
- formats strfmt.Registry
+ return api.WithJSONDefaults()
}
-// WithJSONDefaults loads the json defaults for this api
+// WithJSONDefaults loads the json defaults for this api.
func (d *API) WithJSONDefaults() *API {
d.DefaultConsumes = runtime.JSONMime
d.DefaultProduces = runtime.JSONMime
@@ -74,7 +69,7 @@ func (d *API) WithJSONDefaults() *API {
return d
}
-// WithoutJSONDefaults clears the json defaults for this api
+// WithoutJSONDefaults clears the json defaults for this api.
func (d *API) WithoutJSONDefaults() *API {
d.DefaultConsumes = ""
d.DefaultProduces = ""
@@ -83,7 +78,7 @@ func (d *API) WithoutJSONDefaults() *API {
return d
}
-// Formats returns the registered string formats
+// Formats returns the registered string formats.
func (d *API) Formats() strfmt.Registry {
if d.formats == nil {
d.formats = strfmt.NewFormats()
@@ -91,7 +86,7 @@ func (d *API) Formats() strfmt.Registry {
return d.formats
}
-// RegisterFormat registers a custom format validator
+// RegisterFormat registers a custom format validator.
func (d *API) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) {
if d.formats == nil {
d.formats = strfmt.NewFormats()
@@ -99,7 +94,7 @@ func (d *API) RegisterFormat(name string, format strfmt.Format, validator strfmt
d.formats.Add(name, format, validator)
}
-// RegisterAuth registers an auth handler in this api
+// RegisterAuth registers an auth handler in this api.
func (d *API) RegisterAuth(scheme string, handler runtime.Authenticator) {
if d.authenticators == nil {
d.authenticators = make(map[string]runtime.Authenticator)
@@ -107,7 +102,7 @@ func (d *API) RegisterAuth(scheme string, handler runtime.Authenticator) {
d.authenticators[scheme] = handler
}
-// RegisterAuthorizer registers an authorizer handler in this api
+// RegisterAuthorizer registers an authorizer handler in this api.
func (d *API) RegisterAuthorizer(handler runtime.Authorizer) {
d.authorizer = handler
}
@@ -115,23 +110,23 @@ func (d *API) RegisterAuthorizer(handler runtime.Authorizer) {
// RegisterConsumer registers a consumer for a media type.
func (d *API) RegisterConsumer(mediaType string, handler runtime.Consumer) {
if d.consumers == nil {
- d.consumers = make(map[string]runtime.Consumer, 10)
+ d.consumers = make(map[string]runtime.Consumer, smallPreallocatedSlots)
}
d.consumers[strings.ToLower(mediaType)] = handler
}
-// RegisterProducer registers a producer for a media type
+// RegisterProducer registers a producer for a media type.
func (d *API) RegisterProducer(mediaType string, handler runtime.Producer) {
if d.producers == nil {
- d.producers = make(map[string]runtime.Producer, 10)
+ d.producers = make(map[string]runtime.Producer, smallPreallocatedSlots)
}
d.producers[strings.ToLower(mediaType)] = handler
}
-// RegisterOperation registers an operation handler for an operation name
+// RegisterOperation registers an operation handler for an operation name.
func (d *API) RegisterOperation(method, path string, handler runtime.OperationHandler) {
if d.operations == nil {
- d.operations = make(map[string]map[string]runtime.OperationHandler, 30)
+ d.operations = make(map[string]map[string]runtime.OperationHandler, mediumPreallocatedSlots)
}
um := strings.ToUpper(method)
if b, ok := d.operations[um]; !ok || b == nil {
@@ -140,7 +135,7 @@ func (d *API) RegisterOperation(method, path string, handler runtime.OperationHa
d.operations[um][path] = handler
}
-// OperationHandlerFor returns the operation handler for the specified id if it can be found
+// OperationHandlerFor returns the operation handler for the specified id if it can be found.
func (d *API) OperationHandlerFor(method, path string) (runtime.OperationHandler, bool) {
if d.operations == nil {
return nil, false
@@ -152,7 +147,7 @@ func (d *API) OperationHandlerFor(method, path string) (runtime.OperationHandler
return nil, false
}
-// ConsumersFor gets the consumers for the specified media types
+// ConsumersFor gets the consumers for the specified media types.
func (d *API) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
result := make(map[string]runtime.Consumer)
for _, mt := range mediaTypes {
@@ -163,7 +158,7 @@ func (d *API) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
return result
}
-// ProducersFor gets the producers for the specified media types
+// ProducersFor gets the producers for the specified media types.
func (d *API) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
result := make(map[string]runtime.Producer)
for _, mt := range mediaTypes {
@@ -174,7 +169,7 @@ func (d *API) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
return result
}
-// AuthenticatorsFor gets the authenticators for the specified security schemes
+// AuthenticatorsFor gets the authenticators for the specified security schemes.
func (d *API) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
result := make(map[string]runtime.Authenticator)
for k := range schemes {
@@ -185,42 +180,43 @@ func (d *API) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[stri
return result
}
-// Authorizer returns the registered authorizer
+// Authorizer returns the registered authorizer.
func (d *API) Authorizer() runtime.Authorizer {
return d.authorizer
}
-// Validate validates this API for any missing items
+// Validate validates this API for any missing items.
func (d *API) Validate() error {
return d.validate()
}
-// validateWith validates the registrations in this API against the provided spec analyzer
+// validateWith validates the registrations in this API against the provided spec analyzer.
func (d *API) validate() error {
- var consumes []string
+ consumes := make([]string, 0, len(d.consumers))
for k := range d.consumers {
consumes = append(consumes, k)
}
- var produces []string
+ produces := make([]string, 0, len(d.producers))
for k := range d.producers {
produces = append(produces, k)
}
- var authenticators []string
+ authenticators := make([]string, 0, len(d.authenticators))
for k := range d.authenticators {
authenticators = append(authenticators, k)
}
- var operations []string
+ operations := make([]string, 0, len(d.operations))
for m, v := range d.operations {
for p := range v {
operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p))
}
}
- var definedAuths []string
- for k := range d.spec.Spec().SecurityDefinitions {
+ secDefinitions := d.spec.Spec().SecurityDefinitions
+ definedAuths := make([]string, 0, len(secDefinitions))
+ for k := range secDefinitions {
definedAuths = append(definedAuths, k)
}
@@ -267,7 +263,7 @@ func (d *API) verify(name string, registrations []string, expectations []string)
delete(expected, k)
}
- var unregistered []string
+ unregistered := make([]string, 0, len(expected))
for k := range expected {
unregistered = append(unregistered, k)
}
diff --git a/vendor/github.com/go-openapi/runtime/middleware/validation.go b/vendor/github.com/go-openapi/runtime/middleware/validation.go
index 1f0135b5788d..8a56490639e1 100644
--- a/vendor/github.com/go-openapi/runtime/middleware/validation.go
+++ b/vendor/github.com/go-openapi/runtime/middleware/validation.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 middleware
@@ -20,9 +9,8 @@ import (
"strings"
"github.com/go-openapi/errors"
- "github.com/go-openapi/swag"
-
"github.com/go-openapi/runtime"
+ "github.com/go-openapi/swag/stringutils"
)
type validation struct {
@@ -30,12 +18,11 @@ type validation struct {
result []error
request *http.Request
route *MatchedRoute
- bound map[string]interface{}
+ bound map[string]any
}
-// ContentType validates the content type of a request
+// ContentType validates the content type of a request.
func validateContentType(allowed []string, actual string) error {
- debugLog("validating content type for %q against [%s]", actual, strings.Join(allowed, ", "))
if len(allowed) == 0 {
return nil
}
@@ -43,27 +30,27 @@ func validateContentType(allowed []string, actual string) error {
if err != nil {
return errors.InvalidContentType(actual, allowed)
}
- if swag.ContainsStringsCI(allowed, mt) {
+ if stringutils.ContainsStringsCI(allowed, mt) {
return nil
}
- if swag.ContainsStringsCI(allowed, "*/*") {
+ if stringutils.ContainsStringsCI(allowed, "*/*") {
return nil
}
parts := strings.Split(actual, "/")
- if len(parts) == 2 && swag.ContainsStringsCI(allowed, parts[0]+"/*") {
+ if len(parts) == 2 && stringutils.ContainsStringsCI(allowed, parts[0]+"/*") {
return nil
}
return errors.InvalidContentType(actual, allowed)
}
func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *validation {
- debugLog("validating request %s %s", request.Method, request.URL.EscapedPath())
validate := &validation{
context: ctx,
request: request,
route: route,
- bound: make(map[string]interface{}),
+ bound: make(map[string]any),
}
+ validate.debugLogf("validating request %s %s", request.Method, request.URL.EscapedPath())
validate.contentType()
if len(validate.result) == 0 {
@@ -76,11 +63,15 @@ func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *
return validate
}
+func (v *validation) debugLogf(format string, args ...any) {
+ v.context.debugLogf(format, args...)
+}
+
func (v *validation) parameters() {
- debugLog("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath())
+ 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.([]interface{}) {
+ for _, e := range result.(*errors.Validation).Value.([]any) {
v.result = append(v.result, e.(error))
}
return
@@ -91,7 +82,7 @@ func (v *validation) parameters() {
func (v *validation) contentType() {
if len(v.result) == 0 && runtime.HasBody(v.request) {
- debugLog("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath())
+ 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)
@@ -100,6 +91,7 @@ func (v *validation) contentType() {
}
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)
}
@@ -107,7 +99,7 @@ func (v *validation) contentType() {
if ct != "" && v.route.Consumer == nil {
cons, ok := v.route.Consumers[ct]
if !ok {
- v.result = append(v.result, errors.New(500, "no consumer registered for %s", ct))
+ v.result = append(v.result, errors.New(http.StatusInternalServerError, "no consumer registered for %s", ct))
} else {
v.route.Consumer = cons
}
diff --git a/vendor/github.com/go-openapi/runtime/request.go b/vendor/github.com/go-openapi/runtime/request.go
index 9e51b42b59d0..5c45339aa467 100644
--- a/vendor/github.com/go-openapi/runtime/request.go
+++ b/vendor/github.com/go-openapi/runtime/request.go
@@ -1,54 +1,45 @@
-// 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 runtime
import (
"bufio"
+ "context"
+ "errors"
"io"
"net/http"
"strings"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/stringutils"
)
-// CanHaveBody returns true if this method can have a body
+// CanHaveBody returns true if this method can have a body.
func CanHaveBody(method string) bool {
mn := strings.ToUpper(method)
return mn == "POST" || mn == "PUT" || mn == "PATCH" || mn == "DELETE"
}
-// IsSafe returns true if this is a request with a safe method
+// IsSafe returns true if this is a request with a safe method.
func IsSafe(r *http.Request) bool {
mn := strings.ToUpper(r.Method)
return mn == "GET" || mn == "HEAD"
}
-// AllowsBody returns true if the request allows for a body
+// AllowsBody returns true if the request allows for a body.
func AllowsBody(r *http.Request) bool {
mn := strings.ToUpper(r.Method)
return mn != "HEAD"
}
-// HasBody returns true if this method needs a content-type
+// HasBody returns true if this method needs a content-type.
func HasBody(r *http.Request) bool {
// happy case: we have a content length set
if r.ContentLength > 0 {
return true
}
- if r.Header.Get(http.CanonicalHeaderKey("content-length")) != "" {
+ if r.Header.Get("Content-Length") != "" {
// in this case, no Transfer-Encoding should be present
// we have a header set but it was explicitly set to 0, so we assume no body
return false
@@ -96,10 +87,16 @@ func (p *peekingReader) Read(d []byte) (int, error) {
if p == nil {
return 0, io.EOF
}
+ if p.underlying == nil {
+ return 0, io.ErrUnexpectedEOF
+ }
return p.underlying.Read(d)
}
func (p *peekingReader) Close() error {
+ if p.underlying == nil {
+ return errors.New("reader already closed")
+ }
p.underlying = nil
if p.orig != nil {
return p.orig.Close()
@@ -107,9 +104,11 @@ func (p *peekingReader) Close() error {
return nil
}
-// JSONRequest creates a new http request with json headers set
+// JSONRequest creates a new [http] request with json headers set.
+//
+// It uses [context.Background].
func JSONRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
- req, err := http.NewRequest(method, urlStr, body)
+ req, err := http.NewRequestWithContext(context.Background(), method, urlStr, body)
if err != nil {
return nil, err
}
@@ -118,12 +117,12 @@ func JSONRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
return req, nil
}
-// Gettable for things with a method GetOK(string) (data string, hasKey bool, hasValue bool)
+// Gettable for things with a method [GetOK](string) (data string, hasKey bool, hasValue bool).
type Gettable interface {
GetOK(string) ([]string, bool, bool)
}
-// ReadSingleValue reads a single value from the source
+// ReadSingleValue reads a single value from the source.
func ReadSingleValue(values Gettable, name string) string {
vv, _, hv := values.GetOK(name)
if hv {
@@ -132,8 +131,8 @@ func ReadSingleValue(values Gettable, name string) string {
return ""
}
-// ReadCollectionValue reads a collection value from a string data source
+// ReadCollectionValue reads a collection value from a string data source.
func ReadCollectionValue(values Gettable, name, collectionFormat string) []string {
v := ReadSingleValue(values, name)
- return swag.SplitByFormat(v, collectionFormat)
+ return stringutils.SplitByFormat(v, collectionFormat)
}
diff --git a/vendor/github.com/go-openapi/runtime/security/authenticator.go b/vendor/github.com/go-openapi/runtime/security/authenticator.go
index 476d26c3e77b..4c0910182658 100644
--- a/vendor/github.com/go-openapi/runtime/security/authenticator.go
+++ b/vendor/github.com/go-openapi/runtime/security/authenticator.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 security
@@ -25,13 +14,14 @@ import (
)
const (
- query = "query"
- header = "header"
+ query = "query"
+ header = "header"
+ accessTokenParam = "access_token"
)
-// HttpAuthenticator is a function that authenticates a HTTP request
-func HttpAuthenticator(handler func(*http.Request) (bool, interface{}, error)) runtime.Authenticator {
- return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
+// HttpAuthenticator is a function that authenticates a HTTP request.
+func HttpAuthenticator(handler func(*http.Request) (bool, any, error)) runtime.Authenticator { //nolint:revive
+ return runtime.AuthenticatorFunc(func(params any) (bool, any, error) {
if request, ok := params.(*http.Request); ok {
return handler(request)
}
@@ -42,9 +32,9 @@ func HttpAuthenticator(handler func(*http.Request) (bool, interface{}, error)) r
})
}
-// ScopedAuthenticator is a function that authenticates a HTTP request against a list of valid scopes
-func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, interface{}, error)) runtime.Authenticator {
- return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
+// ScopedAuthenticator is a function that authenticates a 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 {
return handler(request)
}
@@ -52,23 +42,23 @@ func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, interface{}, er
})
}
-// UserPassAuthentication authentication function
-type UserPassAuthentication func(string, string) (interface{}, error)
+// UserPassAuthentication authentication function.
+type UserPassAuthentication func(string, string) (any, error)
-// UserPassAuthenticationCtx authentication function with context.Context
-type UserPassAuthenticationCtx func(context.Context, string, string) (context.Context, interface{}, error)
+// UserPassAuthenticationCtx authentication function with [context.Context].
+type UserPassAuthenticationCtx func(context.Context, string, string) (context.Context, any, error)
-// TokenAuthentication authentication function
-type TokenAuthentication func(string) (interface{}, error)
+// TokenAuthentication authentication function.
+type TokenAuthentication func(string) (any, error)
-// TokenAuthenticationCtx authentication function with context.Context
-type TokenAuthenticationCtx func(context.Context, string) (context.Context, interface{}, error)
+// TokenAuthenticationCtx authentication function with [context.Context].
+type TokenAuthenticationCtx func(context.Context, string) (context.Context, any, error)
-// ScopedTokenAuthentication authentication function
-type ScopedTokenAuthentication func(string, []string) (interface{}, error)
+// ScopedTokenAuthentication authentication function.
+type ScopedTokenAuthentication func(string, []string) (any, error)
-// ScopedTokenAuthenticationCtx authentication function with context.Context
-type ScopedTokenAuthenticationCtx func(context.Context, string, []string) (context.Context, interface{}, error)
+// ScopedTokenAuthenticationCtx authentication function with [context.Context].
+type ScopedTokenAuthenticationCtx func(context.Context, string, []string) (context.Context, any, error)
var DefaultRealmName = "API"
@@ -103,18 +93,18 @@ func OAuth2SchemeNameCtx(ctx context.Context) string {
return v
}
-// BasicAuth creates a basic auth authenticator with the provided authentication function
+// BasicAuth creates a basic auth authenticator with the provided authentication function.
func BasicAuth(authenticate UserPassAuthentication) runtime.Authenticator {
return BasicAuthRealm(DefaultRealmName, authenticate)
}
-// BasicAuthRealm creates a basic auth authenticator with the provided authentication function and realm name
+// BasicAuthRealm creates a basic auth authenticator with the provided authentication function and realm name.
func BasicAuthRealm(realm string, authenticate UserPassAuthentication) runtime.Authenticator {
if realm == "" {
realm = DefaultRealmName
}
- return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
if usr, pass, ok := r.BasicAuth(); ok {
p, err := authenticate(usr, pass)
if err != nil {
@@ -127,18 +117,18 @@ func BasicAuthRealm(realm string, authenticate UserPassAuthentication) runtime.A
})
}
-// BasicAuthCtx creates a basic auth authenticator with the provided authentication function with support for context.Context
+// BasicAuthCtx creates a basic auth authenticator with the provided authentication function with support for [context.Context].
func BasicAuthCtx(authenticate UserPassAuthenticationCtx) runtime.Authenticator {
return BasicAuthRealmCtx(DefaultRealmName, authenticate)
}
-// BasicAuthRealmCtx creates a basic auth authenticator with the provided authentication function and realm name with support for context.Context
+// BasicAuthRealmCtx creates a basic auth authenticator with the provided authentication function and realm name with support for [context.Context].
func BasicAuthRealmCtx(realm string, authenticate UserPassAuthenticationCtx) runtime.Authenticator {
if realm == "" {
realm = DefaultRealmName
}
- return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
if usr, pass, ok := r.BasicAuth(); ok {
ctx, p, err := authenticate(r.Context(), usr, pass)
if err != nil {
@@ -153,12 +143,12 @@ func BasicAuthRealmCtx(realm string, authenticate UserPassAuthenticationCtx) run
}
// APIKeyAuth creates an authenticator that uses a token for authorization.
-// This token can be obtained from either a header or a query string
+// This token can be obtained from either a header or a query string.
func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authenticator {
inl := strings.ToLower(in)
if inl != query && inl != header {
// panic because this is most likely a typo
- panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"."))
+ panic(errors.New(http.StatusInternalServerError, "api key auth: in value needs to be either \"query\" or \"header\""))
}
var getToken func(*http.Request) string
@@ -169,7 +159,7 @@ func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authe
getToken = func(r *http.Request) string { return r.URL.Query().Get(name) }
}
- return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
token := getToken(r)
if token == "" {
return false, nil, nil
@@ -180,13 +170,13 @@ func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authe
})
}
-// APIKeyAuthCtx creates an authenticator that uses a token for authorization with support for context.Context.
-// This token can be obtained from either a header or a query string
+// APIKeyAuthCtx creates an authenticator that uses a token for authorization with support for [context.Context].
+// This token can be obtained from either a header or a query string.
func APIKeyAuthCtx(name, in string, authenticate TokenAuthenticationCtx) runtime.Authenticator {
inl := strings.ToLower(in)
if inl != query && inl != header {
// panic because this is most likely a typo
- panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"."))
+ panic(errors.New(http.StatusInternalServerError, "api key auth: in value needs to be either \"query\" or \"header\""))
}
var getToken func(*http.Request) string
@@ -197,7 +187,7 @@ func APIKeyAuthCtx(name, in string, authenticate TokenAuthenticationCtx) runtime
getToken = func(r *http.Request) string { return r.URL.Query().Get(name) }
}
- return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
+ return HttpAuthenticator(func(r *http.Request) (bool, any, error) {
token := getToken(r)
if token == "" {
return false, nil, nil
@@ -209,29 +199,29 @@ 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 a [http] request and the required scopes for a particular operation.
type ScopedAuthRequest struct {
Request *http.Request
RequiredScopes []string
}
-// BearerAuth for use with oauth2 flows
+// BearerAuth for use with oauth2 flows.
func BearerAuth(name string, authenticate ScopedTokenAuthentication) runtime.Authenticator {
const prefix = "Bearer "
- return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, interface{}, error) {
+ return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, any, error) {
var token string
- hdr := r.Request.Header.Get("Authorization")
- if strings.HasPrefix(hdr, prefix) {
- token = strings.TrimPrefix(hdr, prefix)
+ hdr := r.Request.Header.Get(runtime.HeaderAuthorization)
+ if after, ok := strings.CutPrefix(hdr, prefix); ok {
+ token = after
}
if token == "" {
qs := r.Request.URL.Query()
- token = qs.Get("access_token")
+ token = qs.Get(accessTokenParam)
}
//#nosec
ct, _, _ := runtime.ContentType(r.Request.Header)
if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
- token = r.Request.FormValue("access_token")
+ token = r.Request.FormValue(accessTokenParam)
}
if token == "" {
@@ -245,23 +235,23 @@ func BearerAuth(name string, authenticate ScopedTokenAuthentication) runtime.Aut
})
}
-// BearerAuthCtx for use with oauth2 flows with support for context.Context.
+// BearerAuthCtx for use with oauth2 flows with support for [context.Context].
func BearerAuthCtx(name string, authenticate ScopedTokenAuthenticationCtx) runtime.Authenticator {
const prefix = "Bearer "
- return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, interface{}, error) {
+ return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, any, error) {
var token string
- hdr := r.Request.Header.Get("Authorization")
- if strings.HasPrefix(hdr, prefix) {
- token = strings.TrimPrefix(hdr, prefix)
+ hdr := r.Request.Header.Get(runtime.HeaderAuthorization)
+ if after, ok := strings.CutPrefix(hdr, prefix); ok {
+ token = after
}
if token == "" {
qs := r.Request.URL.Query()
- token = qs.Get("access_token")
+ token = qs.Get(accessTokenParam)
}
//#nosec
ct, _, _ := runtime.ContentType(r.Request.Header)
if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
- token = r.Request.FormValue("access_token")
+ token = r.Request.FormValue(accessTokenParam)
}
if token == "" {
diff --git a/vendor/github.com/go-openapi/runtime/security/authorizer.go b/vendor/github.com/go-openapi/runtime/security/authorizer.go
index 00c1a4d6a4c3..8beef19f09b1 100644
--- a/vendor/github.com/go-openapi/runtime/security/authorizer.go
+++ b/vendor/github.com/go-openapi/runtime/security/authorizer.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 security
@@ -20,8 +9,8 @@ import (
"github.com/go-openapi/runtime"
)
-// Authorized provides a default implementation of the Authorizer interface where all
-// requests are authorized (successful)
+// Authorized provides a default implementation of the [Authorizer] interface where all
+// requests are authorized (successful).
func Authorized() runtime.Authorizer {
- return runtime.AuthorizerFunc(func(_ *http.Request, _ interface{}) error { return nil })
+ return runtime.AuthorizerFunc(func(_ *http.Request, _ any) error { return nil })
}
diff --git a/vendor/github.com/go-openapi/runtime/statuses.go b/vendor/github.com/go-openapi/runtime/statuses.go
index 3b011a0bff19..c0f3e6b44779 100644
--- a/vendor/github.com/go-openapi/runtime/statuses.go
+++ b/vendor/github.com/go-openapi/runtime/statuses.go
@@ -1,20 +1,9 @@
-// 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 runtime
-// Statuses lists the most common HTTP status codes to default message
+// Statuses lists the most common HTTP status codes to default message.
// taken from https://httpstatuses.com/
var Statuses = map[int]string{
100: "Continue",
diff --git a/vendor/github.com/go-openapi/runtime/text.go b/vendor/github.com/go-openapi/runtime/text.go
index c7fd04c3c5c1..1252ac88c710 100644
--- a/vendor/github.com/go-openapi/runtime/text.go
+++ b/vendor/github.com/go-openapi/runtime/text.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 runtime
@@ -22,12 +11,12 @@ import (
"io"
"reflect"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/jsonutils"
)
-// TextConsumer creates a new text consumer
+// TextConsumer creates a new text consumer.
func TextConsumer() Consumer {
- return ConsumerFunc(func(reader io.Reader, data interface{}) error {
+ return ConsumerFunc(func(reader io.Reader, data any) error {
if reader == nil {
return errors.New("TextConsumer requires a reader") // early exit
}
@@ -41,7 +30,6 @@ func TextConsumer() Consumer {
// If the buffer is empty, no need to unmarshal it, which causes a panic.
if len(b) == 0 {
- data = ""
return nil
}
@@ -68,9 +56,9 @@ func TextConsumer() Consumer {
})
}
-// TextProducer creates a new text producer
+// TextProducer creates a new text producer.
func TextProducer() Producer {
- return ProducerFunc(func(writer io.Writer, data interface{}) error {
+ return ProducerFunc(func(writer io.Writer, data any) error {
if writer == nil {
return errors.New("TextProducer requires a writer") // early exit
}
@@ -100,7 +88,7 @@ func TextProducer() Producer {
v := reflect.Indirect(reflect.ValueOf(data))
if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice {
- b, err := swag.WriteJSON(data)
+ b, err := jsonutils.WriteJSON(data)
if err != nil {
return err
}
diff --git a/vendor/github.com/go-openapi/runtime/values.go b/vendor/github.com/go-openapi/runtime/values.go
index 11f5732af4e3..af4d9be7946e 100644
--- a/vendor/github.com/go-openapi/runtime/values.go
+++ b/vendor/github.com/go-openapi/runtime/values.go
@@ -1,6 +1,9 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package runtime
-// Values typically represent parameters on a http request.
+// Values typically represent parameters on a [http] request.
type Values map[string][]string
// GetOK returns the values collection for the given key.
diff --git a/vendor/github.com/go-openapi/runtime/xml.go b/vendor/github.com/go-openapi/runtime/xml.go
index 821c7393dfbb..9cd2540c30f5 100644
--- a/vendor/github.com/go-openapi/runtime/xml.go
+++ b/vendor/github.com/go-openapi/runtime/xml.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 runtime
@@ -19,17 +8,17 @@ import (
"io"
)
-// XMLConsumer creates a new XML consumer
+// XMLConsumer creates a new XML consumer.
func XMLConsumer() Consumer {
- return ConsumerFunc(func(reader io.Reader, data interface{}) error {
+ return ConsumerFunc(func(reader io.Reader, data any) error {
dec := xml.NewDecoder(reader)
return dec.Decode(data)
})
}
-// XMLProducer creates a new XML producer
+// XMLProducer creates a new XML producer.
func XMLProducer() Producer {
- return ProducerFunc(func(writer io.Writer, data interface{}) error {
+ return ProducerFunc(func(writer io.Writer, data any) error {
enc := xml.NewEncoder(writer)
return enc.Encode(data)
})
diff --git a/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go
index b30d37712633..ca71edbb1bab 100644
--- a/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go
+++ b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.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 yamlpc
@@ -18,21 +7,20 @@ import (
"io"
"github.com/go-openapi/runtime"
-
- "gopkg.in/yaml.v2"
+ yaml "go.yaml.in/yaml/v3"
)
-// YAMLConsumer creates a consumer for yaml data
+// YAMLConsumer creates a consumer for [yaml] data.
func YAMLConsumer() runtime.Consumer {
- return runtime.ConsumerFunc(func(r io.Reader, v interface{}) error {
+ return runtime.ConsumerFunc(func(r io.Reader, v any) error {
dec := yaml.NewDecoder(r)
return dec.Decode(v)
})
}
-// YAMLProducer creates a producer for yaml data
+// YAMLProducer creates a producer for [yaml] data.
func YAMLProducer() runtime.Producer {
- return runtime.ProducerFunc(func(w io.Writer, v interface{}) error {
+ return runtime.ProducerFunc(func(w io.Writer, v any) error {
enc := yaml.NewEncoder(w)
defer enc.Close()
return enc.Encode(v)
diff --git a/vendor/github.com/go-openapi/spec/.gitignore b/vendor/github.com/go-openapi/spec/.gitignore
index f47cb2045f13..885dc27ab0bc 100644
--- a/vendor/github.com/go-openapi/spec/.gitignore
+++ b/vendor/github.com/go-openapi/spec/.gitignore
@@ -1 +1,6 @@
*.out
+*.cov
+.idea
+.env
+.mcp.json
+.claude/
diff --git a/vendor/github.com/go-openapi/spec/.golangci.yml b/vendor/github.com/go-openapi/spec/.golangci.yml
index 22f8d21cca19..dc7c96053de0 100644
--- a/vendor/github.com/go-openapi/spec/.golangci.yml
+++ b/vendor/github.com/go-openapi/spec/.golangci.yml
@@ -1,61 +1,67 @@
-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: 3
-
+version: "2"
linters:
- enable-all: true
+ default: all
disable:
- - maligned
- - unparam
- - lll
- - gochecknoinits
- - gochecknoglobals
+ - depguard
- funlen
- godox
- - gocognit
- - whitespace
- - wsl
- - wrapcheck
- - testpackage
+ - exhaustruct
- nlreturn
- - gomnd
- - exhaustivestruct
- - goerr113
- - errorlint
- - nestif
- - godot
- - gofumpt
+ - nonamedreturns
+ - noinlineerr
- paralleltest
- - tparallel
+ - recvcheck
+ - testpackage
- thelper
- - ifshort
- - exhaustruct
+ - tparallel
- varnamelen
- - gci
- - depguard
- - errchkjson
- - inamedparam
- - nonamedreturns
- - musttag
- - ireturn
- - forcetypeassert
- - cyclop
- # deprecated linters
- - deadcode
- - interfacer
- - scopelint
- - varcheck
- - structcheck
- - golint
- - nosnakecase
+ - 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/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/spec/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 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 000000000000..2967e3cedd96
--- /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 | 392 |
+
+| Username | All Time Contribution Count | All Commits |
+| --- | --- | --- |
+| @casualjim | 191 | |
+| @fredbi | 90 | |
+| @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/contributors)_
diff --git a/vendor/github.com/go-openapi/spec/README.md b/vendor/github.com/go-openapi/spec/README.md
index 7fd2810c6983..134809fd77a0 100644
--- a/vendor/github.com/go-openapi/spec/README.md
+++ b/vendor/github.com/go-openapi/spec/README.md
@@ -1,11 +1,38 @@
-# OpenAPI v2 object model [](https://github.com/go-openapi/spec/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/spec)
+# spec
-[](https://slackin.goswagger.io)
-[](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE)
-[](https://pkg.go.dev/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
+ * 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.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/spec
+```
### FAQ
@@ -28,7 +55,7 @@ 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?
@@ -37,13 +64,13 @@ The object model for OpenAPI specification documents.
> 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: https://pkg.go.dev/github.com/go-openapi/loads#example-Spec
+> Take a look at the example there:
>
-> See also https://github.com/go-openapi/spec/issues/164
+> See also
* How can I validate a spec?
-> Validation is provided by [the validate package](http://github.com/go-openapi/validate)
+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?
@@ -51,4 +78,71 @@ The object model for OpenAPI specification documents.
> how `$ref` are resolved.
> This `id` does not conflict with any property named `id`.
>
-> See also https://github.com/go-openapi/spec/issues/23
+> 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](.github/CONTRIBUTING.md)
+* [Maintainers documentation](docs/MAINTAINERS.md)
+* [Code style](docs/STYLE.md)
+
+## 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
+[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
+
+
+[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
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 000000000000..1fea2c5736a5
--- /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/cache.go b/vendor/github.com/go-openapi/spec/cache.go
index 122993b44b41..06495d2c3d32 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 2f7bb219b562..46fada5dff15 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 fc889f6d0b03..fa52b0c7f772 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 000000000000..04eea357588e
--- /dev/null
+++ b/vendor/github.com/go-openapi/spec/doc.go
@@ -0,0 +1,7 @@
+// 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.
+package spec
diff --git a/vendor/github.com/go-openapi/spec/embed.go b/vendor/github.com/go-openapi/spec/embed.go
index 1f4284750ab5..0d0b69996cce 100644
--- a/vendor/github.com/go-openapi/spec/embed.go
+++ b/vendor/github.com/go-openapi/spec/embed.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package spec
import (
diff --git a/vendor/github.com/go-openapi/spec/errors.go b/vendor/github.com/go-openapi/spec/errors.go
index 6992c7ba730b..eaca01cc83c7 100644
--- a/vendor/github.com/go-openapi/spec/errors.go
+++ b/vendor/github.com/go-openapi/spec/errors.go
@@ -1,19 +1,25 @@
+// 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")
+
+ // 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 b81a5699a03e..f9c2fa327aa1 100644
--- a/vendor/github.com/go-openapi/spec/expander.go
+++ b/vendor/github.com/go-openapi/spec/expander.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,6 +8,8 @@ import (
"fmt"
)
+const smallPrealloc = 10
+
// 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.
@@ -47,7 +38,7 @@ func optionsOrDefault(opts *ExpandOptions) *ExpandOptions {
return &ExpandOptions{}
}
-// ExpandSpec expands the references in a swagger spec
+// ExpandSpec expands the references in a swagger spec.
func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
options = optionsOrDefault(options)
resolver := defaultSchemaLoader(spec, options, nil, nil)
@@ -56,7 +47,7 @@ func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
if !options.SkipSchemas {
for key, definition := range spec.Definitions {
- parentRefs := make([]string, 0, 10)
+ parentRefs := make([]string, 0, smallPrealloc)
parentRefs = append(parentRefs, "#/definitions/"+key)
def, err := expandSchema(definition, parentRefs, resolver, specBasePath)
@@ -101,8 +92,8 @@ 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
-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)
@@ -114,7 +105,7 @@ func baseForRoot(root interface{}, cache ResolutionCache) string {
return normalizedBase
}
- root = map[string]interface{}{}
+ root = map[string]any{}
}
cache.Set(normalizedBase, root)
@@ -130,7 +121,7 @@ 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 {
+func ExpandSchema(schema *Schema, root any, cache ResolutionCache) error {
cache = cacheOrDefault(cache)
if root == nil {
root = schema
@@ -160,7 +151,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
@@ -199,6 +190,7 @@ 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 target.Ref.String() == "" && target.Ref.IsRoot() {
newRef := normalizeRef(&target.Ref, basePath)
@@ -386,7 +378,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
}
@@ -461,7 +453,7 @@ 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 {
+func ExpandResponseWithRoot(response *Response, root any, cache ResolutionCache) error {
cache = cacheOrDefault(cache)
opts := &ExpandOptions{
RelativeBase: baseForRoot(root, cache),
@@ -473,7 +465,7 @@ func ExpandResponseWithRoot(response *Response, root interface{}, cache Resoluti
// 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,
@@ -487,7 +479,7 @@ func ExpandResponse(response *Response, basePath string) error {
//
// 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 {
+func ExpandParameterWithRoot(parameter *Parameter, root any, cache ResolutionCache) error {
cache = cacheOrDefault(cache)
opts := &ExpandOptions{
@@ -500,7 +492,7 @@ func ExpandParameterWithRoot(parameter *Parameter, root interface{}, cache Resol
// 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,
@@ -510,7 +502,7 @@ func ExpandParameter(parameter *Parameter, basePath string) error {
return expandParameterOrResponse(parameter, resolver, opts.RelativeBase)
}
-func getRefAndSchema(input interface{}) (*Ref, *Schema, error) {
+func getRefAndSchema(input any) (*Ref, *Schema, error) {
var (
ref *Ref
sch *Schema
@@ -536,7 +528,7 @@ func getRefAndSchema(input interface{}) (*Ref, *Schema, error) {
return ref, sch, nil
}
-func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePath string) error {
+func expandParameterOrResponse(input any, resolver *schemaLoader, basePath string) error {
ref, sch, err := getRefAndSchema(input)
if err != nil {
return err
@@ -546,7 +538,7 @@ func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePa
return nil
}
- parentRefs := make([]string, 0, 10)
+ parentRefs := make([]string, 0, smallPrealloc)
if ref != nil {
// dereference this $ref
if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) {
@@ -554,6 +546,9 @@ func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePa
}
ref, sch, _ = getRefAndSchema(input)
+ if ref == nil {
+ ref = &Ref{} // empty ref
+ }
}
if ref.String() != "" {
@@ -571,7 +566,7 @@ func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePa
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
diff --git a/vendor/github.com/go-openapi/spec/external_docs.go b/vendor/github.com/go-openapi/spec/external_docs.go
index 88add91b2b8b..17b8efbf1008 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 9dfd17b185f8..599ba2c5d7e7 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,10 @@ func (h Header) MarshalJSON() ([]byte, error) {
if err != nil {
return nil, err
}
- return swag.ConcatJSON(b1, b2, b3), nil
+ return jsonutils.ConcatJSON(b1, b2, b3), 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 +167,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 582f0fd4c45c..0ccfdcccd9e2 100644
--- a/vendor/github.com/go-openapi/spec/info.go
+++ b/vendor/github.com/go-openapi/spec/info.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
@@ -20,19 +9,19 @@ import (
"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)
@@ -41,7 +30,7 @@ func (e Extensions) GetString(key string) (string, bool) {
return "", false
}
-// GetInt gets a int value from the extensions
+// GetInt gets a int value from the extensions.
func (e Extensions) GetInt(key string) (int, bool) {
realKey := strings.ToLower(key)
@@ -59,7 +48,7 @@ func (e Extensions) GetInt(key string) (int, bool) {
return -1, false
}
-// GetBool gets a string value from the extensions
+// 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)
@@ -68,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
}
@@ -93,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-") {
@@ -116,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
}
@@ -126,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
}
@@ -134,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"`
@@ -153,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
}
@@ -162,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 {
@@ -172,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 e2afb2133b9b..daf5a4fd4217 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 b42f80368eca..8209f218b563 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 e8b600994576..68252dc30b8b 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
@@ -95,7 +84,7 @@ func denormalizeRef(ref *Ref, originalRelativeBase, id string) Ref {
if 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
}
@@ -129,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)
}
@@ -149,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
diff --git a/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go b/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go
index f19f1a8fb651..0d55632349f8 100644
--- a/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go
+++ b/vendor/github.com/go-openapi/spec/normalizer_nonwindows.go
@@ -1,19 +1,7 @@
//go:build !windows
-// +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
diff --git a/vendor/github.com/go-openapi/spec/normalizer_windows.go b/vendor/github.com/go-openapi/spec/normalizer_windows.go
index a66c532dbc63..61515c9a163f 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
diff --git a/vendor/github.com/go-openapi/spec/operation.go b/vendor/github.com/go-openapi/spec/operation.go
index a69cca881474..cd70d2547cea 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
@@ -231,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 {
@@ -249,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)
@@ -287,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
@@ -301,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
@@ -318,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),
@@ -363,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 bd4f1cdb0760..516f5d95c560 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"`
@@ -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 68fc8e90144e..4408ece4654e 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 9dc82a2901d6..5daf5a6709f8 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 91d2435f0175..b8e97271e196 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,21 +25,26 @@ 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
}
@@ -44,7 +53,7 @@ func (items OrderSchemaItems) Swap(i, j int) { items[i], items[j] = items[j], it
func (items OrderSchemaItems) Less(i, j int) (ret bool) {
ii, oki := items[i].Extensions.GetInt("x-order")
ij, okj := items[j].Extensions.GetInt("x-order")
- if oki {
+ if oki { //nolint:nestif // nested recover logic for safe type comparison
if okj {
defer func() {
if err := recover(); err != nil {
@@ -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 b0ef9bd9c9bc..40b7d486c951 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
@@ -25,27 +14,44 @@ import (
"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 +62,7 @@ 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 url the ref points to can be found.
func (r *Ref) IsValidURI(basepaths ...string) bool {
if r.String() == "" {
return true
@@ -75,10 +81,11 @@ func (r *Ref) IsValidURI(basepaths ...string) bool {
}
defer rr.Body.Close()
- return rr.StatusCode/100 == 2
+ // true if the response is >= 200 and < 300
+ return rr.StatusCode/100 == 2 //nolint:mnd
}
- 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 47d1ee13fc7b..1bf90c86828f 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 0340b60d845e..4bb6a2bcd242 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 16c3076fe80e..fb369e4a6b0d 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
@@ -21,7 +10,7 @@ import (
"strconv"
"strings"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/jsonutils"
)
// Responses is a container for the expected responses of an operation.
@@ -42,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
}
@@ -55,10 +44,10 @@ 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
@@ -73,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 {
@@ -83,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
}
@@ -95,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 {
@@ -107,7 +96,7 @@ 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]json.RawMessage
if err := json.Unmarshal(data, &res); err != nil {
diff --git a/vendor/github.com/go-openapi/spec/schema.go b/vendor/github.com/go-openapi/spec/schema.go
index 4e9be8576bb6..d7a481bf1ac5 100644
--- a/vendor/github.com/go-openapi/spec/schema.go
+++ b/vendor/github.com/go-openapi/spec/schema.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
@@ -20,89 +9,92 @@ import (
"strings"
"github.com/go-openapi/jsonpointer"
- "github.com/go-openapi/swag"
+ "github.com/go-openapi/swag/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"}}}
@@ -110,35 +102,35 @@ 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
}
@@ -155,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:"-"`
@@ -165,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"`
@@ -177,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"`
@@ -194,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.
@@ -214,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
}
@@ -235,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)
@@ -268,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 != "" {
@@ -308,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
}
@@ -449,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)
@@ -458,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)
@@ -467,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)
@@ -476,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)
@@ -485,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)
@@ -494,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)
@@ -503,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)
@@ -533,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{
@@ -562,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
@@ -610,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
}
@@ -620,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)
}
@@ -628,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 0059b99aed52..0894c932c6b2 100644
--- a/vendor/github.com/go-openapi/spec/schema_loader.go
+++ b/vendor/github.com/go-openapi/spec/schema_loader.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
@@ -22,7 +11,9 @@ import (
"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 +24,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
}
@@ -73,12 +64,23 @@ func newResolverContext(options *ExpandOptions) *resolverContext {
}
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,7 +115,7 @@ 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 {
return ErrResolveRefNeedsAPointer
@@ -124,8 +126,8 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string)
}
var (
- res interface{}
- data interface{}
+ res any
+ data any
err error
)
@@ -134,7 +136,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 +144,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,36 +157,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)
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.
@@ -197,25 +198,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:
@@ -267,7 +257,7 @@ func (r *schemaLoader) shouldStopOnError(err error) bool {
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
@@ -299,11 +289,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/security_scheme.go b/vendor/github.com/go-openapi/spec/security_scheme.go
index 9d0bdae90812..6d9019e749c8 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 876aa12759db..4eba04b2d1a4 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
+ // 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,7 +28,7 @@ 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 := jsonschemaDraft04JSONBytes()
if err != nil {
@@ -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,9 +51,8 @@ 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 := 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 1590fd1751b2..dbe32db8a33f 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,7 +242,7 @@ 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) > 0 {
@@ -267,19 +259,19 @@ func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
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 faa3d3de1eb4..af3fb0a4e89f 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
index 5bdfe40bcc19..8d0c81acd688 100644
--- a/vendor/github.com/go-openapi/spec/url_go19.go
+++ b/vendor/github.com/go-openapi/spec/url_go19.go
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
+// SPDX-License-Identifier: Apache-2.0
+
package spec
import "net/url"
diff --git a/vendor/github.com/go-openapi/spec/validations.go b/vendor/github.com/go-openapi/spec/validations.go
index 6360a8ea7746..a82c2ffe1380 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 945a46703d55..07f7ef8ccd75 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/.codecov.yml b/vendor/github.com/go-openapi/strfmt/.codecov.yml
new file mode 100644
index 000000000000..a5ba8e96d8e2
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/.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/strfmt/.gitignore b/vendor/github.com/go-openapi/strfmt/.gitignore
index dd91ed6a04e6..885dc27ab0bc 100644
--- a/vendor/github.com/go-openapi/strfmt/.gitignore
+++ b/vendor/github.com/go-openapi/strfmt/.gitignore
@@ -1,2 +1,6 @@
-secrets.yml
-coverage.out
+*.out
+*.cov
+.idea
+.env
+.mcp.json
+.claude/
diff --git a/vendor/github.com/go-openapi/strfmt/.golangci.yml b/vendor/github.com/go-openapi/strfmt/.golangci.yml
index 22f8d21cca19..3c4cd489a1d0 100644
--- a/vendor/github.com/go-openapi/strfmt/.golangci.yml
+++ b/vendor/github.com/go-openapi/strfmt/.golangci.yml
@@ -1,61 +1,68 @@
-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: 3
-
+version: "2"
linters:
- enable-all: true
+ default: all
disable:
- - maligned
- - unparam
- - lll
- - gochecknoinits
- - gochecknoglobals
+ - depguard
- funlen
+ - gomoddirectives
- godox
- - gocognit
- - whitespace
- - wsl
- - wrapcheck
- - testpackage
+ - exhaustruct
- nlreturn
- - gomnd
- - exhaustivestruct
- - goerr113
- - errorlint
- - nestif
- - godot
- - gofumpt
+ - nonamedreturns
+ - noinlineerr
- paralleltest
- - tparallel
+ - recvcheck
+ - testpackage
- thelper
- - ifshort
- - exhaustruct
+ - tparallel
- varnamelen
- - gci
- - depguard
- - errchkjson
- - inamedparam
- - nonamedreturns
- - musttag
- - ireturn
- - forcetypeassert
- - cyclop
- # deprecated linters
- - deadcode
- - interfacer
- - scopelint
- - varcheck
- - structcheck
- - golint
- - nosnakecase
+ - 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/strfmt/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md
index 9322b065e37a..bac878f216a2 100644
--- a/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md
+++ b/vendor/github.com/go-openapi/strfmt/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/strfmt/CONTRIBUTORS.md b/vendor/github.com/go-openapi/strfmt/CONTRIBUTORS.md
new file mode 100644
index 000000000000..e49700d4d252
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/CONTRIBUTORS.md
@@ -0,0 +1,52 @@
+# Contributors
+
+- Repository: ['go-openapi/strfmt']
+
+| Total Contributors | Total Contributions |
+| --- | --- |
+| 40 | 225 |
+
+| Username | All Time Contribution Count | All Commits |
+| --- | --- | --- |
+| @casualjim | 88 | |
+| @fredbi | 57 | |
+| @youyuanwu | 13 | |
+| @jlambatl | 9 | |
+| @GlenDC | 5 | |
+| @padamstx | 4 | |
+| @dimovnike | 3 | |
+| @carlv-stripe | 3 | |
+| @Copilot | 3 | |
+| @keramix | 3 | |
+| @gregmarr | 2 | |
+| @vadorovsky | 2 | |
+| @Ompluscator | 2 | |
+| @johnnyg | 2 | |
+| @chakrit | 2 | |
+| @bg451 | 2 | |
+| @aleksandr-vin | 2 | |
+| @ujjwalsh | 1 | |
+| @kenjones-cisco | 1 | |
+| @jwalter1-quest | 1 | |
+| @ccoVeille | 1 | |
+| @tylerb | 1 | |
+| @tzneal | 1 | |
+| @tklauser | 1 | |
+| @SuperQ | 1 | |
+| @srizzling | 1 | |
+| @shawnps | 1 | |
+| @prashantv | 1 | |
+| @krnkl | 1 | |
+| @mstoykov | 1 | |
+| @maxatome | 1 | |
+| @jerome-laforge | 1 | |
+| @justincormack | 1 | |
+| @elipavlov | 1 | |
+| @gbjk | 1 | |
+| @enesanbar | 1 | |
+| @CodeLingoBot | 1 | |
+| @Kunde21 | 1 | |
+| @bvwells | 1 | |
+| @ligustah | 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/strfmt/README.md b/vendor/github.com/go-openapi/strfmt/README.md
index f6b39c6c56c5..a0cf64275417 100644
--- a/vendor/github.com/go-openapi/strfmt/README.md
+++ b/vendor/github.com/go-openapi/strfmt/README.md
@@ -1,15 +1,61 @@
-# Strfmt [](https://github.com/go-openapi/strfmt/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/strfmt)
-[](https://slackin.goswagger.io)
-[](https://raw.githubusercontent.com/go-openapi/strfmt/master/LICENSE)
-[](http://godoc.org/github.com/go-openapi/strfmt)
-[](https://goreportcard.com/report/github.com/go-openapi/strfmt)
+# strfmt
+
+
+[![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]
+
+---
+
+Golang support for string formats defined by JSON Schema and OpenAPI.
+
+## 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-03-07** : v0.26.0 **dropped dependency to the mongodb driver**
+ * mongodb users can still use this package without any change
+ * however, we have frozen the back-compatible support for mongodb driver at v2.5.0
+ * users who want to keep-up with future evolutions (possibly incompatible) of this driver
+ can do so by adding a blank import in their program: `import _ "github.com/go-openapi/strfmt/enable/mongodb"`.
+ This will switch the behavior to the actual driver, which remains regularly updated as an independent module.
+
+## Status
+
+API is stable.
+
+## Import this library in your project
+
+```cmd
+go get github.com/go-openapi/strfmt
+```
+
+## Contents
This package exposes a registry of data types to support string formats in the go-openapi toolkit.
-strfmt represents a well known string format such as credit card or email. The go toolkit for OpenAPI specifications knows how to deal with those.
+`strfmt` represents a well known string format such as hostname or email.
+
+This package provides a few extra formats such as credit card (US), color, etc.
-## Supported data formats
-go-openapi/strfmt follows the swagger 2.0 specification with the following formats
+Format types can serialize and deserialize JSON or from a SQL database.
+
+BSON is also supported (MongoDB).
+
+### Supported formats
+
+`go-openapi/strfmt` follows the swagger 2.0 specification with the following formats
defined [here](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types).
It also provides convenient extensions to go-openapi users.
@@ -35,7 +81,7 @@ It also provides convenient extensions to go-openapi users.
- mac (e.g "01:02:03:04:05:06")
- rgbcolor (e.g. "rgb(100,100,100)")
- ssn
- - uuid, uuid3, uuid4, uuid5
+ - 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))
@@ -43,7 +89,7 @@ It also provides convenient extensions to go-openapi users.
> It does not provide validation for numerical values with swagger format extension for JSON types "number" or
> "integer" (e.g. float, double, int32...).
-## Type conversion
+### Type conversion
All types defined here are stringers and may be converted to strings with `.String()`.
Note that most types defined by this package may be converted directly to string like `string(Email{})`.
@@ -51,13 +97,14 @@ Note that most types defined by this package may be converted directly to string
`Date` and `DateTime` may be converted directly to `time.Time` like `time.Time(Time{})`.
Similarly, you can convert `Duration` to `time.Duration` as in `time.Duration(Duration{})`
-## Using pointers
+### Using pointers
The `conv` subpackage provides helpers to convert the types to and from pointers, just like `go-openapi/swag` does
with primitive types.
-## Format types
-Types defined in strfmt expose marshaling and validation capabilities.
+### Format types
+
+Types defined in `strfmt` expose marshaling and validation capabilities.
List of defined types:
- Base64
@@ -81,7 +128,103 @@ List of defined types:
- SSN
- URI
- UUID
-- UUID3
-- UUID4
-- UUID5
+- [UUID3](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-3)
+- [UUID4](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-4)
+- [UUID5](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-5)
+- [UUID7](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7)
- [ULID](https://github.com/ulid/spec)
+
+### Database support
+
+All format types implement the `database/sql` interfaces `sql.Scanner` and `driver.Valuer`,
+so they work out of the box with Go's standard `database/sql` package and any SQL driver.
+
+All format types also implement BSON marshaling/unmarshaling for use with MongoDB.
+By default, a built-in minimal codec is used (compatible with mongo-driver v2.5.0).
+For full driver support, add `import _ "github.com/go-openapi/strfmt/enable/mongodb"`.
+
+> **MySQL / MariaDB caveat for `DateTime`:**
+> The `go-sql-driver/mysql` driver has hard-coded handling for `time.Time` but does not
+> intercept type redefinitions like `strfmt.DateTime`. As a result, `DateTime.Value()` sends
+> an RFC 3339 string (e.g. `"2024-06-15T12:30:45.123Z"`) that MySQL/MariaDB rejects for
+> `DATETIME` columns.
+>
+> Workaround: set `strfmt.MarshalFormat` to a MySQL-compatible format such as
+> `strfmt.ISO8601LocalTime` and normalize to UTC before marshaling:
+>
+> ```go
+> strfmt.MarshalFormat = strfmt.ISO8601LocalTime
+> strfmt.NormalizeTimeForMarshal = func(t time.Time) time.Time { return t.UTC() }
+> ```
+>
+> See [#174](https://github.com/go-openapi/strfmt/issues/174) for details.
+
+Integration tests for MongoDB, MariaDB, and PostgreSQL run in CI to verify database roundtrip
+compatibility for all format types. See [`internal/testintegration/`](internal/testintegration/).
+
+## 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](.github/CONTRIBUTING.md)
+* [Maintainers documentation](docs/MAINTAINERS.md)
+* [Code style](docs/STYLE.md)
+
+## Cutting a new release
+
+Maintainers can cut a new release by either:
+
+* running [this workflow](https://github.com/go-openapi/strfmt/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/strfmt/actions/workflows/go-test.yml/badge.svg
+[test-url]: https://github.com/go-openapi/strfmt/actions/workflows/go-test.yml
+[cov-badge]: https://codecov.io/gh/go-openapi/strfmt/branch/master/graph/badge.svg
+[cov-url]: https://codecov.io/gh/go-openapi/strfmt
+[vuln-scan-badge]: https://github.com/go-openapi/strfmt/actions/workflows/scanner.yml/badge.svg
+[vuln-scan-url]: https://github.com/go-openapi/strfmt/actions/workflows/scanner.yml
+[codeql-badge]: https://github.com/go-openapi/strfmt/actions/workflows/codeql.yml/badge.svg
+[codeql-url]: https://github.com/go-openapi/strfmt/actions/workflows/codeql.yml
+
+[release-badge]: https://badge.fury.io/gh/go-openapi%2Fstrfmt.svg
+[release-url]: https://badge.fury.io/gh/go-openapi%2Fstrfmt
+[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fstrfmt.svg
+[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fstrfmt
+
+[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/strfmt
+[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/strfmt
+[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/strfmt
+[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/strfmt
+
+[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/strfmt
+[godoc-url]: http://pkg.go.dev/github.com/go-openapi/strfmt
+[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
+
+
+[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
+[license-url]: https://github.com/go-openapi/strfmt/?tab=Apache-2.0-1-ov-file#readme
+
+[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/strfmt
+[goversion-url]: https://github.com/go-openapi/strfmt/blob/master/go.mod
+[top-badge]: https://img.shields.io/github/languages/top/go-openapi/strfmt
+[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/strfmt/latest
diff --git a/vendor/github.com/go-openapi/strfmt/SECURITY.md b/vendor/github.com/go-openapi/strfmt/SECURITY.md
new file mode 100644
index 000000000000..6ceb159ca229
--- /dev/null
+++ b/vendor/github.com/go-openapi/strfmt/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 |
+| ------- | ------------------ |
+| 0.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/strfmt/bson.go b/vendor/github.com/go-openapi/strfmt/bson.go
index cfa9a526feb9..16a83f64086a 100644
--- a/vendor/github.com/go-openapi/strfmt/bson.go
+++ b/vendor/github.com/go-openapi/strfmt/bson.go
@@ -1,81 +1,67 @@
-// 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 strfmt
import (
"database/sql/driver"
+ "encoding/hex"
+ "encoding/json"
"fmt"
-
- "go.mongodb.org/mongo-driver/bson"
-
- "go.mongodb.org/mongo-driver/bson/bsontype"
- bsonprim "go.mongodb.org/mongo-driver/bson/primitive"
)
-func init() {
+func init() { //nolint:gochecknoinits // registers bsonobjectid format in the default registry
var id ObjectId
- // register this format in the default registry
Default.Add("bsonobjectid", &id, IsBSONObjectID)
}
-// IsBSONObjectID returns true when the string is a valid BSON.ObjectId
+// IsBSONObjectID returns true when the string is a valid BSON [ObjectId].
func IsBSONObjectID(str string) bool {
- _, err := bsonprim.ObjectIDFromHex(str)
+ _, err := objectIDFromHex(str)
return err == nil
}
-// ObjectId represents a BSON object ID (alias to go.mongodb.org/mongo-driver/bson/primitive.ObjectID)
+// ObjectId represents a BSON object ID (a 12-byte unique identifier).
//
-// swagger:strfmt bsonobjectid
-type ObjectId bsonprim.ObjectID //nolint:revive,stylecheck
+// swagger:strfmt bsonobjectid.
+type ObjectId [12]byte //nolint:revive
+
+// nilObjectID is the zero-value ObjectId.
+var nilObjectID ObjectId //nolint:gochecknoglobals // package-level sentinel
-// NewObjectId creates a ObjectId from a Hex String
-func NewObjectId(hex string) ObjectId { //nolint:revive,stylecheck
- oid, err := bsonprim.ObjectIDFromHex(hex)
+// NewObjectId creates a [ObjectId] from a hexadecimal String.
+func NewObjectId(hex string) ObjectId { //nolint:revive
+ oid, err := objectIDFromHex(hex)
if err != nil {
panic(err)
}
- return ObjectId(oid)
+ return oid
}
-// MarshalText turns this instance into text
+// MarshalText turns this instance into text.
func (id ObjectId) MarshalText() ([]byte, error) {
- oid := bsonprim.ObjectID(id)
- if oid == bsonprim.NilObjectID {
+ if id == nilObjectID {
return nil, nil
}
- return []byte(oid.Hex()), nil
+ return []byte(id.Hex()), nil
}
-// UnmarshalText hydrates this instance from text
+// UnmarshalText hydrates this instance from text.
func (id *ObjectId) UnmarshalText(data []byte) error { // validation is performed later on
if len(data) == 0 {
- *id = ObjectId(bsonprim.NilObjectID)
+ *id = nilObjectID
return nil
}
- oidstr := string(data)
- oid, err := bsonprim.ObjectIDFromHex(oidstr)
+ oid, err := objectIDFromHex(string(data))
if err != nil {
return err
}
- *id = ObjectId(oid)
+ *id = oid
return nil
}
-// Scan read a value from a database driver
-func (id *ObjectId) Scan(raw interface{}) error {
+// Scan read a value from a database driver.
+func (id *ObjectId) Scan(raw any) error {
var data []byte
switch v := raw.(type) {
case []byte:
@@ -83,69 +69,42 @@ func (id *ObjectId) Scan(raw interface{}) error {
case string:
data = []byte(v)
default:
- return fmt.Errorf("cannot sql.Scan() strfmt.URI from: %#v", v)
+ return fmt.Errorf("cannot sql.Scan() strfmt.URI from: %#v: %w", v, ErrFormat)
}
return id.UnmarshalText(data)
}
-// Value converts a value to a database driver value
+// Value converts a value to a database driver value.
func (id ObjectId) Value() (driver.Value, error) {
- return driver.Value(bsonprim.ObjectID(id).Hex()), nil
+ return driver.Value(id.Hex()), nil
+}
+
+// Hex returns the hex string representation of the [ObjectId].
+func (id ObjectId) Hex() string {
+ return hex.EncodeToString(id[:])
}
func (id ObjectId) String() string {
- return bsonprim.ObjectID(id).Hex()
+ return id.Hex()
}
-// MarshalJSON returns the ObjectId as JSON
+// MarshalJSON returns the [ObjectId] as JSON.
func (id ObjectId) MarshalJSON() ([]byte, error) {
- return bsonprim.ObjectID(id).MarshalJSON()
+ return json.Marshal(id.Hex())
}
-// UnmarshalJSON sets the ObjectId from JSON
+// UnmarshalJSON sets the [ObjectId] from JSON.
func (id *ObjectId) UnmarshalJSON(data []byte) error {
- var obj bsonprim.ObjectID
- if err := obj.UnmarshalJSON(data); err != nil {
+ var hexStr string
+ if err := json.Unmarshal(data, &hexStr); err != nil {
return err
}
- *id = ObjectId(obj)
- return nil
-}
-
-// MarshalBSON renders the object id as a BSON document
-func (id ObjectId) MarshalBSON() ([]byte, error) {
- return bson.Marshal(bson.M{"data": bsonprim.ObjectID(id)})
-}
-
-// UnmarshalBSON reads the objectId from a BSON document
-func (id *ObjectId) UnmarshalBSON(data []byte) error {
- var obj struct {
- Data bsonprim.ObjectID
- }
- if err := bson.Unmarshal(data, &obj); err != nil {
+ oid, err := objectIDFromHex(hexStr)
+ if err != nil {
return err
}
- *id = ObjectId(obj.Data)
- return nil
-}
-
-// MarshalBSONValue is an interface implemented by types that can marshal themselves
-// into a BSON document represented as bytes. The bytes returned must be a valid
-// BSON document if the error is nil.
-func (id ObjectId) MarshalBSONValue() (bsontype.Type, []byte, error) {
- oid := bsonprim.ObjectID(id)
- return bson.TypeObjectID, oid[:], nil
-}
-
-// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
-// BSON value representation of themselves. The BSON bytes and type can be
-// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it
-// wishes to retain the data after returning.
-func (id *ObjectId) UnmarshalBSONValue(_ bsontype.Type, data []byte) error {
- var oid bsonprim.ObjectID
- copy(oid[:], data)
- *id = ObjectId(oid)
+ *id = oid
return nil
}
@@ -154,7 +113,7 @@ func (id *ObjectId) DeepCopyInto(out *ObjectId) {
*out = *id
}
-// DeepCopy copies the receiver into a new ObjectId.
+// DeepCopy copies the receiver into a new [ObjectId].
func (id *ObjectId) DeepCopy() *ObjectId {
if id == nil {
return nil
@@ -163,3 +122,18 @@ func (id *ObjectId) DeepCopy() *ObjectId {
id.DeepCopyInto(out)
return out
}
+
+// objectIDFromHex parses a 24-character hex string into an [ObjectId].
+func objectIDFromHex(s string) (ObjectId, error) {
+ const objectIDHexLen = 24
+ if len(s) != objectIDHexLen {
+ return nilObjectID, fmt.Errorf("the provided hex string %q is not a valid ObjectID: %w", s, ErrFormat)
+ }
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ return nilObjectID, fmt.Errorf("the provided hex string %q is not a valid ObjectID: %w", s, err)
+ }
+ var oid ObjectId
+ copy(oid[:], b)
+ return oid, nil
+}
diff --git a/vendor/github.com/go-openapi/strfmt/date.go b/vendor/github.com/go-openapi/strfmt/date.go
index 3c93381c7cc1..59ee1f11216b 100644
--- a/vendor/github.com/go-openapi/strfmt/date.go
+++ b/vendor/github.com/go-openapi/strfmt/date.go
@@ -1,58 +1,43 @@
-// 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 strfmt
import (
"database/sql/driver"
"encoding/json"
- "errors"
"fmt"
"time"
-
- "go.mongodb.org/mongo-driver/bson"
)
-func init() {
+func init() { //nolint:gochecknoinits // registers date format in the default registry
d := Date{}
- // register this format in the default registry
Default.Add("date", &d, IsDate)
}
-// IsDate returns true when the string is a valid date
+// IsDate returns true when the string is a valid date.
func IsDate(str string) bool {
_, err := time.Parse(RFC3339FullDate, str)
return err == nil
}
const (
- // RFC3339FullDate represents a full-date as specified by RFC3339
+ // RFC3339FullDate represents a full-date as specified by RFC3339.
// See: http://goo.gl/xXOvVd
RFC3339FullDate = "2006-01-02"
)
-// Date represents a date from the API
+// Date represents a date from the API.
//
-// swagger:strfmt date
+// swagger:strfmt date.
type Date time.Time
-// String converts this date into a string
+// String converts this date into a string.
func (d Date) String() string {
return time.Time(d).Format(RFC3339FullDate)
}
-// UnmarshalText parses a text representation into a date type
+// UnmarshalText parses a text representation into a date type.
func (d *Date) UnmarshalText(text []byte) error {
if len(text) == 0 {
return nil
@@ -65,13 +50,13 @@ func (d *Date) UnmarshalText(text []byte) error {
return nil
}
-// MarshalText serializes this date type to string
+// MarshalText serializes this date type to string.
func (d Date) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}
// Scan scans a Date value from database driver type.
-func (d *Date) Scan(raw interface{}) error {
+func (d *Date) Scan(raw any) error {
switch v := raw.(type) {
case []byte:
return d.UnmarshalText(v)
@@ -84,7 +69,7 @@ func (d *Date) Scan(raw interface{}) error {
*d = Date{}
return nil
default:
- return fmt.Errorf("cannot sql.Scan() strfmt.Date from: %#v", v)
+ return fmt.Errorf("cannot sql.Scan() strfmt.Date from: %#v: %w", v, ErrFormat)
}
}
@@ -93,12 +78,12 @@ func (d Date) Value() (driver.Value, error) {
return driver.Value(d.String()), nil
}
-// MarshalJSON returns the Date as JSON
+// MarshalJSON returns the Date as JSON.
func (d Date) MarshalJSON() ([]byte, error) {
return json.Marshal(time.Time(d).Format(RFC3339FullDate))
}
-// UnmarshalJSON sets the Date from JSON
+// UnmarshalJSON sets the Date from JSON.
func (d *Date) UnmarshalJSON(data []byte) error {
if string(data) == jsonNull {
return nil
@@ -115,28 +100,6 @@ func (d *Date) UnmarshalJSON(data []byte) error {
return nil
}
-func (d Date) MarshalBSON() ([]byte, error) {
- return bson.Marshal(bson.M{"data": d.String()})
-}
-
-func (d *Date) UnmarshalBSON(data []byte) error {
- var m bson.M
- if err := bson.Unmarshal(data, &m); err != nil {
- return err
- }
-
- if data, ok := m["data"].(string); ok {
- rd, err := time.ParseInLocation(RFC3339FullDate, data, DefaultTimeLocation)
- if err != nil {
- return err
- }
- *d = Date(rd)
- return nil
- }
-
- return errors.New("couldn't unmarshal bson bytes value as Date")
-}
-
// DeepCopyInto copies the receiver and writes its value into out.
func (d *Date) DeepCopyInto(out *Date) {
*out = *d
@@ -162,12 +125,12 @@ func (d *Date) GobDecode(data []byte) error {
return d.UnmarshalBinary(data)
}
-// MarshalBinary implements the encoding.BinaryMarshaler interface.
+// MarshalBinary implements the encoding.[encoding.BinaryMarshaler] interface.
func (d Date) MarshalBinary() ([]byte, error) {
return time.Time(d).MarshalBinary()
}
-// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+// UnmarshalBinary implements the encoding.[encoding.BinaryUnmarshaler] interface.
func (d *Date) UnmarshalBinary(data []byte) error {
var original time.Time
@@ -181,7 +144,7 @@ func (d *Date) UnmarshalBinary(data []byte) error {
return nil
}
-// Equal checks if two Date instances are equal
+// Equal checks if two Date instances are equal.
func (d Date) Equal(d2 Date) bool {
return time.Time(d).Equal(time.Time(d2))
}
diff --git a/vendor/github.com/go-openapi/strfmt/default.go b/vendor/github.com/go-openapi/strfmt/default.go
index 2813714060eb..87d3856ad230 100644
--- a/vendor/github.com/go-openapi/strfmt/default.go
+++ b/vendor/github.com/go-openapi/strfmt/default.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 strfmt
@@ -18,121 +7,367 @@ import (
"database/sql/driver"
"encoding/base64"
"encoding/json"
- "errors"
"fmt"
+ "net"
"net/mail"
+ "net/netip"
+ "net/url"
"regexp"
+ "strconv"
"strings"
- "github.com/asaskevich/govalidator"
"github.com/google/uuid"
- "go.mongodb.org/mongo-driver/bson"
+ "golang.org/x/net/idna"
)
const (
- // HostnamePattern http://json-schema.org/latest/json-schema-validation.html#anchor114
- // A string instance is valid against this attribute if it is a valid
- // representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034].
- // http://tools.ietf.org/html/rfc1034#section-3.5
- // ::= any one of the ten digits 0 through 9
- // var digit = /[0-9]/;
- // ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case
- // var letter = /[a-zA-Z]/;
- // ::= |
- // var letDig = /[0-9a-zA-Z]/;
- // ::= | "-"
- // var letDigHyp = /[-0-9a-zA-Z]/;
- // ::= |
- // var ldhStr = /[-0-9a-zA-Z]+/;
- //