diff --git a/.github/workflows/aks-byocni.yaml b/.github/workflows/aks-byocni.yaml index 4fb818c3d7..d8ff455644 100644 --- a/.github/workflows/aks-byocni.yaml +++ b/.github/workflows/aks-byocni.yaml @@ -39,7 +39,7 @@ env: location: westus2 cost_reduction: --node-vm-size Standard_B2s --node-osdisk-size 30 # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.8 + cilium_version: v1.17.2 kubectl_version: v1.23.6 jobs: diff --git a/.github/workflows/eks-tunnel.yaml b/.github/workflows/eks-tunnel.yaml index 5bb82ad94a..1606191876 100644 --- a/.github/workflows/eks-tunnel.yaml +++ b/.github/workflows/eks-tunnel.yaml @@ -29,7 +29,7 @@ env: region: us-east-2 eksctl_version: v0.147.0 # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.8 + cilium_version: v1.17.2 kubectl_version: v1.23.6 jobs: diff --git a/.github/workflows/eks.yaml b/.github/workflows/eks.yaml index f5cfbf07e7..023d4acb83 100644 --- a/.github/workflows/eks.yaml +++ b/.github/workflows/eks.yaml @@ -29,7 +29,7 @@ env: region: us-east-2 eksctl_version: v0.147.0 # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.8 + cilium_version: v1.17.2 kubectl_version: v1.23.6 jobs: diff --git a/.github/workflows/gke.yaml b/.github/workflows/gke.yaml index 74b7a1a626..409595d793 100644 --- a/.github/workflows/gke.yaml +++ b/.github/workflows/gke.yaml @@ -36,7 +36,7 @@ concurrency: env: zone: us-west2-a # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.8 + cilium_version: v1.17.2 kubectl_version: v1.23.6 USE_GKE_GCLOUD_AUTH_PLUGIN: True diff --git a/.github/workflows/kind.yaml b/.github/workflows/kind.yaml index 167a0b6ef5..0c910b8b90 100644 --- a/.github/workflows/kind.yaml +++ b/.github/workflows/kind.yaml @@ -17,7 +17,7 @@ env: TIMEOUT: 2m LOG_TIME: 30m # renovate: datasource=github-releases depName=cilium/cilium - cilium_version: v1.16.8 + cilium_version: v1.17.2 kubectl_version: v1.23.6 jobs: diff --git a/go.mod b/go.mod index cac74467ec..8849922865 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ go 1.24.0 // as to why we are using a private fork. replace sigs.k8s.io/controller-tools => github.com/cilium/controller-tools v0.16.5-1 -require github.com/cilium/cilium v1.18.0-pre.0.0.20250307211928-06901cc99eca +require github.com/cilium/cilium v1.18.0-pre.0.0.20250321220641-9d59c1208ae1 require ( cel.dev/expr v0.19.1 // indirect @@ -28,16 +28,16 @@ require ( github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/cilium/charts v0.0.0-20250204154402-8a35f8210901 // indirect - github.com/cilium/ebpf v0.17.1 // indirect - github.com/cilium/hive v0.0.0-20250217113459-914947d44393 // indirect - github.com/cilium/proxy v0.0.0-20250214115704-3e4b99dc5d1f // indirect - github.com/cilium/statedb v0.3.6 // indirect + github.com/cilium/charts v0.0.0-20250315135936-15c20a953df6 // indirect + github.com/cilium/ebpf v0.17.3 // indirect + github.com/cilium/hive v0.0.0-20250311080423-b13b66490d76 // indirect + github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb // indirect + github.com/cilium/statedb v0.3.7 // indirect github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 // indirect - github.com/cilium/workerpool v1.2.0 // indirect + github.com/cilium/workerpool v1.3.0 // indirect github.com/cloudflare/cfssl v1.6.5 // indirect github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect - github.com/containerd/containerd v1.7.24 // indirect + github.com/containerd/containerd v1.7.27 // indirect github.com/containerd/errdefs v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect @@ -48,7 +48,7 @@ require ( github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v25.0.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v27.5.1+incompatible // indirect + github.com/docker/docker v28.0.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect @@ -65,15 +65,16 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.23.0 // indirect - github.com/go-openapi/errors v0.22.0 // indirect + github.com/go-openapi/errors v0.22.1 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/loads v0.22.0 // indirect github.com/go-openapi/runtime v0.28.0 // indirect github.com/go-openapi/spec v0.21.0 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/swag v0.23.1 // indirect github.com/go-openapi/validate v0.24.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect @@ -81,8 +82,8 @@ require ( github.com/google/btree v1.1.3 // indirect github.com/google/certificate-transparency-go v1.1.7 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-github/v68 v68.0.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/go-github/v70 v70.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/gops v0.3.28 // indirect @@ -96,21 +97,19 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/hcl v1.0.1-vault-5 // indirect github.com/hmarr/codeowners v1.2.1 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mackerelio/go-osstat v0.2.5 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect @@ -130,31 +129,30 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/osrg/gobgp/v3 v3.34.0 // indirect + github.com/osrg/gobgp/v3 v3.35.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.20.5 // indirect + github.com/prometheus/client_golang v1.21.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/common v0.63.0 // indirect + github.com/prometheus/procfs v0.16.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rubenv/sql-migrate v1.7.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.6 // indirect - github.com/spf13/viper v1.19.0 // indirect + github.com/spf13/viper v1.20.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8 // indirect github.com/vishvananda/netns v0.0.5 // indirect @@ -166,57 +164,55 @@ require ( github.com/xlab/treeprint v1.2.0 // indirect github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300 // indirect github.com/zmap/zlint/v3 v3.5.0 // indirect - go.etcd.io/etcd/api/v3 v3.5.18 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.18 // indirect - go.etcd.io/etcd/client/v3 v3.5.18 // indirect + go.etcd.io/etcd/api/v3 v3.5.19 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.19 // indirect + go.etcd.io/etcd/client/v3 v3.5.19 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect - go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/otel v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/dig v1.17.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.33.0 // indirect - golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect - golang.org/x/net v0.35.0 // indirect - golang.org/x/oauth2 v0.26.0 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/term v0.29.0 // indirect - golang.org/x/text v0.22.0 // indirect - golang.org/x/time v0.10.0 // indirect - golang.org/x/tools v0.30.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250207221924-e9438ea467c6 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect - google.golang.org/grpc v1.70.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/oauth2 v0.28.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/term v0.30.0 // indirect + golang.org/x/text v0.23.0 // indirect + golang.org/x/time v0.11.0 // indirect + golang.org/x/tools v0.31.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect + google.golang.org/grpc v1.71.0 // indirect google.golang.org/protobuf v1.36.5 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - helm.sh/helm/v3 v3.17.0 // indirect - k8s.io/api v0.32.2 // indirect - k8s.io/apiextensions-apiserver v0.32.2 // indirect - k8s.io/apimachinery v0.32.2 // indirect - k8s.io/apiserver v0.32.2 // indirect - k8s.io/cli-runtime v0.32.2 // indirect - k8s.io/client-go v0.32.2 // indirect - k8s.io/component-base v0.32.2 // indirect + helm.sh/helm/v3 v3.17.2 // indirect + k8s.io/api v0.32.3 // indirect + k8s.io/apiextensions-apiserver v0.32.3 // indirect + k8s.io/apimachinery v0.32.3 // indirect + k8s.io/apiserver v0.32.3 // indirect + k8s.io/cli-runtime v0.32.3 // indirect + k8s.io/client-go v0.32.3 // indirect + k8s.io/component-base v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect - k8s.io/kubectl v0.32.2 // indirect + k8s.io/kubectl v0.32.3 // indirect k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect oras.land/oras-go v1.2.5 // indirect - sigs.k8s.io/controller-runtime v0.20.1 // indirect + sigs.k8s.io/controller-runtime v0.20.3 // indirect sigs.k8s.io/gateway-api v1.2.1 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/kustomize/api v0.18.0 // indirect sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect - sigs.k8s.io/mcs-api v0.1.1-0.20250129110323-a7986579439f // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + sigs.k8s.io/mcs-api v0.1.1-0.20250224121229-6c631f4730d0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index fe8b592b55..b9330ca97f 100644 --- a/go.sum +++ b/go.sum @@ -54,32 +54,32 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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= -github.com/cilium/charts v0.0.0-20250204154402-8a35f8210901 h1:5RH3uJeR2kGU2uOdEHh/dzFgFMaSi5wKQbGolcYUFBc= -github.com/cilium/charts v0.0.0-20250204154402-8a35f8210901/go.mod h1:M3C9VOlFvRzuV+a01t07Tw4uFLSfkCH3L542IWjf6BU= -github.com/cilium/cilium v1.18.0-pre.0.0.20250307211928-06901cc99eca h1:H5/i4MDt3w06UMSx1K7liKa5PUKmn3Gx38xSyEXbrBE= -github.com/cilium/cilium v1.18.0-pre.0.0.20250307211928-06901cc99eca/go.mod h1:zNicgMLoL/BiK/qKBkounEJbF2pGEdsi4naIz+V56QE= -github.com/cilium/ebpf v0.17.1 h1:G8mzU81R2JA1nE5/8SRubzqvBMmAmri2VL8BIZPWvV0= -github.com/cilium/ebpf v0.17.1/go.mod h1:vay2FaYSmIlv3r8dNACd4mW/OCaZLJKJOo+IHBvCIO8= -github.com/cilium/hive v0.0.0-20250217113459-914947d44393 h1:x2VYGSK1hnX6N7j2V6rtIDN0E+dO6ozTyYz8iYOugD8= -github.com/cilium/hive v0.0.0-20250217113459-914947d44393/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI= -github.com/cilium/proxy v0.0.0-20250214115704-3e4b99dc5d1f h1:e+c0sFbzPfKjDtsG06uZah+aqpDycdpGF/StqtaUg7Y= -github.com/cilium/proxy v0.0.0-20250214115704-3e4b99dc5d1f/go.mod h1:WcTUEfsCIVY9uvjRLUvl0G+G7RiK5BfOVdg/LknXMpk= -github.com/cilium/statedb v0.3.6 h1:dGwzZTJgVWlnG7io0Wl0XsI7ULsz2TbNqH8Ag+dP6is= -github.com/cilium/statedb v0.3.6/go.mod h1:n2lNVxi8vz5Up1Y1rRD++aQP2izQA932fUwTkedKSV0= +github.com/cilium/charts v0.0.0-20250315135936-15c20a953df6 h1:Fam72veX66q5u+ECGM+aKsw6ICxW4VH9yx97tb/90Ac= +github.com/cilium/charts v0.0.0-20250315135936-15c20a953df6/go.mod h1:M3C9VOlFvRzuV+a01t07Tw4uFLSfkCH3L542IWjf6BU= +github.com/cilium/cilium v1.18.0-pre.0.0.20250321220641-9d59c1208ae1 h1:xHxxZrWvhmfV6cDrkX+ZJ7MxTR/wrNg5iGSvpB6E7K4= +github.com/cilium/cilium v1.18.0-pre.0.0.20250321220641-9d59c1208ae1/go.mod h1:TRn7XKcUe1YA8TOTcHRDX8hq7oOIFPAkyCbpYuLfHfQ= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= +github.com/cilium/hive v0.0.0-20250311080423-b13b66490d76 h1:IZRB3yicRJumH06g9kkGwpnbZkv0+U+zELqEw8pIQys= +github.com/cilium/hive v0.0.0-20250311080423-b13b66490d76/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI= +github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb h1:pV58137rRui6vUJT2HM2h0HcPfaAh+6BVH42oKXytH8= +github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb/go.mod h1:ZCm83Mm0aE17bm2vnYY3kS40VIT7ymoqZhNc8YXK1us= +github.com/cilium/statedb v0.3.7 h1:htzjXktKe37FNLGDQjM899G8BK4Pcp+GM1cFQVV3HGA= +github.com/cilium/statedb v0.3.7/go.mod h1:n2lNVxi8vz5Up1Y1rRD++aQP2izQA932fUwTkedKSV0= github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 h1:f+CgYUy2YyZ2EX31QSqf3vwFiJJQSAMIQLn4d3QQYno= github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744/go.mod h1:/e83AwqvNKpyg4n3C41qmnmj1x2G9DwzI+jb7GkF4lI= -github.com/cilium/workerpool v1.2.0 h1:Wc2iOPTvCgWKQXeq4L5tnx4QFEI+z5q1+bSpSS0cnAY= -github.com/cilium/workerpool v1.2.0/go.mod h1:GOYJhwlnIjR+jWSDNBb5kw47G1H/XA9X4WOBpgr4pQU= +github.com/cilium/workerpool v1.3.0 h1:7BhHxoqNtpqtmce6MxZdgWODze4lYHbWkEUQ+3xEu8M= +github.com/cilium/workerpool v1.3.0/go.mod h1:0evs6P39nORTphjRtTtHLXTyCPQUwelXCK4wBJmVP7g= github.com/cloudflare/cfssl v1.6.5 h1:46zpNkm6dlNkMZH/wMW22ejih6gIaJbzL2du6vD7ZeI= github.com/cloudflare/cfssl v1.6.5/go.mod h1:Bk1si7sq8h2+yVEDrFJiz3d7Aw+pfjjJSZVaD+Taky4= github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA= -github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= -github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= -github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII= +github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0= +github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= +github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -90,7 +90,7 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= 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/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= @@ -107,8 +107,8 @@ github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbT github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8= -github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= +github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -125,8 +125,8 @@ github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfU github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -158,8 +158,8 @@ github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= 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/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.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= +github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= 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/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= @@ -172,8 +172,8 @@ github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9Z github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= 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/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.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= 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-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= @@ -185,6 +185,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -209,11 +211,11 @@ github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYu github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= -github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= +github.com/google/go-github/v70 v70.0.0 h1:/tqCp5KPrcvqCc7vIvYyFYTiCGrYvaWoYMGHSQbo55o= +github.com/google/go-github/v70 v70.0.0/go.mod h1:xBUZgo8MI3lUL/hwxl3hlceJW1U8MVnXP3zUyI+rhQY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= @@ -251,8 +253,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= -github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hmarr/codeowners v1.2.1 h1:+9yndrwG0UVP1GkLBEQMSbSUNeLpbrbL924SRthA/9k= github.com/hmarr/codeowners v1.2.1/go.mod h1:KPlR1p/B4owPjwfNIBueWlOP4CmqlQFX9b6nANG6j40= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= @@ -274,8 +274,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -298,10 +298,8 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhn github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2GXh+o= github.com/mackerelio/go-osstat v0.2.5/go.mod h1:atxwWF+POUZcdtR1wnsUcQxTytoHG4uhl2AKKzrOajY= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -320,8 +318,8 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/ github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= -github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= -github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= +github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -359,10 +357,10 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= -github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= +github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -370,12 +368,12 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= -github.com/osrg/gobgp/v3 v3.34.0 h1:DDIWsAIE7j1dwhSV3tGsTKs9OO8MTOS4atErebZxTtA= -github.com/osrg/gobgp/v3 v3.34.0/go.mod h1:l2nPaHaLmIoKbFxMUzKon/h6c9BTzCp5zJI9Dhnrx5c= +github.com/osrg/gobgp/v3 v3.35.0 h1:8HQyCCoByAJyXiSzTFBl77wuOyVdDXozPdXX+tjYyHQ= +github.com/osrg/gobgp/v3 v3.35.0/go.mod h1:l2nPaHaLmIoKbFxMUzKon/h6c9BTzCp5zJI9Dhnrx5c= 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/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= @@ -395,21 +393,21 @@ github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjz github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= +github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= +github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= +github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -419,10 +417,8 @@ github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmi github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= @@ -437,21 +433,18 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= -github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= +github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -459,11 +452,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -509,12 +498,12 @@ github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300/go.mod h1:mOd4yUMgn2f github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8= github.com/zmap/zlint/v3 v3.5.0 h1:Eh2B5t6VKgVH0DFmTwOqE50POvyDhUaU9T2mJOe1vfQ= github.com/zmap/zlint/v3 v3.5.0/go.mod h1:JkNSrsDJ8F4VRtBZcYUQSvnWFL7utcjDIn+FE64mlBI= -go.etcd.io/etcd/api/v3 v3.5.18 h1:Q4oDAKnmwqTo5lafvB+afbgCDF7E35E4EYV2g+FNGhs= -go.etcd.io/etcd/api/v3 v3.5.18/go.mod h1:uY03Ob2H50077J7Qq0DeehjM/A9S8PhVfbQ1mSaMopU= -go.etcd.io/etcd/client/pkg/v3 v3.5.18 h1:mZPOYw4h8rTk7TeJ5+3udUkfVGBqc+GCjOJYd68QgNM= -go.etcd.io/etcd/client/pkg/v3 v3.5.18/go.mod h1:BxVf2o5wXG9ZJV+/Cu7QNUiJYk4A29sAhoI5tIRsCu4= -go.etcd.io/etcd/client/v3 v3.5.18 h1:nvvYmNHGumkDjZhTHgVU36A9pykGa2K4lAJ0yY7hcXA= -go.etcd.io/etcd/client/v3 v3.5.18/go.mod h1:kmemwOsPU9broExyhYsBxX4spCTDX3yLgPMWtpBXG6E= +go.etcd.io/etcd/api/v3 v3.5.19 h1:w3L6sQZGsWPuBxRQ4m6pPP3bVUtV8rjW033EGwlr0jw= +go.etcd.io/etcd/api/v3 v3.5.19/go.mod h1:QqKGViq4KTgOG43dr/uH0vmGWIaoJY3ggFi6ZH0TH/U= +go.etcd.io/etcd/client/pkg/v3 v3.5.19 h1:9VsyGhg0WQGjDWWlDI4VuaS9PZJGNbPkaHEIuLwtixk= +go.etcd.io/etcd/client/pkg/v3 v3.5.19/go.mod h1:qaOi1k4ZA9lVLejXNvyPABrVEe7VymMF2433yyRQ7O0= +go.etcd.io/etcd/client/v3 v3.5.19 h1:+4byIz6ti3QC28W0zB0cEZWwhpVHXdrKovyycJh1KNo= +go.etcd.io/etcd/client/v3 v3.5.19/go.mod h1:FNzyinmMIl0oVsty1zA3hFeUrxXI/JpEnz4sG+POzjU= 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.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= @@ -523,16 +512,16 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= -go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= -go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= -go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= @@ -553,16 +542,16 @@ golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -577,10 +566,10 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -588,8 +577,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -615,43 +604,43 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= -golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= 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= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20250207221924-e9438ea467c6 h1:L9JNMl/plZH9wmzQUHleO/ZZDSN+9Gh41wPczNy+5Fk= -google.golang.org/genproto/googleapis/api v0.0.0-20250207221924-e9438ea467c6/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk= -google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= -google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY= +google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= 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= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -663,8 +652,6 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -675,34 +662,34 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.17.0 h1:DUD4AGdNVn7PSTYfxe1gmQG7s18QeWv/4jI9TubnhT0= -helm.sh/helm/v3 v3.17.0/go.mod h1:Mo7eGyKPPHlS0Ml67W8z/lbkox/gD9Xt1XpD6bxvZZA= -k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= -k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= -k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= -k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA= -k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= -k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/apiserver v0.32.2 h1:WzyxAu4mvLkQxwD9hGa4ZfExo3yZZaYzoYvvVDlM6vw= -k8s.io/apiserver v0.32.2/go.mod h1:PEwREHiHNU2oFdte7BjzA1ZyjWjuckORLIK/wLV5goM= -k8s.io/cli-runtime v0.32.2 h1:aKQR4foh9qeyckKRkNXUccP9moxzffyndZAvr+IXMks= -k8s.io/cli-runtime v0.32.2/go.mod h1:a/JpeMztz3xDa7GCyyShcwe55p8pbcCVQxvqZnIwXN8= -k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= -k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= -k8s.io/component-base v0.32.2 h1:1aUL5Vdmu7qNo4ZsE+569PV5zFatM9hl+lb3dEea2zU= -k8s.io/component-base v0.32.2/go.mod h1:PXJ61Vx9Lg+P5mS8TLd7bCIr+eMJRQTyXe8KvkrvJq0= +helm.sh/helm/v3 v3.17.2 h1:agYQ5ew2jq5vdx2K7q5W44KyKQrnSubUMCQsjkiv3/o= +helm.sh/helm/v3 v3.17.2/go.mod h1:+uJKMH/UiMzZQOALR3XUf3BLIoczI2RKKD6bMhPh4G8= +k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= +k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= +k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= +k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= +k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= +k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8= +k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc= +k8s.io/cli-runtime v0.32.3 h1:khLF2ivU2T6Q77H97atx3REY9tXiA3OLOjWJxUrdvss= +k8s.io/cli-runtime v0.32.3/go.mod h1:vZT6dZq7mZAca53rwUfdFSZjdtLyfF61mkf/8q+Xjak= +k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= +k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= +k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= +k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/kubectl v0.32.2 h1:TAkag6+XfSBgkqK9I7ZvwtF0WVtUAvK8ZqTt+5zi1Us= -k8s.io/kubectl v0.32.2/go.mod h1:+h/NQFSPxiDZYX/WZaWw9fwYezGLISP0ud8nQKg+3g8= +k8s.io/kubectl v0.32.3 h1:VMi584rbboso+yjfv0d8uBHwwxbC438LKq+dXd5tOAI= +k8s.io/kubectl v0.32.3/go.mod h1:6Euv2aso5GKzo/UVMacV6C7miuyevpfI91SvBvV9Zdg= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= -sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= -sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= +sigs.k8s.io/controller-runtime v0.20.3 h1:I6Ln8JfQjHH7JbtCD2HCYHoIzajoRxPNuvhvcDbZgkI= +sigs.k8s.io/controller-runtime v0.20.3/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/gateway-api v1.2.1 h1:fZZ/+RyRb+Y5tGkwxFKuYuSRQHu9dZtbjenblleOLHM= sigs.k8s.io/gateway-api v1.2.1/go.mod h1:EpNfEXNjiYfUJypf0eZ0P5iXA9ekSGWaS1WgPaM42X0= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= @@ -711,9 +698,9 @@ sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= -sigs.k8s.io/mcs-api v0.1.1-0.20250129110323-a7986579439f h1:VUD0/ipPthw+Q6eLYtbEPfStDidsKavey7fTKw+U30M= -sigs.k8s.io/mcs-api v0.1.1-0.20250129110323-a7986579439f/go.mod h1:M1Zjh0Jn/Z5e/2JHsZyEeLMw0qGBBmkJqEOc+OceERY= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/mcs-api v0.1.1-0.20250224121229-6c631f4730d0 h1:LChl5QBr39XNzUjscGlfBJYjyclDru70cLujcC8Vn/M= +sigs.k8s.io/mcs-api v0.1.1-0.20250224121229-6c631f4730d0/go.mod h1:M1Zjh0Jn/Z5e/2JHsZyEeLMw0qGBBmkJqEOc+OceERY= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/vendor/github.com/cilium/charts/README.md b/vendor/github.com/cilium/charts/README.md index 8521919ba6..b659739b2e 100644 --- a/vendor/github.com/cilium/charts/README.md +++ b/vendor/github.com/cilium/charts/README.md @@ -1,5 +1,8 @@ This repository holds helm templates for the following Cilium releases: +* [v1.18.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.18.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.18.0-pre.0/install/kubernetes/cilium)_) +* [v1.17.2](https://github.com/cilium/cilium/releases/tag/v1.17.2) (_[source](https://github.com/cilium/cilium/tree/v1.17.2/install/kubernetes/cilium)_) +* [v1.17.1](https://github.com/cilium/cilium/releases/tag/v1.17.1) (_[source](https://github.com/cilium/cilium/tree/v1.17.1/install/kubernetes/cilium)_) * [v1.17.0](https://github.com/cilium/cilium/releases/tag/v1.17.0) (_[source](https://github.com/cilium/cilium/tree/v1.17.0/install/kubernetes/cilium)_) * [v1.17.0-rc.2](https://github.com/cilium/cilium/releases/tag/v1.17.0-rc.2) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-rc.2/install/kubernetes/cilium)_) * [v1.17.0-rc.1](https://github.com/cilium/cilium/releases/tag/v1.17.0-rc.1) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-rc.1/install/kubernetes/cilium)_) @@ -8,6 +11,8 @@ This repository holds helm templates for the following Cilium releases: * [v1.17.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.2/install/kubernetes/cilium)_) * [v1.17.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.1/install/kubernetes/cilium)_) * [v1.17.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.17.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.17.0-pre.0/install/kubernetes/cilium)_) +* [v1.16.8](https://github.com/cilium/cilium/releases/tag/v1.16.8) (_[source](https://github.com/cilium/cilium/tree/v1.16.8/install/kubernetes/cilium)_) +* [v1.16.7](https://github.com/cilium/cilium/releases/tag/v1.16.7) (_[source](https://github.com/cilium/cilium/tree/v1.16.7/install/kubernetes/cilium)_) * [v1.16.6](https://github.com/cilium/cilium/releases/tag/v1.16.6) (_[source](https://github.com/cilium/cilium/tree/v1.16.6/install/kubernetes/cilium)_) * [v1.16.5](https://github.com/cilium/cilium/releases/tag/v1.16.5) (_[source](https://github.com/cilium/cilium/tree/v1.16.5/install/kubernetes/cilium)_) * [v1.16.4](https://github.com/cilium/cilium/releases/tag/v1.16.4) (_[source](https://github.com/cilium/cilium/tree/v1.16.4/install/kubernetes/cilium)_) @@ -22,6 +27,8 @@ This repository holds helm templates for the following Cilium releases: * [v1.16.0-pre.2](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.2) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.2/install/kubernetes/cilium)_) * [v1.16.0-pre.1](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.1) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.1/install/kubernetes/cilium)_) * [v1.16.0-pre.0](https://github.com/cilium/cilium/releases/tag/v1.16.0-pre.0) (_[source](https://github.com/cilium/cilium/tree/v1.16.0-pre.0/install/kubernetes/cilium)_) +* [v1.15.15](https://github.com/cilium/cilium/releases/tag/v1.15.15) (_[source](https://github.com/cilium/cilium/tree/v1.15.15/install/kubernetes/cilium)_) +* [v1.15.14](https://github.com/cilium/cilium/releases/tag/v1.15.14) (_[source](https://github.com/cilium/cilium/tree/v1.15.14/install/kubernetes/cilium)_) * [v1.15.13](https://github.com/cilium/cilium/releases/tag/v1.15.13) (_[source](https://github.com/cilium/cilium/tree/v1.15.13/install/kubernetes/cilium)_) * [v1.15.12](https://github.com/cilium/cilium/releases/tag/v1.15.12) (_[source](https://github.com/cilium/cilium/tree/v1.15.12/install/kubernetes/cilium)_) * [v1.15.11](https://github.com/cilium/cilium/releases/tag/v1.15.11) (_[source](https://github.com/cilium/cilium/tree/v1.15.11/install/kubernetes/cilium)_) diff --git a/vendor/github.com/cilium/charts/cilium-1.15.14.tgz b/vendor/github.com/cilium/charts/cilium-1.15.14.tgz new file mode 100644 index 0000000000..aa9f9f728e Binary files /dev/null and b/vendor/github.com/cilium/charts/cilium-1.15.14.tgz differ diff --git a/vendor/github.com/cilium/charts/cilium-1.15.15.tgz b/vendor/github.com/cilium/charts/cilium-1.15.15.tgz new file mode 100644 index 0000000000..14a0431dff Binary files /dev/null and b/vendor/github.com/cilium/charts/cilium-1.15.15.tgz differ diff --git a/vendor/github.com/cilium/charts/cilium-1.16.7.tgz b/vendor/github.com/cilium/charts/cilium-1.16.7.tgz new file mode 100644 index 0000000000..ea7417ee24 Binary files /dev/null and b/vendor/github.com/cilium/charts/cilium-1.16.7.tgz differ diff --git a/vendor/github.com/cilium/charts/cilium-1.16.8.tgz b/vendor/github.com/cilium/charts/cilium-1.16.8.tgz new file mode 100644 index 0000000000..dff3ab3f9a Binary files /dev/null and b/vendor/github.com/cilium/charts/cilium-1.16.8.tgz differ diff --git a/vendor/github.com/cilium/charts/cilium-1.17.1.tgz b/vendor/github.com/cilium/charts/cilium-1.17.1.tgz new file mode 100644 index 0000000000..d95b80cb41 Binary files /dev/null and b/vendor/github.com/cilium/charts/cilium-1.17.1.tgz differ diff --git a/vendor/github.com/cilium/charts/cilium-1.17.2.tgz b/vendor/github.com/cilium/charts/cilium-1.17.2.tgz new file mode 100644 index 0000000000..ecd011dd7b Binary files /dev/null and b/vendor/github.com/cilium/charts/cilium-1.17.2.tgz differ diff --git a/vendor/github.com/cilium/charts/cilium-1.18.0-pre.0.tgz b/vendor/github.com/cilium/charts/cilium-1.18.0-pre.0.tgz new file mode 100644 index 0000000000..e5ebaddd82 Binary files /dev/null and b/vendor/github.com/cilium/charts/cilium-1.18.0-pre.0.tgz differ diff --git a/vendor/github.com/cilium/charts/index.yaml b/vendor/github.com/cilium/charts/index.yaml index 86c23d64f8..2e59c5335a 100644 --- a/vendor/github.com/cilium/charts/index.yaml +++ b/vendor/github.com/cilium/charts/index.yaml @@ -1,6 +1,745 @@ apiVersion: v1 entries: cilium: + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumLocalRedirectPolicy\n + \ version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n displayName: + Cilium Local Redirect Policy\n description: |\n Cilium Local Redirect + Policy allows local redirects to be configured\n within a node to support + use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n version: v2\n + \ name: ciliumnodes.cilium.io\n displayName: Cilium Node\n description: + |\n Cilium Node represents a node managed by Cilium. It contains a\n specification + to control various node specific configuration aspects\n and a status section + to represent the status of the node.\n- kind: CiliumIdentity\n version: v2\n + \ name: ciliumidentities.cilium.io\n displayName: Cilium Identity\n description: + |\n Cilium Identity allows introspection into security identities that\n + \ Cilium allocates which identify sets of labels that are assigned to\n + \ individual endpoints in the cluster.\n- kind: CiliumEndpoint\n version: + v2\n name: ciliumendpoints.cilium.io\n displayName: Cilium Endpoint\n description: + |\n Cilium Endpoint represents the status of individual pods or nodes in\n + \ the cluster which are managed by Cilium, including enforcement status,\n + \ IP addressing and whether the networking is successfully operational.\n- + kind: CiliumEndpointSlice\n version: v2alpha1\n name: ciliumendpointslices.cilium.io\n + \ displayName: Cilium Endpoint Slice\n description: |\n Cilium Endpoint + Slice represents the status of groups of pods or nodes\n in the cluster + which are managed by Cilium, including enforcement status,\n IP addressing + and whether the networking is successfully operational.\n- kind: CiliumEgressGatewayPolicy\n + \ version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n displayName: + Cilium Egress Gateway Policy\n description: |\n Cilium Egress Gateway + Policy provides control over the way that traffic\n leaves the cluster + and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumNodeConfig\n version: + v2\n name: ciliumnodeconfigs.cilium.io\n displayName: Cilium Node Configuration\n + \ description: |\n CiliumNodeConfig is a list of configuration key-value + pairs. It is applied to\n nodes indicated by a label selector.\n- kind: + CiliumBGPPeeringPolicy\n version: v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n + \ displayName: Cilium BGP Peering Policy\n description: |\n Cilium BGP + Peering Policy instructs Cilium to create specific BGP peering\n configurations.\n- + kind: CiliumBGPClusterConfig\n version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n + \ displayName: Cilium BGP Cluster Config\n description: |\n Cilium BGP + Cluster Config instructs Cilium operator to create specific BGP cluster\n + \ configurations.\n- kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: + ciliumbgppeerconfigs.cilium.io\n displayName: Cilium BGP Peer Config\n description: + |\n CiliumBGPPeerConfig is a common set of BGP peer configurations. It + can be referenced \n by multiple peers from CiliumBGPClusterConfig.\n- + kind: CiliumBGPAdvertisement\n version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n + \ displayName: Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement + is used to define source of BGP advertisement as well as BGP attributes \n + \ to be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumCIDRGroup\n version: v2alpha1\n name: ciliumcidrgroups.cilium.io\n + \ displayName: Cilium CIDR Group\n description: |\n CiliumCIDRGroup is + a list of CIDRs that can be referenced as a single entity from CiliumNetworkPolicies.\n- + kind: CiliumL2AnnouncementPolicy\n version: v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n + \ displayName: Cilium L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy + is a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n- kind: CiliumGatewayClassConfig\n + \ version: v2alpha1\n name: ciliumgatewayclassconfigs.cilium.io\n displayName: + Cilium Gateway Class Config\n description: |\n CiliumGatewayClassConfig + defines a configuration for Gateway API GatewayClass.\n" + apiVersion: v2 + appVersion: 1.18.0-pre.0 + created: "2025-03-03T21:20:37.844470429Z" + description: eBPF-based Networking, Security, and Observability + digest: 156903126f0df9f75ceea05c678a038966f32756542a8935f9275d179b31a330 + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.18.0-pre.0.tgz + version: 1.18.0-pre.0 + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumNodeConfig\n version: + v2\n name: ciliumnodeconfigs.cilium.io\n displayName: Cilium Node Configuration\n + \ description: |\n CiliumNodeConfig is a list of configuration key-value + pairs. It is applied to\n nodes indicated by a label selector.\n- kind: + CiliumBGPPeeringPolicy\n version: v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n + \ displayName: Cilium BGP Peering Policy\n description: |\n Cilium BGP + Peering Policy instructs Cilium to create specific BGP peering\n configurations.\n- + kind: CiliumBGPClusterConfig\n version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n + \ displayName: Cilium BGP Cluster Config\n description: |\n Cilium BGP + Cluster Config instructs Cilium operator to create specific BGP cluster\n + \ configurations.\n- kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: + ciliumbgppeerconfigs.cilium.io\n displayName: Cilium BGP Peer Config\n description: + |\n CiliumBGPPeerConfig is a common set of BGP peer configurations. It + can be referenced \n by multiple peers from CiliumBGPClusterConfig.\n- + kind: CiliumBGPAdvertisement\n version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n + \ displayName: Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement + is used to define source of BGP advertisement as well as BGP attributes \n + \ to be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumCIDRGroup\n version: v2alpha1\n name: ciliumcidrgroups.cilium.io\n + \ displayName: Cilium CIDR Group\n description: |\n CiliumCIDRGroup is + a list of CIDRs that can be referenced as a single entity from CiliumNetworkPolicies.\n- + kind: CiliumL2AnnouncementPolicy\n version: v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n + \ displayName: Cilium L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy + is a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.17.2 + created: "2025-03-15T13:57:29.915973514Z" + description: eBPF-based Networking, Security, and Observability + digest: 1fa89da0c6e4f1a5ac54eb1c17ea61150e6cb59476cdf19cd30b8c5f93eae5cb + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.17.2.tgz + version: 1.17.2 + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumNodeConfig\n version: + v2\n name: ciliumnodeconfigs.cilium.io\n displayName: Cilium Node Configuration\n + \ description: |\n CiliumNodeConfig is a list of configuration key-value + pairs. It is applied to\n nodes indicated by a label selector.\n- kind: + CiliumBGPPeeringPolicy\n version: v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n + \ displayName: Cilium BGP Peering Policy\n description: |\n Cilium BGP + Peering Policy instructs Cilium to create specific BGP peering\n configurations.\n- + kind: CiliumBGPClusterConfig\n version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n + \ displayName: Cilium BGP Cluster Config\n description: |\n Cilium BGP + Cluster Config instructs Cilium operator to create specific BGP cluster\n + \ configurations.\n- kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: + ciliumbgppeerconfigs.cilium.io\n displayName: Cilium BGP Peer Config\n description: + |\n CiliumBGPPeerConfig is a common set of BGP peer configurations. It + can be referenced \n by multiple peers from CiliumBGPClusterConfig.\n- + kind: CiliumBGPAdvertisement\n version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n + \ displayName: Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement + is used to define source of BGP advertisement as well as BGP attributes \n + \ to be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumCIDRGroup\n version: v2alpha1\n name: ciliumcidrgroups.cilium.io\n + \ displayName: Cilium CIDR Group\n description: |\n CiliumCIDRGroup is + a list of CIDRs that can be referenced as a single entity from CiliumNetworkPolicies.\n- + kind: CiliumL2AnnouncementPolicy\n version: v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n + \ displayName: Cilium L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy + is a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.17.1 + created: "2025-02-13T09:21:06.335209602Z" + description: eBPF-based Networking, Security, and Observability + digest: 381de4f8f4c5eace677d3426aa8d896ef8d2318c2bf4d1172c9953345b744471 + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.17.1.tgz + version: 1.17.1 + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumBGPPeeringPolicy\n version: + v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium + BGP Peering Policy\n description: |\n Cilium BGP Peering Policy instructs + Cilium to create specific BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n + \ version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n displayName: + Cilium BGP Cluster Config\n description: |\n Cilium BGP Cluster Config + instructs Cilium operator to create specific BGP cluster\n configurations.\n- + kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n + \ displayName: Cilium BGP Peer Config\n description: |\n CiliumBGPPeerConfig + is a common set of BGP peer configurations. It can be referenced \n by + multiple peers from CiliumBGPClusterConfig.\n- kind: CiliumBGPAdvertisement\n + \ version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n displayName: + Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement is + used to define source of BGP advertisement as well as BGP attributes \n to + be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumNodeConfig\n version: v2alpha1\n name: ciliumnodeconfigs.cilium.io\n + \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig + is a list of configuration key-value pairs. It is applied to\n nodes indicated + by a label selector.\n- kind: CiliumCIDRGroup\n version: v2alpha1\n name: + ciliumcidrgroups.cilium.io\n displayName: Cilium CIDR Group\n description: + |\n CiliumCIDRGroup is a list of CIDRs that can be referenced as a single + entity from CiliumNetworkPolicies.\n- kind: CiliumL2AnnouncementPolicy\n version: + v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n displayName: Cilium + L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy is + a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.17.0 + created: "2025-02-04T15:44:02.158877648Z" + description: eBPF-based Networking, Security, and Observability + digest: 72a820bf01bb3e02c01856892a0508da92dfc94174f8705c7bcb5dbb15e228fe + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.17.0.tgz + version: 1.17.0 + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumBGPPeeringPolicy\n version: + v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium + BGP Peering Policy\n description: |\n Cilium BGP Peering Policy instructs + Cilium to create specific BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n + \ version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n displayName: + Cilium BGP Cluster Config\n description: |\n Cilium BGP Cluster Config + instructs Cilium operator to create specific BGP cluster\n configurations.\n- + kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n + \ displayName: Cilium BGP Peer Config\n description: |\n CiliumBGPPeerConfig + is a common set of BGP peer configurations. It can be referenced \n by + multiple peers from CiliumBGPClusterConfig.\n- kind: CiliumBGPAdvertisement\n + \ version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n displayName: + Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement is + used to define source of BGP advertisement as well as BGP attributes \n to + be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumNodeConfig\n version: v2alpha1\n name: ciliumnodeconfigs.cilium.io\n + \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig + is a list of configuration key-value pairs. It is applied to\n nodes indicated + by a label selector.\n- kind: CiliumCIDRGroup\n version: v2alpha1\n name: + ciliumcidrgroups.cilium.io\n displayName: Cilium CIDR Group\n description: + |\n CiliumCIDRGroup is a list of CIDRs that can be referenced as a single + entity from CiliumNetworkPolicies.\n- kind: CiliumL2AnnouncementPolicy\n version: + v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n displayName: Cilium + L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy is + a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.17.0-rc.2 + created: "2025-01-24T16:21:25.188869058Z" + description: eBPF-based Networking, Security, and Observability + digest: 7fccfe9f3977241a5890f2a429b7ac8e4a778edf56d08fd833773c43b4496dbb + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.17.0-rc.2.tgz + version: 1.17.0-rc.2 + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumBGPPeeringPolicy\n version: + v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium + BGP Peering Policy\n description: |\n Cilium BGP Peering Policy instructs + Cilium to create specific BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n + \ version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n displayName: + Cilium BGP Cluster Config\n description: |\n Cilium BGP Cluster Config + instructs Cilium operator to create specific BGP cluster\n configurations.\n- + kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n + \ displayName: Cilium BGP Peer Config\n description: |\n CiliumBGPPeerConfig + is a common set of BGP peer configurations. It can be referenced \n by + multiple peers from CiliumBGPClusterConfig.\n- kind: CiliumBGPAdvertisement\n + \ version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n displayName: + Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement is + used to define source of BGP advertisement as well as BGP attributes \n to + be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumNodeConfig\n version: v2alpha1\n name: ciliumnodeconfigs.cilium.io\n + \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig + is a list of configuration key-value pairs. It is applied to\n nodes indicated + by a label selector.\n- kind: CiliumCIDRGroup\n version: v2alpha1\n name: + ciliumcidrgroups.cilium.io\n displayName: Cilium CIDR Group\n description: + |\n CiliumCIDRGroup is a list of CIDRs that can be referenced as a single + entity from CiliumNetworkPolicies.\n- kind: CiliumL2AnnouncementPolicy\n version: + v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n displayName: Cilium + L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy is + a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.17.0-rc.1 + created: "2025-01-10T22:01:41.151165757Z" + description: eBPF-based Networking, Security, and Observability + digest: a36edb4958505bff7ecb2605050fa8773d194a1ea7846e3bcc7824a9a8f5e987 + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.17.0-rc.1.tgz + version: 1.17.0-rc.1 + - annotations: + artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n + \ displayName: Cilium Network Policy\n description: |\n Cilium Network + Policies provide additional functionality beyond what\n is provided by + standard Kubernetes NetworkPolicy such as the ability\n to allow traffic + based on FQDNs, or to filter at Layer 7.\n- kind: CiliumClusterwideNetworkPolicy\n + \ version: v2\n name: ciliumclusterwidenetworkpolicies.cilium.io\n displayName: + Cilium Clusterwide Network Policy\n description: |\n Cilium Clusterwide + Network Policies support configuring network traffic\n policiies across + the entire cluster, including applying node firewalls.\n- kind: CiliumExternalWorkload\n + \ version: v2\n name: ciliumexternalworkloads.cilium.io\n displayName: Cilium + External Workload\n description: |\n Cilium External Workload supports + configuring the ability for external\n non-Kubernetes workloads to join + the cluster.\n- kind: CiliumLocalRedirectPolicy\n version: v2\n name: ciliumlocalredirectpolicies.cilium.io\n + \ displayName: Cilium Local Redirect Policy\n description: |\n Cilium + Local Redirect Policy allows local redirects to be configured\n within + a node to support use cases like Node-Local DNS or KIAM.\n- kind: CiliumNode\n + \ version: v2\n name: ciliumnodes.cilium.io\n displayName: Cilium Node\n + \ description: |\n Cilium Node represents a node managed by Cilium. It + contains a\n specification to control various node specific configuration + aspects\n and a status section to represent the status of the node.\n- + kind: CiliumIdentity\n version: v2\n name: ciliumidentities.cilium.io\n + \ displayName: Cilium Identity\n description: |\n Cilium Identity allows + introspection into security identities that\n Cilium allocates which identify + sets of labels that are assigned to\n individual endpoints in the cluster.\n- + kind: CiliumEndpoint\n version: v2\n name: ciliumendpoints.cilium.io\n displayName: + Cilium Endpoint\n description: |\n Cilium Endpoint represents the status + of individual pods or nodes in\n the cluster which are managed by Cilium, + including enforcement status,\n IP addressing and whether the networking + is successfully operational.\n- kind: CiliumEndpointSlice\n version: v2alpha1\n + \ name: ciliumendpointslices.cilium.io\n displayName: Cilium Endpoint Slice\n + \ description: |\n Cilium Endpoint Slice represents the status of groups + of pods or nodes\n in the cluster which are managed by Cilium, including + enforcement status,\n IP addressing and whether the networking is successfully + operational.\n- kind: CiliumEgressGatewayPolicy\n version: v2\n name: ciliumegressgatewaypolicies.cilium.io\n + \ displayName: Cilium Egress Gateway Policy\n description: |\n Cilium + Egress Gateway Policy provides control over the way that traffic\n leaves + the cluster and which source addresses to use for that traffic.\n- kind: CiliumClusterwideEnvoyConfig\n + \ version: v2\n name: ciliumclusterwideenvoyconfigs.cilium.io\n displayName: + Cilium Clusterwide Envoy Config\n description: |\n Cilium Clusterwide + Envoy Config specifies Envoy resources and K8s service mappings\n to be + provisioned into Cilium host proxy instances in cluster context.\n- kind: + CiliumEnvoyConfig\n version: v2\n name: ciliumenvoyconfigs.cilium.io\n displayName: + Cilium Envoy Config\n description: |\n Cilium Envoy Config specifies Envoy + resources and K8s service mappings\n to be provisioned into Cilium host + proxy instances in namespace context.\n- kind: CiliumBGPPeeringPolicy\n version: + v2alpha1\n name: ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium + BGP Peering Policy\n description: |\n Cilium BGP Peering Policy instructs + Cilium to create specific BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n + \ version: v2alpha1\n name: ciliumbgpclusterconfigs.cilium.io\n displayName: + Cilium BGP Cluster Config\n description: |\n Cilium BGP Cluster Config + instructs Cilium operator to create specific BGP cluster\n configurations.\n- + kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n + \ displayName: Cilium BGP Peer Config\n description: |\n CiliumBGPPeerConfig + is a common set of BGP peer configurations. It can be referenced \n by + multiple peers from CiliumBGPClusterConfig.\n- kind: CiliumBGPAdvertisement\n + \ version: v2alpha1\n name: ciliumbgpadvertisements.cilium.io\n displayName: + Cilium BGP Advertisement\n description: |\n CiliumBGPAdvertisement is + used to define source of BGP advertisement as well as BGP attributes \n to + be advertised with those prefixes.\n- kind: CiliumBGPNodeConfig\n version: + v2alpha1\n name: ciliumbgpnodeconfigs.cilium.io\n displayName: Cilium BGP + Node Config\n description: |\n CiliumBGPNodeConfig is read only node specific + BGP configuration. It is constructed by Cilium operator.\n It will also + contain node local BGP state information.\n- kind: CiliumBGPNodeConfigOverride\n + \ version: v2alpha1\n name: ciliumbgpnodeconfigoverrides.cilium.io\n displayName: + Cilium BGP Node Config Override\n description: |\n CiliumBGPNodeConfigOverride + can be used to override node specific BGP configuration.\n- kind: CiliumLoadBalancerIPPool\n + \ version: v2alpha1\n name: ciliumloadbalancerippools.cilium.io\n displayName: + Cilium Load Balancer IP Pool\n description: |\n Defining a Cilium Load + Balancer IP Pool instructs Cilium to assign IPs to LoadBalancer Services.\n- + kind: CiliumNodeConfig\n version: v2alpha1\n name: ciliumnodeconfigs.cilium.io\n + \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig + is a list of configuration key-value pairs. It is applied to\n nodes indicated + by a label selector.\n- kind: CiliumCIDRGroup\n version: v2alpha1\n name: + ciliumcidrgroups.cilium.io\n displayName: Cilium CIDR Group\n description: + |\n CiliumCIDRGroup is a list of CIDRs that can be referenced as a single + entity from CiliumNetworkPolicies.\n- kind: CiliumL2AnnouncementPolicy\n version: + v2alpha1\n name: ciliuml2announcementpolicies.cilium.io\n displayName: Cilium + L2 Announcement Policy\n description: |\n CiliumL2AnnouncementPolicy is + a policy which determines which service IPs will be announced to\n the + local area network, by which nodes, and via which interfaces.\n- kind: CiliumPodIPPool\n + \ version: v2alpha1\n name: ciliumpodippools.cilium.io\n displayName: Cilium + Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that + can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" + apiVersion: v2 + appVersion: 1.17.0-rc.0 + created: "2024-12-18T15:38:28.700108392Z" + description: eBPF-based Networking, Security, and Observability + digest: f2930855d7602f1729f52c871d48879d47b86c928dab4d53029876fa96717995 + home: https://cilium.io/ + icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg + keywords: + - BPF + - eBPF + - Kubernetes + - Networking + - Security + - Observability + - Troubleshooting + kubeVersion: '>= 1.21.0-0' + name: cilium + sources: + - https://github.com/cilium/cilium + urls: + - cilium-1.17.0-rc.0.tgz + version: 1.17.0-rc.0 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -86,10 +825,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0 - created: "2025-02-04T15:44:02.158877648Z" + appVersion: 1.17.0-pre.3 + created: "2024-12-02T17:17:27.250000272Z" description: eBPF-based Networking, Security, and Observability - digest: 72a820bf01bb3e02c01856892a0508da92dfc94174f8705c7bcb5dbb15e228fe + digest: 20481d2f5d85ee1b68237aac4210e8e0e1615b037e6ecf3b845fb8bdad254110 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -105,8 +844,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0.tgz - version: 1.17.0 + - cilium-1.17.0-pre.3.tgz + version: 1.17.0-pre.3 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -192,10 +931,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0-rc.2 - created: "2025-01-24T16:21:25.188869058Z" + appVersion: 1.17.0-pre.2 + created: "2024-11-01T22:55:20.834191869Z" description: eBPF-based Networking, Security, and Observability - digest: 7fccfe9f3977241a5890f2a429b7ac8e4a778edf56d08fd833773c43b4496dbb + digest: e51e734bb6e08f34629373dc1a1e6c1bec88a6166083c057b4ace69e4709c3ef home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -211,8 +950,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0-rc.2.tgz - version: 1.17.0-rc.2 + - cilium-1.17.0-pre.2.tgz + version: 1.17.0-pre.2 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -298,10 +1037,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0-rc.1 - created: "2025-01-10T22:01:41.151165757Z" + appVersion: 1.17.0-pre.1 + created: "2024-10-01T08:15:06.105239065Z" description: eBPF-based Networking, Security, and Observability - digest: a36edb4958505bff7ecb2605050fa8773d194a1ea7846e3bcc7824a9a8f5e987 + digest: 414555ed00b250bbaa9edff538d1da68504a557f1c0fd165edca313bfade2d3a home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -317,8 +1056,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0-rc.1.tgz - version: 1.17.0-rc.1 + - cilium-1.17.0-pre.1.tgz + version: 1.17.0-pre.1 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -404,10 +1143,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0-rc.0 - created: "2024-12-18T15:38:28.700108392Z" + appVersion: 1.17.0-pre.0 + created: "2024-09-05T09:21:38.425895279Z" description: eBPF-based Networking, Security, and Observability - digest: f2930855d7602f1729f52c871d48879d47b86c928dab4d53029876fa96717995 + digest: b09c94dfee569ff7426af691ff7e5c5620df6187993f9f29155106160fa8be85 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -423,8 +1162,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0-rc.0.tgz - version: 1.17.0-rc.0 + - cilium-1.17.0-pre.0.tgz + version: 1.17.0-pre.0 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -510,10 +1249,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0-pre.3 - created: "2024-12-02T17:17:27.250000272Z" + appVersion: 1.16.8 + created: "2025-03-15T13:59:35.84623681Z" description: eBPF-based Networking, Security, and Observability - digest: 20481d2f5d85ee1b68237aac4210e8e0e1615b037e6ecf3b845fb8bdad254110 + digest: 4075f908730db69b53c7aec23b5d2f53582e8991b5ebecbd895190391f3baa40 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -529,8 +1268,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0-pre.3.tgz - version: 1.17.0-pre.3 + - cilium-1.16.8.tgz + version: 1.16.8 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -616,10 +1355,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0-pre.2 - created: "2024-11-01T22:55:20.834191869Z" + appVersion: 1.16.7 + created: "2025-02-18T16:41:40.827787438Z" description: eBPF-based Networking, Security, and Observability - digest: e51e734bb6e08f34629373dc1a1e6c1bec88a6166083c057b4ace69e4709c3ef + digest: 9abc7d0b713e496d3b76c7191e06cd13bf425a2a7517c4fb4c353cff2a169336 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -635,8 +1374,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0-pre.2.tgz - version: 1.17.0-pre.2 + - cilium-1.16.7.tgz + version: 1.16.7 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -722,10 +1461,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0-pre.1 - created: "2024-10-01T08:15:06.105239065Z" + appVersion: 1.16.6 + created: "2025-01-22T00:49:12.609546824Z" description: eBPF-based Networking, Security, and Observability - digest: 414555ed00b250bbaa9edff538d1da68504a557f1c0fd165edca313bfade2d3a + digest: 99990b032e98124740138de055a473e5edaa9c5622e6be59b2f6d1733eb943d8 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -741,8 +1480,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0-pre.1.tgz - version: 1.17.0-pre.1 + - cilium-1.16.6.tgz + version: 1.16.6 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -828,10 +1567,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.17.0-pre.0 - created: "2024-09-05T09:21:38.425895279Z" + appVersion: 1.16.5 + created: "2024-12-17T23:57:07.182234567Z" description: eBPF-based Networking, Security, and Observability - digest: b09c94dfee569ff7426af691ff7e5c5620df6187993f9f29155106160fa8be85 + digest: 182035ae7c2cf8d19490ececf618f6a11adc460ed1e7dbd38b23065f02f18b4d home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -847,8 +1586,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.17.0-pre.0.tgz - version: 1.17.0-pre.0 + - cilium-1.16.5.tgz + version: 1.16.5 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -934,10 +1673,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.6 - created: "2025-01-22T00:49:12.609546824Z" + appVersion: 1.16.4 + created: "2024-11-20T09:05:38.752908124Z" description: eBPF-based Networking, Security, and Observability - digest: 99990b032e98124740138de055a473e5edaa9c5622e6be59b2f6d1733eb943d8 + digest: e96a1fba0f361926bb29e6bc2fe565d5fe36be9c5194fad85e8ed2e828d09864 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -953,8 +1692,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.6.tgz - version: 1.16.6 + - cilium-1.16.4.tgz + version: 1.16.4 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1040,10 +1779,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.5 - created: "2024-12-17T23:57:07.182234567Z" + appVersion: 1.16.3 + created: "2024-10-11T23:02:59.494005644Z" description: eBPF-based Networking, Security, and Observability - digest: 182035ae7c2cf8d19490ececf618f6a11adc460ed1e7dbd38b23065f02f18b4d + digest: e1be328218c74bd2bed91f996d8c1b10e785715ce53299a392f79b0cef796805 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1059,8 +1798,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.5.tgz - version: 1.16.5 + - cilium-1.16.3.tgz + version: 1.16.3 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1146,10 +1885,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.4 - created: "2024-11-20T09:05:38.752908124Z" + appVersion: 1.16.2 + created: "2024-09-26T11:51:56.311361Z" description: eBPF-based Networking, Security, and Observability - digest: e96a1fba0f361926bb29e6bc2fe565d5fe36be9c5194fad85e8ed2e828d09864 + digest: 5379083a8c3fe16c5fafe7c02205e9a0a0f51943afa64e172cb719fb17919077 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1165,8 +1904,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.4.tgz - version: 1.16.4 + - cilium-1.16.2.tgz + version: 1.16.2 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1252,10 +1991,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.3 - created: "2024-10-11T23:02:59.494005644Z" + appVersion: 1.16.1 + created: "2024-08-14T12:57:36.976823113Z" description: eBPF-based Networking, Security, and Observability - digest: e1be328218c74bd2bed91f996d8c1b10e785715ce53299a392f79b0cef796805 + digest: 406c5bba515262c52e53b859af31af412cd8d2c332e277e98ec3e5f14382ecbf home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1271,8 +2010,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.3.tgz - version: 1.16.3 + - cilium-1.16.1.tgz + version: 1.16.1 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1358,10 +2097,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.2 - created: "2024-09-26T11:51:56.311361Z" + appVersion: 1.16.0 + created: "2024-07-24T15:00:46.978038359Z" description: eBPF-based Networking, Security, and Observability - digest: 5379083a8c3fe16c5fafe7c02205e9a0a0f51943afa64e172cb719fb17919077 + digest: 2d653f4826722da976791047f7f3d9e999526590ea4df2f36a3846aedbffae2d home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1377,8 +2116,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.2.tgz - version: 1.16.2 + - cilium-1.16.0.tgz + version: 1.16.0 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1464,10 +2203,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.1 - created: "2024-08-14T12:57:36.976823113Z" + appVersion: 1.16.0-rc.2 + created: "2024-07-15T22:46:03.276445381Z" description: eBPF-based Networking, Security, and Observability - digest: 406c5bba515262c52e53b859af31af412cd8d2c332e277e98ec3e5f14382ecbf + digest: 2ef4401a1ced8966aa1388cabacf9e127538d113399b14d66f1fb726ac6210a9 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1483,8 +2222,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.1.tgz - version: 1.16.1 + - cilium-1.16.0-rc.2.tgz + version: 1.16.0-rc.2 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1570,10 +2309,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0 - created: "2024-07-24T15:00:46.978038359Z" + appVersion: 1.16.0-rc.1 + created: "2024-06-28T22:27:40.613256035Z" description: eBPF-based Networking, Security, and Observability - digest: 2d653f4826722da976791047f7f3d9e999526590ea4df2f36a3846aedbffae2d + digest: 81759b91f03f0cbda6b7d81077f69ecaf9c92408c5aa6ef94291287c8995aac5 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1589,8 +2328,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0.tgz - version: 1.16.0 + - cilium-1.16.0-rc.1.tgz + version: 1.16.0-rc.1 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1676,10 +2415,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-rc.2 - created: "2024-07-15T22:46:03.276445381Z" + appVersion: 1.16.0-rc.0 + created: "2024-06-17T19:48:16.546067407Z" description: eBPF-based Networking, Security, and Observability - digest: 2ef4401a1ced8966aa1388cabacf9e127538d113399b14d66f1fb726ac6210a9 + digest: 779b4714b0184b9f4936f3eed323446e5c2b100f6f69e30a90a147760238f635 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1695,8 +2434,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-rc.2.tgz - version: 1.16.0-rc.2 + - cilium-1.16.0-rc.0.tgz + version: 1.16.0-rc.0 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1782,10 +2521,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-rc.1 - created: "2024-06-28T22:27:40.613256035Z" + appVersion: 1.16.0-pre.3 + created: "2024-06-03T23:06:37.960751658Z" description: eBPF-based Networking, Security, and Observability - digest: 81759b91f03f0cbda6b7d81077f69ecaf9c92408c5aa6ef94291287c8995aac5 + digest: 0ac735de66666556bf59c3bb42efee57b6b29a8256cdd11ce85fd77ec85e9beb home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1801,8 +2540,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-rc.1.tgz - version: 1.16.0-rc.1 + - cilium-1.16.0-pre.3.tgz + version: 1.16.0-pre.3 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1888,10 +2627,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-rc.0 - created: "2024-06-17T19:48:16.546067407Z" + appVersion: 1.16.0-pre.2 + created: "2024-05-03T00:03:03.380234662Z" description: eBPF-based Networking, Security, and Observability - digest: 779b4714b0184b9f4936f3eed323446e5c2b100f6f69e30a90a147760238f635 + digest: 9b78652906c1984675d981fa11bc640eb8e888155331720d062acff86425ad39 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -1907,8 +2646,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-rc.0.tgz - version: 1.16.0-rc.0 + - cilium-1.16.0-pre.2.tgz + version: 1.16.0-pre.2 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -1994,10 +2733,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-pre.3 - created: "2024-06-03T23:06:37.960751658Z" + appVersion: 1.16.0-pre.1 + created: "2024-04-02T20:02:25-07:00" description: eBPF-based Networking, Security, and Observability - digest: 0ac735de66666556bf59c3bb42efee57b6b29a8256cdd11ce85fd77ec85e9beb + digest: 646df1ba01ddd9262dab5f38b7ed2bccd509af6418889245bc101e4d481db352 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -2013,8 +2752,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-pre.3.tgz - version: 1.16.0-pre.3 + - cilium-1.16.0-pre.1.tgz + version: 1.16.0-pre.1 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -2100,10 +2839,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-pre.2 - created: "2024-05-03T00:03:03.380234662Z" + appVersion: 1.16.0-pre.0 + created: "2024-03-04T13:27:22+01:00" description: eBPF-based Networking, Security, and Observability - digest: 9b78652906c1984675d981fa11bc640eb8e888155331720d062acff86425ad39 + digest: 4a02367277a1d32d68f45f6fc2c29be6fa22397f1b99cd72a6be5aacf2c78a04 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -2114,13 +2853,13 @@ entries: - Security - Observability - Troubleshooting - kubeVersion: '>= 1.21.0-0' + kubeVersion: '>= 1.16.0-0' name: cilium sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-pre.2.tgz - version: 1.16.0-pre.2 + - cilium-1.16.0-pre.0.tgz + version: 1.16.0-pre.0 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -2206,10 +2945,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-pre.1 - created: "2024-04-02T20:02:25-07:00" + appVersion: 1.16.0-dev + created: "2024-04-11T17:15:14-07:00" description: eBPF-based Networking, Security, and Observability - digest: 646df1ba01ddd9262dab5f38b7ed2bccd509af6418889245bc101e4d481db352 + digest: ecb2db5c7e22529676bc8a204118f971a413853b22b31d91bf32f7946d75799e home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -2220,13 +2959,13 @@ entries: - Security - Observability - Troubleshooting - kubeVersion: '>= 1.21.0-0' + kubeVersion: '>= 1.16.0-0' name: cilium sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-pre.1.tgz - version: 1.16.0-pre.1 + - cilium-1.16.0-dev.tgz + version: 1.16.0-dev - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -2312,10 +3051,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-pre.0 - created: "2024-03-04T13:27:22+01:00" + appVersion: 1.15.15 + created: "2025-03-15T09:18:16.180522717Z" description: eBPF-based Networking, Security, and Observability - digest: 4a02367277a1d32d68f45f6fc2c29be6fa22397f1b99cd72a6be5aacf2c78a04 + digest: c19c53cef793fad0850a59482246f3c52feda89c9f21663848bfb5a0be5d80d6 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -2331,8 +3070,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-pre.0.tgz - version: 1.16.0-pre.0 + - cilium-1.15.15.tgz + version: 1.15.15 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -2418,10 +3157,10 @@ entries: Pod IP Pool\n description: |\n CiliumPodIPPool defines an IP pool that can be used for pooled IPAM (i.e. the multi-pool IPAM mode).\n" apiVersion: v2 - appVersion: 1.16.0-dev - created: "2024-04-11T17:15:14-07:00" + appVersion: 1.15.14 + created: "2025-02-18T15:59:45.53415629Z" description: eBPF-based Networking, Security, and Observability - digest: ecb2db5c7e22529676bc8a204118f971a413853b22b31d91bf32f7946d75799e + digest: 7bce296b74e5508022cf37d9f823a00df2fd18951fddff41972efea00d6693d2 home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg keywords: @@ -2437,8 +3176,8 @@ entries: sources: - https://github.com/cilium/cilium urls: - - cilium-1.16.0-dev.tgz - version: 1.16.0-dev + - cilium-1.15.14.tgz + version: 1.15.14 - annotations: artifacthub.io/crds: "- kind: CiliumNetworkPolicy\n version: v2\n name: ciliumnetworkpolicies.cilium.io\n \ displayName: Cilium Network Policy\n description: |\n Cilium Network @@ -22281,4 +23020,4 @@ entries: urls: - tetragon-0.8.0.tgz version: 0.8.0 -generated: "2025-02-04T15:44:02.149628206Z" +generated: "2025-03-15T13:59:35.838764761Z" diff --git a/vendor/github.com/cilium/cilium/.authors.aux b/vendor/github.com/cilium/cilium/.authors.aux deleted file mode 100644 index ece4ffc5ab..0000000000 --- a/vendor/github.com/cilium/cilium/.authors.aux +++ /dev/null @@ -1,9 +0,0 @@ - -The following additional people are mentioned in commit logs as having provided -helpful bug reports, suggestions or have otherwise provided value to the -project: - -Brenden Blanco bblanco@plumgrid.com -Jakub Kicinski jakub.kicinski@netronome.com -Salvatore Orlando salv.orlando@gmail.com -Tomás Senart tsenart@gmail.com diff --git a/vendor/github.com/cilium/cilium/.clang-format b/vendor/github.com/cilium/cilium/.clang-format deleted file mode 100644 index c41e4c1d98..0000000000 --- a/vendor/github.com/cilium/cilium/.clang-format +++ /dev/null @@ -1,180 +0,0 @@ -# Configuration file for clang-format. -# Intended for clang-format >= 15. -# -# The list and meaning of the options is available at: -# -# https://clang.llvm.org/docs/ClangFormatStyleOptions.html ---- -# BasedOnStyle # No base style in use -# AccessModifierOffset # We don't use access modifiers -AlignAfterOpenBracket: Align -AlignArrayOfStructures: Left -AlignConsecutiveAssignments: false -AlignConsecutiveBitFields: - Enabled: true - AcrossEmptyLines: true - AcrossComments: true -AlignConsecutiveDeclarations: false -AlignConsecutiveMacros: - Enabled: true - AcrossEmptyLines: true - AcrossComments: true -AlignEscapedNewlines: Left -AlignOperands: true -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: false -# AllowAllConstructorInitializersOnNextLine # Deprecated -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortEnumsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Never -# AllowShortLambdasOnASingleLine # We don't use lambdas -AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterDefinitionReturnType # Deprecated -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations # We don't use templates -# AttributeMacros # Unused at this time -BinPackArguments: true -BinPackParameters: true -BitFieldColonSpacing: None -BraceWrapping: - AfterCaseLabel: true - # AfterClass # We don't use classes - AfterControlStatement: Never - AfterEnum: false - AfterFunction: true - # AfterNamespace # We don't use namespaces - # AfterObjCDeclaration # We don't use ObjC - AfterStruct: false - AfterUnion: false - AfterExternBlock: false - # BeforeCatch # We don't use try/catch - BeforeElse: false - # BeforeLambdaBody # We don't use lambdas - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - # SplitEmptyNamespace # We don't use namespaces -# BreakAfterJavaFieldAnnotations # We don't use Java -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Custom -# BreakBeforeConceptDeclarations # We don't use concepts -BreakBeforeTernaryOperators: false -# BreakConstructorInitializers # We don't use constructors -# BreakInheritanceList # We don't use inheritance -BreakStringLiterals: false -ColumnLimit: 80 -# CommentPragmas # Unused at this time -# CompactNamespaces # We don't use namespaces -# ConstructorInitializerAllOnOneLineOrOnePerLine # Deprecated -# ConstructorInitializerIndentWidth # We don't use constructors -ContinuationIndentWidth: 8 -Cpp11BracedListStyle: false -# DeriveLineEnding # Deprecated -DerivePointerAlignment: false -DisableFormat: false -# EmptyLineAfterAccessModifier # We don't use access modifiers -# EmptyLineBeforeAccessModifier # We don't use access modifiers -# ExperimentalAutoDetectBinPacking # Experimental, "Use at your own risk" -# FixNamespaceComments # We don't use namespaces -# ForEachMacros # Unused at this time -# IfMacros # Unused at this time -IncludeBlocks: Preserve -# IncludeCategories # Unused at this time -# IncludeIsMainRegex # Unused at this time -# IncludeIsMainSourceRegex # Unused at this time -# IndentAccessModifiers # We don't use access modifiers -IndentCaseBlocks: false -IndentCaseLabels: false -# IndentExternBlock # We don't use extern blocks -IndentGotoLabels: false -IndentPPDirectives: AfterHash -# IndentRequiresClause # We don't use equire clauses -IndentWidth: 8 -IndentWrappedFunctionNames: false -InsertBraces: false -# InsertTrailingCommas # We don't use JavaScript -# JavaImportGroups # We don't use Java -# JavaScriptQuotes # We don't use JavaScript -# JavaScriptWrapImports # We don't use JavaScript -KeepEmptyLinesAtTheStartOfBlocks: false -# LambdaBodyIndentation # We don't use lambdas -Language: Cpp -# MacroBlockBegin # Unused at this time -# MacroBlockEnd # Unused at this time -MaxEmptyLinesToKeep: 1 -# NamespaceIndentation # We don't use namespaces -# NamespaceMacros # We don't use namespaces -# ObjCBinPackProtocolList # We don't use ObjC -# ObjCBlockIndentWidth # We don't use ObjC -# ObjCBreakBeforeNestedBlockParam # We don't use ObjC -# ObjCSpaceAfterProperty # We don't use ObjC -# ObjCSpaceBeforeProtocolList # We don't use ObjC -PPIndentWidth: 1 -# PackConstructorInitializers # We don't use constructors - -# Penalties decide in what order (weighting) things should be done if a line is -# too long: 100 = try everything else before this. -# See https://stackoverflow.com/a/46749925 -PenaltyBreakAssignment: 10 -PenaltyBreakBeforeFirstCallParameter: 0 -PenaltyBreakComment: 0 -PenaltyBreakFirstLessLess: 0 -PenaltyBreakOpenParenthesis: 100 -PenaltyBreakString: 10 -# PenaltyBreakTemplateDeclaration # We don't use templates -PenaltyExcessCharacter: 100 -PenaltyIndentedWhitespace: 100 -PenaltyReturnTypeOnItsOwnLine: 100 - -PointerAlignment: Right -QualifierAlignment: Leave -# QualifierOrder # Unused at this time -# RawStringFormats # Unused at this time -# ReferenceAlignment # We don't use references -ReflowComments: false -RemoveBracesLLVM: false -# RequiresClausePosition # We don't use require clauses -SeparateDefinitionBlocks: Leave -# ShortNamespaceLines # We don't use namespaces -SortIncludes: Never -# SortJavaStaticImport # We don't use Java -# SortUsingDeclarations # We don't use using declarations -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -# SpaceAfterTemplateKeyword # We don't use templates -SpaceAroundPointerQualifiers: Default -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -# SpaceBeforeCpp11BracedList # We don't use C++11 braced lists to initialize objects -# SpaceBeforeCtorInitializerColon # We don't use constructors -# SpaceBeforeInheritanceColon # We don't use inheritance -SpaceBeforeParens: ControlStatements -# SpaceBeforeParensOptions # No need for custom SpaceBeforeParens options -# SpaceBeforeRangeBasedForLoopColon # We don't use range-based for loops -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -# SpacesInAngles # We don't use templates -SpacesInCStyleCastParentheses: false -SpacesInConditionalStatement: false -SpacesInContainerLiterals: false -SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: 1 -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: C++03 -# StatementAttributeLikeMacros # Unused at this time -# StatementMacros # Unused at this time -TabWidth: 8 -# TypenameMacros # Unused at this time -# UseCRLF # Deprecated -UseTab: Always -# WhitespaceSensitiveMacros # Unused at this time -... diff --git a/vendor/github.com/cilium/cilium/.clomonitor.yml b/vendor/github.com/cilium/cilium/.clomonitor.yml deleted file mode 100644 index a5b76a6b13..0000000000 --- a/vendor/github.com/cilium/cilium/.clomonitor.yml +++ /dev/null @@ -1,22 +0,0 @@ -# CLOMonitor metadata file - -exemptions: - - check: slack_presence - reason: "The Cilium slack community can be found at https://slack.cilium.io" # Justification of this exemption - - - check: dangerous_workflow - reason: > - "It is safe to run code checkout '${{ github.event.pull_request.head.sha }}' - and 'github.event.pull_request.head.ref' in .github/workflows/build-images-base.yaml - as this workflow is only permitted to be executed after an explicit approval of a - subset of committers." - - - check: signed_releases - reason: > - "All Cilium release images are cryptographically signed during build by cosign. - Images are hosted in Quay. OpenSSF Scorecard check is currently limited to repositories - hosted on GitHub, and does not support other source hosting repositories." - - - check: token_permissions - reason: > - "Reason to use every non-read-only token in GitHub workflows is commented in the respective workflow files." diff --git a/vendor/github.com/cilium/cilium/.gitattributes b/vendor/github.com/cilium/cilium/.gitattributes deleted file mode 100644 index f2a9481120..0000000000 --- a/vendor/github.com/cilium/cilium/.gitattributes +++ /dev/null @@ -1,18 +0,0 @@ -/install/kubernetes/cilium/values.yaml.tmpl linguist-language=yml -/install/kubernetes/cilium/values.yaml linguist-generated -/install/kubernetes/cilium/README.md linguist-generated -go.sum linguist-generated -examples/kubernetes/connectivity-check/connectivity-*.yaml linguist-generated -pkg/k8s/apis/cilium.io/v2/client/crds/*.yaml linguist-generated -test/controlplane/**/v1.[0-9][0-9]/*.yaml linguist-generated -test/controlplane/services/graceful-termination/*.yaml linguist-generated -Documentation/cmdref/** linguist-generated -Documentation/crdlist.rst linguist-generated -Documentation/helm-values.rst linguist-generated -Documentation/codeowners.rst linguist-generated -Documentation/_static/* -diff -*svg -diff -pkg/k8s/client/clientset/** linguist-generated -pkg/k8s/client/informers/** linguist-generated -pkg/k8s/client/listers/** linguist-generated -*.bt linguist-language=D diff --git a/vendor/github.com/cilium/cilium/.gitignore b/vendor/github.com/cilium/cilium/.gitignore deleted file mode 100644 index f12f401e63..0000000000 --- a/vendor/github.com/cilium/cilium/.gitignore +++ /dev/null @@ -1,118 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so -*.so.* -*.d - -# LLVM IR files -*.ll -*.ll-* - -# Folders -_obj -_test -_build/ - -# Architecture specific extensions/prefixes -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - -*.swn -*.swp -.vagrant -vagrant.kubeconfig -coverage.out -coverage-all.out -coverage-all.html -coverage-all-tmp.out -bpf-coverage.html -bpf-coverage.cover - -.DS_Store -.idea/ -.vscode/* -!.vscode/launch.json -!.vscode/extensions.json -*.plist - -*_bash_completion -*.swo -outgoing - -*cscope.files -*cscope.out -*cscope.in.out -*cscope.po.out -*tags -.gdb_history -compile_commands.json - -man/ - -test/envoy/cilium-files -test/test_results* -test/.vagrant -test/tmp.yaml -test/*_manifest.yaml -test/*.xml -test/*.json -test/*.log -test/cilium-[0-9a-f]*.yaml -test/*tmp -test/cilium-istioctl - -# Testdata, includes generated .o -!**/testdata/* - -# Updates E2E Test -old-charts/ - -# generated test files -test/k8s/manifests/cnp-second-namespaces.yaml -test/cilium.conf.ginkgo - -# Emacs backup files -*~ - -# generated from make targets -*.ok -*.build_all -LICENSE.all - -# Temporary files that allow build containers/VMs work without git -# Not to be ignored by docker. -GIT_VERSION - -# The following files get created during image builds -.buildx -.buildx_builder - -# Local developer config to be executed in the dev VM and CI VMs started locally -.devvmrc - -# Generated dockerignore files -images/*/Dockerfile.dockerignore - -# Local Emacs files -.dir-locals.el - -# Clangd cache for indexed bpf code -bpf/.cache -.cache - -# Include dummy bpf object necessary for XDP_TX -!test/bpf/xdp.o - -# Files used for direnv -.direnv -.envrc diff --git a/vendor/github.com/cilium/cilium/.golangci.yaml b/vendor/github.com/cilium/cilium/.golangci.yaml deleted file mode 100644 index d674a83757..0000000000 --- a/vendor/github.com/cilium/cilium/.golangci.yaml +++ /dev/null @@ -1,228 +0,0 @@ -# options for analysis running -run: - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 20m - - # exit code when at least one issue was found, default is 1 - issues-exit-code: 1 - - # include test files or not, default is true - tests: true - - # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": - # If invoked with -mod=readonly, the go command is disallowed from the implicit - # automatic updating of go.mod described above. Instead, it fails when any changes - # to go.mod are needed. This setting is most useful to check that go.mod does - # not need updates, such as in a continuous integration and testing system. - # If invoked with -mod=vendor, the go command assumes that the vendor - # directory holds the correct copies of dependencies and ignores - # the dependency descriptions in go.mod. - modules-download-mode: readonly - -# all available settings of specific linters -linters-settings: - depguard: - rules: - main: - deny: - - pkg: "math/rand$" - desc: "Use math/rand/v2 instead" - exhaustruct: - # Ensure that command-line flags are explicitly default-initialized. - include: - - '.+\.[Cc]onfig' - - '.+[Cc]fg' - exclude: - - '.+cache\.Config' # k8s - - '.+fqdn\.Config' # internal API - - '.+tls\.Config' # Go TLS - - '.+v3\.Config' # etcd - - '.+translation\.Config' # internal gateway-api config - govet: - enable: - - nilness - goimports: - local-prefixes: github.com/cilium/cilium/ - goheader: - values: - regexp: - PROJECT: 'Cilium|Hubble' - template: |- - SPDX-License-Identifier: Apache-2.0 - Copyright Authors of {{ PROJECT }} - gosec: - includes: - - G402 - gomodguard: - blocked: - modules: - - github.com/miekg/dns: - recommendations: - - github.com/cilium/dns - reason: "use the cilium fork directly to avoid replace directives in go.mod, see https://github.com/cilium/cilium/pull/27582" - - gopkg.in/check.v1: - recommendations: - - testing - - github.com/stretchr/testify/assert - reason: "gocheck has been deprecated, see https://github.com/cilium/cilium/issues/28596" - - github.com/cilium/checkmate: - recommendations: - - github.com/stretchr/testify/assert - - github.com/stretchr/testify/require - reason: "cilium/checkmate has been deprecated, see https://github.com/cilium/cilium/issues/28596" - - go.uber.org/multierr: - recommendations: - - errors - reason: "Go 1.20+ has support for combining multiple errors, see https://go.dev/doc/go1.20#errors" - - golang.org/x/exp/maps: - recommendations: - - maps - - slices - reason: "Go 1.23+ has support for maps and slices, see https://go.dev/doc/go1.23#iterators" - - golang.org/x/exp/constraints: - recommendations: - - cmp - reason: "Go 1.21+ has support for Ordered constraint, see https://go.dev/doc/go1.21#cmp" - - golang.org/x/exp/slices: - recommendations: - - slices - reason: "Go 1.21+ provides many common operations for slices using generic functions, see https://go.dev/doc/go1.21#slices" - - k8s.io/utils/pointer: - recommendations: - - k8s.io/utils/ptr - reason: "k8s.io/utils/pointer is deprecated, see https://pkg.go.dev/k8s.io/utils/pointer" - - stylecheck: - checks: ["ST1019"] - - sloglint: - # Enforce not mixing key-value pairs and attributes. - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-mixed-arguments - # Default: true - no-mixed-args: true - # Enforce using key-value pairs only (overrides no-mixed-args, incompatible with attr-only). - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#key-value-pairs-only - # Default: false - kv-only: true - # Enforce using attributes only (overrides no-mixed-args, incompatible with kv-only). - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#attributes-only - # Default: false - attr-only: false - # Enforce not using global loggers. - # Values: - # - "": disabled - # - "all": report all global loggers - # - "default": report only the default slog logger - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-global - # Default: "" - no-global: "default" - # Enforce using methods that accept a context. - # Values: - # - "": disabled - # - "all": report all contextless calls - # - "scope": report only if a context exists in the scope of the outermost function - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#context-only - # Default: "" - context: "" - # Enforce using static values for log messages. - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#static-messages - # Default: false - static-msg: false - # Enforce using constants instead of raw keys. - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-raw-keys - # Default: false - no-raw-keys: true - # Enforce a single key naming convention. - # Values: snake, kebab, camel, pascal - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#key-naming-convention - # Default: "" - key-naming-case: camel - # Enforce not using specific keys. - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#forbidden-keys - # Default: [] - forbidden-keys: - - time - - level - - msg - - source - # Enforce putting arguments on separate lines. - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#arguments-on-separate-lines - # Default: false - args-on-sep-lines: true - - testifylint: - enable-all: true - disable: # TODO: remove each disabled rule and fix it - - float-compare - - go-require - - require-error - -issues: - exclude-dirs-use-default: true - - # Excluding configuration per-path, per-linter, per-text and per-source - exclude-rules: - - linters: [staticcheck] - text: "SA1019" # this is rule for deprecated method - - linters: [staticcheck] - text: "SA9003: empty branch" - - linters: [staticcheck] - text: "SA2001: empty critical section" - - linters: [err113] - text: "do not define dynamic errors, use wrapped static errors instead" # This rule to avoid opinionated check fmt.Errorf("text") - # Skip goimports check on generated files - - path: \\.(generated\\.deepcopy|pb)\\.go$ - linters: - - goimports - # Skip goheader check in the example files as these are included in the - # documentation. - - path: "contrib/examples/.+\\.go" - linters: - - goheader - # Skip goheader check on files imported and modified from upstream k8s - - path: "pkg/ipam/(cidrset|service)/.+\\.go" - linters: - - goheader - - path: "pkg/hubble/dropeventemitter/fake_recorder.go" - linters: - - goheader - - - path: "tools/.*.go" - linters: - - sloglint - -linters: - disable-all: true - enable: - - depguard - - errorlint - - err113 - - exhaustruct - - gofmt - - goimports - - govet - - ineffassign - - misspell - - sloglint - - staticcheck - - stylecheck - - testifylint - - unused - - goheader - - gosec - - gomodguard - - gosimple - -# To enable later if makes sense -# - deadcode -# - errcheck -# - gocyclo -# - golint -# - gosec -# - gosimple -# - lll -# - maligned -# - misspell -# - prealloc -# - structcheck -# - typecheck diff --git a/vendor/github.com/cilium/cilium/.mailmap b/vendor/github.com/cilium/cilium/.mailmap deleted file mode 100644 index 86e2de81b3..0000000000 --- a/vendor/github.com/cilium/cilium/.mailmap +++ /dev/null @@ -1,170 +0,0 @@ -Àbéjídé Àyodélé -Adam Korcz -Adam Bocim -Alexei Starovoitov -Alex Waring -Alkama Hasan -André Martins -Andrew Sy Kim -Andrew Li -Anthony Rabbito -Arika Chen -Arthur Chiao -Arthur Evstifeev -Arthur Evstifeev -Arvind Soni -Ashwin Paranjpe -Ashwin Paranjpe -Augustas Berneckas -Barun Acharya -Barun Acharya -Bingshen Wang -Bingwu Yang -Bob Bouteillier -Bruno Miguel Custódio -Carlos Andrés Rocha -Changyu Wang -Charles-Henri Guérin -chenyahui -Chen Kang -Chen Yaqi -Chen Yaqi -Christine Chen -Christopher Biscardi -Claudia J. Kang -Craig Box -Dan Wendlandt -Daniel Qian -Dario Mader <9934402+darox@users.noreply.github.com> -Dario Mader -Darren Mackintosh -Darshan Chaudhary -David Chen -David Cheng -David Chosrova David CHOSROVA -Dawn -Devarshi Sathiya -Divine Odazie -Divya Mohan -Dmitriy Zinin -El-Fadel Bonfoh -Emin Aktas -Fankaixi Li -Felix Färjsjö -fengshunli <1171313930@qq.com> -Fernand Galiana -Florian Koch -François Joulaud <48206448+joulaud@users.noreply.github.com> -Gaurav Genani -Gaurav Yadav -George Kontridze -Gray Liang -Gowtham Sundara -huangxuesen -HaoTian Qi -Hart Hoover -Hui Kong -Ian Vernon -Ifeanyi Ubah -Ivan Makarychev -Jarno Rajahalme -Jarno Rajahalme -James Bodkin -James McShane -Jed Salazar -Jerry J. Muzsik -Jim Ntosas -Jomen Xiao -Jonathan Davies -Jones Shi -Joshua Roppo -Jun Chen -Jussi Maki -Junli Ou -Kamil Lach -Kaito Ii -Karl Heins -Kevin Holditch <82885135+kevholditch-f3@users.noreply.github.com> -Bokang Li -Li Cheng -Lior Rozen -Liu Qun -Livingstone S E -LongHui Li -LongHui Li -Louis DeLosSantos -Madhu Challa -Mahadev Panchal -Mandar U Jog -Marc Stulz -Marcel Zięba Marcel Zieba -Marcel Zięba Marcel Zieba -Matthew Gumport -Maxime Visonneau -Michael Kashin -Michael Vorburger -Neela Jacques <68304471+Neelajacques@users.noreply.github.com> -Oksana Baranova -Oliver Hofmann <91730056+olinux-dev@users.noreply.github.com> -Ondrej Blazek -Parth Patel -Peiqi Shi -Pengfei Song -Philippe Lafoucrière -Pierre-Yves Aillet -Pratyush Singhal -Qifeng Guo -Quentin Monnet -Raam -Rachid Zarouali -Raphael Campos -Rei Shimizu -renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> -Roman Ptitcyn -Sachin Maurya -Sadik Kuzu -Salvatore Mazzarino -Sami Yessou -Sander Timmerman -Sarah Corleissen -Sean Winn -Sebastien Thomas -Sergey Generalov -Simon Felding <45149055+simonfelding@users.noreply.github.com> -Steven Shuang -Tam Mach -Thomas Graf -Tobias Mose -Tobias Mose -Tom Hadlaw -Tomoki Sugiura -Tomoki Sugiura -Tony Lu -Trevor Tao -Vance Li -Vance Li vanceli -Viktor Kurchenko viktor-kurchenko -Viktor Kurchenko viktor-kurchenko <69600804+viktor-kurchenko@users.noreply.github.com> -Ville Ojamo <14869000+bluikko@users.noreply.github.com> -Vlad Ungureanu -Vipul Singh -Vipul Singh -Wang Dong > -Wayne Haber <41373231+whaber@users.noreply.github.com> -Wei Yang <31728060+yulng@users.noreply.github.com> -Weilong Cui -Weizhou Lan -Wenhu Wang -Wongyu Lee -Will Stewart -Yiannis Yiakoumis -Youssef Azrak -Yoyo Wu -Yugo Kobayashi -Yurii Dzobak -Yurii Komar -Yves Blusseau -Xiaoqing -Xiaoyang Zhu -Xin Li -Zhu Yan diff --git a/vendor/github.com/cilium/cilium/CODEOWNERS b/vendor/github.com/cilium/cilium/CODEOWNERS deleted file mode 100644 index 58f1eff22c..0000000000 --- a/vendor/github.com/cilium/cilium/CODEOWNERS +++ /dev/null @@ -1,677 +0,0 @@ -# Code owners are used by the Cilium community to consolidate common knowledge -# into teams that can provide consistent and actionable feedback to -# contributors. This section will describe groups of teams and suggestions -# about the focus areas for review. -# -# The primary motivation for these teams is to provide structure around review -# processes to ensure that contributors know how to reach out to community -# members to conduct discussions, ensure contributions meet the expectations of -# the community, and align on the direction of proposed changes. Furthermore, -# while these teams are primarily drawn upon to provide review on specific pull -# requests, they are also encouraged to self-organize around how to make -# improvements to their areas of the Cilium project over time. -# -# Any committer may self-nominate to code owner teams. Reach out to the core -# team on the #committers channel in Slack to coordinate. Committers do not -# require expert knowledge in an area in order to join a code owner team, -# only a willingness to engage in discussions and learn about the area. -# -# Project-wide -# ++++++++++++ -# -# These code owners may provide feedback for Pull Requests submitted to any -# repository in the Cilium project: -# -# - @cilium/api: -# Ensure the backwards-compatibility of Cilium REST and gRPC APIs, excluding -# Hubble which is owned by @cilium/sig-hubble-api. -# - @cilium/build: -# Provide feedback on languages and scripting used for build and packaging -# system: Make, Shell, Docker. -# - @cilium/cli: -# Provide user experience feedback on changes to Command-Line Interfaces. -# These owners are a stand-in for the user community to bring a user -# perspective to the review process. Consider how information is presented, -# consistency of flags and options. -# - @cilium/ci-structure: -# Provide guidance around the best use of Cilium project continuous -# integration and testing infrastructure, including GitHub actions, VM -# helpers, testing frameworks, etc. -# - @cilium/community: -# Maintain files that refer to Cilium community users such as USERS.md. -# - @cilium/contributing: -# Encourage practices that ensure an inclusive contributor community. Review -# tooling and scripts used by contributors. -# - @cilium/docs-structure: -# Ensure the consistency and layout of documentation. General feedback on the -# use of Sphinx, how to communicate content clearly to the community. This -# code owner is not expected to validate the technical correctness of -# submissions. Correctness is typically handled by another code owner group -# which is also assigned to any given piece of documentation. -# - @cilium/sig-foundations: -# Review changes to the core libraries and provide guidance to overall -# software architecture. -# - @cilium/github-sec: -# Responsible for maintaining the security of repositories in the Cilium -# project by maintaining best practices for workflow usage, for instance -# preventing malicious use of GitHub actions. -# - @cilium/helm: -# Provide input on the way that Helm can be used to configure features. These -# owners are a stand-in for the user community to bring a user perspective to -# the review process. Ensure that Helm changes are defined in manners that -# will be forward-compatible for upgrade and follow best practices for -# deployment (for example, being GitOps-friendly). -# - @cilium/sig-hubble-api: -# Review Hubble API changes related to gRPC endpoints. -# The team ensures that API changes are backward -# compatible or that a new API version is created for backward incompatible -# changes. -# - @cilium/metrics: -# Provide recommendations about the types, names and labels for metrics to -# follow best practices. This includes considering the cardinality impact of -# metrics being added or extended. -# - @cilium/release-managers: -# Review files related to releases like AUTHORS and VERSION. -# - @cilium/security: -# Provide feedback on changes that could have security implications for Cilium, -# and maintain security-related documentation. -# - @cilium/vendor: -# Review vendor updates for software dependencies to check for any potential -# upstream breakages / incompatibilities. Discourage the use of unofficial -# forks of upstream libraries if they are actively maintained. -# -# Repository Owners -# +++++++++++++++++ -# -# The following code owners are responsible for a range of general feedback for -# contributions to specific repositories: -# -# - @cilium/sig-hubble: -# Review all Cilium and Hubble code related to observing system events, -# exporting those via gRPC protocols outside the node and outside the -# cluster. those event channels, for example via TLS. -# - @cilium/hubble-metrics: -# Review code related to Hubble metrics, ensure changes in exposed metrics are -# consistent and not breaking without careful consideration. -# - @cilium/hubble-ui: -# Maintain the Hubble UI graphical interface. -# - @cilium/tetragon: -# Review of all Tetragon code, both for Go and C (for eBPF). -# -# The teams above are responsible for reviewing the majority of contributions -# to the corresponding repositories. Additionally, there are "maintainer" teams -# listed below which may not be responsible for overall code review for a -# repository, but they have administrator access to the repositories and so -# they can assist with configuring GitHub repository settings, secrets, and -# related processes. For the full codeowners for individual repositories, see -# the CODEOWNERS file in the corresponding repository. -# -# - @cilium/cilium-cli-maintainers -# - @cilium/cilium-maintainers -# - @cilium/cilium-packer-ci-build-maintainers -# - @cilium/ebpf-lib-maintainers -# - @cilium/hubble-maintainers -# - @cilium/image-tools-maintainers -# - @cilium/metallb-maintainers -# - @cilium/openshift-terraform-maintainers -# - @cilium/proxy-maintainers -# - @cilium/tetragon-maintainers -# -# Cloud Integrations -# ++++++++++++++++++ -# -# The following codeowner groups provide insight into the integrations with -# specific cloud providers: -# -# - @cilium/alibabacloud -# - @cilium/aws -# - @cilium/azure -# -# Cilium Internals -# ++++++++++++++++ -# -# The following codeowner groups cover more specific knowledge about Cilium -# Agent internals or the way that particular Cilium features interact with -# external software and protocols: -# -# - @cilium/docker: -# Maintain the deprecated docker-plugin. -# - @cilium/endpoint: -# Provide background on how the Cilium Endpoint package fits into the overall -# agent architecture, relationship with generation of policy / datapath -# constructs, serialization and restore from disk. -# - @cilium/envoy: -# Maintain the L7 proxy integration with Envoy. This includes the -# configurations for Envoy via xDS protocols as well as the extensible -# proxylib framework for Go-based layer 7 filters. -# - @cilium/egress-gateway: -# Maintain the egress gateway control plane and datapath logic. -# - @cilium/fqdn: -# Maintain the L7 DNS proxy integration. -# - @cilium/ipcache: -# Provide background on how the userspace IPCache structure fits into the -# overall agent architecture, ordering constraints with respect to network -# policies and encryption. Handle the relationship between Kubernetes state -# and datapath state as it pertains to remote peers. -# - @cilium/ipsec: -# Maintain the kernel IPsec configuration and related eBPF logic to ensure -# traffic is correctly encrypted. -# - @cilium/kvstore: -# Review Cilium interactions with key-value stores, particularly etcd. -# Understand the client libraries used by Cilium for sharing state between -# nodes and clusters. -# - @cilium/loader: -# Maintain the tooling that allows eBPF programs to be loaded into the -# kernel: LLVM, bpftool, use of cilium/ebpf for loading programs in the -# agent, ELF templating, etc. -# - @cilium/operator: -# Review operations that occur once per cluster via the Cilium Operator -# component. Take care of the corresponding garbage collection and leader -# election logic. -# - @cilium/proxy: -# Review low-level implementations used to redirect L7 traffic to the actual -# proxy implementations (FQDN, Envoy, ...). -# - @cilium/sig-agent: -# Provide Cilium (agent) general Go review. Internal architecture, core data -# structures and daemon startup. -# - @cilium/sig-bgp: -# Review changes to our BGP integration. -# - @cilium/sig-clustermesh: -# Ensure the reliability of state sharing between clusters to ensure that -# each cluster maintains a separate fault domain. -# - @cilium/sig-datapath: -# Provide feedback on all eBPF code changes, use of the kernel APIs for -# configuring the networking and socket layers. Coordination of kernel -# subsystems such as xfrm (IPsec), iptables / nftables, tc. Maintain the -# control plane layers that populate most eBPF maps; account for endianness -# and system architecture impacts on the datapath code. -# - @cilium/sig-encryption -# Review control and data plane logic related with encryption (IPSec and -# WireGuard). -# - @cilium/sig-hubble: -# Review all Cilium and Hubble code related to observing system events, -# exporting those via gRPC protocols outside the node and outside the -# cluster. Ensure the security of those event channels, for example via TLS. -# - @cilium/sig-ipam: -# Coordinate the implementation between all of the IP Address Management -# modes, provide awareness/insight into IP resource exhaustion and garbage -# collection concerns. -# - @cilium/sig-k8s: -# Provide input on all interactions with Kubernetes, both for standard -# resources and CRDs. Ensure best practices are followed for the coordination -# of clusterwide state in order to minimize memory usage. -# - @cilium/sig-lb: -# Maintain the layers necessary to coordinate all load balancing -# configurations within the agent control plane, including Services, -# ClusterIP, NodePorts, Maglev, local redirect policies, and -# NAT46/NAT64. -# - @cilium/sig-policy: -# Ensure consistency of semantics for all network policy representations. -# Responsible for all policy logic from Kubernetes down to eBPF policymap -# entries, including all intermediate layers such as the Policy Repository, -# SelectorCache, PolicyCache, CachedSelectorPolicy, EndpointPolicy, etc. -# - @cilium/sig-scalability: -# Maintain scalability and performance tests. Provide input on scalability -# and performance related changes. -# - @cilium/sig-servicemesh: -# Provide input on the way that Service Mesh constructs such as Gateway API -# are converted into lower-level constructs backed by eBPF or Envoy -# configurations. Maintain the CRDs necessary for Service Mesh functionality. -# - @cilium/wireguard: -# Maintain the kernel WireGuard configuration and datapath impacts related to -# ensuring traffic is encrypted correctly when WireGuard mode is enabled. -# -# END_CODEOWNERS_DOCS -# -# The following filepaths should be sorted so that more specific paths occur -# after the less specific paths, otherwise the ownership for the specific paths -# is not properly picked up in Github. -/AUTHORS @cilium/release-managers -/CODE_OF_CONDUCT.md @cilium/contributing -/CODEOWNERS @cilium/contributing -/CONTRIBUTING.md @cilium/contributing -/.authors.aux @cilium/contributing -/.clomonitor.yml @cilium/contributing -/.devcontainer @cilium/ci-structure -/.gitattributes @cilium/contributing -/.github/ @cilium/contributing -/.github/ariane-config.yaml @cilium/github-sec @cilium/ci-structure -/.github/renovate.json5 @cilium/github-sec @cilium/ci-structure -/.github/actions/ @cilium/github-sec @cilium/ci-structure -/.github/actions/bpftrace/ @cilium/sig-encryption @cilium/github-sec @cilium/ci-structure -/.github/actions/ipsec* @cilium/ipsec @cilium/github-sec @cilium/ci-structure -/.github/actions/kvstore/ @cilium/sig-clustermesh @cilium/kvstore @cilium/github-sec @cilium/ci-structure -/.github/workflows/ @cilium/github-sec @cilium/ci-structure -/.github/workflows/auto-approve.yaml @cilium/cilium-maintainers -/.github/workflows/*cilium-cli*.yaml @cilium/cli @cilium/github-sec @cilium/ci-structure -/.github/workflows/*clustermesh*.yaml @cilium/sig-clustermesh @cilium/github-sec @cilium/ci-structure -/.github/workflows/*datapath*.yaml @cilium/sig-datapath @cilium/github-sec @cilium/ci-structure -/.github/workflows/*gateway-api*.yaml @cilium/sig-servicemesh @cilium/github-sec @cilium/ci-structure -/.github/workflows/*hubble*.yaml @cilium/sig-hubble @cilium/github-sec @cilium/ci-structure -/.github/workflows/*ipsec*.yaml @cilium/ipsec @cilium/github-sec @cilium/ci-structure -/.github/workflows/*ingress*.yaml @cilium/sig-servicemesh @cilium/github-sec @cilium/ci-structure -/.github/actions/cl2-modules/ @cilium/sig-scalability -/.github/workflows/*scale*.yaml @cilium/sig-scalability @cilium/github-sec @cilium/ci-structure -/.github/workflows/*perf*.yaml @cilium/sig-scalability @cilium/github-sec @cilium/ci-structure -/.github/workflows/conformance-aks.yaml @cilium/azure @cilium/ipsec @cilium/github-sec @cilium/ci-structure -/.github/workflows/conformance-aws-cni.yaml @cilium/aws @cilium/github-sec @cilium/ci-structure -/.github/workflows/conformance-eks.yaml @cilium/aws @cilium/ipsec @cilium/github-sec @cilium/ci-structure -/.github/workflows/tests-ces-migrate.yaml @cilium/sig-scalability @cilium/github-sec @cilium/ci-structure -/.gitignore @cilium/contributing -/.golangci.yaml @cilium/ci-structure -/.mailmap @cilium/release-managers -/.nvim @cilium/contributing -/.vscode @cilium/contributing -/api/ @cilium/api -/api/v1/Makefile @cilium/sig-hubble-api -/api/v1/Makefile.protoc @cilium/sig-hubble-api -/api/v1/flow/ @cilium/sig-hubble-api -/api/v1/health/ @cilium/api @cilium/sig-agent -/api/v1/observer/ @cilium/sig-hubble-api -/api/v1/operator/ @cilium/api @cilium/operator -/api/v1/peer/ @cilium/sig-hubble-api -/api/v1/recorder/ @cilium/sig-hubble-api -/api/v1/relay/ @cilium/sig-hubble-api -/assets.go @cilium/sig-agent -/bpf/ @cilium/sig-datapath -/bpf/lib/egress_gateway.h @cilium/egress-gateway -Makefile* @cilium/build -/bpf/Makefile* @cilium/loader -/bpf/custom/Makefile* @cilium/build @cilium/loader -/bpf/lib/auth.h @cilium/sig-datapath @cilium/sig-servicemesh -/bpf/lib/encrypt.h @cilium/ipsec -/bpf/lib/policy.h @cilium/sig-datapath @cilium/sig-policy -/bpf/lib/wireguard.h @cilium/wireguard @cilium/sig-datapath -/bpf/bpf_wireguard.c @cilium/wireguard @cilium/sig-datapath -/bpf/lib/ids.h @cilium/loader -/bpf/lib/proxy.h @cilium/proxy @cilium/sig-datapath -/bpf/include/bpf/tailcall.h @cilium/loader -/bpf/include/bpf/config @cilium/loader -/bugtool/ @cilium/cli -/cilium-dbg/ @cilium/cli -/cilium-dbg/cmd/encrypt* @cilium/ipsec @cilium/cli -/cilium-dbg/cmd/preflight_k8s_valid_cnp.go @cilium/sig-k8s -/cilium-cli/ @cilium/cli -/cilium-cli/bgp/ @cilium/sig-bgp -/cilium-cli/cmd/ @cilium/cli -/cilium-cli/clustermesh/ @cilium/sig-clustermesh -/cilium-cli/connectivity/ @cilium/ci-structure -/cilium-cli/connectivity/check/frr.go @cilium/sig-bgp -/cilium-cli/connectivity/check/ipcache.go @cilium/ipcache -/cilium-cli/connectivity/check/metrics*.go @cilium/metrics -/cilium-cli/connectivity/check/policy.go @cilium/sig-policy -/cilium-cli/connectivity/builder/** @cilium/ci-structure -/cilium-cli/connectivity/builder/all_ingress_deny_from_outside.go @cilium/sig-encryption -/cilium-cli/connectivity/builder/bgp_control_plane.go @cilium/sig-bgp -/cilium-cli/connectivity/builder/client_egress.go @cilium/sig-policy -/cilium-cli/connectivity/builder/client_egress_l7*.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/client_egress_tls_sni.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/client_egress_to_cidr*.go @cilium/sig-policy -/cilium-cli/connectivity/builder/client_egress_to_echo*.go @cilium/sig-policy -/cilium-cli/connectivity/builder/cluster_entity_multi_cluster.go @cilium/sig-clustermesh -/cilium-cli/connectivity/builder/dns_only.go @cilium/fqdn -/cilium-cli/connectivity/builder/echo_ingress.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/echo_ingress_auth_always_fail.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/echo_ingress_from_other_client_deny.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/echo_ingress_from_outside.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/echo_ingress_knp.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/echo_ingress_l7.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/echo_ingress_l7_named_port.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/echo_ingress_mutual_auth_spiffe.go @cilium/sig-servicemesh -/cilium-cli/connectivity/builder/egress_gateway.go @cilium/egress-gateway -/cilium-cli/connectivity/builder/egress_gateway_excluded_cidrs.go @cilium/egress-gateway -/cilium-cli/connectivity/builder/egress_gateway_with_l7_policy.go @cilium/egress-gateway -/cilium-cli/connectivity/builder/local_redirect_policy.go @cilium/sig-lb -/cilium-cli/connectivity/builder/no_ipsec_xfrm_errors.go @cilium/sig-encryption -/cilium-cli/connectivity/builder/node_to_node_encryption.go @cilium/sig-encryption -/cilium-cli/connectivity/builder/pod_to_pod_encryption.go @cilium/sig-encryption -/cilium-cli/connectivity/builder/pod_to_pod_encryption_v2.go @cilium/sig-encryption -/cilium-cli/connectivity/perf/** @cilium/sig-scalability -/cilium-cli/connectivity/tests/bgp.go @cilium/sig-bgp -/cilium-cli/connectivity/tests/clustermesh-endpointslice-sync.go @cilium/sig-clustermesh -/cilium-cli/connectivity/tests/egressgateway.go @cilium/egress-gateway -/cilium-cli/connectivity/tests/encryption.go @cilium/sig-encryption -/cilium-cli/connectivity/tests/encryption_v2.go @cilium/sig-encryption -/cilium-cli/connectivity/tests/errors.go @cilium/sig-agent @cilium/sig-datapath -/cilium-cli/connectivity/tests/from-cidr.go @cilium/sig-policy -/cilium-cli/connectivity/tests/health.go @cilium/sig-agent -/cilium-cli/connectivity/tests/host.go @cilium/sig-agent -/cilium-cli/connectivity/tests/ipsec_xfrm.go @cilium/ipsec -/cilium-cli/connectivity/tests/lrp.go @cilium/sig-lb -/cilium-cli/connectivity/tests/pod.go @cilium/sig-agent -/cilium-cli/connectivity/tests/service.go @cilium/sig-lb -/cilium-cli/connectivity/tests/to-cidr.go @cilium/sig-policy -/cilium-cli/connectivity/tests/upgrade.go @cilium/sig-datapath -/cilium-cli/connectivity/tests/world.go @cilium/proxy -/cilium-cli/encrypt/ @cilium/sig-encryption -/cilium-cli/hubble/ @cilium/sig-hubble -/cilium-cli/install/ @cilium/cli @cilium/helm -/cilium-cli/install/azure.go @cilium/azure -/cilium-cli/k8s/ @cilium/sig-k8s -/cilium-health/ @cilium/sig-agent -/cilium-health/cmd/ @cilium/sig-agent @cilium/cli -/clustermesh-apiserver @cilium/sig-clustermesh -/contrib/ @cilium/contributing -/contrib/containerlab/ @cilium/sig-bgp -/contrib/coccinelle/ @cilium/sig-datapath -/contrib/scripts/portgen.py @cilium/sig-datapath -/contrib/scripts/check-datapathconfig.sh @cilium/loader -/daemon/ @cilium/sig-agent -/daemon/cmd/datapath.go @cilium/sig-datapath -/daemon/cmd/endpoint* @cilium/endpoint -/daemon/cmd/fqdn* @cilium/fqdn -/daemon/cmd/health* @cilium/sig-agent -/daemon/cmd/ipcache* @cilium/ipcache -/daemon/cmd/kube_proxy* @cilium/sig-datapath -/daemon/cmd/bootstrap_statistics.go @cilium/metrics -/daemon/cmd/policy* @cilium/sig-policy -/daemon/cmd/state.go @cilium/endpoint -/daemon/cmd/cells*.go @cilium/sig-foundations -/Documentation/ @cilium/docs-structure -/Documentation/_static/ @cilium/docs-structure -/Documentation/api.rst @cilium/sig-agent @cilium/docs-structure -/Documentation/beta.rst @cilium/docs-structure -/Documentation/reference-guides/bpf/ @cilium/sig-datapath @cilium/docs-structure -/Documentation/reference-guides/xfrm/ @cilium/ipsec @cilium/docs-structure -/Documentation/check-build.sh @cilium/docs-structure -/Documentation/check-cmdref.sh @cilium/docs-structure -/Documentation/check-crd-compat-table.sh @cilium/docs-structure -/Documentation/check-examples.sh @cilium/docs-structure -/Documentation/check-helmvalues.sh @cilium/docs-structure -/Documentation/cmdref/ -/Documentation/community/community.rst @cilium/contributing -/Documentation/community/governance.rst @cilium/contributing -/Documentation/community/roadmap.rst @cilium/contributing @cilium/docs-structure -/Documentation/contributing/ @cilium/contributing @cilium/docs-structure -/Documentation/conf.py @cilium/docs-structure -/Documentation/configuration/index.rst @cilium/docs-structure -/Documentation/contributing/ @cilium/contributing @cilium/docs-structure -/Documentation/contributing/development/reviewers_committers/review_vendor.rst @cilium/vendor -/Documentation/crdlist.rst -/Documentation/Dockerfile @cilium/docs-structure -/Documentation/gettingstarted/demo.rst @cilium/docs-structure -/Documentation/gettingstarted/gettinghelp.rst @cilium/contributing @cilium/docs-structure -/Documentation/glossary.rst @cilium/docs-structure -/Documentation/helm-values.rst -/Documentation/images/re-request-review.png @cilium/contributing @cilium/docs-structure -/Documentation/index.rst @cilium/docs-structure -/Documentation/installation/alibabacloud* @cilium/alibabacloud @cilium/docs-structure -/Documentation/installation/aws* @cilium/aws @cilium/docs-structure -/Documentation/installation/cni-chaining-aws-cni.rst @cilium/aws @cilium/docs-structure -/Documentation/installation/cni-chaining-azure-cni.rst @cilium/azure @cilium/docs-structure -/Documentation/installation/kind-configure.rst @cilium/docs-structure -/Documentation/internals/index.rst @cilium/docs-structure -/Documentation/internals/cilium_operator.rst @cilium/operator @cilium/docs-structure -/Documentation/internals/hubble.rst @cilium/sig-hubble @cilium/docs-structure -/Documentation/images/bpf* @cilium/sig-datapath @cilium/docs-structure -/Documentation/images/hubble_getflows.png @cilium/sig-hubble @cilium/docs-structure -/Documentation/Makefile @cilium/docs-structure -/Documentation/network/bgp* @cilium/sig-bgp @cilium/docs-structure -/Documentation/network/clustermesh/ @cilium/sig-clustermesh @cilium/docs-structure -/Documentation/network/concepts/fragmentation.rst @cilium/sig-datapath @cilium/docs-structure -/Documentation/network/concepts/ipam/ @cilium/sig-ipam @cilium/docs-structure -/Documentation/network/concepts/ipam/azure* @cilium/sig-ipam @cilium/azure @cilium/docs-structure -/Documentation/network/concepts/ipam/eni* @cilium/sig-ipam @cilium/aws @cilium/docs-structure -/Documentation/network/concepts/masquerading.rst @cilium/sig-datapath @cilium/docs-structure -/Documentation/network/ebpf/ @cilium/sig-datapath @cilium/docs-structure -/Documentation/network/egress-gateway-toc.rst @cilium/egress-gateway @cilium/docs-structure -/Documentation/network/egress-gateway/ @cilium/egress-gateway @cilium/docs-structure -/Documentation/network/kubernetes/ @cilium/sig-k8s @cilium/docs-structure -/Documentation/network/kubernetes/bandwidth-manager.rst @cilium/sig-datapath @cilium/docs-structure -/Documentation/network/kubernetes/ipam* @cilium/sig-ipam @cilium/docs-structure -/Documentation/network/kubernetes/kubeproxy-free.rst @cilium/sig-lb @cilium/docs-structure -/Documentation/network/kubernetes/local-redirect-policy.rst @cilium/sig-lb @cilium/docs-structure -/Documentation/network/kubernetes/ciliumendpointslice.rst @cilium/sig-scalability @cilium/docs-structure -/Documentation/network/lb-ipam.rst @cilium/sig-lb @cilium/docs-structure -/Documentation/network/multicast.rst @cilium/sig-datapath @cilium/docs-structure -/Documentation/network/servicemesh/ @cilium/sig-servicemesh @cilium/docs-structure -/Documentation/observability/ @cilium/sig-policy @cilium/docs-structure -/Documentation/observability/hubble* @cilium/sig-hubble @cilium/docs-structure -/Documentation/operations/performance/ @cilium/sig-datapath @cilium/docs-structure -/Documentation/operations/system_requirements.rst @cilium/sig-datapath @cilium/docs-structure -/Documentation/operations/troubleshooting_clustermesh.rst @cilium/sig-clustermesh @cilium/docs-structure -/Documentation/overview/component-overview.rst @cilium/docs-structure -/Documentation/overview/intro.rst @cilium/docs-structure -/Documentation/requirements.txt @cilium/docs-structure -/Documentation/security/http.rst @cilium/sig-policy @cilium/docs-structure -/Documentation/security/images/cilium_threat_model* @cilium/security @cilium/docs-structure -/Documentation/security/network/encryption-ipsec.rst @cilium/ipsec @cilium/docs-structure -/Documentation/security/network/encryption-wireguard.rst @cilium/wireguard @cilium/docs-structure -/Documentation/security/network/proxy/ @cilium/proxy @cilium/docs-structure -/Documentation/security/policy-creation.rst @cilium/sig-policy @cilium/docs-structure -/Documentation/security/policy/ @cilium/sig-policy @cilium/docs-structure -/Documentation/security/threat-model.rst @cilium/security @cilium/docs-structure -/Documentation/spelling_wordlist.txt @cilium/docs-structure -/Documentation/update-cmdref.sh @cilium/docs-structure -/Documentation/update-spelling_wordlist.sh @cilium/docs-structure -/Documentation/yaml.config @cilium/docs-structure -/examples/ @cilium/docs-structure -/examples/hubble/ @cilium/sig-hubble -/examples/kubernetes/ @cilium/sig-k8s -/examples/kubernetes/clustermesh/ @cilium/sig-clustermesh -/examples/minikube/ @cilium/sig-k8s -/examples/policies/kubernetes/clustermesh/ @cilium/sig-clustermesh -/FURTHER_READINGS.rst @cilium/docs-structure -/hack/ @cilium/contributing -/hubble/ @cilium/sig-hubble -/hubble-relay/ @cilium/sig-hubble -/images @cilium/build -/images/builder/install-protoc.sh @cilium/sig-hubble-api -/images/builder/install-protoplugins.sh @cilium/sig-hubble-api -/images/builder/update-cilium-builder-image.sh @cilium/github-sec -/images/hubble-relay @cilium/sig-hubble -/images/runtime/update-cilium-runtime-image.sh @cilium/github-sec -/install/kubernetes/ @cilium/sig-k8s @cilium/helm -/install/kubernetes/cilium/**/cilium-envoy @cilium/sig-k8s @cilium/helm @cilium/envoy @cilium/sig-servicemesh -/install/kubernetes/cilium/**/spire @cilium/sig-k8s @cilium/helm @cilium/sig-servicemesh -/install/kubernetes/cilium/templates/clustermesh* @cilium/sig-k8s @cilium/helm @cilium/sig-clustermesh -/install/kubernetes/cilium/templates/hubble* @cilium/sig-k8s @cilium/helm @cilium/sig-hubble -/LICENSE @cilium/contributing -/MAINTAINERS.md @cilium/contributing -/netlify.toml @cilium/ci-structure -/operator/ @cilium/operator -/operator/doublewrite @cilium/metrics -/operator/pkg/bgpv2 @cilium/sig-bgp -/operator/pkg/ciliumendpointslice @cilium/sig-scalability -/operator/pkg/ciliumenvoyconfig @cilium/sig-servicemesh -/operator/pkg/controller-runtime @cilium/envoy @cilium/sig-servicemesh -/operator/pkg/gateway-api @cilium/sig-servicemesh -/operator/pkg/ingress @cilium/sig-servicemesh -/operator/pkg/lbipam @cilium/sig-lb -/operator/pkg/model @cilium/sig-servicemesh -/operator/pkg/networkpolicy @cilium/sig-policy -/operator/pkg/secretsync @cilium/envoy @cilium/sig-servicemesh -/pkg/act/ @cilium/sig-datapath @cilium/metrics -/pkg/annotation @cilium/sig-k8s -/pkg/alibabacloud/ @cilium/alibabacloud -/pkg/alignchecker/ @cilium/sig-datapath @cilium/loader -/pkg/allocator/ @cilium/kvstore -/pkg/api/ @cilium/api -/pkg/auth/ @cilium/sig-servicemesh -/pkg/aws/ @cilium/aws -/pkg/azure/ @cilium/azure -/pkg/backoff/ @cilium/sig-agent -/pkg/bufuuid/ @cilium/sig-scalability -/pkg/datapath/linux/bandwidth/ @cilium/sig-datapath -/pkg/bgpv1/ @cilium/sig-bgp -/pkg/bpf/ @cilium/loader -/pkg/byteorder/ @cilium/sig-datapath @cilium/api -/pkg/cgroups/ @cilium/sig-datapath -/pkg/cidr/ @cilium/sig-agent -/pkg/ciliumenvoyconfig/ @cilium/envoy @cilium/sig-servicemesh -/pkg/cleanup/ @cilium/sig-agent -/pkg/client @cilium/api -/pkg/clustermesh @cilium/sig-clustermesh -/pkg/cmdref @cilium/cli -/pkg/command/ @cilium/cli -/pkg/common/ @cilium/sig-agent -/pkg/common/ipsec/ @cilium/ipsec -/pkg/comparator/ @cilium/sig-agent -/pkg/completion/ @cilium/proxy -/pkg/components/ @cilium/sig-agent -/pkg/container/ @cilium/sig-foundations -/pkg/container/bitlpm/ @cilium/ipcache @cilium/sig-policy -/pkg/container/set/ @cilium/sig-policy -/pkg/controller @cilium/sig-agent -/pkg/counter @cilium/sig-datapath -/pkg/crypto/certificatemanager @cilium/envoy @cilium/sig-servicemesh -/pkg/crypto/certloader @cilium/sig-hubble -/pkg/datapath/ @cilium/sig-datapath -/pkg/datapath/fake/ipsec.go @cilium/ipsec -/pkg/datapath/linux/config/ @cilium/loader -/pkg/datapath/linux/ipsec/ @cilium/ipsec -/pkg/datapath/linux/ipsec/xfrm_collector* @cilium/ipsec @cilium/metrics -/pkg/datapath/linux/ipsec.go @cilium/ipsec -/pkg/datapath/linux/node.go @cilium/sig-datapath -/pkg/datapath/linux/probes/ @cilium/loader -/pkg/datapath/linux/requirements.go @cilium/loader -/pkg/datapath/linux/sysctl/ @cilium/sig-datapath -/pkg/datapath/types/ipsec.go @cilium/ipsec -/pkg/datapath/types/loader.go @cilium/loader -/pkg/datapath/loader/ @cilium/loader -/pkg/datapath/ipcache/ @cilium/ipcache -/pkg/defaults @cilium/sig-agent -/pkg/debug @cilium/sig-agent -/pkg/dial @cilium/sig-agent -/pkg/driftchecker @cilium/sig-foundations -/pkg/dynamicconfig @cilium/sig-foundations -/pkg/ebpf @cilium/sig-datapath -/pkg/egressgateway/ @cilium/egress-gateway -/pkg/endpoint/ @cilium/endpoint -/pkg/endpointcleanup/ @cilium/endpoint -/pkg/endpointmanager/ @cilium/endpoint -/pkg/endpointstate/ @cilium/endpoint -/pkg/envoy/ @cilium/envoy -/pkg/eventqueue/ @cilium/sig-agent -/pkg/dynamiclifecycle/ @cilium/sig-foundations -/pkg/flowdebug/ @cilium/proxy -/pkg/fqdn/ @cilium/fqdn -/pkg/fswatcher/ @cilium/sig-datapath @cilium/sig-hubble -/pkg/gops/ @cilium/sig-agent -/pkg/health/ @cilium/sig-agent -/pkg/hive/ @cilium/sig-foundations -/pkg/hubble/ @cilium/sig-hubble -/pkg/hubble/metrics @cilium/hubble-metrics -/pkg/iana/ @cilium/sig-agent -/pkg/identity @cilium/sig-policy -/pkg/idpool/ @cilium/kvstore -/pkg/ip/ @cilium/sig-agent -/pkg/ipalloc/ @cilium/sig-ipam -/pkg/ipam/ @cilium/sig-ipam -/pkg/ipam/allocator/alibabacloud/ @cilium/sig-ipam @cilium/alibabacloud -/pkg/ipam/allocator/aws/ @cilium/sig-ipam @cilium/aws -/pkg/ipam/allocator/azure/ @cilium/sig-ipam @cilium/azure -/pkg/ipam/allocator/clusterpool/ @cilium/sig-ipam @cilium/operator -/pkg/ipcache/ @cilium/ipcache -/pkg/ipmasq @cilium/sig-agent -/pkg/k8s/ @cilium/sig-k8s -/pkg/k8s/apis/cilium.io/client/crds/v2/ @cilium/sig-k8s -/pkg/k8s/apis/cilium.io/client/crds/v2/ciliumegressgatewaypolicies.yaml @cilium/egress-gateway -/pkg/k8s/apis/cilium.io/v2/cegp_types.go @cilium/egress-gateway -/pkg/k8s/apis/cilium.io/v2/ @cilium/api @cilium/sig-k8s -/pkg/kvstore/ @cilium/kvstore -/pkg/kvstore/etcdinit @cilium/sig-clustermesh @cilium/kvstore -/pkg/l2announcer/ @cilium/sig-agent -/pkg/labels @cilium/sig-policy @cilium/api -/pkg/labelsfilter @cilium/sig-policy -/pkg/launcher @cilium/sig-agent -/pkg/loadbalancer @cilium/sig-lb -/pkg/loadinfo/ @cilium/sig-agent -/pkg/lock @cilium/sig-agent -/pkg/logging/ @cilium/cli -/pkg/mac @cilium/sig-datapath -/pkg/maglev @cilium/sig-lb -/pkg/maps/ @cilium/sig-datapath -/pkg/maps/egressmap @cilium/egress-gateway -/pkg/mcastmanager @cilium/sig-datapath -/pkg/metrics @cilium/metrics -/pkg/monitor @cilium/sig-datapath -/pkg/monitor/api @cilium/api @cilium/sig-datapath -/pkg/monitor/datapath_trace.go @cilium/sig-datapath @cilium/sig-hubble -/pkg/monitor/format @cilium/cli @cilium/sig-datapath -/pkg/monitor/payload @cilium/api @cilium/sig-datapath -/pkg/mountinfo @cilium/sig-datapath -/pkg/mtu @cilium/sig-datapath -/pkg/multicast @cilium/sig-datapath -/pkg/murmur3/ @cilium/sig-datapath -/pkg/netns/ @cilium/sig-datapath @cilium/sig-k8s -/pkg/node @cilium/sig-agent -/pkg/nodediscovery/ @cilium/sig-agent -/pkg/option @cilium/sig-agent @cilium/cli -/pkg/pidfile @cilium/sig-agent -/pkg/policy @cilium/sig-policy -/pkg/policy/api/ @cilium/api -/pkg/policy/groups/aws/ @cilium/sig-policy @cilium/aws -/pkg/policy/k8s @cilium/sig-policy -/pkg/pprof @cilium/sig-foundations -/pkg/promise @cilium/sig-foundations -/pkg/proxy/ @cilium/proxy -/pkg/proxy/accesslog @cilium/proxy @cilium/api -/pkg/proxy/dns.go @cilium/proxy @cilium/fqdn -/pkg/proxy/envoyproxy.go @cilium/proxy @cilium/envoy -/pkg/rate/ @cilium/sig-agent -/pkg/rate/metrics @cilium/metrics -/pkg/recorder @cilium/sig-datapath -/pkg/redirectpolicy @cilium/sig-lb -/pkg/resiliency @cilium/sig-agent -/pkg/revert/ @cilium/sig-agent -/pkg/safeio @cilium/sig-agent -/pkg/safetime/ @cilium/sig-agent -/pkg/service @cilium/sig-lb -/pkg/shortener @cilium/sig-foundations @cilium/sig-k8s -/pkg/signal @cilium/sig-datapath -/pkg/slices @cilium/sig-foundations -/pkg/socketlb @cilium/loader -/pkg/source @cilium/ipcache -/pkg/spanstat/ @cilium/sig-agent -/pkg/status/ @cilium/sig-agent -/pkg/testutils/ @cilium/ci-structure -/pkg/time @cilium/sig-agent -/pkg/trigger/ @cilium/sig-agent -/pkg/tuple @cilium/sig-datapath -/pkg/types/ @cilium/sig-datapath -/pkg/u8proto/ @cilium/sig-agent -/pkg/wireguard @cilium/wireguard -/pkg/version/ @cilium/sig-agent -/pkg/versioncheck/ @cilium/sig-agent -/pkg/xds/ @cilium/envoy -/plugins/cilium-cni/ @cilium/sig-k8s -/plugins/cilium-docker/ @cilium/docker -/README.rst @cilium/docs-structure -/SECURITY.md @cilium/contributing -/SECURITY-INSIGHTS.yml @cilium/security -/stable.txt @cilium/release-managers -/test/ @cilium/ci-structure -/test/Makefile* @cilium/ci-structure @cilium/build -# Service handling tests -/test/k8s/services.go @cilium/sig-lb @cilium/ci-structure -# Datapath tests -/bpf/tests/bpftest/ @cilium/sig-datapath -/test/k8s/bandwidth.go @cilium/sig-datapath @cilium/ci-structure -/test/k8s/chaos.go @cilium/sig-datapath @cilium/ci-structure -/test/k8s/datapath_configuration.go @cilium/sig-datapath @cilium/ci-structure -/test/runtime/connectivity.go @cilium/sig-datapath @cilium/ci-structure -/test/verifier @cilium/loader @cilium/ci-structure -# Policy tests -/test/k8s/net_policies.go @cilium/sig-policy @cilium/ci-structure -/test/runtime/net_policies.go @cilium/sig-policy @cilium/ci-structure -# Hubble/monitoring tests -/test/k8s/hubble.go @cilium/sig-hubble @cilium/ci-structure -/test/runtime/monitor.go @cilium/sig-hubble @cilium/ci-structure -# L7 proxy tests -/test/k8s/fqdn.go @cilium/fqdn @cilium/ci-structure -/test/k8s/kafka_policies.go @cilium/envoy @cilium/ci-structure -/test/runtime/fqdn.go @cilium/fqdn @cilium/ci-structure -# BIG TCP tests -/test/bigtcp @cilium/sig-datapath @cilium/ci-structure -# Misc. tests -/test/runtime/kvstore.go @cilium/kvstore @cilium/ci-structure -/test/runtime/chaos_agent.go @cilium/sig-agent @cilium/ci-structure -/tools/dpgen @cilium/loader -/tools/ @cilium/contributing -/USERS.md @cilium/community -/go.sum @cilium/vendor -/go.mod @cilium/vendor -/vendor/ @cilium/vendor -/VERSION @cilium/release-managers -/.clang-format @cilium/contributing diff --git a/vendor/github.com/cilium/cilium/CODE_OF_CONDUCT.md b/vendor/github.com/cilium/cilium/CODE_OF_CONDUCT.md deleted file mode 100644 index eea0dbd783..0000000000 --- a/vendor/github.com/cilium/cilium/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,46 +0,0 @@ -## Community Code of Conduct v1.0 - -This is Code of Conduct is based on the [CNCF Code of -Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). -See the referred document for translated versions into different languages. The -text below is modified with Cilium community specific contact details. - -### Contributor Code of Conduct - -As contributors and maintainers of this project, and in the interest of fostering -an open and welcoming community, we pledge to respect all people who contribute -through reporting issues, posting feature requests, updating documentation, -submitting pull requests or patches, and other activities. - -We are committed to making participation in this project a harassment-free experience for -everyone, regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, body size, race, ethnicity, age, -religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing others' private information, such as physical or electronic addresses, - without explicit permission -* Other unethical or unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are not -aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers -commit themselves to fairly and consistently applying these principles to every aspect -of managing this project. Project maintainers who do not follow or enforce the Code of -Conduct may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the code of conduct team via -[conduct@cilium.io](mailto:conduct@cilium.io). - -This Code of Conduct is adapted from the Contributor Covenant -(http://contributor-covenant.org), version 1.2.0, available at -http://contributor-covenant.org/version/1/2/0/ diff --git a/vendor/github.com/cilium/cilium/CONTRIBUTING.md b/vendor/github.com/cilium/cilium/CONTRIBUTING.md deleted file mode 100644 index 622295d267..0000000000 --- a/vendor/github.com/cilium/cilium/CONTRIBUTING.md +++ /dev/null @@ -1,23 +0,0 @@ -# How to Contribute - -## To Cilium/Hubble - -See the [Developer / Contributor -Guide](https://docs.cilium.io/en/stable/contributing/development/contributing_guide/) for detailed information on -how to contribute, get started and find good first issues. - -## To the cilium.io website - -Please see the [cilium.io website contributing guide](https://github.com/cilium/cilium.io/blob/main/CONTRIBUTING.md) for detailed -information on how to add blogs, trainings, and other resources. - -## To the Cilium documentation - -Please see the [Cilium documentation contributing guide](https://docs.cilium.io/en/stable/contributing/docs/) for detailed -information on how to contribute to the Cilium documentation. - -## Support Expectations & Enterprise Options - -Cilium is an open source project maintained by the community, and we greatly appreciate all contributions that help improve it. If you find an issue or need a new feature, we encourage you to open an issue, submit a pull request, start a discussion, or join the weekly developer meeting. - -However, if your organization requires stronger guarantees, priority support, or dedicated assistance, enterprise support is available from vendors in the ecosystem. You can find more details on the [website](https://cilium.io/enterprise/). diff --git a/vendor/github.com/cilium/cilium/FURTHER_READINGS.rst b/vendor/github.com/cilium/cilium/FURTHER_READINGS.rst deleted file mode 100644 index b8a8936c6f..0000000000 --- a/vendor/github.com/cilium/cilium/FURTHER_READINGS.rst +++ /dev/null @@ -1,87 +0,0 @@ -Further Reading -=============== - -.. further-reading-begin - -Related Material ----------------- - -* `BPF for security—and chaos—in Kubernetes `_ -* `k8s-snowflake: Configs and scripts for bootstrapping an opinionated - Kubernetes cluster anywhere using Cilium plugin - `_ -* `Using Cilium for NetworkPolicy: Kubernetes documentation on how to use Cilium - to implement NetworkPolicy - `_ - -Presentations -------------- - -* Kubernetes on Edge Day, Europe 2022 - Connecting Klusters on the Edge with Deep Dive into Cilium Cluster Mesh: - `Video `__ -* Cloud Native Telco Day, Europe 2022 - Leveraging Cilium and SRv6 for Telco Networking: - `Video `__ -* KubeCon, Europe 2022 - A Guided Tour of Cilium Service Mesh: - `Video `__ -* eBPF Day, Europe, 2022 - IKEA Private Cloud, eBPF Based Networking, Load Balancing, and Observability with Cilium: - `Video `__ -* KubeCon, North America 2021 - Beyond printf & tcpdump: Debugging Kubernetes Networking with eBPF: - `Video `__ -* eBPF Summit, Virtual 2020 - Our eBPF Journey at Datadog: - `Video `__ -* eBPF Summit, Virtual 2020 - Building a Secure and Maintainable PaaS Leveraging Cilium: - `Video `__ -* eBPF Summit, Virtual 2020 - The Past, Present and Future of Cilium and Hubble at Palantir: - `Video `__ -* KubeCon, Europe 2020 - Hubble - eBPF Based Observability for Kubernetes: - `Video `__ -* Fosdem, Brussels, 2020 - BPF as a revolutionary technology for the container landscape: - `Slides `__, `Video `__ -* KubeCon, North America 2019 - Understanding and Troubleshooting the eBPF Datapath in Cilium: - `Video `__ -* KubeCon, North America 2019 - Liberating Kubernetes from kube-proxy and iptables: - `Slides `__, `Video `__ -* KubeCon, Europe 2019 - Using eBPF to Bring Kubernetes-Aware Security to the Linux Kernel: - `Video `__ -* KubeCon, Europe 2019 - Transparent Chaos Testing with Envoy , Cilium and BPF: - `Slides `__, `Video `__ -* All Systems Go!, Berlin, Sept 2018 - Cilium - Bringing the BPF Revolution to Kubernetes Networking and Security - `Slides `__, `Video `__ -* QCon, San Francisco 2018 - How to Make Linux Microservice-Aware with Cilium and eBPF: - `Slides `__, `Video `__ -* KubeCon, North America 2018 - Connecting Kubernetes Clusters Across Cloud Providers: - `Slides `__, `Video `__ -* KubeCon, North America 2018 - Implementing Least Privilege Security and Networking with BPF on Kubernetes: - `Slides `__, `Video `__ -* KubeCon, Europe 2018 - Accelerating Envoy with the Linux Kernel: - `Video `__ -* Open Source Summit, North America - Cilium: Networking and security for containers with BPF and XDP: - `Video `__ -* DockerCon, Austin TX, Apr 2017 - Cilium - Network and Application Security with BPF and XDP: `Slides - `__, `Video `__ -* CNCF/KubeCon Meetup, Berlin, Mar 2017 - Linux Native, HTTP Aware Network Security: - `Slides `__, `Video `__ -* Docker Distributed Systems Summit, Berlin, Oct 2016: - `Slides `__, `Video `__ -* NetDev1.2, Tokyo, Sep 2016 - cls_bpf/eBPF updates since netdev 1.1: - `Slides `__, `Video `__ -* NetDev1.2, Tokyo, Sep 2016 - Advanced programmability and recent updates with tc’s cls_bpf: - `Slides `__, `Video `__ -* ContainerCon NA, Toronto, Aug 2016 - Fast IPv6 container networking with BPF & XDP: - `Slides `__ - -Podcasts --------- - -* Software Gone Wild by Ivan Pepelnjak, Oct 2016: `Blog `__, `MP3 `__ -* OVS Orbit by Ben Pfaff, May 2016: `Blog `__, `MP3 `__ - -Community blog posts --------------------- - -* `Cilium for Network and Application Security with BPF and XDP, Apr 2017 - `_ -* `Cilium, BPF and XDP, Google Open Source Blog, Nov 2016 - `_ - -.. further-reading-end diff --git a/vendor/github.com/cilium/cilium/MAINTAINERS.md b/vendor/github.com/cilium/cilium/MAINTAINERS.md deleted file mode 100644 index dcfa99014b..0000000000 --- a/vendor/github.com/cilium/cilium/MAINTAINERS.md +++ /dev/null @@ -1,132 +0,0 @@ -# Maintainers - -See [Governance](https://github.com/cilium/community/blob/main/GOVERNANCE.md) for -governance, commit, and vote guidelines as well as committer responsibilities. -Everybody listed is a committer as per governance definition. See the -[Contributor Ladder](https://github.com/cilium/community/blob/main/CONTRIBUTOR-LADDER.md) -to learn how to level up through the project. - -## Cilium Committers - - * [Aditi Ghag] (Isovalent) - * [Alexandre Perrin] (Isovalent) - * [André Martins] (Isovalent) - * [Beatriz Martínez] (Isovalent) - * [Bill Mulligan] (Isovalent) - * [Bruno M. Custódio] (Isovalent) - * [Casey Callendrello] (Isovalent) - * [Chance Zibolski] (Isovalent) - * [Chris Tarazi] (Isovalent) - * [Daniel Borkmann] (Isovalent) - * [Dan Wendlandt] (Isovalent) - * [Deepesh Pathak] - * [Dorde Lapcevic] (Google) - * [Dylan Reimerink] (Isovalent) - * [Gilberto Bertin] (Isovalent) - * [Glib Smaga] (Isovalent) - * [Hemanth Malla] (Datadog) - * [Ian Vernon] - * [Jarno Rajahalme] (Isovalent) - * [Joe Stringer] (Isovalent) - * [John Fastabend] (Isovalent) - * [Julian Wiedmann] (Isovalent) - * [Jussi Mäki] (Isovalent) - * [Kornilios Kourtis] (Isovalent) - * [Laurent Bernaille] (Datadog) - * [Liz Rice] (Isovalent) - * [Lorenz Bauer] (Isovalent) - * [Louis DeLosSantos] (Isovalent) - * [Maciej Kwiek] (Isovalent) - * [Marco Iorio] (Isovalent) - * [Martynas Pumputis] (Isovalent) - * [Michal Rostecki] (Deepfence) - * [Michi Mutsuzaki] (Isovalent) - * [Natália Réka Ivánkó] (Isovalent) - * [Nathan Sweet] (Isovalent) - * [Nick Young] (Isovalent) - * [Nicolas Busseneau] (Isovalent) - * [Nirmoy Das] (AMD) - * [Paul Chaignon] (Isovalent) - * [Quentin Monnet] (Hedgehog) - * [Robin Hahling] (Isovalent) - * [Sebastian Wicki] (Isovalent) - * [Tam Mach] (Isovalent) - * [Thomas Graf] (Isovalent) - * [Timo Beckers] (Isovalent) - * [Tobias Klauser] (Isovalent) - * [Tom Hadlaw] (Isovalent) - * [Vlad Ungureanu] (Palantir) - * [Yutaro Hayakawa] (Isovalent) - -## Cilium & Hubble Emeritus Committers - -We would like to acknowledge previous committers and their huge contributions to our collective success: - - * [Eloy Coto] (Red Hat) - * [Ilya Dmitrichenko] (Docker) - * [Ray Bejjani] - * [Tom Payne] - * [Weilong Cui] (Google) - * [Yongkun Gui] (Google) - * [Zang Li] (Google) - - -Please see the AUTHORS file for the full list of contributors to the Cilium -project. - -[Aditi Ghag]: https://github.com/aditighag -[Alexandre Perrin]: https://github.com/kaworu -[André Martins]: https://github.com/aanm -[Beatriz Martínez]: https://github.com/b3a-dev -[Bill Mulligan]: https://github.com/xmulligan -[Bruno M. Custódio]: https://github.com/bmcustodio -[Casey Callendrello]: https://github.com/squeed -[Chance Zibolski]: https://github.com/chancez -[Chris Tarazi]: https://github.com/christarazi -[Daniel Borkmann]: https://github.com/borkmann -[Dan Wendlandt]: https://github.com/danwent -[Deepesh Pathak]: https://github.com/fristonio -[Dorde Lapcevic]: https://github.com/dlapcevic -[Dylan Reimerink]: https://github.com/dylandreimerink -[Eloy Coto]: https://github.com/eloycoto -[Gilberto Bertin]: https://github.com/jibi -[Glib Smaga]: https://github.com/glibsm -[Hemanth Malla]: https://github.com/hemanthmalla -[Ian Vernon]: https://github.com/ianvernon -[Ilya Dmitrichenko]: https://github.com/errordeveloper -[Jarno Rajahalme]: https://github.com/jrajahalme -[Joe Stringer]: https://github.com/joestringer -[John Fastabend]: https://github.com/jrfastab -[Julian Wiedmann]: https://github.com/julianwiedmann -[Jussi Mäki]: https://github.com/joamaki -[Kornilios Kourtis]: https://github.com/kkourt -[Laurent Bernaille]: https://github.com/lbernail -[Liz Rice]: https://github.com/lizrice -[Lorenz Bauer]: https://github.com/lmb -[Louis DeLosSantos]: https://github.com/ldelossa -[Maciej Kwiek]: https://github.com/nebril -[Marco Iorio]: https://github.com/giorio94 -[Martynas Pumputis]: https://github.com/brb -[Michal Rostecki]: https://github.com/vadorovsky -[Michi Mutsuzaki]: https://github.com/michi-covalent -[Natália Réka Ivánkó]: https://github.com/sharlns -[Nathan Sweet]: https://github.com/nathanjsweet -[Nick Young]: https://github.com/youngnick -[Nicolas Busseneau]: https://github.com/nbusseneau -[Nirmoy Das]: https://github.com/nirmoy -[Paul Chaignon]: https://github.com/pchaigno -[Quentin Monnet]: https://github.com/qmonnet -[Ray Bejjani]: https://github.com/raybejjani -[Robin Hahling]: https://github.com/rolinh -[Sebastian Wicki]: https://github.com/gandro -[Tam Mach]: https://github.com/sayboras -[Thomas Graf]: https://github.com/tgraf -[Timo Beckers]: https://github.com/ti-mo -[Tobias Klauser]: https://github.com/tklauser -[Tom Hadlaw]: https://github.com/tommyp1ckles -[Tom Payne]: https://github.com/twpayne -[Vlad Ungureanu]: https://github.com/ungureanuvladvictor -[Weilong Cui]: https://github.com/Weil0ng -[Yongkun Gui]: https://github.com/anfernee -[Yutaro Hayakawa]: https://github.com/YutaroHayakawa -[Zang Li]: https://github.com/lzang diff --git a/vendor/github.com/cilium/cilium/Makefile b/vendor/github.com/cilium/cilium/Makefile deleted file mode 100644 index 1710dc32e6..0000000000 --- a/vendor/github.com/cilium/cilium/Makefile +++ /dev/null @@ -1,539 +0,0 @@ -# Copyright Authors of Cilium -# SPDX-License-Identifier: Apache-2.0 - -##@ Default -all: precheck build postcheck ## Default make target that perform precheck -> build -> postcheck - @echo "Build finished." - -##@ Build, Install and Test -debug: export NOOPT=1 ## Builds Cilium by disabling inlining, compiler optimizations and without stripping debug symbols, useful for debugging. -debug: export NOSTRIP=1 -debug: all - -include Makefile.defs - -SUBDIRS_CILIUM_CONTAINER := cilium-dbg daemon cilium-health bugtool tools/mount tools/sysctlfix plugins/cilium-cni -SUBDIR_OPERATOR_CONTAINER := operator -SUBDIR_RELAY_CONTAINER := hubble-relay - -ifdef LIBNETWORK_PLUGIN -SUBDIRS_CILIUM_CONTAINER += plugins/cilium-docker -endif - -# Add the ability to override variables --include Makefile.override - -# List of subdirectories used for global "make build", "make clean", etc -SUBDIRS := $(SUBDIRS_CILIUM_CONTAINER) $(SUBDIR_OPERATOR_CONTAINER) plugins tools $(SUBDIR_RELAY_CONTAINER) bpf clustermesh-apiserver - -# Filter out any directories where the parent directory is also present, to avoid -# building or cleaning a subdirectory twice. -# For example: The directory "tools" is transformed into a match pattern "tools/%", -# which is then used to filter out items such as "tools/mount" and "tools/sysctlfx" -SUBDIRS := $(filter-out $(foreach dir,$(SUBDIRS),$(dir)/%),$(SUBDIRS)) - -# Space-separated list of Go packages to test, equivalent to 'go test' package patterns. -# Because is treated as a Go package pattern, the special '...' sequence is supported, -# meaning 'all subpackages of the given package'. -TESTPKGS ?= ./... -UNPARALLELTESTPKGS ?= ./pkg/datapath/linux/ipsec/... - -GOTEST_BASE := -timeout 720s -GOTEST_COVER_OPTS += -coverprofile=coverage.out -BENCH_EVAL := "." -BENCH ?= $(BENCH_EVAL) -BENCHFLAGS_EVAL := -bench=$(BENCH) -run=^$$ -benchtime=10s -BENCHFLAGS ?= $(BENCHFLAGS_EVAL) -SKIP_KVSTORES ?= "false" -SKIP_K8S_CODE_GEN_CHECK ?= "true" -SKIP_CUSTOMVET_CHECK ?= "false" - -JOB_BASE_NAME ?= cilium_test - -TEST_LDFLAGS=-ldflags "-X github.com/cilium/cilium/pkg/kvstore.etcdDummyAddress=http://etcd:4002" - -TEST_UNITTEST_LDFLAGS= - -build: $(SUBDIRS) ## Builds all the components for Cilium by executing make in the respective sub directories. - -build-container: ## Builds components required for cilium-agent container. - for i in $(SUBDIRS_CILIUM_CONTAINER); do $(MAKE) $(SUBMAKEOPTS) -C $$i all; done - -build-container-operator: ## Builds components required for cilium-operator container. - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) all - -build-container-operator-generic: ## Builds components required for a cilium-operator generic variant container. - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) cilium-operator-generic - -build-container-operator-aws: ## Builds components required for a cilium-operator aws variant container. - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) cilium-operator-aws - -build-container-operator-azure: ## Builds components required for a cilium-operator azure variant container. - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) cilium-operator-azure - -build-container-operator-alibabacloud: ## Builds components required for a cilium-operator alibabacloud variant container. - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) cilium-operator-alibabacloud - -build-container-hubble-relay: - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_RELAY_CONTAINER) all - -$(SUBDIRS): force ## Execute default make target(make all) for the provided subdirectory. - @ $(MAKE) $(SUBMAKEOPTS) -C $@ all - -tests-privileged: ## Run Go tests including ones that require elevated privileges. - @$(ECHO_CHECK) running privileged tests... - ## We split tests into two parts: one that can be run in parallel - ## and tests that cannot be run in parallel with other packages - ## One drawback of this approach is that - ## if first set of tests fails, second one is not run - { PRIVILEGED_TESTS=true PATH=$(PATH):$(ROOT_DIR)/bpf $(GO_TEST) $(TEST_LDFLAGS) \ - $(TESTPKGS) $(GOTEST_BASE) $(GOTEST_COVER_OPTS) \ - && PRIVILEGED_TESTS=true PATH=$(PATH):$(ROOT_DIR)/bpf $(GO_TEST) $(TEST_LDFLAGS) \ - $(UNPARALLELTESTPKGS) $(GOTEST_BASE) -json -covermode=count -coverprofile=coverage2.out -p 1 --tags=unparallel; } | $(GOTEST_FORMATTER) - tail -n+2 coverage2.out >> coverage.out - rm coverage2.out - $(MAKE) generate-cov - -start-kvstores: ## Start running kvstores (etcd container) for integration tests. -ifeq ($(SKIP_KVSTORES),"false") - @echo Starting key-value store container... - -$(QUIET)$(CONTAINER_ENGINE) rm -f "cilium-etcd-test-container" 2> /dev/null - $(QUIET)$(CONTAINER_ENGINE) run -d \ - -e ETCD_UNSUPPORTED_ARCH=$(GOARCH) \ - --name "cilium-etcd-test-container" \ - -p 4002:4001 \ - $(ETCD_IMAGE) \ - etcd -name etcd0 \ - -advertise-client-urls http://0.0.0.0:4001 \ - -listen-client-urls http://0.0.0.0:4001 \ - -listen-peer-urls http://0.0.0.0:2380 \ - -initial-cluster-token etcd-cluster-1 \ - -initial-cluster-state new -endif - -stop-kvstores: ## Forcefully removes running kvstore components (etcd container) for integration tests. -ifeq ($(SKIP_KVSTORES),"false") - $(QUIET)$(CONTAINER_ENGINE) rm -f "cilium-etcd-test-container" -endif - -generate-cov: ## Generate HTML coverage report at coverage-all.html. - -@# Remove generated code from coverage -ifneq ($(SKIP_COVERAGE),) - @echo "Skipping generate-cov because SKIP_COVERAGE is set." -else - $(QUIET) grep -Ev '(^github.com/cilium/cilium/api/v1)|(generated.deepcopy.go)|(^github.com/cilium/cilium/pkg/k8s/client/)' \ - coverage.out > coverage.out.tmp - $(QUIET)$(GO) tool cover -html=coverage.out.tmp -o=coverage-all.html - $(QUIET) rm coverage.out.tmp -endif - @rmdir ./daemon/1 ./daemon/1_backup 2> /dev/null || true - -integration-tests: start-kvstores ## Run Go tests including ones that are marked as integration tests. - @$(ECHO_CHECK) running integration tests... - INTEGRATION_TESTS=true $(GO_TEST) $(TEST_UNITTEST_LDFLAGS) $(TESTPKGS) $(GOTEST_BASE) $(GOTEST_COVER_OPTS) | $(GOTEST_FORMATTER) - $(MAKE) generate-cov - $(MAKE) stop-kvstores - -bench: start-kvstores ## Run benchmarks for Cilium integration-tests in the repository. - $(GO_TEST) $(TEST_UNITTEST_LDFLAGS) $(GOTEST_BASE) $(BENCHFLAGS) $(TESTPKGS) - $(MAKE) stop-kvstores - -bench-privileged: ## Run benchmarks for privileged tests. - PRIVILEGED_TESTS=true $(GO_TEST) $(TEST_UNITTEST_LDFLAGS) $(GOTEST_BASE) $(BENCHFLAGS) $(TESTPKGS) - -clean-tags: ## Remove all the tags files from the repository. - @$(ECHO_CLEAN) tags - @-rm -f cscope.out cscope.in.out cscope.po.out cscope.files tags - -.PHONY: cscope.files -cscope.files: ## Generate cscope.files with the list of all files to generate ctags for. - @# Argument to -f must be double-quoted since shell removes backslashes that appear - @# before newlines. Otherwise, backslashes will appear in the output file. - @go list -f "{{ \$$p := .ImportPath }} \ - {{- range .GoFiles }}{{ printf \"%s/%s\n\" \$$p . }}{{ end }} \ - {{- range .TestGoFiles }}{{ printf \"%s/%s\n\" \$$p . }}{{ end }}" ./... \ - | sed 's#github.com/cilium/cilium/##g' | sort | uniq > cscope.files - - @echo "$(BPF_SRCFILES)" | sed 's/ /\n/g' | sort >> cscope.files - -tags: cscope.files ## Generate tags for Go and BPF source files. - @ctags -L cscope.files - cscope -R -b -q - -clean-container: ## Perform `make clean` for each component required in cilium-agent container. - -$(QUIET) for i in $(SUBDIRS_CILIUM_CONTAINER); do $(MAKE) $(SUBMAKEOPTS) -C $$i clean; done - -clean: ## Perform overall cleanup for Cilium. - -$(QUIET) for i in $(SUBDIRS); do $(MAKE) $(SUBMAKEOPTS) -C $$i clean; done - -veryclean: ## Perform complete cleanup for container engine images(including build cache). - -$(QUIET) $(CONTAINER_ENGINE) image prune -af - -$(QUIET) $(CONTAINER_ENGINE) builder prune -af - -install-bpf: ## Copies over the BPF source files from bpf/ to /var/lib/cilium/bpf/ - $(QUIET)$(INSTALL) -m 0750 -d $(DESTDIR)$(LOCALSTATEDIR)/lib/cilium - -rm -rf $(DESTDIR)$(LOCALSTATEDIR)/lib/cilium/bpf/* - $(foreach bpfsrc,$(BPF_SRCFILES), $(INSTALL) -D -m 0644 $(bpfsrc) $(DESTDIR)$(LOCALSTATEDIR)/lib/cilium/$(bpfsrc);) - -install: install-bpf ## Performs install for all the Cilium sub components (daemon, operator, relay etc.) - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - for i in $(SUBDIRS); do $(MAKE) $(SUBMAKEOPTS) -C $$i install; done - -install-container: install-bpf ## Performs install for all components required for cilium-agent container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - for i in $(SUBDIRS_CILIUM_CONTAINER); do $(MAKE) $(SUBMAKEOPTS) -C $$i install; done - -install-container-binary: install-bpf ## Install binaries for all components required for cilium-agent container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - for i in $(SUBDIRS_CILIUM_CONTAINER); do $(MAKE) $(SUBMAKEOPTS) -C $$i install-binary; done - -install-bash-completion: ## Install bash completion for all components required for cilium-agent container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - for i in $(SUBDIRS_CILIUM_CONTAINER); do $(MAKE) $(SUBMAKEOPTS) -C $$i install-bash-completion; done - -install-container-binary-operator: ## Install binaries for all components required for cilium-operator container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) install - -install-container-binary-operator-generic: ## Install binaries for all components required for cilium-operator generic variant container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) install-generic - -install-container-binary-operator-aws: ## Install binaries for all components required for cilium-operator aws variant container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) install-aws - -install-container-binary-operator-azure: ## Install binaries for all components required for cilium-operator azure variant container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) install-azure - -install-container-binary-operator-alibabacloud: ## Install binaries for all components required for cilium-operator alibabacloud variant container. - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_OPERATOR_CONTAINER) install-alibabacloud - -install-container-binary-hubble-relay: - $(QUIET)$(INSTALL) -m 0755 -d $(DESTDIR)$(BINDIR) - $(MAKE) $(SUBMAKEOPTS) -C $(SUBDIR_RELAY_CONTAINER) install-binary - -# Workaround for not having git in the build environment -# Touch the file only if needed -GIT_VERSION: force - @if [ "$(GIT_VERSION)" != "`cat 2>/dev/null GIT_VERSION`" ] ; then echo "$(GIT_VERSION)" >GIT_VERSION; fi - -check_deps: - @$(CILIUM_CLI) --help > /dev/null 2>&1 || ( echo "ERROR: '$(CILIUM_CLI)' not found. Please install it." && exit 1) - -include Makefile.kind - --include Makefile.docker - -manifests: ## Generate K8s manifests e.g. CRD, RBAC etc. - contrib/scripts/k8s-manifests-gen.sh - -.PHONY: generate-apis -generate-apis: generate-api generate-health-api generate-hubble-api generate-operator-api generate-kvstoremesh-api generate-sdp-api - -generate-api: api/v1/openapi.yaml ## Generate cilium-agent client, model and server code from openapi spec. - @$(ECHO_GEN)api/v1/openapi.yaml - -$(QUIET)$(SWAGGER) generate server -s server -a restapi \ - -t api/v1 \ - -f api/v1/openapi.yaml \ - --default-scheme=unix \ - -C api/v1/cilium-server.yml \ - -r hack/spdx-copyright-header.txt - -$(QUIET)$(SWAGGER) generate client -a restapi \ - -t api/v1 \ - -f api/v1/openapi.yaml \ - -r hack/spdx-copyright-header.txt - @# sort goimports automatically - -$(QUIET)$(GO) run golang.org/x/tools/cmd/goimports -w ./api/v1/client ./api/v1/models ./api/v1/server - -generate-health-api: api/v1/health/openapi.yaml ## Generate cilium-health client, model and server code from openapi spec. - @$(ECHO_GEN)api/v1/health/openapi.yaml - -$(QUIET)$(SWAGGER) generate server -s server -a restapi \ - -t api/v1 \ - -t api/v1/health/ \ - -f api/v1/health/openapi.yaml \ - --default-scheme=unix \ - -C api/v1/cilium-server.yml \ - -r hack/spdx-copyright-header.txt - -$(QUIET)$(SWAGGER) generate client -a restapi \ - -t api/v1 \ - -t api/v1/health/ \ - -f api/v1/health/openapi.yaml \ - -r hack/spdx-copyright-header.txt - @# sort goimports automatically - -$(QUIET)$(GO) run golang.org/x/tools/cmd/goimports -w ./api/v1/health - -generate-operator-api: api/v1/operator/openapi.yaml ## Generate cilium-operator client, model and server code from openapi spec. - @$(ECHO_GEN)api/v1/operator/openapi.yaml - -$(QUIET)$(SWAGGER) generate server -s server -a restapi \ - -t api/v1 \ - -t api/v1/operator/ \ - -f api/v1/operator/openapi.yaml \ - --default-scheme=http \ - -C api/v1/cilium-server.yml \ - -r hack/spdx-copyright-header.txt - -$(QUIET)$(SWAGGER) generate client -a restapi \ - -t api/v1 \ - -t api/v1/operator/ \ - -f api/v1/operator/openapi.yaml \ - -r hack/spdx-copyright-header.txt - @# sort goimports automatically - -$(QUIET)$(GO) run golang.org/x/tools/cmd/goimports -w ./api/v1/operator - -generate-kvstoremesh-api: api/v1/kvstoremesh/openapi.yaml ## Generate kvstoremesh client, model and server code from openapi spec. - @$(ECHO_GEN)api/v1/kvstoremesh/openapi.yaml - -$(QUIET)$(SWAGGER) generate server -s server -a restapi \ - -t api/v1 \ - -t api/v1/kvstoremesh/ \ - -f api/v1/kvstoremesh/openapi.yaml \ - --default-scheme=http \ - -C api/v1/cilium-server.yml \ - -r hack/spdx-copyright-header.txt - -$(QUIET)$(SWAGGER) generate client -a restapi \ - -t api/v1 \ - -t api/v1/kvstoremesh/ \ - -f api/v1/kvstoremesh/openapi.yaml \ - -r hack/spdx-copyright-header.txt - @# sort goimports automatically - -$(QUIET)$(GO) run golang.org/x/tools/cmd/goimports -w ./api/v1/kvstoremesh - -generate-hubble-api: api/v1/flow/flow.proto api/v1/peer/peer.proto api/v1/observer/observer.proto api/v1/relay/relay.proto ## Generate hubble proto Go sources. - $(QUIET) $(MAKE) $(SUBMAKEOPTS) -C api/v1 - - -generate-sdp-api: api/v1/standalone-dns-proxy/standalone-dns-proxy.proto - $(QUIET) $(MAKE) $(SUBMAKEOPTS) -C api/v1 - -define generate_k8s_protobuf - $(GO) install k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo && \ - $(GO) install golang.org/x/tools/cmd/goimports && \ - $(GO) run k8s.io/code-generator/cmd/go-to-protobuf \ - --apimachinery-packages='-k8s.io/apimachinery/pkg/util/intstr,$\ - -k8s.io/apimachinery/pkg/api/resource,$\ - -k8s.io/apimachinery/pkg/runtime/schema,$\ - -k8s.io/apimachinery/pkg/runtime,$\ - -k8s.io/apimachinery/pkg/apis/meta/v1,$\ - -k8s.io/apimachinery/pkg/apis/meta/v1beta1'\ - --drop-embedded-fields="github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1.TypeMeta" \ - --proto-import="$$PWD" \ - --proto-import="$$PWD/vendor" \ - --proto-import="$$PWD/tools/protobuf" \ - --packages=$(subst $(newline),$(comma),$(1)) \ - --go-header-file "$$PWD/hack/custom-boilerplate.go.txt" \ - --output-dir=$$GOPATH/src -endef - -define K8S_PROTO_PACKAGES -github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1 -github.com/cilium/cilium/pkg/k8s/slim/k8s/api/discovery/v1 -github.com/cilium/cilium/pkg/k8s/slim/k8s/api/discovery/v1beta1 -github.com/cilium/cilium/pkg/k8s/slim/k8s/api/networking/v1 -github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/apiextensions/v1 -github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1 -github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1beta1 -github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/util/intstr -endef - -.PHONY: generate-k8s-api-local -generate-k8s-api-local: - $(ASSERT_CILIUM_MODULE) - - $(eval TMPDIR := $(shell mktemp -d -t cilium.tmpXXXXXXXX)) - - $(QUIET) $(call generate_k8s_protobuf,${K8S_PROTO_PACKAGES},"$(TMPDIR)") - $(QUIET) contrib/scripts/k8s-code-gen.sh "$(TMPDIR)" - - $(QUIET) rm -rf "$(TMPDIR)" - -.PHONY: generate-k8s-api -generate-k8s-api: ## Generate Cilium k8s API client, deepcopy and deepequal Go sources. - contrib/scripts/builder.sh \ - $(MAKE) -C /go/src/github.com/cilium/cilium/ generate-k8s-api-local - -check-k8s-clusterrole: ## Ensures there is no diff between preflight's clusterrole and runtime's clusterrole. - ./contrib/scripts/check-preflight-clusterrole.sh - -##@ Development -vps: ## List all the running vagrant VMs. - VBoxManage list runningvms - -reload: ## Reload cilium-agent and cilium-docker systemd service after installing built binaries. - sudo systemctl stop cilium cilium-docker - sudo $(MAKE) install - sudo systemctl start cilium cilium-docker - sleep 6 - cilium status - -release: ## Perform a Git release for Cilium. - @echo "Visit https://github.com/cilium/release/issues/new/choose to initiate the release process." - -gofmt: ## Run gofmt on Go source files in the repository. - $(QUIET)$(GO) fmt ./... - -govet: ## Run govet on Go source files in the repository. - @$(ECHO_CHECK) vetting all packages... - $(QUIET) $(GO_VET) ./... - -golangci-lint: ## Run golangci-lint -ifneq (,$(findstring $(GOLANGCILINT_WANT_VERSION:v%=%),$(GOLANGCILINT_VERSION))) - @$(ECHO_CHECK) golangci-lint $(GOLANGCI_LINT_ARGS) - $(QUIET) golangci-lint run $(GOLANGCI_LINT_ARGS) -else - $(QUIET) $(CONTAINER_ENGINE) run --rm -v `pwd`:/app -w /app docker.io/golangci/golangci-lint:$(GOLANGCILINT_WANT_VERSION)@$(GOLANGCILINT_IMAGE_SHA) golangci-lint run $(GOLANGCI_LINT_ARGS) -endif - -golangci-lint-fix: ## Run golangci-lint to automatically fix warnings - $(QUIET)$(MAKE) golangci-lint GOLANGCI_LINT_ARGS="--fix" - -lint: golangci-lint - -lint-fix: golangci-lint-fix - -logging-subsys-field: ## Validate logrus subsystem field for logs in Go source code. - @$(ECHO_CHECK) contrib/scripts/check-logging-subsys-field.sh - $(QUIET) contrib/scripts/check-logging-subsys-field.sh - -check-microk8s: ## Validate if microk8s is ready to install cilium. - @$(ECHO_CHECK) microk8s is ready... - $(QUIET)microk8s.status >/dev/null \ - || (echo "Error: Microk8s is not running" && exit 1) - -LOCAL_IMAGE_TAG=local -microk8s: export DOCKER_REGISTRY=localhost:32000 -microk8s: export LOCAL_AGENT_IMAGE=$(DOCKER_REGISTRY)/$(DOCKER_DEV_ACCOUNT)/cilium-dev:$(LOCAL_IMAGE_TAG) -microk8s: export LOCAL_OPERATOR_IMAGE=$(DOCKER_REGISTRY)/$(DOCKER_DEV_ACCOUNT)/operator:$(LOCAL_IMAGE_TAG) -microk8s: check-microk8s ## Build cilium-dev docker image and import to microk8s - $(QUIET)$(MAKE) dev-docker-image DOCKER_IMAGE_TAG=$(LOCAL_IMAGE_TAG) - @echo " DEPLOY image to microk8s ($(LOCAL_AGENT_IMAGE))" - $(QUIET)./contrib/scripts/microk8s-import.sh $(LOCAL_AGENT_IMAGE) - $(QUIET)$(MAKE) dev-docker-operator-image DOCKER_IMAGE_TAG=$(LOCAL_IMAGE_TAG) - @echo " DEPLOY image to microk8s ($(LOCAL_OPERATOR_IMAGE))" - $(QUIET)./contrib/scripts/microk8s-import.sh $(LOCAL_OPERATOR_IMAGE) - -precheck: logging-subsys-field ## Peform build precheck for the source code. -ifeq ($(SKIP_K8S_CODE_GEN_CHECK),"false") - @$(ECHO_CHECK) contrib/scripts/check-k8s-code-gen.sh - $(QUIET) contrib/scripts/check-k8s-code-gen.sh -endif - @$(ECHO_CHECK) contrib/scripts/check-fmt.sh - $(QUIET) contrib/scripts/check-fmt.sh - @$(ECHO_CHECK) contrib/scripts/check-log-newlines.sh - $(QUIET) contrib/scripts/check-log-newlines.sh - @$(ECHO_CHECK) contrib/scripts/check-test-tags.sh - $(QUIET) contrib/scripts/check-test-tags.sh - @$(ECHO_CHECK) contrib/scripts/lock-check.sh - $(QUIET) contrib/scripts/lock-check.sh - @$(ECHO_CHECK) contrib/scripts/check-viper.sh - $(QUIET) contrib/scripts/check-viper.sh -ifeq ($(SKIP_CUSTOMVET_CHECK),"false") - @$(ECHO_CHECK) contrib/scripts/custom-vet-check.sh - $(QUIET) contrib/scripts/custom-vet-check.sh -endif - @$(ECHO_CHECK) contrib/scripts/check-time.sh - $(QUIET) contrib/scripts/check-time.sh - @$(ECHO_CHECK) contrib/scripts/check-go-testdata.sh - $(QUIET) contrib/scripts/check-go-testdata.sh - @$(ECHO_CHECK) contrib/scripts/check-source-info.sh - $(QUIET) contrib/scripts/check-source-info.sh - @$(ECHO_CHECK) contrib/scripts/check-xfrmstate.sh - $(QUIET) contrib/scripts/check-xfrmstate.sh - @$(ECHO_CHECK) contrib/scripts/check-legacy-header-guard.sh - $(QUIET) contrib/scripts/check-legacy-header-guard.sh - @$(ECHO_CHECK) contrib/scripts/check-logrus.sh - $(QUIET) contrib/scripts/check-logrus.sh - @$(ECHO_CHECK) contrib/scripts/check-safenetlink.sh - $(QUIET) contrib/scripts/check-safenetlink.sh - @$(ECHO_CHECK) contrib/scripts/check-datapathconfig.sh - $(QUIET) contrib/scripts/check-datapathconfig.sh - -pprof-heap: ## Get Go pprof heap profile. - $(QUIET)$(GO) tool pprof http://localhost:6060/debug/pprof/heap - -pprof-profile: ## Get Go pprof profile. - $(QUIET)$(GO) tool pprof http://localhost:6060/debug/pprof/profile - -pprof-block: ## Get Go pprof block profile. - $(QUIET)$(GO) tool pprof http://localhost:6060/debug/pprof/block - -pprof-trace-5s: ## Get Go pprof trace for a duration of 5 seconds. - curl http://localhost:6060/debug/pprof/trace?seconds=5 - -pprof-mutex: ## Get Go pprof mutex profile. - $(QUIET)$(GO) tool pprof http://localhost:6060/debug/pprof/mutex - -update-authors: ## Update AUTHORS file for Cilium repository. - @echo "Updating AUTHORS file..." - @echo "The following people, in alphabetical order, have either authored or signed" > AUTHORS - @echo "off on commits in the Cilium repository:" >> AUTHORS - @echo "" >> AUTHORS - @contrib/scripts/extract_authors.sh >> AUTHORS - @cat .authors.aux >> AUTHORS - -generate-crd-docs: ## Generate CRD List for documentation - $(QUIET)$(GO) run ./tools/crdlistgen - -test-docs: ## Build HTML documentation. - $(MAKE) -C Documentation html - -render-docs: ## Run server with live preview to render documentation. - $(MAKE) -C Documentation live-preview - -manpages: ## Generate manpage for Cilium CLI. - -rm -r man - mkdir -p man - cilium cmdman -d man - -install-manpages: ## Install manpages the Cilium CLI. - cp man/* /usr/local/share/man/man1/ - mandb - -postcheck: build ## Run Cilium build postcheck (update-cmdref, build documentation etc.). - $(QUIET) SKIP_BUILD=true $(MAKE) $(SUBMAKEOPTS) -C Documentation check - -licenses-all: ## Generate file with all the License from dependencies. - @$(GO) run ./tools/licensegen > LICENSE.all || ( rm -f LICENSE.all ; false ) - -dev-doctor: ## Run Cilium dev-doctor to validate local development environment. - $(QUIET)$(GO) version 2>/dev/null || ( echo "go not found, see https://golang.org/doc/install" ; false ) - $(QUIET)$(GO) run ./tools/dev-doctor - -help: ## Display help for the Makefile, from https://www.thapaliya.com/en/writings/well-documented-makefiles/. - $(call print_help_from_makefile) - @# There is also a list of target we have to manually put the information about. - @# These are templated targets. - $(call print_help_line,"docker-cilium-image","Build cilium-agent docker image") - $(call print_help_line,"dev-docker-image","Build cilium-agent development docker image") - $(call print_help_line,"dev-docker-image-debug","Build cilium-agent development docker debug image") - $(call print_help_line,"docker-plugin-image","Build cilium-docker plugin image") - $(call print_help_line,"docker-hubble-relay-image","Build hubble-relay docker image") - $(call print_help_line,"docker-clustermesh-apiserver-image","Build docker image for Cilium clustermesh APIServer") - $(call print_help_line,"docker-operator-image","Build cilium-operator docker image") - $(call print_help_line,"docker-operator-*-image","Build platform specific cilium-operator images(alibabacloud, aws, azure, generic)") - $(call print_help_line,"docker-operator-*-image-debug","Build platform specific cilium-operator debug images(alibabacloud, aws, azure, generic)") - $(call print_help_line,"docker-*-image-unstripped","Build unstripped version of above docker images(cilium, hubble-relay, operator etc.)") - -.PHONY: help clean clean-container dev-doctor force generate-api generate-health-api generate-operator-api generate-kvstoremesh-api generate-hubble-api generate-sdp-api install licenses-all veryclean run_bpf_tests run-builder -force :; - -BPF_TEST_FILE ?= "" -BPF_TEST_DUMP_CTX ?= "" -BPF_TEST_VERBOSE ?= 0 - -run_bpf_tests: ## Build and run the BPF unit tests using the cilium-builder container image. - DOCKER_ARGS=--privileged RUN_AS_ROOT=1 contrib/scripts/builder.sh \ - "make" "-j$(shell nproc)" "-C" "bpf/tests/" "run" "BPF_TEST_FILE=$(BPF_TEST_FILE)" "BPF_TEST_DUMP_CTX=$(BPF_TEST_DUMP_CTX)" "V=$(BPF_TEST_VERBOSE)" - -run-builder: ## Drop into a shell inside a container running the cilium-builder image. - DOCKER_ARGS=-it contrib/scripts/builder.sh bash - -.PHONY: renovate-local -renovate-local: ## Run a local linter for the renovate configuration - $(CONTAINER_ENGINE) run --rm -ti \ - -e LOG_LEVEL=debug \ - -e GITHUB_COM_TOKEN="$(gh auth token)" \ - -v /tmp:/tmp \ - -v $(ROOT_DIR):/usr/src/app \ - docker.io/renovate/renovate:slim \ - renovate --platform=local diff --git a/vendor/github.com/cilium/cilium/Makefile.defs b/vendor/github.com/cilium/cilium/Makefile.defs deleted file mode 100644 index f96711c4aa..0000000000 --- a/vendor/github.com/cilium/cilium/Makefile.defs +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright Authors of Cilium -# SPDX-License-Identifier: Apache-2.0 - -SHELL := /usr/bin/env bash -.SHELLFLAGS := -eu -o pipefail -c - -# define a function replacing spaces with commas in a list -empty := -space := $(empty) $(empty) -comma := , -join-with-comma = $(subst $(space),$(comma),$(strip $1)) - -define newline - - -endef - -ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) -RELATIVE_DIR := $(shell echo $(realpath .) | sed "s;$(ROOT_DIR)[/]*;;") -include $(ROOT_DIR)/Makefile.quiet - -PREFIX?=/usr -BINDIR?=$(PREFIX)/bin -CNIBINDIR?=/opt/cni/bin -CNICONFDIR?=/etc/cni/net.d -LIBDIR?=$(PREFIX)/lib -LOCALSTATEDIR?=/var -RUNDIR?=/var/run -CONFDIR?=/etc - -export GO ?= go -NATIVE_ARCH = $(shell GOARCH= $(GO) env GOARCH) -export GOARCH ?= $(NATIVE_ARCH) - -INSTALL = install - -CONTAINER_ENGINE?=docker -DOCKER_FLAGS?= -DOCKER_BUILD_FLAGS?= - -# use gsed if available, otherwise use sed. -# gsed is needed for MacOS to make in-place replacement work correctly. -SED ?= $(if $(shell command -v gsed),gsed,sed) - -# Set DOCKER_DEV_ACCOUNT with "cilium" by default -ifeq ($(DOCKER_DEV_ACCOUNT),) - DOCKER_DEV_ACCOUNT=cilium -endif - -ifneq ($(CI_BUILD),) - DOCKER_IMAGE_SUFFIX=-ci - DOCKER_IMAGE_TAG=$(shell git rev-parse HEAD) -endif - -# Set DOCKER_IMAGE_TAG with "latest" by default -ifeq ($(DOCKER_IMAGE_TAG),) - DOCKER_IMAGE_TAG=latest -endif - -# renovate: datasource=docker depName=gcr.io/etcd-development/etcd -ETCD_IMAGE_VERSION = v3.5.19 -ETCD_IMAGE_SHA = sha256:c415170328bbb2cb497c79dbd8494b1c8d58886dccf95fbfdd3845c13c6d1ca3 -ETCD_IMAGE=gcr.io/etcd-development/etcd:$(ETCD_IMAGE_VERSION)@$(ETCD_IMAGE_SHA) - -CILIUM_BUILDER_IMAGE=$(shell cat $(ROOT_DIR)/images/cilium/Dockerfile | grep "ARG CILIUM_BUILDER_IMAGE=" | cut -d"=" -f2) - -export CILIUM_CLI ?= cilium -export KUBECTL ?= kubectl - -# Till the self-hosted renovate PR #30185 is merged, we might need to run the below -# command locally for any version update. -# make generate-api generate-health-api generate-hubble-api generate-operator-api generate-kvstoremesh-api -# renovate: datasource=docker depName=quay.io/goswagger/swagger -SWAGGER_VERSION = 0.31.0 -SWAGGER_IMAGE_SHA = sha256:5f36c14131ea569ad687ac546d6cdd2ccf0feff662eae5f5bf37d9d8a0b51cbc -SWAGGER := $(CONTAINER_ENGINE) run -u $(shell id -u):$(shell id -g) --rm -v $(ROOT_DIR):$(ROOT_DIR) -w $(ROOT_DIR) --entrypoint swagger quay.io/goswagger/swagger:$(SWAGGER_VERSION)@$(SWAGGER_IMAGE_SHA) - -# go build/test/clean flags -# these are declared here so they are treated explicitly -# as non-immediate variables -GO_BUILD_FLAGS ?= -GO_TEST_FLAGS ?= -GO_CLEAN_FLAGS ?= -GO_BUILD_LDFLAGS ?= -# go build/test -tags values -GO_TAGS_FLAGS += osusergo - -# This is declared here as it is needed to change the covermode depending on if -# RACE is specified. -GOTEST_COVER_OPTS = - -# By default, just print go test output immediately to the terminal. If tparse -# is installed, use it to format the output. Use -progress instead of -follow, -# as the latter is too verbose for most of the test suite. -GOTEST_FORMATTER ?= cat -ifneq ($(shell command -v tparse),) - GOTEST_COVER_OPTS += -json - GOTEST_FORMATTER_FLAGS := -ifneq ($(V),0) - GOTEST_FORMATTER_FLAGS += -follow -endif -ifneq ($(LOG_CODEOWNERS),) - GOTEST_FORMATTER = tee >($(GO) run ./tools/testowners) >(tparse $(GOTEST_FORMATTER_FLAGS)) >/dev/null -else - GOTEST_FORMATTER = tparse $(GOTEST_FORMATTER_FLAGS) -endif -endif - -# renovate: datasource=docker depName=golangci/golangci-lint -GOLANGCILINT_WANT_VERSION = v1.64.5 -GOLANGCILINT_IMAGE_SHA = sha256:9faef4dda4304c4790a14c5b8c8cd8c2715a8cb754e13f61d8ceaa358f5a454a -GOLANGCILINT_VERSION = $(shell golangci-lint version --format short 2>/dev/null) - -VERSION = $(shell cat $(dir $(lastword $(MAKEFILE_LIST)))/VERSION) -VERSION_MAJOR = $(shell cat $(dir $(lastword $(MAKEFILE_LIST)))/VERSION | cut -d. -f1) -# Use git only if in a Git repo -ifneq ($(wildcard $(dir $(lastword $(MAKEFILE_LIST)))/.git/HEAD),) - GIT_VERSION = $(shell git show -s --format='format:%h %aI') -else - GIT_VERSION = $(shell cat 2>/dev/null $(ROOT_DIR)/GIT_VERSION) -endif -FULL_BUILD_VERSION = $(VERSION) $(GIT_VERSION) -GO_BUILD_LDFLAGS += -X "github.com/cilium/cilium/pkg/version.ciliumVersion=$(FULL_BUILD_VERSION)" - -ifeq ($(NOSTRIP),) - # Note: these options will not remove annotations needed for stack - # traces, so panic backtraces will still be readable. - # - # -w: Omit the DWARF symbol table. - # -s: Omit the symbol table and debug information. - GO_BUILD_LDFLAGS += -s -w -endif - -ifneq ($(wildcard $(dir $(lastword $(MAKEFILE_LIST)))/images/cilium/Dockerfile),) - CILIUM_ENVOY_REF=$(shell sed -E -e 's/^ARG CILIUM_ENVOY_IMAGE=([^ ]*)/\1/p;d' < $(ROOT_DIR)/images/cilium/Dockerfile) - CILIUM_ENVOY_SHA=$(shell echo $(CILIUM_ENVOY_REF) | sed -E -e 's/[^/]*\/[^:]*:(.*-)?([^:@]*).*/\2/p;d') - GO_BUILD_LDFLAGS += -X "github.com/cilium/cilium/pkg/envoy.requiredEnvoyVersionSHA=$(CILIUM_ENVOY_SHA)" -endif - -# Use git only if in a Git repo, otherwise find the files from the file system -BPF_SRCFILES_IGNORE = bpf/.gitignore -ifneq ($(wildcard $(dir $(lastword $(MAKEFILE_LIST)))/.git/HEAD),) - BPF_SRCFILES := $(shell git ls-files $(ROOT_DIR)/bpf/ | LC_ALL=C sort | tr "\n" ' ') -else - # this line has to be in-sync with bpf/.gitignore, please note usage of make patterns like `%.i` - BPF_SRCFILES_IGNORE += bpf/%.i bpf/%.s bpf/.rebuild_all - BPF_SRCFILES := $(shell find $(ROOT_DIR)/bpf/ -type f | LC_ALL=C sort | tr "\n" ' ') -endif - -# ROOT_DIR can be either `../` or absolute path, each of these need to be stripped -BPF_SRCFILES := $(filter-out $(BPF_SRCFILES_IGNORE),$(subst ../,,$(subst $(ROOT_DIR)/,,$(BPF_SRCFILES)))) - -GO_BUILD_FLAGS += -mod=vendor -GO_TEST_FLAGS += -mod=vendor -vet=all -GO_CLEAN_FLAGS += -mod=vendor - -GO_BUILD = CGO_ENABLED=0 $(GO) build - -# Support CGO cross-compiling for amd64 and arm64 targets -CGO_CC = -CROSS_ARCH = -ifneq ($(GOARCH),$(NATIVE_ARCH)) - CROSS_ARCH = $(GOARCH) -endif -ifeq ($(CROSS_ARCH),arm64) - CGO_CC = CC=aarch64-linux-gnu-gcc -else ifeq ($(CROSS_ARCH),amd64) - CGO_CC = CC=x86_64-linux-gnu-gcc -endif -GO_BUILD_WITH_CGO = CGO_ENABLED=1 $(CGO_CC) $(GO) build - -ifneq ($(RACE),) - GO_BUILD_FLAGS += -race - GO_TEST_FLAGS += -race - GOTEST_COVER_OPTS += -covermode=atomic - - # GO_BUILD becomes GO_BUILD_WITH_CGO as `-race` requires CGO - GO_BUILD = $(GO_BUILD_WITH_CGO) - ifeq ($(LOCKDEBUG),) - LOCKDEBUG=1 - endif -else - GOTEST_COVER_OPTS += -covermode=count -endif - -ifneq ($(LOCKDEBUG),) - GO_TAGS_FLAGS += lockdebug -endif - -GO_BUILD_FLAGS += -ldflags '$(GO_BUILD_LDFLAGS) $(EXTRA_GO_BUILD_LDFLAGS)' -tags=$(call join-with-comma,$(GO_TAGS_FLAGS)) $(EXTRA_GO_BUILD_FLAGS) -GO_TEST_FLAGS += -tags=$(call join-with-comma,$(GO_TAGS_FLAGS)) - -ifeq ($(NOOPT),1) - GO_BUILD_FLAGS += -gcflags="all=-N -l" -endif - -GO_BUILD += $(GO_BUILD_FLAGS) -GO_BUILD_WITH_CGO += $(GO_BUILD_FLAGS) - -GO_TEST = CGO_ENABLED=0 $(GO) test $(GO_TEST_FLAGS) -GO_CLEAN = $(GO) clean $(GO_CLEAN_FLAGS) - -GO_VET = $(GO) vet -GO_LIST = $(GO) list - -HELM_TOOLBOX_VERSION ?= "v1.1.0" -HELM_TOOLBOX_SHA ?= "961693f182b9b456ed90e5274ac5df81e4af4343104e252666959cdf9570ce9e" -HELM_TOOLBOX_IMAGE ?= "quay.io/cilium/helm-toolbox:$(HELM_TOOLBOX_VERSION)@sha256:$(HELM_TOOLBOX_SHA)" - -YQ_VERSION ?= "4.40.5" -YQ_SHA ?= "32be61dc94d0acc44f513ba69d0fc05f1f92c2e760491f2a27e11fc13cde6327" -YQ_IMAGE ?= "docker.io/mikefarah/yq:$(YQ_VERSION)@sha256:$(YQ_SHA)" - -define print_help_line - @printf " \033[36m%-29s\033[0m %s.\n" $(1) $(2) -endef - -define print_help_from_makefile - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9][a-zA-Z0-9 _-]*:.*?##/ { split($$1, targets, " "); for (i in targets) { printf " \033[36m%-28s\033[0m %s\n", targets[i], $$2 } } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) -endef - -# Use to ensure the CWD, or any child of it, belongs to Cilium's go module. -CILIUM_GO_MODULE = github.com/cilium/cilium -CURRENT_GO_MODULE = $(shell go list -m) -define ASSERT_CILIUM_MODULE - $(if $(filter $(CILIUM_GO_MODULE), $(CURRENT_GO_MODULE)) ,, $(error "Could not locate Cilium's go.mod file, are you in Cilium's repository?")) -endef diff --git a/vendor/github.com/cilium/cilium/Makefile.docker b/vendor/github.com/cilium/cilium/Makefile.docker deleted file mode 100644 index 026d516872..0000000000 --- a/vendor/github.com/cilium/cilium/Makefile.docker +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright Authors of Cilium -# SPDX-License-Identifier: Apache-2.0 - -DOCKER_BUILDER := default - -# Export with value expected by docker -export DOCKER_BUILDKIT=1 - -# Docker Buildx support. If ARCH is defined, a builder instance 'cross' -# on the local node is configured for amd64 and arm64 platform targets. -# Otherwise build on the current (typically default) builder for the host -# platform only. -ifdef ARCH - # Default to multi-arch builds, always create the builder for all the platforms we support - DOCKER_PLATFORMS := linux/arm64,linux/amd64 - DOCKER_BUILDER := $(shell docker buildx ls | grep -E -e "[a-zA-Z0-9-]+ \*" | cut -d ' ' -f1) - ifneq (,$(filter $(DOCKER_BUILDER),default desktop-linux)) - DOCKER_BUILDKIT_DRIVER := - ifdef DOCKER_BUILDKIT_IMAGE - DOCKER_BUILDKIT_DRIVER := --driver docker-container --driver-opt image=$(DOCKER_BUILDKIT_IMAGE) - endif - BUILDER_SETUP := $(shell docker buildx create --platform $(DOCKER_PLATFORMS) $(DOCKER_BUILDKIT_DRIVER) --use) - endif - # Override default for a single platform - ifneq ($(ARCH),multi) - DOCKER_PLATFORMS := linux/$(ARCH) - endif - DOCKER_FLAGS += --push --platform $(DOCKER_PLATFORMS) -else - ifeq ($(findstring --output,$(DOCKER_FLAGS)),) - ifeq ($(findstring --push,$(DOCKER_FLAGS)),) - # ARCH, --output, and --push are not specified, build for the host platform without pushing, mimicking regular docker build - DOCKER_FLAGS += --load - endif - endif -endif -DOCKER_EXISTS := $(shell command -v docker 2>/dev/null) -ifdef DOCKER_EXISTS -DOCKER_BUILDER := $(shell docker buildx ls | grep -E -e "[a-zA-Z0-9-]+ \*" | cut -d ' ' -f1) -endif - -##@ Docker Images -.PHONY: builder-info -builder-info: ## Print information about the docker builder that will be used for building images. - @echo "Using Docker Buildx builder \"$(DOCKER_BUILDER)\" with build flags \"$(DOCKER_FLAGS)\"." - -# Generic rule for augmented .dockerignore files. -GIT_IGNORE_FILES := $(shell find . -not -path "./vendor*" -name .gitignore -print) -.PRECIOUS: %.dockerignore -%.dockerignore: $(GIT_IGNORE_FILES) Makefile.docker - @-mkdir -p $(dir $@) - @echo "/hack" > $@ - @echo ".git" >> $@ - @echo "/Makefile.docker" >> $@ - @echo $(dir $(GIT_IGNORE_FILES)) | tr ' ' '\n' | xargs -P1 -I {DIR} -n1 sed \ - -e '# Remove lines with white space, comments and files that must be passed to docker, "$$" due to make. #' \ - -e '/^[[:space:]]*$$/d' -e '/^#/d' -e '/GIT_VERSION/d' \ - -e '# Apply pattern in all directories if it contains no "/", keep "!" up front. #' \ - -e '/^[^!/][^/]*$$/s<^<**/<' -e '/^![^/]*$$/s<^!> $@ - -DOCKER_REGISTRY ?= quay.io -ifeq ($(findstring /,$(DOCKER_DEV_ACCOUNT)),/) - # DOCKER_DEV_ACCOUNT already contains '/', assume it specifies a registry - IMAGE_REPOSITORY := $(DOCKER_DEV_ACCOUNT) -else - IMAGE_REPOSITORY := $(DOCKER_REGISTRY)/$(DOCKER_DEV_ACCOUNT) -endif - -# -# Template for Docker images. Paramaters are: -# $(1) image target name -# $(2) Dockerfile path -# $(3) image name stem (e.g., cilium, cilium-operator, etc) -# $(4) image tag -# $(5) target -# -define DOCKER_IMAGE_TEMPLATE -.PHONY: $(1) -$(1): GIT_VERSION $(2) $(2).dockerignore GIT_VERSION builder-info - $(ECHO_DOCKER)$(2) $(IMAGE_REPOSITORY)/$(IMAGE_NAME)$${UNSTRIPPED}:$(4) - $(eval IMAGE_NAME := $(subst %,$$$$*,$(3))) -ifeq ($(5),debug) - @export NOSTRIP=1 -endif - $(QUIET) $(CONTAINER_ENGINE) buildx build -f $(subst %,$$*,$(2)) \ - $(DOCKER_BUILD_FLAGS) $(DOCKER_FLAGS) \ - $(if $(BASE_IMAGE),--build-arg BASE_IMAGE=$(BASE_IMAGE),) \ - --build-arg MODIFIERS="NOSTRIP=$${NOSTRIP} NOOPT=${NOOPT} LOCKDEBUG=${LOCKDEBUG} RACE=${RACE} V=${V} LIBNETWORK_PLUGIN=${LIBNETWORK_PLUGIN} ${ADDITIONAL_MODIFIERS}" \ - --build-arg CILIUM_SHA=$(firstword $(GIT_VERSION)) \ - --build-arg OPERATOR_VARIANT=$(IMAGE_NAME) \ - --build-arg DEBUG_HOLD=$(DEBUG_HOLD) \ - --target $(5) \ - -t $(IMAGE_REPOSITORY)/$(IMAGE_NAME)$${UNSTRIPPED}$(DOCKER_IMAGE_SUFFIX):$(4) . -ifneq ($(KIND_LOAD),) - sleep 1 - kind load docker-image $(IMAGE_REPOSITORY)/$(IMAGE_NAME)$${UNSTRIPPED}$(DOCKER_IMAGE_SUFFIX):$(4) -else - ifeq ($(findstring --push,$(DOCKER_FLAGS)),) - @echo 'Define "DOCKER_FLAGS=--push" to push the build results.' - else - $(CONTAINER_ENGINE) buildx imagetools inspect $(IMAGE_REPOSITORY)/$(IMAGE_NAME)$${UNSTRIPPED}$(DOCKER_IMAGE_SUFFIX):$(4) - @echo '^^^ Images pushed, multi-arch manifest should be above. ^^^' - endif -endif - -$(1)-unstripped: NOSTRIP=1 -$(1)-unstripped: UNSTRIPPED=-unstripped -$(1)-unstripped: $(1) - @echo -endef - -# docker-cilium-image -$(eval $(call DOCKER_IMAGE_TEMPLATE,docker-cilium-image,images/cilium/Dockerfile,cilium,$(DOCKER_IMAGE_TAG),release)) - -# dev-docker-image -$(eval $(call DOCKER_IMAGE_TEMPLATE,dev-docker-image,images/cilium/Dockerfile,cilium-dev,$(DOCKER_IMAGE_TAG),release)) - -# dev-docker-image-debug -$(eval $(call DOCKER_IMAGE_TEMPLATE,dev-docker-image-debug,images/cilium/Dockerfile,cilium-dev,$(DOCKER_IMAGE_TAG),debug)) - -# docker-plugin-image -$(eval $(call DOCKER_IMAGE_TEMPLATE,docker-plugin-image,images/cilium-docker-plugin/Dockerfile,docker-plugin,$(DOCKER_IMAGE_TAG),release)) - -# docker-hubble-relay-image -$(eval $(call DOCKER_IMAGE_TEMPLATE,docker-hubble-relay-image,images/hubble-relay/Dockerfile,hubble-relay,$(DOCKER_IMAGE_TAG),release)) - -# docker-clustermesh-apiserver-image -$(eval $(call DOCKER_IMAGE_TEMPLATE,docker-clustermesh-apiserver-image,images/clustermesh-apiserver/Dockerfile,clustermesh-apiserver,$(DOCKER_IMAGE_TAG),release)) - -# docker-operator-images. -# We eat the ending of "operator" in to the stem ('%') to allow this pattern -# to build also 'docker-operator-image', where the stem would be empty otherwise. -$(eval $(call DOCKER_IMAGE_TEMPLATE,docker-opera%-image,images/operator/Dockerfile,opera%,$(DOCKER_IMAGE_TAG),release)) -$(eval $(call DOCKER_IMAGE_TEMPLATE,dev-docker-opera%-image,images/operator/Dockerfile,opera%,$(DOCKER_IMAGE_TAG),release)) -$(eval $(call DOCKER_IMAGE_TEMPLATE,dev-docker-opera%-image-debug,images/operator/Dockerfile,opera%,$(DOCKER_IMAGE_TAG),debug)) - -# -# docker-*-all targets are mainly used from the CI -# -docker-images-all: docker-cilium-image docker-plugin-image docker-hubble-relay-image docker-clustermesh-apiserver-image docker-operator-images-all ## Build all Cilium related docker images. - -docker-images-all-unstripped: docker-cilium-image-unstripped docker-plugin-image-unstripped docker-hubble-relay-image-unstripped docker-clustermesh-apiserver-image-unstripped docker-operator-images-all-unstripped ## Build all Cilium related unstripped docker images. - -docker-operator-images-all: docker-operator-image docker-operator-aws-image docker-operator-azure-image docker-operator-alibabacloud-image docker-operator-generic-image ## Build all variants of cilium-operator images. - -docker-operator-images-all-unstripped: docker-operator-image-unstripped docker-operator-aws-image-unstripped docker-operator-azure-image-unstripped docker-operator-alibabacloud-image-unstripped docker-operator-generic-image-unstripped ## Build all variants of unstripped cilium-operator images. diff --git a/vendor/github.com/cilium/cilium/Makefile.kind b/vendor/github.com/cilium/cilium/Makefile.kind deleted file mode 100644 index a2cf93c76d..0000000000 --- a/vendor/github.com/cilium/cilium/Makefile.kind +++ /dev/null @@ -1,494 +0,0 @@ -# Copyright Authors of Cilium -# SPDX-License-Identifier: Apache-2.0 - -##@ Development (Kind) - -WAIT_DURATION ?= 30s - -.PHONY: kind -kind: ## Create a kind cluster for Cilium development. - $(QUIET)SED=$(SED) ./contrib/scripts/kind.sh - -.PHONY: kind-egressgw -kind-egressgw: ## Create a kind cluster for egress gateway Cilium development. - $(QUIET)SED=$(SED) WORKERS=3 ./contrib/scripts/kind.sh - kubectl patch node kind-worker3 --type=json -p='[{"op":"add","path":"/metadata/labels/cilium.io~1no-schedule","value":"true"}]' - -.PHONY: kind-down -kind-down: ## Destroy a kind cluster for Cilium development. - $(QUIET)./contrib/scripts/kind-down.sh - -.PHONY: kind-clustermesh -kind-clustermesh: ## Create two kind clusters for clustermesh development. - @echo " If you have problems with too many open file, check https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files" - $(QUIET) CLUSTER_NAME=clustermesh1 IPFAMILY=dual PODSUBNET=10.1.0.0/16,fd00:10:1::/48 SERVICESUBNET=172.20.1.0/24,fd00:10:f1::/112 ./contrib/scripts/kind.sh - $(QUIET) CLUSTER_NAME=clustermesh2 AGENTPORTPREFIX=236 OPERATORPORTPREFIX=237 IPFAMILY=dual PODSUBNET=10.2.0.0/16,fd00:10:2::/48 SERVICESUBNET=172.20.2.0/24,fd00:10:f2::/112 ./contrib/scripts/kind.sh - -.PHONY: kind-clustermesh-down -kind-clustermesh-down: ## Destroy kind clusters for clustermesh development. - $(QUIET)./contrib/scripts/kind-down.sh clustermesh1 clustermesh2 - -.PHONY: kind-clustermesh-ready -kind-clustermesh-ready: ## Check if both kind clustermesh clusters exist - @$(ECHO_CHECK) clustermesh kind is ready... - @kind get clusters 2>&1 | grep "clustermesh1" \ - && exit 0 || exit 1 - @kind get clusters 2>&1 | grep "clustermesh2" \ - && exit 0 || exit 1 - -.PHONY: kind-bgp-v4 -kind-bgp-v4: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-v4 deploy - -.PHONY: kind-bgp-v4-down -kind-bgp-v4-down: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-v4 destroy - -.PHONY: kind-bgp-v4-apply-policy -kind-bgp-v4-apply-policy: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-v4 apply-policy - -.PHONY: kind-bgp-v6 -kind-bgp-v6: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-v6 deploy - -.PHONY: kind-bgp-v6-down -kind-bgp-v6-down: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-v6 destroy - -.PHONY: kind-bgp-v6-apply-policy -kind-bgp-v6-apply-policy: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-v6 apply-policy - -.PHONY: kind-bgp-dual -kind-bgp-dual: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-dual deploy - -.PHONY: kind-bgp-dual-down -kind-bgp-dual-down: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-dual destroy - -.PHONY: kind-bgp-dual-apply-policy -kind-bgp-dual-apply-policy: - $(QUIET) $(MAKE) -C contrib/containerlab/bgp-cplane-dev-dual apply-policy - -# Template for kind environment for a target. Parameters are: -# $(1) Makefile target name -define KIND_ENV -.PHONY: $(1) -$(1): export DOCKER_REGISTRY=localhost:5000 -$(1): export LOCAL_AGENT_IMAGE=$$(DOCKER_REGISTRY)/$$(DOCKER_DEV_ACCOUNT)/cilium-dev:$$(LOCAL_IMAGE_TAG) -$(1): export LOCAL_OPERATOR_IMAGE=$$(DOCKER_REGISTRY)/$$(DOCKER_DEV_ACCOUNT)/operator-generic:$$(LOCAL_IMAGE_TAG) -$(1): export LOCAL_CLUSTERMESH_IMAGE=$$(DOCKER_REGISTRY)/$$(DOCKER_DEV_ACCOUNT)/clustermesh-apiserver:$$(LOCAL_IMAGE_TAG) -endef - -$(eval $(call KIND_ENV,kind-clustermesh-images)) -kind-clustermesh-images: kind-clustermesh-ready kind-build-clustermesh-apiserver kind-build-image-agent kind-build-image-operator ## Builds images and imports them into clustermesh clusters - $(QUIET)kind load docker-image $(LOCAL_CLUSTERMESH_IMAGE) --name clustermesh1 - $(QUIET)kind load docker-image $(LOCAL_CLUSTERMESH_IMAGE) --name clustermesh2 - $(QUIET)kind load docker-image $(LOCAL_AGENT_IMAGE) --name clustermesh1 - $(QUIET)kind load docker-image $(LOCAL_AGENT_IMAGE) --name clustermesh2 - $(QUIET)kind load docker-image $(LOCAL_OPERATOR_IMAGE) --name clustermesh1 - $(QUIET)kind load docker-image $(LOCAL_OPERATOR_IMAGE) --name clustermesh2 - -.PHONY: kind-connect-clustermesh ## Connect the ClusterMesh clusters. -kind-connect-clustermesh: check_deps kind-clustermesh-ready - @echo " CONNECT the two clusters" - $(CILIUM_CLI) clustermesh connect --context kind-clustermesh1 --destination-context kind-clustermesh2 - $(CILIUM_CLI) clustermesh status --context kind-clustermesh1 --wait - $(CILIUM_CLI) clustermesh status --context kind-clustermesh2 --wait - -ENABLE_KVSTOREMESH ?= true -$(eval $(call KIND_ENV,kind-install-cilium-clustermesh)) -kind-install-cilium-clustermesh: check_deps kind-clustermesh-ready ## Install a local Cilium version into the clustermesh clusters and enable clustermesh. - @echo " INSTALL cilium on clustermesh1 cluster" - -$(CILIUM_CLI) --context=kind-clustermesh1 uninstall >/dev/null - $(CILIUM_CLI) --context=kind-clustermesh1 install \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - --values=$(ROOT_DIR)/contrib/testing/kind-clustermesh1.yaml \ - --set=image.override=$(LOCAL_AGENT_IMAGE) \ - --set=operator.image.override=$(LOCAL_OPERATOR_IMAGE) \ - --set=clustermesh.apiserver.image.override=$(LOCAL_CLUSTERMESH_IMAGE) \ - --set=clustermesh.apiserver.kvstoremesh.enabled=$(ENABLE_KVSTOREMESH) - - @echo " INSTALL cilium on clustermesh2 cluster" - -$(CILIUM_CLI) --context=kind-clustermesh2 uninstall >/dev/null - $(KUBECTL) --context=kind-clustermesh1 get secret -n kube-system cilium-ca -o yaml | \ - $(KUBECTL) --context=kind-clustermesh2 replace --force -f - - $(CILIUM_CLI) --context=kind-clustermesh2 install \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - --values=$(ROOT_DIR)/contrib/testing/kind-clustermesh2.yaml \ - --set=image.override=$(LOCAL_AGENT_IMAGE) \ - --set=operator.image.override=$(LOCAL_OPERATOR_IMAGE) \ - --set=clustermesh.apiserver.image.override=$(LOCAL_CLUSTERMESH_IMAGE) \ - --set=clustermesh.apiserver.kvstoremesh.enabled=$(ENABLE_KVSTOREMESH) - - $(MAKE) kind-connect-clustermesh - -.PHONY: kind-install-cilium-clustermesh-fast -kind-install-cilium-clustermesh-fast: check_deps kind-clustermesh-ready ## "Fast" Install a local Cilium version using volume-mounted binaries into the ClusterMesh clusters and enable ClusterMesh. - @echo " INSTALL cilium on clustermesh1 cluster" - docker pull quay.io/cilium/cilium-ci:latest - kind load docker-image --name clustermesh1 quay.io/cilium/cilium-ci:latest - -$(CILIUM_CLI) --context=kind-clustermesh1 uninstall >/dev/null - $(CILIUM_CLI) --context=kind-clustermesh1 install \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - --values=$(ROOT_DIR)/contrib/testing/kind-clustermesh1.yaml \ - --values=$(ROOT_DIR)/contrib/testing/kind-fast.yaml \ - --set=clustermesh.apiserver.kvstoremesh.enabled=$(ENABLE_KVSTOREMESH) - - @echo " INSTALL cilium on clustermesh2 cluster" - kind load docker-image --name clustermesh2 quay.io/cilium/cilium-ci:latest - -$(CILIUM_CLI) --context=kind-clustermesh2 uninstall >/dev/null - $(KUBECTL) --context=kind-clustermesh1 get secret -n kube-system cilium-ca -o yaml | \ - $(KUBECTL) --context=kind-clustermesh2 replace --force -f - - $(CILIUM_CLI) --context=kind-clustermesh2 install \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - --values=$(ROOT_DIR)/contrib/testing/kind-clustermesh2.yaml \ - --values=$(ROOT_DIR)/contrib/testing/kind-fast.yaml \ - --set=clustermesh.apiserver.kvstoremesh.enabled=$(ENABLE_KVSTOREMESH) - - $(MAKE) kind-image-fast - $(MAKE) kind-connect-clustermesh - -KIND_CLUSTER_NAME ?= $(shell kind get clusters -q | head -n1) - -.PHONY: kind-ready -kind-ready: - @$(ECHO_CHECK) kind-ready - @if [ -n "$(shell kind get clusters -q)" ]; then echo "kind is ready"; else echo "kind not ready"; exit 1; fi - -$(eval $(call KIND_ENV,kind-build-image-agent)) -kind-build-image-agent: ## Build cilium-dev docker image - $(QUIET)$(MAKE) dev-docker-image$(DEBUGGER_SUFFIX) DOCKER_IMAGE_TAG=$(LOCAL_IMAGE_TAG) - -$(eval $(call KIND_ENV,kind-image-agent)) -kind-image-agent: .SHELLFLAGS=-c -kind-image-agent: kind-ready kind-build-image-agent ## Build cilium-dev docker image and import it into kind. - $(QUIET)kind load docker-image $(LOCAL_AGENT_IMAGE) -n $(KIND_CLUSTER_NAME); \ - [ $$? -eq 0 ] || $(QUIET)kind load docker-image $(LOCAL_AGENT_IMAGE) -n $(KIND_CLUSTER_NAME) - -$(eval $(call KIND_ENV,kind-build-image-operator)) -kind-build-image-operator: ## Build cilium-operator-dev docker image - $(QUIET)$(MAKE) dev-docker-operator-generic-image$(DEBUGGER_SUFFIX) DOCKER_IMAGE_TAG=$(LOCAL_IMAGE_TAG) - -$(eval $(call KIND_ENV,kind-image-operator)) -kind-image-operator: .SHELLFLAGS=-c -kind-image-operator: kind-ready kind-build-image-operator ## Build cilium-operator-dev docker image and import it into kind. - $(QUIET)kind load docker-image $(LOCAL_OPERATOR_IMAGE) -n $(KIND_CLUSTER_NAME); \ - [ $$? -eq 0 ] || $(QUIET)kind load docker-image $(LOCAL_OPERATOR_IMAGE) -n $(KIND_CLUSTER_NAME) - -$(eval $(call KIND_ENV,kind-build-clustermesh-apiserver)) -kind-build-clustermesh-apiserver: ## Build cilium-clustermesh-apiserver docker image - $(QUIET)$(MAKE) docker-clustermesh-apiserver-image DOCKER_IMAGE_TAG=$(LOCAL_IMAGE_TAG) - -.PHONY: kind-image -kind-image: ## Build cilium and operator images and import them into kind. - $(MAKE) kind-image-agent - $(MAKE) kind-image-operator - -define KIND_VALUES_FAST_FILES ---helm-values=$(ROOT_DIR)/contrib/testing/kind-common.yaml \ ---helm-values=$(ROOT_DIR)/contrib/testing/kind-fast.yaml -endef - -ifneq ("$(wildcard $(ROOT_DIR)/contrib/testing/kind-custom.yaml)","") - KIND_VALUES_FAST_FILES := $(KIND_VALUES_FAST_FILES) --helm-values=$(ROOT_DIR)/contrib/testing/kind-custom.yaml -endif - -ifdef ADDITIONAL_KIND_VALUES_FILE - KIND_VALUES_FAST_FILES := $(KIND_VALUES_FAST_FILES) --helm-values=$(ROOT_DIR)/$(ADDITIONAL_KIND_VALUES_FILE) -endif - -.PHONY: kind-install-cilium-fast -kind-install-cilium-fast: .SHELLFLAGS=-c -kind-install-cilium-fast: check_deps kind-ready ## "Fast" Install a local Cilium version using volume-mounted binaries into all clusters. - @echo " INSTALL cilium" - docker pull quay.io/cilium/cilium-ci:latest - for cluster_name in $${KIND_CLUSTERS:-$(shell kind get clusters)}; do \ - kind load docker-image --name $$cluster_name quay.io/cilium/cilium-ci:latest; \ - [ $$? -eq 0 ] || kind load docker-image --name $$cluster_name quay.io/cilium/cilium-ci:latest; \ - $(CILIUM_CLI) --context=kind-$$cluster_name uninstall >/dev/null 2>&1 || true; \ - $(CILIUM_CLI) install --context=kind-$$cluster_name \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - $(KIND_VALUES_FAST_FILES) \ - --version= >/dev/null ; \ - done - -.PHONY: build-cli -build-cli: ## Build cilium cli binary - $(QUIET)$(MAKE) -C cilium-dbg GOOS=linux - -.PHONY: build-agent -build-agent: ## Build cilium daemon binary - $(QUIET)$(MAKE) -C daemon GOOS=linux - -.PHONY: build-operator -build-operator: ## Build cilium operator binary - $(QUIET)$(MAKE) -C operator cilium-operator-generic GOOS=linux - -.PHONY: build-clustermesh-apiserver -build-clustermesh-apiserver: ## Build cilium clustermesh-apiserver binary - $(QUIET)$(MAKE) -C clustermesh-apiserver GOOS=linux - -.PHONY: build-hubble-cli -build-hubble-cli: ## Build hubble cli binary - $(QUIET)$(MAKE) -C hubble GOOS=linux - -.PHONY: build-bugtool -build-bugtool: ## Build bugtool binary - $(QUIET)$(MAKE) -C bugtool GOOS=linux - -.PHONY: kind-image-fast-agent -kind-image-fast-agent: kind-ready build-cli build-agent build-hubble-cli build-bugtool ## Build cilium cli, daemon binaries, and hubble cli. Copy the bins and bpf files to kind nodes. - $(eval dst:=/cilium-binaries) - for cluster_name in $${KIND_CLUSTERS:-$(shell kind get clusters)}; do \ - for node_name in $$(kind get nodes -n "$$cluster_name"); do \ - docker exec $${node_name} mkdir -p "${dst}"; \ - \ - docker exec $${node_name} rm -rf "${dst}/var/lib/cilium"; \ - docker exec $${node_name} mkdir -p "${dst}/var/lib/cilium"; \ - docker cp "./bpf/" $${node_name}:"${dst}/var/lib/cilium/bpf"; \ - docker exec $${node_name} find "${dst}/var/lib/cilium/bpf" -type f -exec chmod 0644 {} + ;\ - \ - docker exec $${node_name} rm -f "${dst}/cilium-dbg"; \ - docker cp "./cilium-dbg/cilium-dbg" $${node_name}:"${dst}"; \ - docker exec $${node_name} chmod +x "${dst}/cilium-dbg"; \ - \ - docker exec $${node_name} rm -f "${dst}/cilium-agent"; \ - docker cp "./daemon/cilium-agent" $${node_name}:"${dst}"; \ - docker exec $${node_name} chmod +x "${dst}/cilium-agent"; \ - \ - docker exec $${node_name} rm -f "${dst}/hubble"; \ - docker cp "./hubble/hubble" $${node_name}:"${dst}"; \ - docker exec $${node_name} chmod +x "${dst}/hubble"; \ - \ - docker exec $${node_name} rm -f "${dst}/cilium-bugtool"; \ - docker cp "./bugtool/cilium-bugtool" $${node_name}:"${dst}"; \ - docker exec $${node_name} chmod +x "${dst}/cilium-bugtool"; \ - done; \ - kubectl --context=kind-$${cluster_name} delete pods -n kube-system -l k8s-app=cilium --force; \ - done - -.PHONY: kind-image-fast-operator -kind-image-fast-operator: kind-ready build-operator ## Build cilium operator binary and copy it to all kind nodes. - $(eval dst:=/cilium-binaries) - for cluster_name in $${KIND_CLUSTERS:-$(shell kind get clusters)}; do \ - for node_name in $$(kind get nodes -n "$$cluster_name"); do \ - docker exec $${node_name} mkdir -p "${dst}"; \ - \ - docker exec $${node_name} rm -f "${dst}/cilium-operator-generic"; \ - docker cp "./operator/cilium-operator-generic" $${node_name}:"${dst}"; \ - docker exec $${node_name} chmod +x "${dst}/cilium-operator-generic"; \ - done; \ - kubectl --context=kind-$${cluster_name} delete pods -n kube-system -l name=cilium-operator --force; \ - done - -.PHONY: kind-image-fast-clustermesh-apiserver -kind-image-fast-clustermesh-apiserver: kind-ready build-clustermesh-apiserver ## Build clustermesh-apiserver binary and copy it to all kind nodes. - $(eval dst:=/cilium-binaries) - for cluster_name in $${KIND_CLUSTERS:-$(shell kind get clusters)}; do \ - for node_name in $$(kind get nodes -n "$$cluster_name"); do \ - docker exec $${node_name} mkdir -p "${dst}"; \ - \ - docker exec $${node_name} rm -f "${dst}/clustermesh-apiserver"; \ - docker cp "./clustermesh-apiserver/clustermesh-apiserver" $${node_name}:"${dst}"; \ - docker exec $${node_name} chmod +x "${dst}/clustermesh-apiserver"; \ - done; \ - kubectl --context=kind-$${cluster_name} delete pods -n kube-system -l k8s-app=clustermesh-apiserver --force; \ - done - -.PHONY: kind-image-fast -kind-image-fast: kind-image-fast-agent kind-image-fast-operator kind-image-fast-clustermesh-apiserver ## Build all binaries and copy them to kind nodes. - -define KIND_VALUES_FILES ---helm-values=$(ROOT_DIR)/contrib/testing/kind-common.yaml \ ---helm-values=$(ROOT_DIR)/contrib/testing/kind-values.yaml -endef - -ifdef ADDITIONAL_KIND_VALUES_FILE - KIND_VALUES_FILES := $(KIND_VALUES_FILES) --helm-values=$(ROOT_DIR)/$(ADDITIONAL_KIND_VALUES_FILE) -endif - -ifneq ("$(wildcard $(ROOT_DIR)/contrib/testing/kind-custom.yaml)","") - KIND_VALUES_FILES := $(KIND_VALUES_FILES) --helm-values=$(ROOT_DIR)/contrib/testing/kind-custom.yaml -endif - -.PHONY: kind-install-cilium -kind-install-cilium: check_deps kind-ready ## Install a local Cilium version into the cluster. - @echo " INSTALL cilium" - # cilium-cli doesn't support idempotent installs, so we uninstall and - # reinstall here. https://github.com/cilium/cilium-cli/issues/205 - -@$(CILIUM_CLI) uninstall >/dev/null 2>&1 || true - - # cilium-cli's --wait flag doesn't work, so we just force it to run - # in the background instead and wait for the resources to be available. - # https://github.com/cilium/cilium-cli/issues/1070 - $(CILIUM_CLI) install \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - $(KIND_VALUES_FILES) \ - --version= \ - >/dev/null 2>&1 & - -GW_VERSION ?= $(shell grep "sigs.k8s.io/gateway-api" go.mod | awk '{print $$2}' | awk -F'-' '{print (NF>2)?$$NF:$$0}') -# Set this to "standard" to use the standard CRDs instead -GW_CHANNEL ?= "experimental" -KIND_NET_CIDR ?= $(shell docker network inspect kind-cilium -f '{{json .IPAM.Config}}' | jq -r '.[] | select(.Subnet | test("^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+")) | .Subnet') -LB_CIDR ?= $(shell echo $(KIND_NET_CIDR) | sed "s@0.0/16@255.200\/28@" | sed -e 's/[\/&]/\\&/g') - -.PHONY: kind-servicemesh-install-cilium -kind-servicemesh-install-cilium: check_deps kind-ready ## Install a local Cilium version into the cluster. - @echo " INSTALL cilium" - # cilium-cli doesn't support idempotent installs, so we uninstall and - # reinstall here. https://github.com/cilium/cilium-cli/issues/205 - -@$(CILIUM_CLI) uninstall >/dev/null 2>&1 || true - - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_gatewayclasses.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_gateways.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_httproutes.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_referencegrants.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_grpcroutes.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml - - $(CILIUM_CLI) install \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - $(KIND_VALUES_FILES) \ - --helm-values=$(ROOT_DIR)/contrib/testing/kind-servicemesh.yaml \ - --version= \ - >/dev/null 2>&1 & - - $(CILIUM_CLI) status --wait --wait-duration $(WAIT_DURATION) - - @echo "KIND_NET_CIDR: $(KIND_NET_CIDR)" - @echo "LB_CIDR: $(LB_CIDR)" - - @echo "Deploying LB-IPAM Pool..." - sed -e "s/LB_CIDR/$(LB_CIDR)/g" $(ROOT_DIR)/contrib/testing/servicemesh/ippool.yaml | kubectl apply -f - - - @echo "Deploying L2-Announcement Policy..." - kubectl apply -f $(ROOT_DIR)/contrib/testing/servicemesh/l2policy.yaml - -.PHONY: kind-servicemesh-prereqs -kind-servicemesh-prereqs: check_deps kind-ready - @echo " SETUP Servicemesh" - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_gatewayclasses.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_gateways.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_httproutes.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_referencegrants.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/$(GW_CHANNEL)/gateway.networking.k8s.io_grpcroutes.yaml - kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$(GW_VERSION)/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml - - $(eval KIND_VALUES_FAST_FILES += --helm-values=$(ROOT_DIR)/contrib/testing/kind-servicemesh.yaml) - - @echo "KIND_VALUES_FILES $(KIND_VALUES_FAST_FILES)" - -.PHONY: kind-servicemesh-install-cilium-fast -kind-servicemesh-install-cilium-fast: | kind-servicemesh-prereqs kind-image-fast kind-install-cilium-fast - $(CILIUM_CLI) status --wait --wait-duration $(WAIT_DURATION) - - @echo "KIND_NET_CIDR: $(KIND_NET_CIDR)" - @echo "LB_CIDR: $(LB_CIDR)" - - @echo "Deploying LB-IPAM Pool..." - sed -e "s/LB_CIDR/$(LB_CIDR)/g" $(ROOT_DIR)/contrib/testing/servicemesh/ippool.yaml | kubectl apply -f - - - @echo "Deploying L2-Announcement Policy..." - kubectl apply -f $(ROOT_DIR)/contrib/testing/servicemesh/l2policy.yaml - -.PHONY: kind-egressgw-install-cilium -kind-egressgw-install-cilium: check_deps kind-ready ## Install a local Cilium version into the cluster. - @echo " INSTALL cilium" - # cilium-cli doesn't support idempotent installs, so we uninstall and - # reinstall here. https://github.com/cilium/cilium-cli/issues/205 - -@$(CILIUM_CLI) uninstall >/dev/null 2>&1 || true - - # cilium-cli's --wait flag doesn't work, so we just force it to run - # in the background instead and wait for the resources to be available. - # https://github.com/cilium/cilium-cli/issues/1070 - $(CILIUM_CLI) install \ - --chart-directory=$(ROOT_DIR)/install/kubernetes/cilium \ - $(KIND_VALUES_FILES) \ - --helm-values=$(ROOT_DIR)/contrib/testing/kind-egressgw-values.yaml \ - --nodes-without-cilium \ - --version= \ - >/dev/null 2>&1 & - -KVSTORE_POD_NAME ?= "kvstore" -KVSTORE_POD_PORT ?= "2378" - -.PHONY: kind-kvstore-install-cilium -kind-kvstore-install-cilium: check_deps kind-ready kind-kvstore-start ## Install a local Cilium version into the cluster, configured in kvstore mode. - $(MAKE) kind-install-cilium KIND_VALUES_FILES="\ - $(KIND_VALUES_FILES) \ - --set etcd.enabled=true \ - --set etcd.endpoints[0]=http://$(shell kubectl --namespace kube-system get pod $(KVSTORE_POD_NAME) -o jsonpath='{.status.hostIP}'):$(KVSTORE_POD_PORT) \ - --set identityAllocationMode=kvstore \ - " - -.PHONY: kind-kvstore-start -kind-kvstore-start: ## Start an etcd pod serving as Cilium's kvstore - kubectl --namespace kube-system get pod $(KVSTORE_POD_NAME) >/dev/null 2>/dev/null || \ - kubectl --namespace kube-system run $(KVSTORE_POD_NAME) --image $(ETCD_IMAGE) \ - --overrides='{ "apiVersion": "v1", "spec": { "hostNetwork": true, "nodeSelector": {"node-role.kubernetes.io/control-plane": ""}, "tolerations": [{ "operator": "Exists" }] }}' \ - -- etcd --listen-client-urls=http://0.0.0.0:$(KVSTORE_POD_PORT) --advertise-client-urls=http://0.0.0.0:$(KVSTORE_POD_PORT) - - kubectl --namespace kube-system wait --for=condition=Ready pod/$(KVSTORE_POD_NAME) - -.PHONY: kind-kvstore-stop -kind-kvstore-stop: ## Stop the etcd pod serving as Cilium's kvstore - kubectl --namespace kube-system delete pod $(KVSTORE_POD_NAME) --ignore-not-found - kubectl --namespace kube-system wait --for=delete pod/$(KVSTORE_POD_NAME) - -.PHONY: kind-uninstall-cilium -kind-uninstall-cilium: check_deps ## Uninstall Cilium from the cluster. - @echo " UNINSTALL cilium" - -$(CILIUM_CLI) uninstall - -.PHONY: kind-check-cilium -kind-check-cilium: check_deps - @echo " CHECK cilium is ready..." - $(CILIUM_CLI) status --wait --wait-duration 1s >/dev/null 2>/dev/null - -# Template for kind debug targets. Parameters are: -# $(1) agent target -define DEBUG_KIND_TEMPLATE -.PHONY: kind-image$(1)-debug -kind-image$(1)-debug: export DEBUGGER_SUFFIX=-debug -kind-image$(1)-debug: export NOSTRIP=1 -kind-image$(1)-debug: export NOOPT=1 -kind-image$(1)-debug: ## Build cilium$(1) docker image with a dlv debugger wrapper and import it into kind. - $(MAKE) kind-image$(1) -endef - -# kind-image-agent-debug -$(eval $(call DEBUG_KIND_TEMPLATE,-agent)) - -# kind-image-operator-debug -$(eval $(call DEBUG_KIND_TEMPLATE,-operator)) - -$(eval $(call KIND_ENV,kind-debug-agent)) -kind-debug-agent: ## Create a local kind development environment with cilium-agent attached to a debugger. - $(QUIET)$(MAKE) kind-ready 2>/dev/null \ - || $(MAKE) kind - $(MAKE) kind-image-agent-debug - # Not debugging cilium-operator here; any image is good enough. - kind load docker-image $(LOCAL_OPERATOR_IMAGE) \ - || $(MAKE) kind-image-operator - $(MAKE) kind-check-cilium 2>/dev/null \ - || $(MAKE) kind-install-cilium - @echo "Attach delve to localhost on these ports to continue:" - @echo " - 23401: cilium-agent (kind-control-plane)" - @echo " - 23411: cilium-agent (kind-worker)" - -$(eval $(call KIND_ENV,kind-debug)) -kind-debug: ## Create a local kind development environment with cilium-agent & cilium-operator attached to a debugger. - $(QUIET)$(MAKE) kind-ready 2>/dev/null \ - || $(MAKE) kind - $(MAKE) kind-image-agent-debug - $(MAKE) kind-image-operator-debug - $(MAKE) kind-check-cilium 2>/dev/null \ - || $(MAKE) kind-install-cilium - @echo "Attach delve to localhost on these ports to continue:" - @echo " - 23401: cilium-agent (kind-control-plane)" - @echo " - 23411: cilium-agent (kind-worker)" - @echo " - 23511: cilium-operator (kind-worker)" diff --git a/vendor/github.com/cilium/cilium/Makefile.quiet b/vendor/github.com/cilium/cilium/Makefile.quiet deleted file mode 100644 index 397661109e..0000000000 --- a/vendor/github.com/cilium/cilium/Makefile.quiet +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Authors of Cilium -# SPDX-License-Identifier: Apache-2.0 - -ifeq ($(ROOT_DIR),) - ROOT_DIR ?= $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) - RELATIVE_DIR ?= $(shell echo $(realpath .) | sed "s;$(ROOT_DIR)[/]*;;") -endif -ifeq ($(V),0) - QUIET=@ - ECHO_CC=echo " CC $(RELATIVE_DIR)/$@" - ECHO_CHECK=echo " CHECK $(RELATIVE_DIR)" - ECHO_CLEAN=echo " CLEAN $(RELATIVE_DIR)" - ECHO_DOCKER=echo " DOCKER $(RELATIVE_DIR) $@" - ECHO_GEN=echo " GEN $(RELATIVE_DIR)/" - ECHO_GINKGO=echo " GINKGO $(RELATIVE_DIR)" - ECHO_GO=echo " GO $(RELATIVE_DIR)/$@" - ECHO_TEST=echo " TEST " - SUBMAKEOPTS="-s" -else - # The whitespace at below EOLs is required for verbose case! - ECHO_CC=: - ECHO_CHECK=: - ECHO_CLEAN=: - ECHO_DOCKER=: - ECHO_GEN=: - ECHO_GINKGO=: - ECHO_GO=: - ECHO_TEST=: - SUBMAKEOPTS= -endif diff --git a/vendor/github.com/cilium/cilium/README.rst b/vendor/github.com/cilium/cilium/README.rst deleted file mode 100644 index e2eb647eff..0000000000 --- a/vendor/github.com/cilium/cilium/README.rst +++ /dev/null @@ -1,359 +0,0 @@ -.. raw:: html - - - - Cilium Logo - - -|cii| |go-report| |clomonitor| |artifacthub| |slack| |go-doc| |rtd| |apache| |bsd| |gpl| |fossa| |gateway-api| |codespaces| - -Cilium is a networking, observability, and security solution with an eBPF-based -dataplane. It provides a simple flat Layer 3 network with the ability to span -multiple clusters in either a native routing or overlay mode. It is L7-protocol -aware and can enforce network policies on L3-L7 using an identity based security -model that is decoupled from network addressing. - -Cilium implements distributed load balancing for traffic between pods and to -external services, and is able to fully replace kube-proxy, using efficient -hash tables in eBPF allowing for almost unlimited scale. It also supports -advanced functionality like integrated ingress and egress gateway, bandwidth -management and service mesh, and provides deep network and security visibility and monitoring. - -A new Linux kernel technology called eBPF_ is at the foundation of Cilium. It -supports dynamic insertion of eBPF bytecode into the Linux kernel at various -integration points such as: network IO, application sockets, and tracepoints to -implement security, networking and visibility logic. eBPF is highly efficient -and flexible. To learn more about eBPF, visit `eBPF.io`_. - -.. image:: Documentation/images/cilium-overview.png - :alt: Overview of Cilium features for networking, observability, service mesh, and runtime security - -.. raw:: html - - - - - CNCF Graduated Project - - - - - - Powered by eBPF - - - -Stable Releases -=============== - -The Cilium community maintains minor stable releases for the last three minor -Cilium versions. Older Cilium stable versions from minor releases prior to that -are considered EOL. - -For upgrades to new minor releases please consult the `Cilium Upgrade Guide`_. - -Listed below are the actively maintained release branches along with their latest -patch release, corresponding image pull tags and their release notes: - -+---------------------------------------------------------+------------+------------------------------------+----------------------------------------------------------------------------+ -| `v1.17 `__ | 2025-02-12 | ``quay.io/cilium/cilium:v1.17.1`` | `Release Notes `__ | -+---------------------------------------------------------+------------+------------------------------------+----------------------------------------------------------------------------+ -| `v1.16 `__ | 2025-02-18 | ``quay.io/cilium/cilium:v1.16.7`` | `Release Notes `__ | -+---------------------------------------------------------+------------+------------------------------------+----------------------------------------------------------------------------+ -| `v1.15 `__ | 2025-02-18 | ``quay.io/cilium/cilium:v1.15.14`` | `Release Notes `__ | -+---------------------------------------------------------+------------+------------------------------------+----------------------------------------------------------------------------+ - -Architectures -------------- - -Cilium images are distributed for AMD64 and AArch64 architectures. - -Software Bill of Materials --------------------------- - -Starting with Cilium version 1.13.0, all images include a Software Bill of -Materials (SBOM). The SBOM is generated in `SPDX`_ format. More information -on this is available on `Cilium SBOM`_. - -.. _`SPDX`: https://spdx.dev/ -.. _`Cilium SBOM`: https://docs.cilium.io/en/latest/configuration/sbom/ - -Development -=========== - -For development and testing purpose, the Cilium community publishes snapshots, -early release candidates (RC) and CI container images build from the `main -branch `_. These images are -not for use in production. - -For testing upgrades to new development releases please consult the latest -development build of the `Cilium Upgrade Guide`_. - -Listed below are branches for testing along with their snapshots or RC releases, -corresponding image pull tags and their release notes where applicable: - -+----------------------------------------------------------------------------+------------+-----------------------------------------+---------------------------------------------------------------------------------+ -| `main `__ | daily | ``quay.io/cilium/cilium-ci:latest`` | N/A | -+----------------------------------------------------------------------------+------------+-----------------------------------------+---------------------------------------------------------------------------------+ -| `v1.18.0-pre.0 `__ | 2025-03-03 | ``quay.io/cilium/cilium:v1.18.0-pre.0`` | `Release Notes `__ | -+----------------------------------------------------------------------------+------------+-----------------------------------------+---------------------------------------------------------------------------------+ - -Functionality Overview -====================== - -.. begin-functionality-overview - -Protect and secure APIs transparently -------------------------------------- - -Ability to secure modern application protocols such as REST/HTTP, gRPC and -Kafka. Traditional firewalls operate at Layer 3 and 4. A protocol running on a -particular port is either completely trusted or blocked entirely. Cilium -provides the ability to filter on individual application protocol requests such -as: - -- Allow all HTTP requests with method ``GET`` and path ``/public/.*``. Deny all - other requests. -- Allow ``service1`` to produce on Kafka topic ``topic1`` and ``service2`` to - consume on ``topic1``. Reject all other Kafka messages. -- Require the HTTP header ``X-Token: [0-9]+`` to be present in all REST calls. - -See the section `Layer 7 Policy`_ in our documentation for the latest list of -supported protocols and examples on how to use it. - -Secure service to service communication based on identities ------------------------------------------------------------ - -Modern distributed applications rely on technologies such as application -containers to facilitate agility in deployment and scale out on demand. This -results in a large number of application containers being started in a short -period of time. Typical container firewalls secure workloads by filtering on -source IP addresses and destination ports. This concept requires the firewalls -on all servers to be manipulated whenever a container is started anywhere in -the cluster. - -In order to avoid this situation which limits scale, Cilium assigns a security -identity to groups of application containers which share identical security -policies. The identity is then associated with all network packets emitted by -the application containers, allowing to validate the identity at the receiving -node. Security identity management is performed using a key-value store. - -Secure access to and from external services -------------------------------------------- - -Label based security is the tool of choice for cluster internal access control. -In order to secure access to and from external services, traditional CIDR based -security policies for both ingress and egress are supported. This allows to -limit access to and from application containers to particular IP ranges. - -Simple Networking ------------------ - -A simple flat Layer 3 network with the ability to span multiple clusters -connects all application containers. IP allocation is kept simple by using host -scope allocators. This means that each host can allocate IPs without any -coordination between hosts. - -The following multi node networking models are supported: - -* **Overlay:** Encapsulation-based virtual network spanning all hosts. - Currently, VXLAN and Geneve are baked in but all encapsulation formats - supported by Linux can be enabled. - - When to use this mode: This mode has minimal infrastructure and integration - requirements. It works on almost any network infrastructure as the only - requirement is IP connectivity between hosts which is typically already - given. - -* **Native Routing:** Use of the regular routing table of the Linux host. - The network is required to be capable to route the IP addresses of the - application containers. - - When to use this mode: This mode is for advanced users and requires some - awareness of the underlying networking infrastructure. This mode works well - with: - - - Native IPv6 networks - - In conjunction with cloud network routers - - If you are already running routing daemons - -Load Balancing --------------- - -Cilium implements distributed load balancing for traffic between application -containers and to external services and is able to fully replace components -such as kube-proxy. The load balancing is implemented in eBPF using efficient -hashtables allowing for almost unlimited scale. - -For north-south type load balancing, Cilium's eBPF implementation is optimized -for maximum performance, can be attached to XDP (eXpress Data Path), and supports -direct server return (DSR) as well as Maglev consistent hashing if the load -balancing operation is not performed on the source host. - -For east-west type load balancing, Cilium performs efficient service-to-backend -translation right in the Linux kernel's socket layer (e.g. at TCP connect time) -such that per-packet NAT operations overhead can be avoided in lower layers. - -Bandwidth Management --------------------- - -Cilium implements bandwidth management through efficient EDT-based (Earliest Departure -Time) rate-limiting with eBPF for container traffic that is egressing a node. This -allows to significantly reduce transmission tail latencies for applications and to -avoid locking under multi-queue NICs compared to traditional approaches such as HTB -(Hierarchy Token Bucket) or TBF (Token Bucket Filter) as used in the bandwidth CNI -plugin, for example. - -Monitoring and Troubleshooting ------------------------------- - -The ability to gain visibility and troubleshoot issues is fundamental to the -operation of any distributed system. While we learned to love tools like -``tcpdump`` and ``ping`` and while they will always find a special place in our -hearts, we strive to provide better tooling for troubleshooting. This includes -tooling to provide: - -- Event monitoring with metadata: When a packet is dropped, the tool doesn't - just report the source and destination IP of the packet, the tool provides - the full label information of both the sender and receiver among a lot of - other information. - -- Metrics export via Prometheus: Key metrics are exported via Prometheus for - integration with your existing dashboards. - -- Hubble_: An observability platform specifically written for Cilium. It - provides service dependency maps, operational monitoring and alerting, - and application and security visibility based on flow logs. - -.. _Hubble: https://github.com/cilium/hubble/ -.. _`Layer 7 Policy`: https://docs.cilium.io/en/stable/security/policy/language/#layer-7-examples - -.. end-functionality-overview - -Getting Started -=============== - -* `Why Cilium?`_ -* `Getting Started`_ -* `Architecture and Concepts`_ -* `Installing Cilium`_ -* `Frequently Asked Questions`_ -* Contributing_ - -Community -========= - -Slack ------ - -Join the Cilium `Slack channel `_ to chat with -Cilium developers and other Cilium users. This is a good place to learn about -Cilium, ask questions, and share your experiences. - -Special Interest Groups (SIG) ------------------------------ - -See `Special Interest groups -`_ for a list of all SIGs and their meeting times. - -Developer meetings ------------------- -The Cilium developer community hangs out on Zoom to chat. Everybody is welcome. - -* Weekly, Wednesday, - 5:00 pm `Europe/Zurich time `__ (CET/CEST), - usually equivalent to 8:00 am PT, or 11:00 am ET. `Meeting Notes and Zoom Info`_ -* Third Wednesday of each month, 9:00 am `Japan time `__ (JST). `APAC Meeting Notes and Zoom Info`_ - -eBPF & Cilium Office Hours livestream -------------------------------------- -We host a weekly community `YouTube livestream called eCHO `_ which (very loosely!) stands for eBPF & Cilium Office Hours. Join us live, catch up with past episodes, or head over to the `eCHO repo `_ and let us know your ideas for topics we should cover. - -Governance ----------- -The Cilium project is governed by a group of `Maintainers and Committers `__. -How they are selected and govern is outlined in our `governance document `__. - -Adopters --------- -A list of adopters of the Cilium project who are deploying it in production, and of their use cases, -can be found in file `USERS.md `__. - -License -======= - -.. _apache-license: LICENSE -.. _bsd-license: bpf/LICENSE.BSD-2-Clause -.. _gpl-license: bpf/LICENSE.GPL-2.0 - -The Cilium user space components are licensed under the -`Apache License, Version 2.0 `__. -The BPF code templates are dual-licensed under the -`General Public License, Version 2.0 (only) `__ -and the `2-Clause BSD License `__ -(you can use the terms of either license, at your option). - -.. _`Cilium Upgrade Guide`: https://docs.cilium.io/en/stable/operations/upgrade/ -.. _`Why Cilium?`: https://docs.cilium.io/en/stable/overview/intro -.. _`Getting Started`: https://docs.cilium.io/en/stable/#getting-started -.. _`Architecture and Concepts`: https://docs.cilium.io/en/stable/overview/component-overview/ -.. _`Installing Cilium`: https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/ -.. _`Frequently Asked Questions`: https://github.com/cilium/cilium/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3Akind%2Fquestion+ -.. _Contributing: https://docs.cilium.io/en/stable/contributing/development/ -.. _Prerequisites: https://docs.cilium.io/en/stable/operations/system_requirements/ -.. _`eBPF`: https://ebpf.io -.. _`eBPF.io`: https://ebpf.io -.. _`Meeting Notes and Zoom Info`: https://docs.google.com/document/d/1Y_4chDk4rznD6UgXPlPvn3Dc7l-ZutGajUv1eF0VDwQ/edit# -.. _`APAC Meeting Notes and Zoom Info`: https://docs.google.com/document/d/1egv4qLydr0geP-GjQexYKm4tz3_tHy-LCBjVQcXcT5M/edit# - -.. |go-report| image:: https://goreportcard.com/badge/github.com/cilium/cilium - :alt: Go Report Card - :target: https://goreportcard.com/report/github.com/cilium/cilium - -.. |go-doc| image:: https://godoc.org/github.com/cilium/cilium?status.svg - :alt: GoDoc - :target: https://godoc.org/github.com/cilium/cilium - -.. |rtd| image:: https://readthedocs.org/projects/docs/badge/?version=latest - :alt: Read the Docs - :target: https://docs.cilium.io/ - -.. |apache| image:: https://img.shields.io/badge/license-Apache-blue.svg - :alt: Apache licensed - :target: apache-license_ - -.. |bsd| image:: https://img.shields.io/badge/license-BSD-blue.svg - :alt: BSD licensed - :target: bsd-license_ - -.. |gpl| image:: https://img.shields.io/badge/license-GPL-blue.svg - :alt: GPL licensed - :target: gpl-license_ - -.. |slack| image:: https://img.shields.io/badge/slack-cilium-brightgreen.svg?logo=slack - :alt: Join the Cilium slack channel - :target: https://slack.cilium.io - -.. |cii| image:: https://bestpractices.coreinfrastructure.org/projects/1269/badge - :alt: CII Best Practices - :target: https://bestpractices.coreinfrastructure.org/projects/1269 - -.. |clomonitor| image:: https://img.shields.io/endpoint?url=https://clomonitor.io/api/projects/cncf/cilium/badge - :alt: CLOMonitor - :target: https://clomonitor.io/projects/cncf/cilium - -.. |artifacthub| image:: https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/cilium - :alt: Artifact Hub - :target: https://artifacthub.io/packages/helm/cilium/cilium - -.. |fossa| image:: https://app.fossa.com/api/projects/custom%2B162%2Fgit%40github.com%3Acilium%2Fcilium.git.svg?type=shield - :alt: FOSSA Status - :target: https://app.fossa.com/projects/custom%2B162%2Fgit%40github.com%3Acilium%2Fcilium.git?ref=badge_shield - -.. |gateway-api| image:: https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.0-Cilium-green - :alt: Gateway API Status - :target: https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports/v1.2.0/cilium-cilium - -.. |codespaces| image:: https://img.shields.io/badge/Open_in_GitHub_Codespaces-gray?logo=github - :alt: Github Codespaces - :target: https://github.com/codespaces/new?hide_repo_select=true&ref=master&repo=48109239&machine=standardLinux32gb&location=WestEurope diff --git a/vendor/github.com/cilium/cilium/SECURITY-INSIGHTS.yml b/vendor/github.com/cilium/cilium/SECURITY-INSIGHTS.yml deleted file mode 100644 index 3074a9d1e2..0000000000 --- a/vendor/github.com/cilium/cilium/SECURITY-INSIGHTS.yml +++ /dev/null @@ -1,69 +0,0 @@ -header: - schema-version: '1.0.0' - expiration-date: '2025-01-26T01:00:00.000Z' - last-updated: '2024-01-26' - last-reviewed: '2024-01-26' - project-url: https://github.com/cilium/cilium - license: https://github.com/cilium/cilium/blob/main/LICENSE -project-lifecycle: - status: active - bug-fixes-only: false - core-maintainers: - - https://github.com/cilium/cilium/blob/main/MAINTAINERS.md - roadmap: https://docs.cilium.io/en/stable/community/roadmap -contribution-policy: - accepts-pull-requests: true - accepts-automated-pull-requests: true -dependencies: - third-party-packages: true - dependencies-lists: - - https://github.com/cilium/cilium/blob/main/go.mod - sbom: - - sbom-format: SPDX - sbom-url: https://docs.cilium.io/en/stable/configuration/sbom -distribution-points: - - https://github.com/cilium/cilium - - https://hub.docker.com/u/cilium - - https://quay.io/organization/cilium -documentation: - - https://docs.cilium.io/en/stable/ -security-assessments: - - auditor-name: ADA Logics - auditor-url: https://adalogics.com - auditor-report: https://github.com/cilium/cilium.io/blob/main/Security-Reports/CiliumSecurityAudit2022.pdf - report-year: 2022 - - auditor-name: ADA Logics - auditor-url: https://adalogics.com - auditor-report: https://github.com/cilium/cilium.io/blob/main/Security-Reports/CiliumFuzzingAudit2022.pdf - report-year: 2022 -security-contacts: - - type: email - value: security@cilium.io -security-testing: -- tool-type: sca - tool-name: Mend Renovate - tool-url: https://www.mend.io/renovate - tool-version: latest - integration: - ad-hoc: false - ci: true - before-release: true -- tool-type: fuzzer - tool-name: OSS-Fuzz - tool-url: https://github.com/google/oss-fuzz - tool-version: latest - integration: - ad-hoc: false - ci: true - before-release: true -- tool-type: sast - tool-name: Grype - tool-url: https://github.com/anchore/grype - tool-version: latest - integration: - ad-hoc: false - ci: true - before-release: true -vulnerability-reporting: - accepts-vulnerability-reports: true - security-policy: https://github.com/cilium/cilium/security diff --git a/vendor/github.com/cilium/cilium/SECURITY.md b/vendor/github.com/cilium/cilium/SECURITY.md deleted file mode 100644 index 87570c3114..0000000000 --- a/vendor/github.com/cilium/cilium/SECURITY.md +++ /dev/null @@ -1,29 +0,0 @@ -# Security Policy - -## Supported Versions - -| Version | Supported | -|----------| ------------------ | -| main | :white_check_mark: | -| 1.17.x | :white_check_mark: | -| 1.16.x | :white_check_mark: | -| 1.15.x | :white_check_mark: | -| < 1.15.0 | :x: | - -## Reporting a Vulnerability - -We strongly encourage you to report security vulnerabilities to -our private security mailing list: security@cilium.io - first, before -disclosing them in any public forums. - -A threat model for Cilium and recommendations for running Cilium in production -environments can be found [here][threat-model]. Please ensure that you have -taken this threat model into consideration before making a report, including -considering the feasibility of an attack against a correctly secured -environment. - -This is a private mailing list where members of Cilium's -[Security Team](https://github.com/cilium/community/blob/main/roles/Security-Team.md) -are subscribed to, and is treated as top priority. - -[threat-model]: https://docs.cilium.io/en/latest/security/threat-model/ diff --git a/vendor/github.com/cilium/cilium/USERS.md b/vendor/github.com/cilium/cilium/USERS.md deleted file mode 100644 index 6d646f0c5b..0000000000 --- a/vendor/github.com/cilium/cilium/USERS.md +++ /dev/null @@ -1,930 +0,0 @@ -Who is using Cilium? -==================== - -Sharing experiences and learning from other users is essential. We are -frequently asked who is using a particular feature of Cilium so people can get in -contact with other users to share experiences and best practices. People -also often want to know if product/platform X has integrated Cilium. -While the [Cilium Slack community](https://slack.cilium.io) allows -users to get in touch, it can be challenging to find this information quickly. - -The following is a directory of adopters to help identify users of individual -features. The users themselves directly maintain the list. - -Adding yourself as a user -------------------------- - -If you are using Cilium or it is integrated into your product, service, or -platform, please consider adding yourself as a user with a quick -description of your use case by opening a pull request to this file and adding -a section describing your usage of Cilium. If you are open to others contacting -you about your use of Cilium on Slack, add your Slack nickname as well. - - N: Name of user (company) - D: Description - U: Usage of features - L: Link with further information (optional) - Q: Contacts available for questions (optional) - -Example entry: - - * N: Cilium Example User Inc. - D: Cilium Example User Inc. is using Cilium for scientific purposes - U: ENI networking, DNS policies, ClusterMesh - Q: @slacknick1, @slacknick2 - -Requirements to be listed -------------------------- - - * You must represent the user listed. Do *NOT* add entries on behalf of - other users. - * There is no minimum deployment size but we request to list permanent - production deployments only, i.e., no demo or trial deployments. Commercial - use is not required. A well-done home lab setup can be equally - interesting as a large-scale commercial deployment. - -Users (Alphabetically) ----------------------- - - * N: Ænix - D: Ænix uses Cilium in free PaaS platform [Cozystack](https://cozystack.io) for running containers, virtual machines and Kubernetes-as-a-Service. - U: Networking, NetworkPolicy, kube-proxy replacement, CNI-Chaining (with kube-ovn) - L: https://cozystack.io/ - Q: @kvaps - - * N: AccuKnox - D: AccuKnox uses Cilium for network visibility and network policy enforcement. - U: L3/L4/L7 policy enforcement using Identity, External/VM Workloads, Network Visibility using Hubble - L: https://www.accuknox.com/spifee-identity-for-cilium-presentation-at-kubecon-2021, https://www.accuknox.com/cilium - Q: @nyrahul - - * N: Acoss - D: Acoss is using cilium as their main CNI plugin (self hosted k8s, On-premises) - U: CiliumNetworkPolicy, Hubble, BPF NodePort, Direct routing - L: @JrCs - - * N: Adobe, Inc. - D: Adobe's Project Ethos uses Cilium for multi-tenant, multi-cloud clusters - U: L3/L4/L7 policies - L: https://youtu.be/39FLsSc2P-Y - - * N: AirQo - D: AirQo uses Cilium as the CNI plugin - U: CNI, Networking, NetworkPolicy, Cluster Mesh, Hubble, Kubernetes services - L: @airqo-platform - - * N: Alauda - D: Alauda uses Cilium in the Alauda Container Platform product to provide high performance network,observability and security. - U: Networking, NetworkPolicy, Services, Observability - Q:@oilbeater - - * N: Alibaba Cloud - D: Alibaba Cloud is using Cilium together with Terway CNI as the high-performance ENI dataplane - U: Networking, NetworkPolicy, Services, IPVLAN - L: https://www.alibabacloud.com/blog/how-does-alibaba-cloud-build-high-performance-cloud-native-pod-networks-in-production-environments_596590 - - * N: Amazon Web Services (AWS) - D: AWS uses Cilium as the default CNI for EKS Anywhere - U: Networking, NetworkPolicy, Services - L: https://isovalent.com/blog/post/2021-09-aws-eks-anywhere-chooses-cilium - - * N: APPUiO by VSHN - D: VSHN uses Cilium for multi-tenant networking on APPUiO Cloud and as an add-on to APPUiO Managed, both on Red Hat OpenShift and Cloud Kubernetes. - U: CNI, Networking, NetworkPolicy, Hubble, IPAM, Kubernetes services - L: https://products.docs.vshn.ch/products/appuio/managed/addon_cilium.html and https://www.appuio.cloud - - * N: ArangoDB Oasis - D: ArangoDB Oasis is using Cilium in to separate database deployments in our multi-tenant cloud environment - U: Networking, CiliumNetworkPolicy(cluster & local), Hubble, IPAM - L: https://cloud.arangodb.com - Q: @ewoutp @Robert-Stam - - * N: Archer Aviation - D: Archer Aviation uses Cilium as part of the foundation of the Kubernetes cluster. - U: Networking, Observability, Security - L: https://www.archer.com - Q: @Hongbo Miao - - * N: Ascend.io - D: Ascend.io is using Cilium as a consistent CNI for our Data Automation Platform on GKE, EKS, and AKS. - U: Transparent Encryption, Overlay Networking, Cluster Mesh, Egress Gateway, Network Policy, Hubble - L: https://www.ascend.io/ - Q: @Joe Stevens - - * N: Ayedo - D: Ayedo builds and operates cloud-native container platforms based on Kubernetes - U: Hubble for Visibility, Cilium as Mesh between Services - L: https://www.ayedo.de/ - - * N: Back Market - D: Back Market is using Cilium as CNI in all their clusters and environments (kOps + EKS in AWS) - U: CNI, Network Policies, Transparent Encryption (WG), Hubble - Q: @nitrikx - L: https://www.backmarket.com/ - - * N: Berops - D: Cilium is used as a CNI plug-in in our open-source multi-cloud and hybrid-cloud Kubernetes platform - Claudie - U: CNI, Network Policies, Hubble - Q: @Bernard Halas - L: https://github.com/berops/claudie - - * N: Bitnami - D: Cilium is part of the largest open-source application catalog. - U: CNI, Hubble, BGP, eBPF, CiliumNetworkPolicy, CiliumClusterwideNetworkPolicy - L: https://bitnami.com/stack/cilium - Q: @carrodher - - * N: BMC Software - D: Cilium can be optionally used in BMC Helix Innovaton Suite and BMC IT Operations Management On Premise - U: CNI, Hubble - L: https://www.bmc.com - Q: @ryebridge - - * N: ByteDance - D: ByteDance is using Cilium as CNI plug-in for self-hosted Kubernetes. - U: CNI, Networking - L: @Jiang Wang - - * N: Canonical - D: Canonical's Kubernetes distribution microk8s uses Cilium as CNI plugin - U: Networking, NetworkPolicy, and Kubernetes services - L: https://microk8s.io/ - - * N: Capital One - D: Capital One uses Cilium as its standard CNI for all Kubernetes environments - U: CNI, CiliumClusterWideNetworkpolicy, CiliumNetworkPolicy, Hubble, network visibility - L: https://www.youtube.com/watch?v=hwOpCKBaJ-w - - * N: CENGN - Centre of Excellence in Next Generation Networks - D: CENGN is using Cilium in multiple clusters including production and development clusters (self-hosted k8s, On-premises) - U: L3/L4/L7 network policies, Monitoring via Prometheus metrics & Hubble - L: https://www.youtube.com/watch?v=yXm7yZE2rk4 - Q: @rmaika @mohahmed13 - - * N: Cistec - D: Cistec is a clinical information system provider and uses Cilium as the CNI plugin. - U: Networking and network policy - L: https://www.cistec.com/ - - * N: Civo - D: Civo is offering Cilium as the CNI option for Civo users to choose it for their Civo Kubernetes clusters. - U: Networking and network policy - L: https://www.civo.com/kubernetes - - * N: ClickHouse - D: ClickHouse uses Cilium as CNI for AWS Kubernetes environments - U: CiliumNetworkPolicy, Hubble, ClusterMesh - L: https://clickhouse.com - - * N: Cloutomate - D: Cloutomate uses Cilium as CNI for itself and customer installations - U: Networking Observability and Security, Service Mesh, Cluster Mesh - L: https://cloutomate.de - - * N: Cognite - D: Cognite is an industrial DataOps provider and uses Cilium as the CNI plugin - Q: @Robert Collins - - * N: CONNY - D: CONNY is legaltech platform to improve access to justice for individuals - U: Networking, NetworkPolicy, Services - Q: @ant31 - L: https://conny.de - - * N: Cosmonic - D: Cilium is the CNI for Cosmonic's Nomad based PaaS - U: Networking, NetworkPolicy, Transparent Encryption - L: https://cilium.io/blog/2023/01/18/cosmonic-user-story/ - - * N: Crane - D: Crane uses Cilium as the default CNI - U: Networking, NetworkPolicy, Services - L: https://github.com/slzcc/crane - Q: @slzcc - - * N: Cybozu - D: Cybozu deploys Cilium to on-prem Kubernetes Cluster and uses it with Coil by CNI chaining. - U: CNI Chaining, L4 LoadBalancer, NetworkPolicy, Hubble - L: https://cybozu-global.com/ - - * N: Daimler Truck AG - D: The CSG RuntimeDepartment of DaimlerTruck is maintaining an AKS k8s cluster as a shared resource for DevOps crews and is using Cilium as the default CNI (BYOCNI). - U: Networking, NetworkPolicy and Monitoring - L: https://daimlertruck.com - Q: @brandshaide - - * N: DaoCloud - spiderpool & merbridge - D: spiderpool is using Cilium as their main CNI plugin for overlay and merbridge is using Cilium eBPF library to speed up your Service Mesh - U: CNI, Service load-balancing, cluster mesh - L: https://github.com/spidernet-io/spiderpool, https://github.com/merbridge/merbridge - Q: @weizhoublue, @kebe7jun - - * N: Datadog - D: Datadog is using Cilium in AWS (self-hosted k8s) - U: ENI Networking, Service load-balancing, Encryption, Network Policies, Hubble - Q: @lbernail, @roboll, @mvisonneau - - * N: Dcode.tech - D: We specialize in AWS and Kubernetes, and actively implement Cilium at our clients. - U: CNI, CiliumNetworkPolicy, Hubble UI - L: https://dcode.tech/ - Q: @eliranw, @maordavidov - - * N: Deckhouse - D: Deckhouse Kubernetes Platform is using Cilium as a one of the supported CNIs. - U: Networking, Security, Hubble UI for network visibility - L: https://github.com/deckhouse/deckhouse - - * N: Deezer - D: Deezer is using Cilium as CNI for all our on-prem clusters for its performance and security. We plan to leverage BGP features as well soon - U: CNI, Hubble, kube-proxy replacement, eBPF - L: https://github.com/deezer - - * N: DigitalOcean - D: DigitalOcean is using Cilium as the CNI for Digital Ocean's managed Kubernetes Services (DOKS) - U: Networking and network policy - L: https://github.com/digitalocean/DOKS - - * N: Docaposte - D: Docaposte is the digital trust leader in France. We have selected Cilium as our CNI for Kubernetes deployments in production environments, due to its performance and advanced features. - U: eBPF, CiliumclusterWideNetworkPolicy, CiliumNetworkPolicy, kube-proxy replacement, Hubble - L: https://docaposte.fr - Q: @albundy83 - - * N: ECCO Data and AI - D: ECCO Data and AI is using Cilium as CNI in all their clusters and environments (EKS in AWS). - U: CNI, IPv6 networking, Service Load Balancing and Cluster Mesh - L: https://github.com/SneaksAndData - - * N: Edgeless Systems - D: Edgeless Systems is using Cilium as the CNI for Edgeless System's Confidential Kubernetes Distribution (Constellation) - U: Networking (CNI), Transparent Encryption (WG), - L: https://docs.edgeless.systems/constellation/architecture/networking - Q: @m1ghtym0 - - * N: Eficode - D: As a cloud-native and devops consulting firm, we have implemented Cilium on customer engagements - U: CNI, CiliumNetworkPolicy at L7, Hubble - L: https://eficode.com/ - Q: @Andy Allred - - * N: Elastic Path - D: Elastic Path is using Cilium in their CloudOps for Kubernetes production clusters - U: CNI - L: https://documentation.elasticpath.com/cloudops-kubernetes/docs/index.html - Q: @Neil Seward - - * N: Entrywan - D: Entrywan provides Cilium as a CNI option in its managed kubernetes service - U: CNI - L: https://www.entrywan.com/docs#kubernetes - Q: @aarongroom - - * N: Equinix - D: Equinix Metal is using Cilium for production and non-production environments on bare metal - U: CNI, CiliumClusterWideNetworkpolicy, CiliumNetworkPolicy, BGP advertisements, Hubble, network visibility - L: https://metal.equinix.com/ - Q: @tylerauerbeck, @fishnix, @tenyo, @hegartyk - - * N: Equinix - D: Equinix NL Managed Services is using Cilium with their Managed Kubernetes offering - U: CNI, network policies, visibility - L: https://www.equinix.nl/products/support-services/managed-services/netherlands - Q: @jonkerj - - * N: EvoCloud - D: EvoCloud uses Cilium as a Kubernetes proxy replacement, CNI with Gateway API integration, Cluster mesh with BGP enabled, Network policy and Hubble Observability. - U: L4/L7 Networking, L2 Announcement, Network Policies, Kube-proxy replacement, CNI with Gateway API, Hubble for tracing and observability, ClusterMesh and ServiceMesh - L: https://github.com/evocloud-dev/evocloud-paas - Q: @geanttechnology, @escapevelocity17321 - - * N: Exoscale - D: Exoscale is offering Cilium as a CNI option on its managed Kubernetes service named SKS (Scalable Kubernetes Service) - U: CNI, Networking - L: https://www.exoscale.com/sks/ - Q: @Antoine - - * N: finleap connect - D: finleap connect is using Cilium in their production clusters (self-hosted, bare-metal, private cloud) - U: CNI, NetworkPolicies - Q: @chue - - * N: Form3 - D: Form3 is using Cilium in their production clusters (self-hosted, bare-metal, private cloud) - U: Service load-balancing, Encryption, CNI, NetworkPolicies - Q: @kevholditch-f3, samo-f3, ewilde-form3 - - * N: FRSCA - Factory for Repeatable Secure Creation of Artifacts - D: FRSCA is utilizing tetragon integrated with Tekton to create runtime attestation to attest artifact and builder attributes - U: Runtime observability - L: https://github.com/buildsec/frsca - Q: @Parth Patel - - * N: F5 Inc - D: F5 helps customers with Cilium VXLAN tunnel integration with BIG-IP - U: Networking - L: https://github.com/f5devcentral/f5-ci-docs/blob/master/docs/cilium/cilium-bigip-info.rst - Q: @vincentmli - - * N: Gcore - D: Gcore supports Cilium as CNI provider for Gcore Managed Kubernetes Service - U: CNI, Networking, NetworkPolicy, Kubernetes Services - L: https://gcore.com/news/cilium-cni-support - Q: @rzdebskiy - - * N: Giant Swarm - D: Giant Swarm is using Cilium in their Cluster API based managed Kubernetes service (AWS, Azure, GCP, OpenStack, VMware Cloud Director and VMware vSphere) as CNI - U: Networking - L: https://www.giantswarm.io/ - - * N: GitLab - D: GitLab is using Cilium to implement network policies inside Auto DevOps deployed clusters for customers using k8s - U: Network policies - L: https://docs.gitlab.com/ee/user/clusters/applications.html#install-cilium-using-gitlab-ci - Q: @ap4y @whaber - - * N: Google - D: Google is using Cilium in Anthos and Google Kubernetes Engine (GKE) as Dataplane V2 - U: Networking, network policy, and network visibility - L: https://cloud.google.com/blog/products/containers-kubernetes/bringing-ebpf-and-cilium-to-google-kubernetes-engine - - * N: G DATA CyberDefense AG - D: G DATA CyberDefense AG is using Cilium on our managed on premise clusters. - U: Networking, network policy, security, and network visibility - L: https://gdatasoftware.com - Q: @farodin91 - - * N: Guidewire Software, Inc. - D: Guidewire Software, Inc. is using Cilium for the Guidewire Cloud Platform. - U: CNI, network policy, and network visibility - L: https://www.guidewire.com - - * N: IDNIC | Kadabra - D: IDNIC is the National Internet Registry administering IP addresses for INDONESIA, uses Cilium to powered Kadabra project runing services across multi data centers. - U: Networking, Network Policies, kube-proxy Replacement, Service Load Balancing and Cluster Mesh - L: https://ris.idnic.net/ - Q: @ardikabs - - * N: IKEA IT AB - D: IKEA IT AB is using Cilium for production and non-production environments (self-hosted, bare-metal, private cloud) - U: Networking, CiliumclusterWideNetworkPolicy, CiliumNetworkPolicy, kube-proxy replacement, Hubble, Direct routing, egress gateway, hubble-otel, Multi Nic XDP, BGP advertisements, Bandwidth Manager, Service Load Balancing, Cluster Mesh - L: https://www.ingka.com/ - - * N: Immerok - D: Immerok uses Cilium for cross-cluster communication and network isolation; Immerok Cloud is a serverless platform for the full power of [Apache Flink](https://flink.apache.org) at any scale. - U: Networking, network policy, observability, cluster mesh, kube-proxy replacement, security, CNI - L: https://immerok.io - Q: @austince, @dmvk - - * N: Incentive.me - D: Incentive.me use Cilium, Tetragon and Hubble for enterprise networking, observability, and security of all environments. - U: Networking, network policy, observability, cluster mesh, kube-proxy replacement, security, egress gateway, service load balancing, CNI - L: https://incentive.me - Q: @lucasfcnunes - - * N: Infomaniak - D: Infomaniak is using Cilium in their production clusters (self-hosted, bare-metal and openstack) - U: Networking, CiliumNetworkPolicy, BPF NodePort, Direct routing, kube-proxy replacement - L: https://www.infomaniak.com/en - Q: @reneluria - - * N: innoQ Schweiz GmbH - D: As a consulting company we added Cilium to a couple of our customers infrastructure - U: Networking, CiliumNetworkPolicy at L7, kube-proxy replacement, encryption - L: https://www.cloud-migration.ch/ - Q: @fakod - - * N: Intility AS - D: Intility is a managed service provider for enterprises and we use Cilium, Tetragon and Hubble to deliver world class managed Kubernetes clusters to customers from our own private cloud - U: Networking, CiliumNetworkPolicy, CiliumCIDRGroup, security, CNI - L: https://intility.com/container-platform/ - Q: @jonasks, @daniwk, @stianfro - - * N: Isovalent - D: Cilium is the platform that powers Isovalent’s enterprise networking, observability, and security solutions - U: Networking, network policy, observability, cluster mesh, kube-proxy replacement, security, egress gateway, service load balancing, CNI - L: https://isovalent.com/product/ - Q: @BillMulligan - - * N: Jar - D: Cilium is used as Jar's CNI on all prod and pre production environments. - U: Networking, network policy, observability, cluster mesh, kube-proxy replacement, security, egress gateway, service load balancing, CNI - L: https://myjar.app/blog/engineering/ - Q: @rohan-changejar @rohangrge - - - * N: JUMO - D: JUMO is using Cilium as their CNI plugin for all of their AWS-hosted EKS clusters - U: Networking, network policy, network visibility, cluster mesh - Q: @Matthieu ANTOINE, @Carlos Castro, @Joao Coutinho (Slack) - - * N: Kakao - D: Kakao is using Cilium as the CNI for their private cloud's managed Kubernetes service - U: Custom eBPF programs, networking, network policy, kube-proxy replacement - L: https://youtu.be/WRACr5nXl9U - Q: @gyutaeb - - * N: KA-NABELL - D: KA-NABELL harnesses Cilium to deliver Kubernetes networking with robust security and clear observability. - U: CNI/ENI Networking, kube-proxy replacement, Monitoring via Prometheus metrics & Hubble, eBPF, CiliumNetworkPolicy - L: https://speakerdeck.com/andoshin11/envoy-external-authztogrpc-extensionwoli-yong-sita-wan-zhang-ranai-microservicesren-zheng-ren-ke-ji-pan?slide=8 - Q: @kahirokunn - - * N: Keploy - D: Keploy is using the Cilium to capture the network traffic to perform E2E Testing. - U: Networking, network policy, Monitoring, E2E Testing - L: https://keploy.io/ - - * N: Kilo - D: Cilium is a supported CNI for Kilo. When used together, Cilium + Kilo create a full mesh via WireGuard for Kubernetes in edge environments. - U: CNI, Networking, Hubble, kube-proxy replacement, network policy - L: https://kilo.squat.ai/ - Q: @squat, @arpagon - - * N: Koyeb - D: Koyeb hosts microVMs on its own servers and uses Cilium to power a mesh in between those - U: Networking, policies inside a non-Kubernetes environment - L: https://www.koyeb.com/blog/70-faster-deployments-and-high-performance-private-network - Q: @koyeb on Twitter / https://community.koyeb.com/ - - * N: kOps - D: kOps is using Cilium as one of the supported CNIs - U: Networking, Hubble, Encryption, kube-proxy replacement - L: kops.sigs.k8s.io/ - Q: @olemarkus - - * N: Kryptos Logic - D: Kryptos is a cyber security company that is using Kubernetes on-prem in which Cilium is our CNI of choice. - U: Networking, Observability, kube-proxy replacement - - * N: kubeasz - D: kubeasz, a certified kubernetes installer, is using Cilium as a one of the supported CNIs. - U: Networking, network policy, Hubble for network visibility - L: https://github.com/easzlab/kubeasz - - * N: Kube-OVN - D: Kube-OVN uses Cilium to enhance service performance, security and monitoring. - U: CNI-Chaining, Hubble, kube-proxy replacement - L: https://github.com/kubeovn/kube-ovn/blob/master/docs/IntegrateCiliumIntoKubeOVN.md - Q: @oilbeater - - * N: Kube-Hetzner - D: Kube-Hetzner is a open-source Terraform project that uses Cilium as an possible CNI in its cluster deployment on Hetzner Cloud. - U: Networking, Hubble, kube-proxy replacement - L: https://github.com/kube-hetzner/terraform-hcloud-kube-hetzner#cni - Q: @MysticalTech - - * N: Kubermatic - D: Kubermatic Kubernetes Platform is using Cilium as a one of the supported CNIs. - U: Networking, network policy, Hubble for network visibility - L: https://github.com/kubermatic/kubermatic - - * N: KubeSphere - KubeKey - D: KubeKey is an open-source lightweight tool for deploying Kubernetes clusters and addons efficiently. It uses Cilium as one of the supported CNIs. - U: Networking, Security, Hubble UI for network visibility - L: https://github.com/kubesphere/kubekey - Q: @FeynmanZhou - - * N: K8e - Simple Kubernetes Distribution - D: Kubernetes Easy (k8e) is a lightweight, Extensible, Enterprise Kubernetes distribution. It uses Cilium as default CNI network. - U: Networking, network policy, Hubble for network visibility - L: https://github.com/xiaods/k8e - Q: @xds2000 - - * N: LinkPool - D: LinkPool is a professional Web3 infrastructure provider. - U: LinkPool is using Cilium as the CNI for its on-premise production clusters - L: https://linkpool.com - Q: @jleeh - - * N: Liquid Reply - D: Liquid Reply is a professional service provider and utilizes Cilium on suitable projects and implementations. - U: Networking, network policy, Hubble for network visibility, Security - L: http://liquidreply.com - Q: @mkorbi - - * N: Magic Leap - D: Magic Leap is using Hubble plugged to GKE Dataplane v2 clusters - U: Hubble - Q: @romachalm - - * N: Melenion Inc - D: Melenion is using Cilium as the CNI for its on-premise production clusters - U: Service Load Balancing, Hubble - Q: @edude03 - - * N: Meltwater - D: Meltwater is using Cilium in AWS on self-hosted multi-tenant k8s clusters as the CNI plugin - U: ENI Networking, Encryption, Monitoring via Prometheus metrics & Hubble - Q: @recollir, @dezmodue - - * N: Microsoft - D: Microsoft is using Cilium in "Azure CNI powered by Cilium" AKS (Azure Kubernetes Services) clusters - L: https://techcommunity.microsoft.com/t5/azure-networking-blog/azure-cni-powered-by-cilium-for-azure-kubernetes-service-aks/ba-p/3662341 - Q: @tamilmani1989 @chandanAggarwal - - * N: Mobilab - D: Mobilab uses Cilium as the CNI for its internal cloud - U: CNI - L: https://mobilabsolutions.com/2019/01/why-we-switched-to-cilium/ - - * N: MyFitnessPal - D: MyFitnessPal trusts Cilium with high volume user traffic in AWS on self-hosted k8s clusters as the CNI plugin and in GKE with Dataplane V2 - U: Networking (CNI, Maglev, kube-proxy replacement, local redirect policy), Observability (Network metrics with Hubble, DNS proxy, service maps, policy troubleshooting) and Security (Network Policy) - L: https://www.myfitnesspal.com - - * N: Mux, Inc. - D: Mux deploys Cilium on self-hosted k8s clusters (Cluster API) in GCP and AWS to run its video streaming/analytics platforms. - U: Pod networking (CNI, IPAM, Host-reachable Services), Hubble, Cluster-mesh. TBD: Network Policy, Transparent Encryption (WG), Host Firewall. - L: https://mux.com - Q: @dilyevsky - - * N: NetBird - D: NetBird uses Cilium to compile BPF to Go for cross-platform DNS management and NAT traversal - U: bpf2go to compile a C source file into eBPF bytecode and then to Go - L: https://netbird.io/knowledge-hub/using-xdp-ebpf-to-share-default-dns-port-between-resolvers - Q: @braginini - - * N: Netcloud AG - D: As a Swiss ICT company we are using Cilium as their CNI for mission critical, on premise k8s clusters. - U: Overlay Networking, CNI, Network Policy, Kube-Proxy Replacement, Service load-balancing - L: https://www.netcloud.ch - - * N: NETWAYS Web Services - D: NETWAYS Web Services offers Cilium to their clients as CNI option for their Managed Kubernetes clusters. - U: Networking (CNI), Observability (Hubble) - L: https://nws.netways.de/managed-kubernetes/ - - * N: New York Times (the) - D: The New York Times is using Cilium on EKS to build multi-region multi-tenant shared clusters - U: Networking (CNI, EKS IPAM, Maglev, kube-proxy replacement, Direct Routing), Observability (Network metrics with Hubble, policy troubleshooting) and Security (Network Policy) - L: https://www.nytimes.com/, https://youtu.be/9FDpMNvPrCw - Q: @abebars - - * N: Nexxiot - D: Nexxiot is an IoT SaaS provider using Cilium as the main CNI plugin on AWS EKS clusters - U: Networking (IPAM, CNI), Security (Network Policies), Visibility (hubble) - L: https://nexxiot.com - - * N: Nine Internet Solutions AG - D: Nine uses Cilium on all Nine Kubernetes Engine clusters - U: CNI, network policy, kube-proxy replacement, host firewall - L: https://www.nine.ch/en/kubernetes - - * N: Northflank - D: Northflank is a PaaS and uses Cilium as the main CNI plugin across GCP, Azure, AWS and bare-metal - U: Networking, network policy, hubble, packet monitoring and network visibility - L: https://northflank.com - Q: @NorthflankWill, @Champgoblem - - * N: Nutanix - D: Nutanix uses Cilium as the default CNI plugin for NKP (Nutanix Kubernetes Platform) when deployed on AHV - U: Networking, NetworkPolicy, Services - L: https://www.nutanix.com/products/kubernetes-management-platform - Q: @tuxtof - - * N: Overstock Inc. - D: Overstock is using Cilium as the main CNI plugin on bare-metal clusters (self hosted k8s). - U: Networking, network policy, hubble, observability - - * N: Palantir Technologies Inc. - D: Palantir is using Cilium as their main CNI plugin in all major cloud providers [AWS/Azure/GCP] (self hosted k8s). - U: ENI networking, L3/L4 policies, FQDN based policy, FQDN filtering, IPSec - Q: ungureanuvladvictor - - * N: Palark GmbH - D: Palark uses Cilium for networking in its Kubernetes platform provided to numerous customers as a part of its DevOps as a Service offering. - U: CNI, Networking, Network policy, Security, Hubble UI - L: https://blog.palark.com/why-cilium-for-kubernetes-networking/ - Q: @shurup - - * N: Parseable - D: Parseable uses Tertragon for collecting and ingesting eBPF logs for Kubernetes clusters. - U: Security, eBPF, Tetragon - L: https://www.parseable.io/blog/ebpf-log-analytics - Q: @nitisht - - * N: Pionative - D: Pionative supplies all its clients across cloud providers with - Kubernetes running Cilium to deliver the best performance out there. - U: CNI, Networking, Security, eBPF - L: https://www.pionative.com - Q: @Pionerd - - * N: Plaid Inc - D: Plaid is using Cilium as their CNI plugin in self-hosted Kubernetes on AWS. - U: CNI, network policies - L: [https://plaid.com](https://plaid.com/contact/) - Q: @diversario @jandersen-plaid - - * N: PlanetScale - D: PlanetScale is using Cilium as the CNI for its serverless database platform. - U: Networking (CNI, IPAM, kube-proxy replacement, native routing), Network Security, Cluster Mesh, Load Balancing - L: https://planetscale.com/ - Q: @dctrwatson - - * N: plusserver Kubernetes Engine (PSKE) - D: PSKE uses Cilium for multiple scenarios, for examples for managed Kubernetes clusters provided with Gardener Project across AWS and OpenStack. - U: CNI , Overlay Network, Network Policies - L: https://www.plusserver.com/en/product/managed-kubernetes/, https://github.com/gardener/gardener-extension-networking-cilium - - * N: Polar Signals - D: Polar Signals uses Cilium as the CNI on its GKE dataplane v2 based clusters. - U: Networking - L: https://polarsignals.com - Q: @polarsignals @brancz - - * N: Polverio - D: Polverio KubeLift is a single-node Kubernetes distribution optimized for Azure, using Cilium as the CNI. - U: CNI, IPAM - L: https://polverio.com - Q: @polverio @stuartpreston - - * N: Poseidon Laboratories - D: Poseidon's Typhoon Kubernetes distro uses Cilium as the default CNI and its used internally - U: Networking, policies, service load balancing - L: https://github.com/poseidon/typhoon/ - Q: @dghubble @typhoon8s - - * N: PostFinance AG - D: PostFinance is using Cilium as their CNI for all mission critical, on premise k8s clusters - U: Networking, network policies, kube-proxy replacement - L: https://github.com/postfinance - - * N: Proton AG - D: Proton is using Cilium as their CNI for all their Kubernetes clusters - U: Networking, network policies, host firewall, kube-proxy replacement, Hubble - L: https://proton.me/ - Q: @j4m3s @MrFreezeex - - * N: Radio France - D: Radio France is using Cilium in their production clusters (self-hosted k8s with kops on AWS) - U: Mainly Service load-balancing - Q: @francoisj - - * N: Qpoint - D: An eBPF-based egress observability platform for your cloud and production applications - U: CNI, bpf2go to compile a C source file into eBPF bytecode and then to Go - L: https://www.qpoint.io/ and https://github.com/qpoint-io - Q: @Marc Barry - - * N: Rancher Labs, now part of SUSE - D: Rancher Labs certified Kubernetes distribution RKE2 can be deployed with Cilium. - U: Networking and network policy - L: https://github.com/rancher/rke and https://github.com/rancher/rke2 - - * N: Rapyuta Robotics. - D: Rapyuta is using cilium as their main CNI plugin. (self hosted k8s) - U: CiliumNetworkPolicy, Hubble, Service Load Balancing. - Q: @Gowtham - - * N: Rafay Systems - D: Rafay's Kubernetes Operations Platform uses Cilium for centralized network visibility and network policy enforcement - U: NetworkPolicy, Visibility via Prometheus metrics & Hubble - L: https://rafay.co/platform/network-policy-manager/ - Q: @cloudnativeboy @mohanatreya - - * N: Robinhood Markets - D: Robinhood uses Cilium for Kubernetes overlay networking in an environment where we run tests for backend services - U: CNI, Overlay networking - Q: @Madhu CS - - * N: Santa Claus & the Elves - D: All our infrastructure to process children's letters and wishes, toy making, and delivery, distributed over multiple clusters around the world, is now powered by Cilium. - U: ClusterMesh, L4LB, XDP acceleration, Bandwidth manager, Encryption, Hubble - L: https://qmonnet.github.io/whirl-offload/2024/01/02/santa-switches-to-cilium/ - - * N: SAP - D: SAP uses Cilium for multiple internal scenarios. For examples for self-hosted Kubernetes scenarios on AWS with SAP Concur and for managed Kubernetes clusters provided with Gardener Project across AWS, Azure, GCP, and OpenStack. - U: CNI , Overlay Network, Network Policies - L: https://www.concur.com, https://gardener.cloud/, https://github.com/gardener/gardener-extension-networking-cilium - Q: @dragan (SAP Concur), @docktofuture & @ScheererJ (Gardener) - - * N: Sapian - D: Sapian uses Cilium as the default CNI in our product DialBox Cloud; DialBox cloud is an Edge Kubernetes cluster using [kilo](https://github.com/squat/kilo) for WireGuard mesh connectivity inter-nodes. Therefore, Cilium is crucial for low latency in real-time communications environments. - U: CNI, Network Policies, Hubble, kube-proxy replacement - L: https://sapian.com.co, https://arpagon.co/blog/k8s-edge - Q: @arpagon - - * N: Schenker AG - D: Land transportation unit of Schenker uses Cilium as default CNI in self-managed kubernetes clusters running in AWS - U: CNI, Monitoring, kube-proxy replacement - L: https://www.dbschenker.com/global - Q: @amirkkn - - * N: Scigility AG - D: We use Cilium as the default CNI across client implementations and also for our internal platform. - U: CNI, Monitoring, kube-proxy replacement, Hubble - L: https://scigility.com/ - Q: @ciil - - * N: Sealos - D: Sealos is using Cilium as a consistent CNI for our Sealos Cloud. - U: Networking, Service, kube-proxy replacement, Network Policy, Hubble - L: https://sealos.io - Q: @fanux, @yangchuansheng - - * N: SeatGeek - D: SeatGeek uses Cilium as the default CNI/service mesh for AWS hosted clusters - U: CNI, ClusterMesh, Network Policy, Hubble, L7 Mesh - L: https://seatgeek.com - Q: @byxorna, @aetimmes - - * N: Seznam.cz - D: Seznam.cz uses Cilium in multiple scenarios in on-prem DCs. At first as L4LB which loadbalances external traffic into k8s+openstack clusters then as CNI in multiple k8s and openstack clusters which are all connected in a clustermesh to enforce NetworkPolicies across pods/VMs. - U: L4LB, L3/4 CNPs+CCNPs, KPR, Hubble, HostPolicy, Direct-routing, IPv4+IPv6, ClusterMesh - Q: @oblazek - - * N: Simple - D: Simple uses cilium as default CNI in Kubernetes clusters (AWS EKS) for both development and production environments. - U: CNI, Network Policies, Hubble - L: https://simple.life - Q: @sergeyshevch - - * N: Scaleway - D: Scaleway uses Cilium as the default CNI for Kubernetes Kapsule - U: Networking, NetworkPolicy, Services - L: @jtherin @remyleone - - * N: Schuberg Philis - D: Schuberg Philis uses Cilium as CNI for mission critical kubernetes clusters we run for our customers. - U: CNI (instead of amazon-vpc-cni-k8s), DefaultDeny(Zero Trust), Hubble, CiliumNetworkPolicy, CiliumClusterwideNetworkPolicy, EKS - L: https://schubergphilis.com/en - Q: @stimmerman @shoekstra @mbaumann - - * N: SDV Services - D: SDV Services uses Cilium to host Wordpress multi-tenant the cloud-native way and also as the CNI for customer Kubernetes clusters. - U: CNI, Networking, NetworkPolicy, Hubble, IPAM, Kubernetes services - L: https://sdvservices.nl - Q: @Sjouke de Vries - - * N: SI Analytics - D: SI Analytics uses Cilium as CNI in self-managed Kubernetes clusters in on-prem DCs. And also use Cilium as CNI in its GKE dataplane v2 based clusters. - U: CNI, Network Policies, Hubble - L: https://si-analytics.ai, https://ovision.ai - Q: @jholee - - * N: SIGHUP - D: SIGHUP integrated Cilium as a supported CNI for KFD (Kubernetes Fury Distribution), our enterprise-grade OSS reference architecture - U: Available supported CNI - L: https://sighup.io, https://github.com/sighupio/fury-kubernetes-networking - Q: @jnardiello @nutellino - - * N: SINAD - D: SINAD uses Cilium and integrates Tetragon (Which is amazing) to their application EzyKube - U: CNI, Networking, Node2Node & Pod2Pod Encryption, Kube-Proxy Replacement, eBPF, security - L: https://sinad.io - - * N: SmileDirectClub - D: SmileDirectClub is using Cilium in manufacturing clusters (self-hosted on vSphere and AWS EC2) - U: CNI - Q: @joey, @onur.gokkocabas - - * N: Snapp - D: Snapp is using Cilium in production for its on premise openshift clusters - U: CNI, Network Policies, Hubble - Q: @m-yosefpor - - * N: Solo.io - D: Cilium is part of Gloo Application Networking platform, with a “batteries included but swappable” manner - U: CNI, Network Policies - Q: @linsun - - * N: S&P Global - D: S&P Global uses Cilium as their multi-cloud CNI - U: CNI - L: https://www.youtube.com/watch?v=6CZ_SSTqb4g - - * N: Spectro Cloud - D: Spectro Cloud uses & promotes Cilium for clusters its K8S management platform (Palette) deploys - U: CNI, Overlay network, kube-proxy replacement - Q: @Kevin Reeuwijk - - * N: Spherity - D: Spherity is using Cilium on AWS EKS - U: CNI/ENI Networking, Network policies, Hubble - Q: @solidnerd - - * N: Sportradar - D: Sportradar is using Cilium as their main CNI plugin in AWS (using kops) - U: L3/L4 policies, Hubble, BPF NodePort, CiliumClusterwideNetworkPolicy - Q: @Eric Bailey, @Ole Markus - - * N: Sproutfi - D: Sproutfi uses Cilium as the CNI on its GKE based clusters - U: Service Load Balancing, Hubble, Datadog Integration for Prometheus metrics - Q: @edude03 - - * N: SuperOrbital - D: As a Kubernetes-focused consulting firm, we have implemented Cilium on customer engagements - U: CNI, CiliumNetworkPolicy at L7, Hubble - L: https://superorbital.io/ - Q: @jmcshane - - * N: Syself - D: Syself uses Cilium as the CNI for Syself Autopilot, a managed Kubernetes platform - U: CNI, HostFirewall, Monitoring, CiliumClusterwideNetworkPolicy, Hubble - L: https://syself.com - Q: @sbaete - - * N: Talos - D: Cilium is one of the supported CNI's in Talos - U: Networking, NetworkPolicy, Hubble, BPF NodePort - L: https://github.com/talos-systems/talos - Q: @frezbo, @smira, @Ulexus - - * N: Tencent Cloud - D: Tencent Cloud container team designed the TKE hybrid cloud container network solution with Cilium as the cluster network base - U: Networking, CNI - L: https://segmentfault.com/a/1190000040298428/en - - * N: teuto.net Netzdienste GmbH - D: teuto.net is using cilium for their managed k8s service, t8s - U: CNI, CiliumNetworkPolicy, Hubble, Encryption, ... - L: https://teuto.net/managed-kubernetes - Q: @cwrau - - * N: Trendyol - D: Trendyol.com has recently implemented Cilium as the default CNI for its production Kubernetes clusters starting from version 1.26. - U: Networking, kube-proxy replacement, eBPF, Network Visibility with Hubble and Grafana, Local Redirect Policy - L: https://t.ly/FDCZK - - * N: T-Systems International - D: TSI uses Cilium for it's Open Sovereign Cloud product, including as a CNI for Gardener-based Kubernetes clusters and bare-metal infrastructure managed by OnMetal. - U: CNI, overlay network, NetworkPolicies - Q: @ManuStoessel - - * N: uSwitch - D: uSwitch is using Cilium in AWS for all their production clusters (self hosted k8s) - U: ClusterMesh, CNI-Chaining (with amazon-vpc-cni-k8s) - Q: @jirving - - * N: United Cloud - D: United Cloud is using Cilium for all non-production and production clusters (on-premises) - U: CNI, Hubble, CiliumNetworkPolicy, CiliumClusterwideNetworkPolicy, ClusterMesh, Encryption - L: https://united.cloud - Q: @boris - - * N: Utmost Software, Inc - D: Utmost is using Cilium in all tiers of its Kubernetes ecosystem to implement zero trust - U: CNI, DefaultDeny(Zero Trust), Hubble, CiliumNetworkPolicy, CiliumClusterwideNetworkPolicy - L: https://blog.utmost.co/zero-trust-security-at-utmost - Q: @andrewholt - - * N: Trip.com - D: Trip.com is using Cilium in their production clusters (self-hosted k8s, On-premises and AWS) - U: ENI Networking, Service load-balancing, Direct routing (via Bird) - L: https://ctripcloud.github.io/cilium/network/2020/01/19/trip-first-step-towards-cloud-native-networking.html - Q: @ArthurChiao - - * N: Tailor Brands - D: Tailor Brands is using Cilium in their production, staging, and development clusters (AWS EKS) - U: CNI (instead of amazon-vpc-cni-k8s), Hubble, Datadog Integration for Prometheus metrics - Q: @liorrozen - - * N: Twilio - D: Twilio Segment is using Cilium across their k8s-based compute platform - U: CNI, EKS direct routing, kube-proxy replacement, Hubble, CiliumNetworkPolicies - Q: @msaah - - * N: ungleich - D: ungleich is using Cilium as part of IPv6-only Kubernetes deployments. - U: CNI, IPv6 only networking, BGP, eBPF - Q: @Nico Schottelius, @nico:ungleich.ch (Matrix) - - * N: Veepee - D: Veepee is using Cilium on their on-premise Kubernetes clusters, hosting majority of their applications. - U. CNI, BGP, eBPF, Hubble, DirectRouting (via kube-router) - Q: @nerzhul - - * N: Virtuozzo - D: Cilium CNI is the default network plugin for Kubernetes clusters within Virtuozzo Hybrid Infrastructure. - U: Networking, NetworkPolicy, Services - L: https://docs.virtuozzo.com/virtuozzo_hybrid_infrastructure_6_3_admins_guide/index.html#provisioning-kubernetes.html - Q: egor.ustinov@virtuozzo.com - - * N: VMware by Broadcom - D: VMware offers multi-arch (ARM, AMD) and multi-distro (Ubuntu, RedHat UBI, Debian, PhotonOS) Cilium as part of the Tanzu Application Catalog, enabling customers to deploy it in their Kubernetes infrastructure. - U: CNI, Hubble, BGP, eBPF, CiliumNetworkPolicy, CiliumClusterwideNetworkPolicy - L: https://app-catalog.vmware.com/catalog?gfilter=cilium - Q: @carrodher - - * N: Wildlife Studios - D: Wildlife Studios is using Cilium in AWS for all their game production clusters (self hosted k8s) - U: ClusterMesh, Global Service Load Balancing. - Q: @Oki @luanguimaraesla @rsafonseca - - * N: WSO2 - D: WSO2 is using Cilium to implemented Zero Trust Network Security for their Kubernetes clusters - U: CNI, WireGuard Transparent Encryption, CiliumClusterWideNetworkpolicy, CiliumNetworkPolicy, Hubble, Layer 7 visibility and Service Mesh via Cilium Envoy - L: https://www.cncf.io/case-studies/wso2/ - Q: @lakwarus @isala404 @tharinduwijewardane - - * N: Yahoo! - D: Yahoo is using Cilium for L4 North-South Load Balancing for Kubernetes Services - L: https://www.youtube.com/watch?v=-C86fBMcp5Q - - * N: ZeroHash - D: Zero Hash is using Cilium as CNI for networking, security and monitoring features for Kubernetes clusters - U: CNI/ENI Networking, Network policies, Hubble - Q: @eugenestarchenko diff --git a/vendor/github.com/cilium/cilium/VERSION b/vendor/github.com/cilium/cilium/VERSION deleted file mode 100644 index ee017091ff..0000000000 --- a/vendor/github.com/cilium/cilium/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.18.0-dev diff --git a/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go b/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go index ca90a8a6d5..a71c0c56c5 100644 --- a/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/flow/flow.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.5 -// protoc v5.29.3 +// protoc v6.30.1 // source: flow/flow.proto package flow diff --git a/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go b/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go index bc136ad831..cf2a39cfa4 100644 --- a/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/observer/observer.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.5 -// protoc v5.29.3 +// protoc v6.30.1 // source: observer/observer.proto package observer diff --git a/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go b/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go index f9e149cf81..c4e670e6a9 100644 --- a/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/observer/observer_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.29.3 +// - protoc v6.30.1 // source: observer/observer.proto package observer diff --git a/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go b/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go index 3af74c961a..c232915ef0 100644 --- a/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go +++ b/vendor/github.com/cilium/cilium/api/v1/relay/relay.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.5 -// protoc v5.29.3 +// protoc v6.30.1 // source: relay/relay.proto package relay diff --git a/vendor/github.com/cilium/cilium/assets.go b/vendor/github.com/cilium/cilium/assets.go deleted file mode 100644 index cca1fcf7bf..0000000000 --- a/vendor/github.com/cilium/cilium/assets.go +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -// Cilium provides access to top-level files in the tree for Cilium development. -package cilium - -import ( - _ "embed" -) - -//go:embed CODEOWNERS -var CodeOwnersRaw string diff --git a/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go b/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go index 4fa7caeb36..6fbae86479 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/cli/connectivity.go @@ -17,12 +17,12 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" - assets "github.com/cilium/cilium" "github.com/cilium/cilium/cilium-cli/api" "github.com/cilium/cilium/cilium-cli/connectivity" "github.com/cilium/cilium/cilium-cli/connectivity/check" "github.com/cilium/cilium/cilium-cli/defaults" "github.com/cilium/cilium/cilium-cli/sysdump" + owners_util "github.com/cilium/cilium/cilium-cli/utils/codeowners" "github.com/cilium/cilium/cilium-cli/utils/features" "github.com/cilium/cilium/pkg/option" ) @@ -44,6 +44,8 @@ var params = check.Parameters{ ExternalDeploymentPort: 8080, EchoServerHostPort: 4000, JunitProperties: make(map[string]string), + NamespaceLabels: make(map[string]string), + NamespaceAnnotations: make(map[string]string), NodeSelector: make(map[string]string), Writer: os.Stdout, SysdumpOptions: sysdump.Options{ @@ -95,12 +97,17 @@ func RunE(hooks api.Hooks) func(cmd *cobra.Command, args []string) error { return nil } - logger := check.NewConcurrentLogger(params.Writer, params.TestConcurrency) - owners, err := codeowners.ParseFile(strings.NewReader(assets.CodeOwnersRaw)) - if err != nil { - return fmt.Errorf("🐛 Failed to parse CODEOWNERS. Developer BUG? %w", err) + var owners codeowners.Ruleset + if params.LogCodeOwners { + var err error + + owners, err = owners_util.Load(params.CodeOwners) + if err != nil { + return fmt.Errorf("❗ Failed to load code owners: %w", err) + } } + logger := check.NewConcurrentLogger(params.Writer) connTests, err := newConnectivityTests(params, hooks, logger, owners) if err != nil { return err @@ -143,9 +150,6 @@ func newCmdConnectivityTest(hooks api.Hooks) *cobra.Command { cmd.Flags().StringVar(¶ms.AgentPodSelector, "agent-pod-selector", defaults.AgentPodSelector, "Label on cilium-agent pods to select with") cmd.Flags().StringVar(¶ms.CiliumPodSelector, "cilium-pod-selector", defaults.CiliumPodSelector, "Label selector matching all cilium-related pods") cmd.Flags().Var(option.NewNamedMapOptions("node-selector", ¶ms.NodeSelector, nil), "node-selector", "Restrict connectivity pods to nodes matching this label") - cmd.Flags().Var(¶ms.NamespaceAnnotations, "namespace-annotations", "Add annotations to the connectivity test namespace, e.g. '{\"foo\":\"bar\"}'") - cmd.Flags().MarkHidden("namespace-annotations") - cmd.Flags().MarkHidden("deployment-pod-annotations") cmd.Flags().StringVar(¶ms.MultiCluster, "multi-cluster", "", "Test across clusters to given context") cmd.Flags().StringSliceVar(&tests, "test", []string{}, "Run tests that match one of the given regular expressions, skip tests by starting the expression with '!', target Scenarios with e.g. '/pod-to-cidr'") cmd.Flags().StringVar(¶ms.FlowValidation, "flow-validation", check.FlowValidationModeWarning, "Enable Hubble flow validation { disabled | warning | strict }") @@ -155,7 +159,7 @@ func newCmdConnectivityTest(hooks api.Hooks) *cobra.Command { cmd.Flags().BoolVarP(¶ms.Timestamp, "timestamp", "t", false, "Show timestamp in messages") cmd.Flags().BoolVarP(¶ms.PauseOnFail, "pause-on-fail", "p", false, "Pause execution on test failure") cmd.Flags().StringVar(¶ms.ExternalTarget, "external-target", "one.one.one.one.", "Domain name to use as external target in connectivity tests") - cmd.Flags().StringVar(¶ms.ExternalOtherTarget, "external-other-target", "cilium.io.", "Domain name to use as a second external target in connectivity tests") + cmd.Flags().StringVar(¶ms.ExternalOtherTarget, "external-other-target", "k8s.io.", "Domain name to use as a second external target in connectivity tests") cmd.Flags().StringVar(¶ms.ExternalTargetCANamespace, "external-target-ca-namespace", "", "Namespace of the CA secret for the external target. Used by client-egress-l7-tls test cases.") cmd.Flags().StringVar(¶ms.ExternalTargetCAName, "external-target-ca-name", "cabundle", "Name of the CA secret for the external target. Used by client-egress-l7-tls test cases.") cmd.Flags().StringVar(¶ms.ExternalCIDR, "external-cidr", "1.0.0.0/8", "CIDR to use as external target in connectivity tests") @@ -197,6 +201,7 @@ func newCmdConnectivityTest(hooks api.Hooks) *cobra.Command { cmd.Flags().BoolVar(¶ms.IncludeConnDisruptTest, "include-conn-disrupt-test", false, "Include conn disrupt test") cmd.Flags().BoolVar(¶ms.IncludeConnDisruptTestNSTraffic, "include-conn-disrupt-test-ns-traffic", false, "Include conn disrupt test for NS traffic") + cmd.Flags().BoolVar(¶ms.IncludeConnDisruptTestEgressGateway, "include-conn-disrupt-test-egw", false, "Include conn disrupt test for Egress Gateway") cmd.Flags().BoolVar(¶ms.ConnDisruptTestSetup, "conn-disrupt-test-setup", false, "Set up conn disrupt test dependencies") cmd.Flags().StringVar(¶ms.ConnDisruptTestRestartsPath, "conn-disrupt-test-restarts-path", "/tmp/cilium-conn-disrupt-restarts", "Conn disrupt test temporary result file (used internally)") cmd.Flags().StringVar(¶ms.ConnDisruptTestXfrmErrorsPath, "conn-disrupt-test-xfrm-errors-path", "/tmp/cilium-conn-disrupt-xfrm-errors", "Conn disrupt test temporary result file (used internally)") @@ -207,6 +212,8 @@ func newCmdConnectivityTest(hooks api.Hooks) *cobra.Command { cmd.Flags().StringSliceVar(¶ms.ExpectedXFRMErrors, "expected-xfrm-errors", defaults.ExpectedXFRMErrors, "List of expected XFRM errors") cmd.Flags().MarkHidden("expected-xfrm-errors") + cmd.Flags().StringSliceVar(¶ms.CodeOwners, "code-owners", []string{}, "Use the code owners defined in these files for --log-code-owners") + cmd.Flags().MarkHidden("code-owners") cmd.Flags().BoolVar(¶ms.LogCodeOwners, "log-code-owners", defaults.LogCodeOwners, "Log code owners for tests that fail") cmd.Flags().MarkHidden("log-code-owners") cmd.Flags().StringSliceVar(¶ms.ExcludeCodeOwners, "exclude-code-owners", []string{}, "Exclude specific code owners from --log-code-owners") @@ -254,7 +261,9 @@ func newCmdConnectivityPerf(hooks api.Hooks) *cobra.Command { cmd.Flags().BoolVar(¶ms.PerfParameters.RR, "rr", true, "Run RR test") cmd.Flags().BoolVar(¶ms.PerfParameters.UDP, "udp", false, "Run UDP tests") cmd.Flags().BoolVar(¶ms.PerfParameters.Throughput, "throughput", true, "Run throughput test") + cmd.Flags().BoolVar(¶ms.PerfParameters.ThroughputMulti, "throughput-multi", true, "Run throughput test with multiple streams") cmd.Flags().IntVar(¶ms.PerfParameters.Samples, "samples", 1, "Number of Performance samples to capture (how many times to run each test)") + cmd.Flags().UintVar(¶ms.PerfParameters.Streams, "streams", 4, "The parallelism of tests with multiple streams") cmd.Flags().BoolVar(¶ms.PerfParameters.HostNet, "host-net", true, "Test host network") cmd.Flags().BoolVar(¶ms.PerfParameters.PodNet, "pod-net", true, "Test pod network") cmd.Flags().BoolVar(¶ms.PerfParameters.PodToHost, "pod-to-host", false, "Test pod-to-host traffic") @@ -279,7 +288,11 @@ func newCmdConnectivityPerf(hooks api.Hooks) *cobra.Command { func registerCommonFlags(flags *pflag.FlagSet) { flags.BoolVarP(¶ms.Debug, "debug", "d", false, "Show debug messages") flags.StringVar(¶ms.TestNamespace, "test-namespace", defaults.ConnectivityCheckNamespace, "Namespace to perform the connectivity in (always suffixed with a sequence number to be compliant with test-concurrency param, e.g.: cilium-test-1)") + flags.Var(option.NewNamedMapOptions("namespace-labels", ¶ms.NamespaceLabels, nil), "namespace-labels", "Add labels to the connectivity test namespace") + flags.Var(option.NewNamedMapOptions("namespace-annotations", ¶ms.NamespaceAnnotations, nil), "namespace-annotations", "Add annotations to the connectivity test namespace") + flags.MarkHidden("namespace-annotations") flags.Var(¶ms.DeploymentAnnotations, "deployment-pod-annotations", "Add annotations to the connectivity pods, e.g. '{\"client\":{\"foo\":\"bar\"}}'") + flags.MarkHidden("deployment-pod-annotations") flags.BoolVar(¶ms.PrintImageArtifacts, "print-image-artifacts", false, "Prints the used image artifacts") } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/clustermesh/clustermesh.go b/vendor/github.com/cilium/cilium/cilium-cli/clustermesh/clustermesh.go index d6e84b2e38..ed8880e3e5 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/clustermesh/clustermesh.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/clustermesh/clustermesh.go @@ -1319,10 +1319,8 @@ func (k *K8sClusterMesh) checkConnectionMode() error { defaults.ClusterMeshConnectionModeUnicast, } - for _, mode := range validModes { - if k.params.ConnectionMode == mode { - return nil - } + if slices.Contains(validModes, k.params.ConnectionMode) { + return nil } k.Log("❌ %s is not a correct connection mode.", k.params.ConnectionMode) @@ -1497,7 +1495,7 @@ func (k *K8sClusterMesh) retrieveRemoteHelmValues(ctx context.Context, remoteCli } func removeStringFromSlice(name string, names []string) []string { - namesCopy := append([]string{}, names...) + namesCopy := slices.Clone(names) namesCopy = slices.DeleteFunc(namesCopy, func(n string) bool { return n == name }) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/builder.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/builder.go index 261fdeff24..eb113e0646 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/builder.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/builder.go @@ -78,6 +78,9 @@ var ( //go:embed manifests/client-egress-l7-tls-sni.yaml clientEgressL7TLSSNIPolicyYAML string + //go:embed manifests/client-egress-l7-tls-other-sni.yaml + clientEgressL7TLSOtherSNIPolicyYAML string + //go:embed manifests/client-egress-l7-tls.yaml clientEgressL7TLSPolicyYAML string @@ -262,14 +265,7 @@ func concurrentTests(connTests []*check.ConnectivityTest) error { echoIngressAuthAlwaysFail{}, echoIngressMutualAuthSpiffe{}, podToIngressService{}, - podToIngressServiceDenyAll{}, - podToIngressServiceDenyIngressIdentity{}, - podToIngressServiceDenyBackendService{}, - podToIngressServiceAllowIngressIdentity{}, outsideToIngressService{}, - outsideToIngressServiceDenyWorldIdentity{}, - outsideToIngressServiceDenyCidr{}, - outsideToIngressServiceDenyAllIngress{}, dnsOnly{}, toFqdns{}, podToControlplaneHost{}, @@ -317,6 +313,7 @@ func renderTemplates(clusterName string, param check.Parameters) (map[string]str "clientEgressTLSSNIPolicyYAML": clientEgressTLSSNIPolicyYAML, "clientEgressTLSSNIOtherPolicyYAML": clientEgressTLSSNIOtherPolicyYAML, "clientEgressL7TLSSNIPolicyYAML": clientEgressL7TLSSNIPolicyYAML, + "clientEgressL7TLSOtherSNIPolicyYAML": clientEgressL7TLSOtherSNIPolicyYAML, "clientEgressL7TLSPolicyYAML": clientEgressL7TLSPolicyYAML, "clientEgressL7TLSPolicyPortRangeYAML": clientEgressL7TLSPolicyPortRangeYAML, "clientEgressL7HTTPMatchheaderSecretYAML": clientEgressL7HTTPMatchheaderSecretYAML, diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go index 55ec4379e5..eaa9cc6545 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/client_egress_tls_sni.go @@ -67,4 +67,25 @@ func clientEgressL7TlsSniTest(ct *check.ConnectivityTest, templates map[string]s WithExpectations(func(a *check.Action) (egress, ingress check.Result) { return check.ResultOK, check.ResultNone }) + + // This test is similar to the previous one, but with a different SNI. + // So the expectation is curl ssl error (e.g. exit code 35) instead. + testName = "client-egress-l7-tls-headers-other-sni" + yamlFile = templates["clientEgressL7TLSOtherSNIPolicyYAML"] + newTest(testName, ct). + WithCiliumVersion("!1.14.15 !1.14.16 !1.15.9 !1.15.10 !1.16.2 !1.16.3"). + WithFeatureRequirements(features.RequireEnabled(features.L7Proxy)). + WithFeatureRequirements(features.RequireEnabled(features.PolicySecretsOnlyFromSecretsNamespace)). + WithCABundleSecret(). + WithCertificate("externaltarget-tls", ct.Params().ExternalTarget). + WithCiliumPolicy(yamlFile). // L7 allow policy TLS SNI enforcement + WithCiliumPolicy(templates["clientEgressOnlyDNSPolicyYAML"]). // DNS resolution only + WithScenarios(tests.PodToWorldWithTLSIntercept("-H", "X-Very-Secret-Token: 42")). + WithExpectations(func(a *check.Action) (egress, ingress check.Result) { + if a.Destination().Port() == 443 { + // SSL error as another external target (e.g. cilium.io) SNI is not allowed + return check.ResultCurlSSLError, check.ResultNone + } + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls-other-sni.yaml b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls-other-sni.yaml new file mode 100644 index 0000000000..46493a8650 --- /dev/null +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/client-egress-l7-tls-other-sni.yaml @@ -0,0 +1,31 @@ +apiVersion: "cilium.io/v2" +kind: CiliumNetworkPolicy +metadata: + name: "client-egress-l7-tls-other-sni" +specs: +- description: "L7 policy with TLS" + endpointSelector: + matchLabels: + kind: client + egress: + # Allow HTTPS when X-Very-Secret-Token is set + - toPorts: + - ports: + - port: "443" + protocol: "TCP" + serverNames: + - "{{trimSuffix .ExternalOtherTarget "."}}" + terminatingTLS: + secret: + namespace: "{{.TestNamespace}}" + name: externaltarget-tls # internal certificate to terminate in cluster + originatingTLS: + secret: + namespace: "{{.ExternalTargetCANamespace}}" + name: "{{.ExternalTargetCAName}}" # public CA bundle to validate external target + rules: + http: + - method: "GET" + path: "/" + headers: + - "X-Very-Secret-Token: 42" diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/deny-ingress-source-egress-other-node.yaml b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/deny-ingress-source-egress-other-node.yaml new file mode 100644 index 0000000000..8d0114478e --- /dev/null +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/manifests/deny-ingress-source-egress-other-node.yaml @@ -0,0 +1,12 @@ +apiVersion: "cilium.io/v2" +kind: CiliumNetworkPolicy +metadata: + name: "ingress-source-egress-deny-other-node" +spec: + endpointSelector: + matchLabels: + kind: client + egress: + - toEndpoints: + - matchLabels: + name: echo-same-node diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service.go index a580dcb1b3..1bea3c0496 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service.go @@ -4,17 +4,55 @@ package builder import ( + _ "embed" + "github.com/cilium/cilium/cilium-cli/connectivity/check" "github.com/cilium/cilium/cilium-cli/connectivity/tests" "github.com/cilium/cilium/cilium-cli/utils/features" ) +//go:embed manifests/deny-world-entity.yaml +var denyWorldIdentityPolicyYAML string + type outsideToIngressService struct{} -func (t outsideToIngressService) build(ct *check.ConnectivityTest, _ map[string]string) { +func (t outsideToIngressService) build(ct *check.ConnectivityTest, templates map[string]string) { newTest("outside-to-ingress-service", ct). WithFeatureRequirements( features.RequireEnabled(features.IngressController), features.RequireEnabled(features.NodeWithoutCilium)). WithScenarios(tests.OutsideToIngressService()) + + newTest("outside-to-ingress-service-deny-all-ingress", ct). + WithFeatureRequirements( + features.RequireEnabled(features.IngressController), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithScenarios(tests.OutsideToIngressService()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + + newTest("outside-to-ingress-service-deny-cidr", ct). + WithFeatureRequirements( + features.RequireEnabled(features.IngressController), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithCiliumPolicy(templates["denyCIDRPolicyYAML"]). + WithScenarios(tests.OutsideToIngressService()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + + newTest("outside-to-ingress-service-deny-world-identity", ct). + WithFeatureRequirements( + features.RequireEnabled(features.IngressController), + features.RequireEnabled(features.NodeWithoutCilium), + ). + WithCiliumPolicy(denyWorldIdentityPolicyYAML). + WithScenarios(tests.OutsideToIngressService()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_all_ingress.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_all_ingress.go deleted file mode 100644 index a6c8e28b6a..0000000000 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_all_ingress.go +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package builder - -import ( - "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium/cilium-cli/utils/features" -) - -type outsideToIngressServiceDenyAllIngress struct{} - -func (t outsideToIngressServiceDenyAllIngress) build(ct *check.ConnectivityTest, _ map[string]string) { - newTest("outside-to-ingress-service-deny-all-ingress", ct). - WithFeatureRequirements( - features.RequireEnabled(features.IngressController), - features.RequireEnabled(features.NodeWithoutCilium), - ). - WithCiliumPolicy(denyAllIngressPolicyYAML). - WithScenarios(tests.OutsideToIngressService()). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_cidr.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_cidr.go deleted file mode 100644 index ac3f930d3e..0000000000 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_cidr.go +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package builder - -import ( - "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium/cilium-cli/utils/features" -) - -type outsideToIngressServiceDenyCidr struct{} - -func (t outsideToIngressServiceDenyCidr) build(ct *check.ConnectivityTest, templates map[string]string) { - newTest("outside-to-ingress-service-deny-cidr", ct). - WithFeatureRequirements( - features.RequireEnabled(features.IngressController), - features.RequireEnabled(features.NodeWithoutCilium), - ). - WithCiliumPolicy(templates["denyCIDRPolicyYAML"]). - WithScenarios(tests.OutsideToIngressService()). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_world_identity.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_world_identity.go deleted file mode 100644 index 8fe39ee45c..0000000000 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/outside_to_ingress_service_deny_world_identity.go +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package builder - -import ( - _ "embed" - - "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium/cilium-cli/utils/features" -) - -//go:embed manifests/deny-world-entity.yaml -var denyWorldIdentityPolicyYAML string - -type outsideToIngressServiceDenyWorldIdentity struct{} - -func (t outsideToIngressServiceDenyWorldIdentity) build(ct *check.ConnectivityTest, _ map[string]string) { - newTest("outside-to-ingress-service-deny-world-identity", ct). - WithFeatureRequirements( - features.RequireEnabled(features.IngressController), - features.RequireEnabled(features.NodeWithoutCilium), - ). - WithCiliumPolicy(denyWorldIdentityPolicyYAML). - WithScenarios(tests.OutsideToIngressService()). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service.go index 36d2857942..219c3589d1 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service.go @@ -4,16 +4,76 @@ package builder import ( + _ "embed" + "strings" + "github.com/cilium/cilium/cilium-cli/connectivity/check" "github.com/cilium/cilium/cilium-cli/connectivity/tests" "github.com/cilium/cilium/cilium-cli/utils/features" ) +var ( + //go:embed manifests/allow-ingress-identity.yaml + allowIngressIdentityPolicyYAML string + + //go:embed manifests/deny-ingress-backend.yaml + denyIngressBackendPolicyYAML string + + //go:embed manifests/deny-ingress-entity.yaml + denyIngressIdentityPolicyYAML string + + //go:embed manifests/deny-ingress-source-egress-other-node.yaml + denyIngressSourceEgressOtherNodePolicyYML string +) + type podToIngressService struct{} -func (t podToIngressService) build(ct *check.ConnectivityTest, _ map[string]string) { +func (t podToIngressService) build(ct *check.ConnectivityTest, templates map[string]string) { // Test Ingress controller newTest("pod-to-ingress-service", ct). WithFeatureRequirements(features.RequireEnabled(features.IngressController)). WithScenarios(tests.PodToIngress()) + + newTest("pod-to-ingress-service-allow-ingress-identity", ct). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithCiliumPolicy(allowIngressIdentityPolicyYAML). + WithScenarios(tests.PodToIngress()) + + newTest("pod-to-ingress-service-deny-all", ct). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyAllIngressPolicyYAML). + WithScenarios(tests.PodToIngress()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + + newTest("pod-to-ingress-service-deny-backend-service", ct). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyIngressBackendPolicyYAML). + WithScenarios(tests.PodToIngress()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + + newTest("pod-to-ingress-service-deny-ingress-identity", ct). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyIngressIdentityPolicyYAML). + WithScenarios(tests.PodToIngress()). + WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) + + newTest("pod-to-ingress-service-deny-source-egress-other-node", ct). + WithCiliumVersion(">1.17.1 >1.16.7 >1.15.14"). + WithFeatureRequirements(features.RequireEnabled(features.IngressController)). + WithCiliumPolicy(denyIngressSourceEgressOtherNodePolicyYML). + WithCiliumPolicy(templates["clientEgressOnlyDNSPolicyYAML"]). // DNS resolution only + WithScenarios(tests.PodToIngress()). + WithExpectations(func(a *check.Action) (egress check.Result, ingress check.Result) { + if strings.Contains(a.Destination().Name(), "cilium-ingress-same-node") { + return check.ResultOK, check.ResultOK + } + return check.ResultDefaultDenyEgressDrop, check.ResultNone + }) } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_allow_ingress_identity.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_allow_ingress_identity.go deleted file mode 100644 index 6ebc506b1c..0000000000 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_allow_ingress_identity.go +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package builder - -import ( - _ "embed" - - "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium/cilium-cli/utils/features" -) - -//go:embed manifests/allow-ingress-identity.yaml -var allowIngressIdentityPolicyYAML string - -type podToIngressServiceAllowIngressIdentity struct{} - -func (t podToIngressServiceAllowIngressIdentity) build(ct *check.ConnectivityTest, _ map[string]string) { - newTest("pod-to-ingress-service-allow-ingress-identity", ct). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyAllIngressPolicyYAML). - WithCiliumPolicy(allowIngressIdentityPolicyYAML). - WithScenarios(tests.PodToIngress()) -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_all.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_all.go deleted file mode 100644 index dcc27df22f..0000000000 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_all.go +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package builder - -import ( - "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium/cilium-cli/utils/features" -) - -type podToIngressServiceDenyAll struct{} - -func (t podToIngressServiceDenyAll) build(ct *check.ConnectivityTest, _ map[string]string) { - newTest("pod-to-ingress-service-deny-all", ct). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyAllIngressPolicyYAML). - WithScenarios(tests.PodToIngress()). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_backend_service.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_backend_service.go deleted file mode 100644 index 42ee591c9a..0000000000 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_backend_service.go +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package builder - -import ( - _ "embed" - - "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium/cilium-cli/utils/features" -) - -//go:embed manifests/deny-ingress-backend.yaml -var denyIngressBackendPolicyYAML string - -type podToIngressServiceDenyBackendService struct{} - -func (t podToIngressServiceDenyBackendService) build(ct *check.ConnectivityTest, _ map[string]string) { - newTest("pod-to-ingress-service-deny-backend-service", ct). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyIngressBackendPolicyYAML). - WithScenarios(tests.PodToIngress()). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_ingress_identity.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_ingress_identity.go deleted file mode 100644 index 8ecad45034..0000000000 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/builder/pod_to_ingress_service_deny_ingress_identity.go +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package builder - -import ( - _ "embed" - - "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/connectivity/tests" - "github.com/cilium/cilium/cilium-cli/utils/features" -) - -//go:embed manifests/deny-ingress-entity.yaml -var denyIngressIdentityPolicyYAML string - -type podToIngressServiceDenyIngressIdentity struct{} - -func (t podToIngressServiceDenyIngressIdentity) build(ct *check.ConnectivityTest, _ map[string]string) { - newTest("pod-to-ingress-service-deny-ingress-identity", ct). - WithFeatureRequirements(features.RequireEnabled(features.IngressController)). - WithCiliumPolicy(denyIngressIdentityPolicyYAML). - WithScenarios(tests.PodToIngress()). - WithExpectations(func(_ *check.Action) (egress check.Result, ingress check.Result) { - return check.ResultDefaultDenyEgressDrop, check.ResultNone - }) -} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go index a366ba0e45..c676c3f0e0 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/check.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "maps" "regexp" "strings" "time" @@ -21,23 +22,25 @@ import ( ) type PerfParameters struct { - ReportDir string - Duration time.Duration - SetupDelay time.Duration - HostNet bool - PodNet bool - PodToHost bool - HostToPod bool - SameNode bool - OtherNode bool - Samples int - MessageSize int - Throughput bool - CRR bool - RR bool - UDP bool - Image string - NetQos bool + ReportDir string + Duration time.Duration + SetupDelay time.Duration + HostNet bool + PodNet bool + PodToHost bool + HostToPod bool + SameNode bool + OtherNode bool + Samples int + MessageSize int + Streams uint + Throughput bool + ThroughputMulti bool + CRR bool + RR bool + UDP bool + Image string + NetQos bool NodeSelectorServer map[string]string NodeSelectorClient map[string]string @@ -91,7 +94,8 @@ type Parameters struct { CiliumPodSelector string NodeSelector map[string]string DeploymentAnnotations annotationsMap - NamespaceAnnotations annotations + NamespaceLabels map[string]string + NamespaceAnnotations map[string]string ExternalTarget string ExternalOtherTarget string ExternalCIDR string @@ -111,16 +115,18 @@ type Parameters struct { ImpersonateGroups []string IPFamilies []string - IncludeConnDisruptTest bool - IncludeConnDisruptTestNSTraffic bool - ConnDisruptTestSetup bool - ConnDisruptTestRestartsPath string - ConnDisruptTestXfrmErrorsPath string - ConnDisruptDispatchInterval time.Duration + IncludeConnDisruptTest bool + IncludeConnDisruptTestNSTraffic bool + IncludeConnDisruptTestEgressGateway bool + ConnDisruptTestSetup bool + ConnDisruptTestRestartsPath string + ConnDisruptTestXfrmErrorsPath string + ConnDisruptDispatchInterval time.Duration ExpectedDropReasons []string ExpectedXFRMErrors []string + CodeOwners []string LogCodeOwners bool ExcludeCodeOwners []string LogCheckLevels []string @@ -308,9 +314,7 @@ func (r *FlowRequirementResults) Merge(from *FlowRequirementResults) { if r.Matched == nil { r.Matched = from.Matched } else { - for k, v := range from.Matched { - r.Matched[k] = v - } + maps.Copy(r.Matched, from.Matched) } r.Failures += from.Failures r.NeedMoreFlows = r.NeedMoreFlows || from.NeedMoreFlows diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go index 367b2b2086..1219b3a512 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/context.go @@ -303,6 +303,21 @@ func (ct *ConnectivityTest) SetupAndValidate(ctx context.Context, extra SetupHoo if err := ctx.Err(); err != nil { return err } + + setupAndValidate := ct.setupAndValidate + if ct.Params().Perf { + setupAndValidate = ct.setupAndValidatePerf + } + + if err := setupAndValidate(ctx, extra); err != nil { + return err + } + + // Setup and validate all the extras coming from extended functionalities. + return extra.SetupAndValidate(ctx, ct) +} + +func (ct *ConnectivityTest) setupAndValidate(ctx context.Context, extra SetupHooks) error { if err := ct.detectSingleNode(ctx); err != nil { return err } @@ -375,8 +390,23 @@ func (ct *ConnectivityTest) SetupAndValidate(ctx context.Context, extra SetupHoo } } - // Setup and validate all the extras coming from extended functionalities. - return extra.SetupAndValidate(ctx, ct) + return nil +} + +func (ct *ConnectivityTest) setupAndValidatePerf(ctx context.Context, _ SetupHooks) error { + if err := ct.initClients(ctx); err != nil { + return err + } + + if err := ct.deployPerf(ctx); err != nil { + return err + } + + if err := ct.validateDeploymentPerf(ctx); err != nil { + return err + } + + return nil } // PrintTestInfo prints connectivity test names and count. @@ -561,12 +591,12 @@ func (ct *ConnectivityTest) report() error { } } ct.Logf("%s", strings.Repeat("-", 200)) - ct.Logf("%s", strings.Repeat("-", 85)) - ct.Logf("📋 %-15s | %-10s | %-15s | %-15s | %-15s ", "Scenario", "Node", "Test", "Duration", "Throughput Mb/s") - ct.Logf("%s", strings.Repeat("-", 85)) + ct.Logf("%s", strings.Repeat("-", 88)) + ct.Logf("📋 %-15s | %-10s | %-18s | %-15s | %-15s ", "Scenario", "Node", "Test", "Duration", "Throughput Mb/s") + ct.Logf("%s", strings.Repeat("-", 88)) for _, result := range ct.PerfResults { if result.Result.ThroughputMetric != nil { - ct.Logf("📋 %-15s | %-10s | %-15s | %-15s | %-12.2f ", + ct.Logf("📋 %-15s | %-10s | %-18s | %-15s | %-12.2f ", result.PerfTest.Scenario, nodeString(result.PerfTest.SameNode), result.PerfTest.Test, @@ -575,7 +605,7 @@ func (ct *ConnectivityTest) report() error { ) } } - ct.Logf("%s", strings.Repeat("-", 85)) + ct.Logf("%s", strings.Repeat("-", 88)) if ct.Params().PerfParameters.ReportDir != "" { common.ExportPerfSummaries(ct.PerfResults, ct.Params().PerfParameters.ReportDir) } @@ -1285,3 +1315,12 @@ func (ct *ConnectivityTest) ShouldRunConnDisruptNSTraffic() bool { !ct.Features[features.KPRNodePortAcceleration].Enabled && (!ct.Features[features.IPsecEnabled].Enabled || !ct.Features[features.KPRNodePort].Enabled) } + +func (ct *ConnectivityTest) ShouldRunConnDisruptEgressGateway() bool { + return ct.params.IncludeUnsafeTests && + ct.params.IncludeConnDisruptTestEgressGateway && + ct.Features[features.EgressGateway].Enabled && + ct.Features[features.NodeWithoutCilium].Enabled && + !ct.Features[features.KPRNodePortAcceleration].Enabled && + ct.params.MultiCluster == "" +} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/deployment.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/deployment.go index 2039f3df74..0664026688 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/deployment.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/deployment.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "maps" + "net" "net/netip" "slices" "sort" @@ -26,6 +27,7 @@ import ( "github.com/cilium/cilium/cilium-cli/defaults" "github.com/cilium/cilium/cilium-cli/k8s" "github.com/cilium/cilium/cilium-cli/utils/features" + k8sconst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io" ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" slimmetav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" policyapi "github.com/cilium/cilium/pkg/policy/api" @@ -71,17 +73,27 @@ const ( hostNetNSDeploymentNameNonCilium = "host-netns-non-cilium" // runs on non-Cilium test nodes kindHostNetNS = "host-netns" - testConnDisruptClientDeploymentName = "test-conn-disrupt-client" - testConnDisruptClientNSTrafficDeploymentName = "test-conn-disrupt-client" - testConnDisruptServerDeploymentName = "test-conn-disrupt-server" - testConnDisruptServerNSTrafficDeploymentName = "test-conn-disrupt-server-ns-traffic" - testConnDisruptServiceName = "test-conn-disrupt" - testConnDisruptNSTrafficServiceName = "test-conn-disrupt-ns-traffic" - testConnDisruptCNPName = "test-conn-disrupt" - testConnDisruptNSTrafficCNPName = "test-conn-disrupt-ns-traffic" - testConnDisruptServerNSTrafficAppLabel = "test-conn-disrupt-server-ns-traffic" - KindTestConnDisrupt = "test-conn-disrupt" - KindTestConnDisruptNSTraffic = "test-conn-disrupt-ns-traffic" + testConnDisruptClientDeploymentName = "test-conn-disrupt-client" + testConnDisruptClientNSTrafficDeploymentName = "test-conn-disrupt-client" + testConnDisruptClientEgressGatewayOnGatewayNodeDeploymentName = "test-conn-disrupt-client-egw-gw-node" + testConnDisruptClientEgressGatewayOnNonGatewayNodeDeploymentName = "test-conn-disrupt-client-egw-non-gw-node" + testConnDisruptServerDeploymentName = "test-conn-disrupt-server" + testConnDisruptServerNSTrafficDeploymentName = "test-conn-disrupt-server-ns-traffic" + testConnDisruptServerEgressGatewayDeploymentName = "test-conn-disrupt-server-egw" + testConnDisruptServiceName = "test-conn-disrupt" + testConnDisruptNSTrafficServiceName = "test-conn-disrupt-ns-traffic" + testConnDisruptEgressGatewayServiceName = "test-conn-disrupt-egw" + testConnDisruptCNPName = "test-conn-disrupt" + testConnDisruptNSTrafficCNPName = "test-conn-disrupt-ns-traffic" + testConnDisruptEgressGatewayCNPName = "test-conn-disrupt-egw" + testConnDisruptCEGPName = "test-conn-disrupt" + testConnDisruptServerNSTrafficAppLabel = "test-conn-disrupt-server-ns-traffic" + testConnDisruptServerEgressGatewayAppLabel = "test-conn-disrupt-server-egw" + testConnDisruptClientEgressGatewayOnGatewayNodeAppLabel = "test-conn-disrupt-client-egw-gw-node" + testConnDisruptClientEgressGatewayOnNonGatewayNodeAppLabel = "test-conn-disrupt-client-egw-non-gw-node" + KindTestConnDisrupt = "test-conn-disrupt" + KindTestConnDisruptNSTraffic = "test-conn-disrupt-ns-traffic" + KindTestConnDisruptEgressGateway = "test-conn-disrupt-egw" bwPrioAnnotationString = "bandwidth.cilium.io/priority" ) @@ -198,9 +210,7 @@ func newDeployment(p deploymentParameters) *appsv1.Deployment { }, } - for k, v := range p.Labels { - dep.Spec.Template.ObjectMeta.Labels[k] = v - } + maps.Copy(dep.Spec.Template.ObjectMeta.Labels, p.Labels) return dep } @@ -313,9 +323,7 @@ func newDaemonSet(p daemonSetParameters) *appsv1.DaemonSet { }, } - for k, v := range p.Labels { - ds.Spec.Template.ObjectMeta.Labels[k] = v - } + maps.Copy(ds.Spec.Template.ObjectMeta.Labels, p.Labels) if p.NodeSelector != nil { ds.Spec.Template.Spec.NodeSelector = p.NodeSelector @@ -490,6 +498,81 @@ func newConnDisruptCNPForNSTraffic(ns string) *ciliumv2.CiliumNetworkPolicy { } } +func newConnDisruptCNPForEgressGateway(ns string) *ciliumv2.CiliumNetworkPolicy { + selector := policyapi.EndpointSelector{ + LabelSelector: &slimmetav1.LabelSelector{ + MatchLabels: map[string]string{"kind": KindTestConnDisruptEgressGateway}, + }, + } + + ports := []policyapi.PortRule{{ + Ports: []policyapi.PortProtocol{{ + Protocol: policyapi.ProtoTCP, + Port: "8000", + }}, + }} + + return &ciliumv2.CiliumNetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: ciliumv2.CNPKindDefinition, + APIVersion: ciliumv2.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{Name: testConnDisruptEgressGatewayCNPName, Namespace: ns}, + Spec: &policyapi.Rule{ + EndpointSelector: selector, + Egress: []policyapi.EgressRule{ + { + EgressCommonRule: policyapi.EgressCommonRule{ + ToEntities: policyapi.EntitySlice{ + policyapi.EntityWorld, + }, + }, + ToPorts: ports, + }, + { + ToPorts: []policyapi.PortRule{{ + Ports: []policyapi.PortProtocol{ + {Protocol: policyapi.ProtoUDP, Port: "53"}, + {Protocol: policyapi.ProtoUDP, Port: "5353"}, + }, + }}, + }, + }, + }, + } +} + +func newConnDisruptCEGP(ns, gwNode string) *ciliumv2.CiliumEgressGatewayPolicy { + return &ciliumv2.CiliumEgressGatewayPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: ciliumv2.CEGPKindDefinition, + APIVersion: ciliumv2.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{Name: testConnDisruptCEGPName}, + Spec: ciliumv2.CiliumEgressGatewayPolicySpec{ + Selectors: []ciliumv2.EgressRule{ + { + PodSelector: &slimmetav1.LabelSelector{ + MatchLabels: map[string]slimmetav1.MatchLabelsValue{ + k8sconst.PodNamespaceLabel: ns, + "kind": KindTestConnDisruptEgressGateway, + }, + }, + }, + }, + DestinationCIDRs: []ciliumv2.IPv4CIDR{"0.0.0.0/0"}, + ExcludedCIDRs: []ciliumv2.IPv4CIDR{}, + EgressGateway: &ciliumv2.EgressGateway{ + NodeSelector: &slimmetav1.LabelSelector{ + MatchLabels: map[string]slimmetav1.MatchLabelsValue{ + "kubernetes.io/hostname": gwNode, + }, + }, + }, + }, + } +} + func (ct *ConnectivityTest) ingresses() map[string]string { ingresses := map[string]string{"same-node": echoSameNodeDeploymentName} if !ct.Params().SingleNode || ct.Params().MultiCluster != "" { @@ -522,10 +605,8 @@ func (ct *ConnectivityTest) maybeNodeToNodeEncryptionAffinity() *corev1.NodeAffi } } -// deploy ensures the test Namespace, Services and Deployments are running on the cluster. -func (ct *ConnectivityTest) deploy(ctx context.Context) error { - var err error - +// deployNamespace sets up the test namespace. +func (ct *ConnectivityTest) deployNamespace(ctx context.Context) error { for _, client := range ct.Clients() { if ct.params.ForceDeploy { if err := ct.deleteDeployments(ctx, client); err != nil { @@ -543,7 +624,7 @@ func (ct *ConnectivityTest) deploy(ctx context.Context) error { ObjectMeta: metav1.ObjectMeta{ Name: ct.params.TestNamespace, Annotations: ct.params.NamespaceAnnotations, - Labels: appLabels, + Labels: labels.Merge(ct.params.NamespaceLabels, appLabels), }, } _, err = client.CreateNamespace(ctx, namespace, metav1.CreateOptions{}) @@ -553,29 +634,32 @@ func (ct *ConnectivityTest) deploy(ctx context.Context) error { } } - // Deploy perf actors (only in the first test namespace - // in case of tests concurrent run) - if ct.params.Perf && ct.params.TestNamespaceIndex == 0 { - return ct.deployPerf(ctx) + return nil +} + +// deploy ensures the test Namespace, Services and Deployments are running on the cluster. +func (ct *ConnectivityTest) deploy(ctx context.Context) error { + if err := ct.deployNamespace(ctx); err != nil { + return err } // Deploy test-conn-disrupt actors (only in the first // test namespace in case of tests concurrent run) if ct.params.ConnDisruptTestSetup && ct.params.TestNamespaceIndex == 0 { if err := ct.createTestConnDisruptServerDeployAndSvc(ctx, testConnDisruptServerDeploymentName, KindTestConnDisrupt, 3, - testConnDisruptServiceName, "test-conn-disrupt-server", newConnDisruptCNP); err != nil { + testConnDisruptServiceName, "test-conn-disrupt-server", false, newConnDisruptCNP); err != nil { return err } if err := ct.createTestConnDisruptClientDeployment(ctx, testConnDisruptClientDeploymentName, KindTestConnDisrupt, "test-conn-disrupt-client", fmt.Sprintf("test-conn-disrupt.%s.svc.cluster.local.:8000", ct.params.TestNamespace), - 5, false); err != nil { + 5, false, nil); err != nil { return err } if ct.ShouldRunConnDisruptNSTraffic() { if err := ct.createTestConnDisruptServerDeployAndSvc(ctx, testConnDisruptServerNSTrafficDeploymentName, KindTestConnDisruptNSTraffic, 1, - testConnDisruptNSTrafficServiceName, testConnDisruptServerNSTrafficAppLabel, newConnDisruptCNPForNSTraffic); err != nil { + testConnDisruptNSTrafficServiceName, testConnDisruptServerNSTrafficAppLabel, false, newConnDisruptCNPForNSTraffic); err != nil { return err } @@ -585,9 +669,54 @@ func (ct *ConnectivityTest) deploy(ctx context.Context) error { } else { ct.Info("Skipping conn-disrupt-test for NS traffic") } + + if ct.ShouldRunConnDisruptEgressGateway() { + gatewayNode, nonGatewayNode, err := ct.getGatewayAndNonGatewayNodes() + if err != nil { + return err + } + cegp := newConnDisruptCEGP(ct.params.TestNamespace, gatewayNode) + ct.Logf("✨ [%s] Deploying %s CiliumEgressGatewayPolicy...", ct.K8sClient().ClusterName(), cegp.Name) + _, err = ct.K8sClient().ApplyGeneric(ctx, cegp) + if err != nil { + return fmt.Errorf("unable to create CiliumEgressGatewayPolicy %s: %w", cegp.Name, err) + } + + if err := ct.createTestConnDisruptServerDeployAndSvc(ctx, testConnDisruptServerEgressGatewayDeploymentName, KindTestConnDisruptEgressGateway, 1, + testConnDisruptEgressGatewayServiceName, testConnDisruptServerEgressGatewayAppLabel, true, newConnDisruptCNPForEgressGateway); err != nil { + return err + } + + if err := ct.createTestConnDisruptClientDeployment(ctx, testConnDisruptClientEgressGatewayOnGatewayNodeDeploymentName, KindTestConnDisruptEgressGateway, + testConnDisruptClientEgressGatewayOnGatewayNodeAppLabel, fmt.Sprintf("test-conn-disrupt-egw.%s.svc.cluster.local.:8000", ct.params.TestNamespace), + 1, false, map[string]string{"kubernetes.io/hostname": gatewayNode}); err != nil { + return err + } + if err := ct.createTestConnDisruptClientDeployment(ctx, testConnDisruptClientEgressGatewayOnNonGatewayNodeDeploymentName, KindTestConnDisruptEgressGateway, + testConnDisruptClientEgressGatewayOnNonGatewayNodeAppLabel, fmt.Sprintf("test-conn-disrupt-egw.%s.svc.cluster.local.:8000", ct.params.TestNamespace), + 1, false, map[string]string{"kubernetes.io/hostname": nonGatewayNode}); err != nil { + return err + } + for _, clientDeploy := range []string{testConnDisruptClientEgressGatewayOnGatewayNodeDeploymentName, testConnDisruptClientEgressGatewayOnNonGatewayNodeDeploymentName} { + err := WaitForDeployment(ctx, ct, ct.clients.dst, ct.params.TestNamespace, clientDeploy) + if err != nil { + ct.Failf("%s deployment is not ready: %s", clientDeploy, err) + } + } + if err := WaitForEgressGatewayBpfPolicyEntries(ctx, ct.CiliumPods(), + func(ciliumPod Pod) ([]BPFEgressGatewayPolicyEntry, error) { + return ct.GetConnDisruptEgressPolicyEntries(ctx, ciliumPod) + }, func(ciliumPod Pod) ([]BPFEgressGatewayPolicyEntry, error) { + return nil, nil + }); err != nil { + ct.Fail(err) + } + } else { + ct.Info("Skipping conn-disrupt-test for Egress Gateway") + } } - _, err = ct.clients.src.GetService(ctx, ct.params.TestNamespace, echoSameNodeDeploymentName, metav1.GetOptions{}) + _, err := ct.clients.src.GetService(ctx, ct.params.TestNamespace, echoSameNodeDeploymentName, metav1.GetOptions{}) if err != nil { ct.Logf("✨ [%s] Deploying %s service...", ct.clients.src.ClusterName(), echoSameNodeDeploymentName) svc := newService(echoSameNodeDeploymentName, map[string]string{"name": echoSameNodeDeploymentName}, serviceLabels, "http", 8080, ct.Params().ServiceType) @@ -1136,7 +1265,7 @@ func (ct *ConnectivityTest) deploy(ctx context.Context) error { } func (ct *ConnectivityTest) createTestConnDisruptServerDeployAndSvc(ctx context.Context, deployName, kind string, replicas int, svcName, appLabel string, - cnpFunc func(ns string) *ciliumv2.CiliumNetworkPolicy) error { + isExternal bool, cnpFunc func(ns string) *ciliumv2.CiliumNetworkPolicy) error { _, err := ct.clients.src.GetDeployment(ctx, ct.params.TestNamespace, deployName, metav1.GetOptions{}) if err != nil { ct.Logf("✨ [%s] Deploying %s deployment...", ct.clients.src.ClusterName(), deployName) @@ -1150,7 +1279,7 @@ func (ct *ConnectivityTest) createTestConnDisruptServerDeployAndSvc(ctx context. InitialDelaySeconds: int32(1), FailureThreshold: int32(20), } - testConnDisruptServerDeployment := newDeployment(deploymentParameters{ + param := deploymentParameters{ Name: deployName, Kind: kind, Image: ct.params.TestConnDisruptImage, @@ -1162,7 +1291,15 @@ func (ct *ConnectivityTest) createTestConnDisruptServerDeployAndSvc(ctx context. Resources: corev1.ResourceRequirements{ Requests: corev1.ResourceList{corev1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI)}, }, - }) + } + if isExternal { + param.NodeSelector = map[string]string{defaults.CiliumNoScheduleLabel: "true"} + param.HostNetwork = true + param.Tolerations = []corev1.Toleration{ + {Operator: corev1.TolerationOpExists}, + } + } + testConnDisruptServerDeployment := newDeployment(param) _, err = ct.clients.src.CreateServiceAccount(ctx, ct.params.TestNamespace, k8s.NewServiceAccount(deployName), metav1.CreateOptions{}) if err != nil { return fmt.Errorf("unable to create service account %s: %w", deployName, err) @@ -1211,7 +1348,7 @@ func (ct *ConnectivityTest) createTestConnDisruptServerDeployAndSvc(ctx context. return err } -func (ct *ConnectivityTest) createTestConnDisruptClientDeployment(ctx context.Context, deployName, kind, appLabel, address string, replicas int, isExternal bool) error { +func (ct *ConnectivityTest) createTestConnDisruptClientDeployment(ctx context.Context, deployName, kind, appLabel, address string, replicas int, isExternal bool, nodeSelector map[string]string) error { _, err := ct.clients.dst.GetDeployment(ctx, ct.params.TestNamespace, deployName, metav1.GetOptions{}) if err != nil { ct.Logf("✨ [%s] Deploying %s deployment...", ct.clients.dst.ClusterName(), deployName) @@ -1249,6 +1386,9 @@ func (ct *ConnectivityTest) createTestConnDisruptClientDeployment(ctx context.Co {Operator: corev1.TolerationOpExists}, } } + if nodeSelector != nil { + param.NodeSelector = nodeSelector + } testConnDisruptClientDeployment := newDeployment(param) _, err = ct.clients.dst.CreateServiceAccount(ctx, ct.params.TestNamespace, k8s.NewServiceAccount(deployName), metav1.CreateOptions{}) @@ -1303,7 +1443,7 @@ func (ct *ConnectivityTest) createTestConnDisruptClientDeploymentForNSTraffic(ct KindTestConnDisruptNSTraffic, fmt.Sprintf("test-conn-disrupt-client-%s-%s-%s", n.nodeType, family, strings.ToLower(string(addr.Type))), netip.AddrPortFrom(netip.MustParseAddr(addr.Address), np).String(), - 1, true); err != nil { + 1, true, nil); err != nil { errs = errors.Join(errs, err) } ct.testConnDisruptClientNSTrafficDeploymentNames = append(ct.testConnDisruptClientNSTrafficDeploymentNames, deployName) @@ -1350,6 +1490,100 @@ func (ct *ConnectivityTest) getBackendNodeAndNonBackendNode(ctx context.Context) return nodes, err } +func (ct *ConnectivityTest) getGatewayAndNonGatewayNodes() (string, string, error) { + var workerNodes []string + for _, node := range ct.nodes { + if _, found := ct.controlPlaneNodes[node.Name]; !found { + workerNodes = append(workerNodes, node.Name) + } + } + if len(workerNodes) < 2 { + return "", "", fmt.Errorf("unable to pick gateway and non gateway nodes") + } + slices.Sort(workerNodes) + + return workerNodes[0], workerNodes[1], nil + +} + +func (ct *ConnectivityTest) GetGatewayNodeInternalIP(egressGatewayNode string) net.IP { + gatewayNode, ok := ct.Nodes()[egressGatewayNode] + if !ok { + return nil + } + + for _, addr := range gatewayNode.Status.Addresses { + if addr.Type != corev1.NodeInternalIP { + continue + } + + ip := net.ParseIP(addr.Address) + if ip == nil || ip.To4() == nil { + continue + } + + return ip + } + + return nil +} + +func (ct *ConnectivityTest) getConnDisruptClientEgressGatewayPodIPs(ctx context.Context) ([]string, error) { + var appLabels []string + appLabels = append(appLabels, fmt.Sprintf("app=%s", testConnDisruptClientEgressGatewayOnGatewayNodeAppLabel)) + appLabels = append(appLabels, fmt.Sprintf("app=%s", testConnDisruptClientEgressGatewayOnNonGatewayNodeAppLabel)) + + var podIPs []string + for _, appLabel := range appLabels { + connDisruptPods, err := ct.K8sClient().ListPods(ctx, ct.Params().TestNamespace, metav1.ListOptions{LabelSelector: appLabel}) + if err != nil { + return nil, fmt.Errorf("unable to list pods with lable %s: %w", appLabel, err) + } + + for _, connDisruptPod := range connDisruptPods.Items { + podIPs = append(podIPs, connDisruptPod.Status.PodIP) + } + } + + return podIPs, nil +} + +func (ct *ConnectivityTest) GetConnDisruptEgressPolicyEntries(ctx context.Context, ciliumPod Pod) ([]BPFEgressGatewayPolicyEntry, error) { + var targetEntries []BPFEgressGatewayPolicyEntry + + podIPs, err := ct.getConnDisruptClientEgressGatewayPodIPs(ctx) + if err != nil { + return nil, err + } + + gatewayNode, _, err := ct.getGatewayAndNonGatewayNodes() + if err != nil { + return nil, err + } + + gatewayIP := ct.GetGatewayNodeInternalIP(gatewayNode) + if gatewayIP == nil { + return nil, nil + } + + egressIP := "0.0.0.0" + if ciliumPod.Pod.Spec.NodeName == gatewayNode { + egressIP = gatewayIP.String() + } + + for _, podIP := range podIPs { + targetEntries = append(targetEntries, + BPFEgressGatewayPolicyEntry{ + SourceIP: podIP, + DestCIDR: "0.0.0.0/0", + EgressIP: egressIP, + GatewayIP: gatewayIP.String(), + }) + } + + return targetEntries, nil +} + func (ct *ConnectivityTest) hasNetworkPolicies(ctx context.Context) (bool, error) { for _, client := range ct.Clients() { cnps, err := client.ListCiliumNetworkPolicies(ctx, ct.params.TestNamespace, metav1.ListOptions{Limit: 1}) @@ -1440,7 +1674,9 @@ func (ct *ConnectivityTest) createServerPerfDeployment(ctx context.Context, name } func (ct *ConnectivityTest) deployPerf(ctx context.Context) error { - var err error + if err := ct.deployNamespace(ctx); err != nil { + return err + } nodeSelectorServer := labels.SelectorFromSet(ct.params.PerfParameters.NodeSelectorServer).String() nodeSelectorClient := labels.SelectorFromSet(ct.params.PerfParameters.NodeSelectorClient).String() @@ -1546,45 +1782,44 @@ func (ct *ConnectivityTest) deployPerf(ctx context.Context) error { return nil } -// deploymentList returns 2 lists of Deployments to be used for running tests with. -func (ct *ConnectivityTest) deploymentList() (srcList []string, dstList []string) { - if ct.params.Perf && ct.params.TestNamespaceIndex == 0 { - if ct.params.PerfParameters.NetQos { - srcList = append(srcList, perClientLowPriorityDeploymentName) - srcList = append(srcList, perClientHighPriorityDeploymentName) - srcList = append(srcList, perfServerDeploymentName) - return - } +// deploymentListPerf returns the list of deployments required by the performance tests. +func (ct *ConnectivityTest) deploymentListPerf() (srcList []string, dstList []string) { + if ct.params.PerfParameters.NetQos { + srcList = append(srcList, perClientLowPriorityDeploymentName) + srcList = append(srcList, perClientHighPriorityDeploymentName) + srcList = append(srcList, perfServerDeploymentName) + return + } - if ct.params.PerfParameters.PodNet || ct.params.PerfParameters.PodToHost { - if ct.params.PerfParameters.SameNode { - srcList = append(srcList, perfClientDeploymentName) - } - if ct.params.PerfParameters.OtherNode { - srcList = append(srcList, perfClientAcrossDeploymentName) - } + if ct.params.PerfParameters.PodNet || ct.params.PerfParameters.PodToHost { + if ct.params.PerfParameters.SameNode { + srcList = append(srcList, perfClientDeploymentName) } - if ct.params.PerfParameters.PodNet || ct.params.PerfParameters.HostToPod { - srcList = append(srcList, perfServerDeploymentName) + if ct.params.PerfParameters.OtherNode { + srcList = append(srcList, perfClientAcrossDeploymentName) } + } + if ct.params.PerfParameters.PodNet || ct.params.PerfParameters.HostToPod { + srcList = append(srcList, perfServerDeploymentName) + } - if ct.params.PerfParameters.HostNet || ct.params.PerfParameters.HostToPod { - if ct.params.PerfParameters.SameNode { - srcList = append(srcList, perfClientHostNetDeploymentName) - } - if ct.params.PerfParameters.OtherNode { - srcList = append(srcList, perfClientHostNetAcrossDeploymentName) - } + if ct.params.PerfParameters.HostNet || ct.params.PerfParameters.HostToPod { + if ct.params.PerfParameters.SameNode { + srcList = append(srcList, perfClientHostNetDeploymentName) } - if ct.params.PerfParameters.HostNet || ct.params.PerfParameters.PodToHost { - srcList = append(srcList, perfServerHostNetDeploymentName) + if ct.params.PerfParameters.OtherNode { + srcList = append(srcList, perfClientHostNetAcrossDeploymentName) } - - // Return early, we can't run regular connectivity tests - // along perf test - return } + if ct.params.PerfParameters.HostNet || ct.params.PerfParameters.PodToHost { + srcList = append(srcList, perfServerHostNetDeploymentName) + } + + return +} +// deploymentList returns 2 lists of Deployments to be used for running tests with. +func (ct *ConnectivityTest) deploymentList() (srcList []string, dstList []string) { srcList = []string{clientDeploymentName, client2DeploymentName, echoSameNodeDeploymentName} if ct.params.MultiCluster == "" && !ct.params.SingleNode { srcList = append(srcList, client3DeploymentName) @@ -1603,6 +1838,11 @@ func (ct *ConnectivityTest) deploymentList() (srcList []string, dstList []string srcList = append(srcList, testConnDisruptServerNSTrafficDeploymentName) dstList = append(dstList, ct.testConnDisruptClientNSTrafficDeploymentNames...) } + if ct.ShouldRunConnDisruptEgressGateway() { + srcList = append(srcList, testConnDisruptServerEgressGatewayDeploymentName) + dstList = append(dstList, testConnDisruptClientEgressGatewayOnGatewayNodeDeploymentName, + testConnDisruptClientEgressGatewayOnNonGatewayNodeDeploymentName) + } } if ct.params.MultiCluster != "" || !ct.params.SingleNode { @@ -1673,23 +1913,29 @@ func (ct *ConnectivityTest) DeleteConnDisruptTestDeployment(ctx context.Context, _ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, deploy.Name, metav1.DeleteOptions{}) } _ = client.DeleteDeployment(ctx, ct.params.TestNamespace, testConnDisruptServerNSTrafficDeploymentName, metav1.DeleteOptions{}) + _ = client.DeleteDeployment(ctx, ct.params.TestNamespace, testConnDisruptClientEgressGatewayOnGatewayNodeDeploymentName, metav1.DeleteOptions{}) + _ = client.DeleteDeployment(ctx, ct.params.TestNamespace, testConnDisruptClientEgressGatewayOnNonGatewayNodeDeploymentName, metav1.DeleteOptions{}) + _ = client.DeleteDeployment(ctx, ct.params.TestNamespace, testConnDisruptServerEgressGatewayDeploymentName, metav1.DeleteOptions{}) _ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, testConnDisruptClientDeploymentName, metav1.DeleteOptions{}) _ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, testConnDisruptServerDeploymentName, metav1.DeleteOptions{}) _ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, testConnDisruptServerNSTrafficDeploymentName, metav1.DeleteOptions{}) + _ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, testConnDisruptServerEgressGatewayDeploymentName, metav1.DeleteOptions{}) + _ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, testConnDisruptClientEgressGatewayOnGatewayNodeDeploymentName, metav1.DeleteOptions{}) + _ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, testConnDisruptClientEgressGatewayOnNonGatewayNodeDeploymentName, metav1.DeleteOptions{}) _ = client.DeleteService(ctx, ct.params.TestNamespace, testConnDisruptServiceName, metav1.DeleteOptions{}) _ = client.DeleteService(ctx, ct.params.TestNamespace, testConnDisruptNSTrafficServiceName, metav1.DeleteOptions{}) + _ = client.DeleteService(ctx, ct.params.TestNamespace, testConnDisruptEgressGatewayServiceName, metav1.DeleteOptions{}) _ = client.DeleteCiliumNetworkPolicy(ctx, ct.params.TestNamespace, testConnDisruptCNPName, metav1.DeleteOptions{}) _ = client.DeleteCiliumNetworkPolicy(ctx, ct.params.TestNamespace, testConnDisruptNSTrafficCNPName, metav1.DeleteOptions{}) + _ = client.DeleteCiliumNetworkPolicy(ctx, ct.params.TestNamespace, testConnDisruptEgressGatewayCNPName, metav1.DeleteOptions{}) + _ = client.DeleteCiliumEgressGatewayPolicy(ctx, testConnDisruptCEGPName, metav1.DeleteOptions{}) return nil } -// validateDeployment checks if the Deployments we created have the expected Pods in them. -func (ct *ConnectivityTest) validateDeployment(ctx context.Context) error { - +func (ct *ConnectivityTest) validateDeploymentCommon(ctx context.Context, srcDeployments, dstDeployments []string) error { ct.Debug("Validating Deployments...") - srcDeployments, dstDeployments := ct.deploymentList() for _, name := range srcDeployments { if err := WaitForDeployment(ctx, ct, ct.clients.src, ct.Params().TestNamespace, name); err != nil { return err @@ -1702,34 +1948,51 @@ func (ct *ConnectivityTest) validateDeployment(ctx context.Context) error { } } - if ct.params.Perf { - perfPods, err := ct.client.ListPods(ctx, ct.params.TestNamespace, metav1.ListOptions{LabelSelector: "kind=" + kindPerfName}) - if err != nil { - return fmt.Errorf("unable to list perf pods: %w", err) - } - for _, perfPod := range perfPods.Items { - _, hasLabel := perfPod.GetLabels()["server"] - if hasLabel { - ct.perfServerPod = append(ct.perfServerPod, Pod{ - K8sClient: ct.client, - Pod: perfPod.DeepCopy(), - port: 5201, - }) - } else { - ct.perfClientPods = append(ct.perfClientPods, Pod{ - K8sClient: ct.client, - Pod: perfPod.DeepCopy(), - }) - } + return nil +} + +func (ct *ConnectivityTest) validateDeploymentPerf(ctx context.Context) error { + srcDeployments, dstDeployments := ct.deploymentListPerf() + if err := ct.validateDeploymentCommon(ctx, srcDeployments, dstDeployments); err != nil { + return err + } + + perfPods, err := ct.client.ListPods(ctx, ct.params.TestNamespace, metav1.ListOptions{LabelSelector: "kind=" + kindPerfName}) + if err != nil { + return fmt.Errorf("unable to list perf pods: %w", err) + } + + for _, perfPod := range perfPods.Items { + _, hasLabel := perfPod.GetLabels()["server"] + if hasLabel { + ct.perfServerPod = append(ct.perfServerPod, Pod{ + K8sClient: ct.client, + Pod: perfPod.DeepCopy(), + port: 5201, + }) + } else { + ct.perfClientPods = append(ct.perfClientPods, Pod{ + K8sClient: ct.client, + Pod: perfPod.DeepCopy(), + }) } - // Sort pods so results are always displayed in the same order in console - sort.SliceStable(ct.perfServerPod, func(i, j int) bool { - return ct.perfServerPod[i].Pod.Name < ct.perfServerPod[j].Pod.Name - }) - sort.SliceStable(ct.perfClientPods, func(i, j int) bool { - return ct.perfClientPods[i].Pod.Name < ct.perfClientPods[j].Pod.Name - }) - return nil + } + + // Sort pods so results are always displayed in the same order in console + sort.SliceStable(ct.perfServerPod, func(i, j int) bool { + return ct.perfServerPod[i].Pod.Name < ct.perfServerPod[j].Pod.Name + }) + sort.SliceStable(ct.perfClientPods, func(i, j int) bool { + return ct.perfClientPods[i].Pod.Name < ct.perfClientPods[j].Pod.Name + }) + + return nil +} + +func (ct *ConnectivityTest) validateDeployment(ctx context.Context) error { + srcDeployments, dstDeployments := ct.deploymentList() + if err := ct.validateDeploymentCommon(ctx, srcDeployments, dstDeployments); err != nil { + return err } if ct.Features[features.LocalRedirectPolicy].Enabled { diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/features.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/features.go index 04c61a201d..d15f784f09 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/features.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/features.go @@ -330,7 +330,7 @@ func (ct *ConnectivityTest) detectFeatures(ctx context.Context) error { if err != nil { return err } - features.ExtractFromNodes(ct.params.Perf, ct.nodesWithoutCilium) + features.ExtractFromNodes(ct.nodesWithoutCilium) err = ct.extractFeaturesFromCiliumStatus(ctx, ciliumPod, features) if err != nil { return err diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/junit.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/junit.go index 38ded9002b..a03b93a0d0 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/junit.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/junit.go @@ -5,12 +5,15 @@ package check import ( "errors" + "fmt" "os" "strings" "github.com/cilium/cilium/cilium-cli/connectivity/internal/junit" ) +const MetadataDelimiter = ";metadata;" + // NewJUnitCollector factory function that returns JUnitCollector. func NewJUnitCollector(junitProperties map[string]string, junitFile string) *JUnitCollector { properties := []junit.Property{ @@ -68,7 +71,8 @@ func (j *JUnitCollector) Collect(ct *ConnectivityTest) { j.testSuite.Failures++ msgs := []string{} for _, a := range t.failedActions() { - msgs = append(msgs, a.String()) + owners := ct.GetOwners(a.Scenario()) + msgs = append(msgs, fmt.Sprintf("%s%sOwners: %s", a, MetadataDelimiter, strings.Join(owners, ", "))) } test.Failure.Value = strings.Join(msgs, "\n") } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logger.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logger.go index 6094a527e0..bfc2b5bbc5 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logger.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logger.go @@ -7,78 +7,109 @@ import ( "bytes" "fmt" "io" - "sync/atomic" - "time" - - "github.com/cilium/cilium/pkg/lock" ) // NewConcurrentLogger factory function that returns ConcurrentLogger. -func NewConcurrentLogger(writer io.Writer, concurrency int) *ConcurrentLogger { +func NewConcurrentLogger(writer io.Writer) *ConcurrentLogger { return &ConcurrentLogger{ - messageCh: make(chan message), - writer: writer, - // The concurrency parameter is used for nsTestsCh buffer size calculation. - // The buffer will be able to accept 10 times more unique connectivity tests - // than concurrency value. Write to the channel implemented in a separate - // goroutine to avoid deadlock in case if buffer is full. - nsTestsCh: make(chan string, concurrency*10), - nsTestMsgs: make(map[string][]message), - nsTestMsgsLock: lock.Mutex{}, - collectorStarted: atomic.Bool{}, - printerDoneCh: make(chan bool), + writer: writer, + messages: make(chan message), + done: make(chan struct{}), } } type ConcurrentLogger struct { - messageCh chan message - writer io.Writer - nsTestsCh chan string - nsTestMsgs map[string][]message - nsTestMsgsLock lock.Mutex - collectorStarted atomic.Bool - printerDoneCh chan bool - nsTestFinishCount int + writer io.Writer + messages chan message + done chan struct{} } -// Start starts ConcurrentLogger internals in separate goroutines: -// - collector: collects incoming test messages. -// - printer: sends messages to the writer in corresponding order. +// Start starts ConcurrentLogger func (c *ConcurrentLogger) Start() { - c.collectorStarted.Store(true) - go c.collector() - go c.printer() + go func() { + // current is the test that is currently being streamed to the writer without + // buffering + var current *Test + + // buffered is a map of tests (other than current one) that have not finished yet + buffered := make(map[*Test]*bytes.Buffer) + + // finished is an ordered list of tests to be logged once the current test finishes + var finished []*bytes.Buffer + + for m := range c.messages { + // make this the current test if none + if current == nil { + current = m.test + } + + // stream the current test without buffering + if m.test == current { + mustWrite(c.writer, m.data) + if m.finish { + current = nil + } + } else { + // buffer other tests + buf, ok := buffered[m.test] + if !ok { + buf = &bytes.Buffer{} + buffered[m.test] = buf + } + mustWrite(buf, m.data) + if m.finish { + delete(buffered, m.test) + finished = append(finished, buf) + } + } + + if current == nil { + // log any finished tests after done with the current test + for _, buf := range finished { + mustWrite(c.writer, buf.Bytes()) + } + finished = finished[len(finished):] + + // pick one of the running tests as the current one, if any + for test, buf := range buffered { + delete(buffered, test) + mustWrite(c.writer, buf.Bytes()) + current = test + break + } + } + } + // No more messages, log all remaining messages + for _, buf := range finished { + mustWrite(c.writer, buf.Bytes()) + } + for _, buf := range buffered { + mustWrite(c.writer, buf.Bytes()) + } + close(c.done) + }() } // Stop closes incoming message channel and waits while all messages are printed. func (c *ConcurrentLogger) Stop() { - close(c.messageCh) - <-c.printerDoneCh - close(c.printerDoneCh) + close(c.messages) + <-c.done } type message struct { - namespace string - testName string - data string - finish bool -} - -func (m message) nsTest() string { - return fmt.Sprintf("%s:%s", m.namespace, m.testName) + test *Test + data []byte + finish bool } // Print schedules message for the test to be printed. -func (c *ConcurrentLogger) Print(test *Test, msg string) { - buf := &bytes.Buffer{} +func (c *ConcurrentLogger) Print(test *Test, msg []byte) { if test.ctx.timestamp() { - mustFprint(buf, timestamp()) + msg = append(timestampBytes(), msg...) } - mustFprint(buf, msg) - c.messageCh <- message{ - namespace: test.ctx.params.TestNamespace, - testName: test.name, - data: buf.String(), + c.messages <- message{ + test: test, + data: msg, } } @@ -86,13 +117,12 @@ func (c *ConcurrentLogger) Print(test *Test, msg string) { func (c *ConcurrentLogger) Printf(test *Test, format string, args ...interface{}) { buf := &bytes.Buffer{} if test.ctx.timestamp() { - mustFprint(buf, timestamp()) + mustWrite(buf, timestampBytes()) } mustFprintf(buf, format, args...) - c.messageCh <- message{ - namespace: test.ctx.params.TestNamespace, - testName: test.name, - data: buf.String(), + c.messages <- message{ + test: test, + data: buf.Bytes(), } } @@ -105,77 +135,15 @@ func (c *ConcurrentLogger) FinishTest(test *Test) { panic(fmt.Errorf("failed to read from test log buffer: %w", err)) } } - c.messageCh <- message{ - namespace: test.Context().Params().TestNamespace, - testName: test.Name(), - data: buf.String(), - finish: true, - } -} - -func (c *ConcurrentLogger) collector() { - defer c.collectorStarted.Store(false) - for m := range c.messageCh { - nsTest := m.nsTest() - c.nsTestMsgsLock.Lock() - nsTestMsgs, ok := c.nsTestMsgs[nsTest] - if !ok { - nsTestMsgs = make([]message, 0) - // use a separate goroutine to avoid deadlock if the channel - // buffer is full, printer goroutine will pull it eventually - go func() { c.nsTestsCh <- nsTest }() - } - c.nsTestMsgs[nsTest] = append(nsTestMsgs, m) - c.nsTestMsgsLock.Unlock() - } -} - -func (c *ConcurrentLogger) printer() { - // read messages while the collector is working - for c.collectorStarted.Load() { - // double-check if there are new messages to avoid - // deadlock reading from the `nsTestsCh` channel - if c.nsTestFinishCount < c.collectedTestCount() { - c.printTestMessages(<-c.nsTestsCh) - } - } - // collector stopped but there still might be messages to print - for c.nsTestFinishCount < c.collectedTestCount() { - c.printTestMessages(<-c.nsTestsCh) - } - c.printerDoneCh <- true - close(c.nsTestsCh) -} - -func (c *ConcurrentLogger) collectedTestCount() int { - c.nsTestMsgsLock.Lock() - testCount := len(c.nsTestMsgs) - c.nsTestMsgsLock.Unlock() - return testCount -} - -func (c *ConcurrentLogger) printTestMessages(nsTest string) { - for printedMessageIndex := 0; ; { - c.nsTestMsgsLock.Lock() - messages := c.nsTestMsgs[nsTest] - c.nsTestMsgsLock.Unlock() - if len(messages) == printedMessageIndex { - // wait for new test messages - time.Sleep(time.Millisecond * 50) - continue - } - for ; printedMessageIndex < len(messages); printedMessageIndex++ { - mustFprint(c.writer, messages[printedMessageIndex].data) - if messages[printedMessageIndex].finish { - c.nsTestFinishCount++ - return - } - } + c.messages <- message{ + test: test, + data: buf.Bytes(), + finish: true, } } -func mustFprint(writer io.Writer, msg string) { - if _, err := fmt.Fprint(writer, msg); err != nil { +func mustWrite(writer io.Writer, msg []byte) { + if _, err := writer.Write(msg); err != nil { panic(fmt.Errorf("failed to print log message: %w", err)) } } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logging.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logging.go index 689485f069..5b13de7b09 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logging.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/logging.go @@ -115,9 +115,9 @@ func (s defaultScenario) Name() string { var ghWorkflowRegexp = regexp.MustCompile("^(?:.+?)/(?:.+?)/(.+?)@.*$") -func (ct *ConnectivityTest) LogOwners(scenarios ...ownedScenario) { +func (ct *ConnectivityTest) GetOwners(scenarios ...ownedScenario) []string { if !ct.params.LogCodeOwners { - return + return nil } rules := make(map[ownedScenario]*codeowners.Rule) @@ -126,7 +126,7 @@ func (ct *ConnectivityTest) LogOwners(scenarios ...ownedScenario) { if err != nil || rule == nil || rule.Owners == nil { ct.Fatalf("Failed to find CODEOWNERS for test scenario. Developer BUG?"+ "\n\t\tname=%s path=%s err=%s", scenario.Name(), scenario.FilePath(), err) - return + return nil } rules[scenario] = rule } @@ -154,23 +154,36 @@ func (ct *ConnectivityTest) LogOwners(scenarios ...ownedScenario) { excludeOwners[owner] = struct{}{} } - ct.Log(" ⛑️ The following owners are responsible for reliability of the testsuite: ") + var owners []string for scenario, rule := range rules { for _, o := range rule.Owners { owner := o.String() if _, ok := excludeOwners[owner]; ok { continue } - ct.Log(" - " + owner + " (" + scenario.Name() + ")") + owners = append(owners, fmt.Sprintf("%s (%s)", owner, scenario.Name())) } for _, o := range workflowOwners { owner := o.String() if _, ok := excludeOwners[owner]; ok { continue } - ct.Log(" - " + owner + " (" + ghWorkflow + ")") + owners = append(owners, fmt.Sprintf("%s (%s)", owner, ghWorkflow)) } } + return owners +} + +func (ct *ConnectivityTest) LogOwners(scenarios ...ownedScenario) { + owners := ct.GetOwners(scenarios...) + if len(owners) == 0 { + return + } + + ct.Log(" ⛑️ The following owners are responsible for reliability of the testsuite: ") + for _, o := range owners { + ct.Log(" - " + o) + } } // Logf logs a formatted message. @@ -323,7 +336,7 @@ func (t *Test) flush() { if _, err := io.Copy(buf, t.logBuf); err != nil { panic(err) } - t.ctx.logger.Print(t, buf.String()) + t.ctx.logger.Print(t, buf.Bytes()) // Assign a nil buffer so future writes go to user-specified writer. t.logBuf = nil @@ -486,6 +499,14 @@ func timestamp() string { return fmt.Sprintf("[%s] ", time.Now().Format(time.RFC3339)) } +func timestampBytes() []byte { + b := make([]byte, 0, 32) // roughly enough space + b = append(b, '[') + b = time.Now().AppendFormat(b, time.RFC3339) + b = append(b, ']', ' ') + return b +} + type debugWriter struct { ct *ConnectivityTest } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/peer.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/peer.go index 4f3a883488..9baf13a4e2 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/peer.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/peer.go @@ -5,6 +5,7 @@ package check import ( "fmt" + "maps" "net" "net/url" "strconv" @@ -129,9 +130,7 @@ func (p Pod) Port() uint32 { func (p Pod) Labels() map[string]string { newMap := make(map[string]string, len(p.Pod.Labels)) - for k, v := range p.Pod.Labels { - newMap[k] = v - } + maps.Copy(newMap, p.Pod.Labels) return newMap } @@ -239,9 +238,7 @@ func (s Service) HasLabel(name, value string) bool { // Labels returns the copy of service labels func (s Service) Labels() map[string]string { newMap := make(map[string]string, len(s.Service.Labels)) - for k, v := range s.Service.Labels { - newMap[k] = v - } + maps.Copy(newMap, s.Service.Labels) return newMap } @@ -436,9 +433,7 @@ func (he httpEndpoint) HasLabel(name, value string) bool { func (he httpEndpoint) Labels() map[string]string { newMap := make(map[string]string, len(*he.labels)) - for k, v := range *he.labels { - newMap[k] = v - } + maps.Copy(newMap, *he.labels) return newMap } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/policy.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/policy.go index caf6518461..52fc24c108 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/policy.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/policy.go @@ -23,6 +23,7 @@ import ( "github.com/cilium/cilium/cilium-cli/defaults" "github.com/cilium/cilium/cilium-cli/k8s" "github.com/cilium/cilium/cilium-cli/utils/features" + logfilter "github.com/cilium/cilium/cilium-cli/utils/log" k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io" ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned/scheme" @@ -378,7 +379,13 @@ func (t *Test) ContainerLogs(ctx context.Context) { if err != nil { t.Fatalf("Error reading Cilium logs: %s", err) } - t.Infof("Cilium agent %s/%s logs since %s:\n%s", pod.Pod.Namespace, pod.Pod.Name, t.startTime.String(), log) + t.Infof( + "Cilium agent %s/%s logs since %s:\n%s", + pod.Pod.Namespace, + pod.Pod.Name, + t.startTime.String(), + logfilter.Reduce(log, t.verbose), + ) } } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go index 23aca30ffe..95a5918d06 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/test.go @@ -11,6 +11,7 @@ import ( "fmt" "io" "net" + "slices" "time" "github.com/blang/semver/v4" @@ -68,6 +69,7 @@ func NewTest(name string, verbose bool, debug bool) *Test { clrps: make(map[string]*ciliumv2.CiliumLocalRedirectPolicy), logBuf: &bytes.Buffer{}, // maintain internal buffer by default conditionFn: nil, + verbose: verbose, } // Setting the internal buffer to nil causes the logger to // write directly to stdout in verbose or debug mode. @@ -140,8 +142,9 @@ type Test struct { // Buffer to store output until it's flushed by a failure. // Unused when run in verbose or debug mode. - logMu lock.RWMutex - logBuf io.ReadWriter + logMu lock.RWMutex + logBuf io.ReadWriter + verbose bool // conditionFn is a function that returns true if the test needs to run, // and false otherwise. By default, it's set to a function that returns @@ -299,7 +302,10 @@ func (t *Test) willRun() (bool, string) { func (t *Test) finalize() { t.Debug("Finalizing Test", t.Name()) - for _, f := range t.finalizers { + // Iterate finalizers in backward order. + // As an example, first we create secrets that are referenced in policies. + // When performing cleanup, we want to first delete policies and then secrets. + for _, f := range slices.Backward(t.finalizers) { // Use a detached context to make sure this call is not affected by // context cancellation. Usually, finalization (e.g., netpol removal) // needs to happen even when the user interrupted the program. @@ -855,10 +861,5 @@ func (t *Test) CiliumLocalRedirectPolicies() map[string]*ciliumv2.CiliumLocalRed } func (t *Test) HasNetworkPolicies() bool { - for _, obj := range t.resources { - if isPolicy(obj) { - return true - } - } - return false + return slices.ContainsFunc(t.resources, isPolicy) } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/wait.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/wait.go index e0c80839cd..1a6c02f9ac 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/wait.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/check/wait.go @@ -343,6 +343,86 @@ func WaitForIPCache(ctx context.Context, log Logger, agent Pod, pods []Pod) erro } } +// BPFEgressGatewayPolicyEntry represents an entry in the BPF egress gateway policy map +type BPFEgressGatewayPolicyEntry struct { + SourceIP string `json:"sourceIP"` + DestCIDR string `json:"destCIDR"` + EgressIP string `json:"egressIP"` + GatewayIP string `json:"gatewayIP"` +} + +// matches is an helper used to compare the receiver bpfEgressGatewayPolicyEntry with another entry +func (e *BPFEgressGatewayPolicyEntry) matches(t BPFEgressGatewayPolicyEntry) bool { + return t.SourceIP == e.SourceIP && + t.DestCIDR == e.DestCIDR && + t.EgressIP == e.EgressIP && + t.GatewayIP == e.GatewayIP +} + +// WaitForEgressGatewayBpfPolicyEntries waits for the egress gateway policy maps on each node to WaitForEgressGatewayBpfPolicyEntries +// with the entries returned by the targetEntriesCallback +func WaitForEgressGatewayBpfPolicyEntries(ctx context.Context, ciliumPods map[string]Pod, + targetEntriesCallback func(ciliumPod Pod) ([]BPFEgressGatewayPolicyEntry, error), + excludeEntries func(ciliumPod Pod) ([]BPFEgressGatewayPolicyEntry, error), +) error { + w := wait.NewObserver(ctx, wait.Parameters{Timeout: 10 * time.Second}) + defer w.Cancel() + + ensureBpfPolicyEntries := func() error { + for _, ciliumPod := range ciliumPods { + targetEntries, err := targetEntriesCallback(ciliumPod) + if err != nil { + return fmt.Errorf("failed to get target entries: %w", err) + } + + cmd := strings.Split("cilium bpf egress list -o json", " ") + stdout, err := ciliumPod.K8sClient.ExecInPod(ctx, ciliumPod.Pod.Namespace, ciliumPod.Pod.Name, defaults.AgentContainerName, cmd) + if err != nil { + return fmt.Errorf("failed to run cilium bpf egress list command: %w", err) + } + + var entries []BPFEgressGatewayPolicyEntry + json.Unmarshal(stdout.Bytes(), &entries) + + excludes, err := excludeEntries(ciliumPod) + if err != nil { + return fmt.Errorf("failed to get exclude entries: %w", err) + } + for _, exclude := range excludes { + entries = slices.DeleteFunc(entries, func(entry BPFEgressGatewayPolicyEntry) bool { + return entry.matches(exclude) + }) + } + + for _, targetEntry := range targetEntries { + if !slices.ContainsFunc(entries, targetEntry.matches) { + return fmt.Errorf("could not find egress gateway policy entry matching %+v", targetEntry) + } + } + + for _, entry := range entries { + if !slices.ContainsFunc(targetEntries, entry.matches) { + return fmt.Errorf("untracked entry %+v in the egress gateway policy map", entry) + } + } + } + + return nil + } + + for { + if err := ensureBpfPolicyEntries(); err != nil { + if err := w.Retry(err); err != nil { + return fmt.Errorf("failed to ensure egress gateway policy map is properly populated: %w", err) + } + + continue + } + + return nil + } +} + func validateIPCache(ctx context.Context, agent Pod, pods []Pod) error { stdout, err := agent.K8sClient.ExecInPod(ctx, agent.Namespace(), agent.NameWithoutNamespace(), defaults.AgentContainerName, []string{"cilium", "bpf", "ipcache", "list", "-o", "json"}) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/benchmarks/netperf/perfpod.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/benchmarks/netperf/perfpod.go index afb9588015..d860442164 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/benchmarks/netperf/perfpod.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/benchmarks/netperf/perfpod.go @@ -6,6 +6,7 @@ package netperf import ( "context" "fmt" + "slices" "strconv" "strings" "time" @@ -52,6 +53,13 @@ func (s *netPerf) Run(ctx context.Context, t *check.Test) { } } + if perfParameters.ThroughputMulti { + tests = append(tests, "TCP_STREAM_MULTI") + if perfParameters.UDP { + tests = append(tests, "UDP_STREAM_MULTI") + } + } + if perfParameters.CRR { tests = append(tests, "TCP_CRR") } @@ -120,6 +128,7 @@ func (s *netPerf) Run(ctx context.Context, t *check.Test) { SameNode: sameNode, Sample: sample, Duration: perfParameters.Duration, + Streams: perfParameters.Streams, Scenario: scenarioName, MsgSize: perfParameters.MessageSize, NetQos: false, @@ -140,7 +149,7 @@ func buildExecCommand(test string, sip string, duration time.Duration, args []st return exec } -func parseDuration(a *check.Action, value string) time.Duration { +func parseDuration(a action, value string) time.Duration { res, err := time.ParseDuration(value + "us") // by default latencies in netperf are reported in microseconds if err != nil { a.Fatalf("Unable to process netperf result, duration: %s", value) @@ -148,7 +157,7 @@ func parseDuration(a *check.Action, value string) time.Duration { return res } -func parseFloat(a *check.Action, value string) float64 { +func parseFloat(a action, value string) float64 { res, err := strconv.ParseFloat(value, 64) if err != nil { a.Fatalf("Unable to process netperf result, float: %s", value) @@ -156,22 +165,8 @@ func parseFloat(a *check.Action, value string) float64 { return res } -func NetperfCmd(ctx context.Context, sip string, perfTest common.PerfTests, a *check.Action) common.PerfResult { - args := []string{"-o", "MIN_LATENCY,MEAN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,TRANSACTION_RATE,THROUGHPUT,THROUGHPUT_UNITS"} - if perfTest.Test == "UDP_STREAM" || perfTest.NetQos { - args = append(args, "-m", fmt.Sprintf("%d", perfTest.MsgSize)) - } - exec := buildExecCommand(perfTest.Test, sip, perfTest.Duration, args) - - a.ExecInPod(ctx, exec) - output := a.CmdOutput() - a.Debugf("Netperf output: ", output) - lines := strings.Split(output, "\n") - if len(lines) < 2 { - a.Fatal("Unable to process netperf result") - } - resultsLine := lines[len(lines)-2] - values := strings.Split(resultsLine, ",") +func parseNetperfResult(a action, test, line string) common.PerfResult { + values := strings.Split(line, ",") if len(values) != 9 { a.Fatalf("Unable to process netperf result") } @@ -195,19 +190,75 @@ func NetperfCmd(ctx context.Context, sip string, perfTest common.PerfTests, a *c }, } - if strings.HasSuffix(perfTest.Test, "_STREAM") { + if strings.HasSuffix(test, "_STREAM") { // We don't want to report transaction rate or latency res.TransactionRateMetric = nil res.Latency = nil // Verify that throughput unit is 10^6bits/s if values[8] != "10^6bits/s" { - a.Fatal("Unable to process netperf result") + a.Fatalf("Unable to process netperf result") } } - if strings.HasSuffix(perfTest.Test, "_RR") || strings.HasSuffix(perfTest.Test, "_CRR") { + if strings.HasSuffix(test, "_RR") || strings.HasSuffix(test, "_CRR") { // We don't want to report throughput res.ThroughputMetric = nil } return res } + +type action interface { + ExecInPod(ctx context.Context, cmd []string) + CmdOutput() string + + Debugf(format string, args ...any) + Fatalf(format string, args ...any) +} + +func NetperfCmd(ctx context.Context, sip string, perfTest common.PerfTests, a action) common.PerfResult { + test := strings.TrimSuffix(perfTest.Test, "_MULTI") + + streams := uint(1) + if strings.HasSuffix(perfTest.Test, "_MULTI") { + streams = perfTest.Streams + + if !strings.HasSuffix(test, "_STREAM") { + a.Fatalf("Only STREAM tests support parallelism") + } + } + + args := []string{"-o", "MIN_LATENCY,MEAN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,TRANSACTION_RATE,THROUGHPUT,THROUGHPUT_UNITS"} + if test == "UDP_STREAM" || perfTest.NetQos { + args = append(args, "-m", fmt.Sprintf("%d", perfTest.MsgSize)) + } + exec := buildExecCommand(test, sip, perfTest.Duration, args) + + if streams >= 2 { + exec = []string{"/bin/bash", "-c", + // We write the output of each process to a separate file and cat them + // at the end to prevent the possibility of interleaved output. + fmt.Sprintf("DIR=$(mktemp -d); for i in {1..%d}; do %s > $DIR/out$i.out & done; wait; cat $DIR/*; rm -rf $DIR", + streams, strings.Join(exec, " "), + )} + } + + a.ExecInPod(ctx, exec) + output := a.CmdOutput() + a.Debugf("Netperf output: %s", output) + lines := slices.DeleteFunc( + strings.Split(output, "\n"), + // Result lines always start with a number, hence drop all the others. + func(line string) bool { return len(line) == 0 || line[0] < '0' || line[0] > '9' }, + ) + if uint(len(lines)) != streams { + a.Fatalf("Unable to process netperf result: expected %d, got %d", streams, len(lines)) + } + + res := parseNetperfResult(a, test, lines[0]) + for _, line := range lines[1:] { + parsed := parseNetperfResult(a, test, line) + res.ThroughputMetric.Throughput += parsed.ThroughputMetric.Throughput + } + + return res +} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/common/metrics.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/common/metrics.go index 199e5e8372..f9da1ef086 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/common/metrics.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/perf/common/metrics.go @@ -101,6 +101,7 @@ type PerfTests struct { Sample int MsgSize int Duration time.Duration + Streams uint NetQos bool } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/egressgateway.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/egressgateway.go index e2dce34550..61b6e36580 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/egressgateway.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/egressgateway.go @@ -8,120 +8,14 @@ import ( "encoding/json" "fmt" "net" - "strings" - "time" - v1 "k8s.io/api/core/v1" k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/cilium/cilium/cilium-cli/connectivity/check" - "github.com/cilium/cilium/cilium-cli/defaults" "github.com/cilium/cilium/cilium-cli/utils/features" - "github.com/cilium/cilium/cilium-cli/utils/wait" ) -// bpfEgressGatewayPolicyEntry represents an entry in the BPF egress gateway policy map -type bpfEgressGatewayPolicyEntry struct { - SourceIP string `json:"sourceIP"` - DestCIDR string `json:"destCIDR"` - EgressIP string `json:"egressIP"` - GatewayIP string `json:"gatewayIP"` -} - -// matches is an helper used to compare the receiver bpfEgressGatewayPolicyEntry with another entry -func (e *bpfEgressGatewayPolicyEntry) matches(t bpfEgressGatewayPolicyEntry) bool { - return t.SourceIP == e.SourceIP && - t.DestCIDR == e.DestCIDR && - t.EgressIP == e.EgressIP && - t.GatewayIP == e.GatewayIP -} - -// WaitForEgressGatewayBpfPolicyEntries waits for the egress gateway policy maps on each node to WaitForEgressGatewayBpfPolicyEntries -// with the entries returned by the targetEntriesCallback -func WaitForEgressGatewayBpfPolicyEntries(ctx context.Context, t *check.Test, - targetEntriesCallback func(ciliumPod check.Pod) []bpfEgressGatewayPolicyEntry, -) { - ct := t.Context() - - w := wait.NewObserver(ctx, wait.Parameters{Timeout: 10 * time.Second}) - defer w.Cancel() - - ensureBpfPolicyEntries := func() error { - for _, ciliumPod := range ct.CiliumPods() { - targetEntries := targetEntriesCallback(ciliumPod) - - cmd := strings.Split("cilium bpf egress list -o json", " ") - stdout, err := ciliumPod.K8sClient.ExecInPod(ctx, ciliumPod.Pod.Namespace, ciliumPod.Pod.Name, defaults.AgentContainerName, cmd) - if err != nil { - t.Fatal("failed to run cilium bpf egress list command: %w", err) - } - - entries := []bpfEgressGatewayPolicyEntry{} - json.Unmarshal(stdout.Bytes(), &entries) - - nextTargetEntry: - for _, targetEntry := range targetEntries { - for _, entry := range entries { - if targetEntry.matches(entry) { - continue nextTargetEntry - } - } - - return fmt.Errorf("Could not find egress gateway policy entry matching %+v", targetEntry) - } - - nextEntry: - for _, entry := range entries { - for _, targetEntry := range targetEntries { - if targetEntry.matches(entry) { - continue nextEntry - } - } - - return fmt.Errorf("Untracked entry %+v in the egress gateway policy map", entry) - } - } - - return nil - } - - for { - if err := ensureBpfPolicyEntries(); err != nil { - if err := w.Retry(err); err != nil { - t.Fatal("Failed to ensure egress gateway policy map is properly populated:", err) - } - - continue - } - - return - } -} - -// getGatewayNodeInternalIP returns the k8s internal IP of the node acting as gateway for this test -func getGatewayNodeInternalIP(ct *check.ConnectivityTest, egressGatewayNode string) net.IP { - gatewayNode, ok := ct.Nodes()[egressGatewayNode] - if !ok { - return nil - } - - for _, addr := range gatewayNode.Status.Addresses { - if addr.Type != v1.NodeInternalIP { - continue - } - - ip := net.ParseIP(addr.Address) - if ip == nil || ip.To4() == nil { - continue - } - - return ip - } - - return nil -} - // extractClientIPFromResponse extracts the client IP from the response of the echo-external service func extractClientIPFromResponse(res string) net.IP { var clientIP struct { @@ -171,13 +65,13 @@ func (s *egressGateway) Run(ctx context.Context, t *check.Test) { t.Fatal("Cannot get egress gateway node") } - egressGatewayNodeInternalIP := getGatewayNodeInternalIP(ct, egressGatewayNode) + egressGatewayNodeInternalIP := ct.GetGatewayNodeInternalIP(egressGatewayNode) if egressGatewayNodeInternalIP == nil { t.Fatal("Cannot get egress gateway node internal IP") } - WaitForEgressGatewayBpfPolicyEntries(ctx, t, func(ciliumPod check.Pod) []bpfEgressGatewayPolicyEntry { - targetEntries := []bpfEgressGatewayPolicyEntry{} + err := check.WaitForEgressGatewayBpfPolicyEntries(ctx, ct.CiliumPods(), func(ciliumPod check.Pod) ([]check.BPFEgressGatewayPolicyEntry, error) { + var targetEntries []check.BPFEgressGatewayPolicyEntry egressIP := "0.0.0.0" if ciliumPod.Pod.Spec.NodeName == egressGatewayNode { @@ -186,7 +80,7 @@ func (s *egressGateway) Run(ctx context.Context, t *check.Test) { for _, client := range ct.ClientPods() { targetEntries = append(targetEntries, - bpfEgressGatewayPolicyEntry{ + check.BPFEgressGatewayPolicyEntry{ SourceIP: client.Pod.Status.PodIP, DestCIDR: "0.0.0.0/0", EgressIP: egressIP, @@ -196,7 +90,7 @@ func (s *egressGateway) Run(ctx context.Context, t *check.Test) { for _, echo := range ct.EchoPods() { targetEntries = append(targetEntries, - bpfEgressGatewayPolicyEntry{ + check.BPFEgressGatewayPolicyEntry{ SourceIP: echo.Pod.Status.PodIP, DestCIDR: "0.0.0.0/0", EgressIP: egressIP, @@ -204,8 +98,13 @@ func (s *egressGateway) Run(ctx context.Context, t *check.Test) { }) } - return targetEntries + return targetEntries, nil + }, func(ciliumPod check.Pod) ([]check.BPFEgressGatewayPolicyEntry, error) { + return ct.GetConnDisruptEgressPolicyEntries(ctx, ciliumPod) }) + if err != nil { + t.Fatal(err) + } // Ping hosts (pod to host connectivity). Should not get masqueraded with egress IP i := 0 @@ -336,13 +235,13 @@ func (s *egressGatewayExcludedCIDRs) Run(ctx context.Context, t *check.Test) { t.Fatal("Cannot get egress gateway node") } - egressGatewayNodeInternalIP := getGatewayNodeInternalIP(ct, egressGatewayNode) + egressGatewayNodeInternalIP := ct.GetGatewayNodeInternalIP(egressGatewayNode) if egressGatewayNodeInternalIP == nil { t.Fatal("Cannot get egress gateway node internal IP") } - WaitForEgressGatewayBpfPolicyEntries(ctx, t, func(ciliumPod check.Pod) []bpfEgressGatewayPolicyEntry { - targetEntries := []bpfEgressGatewayPolicyEntry{} + err := check.WaitForEgressGatewayBpfPolicyEntries(ctx, ct.CiliumPods(), func(ciliumPod check.Pod) ([]check.BPFEgressGatewayPolicyEntry, error) { + var targetEntries []check.BPFEgressGatewayPolicyEntry egressIP := "0.0.0.0" if ciliumPod.Pod.Spec.NodeName == egressGatewayNode { @@ -361,7 +260,7 @@ func (s *egressGatewayExcludedCIDRs) Run(ctx context.Context, t *check.Test) { } targetEntries = append(targetEntries, - bpfEgressGatewayPolicyEntry{ + check.BPFEgressGatewayPolicyEntry{ SourceIP: client.Pod.Status.PodIP, DestCIDR: "0.0.0.0/0", EgressIP: egressIP, @@ -369,7 +268,7 @@ func (s *egressGatewayExcludedCIDRs) Run(ctx context.Context, t *check.Test) { }) targetEntries = append(targetEntries, - bpfEgressGatewayPolicyEntry{ + check.BPFEgressGatewayPolicyEntry{ SourceIP: client.Pod.Status.PodIP, DestCIDR: fmt.Sprintf("%s/32", nodeWithoutCilium.Status.Addresses[0].Address), EgressIP: egressIP, @@ -378,8 +277,13 @@ func (s *egressGatewayExcludedCIDRs) Run(ctx context.Context, t *check.Test) { } } - return targetEntries + return targetEntries, nil + }, func(ciliumPod check.Pod) ([]check.BPFEgressGatewayPolicyEntry, error) { + return ct.GetConnDisruptEgressPolicyEntries(ctx, ciliumPod) }) + if err != nil { + t.Fatal(err) + } // Traffic matching an egress gateway policy and an excluded CIDR should leave the cluster masqueraded with the // node IP where the pod is running rather than with the egress IP(pod to external service) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/encryption.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/encryption.go index 4bf32e8eba..07f737773f 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/encryption.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/encryption.go @@ -258,14 +258,7 @@ func (s *podToPodEncryption) Run(ctx context.Context, t *check.Test) { t.Debug("Encapsulation before WG encryption") } - e, ok := t.Context().Feature(features.EncryptionPod) - isIPSec := ok && e.Enabled && e.Mode == "ipsec" - t.ForEachIPFamily(func(ipFam features.IPFamily) { - if isIPSec && ipFam == features.IPFamilyV6 { - t.Debugf("Inactive IPv6 test with IPSec, see https://github.com/cilium/cilium/issues/35485") - return - } testNoTrafficLeak(ctx, t, s, client, &server, &clientHost, &serverHost, requestHTTP, ipFam, assertNoLeaks, true, wgEncap) }) } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go index bab66d441f..f0751bf36f 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/errors.go @@ -65,7 +65,7 @@ func NoErrorsInLogs(ciliumVersion semver.Version, checkLevels []string, external endpointMapDeleteFailed, etcdReconnection, epRestoreMissingState, mutationDetectorKlog, hubbleFailedCreatePeer, fqdnDpUpdatesTimeout, longNetpolUpdate, failedToGetEpLabels, failedCreategRPCClient, unableReallocateIngressIP, fqdnMaxIPPerHostname, failedGetMetricsAPI, envoyTLSWarning, - ciliumNodeConfigDeprecation, hubbleUIEnvVarFallback, k8sClientNetworkStatusError} + ciliumNodeConfigDeprecation, hubbleUIEnvVarFallback, k8sClientNetworkStatusError, bgpAlphaResourceDeprecation} // The list is adopted from cilium/cilium/test/helper/utils.go var errorMsgsWithExceptions = map[string][]logMatcher{ panicMessage: nil, @@ -383,4 +383,6 @@ var ( // envoyTLSWarningTemplate is the legitimate warning log for negative TLS SNI test case // This is a template string as we need to replace %s for external target flag envoyTLSWarningTemplate = "cilium.tls_wrapper: Could not get server TLS context for pod.*on destination IP.*port 443 sni.*%s.*and raw socket is not allowed" + // bgpV2alpha1ResourceDeprecation is expected when using deprecated BGP resource versions in a test, specifically when running the tests after a Cilium downgrade. + bgpAlphaResourceDeprecation = regexMatcher{regexp.MustCompile(`cilium.io/v2alpha1 CiliumBGP\w+ is deprecated`)} ) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/multicast.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/multicast.go index 170a404457..5521e6e2a2 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/multicast.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/multicast.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "net/netip" + "slices" "strings" "sync" @@ -146,12 +147,7 @@ func (s *socatMulticast) addNodeWithoutGroup(nodeName string) { func (s *socatMulticast) isNodeWithoutGroup(nodeName string) bool { NodeWithoutGroupMu.RLock() defer NodeWithoutGroupMu.RUnlock() - for _, node := range NodeWithoutGroup { - if node == nodeName { - return true - } - } - return false + return slices.Contains(NodeWithoutGroup, nodeName) } func (s *socatMulticast) addNotSubscribePodAddress(nodeName string, podAddress v2.NodeAddress) { diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go index daa5f2caff..9e5393a703 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/pod.go @@ -211,11 +211,46 @@ func (s *podToPodNoFrag) Name() string { func (s *podToPodNoFrag) Run(ctx context.Context, t *check.Test) { ct := t.Context() client := ct.RandomClientPod() + + var server check.Pod + for _, pod := range ct.EchoPods() { + // Make sure that the server pod is on another node than client + if pod.Pod.Status.HostIP != client.Pod.Status.HostIP { + server = pod + break + } + } + + t.ForEachIPFamily(func(ipFam features.IPFamily) { + mtu := s.deriveMTU(ctx, t, ipFam) + t.NewAction(s, fmt.Sprintf("ping-%s", ipFam), client, server, ipFam).Run(func(a *check.Action) { + payloadSize := mtu - HdrSizeICMPEcho + switch ipFam { + case features.IPFamilyV4: + payloadSize -= HdrSizeIPv4 + case features.IPFamilyV6: + payloadSize -= HdrSizeIPv6 + } + a.ExecInPod(ctx, t.Context().PingCommand(server, ipFam, + "-M", "do", // DF + "-s", strconv.Itoa(payloadSize), // payload size + )) + }) + + }) +} + +func (s *podToPodNoFrag) deriveMTU(ctx context.Context, t *check.Test, ipFam features.IPFamily) int { + client := t.Context().RandomClientPod() var mtu int + ipFlag := "" + if ipFam == features.IPFamilyV6 { + ipFlag = " -6" + } cmd := []string{ "/bin/sh", "-c", - "ip route show default | grep -oE 'mtu [^ ]*' | cut -d' ' -f2", + fmt.Sprintf("ip%s route show default | grep -oE 'mtu [^ ]*' | cut -d' ' -f2", ipFlag), } t.Debugf("Running %s", strings.Join(cmd, " ")) mtuBytes, err := client.K8sClient.ExecInPod(ctx, client.Pod.Namespace, @@ -247,31 +282,7 @@ func (s *podToPodNoFrag) Run(ctx context.Context, t *check.Test) { } t.Debugf("Derived MTU: %d", mtu) - var server check.Pod - for _, pod := range ct.EchoPods() { - // Make sure that the server pod is on another node than client - if pod.Pod.Status.HostIP != client.Pod.Status.HostIP { - server = pod - break - } - } - - t.ForEachIPFamily(func(ipFam features.IPFamily) { - t.NewAction(s, fmt.Sprintf("ping-%s", ipFam), client, server, ipFam).Run(func(a *check.Action) { - payloadSize := mtu - HdrSizeICMPEcho - switch ipFam { - case features.IPFamilyV4: - payloadSize -= HdrSizeIPv4 - case features.IPFamilyV6: - payloadSize -= HdrSizeIPv6 - } - a.ExecInPod(ctx, t.Context().PingCommand(server, ipFam, - "-M", "do", // DF - "-s", strconv.Itoa(payloadSize), // payload size - )) - }) - - }) + return mtu } func PodToPodMissingIPCache(opts ...Option) check.Scenario { @@ -315,6 +326,10 @@ func (s *podToPodMissingIPCache) Run(ctx context.Context, t *check.Test) { continue } matches := ipcacheGetPat.FindStringSubmatch(output.String()) + if matches == nil { + ct.Warnf(`failed to find IP cache entry: "%s"`, output.String()) + continue + } identity := matches[1] encryptkey := matches[2] tunnelendpoint := matches[3] diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/upgrade.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/upgrade.go index a98404fcac..f1b1458ace 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/upgrade.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/upgrade.go @@ -6,6 +6,7 @@ package tests import ( "context" gojson "encoding/json" + "maps" "os" "strconv" @@ -76,6 +77,22 @@ func (n *noInterruptedConnections) Run(ctx context.Context, t *check.Test) { } else { ct.Info("Skipping conn-disrupt-test for NS traffic") } + + if ct.ShouldRunConnDisruptEgressGateway() { + pods, err = client.ListPods(ctx, ct.Params().TestNamespace, metav1.ListOptions{LabelSelector: "kind=" + check.KindTestConnDisruptEgressGateway}) + if err != nil { + t.Fatalf("Unable to list test-conn-disrupt-egw pods: %s", err) + } + if len(pods.Items) == 0 { + t.Fatal("No test-conn-disrupt-{client,server} for Egress Gateway pods found") + } + + for _, pod := range pods.Items { + restartCount[pod.GetObjectMeta().GetName()] = strconv.Itoa(int(pod.Status.ContainerStatuses[0].RestartCount)) + } + } else { + ct.Info("Skipping conn-disrupt-test for Egress Gateway") + } } // Only store restart counters which will be used later when running the same @@ -88,10 +105,7 @@ func (n *noInterruptedConnections) Run(ctx context.Context, t *check.Test) { } defer file.Close() - counts := make(map[string]string) - for pod, count := range restartCount { - counts[pod] = count - } + counts := maps.Clone(restartCount) j, err := gojson.Marshal(counts) if err != nil { t.Fatalf("Failed to marshal JSON: %s", err) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go index 5438f18bc9..5dd6ff1b63 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/connectivity/tests/world.go @@ -62,25 +62,34 @@ func (s *podToWorld) Run(ctx context.Context, t *check.Test) { ct := t.Context() for _, client := range ct.ClientPods() { - // With http, over port 80. - httpOpts := s.rc.CurlOptions(http, features.IPFamilyAny, client, ct.Params()) - t.NewAction(s, fmt.Sprintf("http-to-%s-%d", extTarget, i), &client, http, features.IPFamilyAny).Run(func(a *check.Action) { - a.ExecInPod(ctx, a.CurlCommand(http, httpOpts...)) - a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) - }) + t.ForEachIPFamily(func(ipFam features.IPFamily) { + // TODO: Reenable the test once the kernel with the bugfix is released: + // https://patchwork.kernel.org/project/netdevbpf/patch/20250318161516.3791383-1-maxim@isovalent.com/ + // and when IPv6 external connectivity starts working in the CI. + if ipFam == features.IPFamilyV6 { + return + } - // With https, over port 443. - httpsOpts := s.rc.CurlOptions(https, features.IPFamilyAny, client, ct.Params()) - t.NewAction(s, fmt.Sprintf("https-to-%s-%d", extTarget, i), &client, https, features.IPFamilyAny).Run(func(a *check.Action) { - a.ExecInPod(ctx, a.CurlCommand(https, httpsOpts...)) - a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) - }) + // With http, over port 80. + httpOpts := s.rc.CurlOptions(http, ipFam, client, ct.Params()) + t.NewAction(s, fmt.Sprintf("http-to-%s-%s-%d", extTarget, ipFam, i), &client, http, ipFam).Run(func(a *check.Action) { + a.ExecInPod(ctx, a.CurlCommand(http, httpOpts...)) + a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) + }) - // With https, over port 443, index.html. - httpsindexOpts := s.rc.CurlOptions(httpsindex, features.IPFamilyAny, client, ct.Params()) - t.NewAction(s, fmt.Sprintf("https-to-%s-index-%d", extTarget, i), &client, httpsindex, features.IPFamilyAny).Run(func(a *check.Action) { - a.ExecInPod(ctx, a.CurlCommand(httpsindex, httpsindexOpts...)) - a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) + // With https, over port 443. + httpsOpts := s.rc.CurlOptions(https, ipFam, client, ct.Params()) + t.NewAction(s, fmt.Sprintf("https-to-%s-%s-%d", extTarget, ipFam, i), &client, https, ipFam).Run(func(a *check.Action) { + a.ExecInPod(ctx, a.CurlCommand(https, httpsOpts...)) + a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) + }) + + // With https, over port 443, index.html. + httpsindexOpts := s.rc.CurlOptions(httpsindex, ipFam, client, ct.Params()) + t.NewAction(s, fmt.Sprintf("https-to-%s-index-%s-%d", extTarget, ipFam, i), &client, httpsindex, ipFam).Run(func(a *check.Action) { + a.ExecInPod(ctx, a.CurlCommand(httpsindex, httpsindexOpts...)) + a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) + }) }) i++ @@ -117,11 +126,20 @@ func (s *podToWorld2) Run(ctx context.Context, t *check.Test) { ct := t.Context() for _, client := range ct.ClientPods() { - // With https, over port 443. - t.NewAction(s, fmt.Sprintf("https-%s-%d", extTarget, i), &client, https, features.IPFamilyAny).Run(func(a *check.Action) { - a.ExecInPod(ctx, a.CurlCommand(https)) - a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) - a.ValidateMetrics(ctx, client, a.GetEgressMetricsRequirements()) + t.ForEachIPFamily(func(ipFam features.IPFamily) { + // TODO: Reenable the test once the kernel with the bugfix is released: + // https://patchwork.kernel.org/project/netdevbpf/patch/20250318161516.3791383-1-maxim@isovalent.com/ + // and when IPv6 external connectivity starts working in the CI. + if ipFam == features.IPFamilyV6 { + return + } + + // With https, over port 443. + t.NewAction(s, fmt.Sprintf("https-%s-%s-%d", extTarget, ipFam, i), &client, https, ipFam).Run(func(a *check.Action) { + a.ExecInPod(ctx, a.CurlCommand(https)) + a.ValidateFlows(ctx, client, a.GetEgressRequirements(fp)) + a.ValidateMetrics(ctx, client, a.GetEgressMetricsRequirements()) + }) }) i++ diff --git a/vendor/github.com/cilium/cilium/cilium-cli/encrypt/status.go b/vendor/github.com/cilium/cilium/cilium-cli/encrypt/status.go index f41b496fdf..9f49d39edb 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/encrypt/status.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/encrypt/status.go @@ -8,7 +8,7 @@ import ( "encoding/json" "errors" "fmt" - "sort" + "slices" "strconv" "strings" @@ -312,9 +312,7 @@ func printClusterStatus(cs clusterStatus, format string) error { for k := range cs.IPsecKeysInUseNodeCount { keys = append(keys, k) } - sort.Slice(keys, func(i, j int) bool { - return keys[i] < keys[j] - }) + slices.Sort(keys) keyStrs := make([]string, 0, len(keys)) for _, k := range keys { keyStrs = append(keyStrs, fmt.Sprintf("%d on %d/%d", k, cs.IPsecKeysInUseNodeCount[k], cs.TotalNodeCount)) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/features/summary.go b/vendor/github.com/cilium/cilium/cilium-cli/features/summary.go index efedb8b3b4..539860c2f2 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/features/summary.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/features/summary.go @@ -23,7 +23,7 @@ import ( "github.com/cilium/cilium/api/v1/models" "github.com/cilium/cilium/cilium-cli/defaults" - "github.com/google/go-github/v68/github" + "github.com/google/go-github/v70/github" "golang.org/x/oauth2" ) diff --git a/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go b/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go index f560f0740f..e0190cd0a5 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/internal/helm/helm.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "io/fs" + "maps" "os" "path" "regexp" @@ -38,10 +39,7 @@ var settings = cli.New() // Merge maps recursively merges the values of b into a copy of a, preferring the values from b func mergeMaps(a, b map[string]interface{}) map[string]interface{} { - out := make(map[string]interface{}, len(a)) - for k, v := range a { - out[k] = v - } + out := maps.Clone(a) for k, v := range b { if v, ok := v.(map[string]interface{}); ok { if bv, ok := out[k]; ok { diff --git a/vendor/github.com/cilium/cilium/cilium-cli/status/k8s.go b/vendor/github.com/cilium/cilium/cilium-cli/status/k8s.go index 224646455b..745cadf1b1 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/status/k8s.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/status/k8s.go @@ -26,6 +26,7 @@ import ( "github.com/cilium/cilium/api/v1/models" "github.com/cilium/cilium/cilium-cli/defaults" "github.com/cilium/cilium/cilium-cli/k8s" + logfilter "github.com/cilium/cilium/cilium-cli/utils/log" "github.com/cilium/cilium/pkg/annotation" ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" ) @@ -451,7 +452,7 @@ func (k *K8sStatusCollector) logComponentTask(status *Status, namespace, deploym if errLogCollection != nil { status.CollectionError(fmt.Errorf("failed to gather logs from %s:%s:%s: %w", namespace, podName, containerName, err)) } else if logs != "" { - lastLog := k.processLogs(logs) + lastLog := logfilter.Reduce(logs, k.params.Verbose) err = fmt.Errorf("container %s %s:\n%s", containerName, desc, lastLog) } } @@ -470,54 +471,6 @@ func (k *K8sStatusCollector) logComponentTask(status *Status, namespace, deploym } } -func (k *K8sStatusCollector) processLogs(logs string) string { - logs = strings.TrimSpace(logs) - if k.params.Verbose { - return logs - } - - // If the log is small, just print the whole thing. - context := 5 // lines - lines := strings.Split(logs, "\n") - if len(lines) <= context*2 { - return logs - } - - // There's a few critical things in most logs: - // - A few of the oldest lines from initial startup - // - A few of the newest lines with the final error - // - Anything marked with warning level or higher severity - truncated := false - result := lines[:context] - for i := context; i < len(lines); i++ { - // Always keep the end of the log - if i >= len(lines)-context { - result = append(result, lines[i]) - continue - } - - // Keep serious-looking logs - switch { - case strings.Contains(lines[i], "level=warn"): - result = append(result, lines[i]) - truncated = false - case strings.Contains(lines[i], "level=err"): - result = append(result, lines[i]) - truncated = false - case strings.Contains(lines[i], "level=fatal"): - result = append(result, lines[i]) - truncated = false - default: - if !truncated { - result = append(result, "<...>") - truncated = true - } - } - } - - return strings.Join(result, "\n") -} - func (k *K8sStatusCollector) status(ctx context.Context, cancel context.CancelFunc) *Status { status := newStatus() tasks := []statusTask{ diff --git a/vendor/github.com/cilium/cilium/cilium-cli/utils/codeowners/codeowners.go b/vendor/github.com/cilium/cilium/cilium-cli/utils/codeowners/codeowners.go new file mode 100644 index 0000000000..b8a18af7a1 --- /dev/null +++ b/vendor/github.com/cilium/cilium/cilium-cli/utils/codeowners/codeowners.go @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package codeowners + +import ( + "fmt" + "os" + + "github.com/hmarr/codeowners" +) + +type Ruleset codeowners.Ruleset + +func Load(paths []string) (codeowners.Ruleset, error) { + if len(paths) == 0 { + owners, err := codeowners.LoadFileFromStandardLocation() + if err != nil { + return nil, fmt.Errorf("while loading: %w", err) + } + return owners, nil + } + + var allOwners codeowners.Ruleset + + for _, f := range paths { + coFile, err := os.Open(f) + if err != nil { + return nil, fmt.Errorf("while opening %s: %w", f, err) + } + defer coFile.Close() + + owners, err := codeowners.ParseFile(coFile) + if err != nil { + return nil, fmt.Errorf("while parsing %s: %w", f, err) + } + + allOwners = append(allOwners, owners...) + } + + return allOwners, nil +} diff --git a/vendor/github.com/cilium/cilium/cilium-cli/utils/features/features.go b/vendor/github.com/cilium/cilium/cilium-cli/utils/features/features.go index 9100fd5148..2560637f77 100644 --- a/vendor/github.com/cilium/cilium/cilium-cli/utils/features/features.go +++ b/vendor/github.com/cilium/cilium/cilium-cli/utils/features/features.go @@ -407,9 +407,9 @@ func (fs Set) ExtractFromConfigMap(cm *v1.ConfigMap) { } } -func (fs Set) ExtractFromNodes(perf bool, nodesWithoutCilium map[string]struct{}) { +func (fs Set) ExtractFromNodes(nodesWithoutCilium map[string]struct{}) { fs[NodeWithoutCilium] = Status{ - Enabled: !perf && len(nodesWithoutCilium) != 0, + Enabled: len(nodesWithoutCilium) != 0, Mode: strings.Join(slices.Collect(maps.Keys(nodesWithoutCilium)), ","), } } diff --git a/vendor/github.com/cilium/cilium/cilium-cli/utils/log/log.go b/vendor/github.com/cilium/cilium/cilium-cli/utils/log/log.go new file mode 100644 index 0000000000..e887b88b0f --- /dev/null +++ b/vendor/github.com/cilium/cilium/cilium-cli/utils/log/log.go @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package log + +import "strings" + +// Reduce function filters log messages +// and returns only valuable data (warn, err, fatal) +// in case of verbose all the messages will be returned +func Reduce(logs string, verbose bool) string { + logs = strings.TrimSpace(logs) + if verbose { + return logs + } + + // If the log is small, just print the whole thing. + context := 5 // lines + lines := strings.Split(logs, "\n") + if len(lines) <= context*2 { + return logs + } + + // There's a few critical things in most logs: + // - A few of the oldest lines from initial startup + // - A few of the newest lines with the final error + // - Anything marked with warning level or higher severity + truncated := false + result := lines[:context] + for i := context; i < len(lines); i++ { + // Always keep the end of the log + if i >= len(lines)-context { + result = append(result, lines[i]) + continue + } + + // Keep serious-looking logs + switch { + case strings.Contains(lines[i], "level=warn"): + result = append(result, lines[i]) + truncated = false + case strings.Contains(lines[i], "level=err"): + result = append(result, lines[i]) + truncated = false + case strings.Contains(lines[i], "level=fatal"): + result = append(result, lines[i]) + truncated = false + default: + if !truncated { + result = append(result, "<...>") + truncated = true + } + } + } + + return strings.Join(result, "\n") +} diff --git a/vendor/github.com/cilium/cilium/daemon/k8s/init.go b/vendor/github.com/cilium/cilium/daemon/k8s/init.go index 9654a44602..d0b86fadb9 100644 --- a/vendor/github.com/cilium/cilium/daemon/k8s/init.go +++ b/vendor/github.com/cilium/cilium/daemon/k8s/init.go @@ -15,6 +15,7 @@ import ( "github.com/cilium/cilium/pkg/k8s" k8sConst "github.com/cilium/cilium/pkg/k8s/constants" "github.com/cilium/cilium/pkg/k8s/resource" + "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/node" nodeTypes "github.com/cilium/cilium/pkg/node/types" @@ -61,7 +62,7 @@ func retrieveNodeInformation(ctx context.Context, log logrus.FieldLogger, localN break } if event.Kind == resource.Upsert { - n = k8s.ParseNode(event.Object, source.Unspec) + n = k8s.ParseNode(logging.DefaultSlogLogger, event.Object, source.Unspec) log.WithField(logfields.NodeName, n.Name).Info("Retrieved node information from kubernetes node") if err := waitForCIDR(); err != nil { log.WithError(err).Warning("Waiting for k8s node information") diff --git a/vendor/github.com/cilium/cilium/netlify.toml b/vendor/github.com/cilium/cilium/netlify.toml deleted file mode 100644 index ce6d7f8250..0000000000 --- a/vendor/github.com/cilium/cilium/netlify.toml +++ /dev/null @@ -1,4 +0,0 @@ -[build] - base = "Documentation/" - publish = "_build/html" - command = "make html-netlify" diff --git a/vendor/github.com/cilium/cilium/operator/option/config.go b/vendor/github.com/cilium/cilium/operator/option/config.go index 1ef32dda82..f2994de57f 100644 --- a/vendor/github.com/cilium/cilium/operator/option/config.go +++ b/vendor/github.com/cilium/cilium/operator/option/config.go @@ -95,11 +95,6 @@ const ( // AWS options - // AWSInstanceLimitMapping allows overwirting AWS instance limits defined in - // pkg/aws/eni/limits.go - // e.g. {"a1.medium": "2,4,4", "a2.custom2": "4,5,6"} - AWSInstanceLimitMapping = "aws-instance-limit-mapping" - // AWSReleaseExcessIPs allows releasing excess free IP addresses from ENI. // Enabling this option reduces waste of IP addresses but may increase // the number of API calls to AWS EC2 service. @@ -129,10 +124,6 @@ const ( // ParallelAllocWorkers specifies the number of parallel workers to be used for IPAM allocation ParallelAllocWorkers = "parallel-alloc-workers" - // UpdateEC2AdapterLimitViaAPI configures the operator to use the EC2 - // API to fill out the instancetype to adapter limit mapping. - UpdateEC2AdapterLimitViaAPI = "update-ec2-adapter-limit-via-api" - // EC2APIEndpoint is the custom API endpoint to use for the EC2 AWS service, // e.g. "ec2-fips.us-west-1.amazonaws.com" to use a FIPS endpoint in the us-west-1 region. EC2APIEndpoint = "ec2-api-endpoint" @@ -321,11 +312,6 @@ type OperatorConfig struct { // ParallelAllocWorkers specifies the number of parallel workers to be used for accessing cloud provider APIs . ParallelAllocWorkers int64 - // AWSInstanceLimitMapping allows overwriting AWS instance limits defined in - // pkg/aws/eni/limits.go - // e.g. {"a1.medium": "2,4,4", "a2.custom2": "4,5,6"} - AWSInstanceLimitMapping map[string]string - // AWSReleaseExcessIps allows releasing excess free IP addresses from ENI. // Enabling this option reduces waste of IP addresses but may increase // the number of API calls to AWS EC2 service. @@ -339,10 +325,6 @@ type OperatorConfig struct { // node AWSUsePrimaryAddress bool - // UpdateEC2AdapterLimitViaAPI configures the operator to use the EC2 API to fill out the - // instancetype to adapter limit mapping. - UpdateEC2AdapterLimitViaAPI bool - // ExcessIPReleaseDelay controls how long operator would wait before an IP previously marked as excess is released. // Defaults to 180 secs ExcessIPReleaseDelay int @@ -469,7 +451,6 @@ func (c *OperatorConfig) Populate(vp *viper.Viper) { c.AWSReleaseExcessIPs = vp.GetBool(AWSReleaseExcessIPs) c.AWSEnablePrefixDelegation = vp.GetBool(AWSEnablePrefixDelegation) c.AWSUsePrimaryAddress = vp.GetBool(AWSUsePrimaryAddress) - c.UpdateEC2AdapterLimitViaAPI = vp.GetBool(UpdateEC2AdapterLimitViaAPI) c.EC2APIEndpoint = vp.GetString(EC2APIEndpoint) c.ExcessIPReleaseDelay = vp.GetInt(ExcessIPReleaseDelay) c.ENIGarbageCollectionInterval = vp.GetDuration(ENIGarbageCollectionInterval) @@ -504,12 +485,6 @@ func (c *OperatorConfig) Populate(vp *viper.Viper) { c.IPAMInstanceTags = m } - if m, err := command.GetStringMapStringE(vp, AWSInstanceLimitMapping); err != nil { - log.Fatalf("unable to parse %s: %s", AWSInstanceLimitMapping, err) - } else { - c.AWSInstanceLimitMapping = m - } - if m, err := command.GetStringMapStringE(vp, ENITags); err != nil { log.Fatalf("unable to parse %s: %s", ENITags, err) } else { @@ -535,7 +510,6 @@ var Config = &OperatorConfig{ IPAMSubnetsTags: make(map[string]string), IPAMInstanceTags: make(map[string]string), IPAMAutoCreateCiliumPodIPPools: make(map[string]string), - AWSInstanceLimitMapping: make(map[string]string), ENITags: make(map[string]string), ENIGarbageCollectionTags: make(map[string]string), } diff --git a/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go b/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go index aab22b52bd..4f88edeffd 100644 --- a/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go +++ b/vendor/github.com/cilium/cilium/pkg/allocator/allocator.go @@ -10,7 +10,6 @@ import ( "log/slog" "github.com/google/uuid" - "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/backoff" "github.com/cilium/cilium/pkg/idpool" @@ -315,7 +314,7 @@ func NewAllocator(rootLogger *slog.Logger, typ AllocatorKey, backend Backend, op backend: backend, min: idpool.ID(1), max: idpool.ID(^uint64(0)), - localKeys: newLocalKeys(), + localKeys: newLocalKeys(rootLogger), stopGC: make(chan struct{}), suffix: uuid.New().String()[:10], remoteCaches: map[string]*remoteCache{}, @@ -527,7 +526,7 @@ type AllocatorKey interface { func (a *Allocator) lockedAllocate(ctx context.Context, key AllocatorKey) (idpool.ID, bool, bool, error) { var firstUse bool - kvstore.Trace("Allocating key in kvstore", nil, logrus.Fields{fieldKey: key}) + kvstore.Trace(a.logger, "Allocating key in kvstore", fieldKey, key) k := key.GetKey() lock, err := a.backend.Lock(ctx, key) @@ -544,7 +543,7 @@ func (a *Allocator) lockedAllocate(ctx context.Context, key AllocatorKey) (idpoo return 0, false, false, err } - kvstore.Trace("kvstore state is: ", nil, logrus.Fields{fieldID: value}) + kvstore.Trace(a.logger, "kvstore state is: ", fieldID, value) a.slaveKeysMutex.Lock() defer a.slaveKeysMutex.Unlock() @@ -595,7 +594,7 @@ func (a *Allocator) lockedAllocate(ctx context.Context, key AllocatorKey) (idpoo return 0, false, false, fmt.Errorf("no more available IDs in configured space") } - kvstore.Trace("Selected available key ID", nil, logrus.Fields{fieldID: id}) + kvstore.Trace(a.logger, "Selected available key ID", fieldID, id) releaseKeyAndID := func() { a.localKeys.release(k) @@ -695,7 +694,7 @@ func (a *Allocator) Allocate(ctx context.Context, key AllocatorKey) (idpool.ID, return id, false, false, err } - kvstore.Trace("Allocating from kvstore", nil, logrus.Fields{fieldKey: key}) + kvstore.Trace(a.logger, "Allocating from kvstore", fieldKey, key) // make a copy of the template and customize it boff := a.backoffTemplate @@ -710,7 +709,10 @@ func (a *Allocator) Allocate(ctx context.Context, key AllocatorKey) (idpool.ID, // execution thread. It does not hurt to check if localKeys contains a // reference for the key that we are attempting to allocate. if val := a.localKeys.use(key.GetKey()); val != idpool.NoID { - kvstore.Trace("Reusing local id", nil, logrus.Fields{fieldID: val, fieldKey: key}) + kvstore.Trace(a.logger, "Reusing local id", + fieldID, val, + fieldKey, key, + ) a.mainCache.insert(key, val) return val, false, false, nil } @@ -742,7 +744,10 @@ func (a *Allocator) Allocate(ctx context.Context, key AllocatorKey) (idpool.ID, ) } - kvstore.Trace("Allocation attempt failed", err, logrus.Fields{fieldKey: key, logfields.Attempt: attempt}) + kvstore.Trace(a.logger, "Allocation attempt failed", + fieldKey, key, + logfields.Attempt, attempt, + ) if waitErr := boff.Wait(ctx); waitErr != nil { return 0, false, false, waitErr diff --git a/vendor/github.com/cilium/cilium/pkg/allocator/localkeys.go b/vendor/github.com/cilium/cilium/pkg/allocator/localkeys.go index 48820d7366..54cc5e6928 100644 --- a/vendor/github.com/cilium/cilium/pkg/allocator/localkeys.go +++ b/vendor/github.com/cilium/cilium/pkg/allocator/localkeys.go @@ -5,8 +5,7 @@ package allocator import ( "fmt" - - "github.com/sirupsen/logrus" + "log/slog" "github.com/cilium/cilium/pkg/idpool" "github.com/cilium/cilium/pkg/kvstore" @@ -25,15 +24,17 @@ type localKey struct { // localKeys is a map of keys in use locally. Keys can be used multiple times. // A refcnt is managed to know when a key is no longer in use type localKeys struct { + logger *slog.Logger lock.RWMutex keys map[string]*localKey ids map[idpool.ID]*localKey } -func newLocalKeys() *localKeys { +func newLocalKeys(logger *slog.Logger) *localKeys { return &localKeys{ - keys: map[string]*localKey{}, - ids: map[idpool.ID]*localKey{}, + logger: logger, + keys: map[string]*localKey{}, + ids: map[idpool.ID]*localKey{}, } } @@ -52,7 +53,11 @@ func (lk *localKeys) allocate(keyString string, key AllocatorKey, val idpool.ID) } k.refcnt++ - kvstore.Trace("Incremented local key refcnt", nil, logrus.Fields{fieldKey: keyString, fieldID: val, fieldRefCnt: k.refcnt}) + kvstore.Trace(lk.logger, "Incremented local key refcnt", + fieldKey, keyString, + fieldID, val, + fieldRefCnt, k.refcnt, + ) return k.val, firstUse, nil } @@ -60,7 +65,11 @@ func (lk *localKeys) allocate(keyString string, key AllocatorKey, val idpool.ID) k := &localKey{key: key, val: val, refcnt: 1} lk.keys[keyString] = k lk.ids[val] = k - kvstore.Trace("New local key", nil, logrus.Fields{fieldKey: keyString, fieldID: val, fieldRefCnt: 1}) + kvstore.Trace(lk.logger, "New local key", + fieldKey, keyString, + fieldID, val, + fieldRefCnt, 1, + ) return val, firstUse, nil } @@ -70,7 +79,9 @@ func (lk *localKeys) verify(key string) error { if k, ok := lk.keys[key]; ok { k.verified = true - kvstore.Trace("Local key verified", nil, logrus.Fields{fieldKey: key}) + kvstore.Trace(lk.logger, "Local key verified", + fieldKey, key, + ) return nil } @@ -114,7 +125,11 @@ func (lk *localKeys) use(key string) idpool.ID { } k.refcnt++ - kvstore.Trace("Incremented local key refcnt", nil, logrus.Fields{fieldKey: key, fieldID: k.val, fieldRefCnt: k.refcnt}) + kvstore.Trace(lk.logger, "Incremented local key refcnt", + fieldKey, key, + fieldID, k.val, + fieldRefCnt, k.refcnt, + ) return k.val } @@ -129,7 +144,11 @@ func (lk *localKeys) release(key string) (lastUse bool, id idpool.ID, err error) defer lk.Unlock() if k, ok := lk.keys[key]; ok { k.refcnt-- - kvstore.Trace("Decremented local key refcnt", nil, logrus.Fields{fieldKey: key, fieldID: k.val, fieldRefCnt: k.refcnt}) + kvstore.Trace(lk.logger, "Decremented local key refcnt", + fieldKey, key, + fieldID, k.val, + fieldRefCnt, k.refcnt, + ) if k.refcnt == 0 { delete(lk.keys, key) delete(lk.ids, k.val) diff --git a/vendor/github.com/cilium/cilium/pkg/client/client.go b/vendor/github.com/cilium/cilium/pkg/client/client.go index fef6a84f44..e168e280eb 100644 --- a/vendor/github.com/cilium/cilium/pkg/client/client.go +++ b/vendor/github.com/cilium/cilium/pkg/client/client.go @@ -535,8 +535,6 @@ func FormatStatusResponse(w io.Writer, sr *models.StatusResponse, sd StatusDetai status = "BPF" } if sr.KubeProxyReplacement != nil { - // When BPF Masquerading is enabled we don't do any masquerading for IPv6 - // traffic so no SNAT Exclusion IPv6 CIDR is listed in status output. devStr := "" for i, dev := range sr.KubeProxyReplacement.DeviceList { devStr += dev.Name @@ -544,9 +542,12 @@ func FormatStatusResponse(w io.Writer, sr *models.StatusResponse, sd StatusDetai devStr += ", " } } - status += fmt.Sprintf("\t[%s]\t%s", + status += fmt.Sprintf( + "\t[%s]\t%s %s", devStr, - sr.Masquerading.SnatExclusionCidrV4) + sr.Masquerading.SnatExclusionCidrV4, + sr.Masquerading.SnatExclusionCidrV6, + ) } } else if sr.Masquerading.Mode == models.MasqueradingModeIptables { diff --git a/vendor/github.com/cilium/cilium/pkg/client/config.go b/vendor/github.com/cilium/cilium/pkg/client/config.go index 3775abe2ee..1734eded0b 100644 --- a/vendor/github.com/cilium/cilium/pkg/client/config.go +++ b/vendor/github.com/cilium/cilium/pkg/client/config.go @@ -4,6 +4,8 @@ package client import ( + "maps" + "github.com/cilium/cilium/api/v1/client/daemon" "github.com/cilium/cilium/api/v1/models" "github.com/cilium/cilium/pkg/api" @@ -25,9 +27,7 @@ func (c *Client) ConfigPatch(cfg models.DaemonConfigurationSpec) error { return err } - for opt, value := range cfg.Options { - fullCfg.Spec.Options[opt] = value - } + maps.Copy(fullCfg.Spec.Options, cfg.Options) if cfg.PolicyEnforcement != "" { fullCfg.Spec.PolicyEnforcement = cfg.PolicyEnforcement } diff --git a/vendor/github.com/cilium/cilium/pkg/comparator/comparator.go b/vendor/github.com/cilium/cilium/pkg/comparator/comparator.go index 49ccc8dd1e..03b4985c8c 100644 --- a/vendor/github.com/cilium/cilium/pkg/comparator/comparator.go +++ b/vendor/github.com/cilium/cilium/pkg/comparator/comparator.go @@ -3,6 +3,8 @@ package comparator +import "slices" + // MapStringEqualsIgnoreKeys returns true if both maps have the same values for // the keys that are not present in the 'ignoreKeys'. func MapStringEqualsIgnoreKeys(m1, m2 map[string]string, ignoreKeys []string) bool { @@ -16,11 +18,8 @@ func MapStringEqualsIgnoreKeys(m1, m2 map[string]string, ignoreKeys []string) bo ignoredM1 := 0 for k1, v1 := range m1 { var ignore bool - for _, ig := range ignoreKeys { - if k1 == ig { - ignore = true - break - } + if slices.Contains(ignoreKeys, k1) { + ignore = true } if ignore { ignoredM1++ diff --git a/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go b/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go index 79aa63e3f3..dd2940ced0 100644 --- a/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go +++ b/vendor/github.com/cilium/cilium/pkg/container/versioned/value.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "iter" + "log/slog" "math" "runtime" "slices" @@ -14,7 +15,6 @@ import ( "sync/atomic" "github.com/hashicorp/go-hclog" - "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/lock" "github.com/cilium/cilium/pkg/logging/logfields" @@ -103,9 +103,9 @@ func versionHandleFinalizer(h *VersionHandle) { if coordinator != nil && coordinator.Logger != nil { logger := coordinator.Logger if h.stacktrace != "" { - logger = logger.WithField(logfields.Stacktrace, h.stacktrace) + logger = logger.With(logfields.Stacktrace, h.stacktrace) } - logger.WithField(logfields.Version, h.version).Error("Handle for version not closed.") + logger.Error("Handle for version not closed.", logfields.Version, h.version) } h.Close() } @@ -159,7 +159,7 @@ type versionCount struct { // should be cleaned by the 'cleaner' function given to the Coordinator. type Coordinator struct { // Logger supplied to NewCoordinator. Should be set if logging is desired. - Logger *logrus.Entry + Logger *slog.Logger // Cleaner is called with the earliest version that must be kept. // Must be set to clean up resources held for old versions. @@ -270,10 +270,11 @@ func (v *Coordinator) releaseVersion(version version) error { n, found := slices.BinarySearchFunc(v.versions, version, versionHandleCmp) if !found { if v.Logger != nil { - v.Logger.WithFields(logrus.Fields{ - logfields.Version: version, - logfields.Stacktrace: hclog.Stacktrace(), - }).Error("Version not found.") + v.Logger.Error( + "Version not found.", + logfields.Version, version, + logfields.Stacktrace, hclog.Stacktrace(), + ) } return ErrVersionNotFound } @@ -303,15 +304,16 @@ func (v *Coordinator) clean() { // The cleaner is called from a goroutine without holding any locks if v.Cleaner != nil { if v.Logger != nil { - v.Logger.WithFields(logrus.Fields{ - logfields.OldVersion: v.oldestVersion, - logfields.NewVersion: keepVersion, - }).Debug("releaseVersion: calling cleaner") + v.Logger.Debug( + "releaseVersion: calling cleaner", + logfields.OldVersion, v.oldestVersion, + logfields.NewVersion, keepVersion, + ) } go v.Cleaner(KeepVersion(keepVersion)) v.oldestVersion = keepVersion } else if v.Logger != nil { - v.Logger.Warnf("VersionHandle.Close: Cleaner function not set") + v.Logger.Warn("VersionHandle.Close: Cleaner function not set") } } } @@ -333,11 +335,12 @@ func (v *Coordinator) getVersionHandleLocked(version version) *VersionHandle { oldVersion := version version = v.oldestVersion if v.Logger != nil { - v.Logger.WithFields(logrus.Fields{ - logfields.Stacktrace: hclog.Stacktrace(), - logfields.Version: version, - logfields.OldVersion: oldVersion, - }).Warn("GetVersionHandle: Handle to a stale version requested, returning oldest valid version instead") + v.Logger.Warn( + "GetVersionHandle: Handle to a stale version requested, returning oldest valid version instead", + logfields.Stacktrace, hclog.Stacktrace(), + logfields.Version, version, + logfields.OldVersion, oldVersion, + ) } } n, found := slices.BinarySearchFunc(v.versions, version, versionHandleCmp) diff --git a/vendor/github.com/cilium/cilium/pkg/controller/manager.go b/vendor/github.com/cilium/cilium/pkg/controller/manager.go index cd9a2c73ad..a34e4a79dd 100644 --- a/vendor/github.com/cilium/cilium/pkg/controller/manager.go +++ b/vendor/github.com/cilium/cilium/pkg/controller/manager.go @@ -6,6 +6,7 @@ package controller import ( "context" "fmt" + "maps" "github.com/go-openapi/strfmt" "github.com/google/uuid" @@ -70,14 +71,18 @@ func (m *Manager) updateController(name string, params ControllerParams) *manage ctrl := m.lookupLocked(name) if ctrl != nil { + ctrl.mutex.Lock() ctrl.getLogger().Debug("Updating existing controller") ctrl.updateParamsLocked(params) + ctrl.mutex.Unlock() + ctrl.mutex.RLock() // Notify the goroutine of the params update. select { case ctrl.update <- ctrl.params: default: } + ctrl.mutex.RUnlock() ctrl.getLogger().Debug("Controller update time: ", time.Since(start)) } else { @@ -229,9 +234,7 @@ func (m *Manager) GetStatusModel() models.ControllerStatuses { // manager mutex quickly again controllers := controllerMap{} m.mutex.RLock() - for key, c := range m.controllers { - controllers[key] = c - } + maps.Copy(controllers, m.controllers) m.mutex.RUnlock() statuses := models.ControllerStatuses{} diff --git a/vendor/github.com/cilium/cilium/pkg/counter/counter.go b/vendor/github.com/cilium/cilium/pkg/counter/counter.go index 7b154ffe6c..7925dfa27f 100644 --- a/vendor/github.com/cilium/cilium/pkg/counter/counter.go +++ b/vendor/github.com/cilium/cilium/pkg/counter/counter.go @@ -3,6 +3,8 @@ package counter +import "maps" + // Counter tracks references for comparable . // // No thread safety is provided within this structure, the user is expected to @@ -31,9 +33,7 @@ func (c Counter[T]) Delete(key T) bool { // DeepCopy makes a new copy of the received Counter. func (c Counter[T]) DeepCopy() Counter[T] { result := make(Counter[T], len(c)) - for k, v := range c { - result[k] = v - } + maps.Copy(result, c) return result } diff --git a/vendor/github.com/cilium/cilium/pkg/crypto/certificatemanager/certificate_manager_mock.go b/vendor/github.com/cilium/cilium/pkg/crypto/certificatemanager/certificate_manager_mock.go new file mode 100644 index 0000000000..723dc21d3b --- /dev/null +++ b/vendor/github.com/cilium/cilium/pkg/crypto/certificatemanager/certificate_manager_mock.go @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package certificatemanager + +import ( + "context" + "errors" + + "github.com/cilium/cilium/pkg/policy/api" +) + +func NewMockSecretManagerInline() SecretManager { + return &mockSecretManager{ + inlineValue: "somevalue", + } +} + +func NewMockSecretManagerNotFound() SecretManager { + return &mockSecretManager{ + inlineError: errors.New("not found"), + } +} + +func NewMockSecretManagerSDS() SecretManager { + return &mockSecretManager{ + isSDS: true, + } +} + +type mockSecretManager struct { + inlineValue string + inlineError error + isSDS bool +} + +func (m mockSecretManager) GetSecretString(_ context.Context, secret *api.Secret, ns string) (string, error) { + return m.inlineValue, m.inlineError +} + +func (m mockSecretManager) PolicySecretSyncEnabled() bool { + return m.isSDS +} + +func (m mockSecretManager) SecretsOnlyFromSecretsNamespace() bool { + return m.isSDS +} + +func (m mockSecretManager) GetSecretSyncNamespace() string { + return "" +} diff --git a/vendor/github.com/cilium/cilium/pkg/debug/subsystem.go b/vendor/github.com/cilium/cilium/pkg/debug/subsystem.go index 62162e3648..9013cf1487 100644 --- a/vendor/github.com/cilium/cilium/pkg/debug/subsystem.go +++ b/vendor/github.com/cilium/cilium/pkg/debug/subsystem.go @@ -5,6 +5,7 @@ package debug import ( "fmt" + "maps" "github.com/cilium/cilium/pkg/lock" ) @@ -56,13 +57,9 @@ func (s *statusFunctions) registerStatusObject(name string, obj StatusObject) er } func (s *statusFunctions) collectStatus() StatusMap { - fnCopy := functionMap{} - // Make a copy to not hold the mutex while collecting the status s.mutex.RLock() - for name, fn := range s.functions { - fnCopy[name] = fn - } + fnCopy := maps.Clone(s.functions) s.mutex.RUnlock() status := StatusMap{} diff --git a/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go b/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go index 03d325e6c2..203340db39 100644 --- a/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go +++ b/vendor/github.com/cilium/cilium/pkg/defaults/defaults.go @@ -313,10 +313,6 @@ const ( // a kvstore path for too long. KVStoreStaleLockTimeout = 30 * time.Second - // KVstorePodNetworkSupport represents whether to enable the support for - // running the Cilium KVstore in pod network. - KVstorePodNetworkSupport = false - // KVstoreQPS is default rate limit for kv store operations KVstoreQPS = 20 @@ -414,6 +410,9 @@ const ( // per GC interval ENIGarbageCollectionMaxPerInterval = 25 + // ENIMaxResultsPerApiCall is the maximum number of ENI objects to fetch per DescribeNetworkInterfaces API call + ENIMaxResultsPerApiCall = 1000 + // ParallelAllocWorkers is the default max number of parallel workers doing allocation in the operator ParallelAllocWorkers = 50 diff --git a/vendor/github.com/cilium/cilium/pkg/envoy/policy/envoy_l7_rules_translator.go b/vendor/github.com/cilium/cilium/pkg/envoy/policy/envoy_l7_rules_translator.go new file mode 100644 index 0000000000..a8be568085 --- /dev/null +++ b/vendor/github.com/cilium/cilium/pkg/envoy/policy/envoy_l7_rules_translator.go @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package envoypolicy + +import ( + "context" + "fmt" + "log/slog" + "strings" + + cilium "github.com/cilium/proxy/go/cilium/api" + envoy_config_route "github.com/cilium/proxy/go/envoy/config/route/v3" + envoy_type_matcher "github.com/cilium/proxy/go/envoy/type/matcher/v3" + "k8s.io/apimachinery/pkg/types" + + "github.com/cilium/cilium/pkg/crypto/certificatemanager" + "github.com/cilium/cilium/pkg/logging/logfields" + policyapi "github.com/cilium/cilium/pkg/policy/api" +) + +type EnvoyL7RulesTranslator interface { + GetEnvoyHTTPRules(l7Rules *policyapi.L7Rules, ns string) (*cilium.HttpNetworkPolicyRules, bool) +} + +type envoyL7RulesTranslator struct { + logger *slog.Logger + secretManager certificatemanager.SecretManager +} + +func NewEnvoyL7RulesTranslator(logger *slog.Logger, secretManager certificatemanager.SecretManager) EnvoyL7RulesTranslator { + return &envoyL7RulesTranslator{ + logger: logger, + secretManager: secretManager, + } +} + +func (r *envoyL7RulesTranslator) GetEnvoyHTTPRules(l7Rules *policyapi.L7Rules, ns string) (*cilium.HttpNetworkPolicyRules, bool) { + if len(l7Rules.HTTP) > 0 { // Just cautious. This should never be false. + // Assume none of the rules have side-effects so that rule evaluation can + // be stopped as soon as the first allowing rule is found. 'canShortCircuit' + // is set to 'false' below if any rules with side effects are encountered, + // causing all the applicable rules to be evaluated instead. + canShortCircuit := true + httpRules := make([]*cilium.HttpNetworkPolicyRule, 0, len(l7Rules.HTTP)) + for _, l7 := range l7Rules.HTTP { + rule, cs := r.getHTTPRule(&l7, ns) + httpRules = append(httpRules, rule) + if !cs { + canShortCircuit = false + } + } + SortHTTPNetworkPolicyRules(httpRules) + return &cilium.HttpNetworkPolicyRules{ + HttpRules: httpRules, + }, canShortCircuit + } + + return nil, true +} + +func (r *envoyL7RulesTranslator) getHTTPRule(h *policyapi.PortRuleHTTP, ns string) (*cilium.HttpNetworkPolicyRule, bool) { + // Count the number of header matches we need + cnt := len(h.Headers) + len(h.HeaderMatches) + if h.Path != "" { + cnt++ + } + if h.Method != "" { + cnt++ + } + if h.Host != "" { + cnt++ + } + + headers := make([]*envoy_config_route.HeaderMatcher, 0, cnt) + if h.Path != "" { + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: ":path", + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_StringMatch{ + StringMatch: &envoy_type_matcher.StringMatcher{ + MatchPattern: &envoy_type_matcher.StringMatcher_SafeRegex{ + SafeRegex: &envoy_type_matcher.RegexMatcher{ + Regex: h.Path, + }, + }, + }, + }, + }) + } + if h.Method != "" { + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: ":method", + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_StringMatch{ + StringMatch: &envoy_type_matcher.StringMatcher{ + MatchPattern: &envoy_type_matcher.StringMatcher_SafeRegex{ + SafeRegex: &envoy_type_matcher.RegexMatcher{ + Regex: h.Method, + }, + }, + }, + }, + }) + } + if h.Host != "" { + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: ":authority", + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_StringMatch{ + StringMatch: &envoy_type_matcher.StringMatcher{ + MatchPattern: &envoy_type_matcher.StringMatcher_SafeRegex{ + SafeRegex: &envoy_type_matcher.RegexMatcher{ + Regex: h.Host, + }, + }, + }, + }, + }) + } + for _, hdr := range h.Headers { + strs := strings.SplitN(hdr, " ", 2) + if len(strs) == 2 { + // Remove ':' in "X-Key: true" + key := strings.TrimRight(strs[0], ":") + // Header presence and matching (literal) value needed. + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: key, + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_StringMatch{ + StringMatch: &envoy_type_matcher.StringMatcher{ + MatchPattern: &envoy_type_matcher.StringMatcher_Exact{ + Exact: strs[1], + }, + }, + }, + }) + } else { + // Only header presence needed + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: strs[0], + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_PresentMatch{PresentMatch: true}, + }) + } + } + + headerMatches := make([]*cilium.HeaderMatch, 0, len(h.HeaderMatches)) + for _, hdr := range h.HeaderMatches { + var mismatch_action cilium.HeaderMatch_MismatchAction + switch hdr.Mismatch { + case policyapi.MismatchActionLog: + mismatch_action = cilium.HeaderMatch_CONTINUE_ON_MISMATCH + case policyapi.MismatchActionAdd: + mismatch_action = cilium.HeaderMatch_ADD_ON_MISMATCH + case policyapi.MismatchActionDelete: + mismatch_action = cilium.HeaderMatch_DELETE_ON_MISMATCH + case policyapi.MismatchActionReplace: + mismatch_action = cilium.HeaderMatch_REPLACE_ON_MISMATCH + default: + mismatch_action = cilium.HeaderMatch_FAIL_ON_MISMATCH + } + // Fetch the secret + value, err := r.getSecretString(hdr, ns) + if err != nil { + r.logger.Warn("Failed fetching K8s Secret, header match will fail", logfields.Error, err) + // Envoy treats an empty exact match value as matching ANY value; adding + // InvertMatch: true here will cause this rule to NEVER match. + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: hdr.Name, + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_StringMatch{ + StringMatch: &envoy_type_matcher.StringMatcher{ + MatchPattern: &envoy_type_matcher.StringMatcher_Exact{ + Exact: "", + }, + }, + }, + InvertMatch: true, + }) + } else if value != "" { + // Inline value provided. + // Header presence and matching (literal) value needed. + if mismatch_action == cilium.HeaderMatch_FAIL_ON_MISMATCH { + // fail on mismatch gets converted for regular HeaderMatcher + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: hdr.Name, + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_StringMatch{ + StringMatch: &envoy_type_matcher.StringMatcher{ + MatchPattern: &envoy_type_matcher.StringMatcher_Exact{ + Exact: value, + }, + }, + }, + }) + } else { + r.logger.Debug("HeaderMatches: Adding header", logfields.Name, hdr.Name) + headerMatches = append(headerMatches, &cilium.HeaderMatch{ + MismatchAction: mismatch_action, + Name: hdr.Name, + Value: value, + }) + } + } else if hdr.Secret == nil { + // No inline value and no secret. + // Header presence for FAIL_ON_MISMSTCH or matching empty value otherwise needed. + if mismatch_action == cilium.HeaderMatch_FAIL_ON_MISMATCH { + // Only header presence needed + headers = append(headers, &envoy_config_route.HeaderMatcher{ + Name: hdr.Name, + HeaderMatchSpecifier: &envoy_config_route.HeaderMatcher_PresentMatch{PresentMatch: true}, + }) + } else { + r.logger.Debug("HeaderMatches: Adding header for an empty value", logfields.Name, hdr.Name) + headerMatches = append(headerMatches, &cilium.HeaderMatch{ + MismatchAction: mismatch_action, + Name: hdr.Name, + }) + } + } else { + // A secret is set, so we transform to an SDS value. + // cilium-envoy takes care of treating this as a presence match if the + // secret exists with an empty value. + r.logger.Debug("HeaderMatches: Adding header because SDS value is required", logfields.Name, hdr.Name) + headerMatches = append(headerMatches, &cilium.HeaderMatch{ + MismatchAction: mismatch_action, + Name: hdr.Name, + ValueSdsSecret: namespacedNametoSyncedSDSSecretName(types.NamespacedName{ + Namespace: hdr.Secret.Namespace, + Name: hdr.Secret.Name, + }, r.secretManager.GetSecretSyncNamespace()), + }) + } + } + if len(headers) == 0 { + headers = nil + } else { + SortHeaderMatchers(headers) + } + if len(headerMatches) == 0 { + headerMatches = nil + } else { + // Optimally we should sort the headerMatches to avoid + // updating the policy if only the order of the rules + // has changed. Right now, when 'headerMatches' is a + // slice (rather than a map) the order only changes if + // the order of the rules in the imported policies + // changes, so there is minimal likelihood of + // unnecessary policy updates. + + // SortHeaderMatches(headerMatches) + } + + return &cilium.HttpNetworkPolicyRule{Headers: headers, HeaderMatches: headerMatches}, len(headerMatches) == 0 +} + +func (r *envoyL7RulesTranslator) getSecretString(hdr *policyapi.HeaderMatch, ns string) (string, error) { + value := "" + var err error + if hdr.Secret != nil { + value, err = r.secretManager.GetSecretString(context.TODO(), hdr.Secret, ns) + } + // Only use Value if secret was not obtained + if value == "" && hdr.Value != "" { + value = hdr.Value + if err != nil { + r.logger.Debug("HeaderMatches: Using a default value due to k8s secret not being available", logfields.Error, err) + err = nil + } + } + + return value, err +} + +func namespacedNametoSyncedSDSSecretName(namespacedName types.NamespacedName, policySecretsNamespace string) string { + if policySecretsNamespace == "" { + return fmt.Sprintf("%s/%s", namespacedName.Namespace, namespacedName.Name) + } + return fmt.Sprintf("%s/%s-%s", policySecretsNamespace, namespacedName.Namespace, namespacedName.Name) +} diff --git a/vendor/github.com/cilium/cilium/pkg/envoy/policy/sort.go b/vendor/github.com/cilium/cilium/pkg/envoy/policy/sort.go new file mode 100644 index 0000000000..ae35fbe49d --- /dev/null +++ b/vendor/github.com/cilium/cilium/pkg/envoy/policy/sort.go @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package envoypolicy + +import ( + "sort" + + cilium "github.com/cilium/proxy/go/cilium/api" + envoy_config_route "github.com/cilium/proxy/go/envoy/config/route/v3" +) + +// PortNetworkPolicySlice implements sort.Interface to sort a slice of +// *cilium.PortNetworkPolicy. +type PortNetworkPolicySlice []*cilium.PortNetworkPolicy + +func (s PortNetworkPolicySlice) Len() int { + return len(s) +} + +func (s PortNetworkPolicySlice) Less(i, j int) bool { + p1, p2 := s[i], s[j] + + switch { + case p1.Protocol < p2.Protocol: + return true + case p1.Protocol > p2.Protocol: + return false + } + + switch { + case p1.Port < p2.Port: + return true + case p1.Port > p2.Port: + return false + } + + rules1, rules2 := p1.Rules, p2.Rules + switch { + case len(rules1) < len(rules2): + return true + case len(rules1) > len(rules2): + return false + } + // Assuming that the slices are sorted. + for idx := range rules1 { + r1, r2 := rules1[idx], rules2[idx] + switch { + case PortNetworkPolicyRuleLess(r1, r2): + return true + case PortNetworkPolicyRuleLess(r2, r1): + return false + } + } + + // Elements are equal. + return false +} + +func (s PortNetworkPolicySlice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// SortPortNetworkPolicies sorts the given slice in place and returns +// the sorted slice for convenience. +func SortPortNetworkPolicies(policies []*cilium.PortNetworkPolicy) []*cilium.PortNetworkPolicy { + sort.Sort(PortNetworkPolicySlice(policies)) + return policies +} + +// PortNetworkPolicyRuleSlice implements sort.Interface to sort a slice of +// *cilium.PortNetworkPolicyRuleSlice. +type PortNetworkPolicyRuleSlice []*cilium.PortNetworkPolicyRule + +// PortNetworkPolicyRuleLess reports whether the r1 rule should sort before +// the r2 rule. +// L3-L4-only rules are less than L7 rules. +func PortNetworkPolicyRuleLess(r1, r2 *cilium.PortNetworkPolicyRule) bool { + // TODO: Support Kafka. + + http1, http2 := r1.GetHttpRules(), r2.GetHttpRules() + switch { + case http1 == nil && http2 != nil: + return true + case http1 != nil && http2 == nil: + return false + } + + if http1 != nil && http2 != nil { + httpRules1, httpRules2 := http1.HttpRules, http2.HttpRules + switch { + case len(httpRules1) < len(httpRules2): + return true + case len(httpRules1) > len(httpRules2): + return false + } + // Assuming that the slices are sorted. + for idx := range httpRules1 { + httpRule1, httpRule2 := httpRules1[idx], httpRules2[idx] + switch { + case HTTPNetworkPolicyRuleLess(httpRule1, httpRule2): + return true + case HTTPNetworkPolicyRuleLess(httpRule2, httpRule1): + return false + } + } + } + + remotePolicies1, remotePolicies2 := r1.RemotePolicies, r2.RemotePolicies + switch { + case len(remotePolicies1) < len(remotePolicies2): + return true + case len(remotePolicies1) > len(remotePolicies2): + return false + } + // Assuming that the slices are sorted. + for idx := range remotePolicies1 { + p1, p2 := remotePolicies1[idx], remotePolicies2[idx] + switch { + case p1 < p2: + return true + case p1 > p2: + return false + } + } + + // Elements are equal. + return false +} + +func (s PortNetworkPolicyRuleSlice) Len() int { + return len(s) +} + +func (s PortNetworkPolicyRuleSlice) Less(i, j int) bool { + return PortNetworkPolicyRuleLess(s[i], s[j]) +} + +func (s PortNetworkPolicyRuleSlice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// SortPortNetworkPolicyRules sorts the given slice in place +// and returns the sorted slice for convenience. +func SortPortNetworkPolicyRules(rules []*cilium.PortNetworkPolicyRule) []*cilium.PortNetworkPolicyRule { + sort.Sort(PortNetworkPolicyRuleSlice(rules)) + return rules +} + +// HTTPNetworkPolicyRuleSlice implements sort.Interface to sort a slice of +// *cilium.HttpNetworkPolicyRule. +type HTTPNetworkPolicyRuleSlice []*cilium.HttpNetworkPolicyRule + +// HTTPNetworkPolicyRuleLess reports whether the r1 rule should sort before the +// r2 rule. +func HTTPNetworkPolicyRuleLess(r1, r2 *cilium.HttpNetworkPolicyRule) bool { + headers1, headers2 := r1.Headers, r2.Headers + switch { + case len(headers1) < len(headers2): + return true + case len(headers1) > len(headers2): + return false + } + // Assuming that the slices are sorted. + for idx := range headers1 { + header1, header2 := headers1[idx], headers2[idx] + switch { + case HeaderMatcherLess(header1, header2): + return true + case HeaderMatcherLess(header2, header1): + return false + } + } + + // Elements are equal. + return false +} + +func (s HTTPNetworkPolicyRuleSlice) Len() int { + return len(s) +} + +func (s HTTPNetworkPolicyRuleSlice) Less(i, j int) bool { + return HTTPNetworkPolicyRuleLess(s[i], s[j]) +} + +func (s HTTPNetworkPolicyRuleSlice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// SortHTTPNetworkPolicyRules sorts the given slice. +func SortHTTPNetworkPolicyRules(rules []*cilium.HttpNetworkPolicyRule) { + sort.Sort(HTTPNetworkPolicyRuleSlice(rules)) +} + +// HeaderMatcherSlice implements sort.Interface to sort a slice of +// *envoy_config_route.HeaderMatcher. +type HeaderMatcherSlice []*envoy_config_route.HeaderMatcher + +// HeaderMatcherLess reports whether the m1 matcher should sort before the m2 +// matcher. +func HeaderMatcherLess(m1, m2 *envoy_config_route.HeaderMatcher) bool { + switch { + case m1.Name < m2.Name: + return true + case m1.Name > m2.Name: + return false + } + + // Compare the header_match_specifier oneof field, by comparing each + // possible field in the oneof individually: + // - exactMatch + // - regexMatch + // - rangeMatch + // - presentMatch + // - prefixMatch + // - suffixMatch + // Use the getters to access the fields and return zero values when they + // are not set. + + s1 := m1.GetExactMatch() + s2 := m2.GetExactMatch() + switch { + case s1 < s2: + return true + case s1 > s2: + return false + } + + srm1 := m1.GetSafeRegexMatch() + srm2 := m2.GetSafeRegexMatch() + switch { + case srm1 == nil && srm2 != nil: + return true + case srm1 != nil && srm2 == nil: + return false + case srm1 != nil && srm2 != nil: + switch { + case srm1.Regex < srm2.Regex: + return true + case srm1.Regex > srm2.Regex: + return false + } + } + + rm1 := m1.GetRangeMatch() + rm2 := m2.GetRangeMatch() + switch { + case rm1 == nil && rm2 != nil: + return true + case rm1 != nil && rm2 == nil: + return false + case rm1 != nil && rm2 != nil: + switch { + case rm1.Start < rm2.Start: + return true + case rm1.Start > rm2.Start: + return false + } + switch { + case rm1.End < rm2.End: + return true + case rm1.End > rm2.End: + return false + } + } + + switch { + case !m1.GetPresentMatch() && m2.GetPresentMatch(): + return true + case m1.GetPresentMatch() && !m2.GetPresentMatch(): + return false + } + + s1 = m1.GetPrefixMatch() + s2 = m2.GetPrefixMatch() + switch { + case s1 < s2: + return true + case s1 > s2: + return false + } + + s1 = m1.GetSuffixMatch() + s2 = m2.GetSuffixMatch() + switch { + case s1 < s2: + return true + case s1 > s2: + return false + } + + switch { + case !m1.InvertMatch && m2.InvertMatch: + return true + case m1.InvertMatch && !m2.InvertMatch: + return false + } + + // Elements are equal. + return false +} + +func (s HeaderMatcherSlice) Len() int { + return len(s) +} + +func (s HeaderMatcherSlice) Less(i, j int) bool { + return HeaderMatcherLess(s[i], s[j]) +} + +func (s HeaderMatcherSlice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// SortHeaderMatchers sorts the given slice. +func SortHeaderMatchers(headers []*envoy_config_route.HeaderMatcher) { + sort.Sort(HeaderMatcherSlice(headers)) +} diff --git a/vendor/github.com/cilium/cilium/pkg/health/client/tree.go b/vendor/github.com/cilium/cilium/pkg/health/client/tree.go index febac0144a..28ab5e4315 100644 --- a/vendor/github.com/cilium/cilium/pkg/health/client/tree.go +++ b/vendor/github.com/cilium/cilium/pkg/health/client/tree.go @@ -7,6 +7,7 @@ import ( "bytes" "fmt" "io" + "slices" "sort" "strconv" "strings" @@ -177,13 +178,7 @@ func dumpVals(w io.Writer, level, maxLevel int, levelsEnded []int, edge decorati } func isEnded(levelsEnded []int, level int) bool { - for _, l := range levelsEnded { - if l == level { - return true - } - } - - return false + return slices.Contains(levelsEnded, level) } func dumpVal(level int, node *node) string { diff --git a/vendor/github.com/cilium/cilium/pkg/ip/ip.go b/vendor/github.com/cilium/cilium/pkg/ip/ip.go index 7f457f340c..23af4e44a7 100644 --- a/vendor/github.com/cilium/cilium/pkg/ip/ip.go +++ b/vendor/github.com/cilium/cilium/pkg/ip/ip.go @@ -132,7 +132,7 @@ func removeRedundantCIDRs(CIDRs []*net.IPNet) []*net.IPNet { if len(redundant) == 1 { for i := range redundant { - return append(CIDRs[:i], CIDRs[i+1:]...) + return slices.Delete(CIDRs, i, i+1) } } @@ -175,12 +175,12 @@ func RemoveCIDRs(allowCIDRs, removeCIDRs []*net.IPNet) []*net.IPNet { // Remove CIDR that we have just processed and append new CIDRs // that we computed from removing the CIDR to remove. - allowCIDRs = append(allowCIDRs[:i], allowCIDRs[i+1:]...) + allowCIDRs = slices.Delete(allowCIDRs, i, i+1) allowCIDRs = append(allowCIDRs, nets...) } else if remove.Contains(allowCIDR.IP.Mask(allowCIDR.Mask)) { // If a CIDR that we want to remove contains a CIDR in the list // that is allowed, then we can just remove the CIDR to allow. - allowCIDRs = append(allowCIDRs[:i], allowCIDRs[i+1:]...) + allowCIDRs = slices.Delete(allowCIDRs, i, i+1) } else { // Advance only if CIDR at index 'i' was not removed i++ @@ -500,7 +500,7 @@ func mergeAdjacentCIDRs(ranges []*netWithRange) []*netWithRange { // Since we have combined ranges[i] with the preceding item in the // ranges list, we can delete ranges[i] from the slice. - ranges = append(ranges[:i], ranges[i+1:]...) + ranges = slices.Delete(ranges, i, i+1) } } return ranges diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/annotate.go b/vendor/github.com/cilium/cilium/pkg/k8s/annotate.go index c6d072d225..46a18dd28b 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/annotate.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/annotate.go @@ -7,11 +7,11 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "reflect" "strconv" "strings" - "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sTypes "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" @@ -69,20 +69,21 @@ func updateNodeAnnotation(c kubernetes.Interface, nodeName string, annotation no // AnnotateNode writes v4 and v6 CIDRs and health IPs in the given k8s node name. // In case of failure while updating the node, this function while spawn a go // routine to retry the node update indefinitely. -func AnnotateNode(cs kubernetes.Interface, nodeName string, nd nodeTypes.Node, encryptKey uint8) (nodeAnnotation, error) { - scopedLog := log.WithFields(logrus.Fields{ - logfields.NodeName: nodeName, - logfields.V4Prefix: nd.IPv4AllocCIDR, - logfields.V6Prefix: nd.IPv6AllocCIDR, - logfields.V4HealthIP: nd.IPv4HealthIP, - logfields.V6HealthIP: nd.IPv6HealthIP, - logfields.V4IngressIP: nd.IPv4IngressIP, - logfields.V6IngressIP: nd.IPv6IngressIP, - logfields.V4CiliumHostIP: nd.GetCiliumInternalIP(false), - logfields.V6CiliumHostIP: nd.GetCiliumInternalIP(true), - logfields.Key: encryptKey, - }) +func AnnotateNode(logger *slog.Logger, cs kubernetes.Interface, nodeName string, nd nodeTypes.Node, encryptKey uint8) (nodeAnnotation, error) { + scopedLog := logger.With( + logfields.NodeName, nodeName, + logfields.V4Prefix, nd.IPv4AllocCIDR, + logfields.V6Prefix, nd.IPv6AllocCIDR, + logfields.V4HealthIP, nd.IPv4HealthIP, + logfields.V6HealthIP, nd.IPv6HealthIP, + logfields.V4IngressIP, nd.IPv4IngressIP, + logfields.V6IngressIP, nd.IPv6IngressIP, + logfields.V4CiliumHostIP, nd.GetCiliumInternalIP(false), + logfields.V6CiliumHostIP, nd.GetCiliumInternalIP(true), + logfields.Key, encryptKey, + ) scopedLog.Debug("Updating node annotations with node CIDRs") + annotation := prepareNodeAnnotation(nd, encryptKey) controller.NewManager().UpdateController("update-k8s-node-annotations", controller.ControllerParams{ @@ -90,7 +91,7 @@ func AnnotateNode(cs kubernetes.Interface, nodeName string, nd nodeTypes.Node, e DoFunc: func(_ context.Context) error { err := updateNodeAnnotation(cs, nodeName, annotation) if err != nil { - scopedLog.WithFields(logrus.Fields{}).WithError(err).Warn("Unable to patch node resource with annotation") + scopedLog.Warn("Unable to patch node resource with annotation", logfields.Error, err) } return err }, diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/register.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/register.go index 0d015cab95..710a840001 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/register.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/register.go @@ -15,5 +15,5 @@ const ( // // Maintainers: Run ./Documentation/check-crd-compat-table.sh for each release // Developers: Bump patch for each change in the CRD schema. - CustomResourceDefinitionSchemaVersion = "1.31.3" + CustomResourceDefinitionSchemaVersion = "1.31.4" ) diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/utils/utils.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/utils/utils.go index 90227aa005..611eedcb73 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/utils/utils.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/utils/utils.go @@ -4,20 +4,18 @@ package utils import ( - "github.com/sirupsen/logrus" + "log/slog" + "k8s.io/apimachinery/pkg/types" k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io" slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" "github.com/cilium/cilium/pkg/labels" - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/policy/api" ) const ( - // subsysK8s is the value for logfields.LogSubsys - subsysK8s = "k8s" // podPrefixLbl is the value the prefix used in the label selector to // represent pods on the default namespace. podPrefixLbl = labels.LabelSourceK8sKeyPrefix + k8sConst.PodNamespaceLabel @@ -45,11 +43,6 @@ const ( ResourceTypeCiliumClusterwideNetworkPolicy = "CiliumClusterwideNetworkPolicy" ) -var ( - // log is the k8s package logger object. - log = logging.DefaultLogger.WithField(logfields.LogSubsys, subsysK8s) -) - // GetPolicyLabels returns a LabelArray for the given namespace and name. func GetPolicyLabels(ns, name string, uid types.UID, derivedFrom string) labels.LabelArray { // Keep labels sorted by the key. @@ -326,7 +319,7 @@ func namespacesAreValid(namespace string, userNamespaces []string) bool { // labels. If the namespace provided is empty then the rule is cluster scoped, this // might happen in case of CiliumClusterwideNetworkPolicy which enforces a policy on the cluster // instead of the particular namespace. -func ParseToCiliumRule(namespace, name string, uid types.UID, r *api.Rule) *api.Rule { +func ParseToCiliumRule(logger *slog.Logger, namespace, name string, uid types.UID, r *api.Rule) *api.Rule { retRule := &api.Rule{} if r.EndpointSelector.LabelSelector != nil { retRule.EndpointSelector = api.NewESFromK8sLabelSelector("", r.EndpointSelector.LabelSelector) @@ -343,12 +336,12 @@ func ParseToCiliumRule(namespace, name string, uid types.UID, r *api.Rule) *api. if namespace != "" { userNamespace, present := r.EndpointSelector.GetMatch(podPrefixLbl) if present && !namespacesAreValid(namespace, userNamespace) { - log.WithFields(logrus.Fields{ - logfields.K8sNamespace: namespace, - logfields.CiliumNetworkPolicyName: name, - logfields.K8sNamespace + ".illegal": userNamespace, - }).Warn("CiliumNetworkPolicy contains illegal namespace match in EndpointSelector." + - " EndpointSelector always applies in namespace of the policy resource, removing illegal namespace match'.") + logger.Warn("CiliumNetworkPolicy contains illegal namespace match in EndpointSelector."+ + " EndpointSelector always applies in namespace of the policy resource, removing illegal namespace match'.", + logfields.K8sNamespace, namespace, + logfields.CiliumNetworkPolicyName, name, + logfields.K8sNamespaceIllegal, userNamespace, + ) } retRule.EndpointSelector.AddMatch(podPrefixLbl, namespace) } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/bgp_advert_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/bgp_advert_types.go index 8be0ae1209..3711b4e7b4 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/bgp_advert_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/bgp_advert_types.go @@ -127,6 +127,16 @@ type BGPAdvertisement struct { // BGPServiceOptions defines the configuration for Service advertisement type. type BGPServiceOptions struct { + // IPv4 mask to aggregate BGP route advertisements of service + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=31 + // +kubebuilder:validation:Optional + AggregationLengthIPv4 *int16 `json:"aggregationLengthIPv4,omitempty"` + // IPv6 mask to aggregate BGP route advertisements of service + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=127 + // +kubebuilder:validation:Optional + AggregationLengthIPv6 *int16 `json:"aggregationLengthIPv6,omitempty"` // Addresses is a list of service address types which needs to be advertised via BGP. // // +kubebuilder:validation:Required diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go index dd563f079f..9059252a47 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/ccnp_types.go @@ -5,6 +5,7 @@ package v2 import ( "fmt" + "log/slog" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -77,7 +78,7 @@ type CiliumClusterwideNetworkPolicyList struct { // Parse parses a CiliumClusterwideNetworkPolicy and returns a list of cilium // policy rules. -func (r *CiliumClusterwideNetworkPolicy) Parse() (api.Rules, error) { +func (r *CiliumClusterwideNetworkPolicy) Parse(logger *slog.Logger) (api.Rules, error) { if r.ObjectMeta.Name == "" { return nil, NewErrParse("CiliumClusterwideNetworkPolicy must have name") } @@ -95,7 +96,7 @@ func (r *CiliumClusterwideNetworkPolicy) Parse() (api.Rules, error) { if err := r.Spec.Sanitize(); err != nil { return nil, NewErrParse(fmt.Sprintf("Invalid CiliumClusterwideNetworkPolicy spec: %s", err)) } - cr := k8sCiliumUtils.ParseToCiliumRule("", name, uid, r.Spec) + cr := k8sCiliumUtils.ParseToCiliumRule(logger, "", name, uid, r.Spec) retRules = append(retRules, cr) } if r.Specs != nil { @@ -104,7 +105,7 @@ func (r *CiliumClusterwideNetworkPolicy) Parse() (api.Rules, error) { return nil, NewErrParse(fmt.Sprintf("Invalid CiliumClusterwideNetworkPolicy specs: %s", err)) } - cr := k8sCiliumUtils.ParseToCiliumRule("", name, uid, rule) + cr := k8sCiliumUtils.ParseToCiliumRule(logger, "", name, uid, rule) retRules = append(retRules, cr) } } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cec_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cec_types.go index e672fbb31b..e5e1ef2c61 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cec_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cec_types.go @@ -16,6 +16,8 @@ import ( slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" "github.com/cilium/cilium/pkg/loadbalancer" + "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/option" ) @@ -185,10 +187,12 @@ func (u *XDSResource) UnmarshalJSON(b []byte) (err error) { if err != nil { var buf bytes.Buffer json.Indent(&buf, b, "", "\t") - log.Warningf("Ignoring invalid CiliumEnvoyConfig JSON (%s): %s", - err, buf.String()) + logging.DefaultSlogLogger.Warn("Ignoring invalid CiliumEnvoyConfig JSON", + logfields.Error, err, + logfields.Object, buf, + ) } else if option.Config.Debug { - log.Debugf("CEC unmarshaled XDS Resource: %v", prototext.Format(u.Any)) + logging.DefaultSlogLogger.Debug("CEC unmarshaled XDS Resource", logfields.Resource, prototext.Format(u.Any)) } return nil } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go index 27c2667f36..0ad09fa280 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/cnp_types.go @@ -5,6 +5,7 @@ package v2 import ( "fmt" + "log/slog" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -159,7 +160,7 @@ func (r *CiliumNetworkPolicy) SetDerivedPolicyStatus(derivativePolicyName string // Parse parses a CiliumNetworkPolicy and returns a list of cilium policy // rules. -func (r *CiliumNetworkPolicy) Parse() (api.Rules, error) { +func (r *CiliumNetworkPolicy) Parse(logger *slog.Logger) (api.Rules, error) { if r.ObjectMeta.Name == "" { return nil, NewErrParse("CiliumNetworkPolicy must have name") } @@ -176,7 +177,7 @@ func (r *CiliumNetworkPolicy) Parse() (api.Rules, error) { Specs: r.Specs, Status: r.Status, } - return ccnp.Parse() + return ccnp.Parse(logger) } name := r.ObjectMeta.Name uid := r.ObjectMeta.UID @@ -194,7 +195,7 @@ func (r *CiliumNetworkPolicy) Parse() (api.Rules, error) { if r.Spec.NodeSelector.LabelSelector != nil { return nil, NewErrParse("Invalid CiliumNetworkPolicy spec: rule cannot have NodeSelector") } - cr := k8sCiliumUtils.ParseToCiliumRule(namespace, name, uid, r.Spec) + cr := k8sCiliumUtils.ParseToCiliumRule(logger, namespace, name, uid, r.Spec) retRules = append(retRules, cr) } if r.Specs != nil { @@ -203,7 +204,7 @@ func (r *CiliumNetworkPolicy) Parse() (api.Rules, error) { return nil, NewErrParse(fmt.Sprintf("Invalid CiliumNetworkPolicy specs: %s", err)) } - cr := k8sCiliumUtils.ParseToCiliumRule(namespace, name, uid, rule) + cr := k8sCiliumUtils.ParseToCiliumRule(logger, namespace, name, uid, rule) retRules = append(retRules, cr) } } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/logfields.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/logfields.go deleted file mode 100644 index b4f5563730..0000000000 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/logfields.go +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package v2 - -import ( - "github.com/cilium/cilium/pkg/logging" - "github.com/cilium/cilium/pkg/logging/logfields" -) - -var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "k8s-apis-cilium.io-v2") diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepcopy.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepcopy.go index 87ccf9652c..cf67c096c1 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepcopy.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepcopy.go @@ -133,6 +133,16 @@ func (in *BGPFamilyRouteCount) DeepCopy() *BGPFamilyRouteCount { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BGPServiceOptions) DeepCopyInto(out *BGPServiceOptions) { *out = *in + if in.AggregationLengthIPv4 != nil { + in, out := &in.AggregationLengthIPv4, &out.AggregationLengthIPv4 + *out = new(int16) + **out = **in + } + if in.AggregationLengthIPv6 != nil { + in, out := &in.AggregationLengthIPv6, &out.AggregationLengthIPv6 + *out = new(int16) + **out = **in + } if in.Addresses != nil { in, out := &in.Addresses, &out.Addresses *out = make([]BGPServiceAddressType, len(*in)) diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepequal.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepequal.go index 17b526dc60..3459656914 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepequal.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2/zz_generated.deepequal.go @@ -228,6 +228,22 @@ func (in *BGPServiceOptions) DeepEqual(other *BGPServiceOptions) bool { return false } + if (in.AggregationLengthIPv4 == nil) != (other.AggregationLengthIPv4 == nil) { + return false + } else if in.AggregationLengthIPv4 != nil { + if *in.AggregationLengthIPv4 != *other.AggregationLengthIPv4 { + return false + } + } + + if (in.AggregationLengthIPv6 == nil) != (other.AggregationLengthIPv6 == nil) { + return false + } else if in.AggregationLengthIPv6 != nil { + if *in.AggregationLengthIPv6 != *other.AggregationLengthIPv6 { + return false + } + } + if ((in.Addresses != nil) && (other.Addresses != nil)) || ((in.Addresses == nil) != (other.Addresses == nil)) { in, other := &in.Addresses, &other.Addresses if other == nil { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_advert_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_advert_types.go index fc5e508336..822ba6f5ce 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_advert_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_advert_types.go @@ -62,6 +62,7 @@ const ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +kubebuilder:resource:categories={cilium,ciliumbgp},singular="ciliumbgpadvertisement",path="ciliumbgpadvertisements",scope="Cluster",shortName={cbgpadvert} // +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name="Age",type=date +// +kubebuilder:deprecatedversion // CiliumBGPAdvertisement is the Schema for the ciliumbgpadvertisements API type CiliumBGPAdvertisement struct { @@ -121,6 +122,16 @@ type BGPAdvertisement struct { // BGPServiceOptions defines the configuration for Service advertisement type. type BGPServiceOptions struct { + // IPv4 mask to aggregate BGP route advertisements of service + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=31 + // +kubebuilder:validation:Optional + AggregationLengthIPv4 *int16 `json:"aggregationLengthIPv4,omitempty"` + // IPv6 mask to aggregate BGP route advertisements of service + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=127 + // +kubebuilder:validation:Optional + AggregationLengthIPv6 *int16 `json:"aggregationLengthIPv6,omitempty"` // Addresses is a list of service address types which needs to be advertised via BGP. // // +kubebuilder:validation:Required diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_cluster_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_cluster_types.go index fee94679fc..bc94c1ab4b 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_cluster_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_cluster_types.go @@ -15,6 +15,7 @@ import ( // +kubebuilder:resource:categories={cilium,ciliumbgp},singular="ciliumbgpclusterconfig",path="ciliumbgpclusterconfigs",scope="Cluster",shortName={cbgpcluster} // +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name="Age",type=date // +kubebuilder:subresource:status +// +kubebuilder:deprecatedversion // CiliumBGPClusterConfig is the Schema for the CiliumBGPClusterConfig API type CiliumBGPClusterConfig struct { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_override_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_override_types.go index 6ba6b00f3d..e7f208c07b 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_override_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_override_types.go @@ -12,6 +12,7 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +kubebuilder:resource:categories={cilium,ciliumbgp},singular="ciliumbgpnodeconfigoverride",path="ciliumbgpnodeconfigoverrides",scope="Cluster",shortName={cbgpnodeoverride} // +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name="Age",type=date +// +kubebuilder:deprecatedversion // CiliumBGPNodeConfigOverride specifies configuration overrides for a CiliumBGPNodeConfig. // It allows fine-tuning of BGP behavior on a per-node basis. For the override to be effective, diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_types.go index 1b5abad121..a9e1d7e9e0 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_node_types.go @@ -13,6 +13,7 @@ import ( // +kubebuilder:resource:categories={cilium,ciliumbgp},singular="ciliumbgpnodeconfig",path="ciliumbgpnodeconfigs",scope="Cluster",shortName={cbgpnode} // +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name="Age",type=date // +kubebuilder:subresource:status +// +kubebuilder:deprecatedversion // CiliumBGPNodeConfig is node local configuration for BGP agent. Name of the object should be node name. // This resource will be created by Cilium operator and is read-only for the users. diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_peer_types.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_peer_types.go index 2108722234..e37aee2596 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_peer_types.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/bgp_peer_types.go @@ -29,6 +29,7 @@ type CiliumBGPPeerConfigList struct { // +kubebuilder:resource:categories={cilium,ciliumbgp},singular="ciliumbgppeerconfig",path="ciliumbgppeerconfigs",scope="Cluster",shortName={cbgppeer} // +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name="Age",type=date // +kubebuilder:subresource:status +// +kubebuilder:deprecatedversion type CiliumBGPPeerConfig struct { // +deepequal-gen=false diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepcopy.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepcopy.go index a940e26c2e..3f06ff505d 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepcopy.go @@ -135,6 +135,16 @@ func (in *BGPFamilyRouteCount) DeepCopy() *BGPFamilyRouteCount { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BGPServiceOptions) DeepCopyInto(out *BGPServiceOptions) { *out = *in + if in.AggregationLengthIPv4 != nil { + in, out := &in.AggregationLengthIPv4, &out.AggregationLengthIPv4 + *out = new(int16) + **out = **in + } + if in.AggregationLengthIPv6 != nil { + in, out := &in.AggregationLengthIPv6, &out.AggregationLengthIPv6 + *out = new(int16) + **out = **in + } if in.Addresses != nil { in, out := &in.Addresses, &out.Addresses *out = make([]BGPServiceAddressType, len(*in)) diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepequal.go b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepequal.go index 8be7566a97..226239125a 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepequal.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1/zz_generated.deepequal.go @@ -171,6 +171,22 @@ func (in *BGPServiceOptions) DeepEqual(other *BGPServiceOptions) bool { return false } + if (in.AggregationLengthIPv4 == nil) != (other.AggregationLengthIPv4 == nil) { + return false + } else if in.AggregationLengthIPv4 != nil { + if *in.AggregationLengthIPv4 != *other.AggregationLengthIPv4 { + return false + } + } + + if (in.AggregationLengthIPv6 == nil) != (other.AggregationLengthIPv6 == nil) { + return false + } else if in.AggregationLengthIPv6 != nil { + if *in.AggregationLengthIPv6 != *other.AggregationLengthIPv6 { + return false + } + } + if ((in.Addresses != nil) && (other.Addresses != nil)) || ((in.Addresses == nil) != (other.Addresses == nil)) { in, other := &in.Addresses, &other.Addresses if other == nil { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/client/cell.go b/vendor/github.com/cilium/cilium/pkg/k8s/client/cell.go index c0f5dd96ed..b6e3cbe366 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/client/cell.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/client/cell.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "log/slog" "net" "net/http" "os" @@ -15,7 +16,6 @@ import ( "github.com/cilium/hive/cell" "github.com/cilium/hive/job" - "github.com/sirupsen/logrus" apiext_clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -121,28 +121,28 @@ type compositeClientset struct { controller *controller.Manager slim *SlimClientset config Config - log logrus.FieldLogger + logger *slog.Logger closeAllConns func() restConfigManager restConfig } -func newClientset(lc cell.Lifecycle, log logrus.FieldLogger, cfg Config, jobs job.Group) (Clientset, error) { - return newClientsetForUserAgent(lc, log, cfg, "", jobs) +func newClientset(lc cell.Lifecycle, logger *slog.Logger, cfg Config, jobs job.Group) (Clientset, error) { + return newClientsetForUserAgent(lc, logger, cfg, "", jobs) } -func newClientsetForUserAgent(lc cell.Lifecycle, log logrus.FieldLogger, cfg Config, name string, jobs job.Group) (Clientset, error) { +func newClientsetForUserAgent(lc cell.Lifecycle, logger *slog.Logger, cfg Config, name string, jobs job.Group) (Clientset, error) { if !cfg.isEnabled() { return &compositeClientset{disabled: true}, nil } client := compositeClientset{ - log: log, + logger: logger, controller: controller.NewManager(), config: cfg, } var err error - client.restConfigManager, err = restConfigManagerInit(cfg, name, log, jobs) + client.restConfigManager, err = restConfigManagerInit(cfg, name, logger, jobs) if err != nil { return nil, fmt.Errorf("unable to create k8s client rest configuration: %w", err) } @@ -243,7 +243,7 @@ func (c *compositeClientset) onStart(startCtx cell.HookContext) error { c.startHeartbeat() // Update the global K8s clients, K8s version and the capabilities. - if err := k8sversion.Update(c, c.config.EnableK8sAPIDiscovery); err != nil { + if err := k8sversion.Update(c.logger, c, c.config.EnableK8sAPIDiscovery); err != nil { return err } @@ -295,7 +295,7 @@ func (c *compositeClientset) startHeartbeat() { Group: k8sHeartbeatControllerGroup, DoFunc: func(context.Context) error { runHeartbeat( - c.log, + c.logger, heartBeat, timeout, c.closeAllConns, @@ -314,7 +314,9 @@ func (c *compositeClientset) waitForConn(ctx context.Context) error { var err error wait.Until(func() { retry: - c.log.WithField("host", c.restConfigManager.getConfig().Host).Info("Establishing connection to apiserver") + c.logger.Info("Establishing connection to apiserver", + logfields.IPAddr, c.restConfigManager.getConfig().Host, + ) err = isConnReady(c) if err == nil { close(stop) @@ -332,11 +334,14 @@ func (c *compositeClientset) waitForConn(ctx context.Context) error { return } - c.log.WithError(err).WithField(logfields.IPAddr, c.restConfigManager.getConfig().Host).Error("Unable to contact k8s api-server") + c.logger.Error("Unable to contact k8s api-server", + logfields.IPAddr, c.restConfigManager.getConfig().Host, + logfields.Error, err, + ) close(stop) }, connRetryInterval, stop) if err == nil { - c.log.Info("Connected to apiserver") + c.logger.Info("Connected to apiserver") } return err } @@ -354,7 +359,7 @@ func setDialer(cfg Config, restConfig *rest.Config) func() { return dialer.CloseAll } -func runHeartbeat(log logrus.FieldLogger, heartBeat func(context.Context) error, timeout time.Duration, onFailure ...func()) { +func runHeartbeat(logger *slog.Logger, heartBeat func(context.Context) error, timeout time.Duration, onFailure ...func()) { expireDate := time.Now().Add(-timeout) // Don't even perform a health check if we have received a successful // k8s event in the last 'timeout' duration @@ -385,13 +390,13 @@ func runHeartbeat(log logrus.FieldLogger, heartBeat func(context.Context) error, select { case err := <-done: if err != nil { - log.WithError(err).Warn("Network status error received, restarting client connections") + logger.Warn("Network status error received, restarting client connections", logfields.Error, err) for _, fn := range onFailure { fn() } } case <-ctx.Done(): - log.Warn("Heartbeat timed out, restarting client connections") + logger.Warn("Heartbeat timed out, restarting client connections") for _, fn := range onFailure { fn() } @@ -414,9 +419,9 @@ type ClientBuilderFunc func(name string) (Clientset, error) // NewClientBuilder returns a function that creates a new Clientset with the given // name appended to the user agent, or returns an error if the Clientset cannot be // created. -func NewClientBuilder(lc cell.Lifecycle, log logrus.FieldLogger, cfg Config, jobs job.Group) ClientBuilderFunc { +func NewClientBuilder(lc cell.Lifecycle, logger *slog.Logger, cfg Config, jobs job.Group) ClientBuilderFunc { return func(name string) (Clientset, error) { - c, err := newClientsetForUserAgent(lc, log, cfg, name, jobs) + c, err := newClientsetForUserAgent(lc, logger, cfg, name, jobs) if err != nil { return nil, err } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/client/restConfig_provider.go b/vendor/github.com/cilium/cilium/pkg/k8s/client/restConfig_provider.go index 4fc7c0825d..2dfbf4689b 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/client/restConfig_provider.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/client/restConfig_provider.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "log/slog" "math/rand/v2" "net/http" "net/url" @@ -18,7 +19,6 @@ import ( "github.com/cilium/hive/cell" "github.com/cilium/hive/job" "github.com/fsnotify/fsnotify" - "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -26,7 +26,6 @@ import ( "github.com/cilium/cilium/pkg/fswatcher" "github.com/cilium/cilium/pkg/lock" - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/option" "github.com/cilium/cilium/pkg/time" @@ -34,8 +33,6 @@ import ( ) var ( - log = logging.DefaultLogger.WithField(logfields.LogSubsys, "k8s-client") - // K8sAPIServerFilePath is the file path for storing kube-apiserver service and // endpoints for high availability failover. K8sAPIServerFilePath = filepath.Join(option.Config.StateDir, "k8sapi_server_state.json") @@ -69,7 +66,7 @@ type restConfigManager struct { apiServerURLs []*url.URL isConnectedToService bool lock.RWMutex - log logrus.FieldLogger + log *slog.Logger rt *rotatingHttpRoundTripper jobs job.Group } @@ -82,7 +79,7 @@ type restConfig interface { // UpdateK8sAPIServerEntry writes the provided kubernetes service to endpoint mapping // to K8sAPIServerFilePath. -func UpdateK8sAPIServerEntry(mapping K8sServiceEndpointMapping) { +func UpdateK8sAPIServerEntry(logger *slog.Logger, mapping K8sServiceEndpointMapping) { f, err := os.OpenFile(K8sAPIServerFilePath, os.O_RDWR, 0644) if err != nil { return @@ -90,8 +87,11 @@ func UpdateK8sAPIServerEntry(mapping K8sServiceEndpointMapping) { defer f.Close() if err = json.NewEncoder(f).Encode(mapping); err != nil { - log.WithError(err).WithField("entry", mapping).Error("failed to write kubernetes service entry," + - "agent may not be able to fail over to an active k8sapi-server") + logger.Error("failed to write kubernetes service entry,"+ + "agent may not be able to fail over to an active k8sapi-server", + logfields.Error, err, + logfields.Entry, mapping, + ) } } @@ -113,7 +113,7 @@ func (r *restConfigManager) canRotateAPIServerURL() bool { return len(r.apiServerURLs) > 1 && !r.isConnectedToService } -func restConfigManagerInit(cfg Config, name string, log logrus.FieldLogger, jobs job.Group) (restConfig, error) { +func restConfigManagerInit(cfg Config, name string, log *slog.Logger, jobs job.Group) (restConfig, error) { var err error manager := restConfigManager{ log: log, @@ -211,7 +211,10 @@ func (r *restConfigManager) parseConfig(cfg Config) { } serverURL, err = url.Parse(s) if err != nil { - r.log.WithError(err).Errorf("Failed to parse APIServerURL %s, skipping", serverURL) + r.log.Error("Failed to parse APIServerURL, skipping", + logfields.Error, err, + logfields.URL, serverURL, + ) return } r.apiServerURLs = append(r.apiServerURLs, serverURL) @@ -228,7 +231,10 @@ func (r *restConfigManager) parseConfig(cfg Config) { serverURL, err := url.Parse(apiServerURL) if err != nil { - r.log.WithError(err).Errorf("Failed to parse APIServerURL %s, skipping", apiServerURL) + r.log.Error("Failed to parse APIServerURL, skipping", + logfields.Error, err, + logfields.URL, apiServerURL, + ) continue } @@ -265,13 +271,15 @@ func (r *restConfigManager) rotateAPIServerURL() { r.Lock() r.restConfig.Host = r.rt.apiServerURL.String() r.Unlock() - r.log.WithField("url", r.rt.apiServerURL).Info("Rotated api server") + r.log.Info("Rotated api server", + logfields.URL, r.rt.apiServerURL, + ) } // rotatingHttpRoundTripper sets the remote host in the rest configuration used to make API requests to the API server. type rotatingHttpRoundTripper struct { delegate http.RoundTripper - log logrus.FieldLogger + log *slog.Logger apiServerURL *url.URL lock.RWMutex // Synchronizes access to apiServerURL } @@ -280,7 +288,9 @@ func (rt *rotatingHttpRoundTripper) RoundTrip(req *http.Request) (*http.Response rt.RLock() defer rt.RUnlock() - rt.log.WithField("host", rt.apiServerURL).Debug("Kubernetes api server host") + rt.log.Debug("Kubernetes api server host", + logfields.URL, rt.apiServerURL, + ) req.URL.Host = rt.apiServerURL.Host return rt.delegate.RoundTrip(req) } @@ -344,11 +354,16 @@ func (r *restConfigManager) k8sAPIServerFileWatcher(ctx context.Context, watcher if !event.Op.Has(fsnotify.Write) { continue } - r.log.WithField("file", K8sAPIServerFilePath).Info("Processing write event ") + r.log.Info("Processing write event", + logfields.Path, K8sAPIServerFilePath, + ) r.updateK8sAPIServerURL() case err := <-watcher.Errors: health.Degraded(fmt.Sprintf("Failed to load %q", K8sAPIServerFilePath), err) - r.log.WithField("file", K8sAPIServerFilePath).WithError(err).Error("Unexpected error while watching") + r.log.Error("Unexpected error while watching", + logfields.Path, K8sAPIServerFilePath, + logfields.Error, err, + ) } } @@ -357,23 +372,29 @@ func (r *restConfigManager) k8sAPIServerFileWatcher(ctx context.Context, watcher func (r *restConfigManager) updateK8sAPIServerURL() { f, err := os.Open(K8sAPIServerFilePath) if err != nil { - r.log.WithError(err).WithField(logfields.Path, K8sAPIServerFilePath).Error("unable " + - "to open file, agent may not be able to fail over to an active kube-apiserver") + r.log.Error("unable "+ + "to open file, agent may not be able to fail over to an active kube-apiserver", + logfields.Path, K8sAPIServerFilePath, + logfields.Error, err, + ) } defer f.Close() var mapping K8sServiceEndpointMapping if err = json.NewDecoder(f).Decode(&mapping); err != nil { - r.log.WithError(err).WithFields(logrus.Fields{ - logfields.Path: K8sAPIServerFilePath, - "entry": mapping, - }).Error("failed to " + - "decode file entry, agent may not be able to fail over to an active kube-apiserver") + r.log.Error("failed to "+ + "decode file entry, agent may not be able to fail over to an active kube-apiserver", + logfields.Error, err, + logfields.Path, K8sAPIServerFilePath, + logfields.Entry, mapping, + ) } if err = r.checkConnToService(mapping.Service); err != nil { return } - r.log.WithField("host", mapping.Service).Info("Updated kubeapi server url host") + r.log.Info("Updated kubeapi server url host", + logfields.URL, mapping.Service, + ) // Set in tests mapping.Service = strings.TrimPrefix(mapping.Service, "http://") r.rt.Lock() @@ -388,7 +409,10 @@ func (r *restConfigManager) updateK8sAPIServerURL() { endpoint = fmt.Sprintf("https://%s", endpoint) serverURL, err := url.Parse(endpoint) if err != nil { - r.log.WithError(err).Errorf("Failed to parse endpoint %s, skipping", endpoint) + r.log.Info("Failed to parse endpoint, skipping", + logfields.Endpoint, endpoint, + logfields.Error, err, + ) continue } updatedServerURLs = append(updatedServerURLs, serverURL) @@ -415,13 +439,17 @@ func (r *restConfigManager) checkConnToService(host string) error { hostURL := fmt.Sprintf("https://%s", host) config, err = rest.InClusterConfig() if err != nil { - log.WithError(err).Error("unable to read cluster config") + r.log.Error("unable to read cluster config", + logfields.Error, err, + ) return err } config.Host = hostURL } wait.Until(func() { - r.log.WithField(logfields.Address, config.Host).Info("Checking connection to kubeapi service") + r.log.Info("Checking connection to kubeapi service", + logfields.Address, config.Host, + ) httpClient, _ := rest.HTTPClientFor(config) cs, _ := kubernetes.NewForConfigAndClient(config, httpClient) @@ -436,11 +464,16 @@ func (r *restConfigManager) checkConnToService(host string) error { return } - r.log.WithError(err).WithField(logfields.Address, config.Host).Error("kubeapi service not ready yet") + r.log.Error("kubeapi service not ready yet", + logfields.Address, config.Host, + logfields.Error, err, + ) close(stop) }, connRetryInterval, stop) if err == nil { - r.log.WithField(logfields.Address, config.Host).Info("Connected to kubeapi service") + r.log.Info("Connected to kubeapi service", + logfields.Address, config.Host, + ) } return err } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/endpoints.go b/vendor/github.com/cilium/cilium/pkg/k8s/endpoints.go index 9d25add5b8..f6d24ce150 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/endpoints.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/endpoints.go @@ -5,6 +5,7 @@ package k8s import ( "fmt" + "log/slog" "net" "net/netip" "slices" @@ -20,6 +21,7 @@ import ( slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" "github.com/cilium/cilium/pkg/k8s/types" "github.com/cilium/cilium/pkg/loadbalancer" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/metrics" "github.com/cilium/cilium/pkg/option" serviceStore "github.com/cilium/cilium/pkg/service/store" @@ -311,7 +313,7 @@ func parseEndpointPortV1Beta1(port slim_discovery_v1beta1.EndpointPort) (string, // ParseEndpointSliceV1 parses a Kubernetes EndpointSlice resource. // It reads ready and terminating state of endpoints in the EndpointSlice to // return an EndpointSlice ID and a filtered list of Endpoints for service load-balancing. -func ParseEndpointSliceV1(ep *slim_discovery_v1.EndpointSlice) *Endpoints { +func ParseEndpointSliceV1(logger *slog.Logger, ep *slim_discovery_v1.EndpointSlice) *Endpoints { endpoints := newEndpoints() endpoints.ObjectMeta = ep.ObjectMeta endpoints.EndpointSliceID = ParseEndpointSliceID(ep) @@ -322,7 +324,10 @@ func ParseEndpointSliceV1(ep *slim_discovery_v1.EndpointSlice) *Endpoints { return endpoints } - log.Debugf("Processing %d endpoints for EndpointSlice %s", len(ep.Endpoints), ep.Name) + logger.Debug("Processing endpoints for EndpointSlice", + logfields.LenEndpoints, len(ep.Endpoints), + logfields.Name, ep.Name, + ) for _, sub := range ep.Endpoints { // ready indicates that this endpoint is prepared to receive traffic, // according to whatever system is managing the endpoint. A nil value @@ -347,12 +352,20 @@ func ParseEndpointSliceV1(ep *slim_discovery_v1.EndpointSlice) *Endpoints { // allow endpoints that are Serving and Terminating if !isReady { if !option.Config.EnableK8sTerminatingEndpoint { - log.Debugf("discarding Endpoint on EndpointSlice %s: not Ready and EnableK8sTerminatingEndpoint %v", ep.Name, option.Config.EnableK8sTerminatingEndpoint) + logger.Debug( + "discarding Endpoint on EndpointSlice: not Ready", + logfields.Name, ep.Name, + logfields.EnableK8sTerminatingEndpoint, option.Config.EnableK8sTerminatingEndpoint, + ) continue } // filter not Serving endpoints since those can not receive traffic if !isServing { - log.Debugf("discarding Endpoint on EndpointSlice %s: not Serving and EnableK8sTerminatingEndpoint %v", ep.Name, option.Config.EnableK8sTerminatingEndpoint) + logger.Debug( + "discarding Endpoint on EndpointSlice: not Serving", + logfields.Name, ep.Name, + logfields.EnableK8sTerminatingEndpoint, option.Config.EnableK8sTerminatingEndpoint, + ) continue } } @@ -360,7 +373,12 @@ func ParseEndpointSliceV1(ep *slim_discovery_v1.EndpointSlice) *Endpoints { for _, addr := range sub.Addresses { addrCluster, err := cmtypes.ParseAddrCluster(addr) if err != nil { - log.WithError(err).Infof("Unable to parse address %s for EndpointSlices %s", addr, ep.Name) + logger.Info( + "Unable to parse address for EndpointSlices", + logfields.Error, err, + logfields.Address, addr, + logfields.Name, ep.Name, + ) continue } @@ -386,7 +404,11 @@ func ParseEndpointSliceV1(ep *slim_discovery_v1.EndpointSlice) *Endpoints { // If is not ready check if is serving and terminating if !isReady && option.Config.EnableK8sTerminatingEndpoint && isServing && isTerminating { - log.Debugf("Endpoint address %s on EndpointSlice %s is Terminating", addr, ep.Name) + logger.Debug( + "Endpoint address on EndpointSlice is Terminating", + logfields.Address, addr, + logfields.Name, ep.Name, + ) backend.Terminating = true metrics.TerminatingEndpointsEvents.Inc() } @@ -408,7 +430,11 @@ func ParseEndpointSliceV1(ep *slim_discovery_v1.EndpointSlice) *Endpoints { } } - log.Debugf("EndpointSlice %s has %d backends", ep.Name, len(endpoints.Backends)) + logger.Debug( + "EndpointSlice has backends", + logfields.LenBackends, len(endpoints.Backends), + logfields.Name, ep.Name, + ) return endpoints } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/error_helpers.go b/vendor/github.com/cilium/cilium/pkg/k8s/error_helpers.go index afc217257a..cabaf799be 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/error_helpers.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/error_helpers.go @@ -9,6 +9,8 @@ import ( "strings" "github.com/cilium/cilium/pkg/lock" + "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/time" ) @@ -48,6 +50,8 @@ func K8sErrorHandler(_ context.Context, e error, _ string, _ ...interface{}) { return } + logger := logging.DefaultSlogLogger + // We rate-limit certain categories of error message. These are matched // below, with a default behaviour to print everything else without // rate-limiting. @@ -59,7 +63,7 @@ func K8sErrorHandler(_ context.Context, e error, _ string, _ ...interface{}) { // trying to connect. case strings.Contains(errstr, "connection refused"): if k8sErrorUpdateCheckUnmuteTime(errstr, now) { - log.WithError(e).Error("k8sError") + logger.Error("k8sError", logfields.Error, e) } // k8s does not allow us to watch both ThirdPartyResource and @@ -68,7 +72,7 @@ func K8sErrorHandler(_ context.Context, e error, _ string, _ ...interface{}) { // that used ThirdPartyResource to define CiliumNetworkPolicy. case strings.Contains(errstr, "Failed to list *v2.CiliumNetworkPolicy: the server could not find the requested resource"): if k8sErrorUpdateCheckUnmuteTime(errstr, now) { - log.WithError(e).Error("No Cilium Network Policy CRD defined in the cluster, please set `--skip-crd-creation=false` to avoid seeing this error.") + logger.Error("No Cilium Network Policy CRD defined in the cluster, please set `--skip-crd-creation=false` to avoid seeing this error.", logfields.Error, e) } // fromCIDR and toCIDR used to expect an "ip" subfield (so, they were a YAML @@ -81,14 +85,16 @@ func K8sErrorHandler(_ context.Context, e error, _ string, _ ...interface{}) { strings.Contains(errstr, "Failed to list *v2.CiliumNetworkPolicy: only encoded map or array can be decoded into a struct"), strings.Contains(errstr, "Failed to list *v2.CiliumNetworkPolicy: v2.CiliumNetworkPolicyList:"): if k8sErrorUpdateCheckUnmuteTime(errstr, now) { - log.WithError(e).Error("Unable to decode k8s watch event") + logger.Error("Unable to decode k8s watch event", logfields.Error, e) } case k8sObjDecodeErrRe.MatchString(errstr): - log.WithError(e).Error("K8s client-go error indicates failure to decode k8s objs from apiserver." + - " This likely indicate issues with k8s apiserver sending malformed data or errors." + - " Such issues may be related to corrupted k8s etcd state.") + logger.Error("K8s client-go error indicates failure to decode k8s objs from apiserver."+ + " This likely indicate issues with k8s apiserver sending malformed data or errors."+ + " Such issues may be related to corrupted k8s etcd state.", + logfields.Error, e, + ) default: - log.WithError(e).Error("k8sError") + logger.Error("k8sError", logfields.Error, e) } } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/informer/cast.go b/vendor/github.com/cilium/cilium/pkg/k8s/informer/cast.go index 16b672acf2..677e258b83 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/informer/cast.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/informer/cast.go @@ -4,6 +4,9 @@ package informer import ( + "fmt" + "log/slog" + "k8s.io/client-go/tools/cache" "github.com/cilium/cilium/pkg/logging/logfields" @@ -12,7 +15,7 @@ import ( // CastInformerEvent tries to cast obj to type typ, directly // or by DeletedFinalStateUnknown type. It returns nil and logs // an error if obj doesn't contain type typ. -func CastInformerEvent[typ any](obj interface{}) *typ { +func CastInformerEvent[typ any](logger *slog.Logger, obj interface{}) *typ { k8sObj, ok := obj.(*typ) if ok { return k8sObj @@ -27,7 +30,9 @@ func CastInformerEvent[typ any](obj interface{}) *typ { return k8sObj } } - log.WithField(logfields.Object, logfields.Repr(obj)). - Warnf("Ignoring invalid type, expected: %T", new(typ)) + logger.Warn( + fmt.Sprintf("Ignoring invalid type, expected: %T", new(typ)), + logfields.Object, obj, + ) return nil } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/informer/informer.go b/vendor/github.com/cilium/cilium/pkg/k8s/informer/informer.go index 274aa61700..25b248620f 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/informer/informer.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/informer/informer.go @@ -15,12 +15,9 @@ import ( "github.com/cilium/cilium/pkg/k8s/watchers/resources" "github.com/cilium/cilium/pkg/logging" - "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/time" ) -var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "k8s") - func init() { utilRuntime.PanicHandlers = append( utilRuntime.PanicHandlers, @@ -33,7 +30,7 @@ func init() { // panicking with ErrAbortHandler also suppresses logging of a stack trace to the server's error log. return } - log.Fatal("Panic in Kubernetes runtime handler") + logging.Fatal(logging.DefaultSlogLogger, "Panic in Kubernetes runtime handler") }, ) } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/labels.go b/vendor/github.com/cilium/cilium/pkg/k8s/labels.go index 349ffbf767..825c4746d9 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/labels.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/labels.go @@ -4,7 +4,7 @@ package k8s import ( - "github.com/sirupsen/logrus" + "log/slog" slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" k8sUtils "github.com/cilium/cilium/pkg/k8s/utils" @@ -19,13 +19,13 @@ const UseOriginalSourceAddressLabel = "cilium.io/use-original-source-address" // GetPodMetadata returns the labels and annotations of the pod with the given // namespace / name. -func GetPodMetadata(k8sNs *slim_corev1.Namespace, pod *slim_corev1.Pod) (containerPorts []slim_corev1.ContainerPort, lbls map[string]string) { +func GetPodMetadata(logger *slog.Logger, k8sNs *slim_corev1.Namespace, pod *slim_corev1.Pod) (containerPorts []slim_corev1.ContainerPort, lbls map[string]string) { namespace := pod.Namespace - scopedLog := log.WithFields(logrus.Fields{ - logfields.K8sNamespace: namespace, - logfields.K8sPodName: pod.Name, - }) - scopedLog.Debug("Connecting to k8s local stores to retrieve labels for pod") + logger.Debug( + "Connecting to k8s local stores to retrieve labels for pod", + logfields.K8sNamespace, namespace, + logfields.K8sPodName, pod.Name, + ) objMetaCpy := pod.ObjectMeta.DeepCopy() labels := k8sUtils.SanitizePodLabels(objMetaCpy.Labels, k8sNs, pod.Spec.ServiceAccountName, option.Config.ClusterName) diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/logfields.go b/vendor/github.com/cilium/cilium/pkg/k8s/logfields.go deleted file mode 100644 index bf6b46bfa9..0000000000 --- a/vendor/github.com/cilium/cilium/pkg/k8s/logfields.go +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package k8s - -import ( - "github.com/cilium/cilium/pkg/logging" - "github.com/cilium/cilium/pkg/logging/logfields" -) - -// logging field definitions -const ( - // subsysK8s is the value for logfields.LogSubsys - subsysK8s = "k8s" -) - -var ( - // log is the k8s package logger object. - log = logging.DefaultLogger.WithField(logfields.LogSubsys, subsysK8s) -) diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/network_policy.go b/vendor/github.com/cilium/cilium/pkg/k8s/network_policy.go index 309abc2bd1..397911c4b7 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/network_policy.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/network_policy.go @@ -5,6 +5,9 @@ package k8s import ( "fmt" + "log/slog" + "maps" + "slices" "github.com/cilium/cilium/pkg/annotation" k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io" @@ -32,9 +35,9 @@ var ( // GetPolicyLabelsv1 extracts the name of np. It uses the name from the Cilium // annotation if present. If the policy's annotations do not contain // the Cilium annotation, the policy's name field is used instead. -func GetPolicyLabelsv1(np *slim_networkingv1.NetworkPolicy) labels.LabelArray { +func GetPolicyLabelsv1(logger *slog.Logger, np *slim_networkingv1.NetworkPolicy) labels.LabelArray { if np == nil { - log.Warningf("unable to extract policy labels because provided NetworkPolicy is nil") + logger.Warn("unable to extract policy labels because provided NetworkPolicy is nil") return nil } @@ -103,18 +106,13 @@ func parseNetworkPolicyPeer(namespace string, peer *slim_networkingv1.NetworkPol } func hasV1PolicyType(pTypes []slim_networkingv1.PolicyType, typ slim_networkingv1.PolicyType) bool { - for _, pType := range pTypes { - if pType == typ { - return true - } - } - return false + return slices.Contains(pTypes, typ) } // ParseNetworkPolicy parses a k8s NetworkPolicy. Returns a list of // Cilium policy rules that can be added, along with an error if there was an // error sanitizing the rules. -func ParseNetworkPolicy(np *slim_networkingv1.NetworkPolicy) (api.Rules, error) { +func ParseNetworkPolicy(logger *slog.Logger, np *slim_networkingv1.NetworkPolicy) (api.Rules, error) { if np == nil { return nil, fmt.Errorf("cannot parse NetworkPolicy because it is nil") @@ -138,7 +136,7 @@ func ParseNetworkPolicy(np *slim_networkingv1.NetworkPolicy) (api.Rules, error) ingress.FromEndpoints = append(ingress.FromEndpoints, *endpointSelector) } else { // No label-based selectors were in NetworkPolicyPeer. - log.WithField(logfields.K8sNetworkPolicyName, np.Name).Debug("NetworkPolicyPeer does not have PodSelector or NamespaceSelector") + logger.Debug("NetworkPolicyPeer does not have PodSelector or NamespaceSelector", logfields.K8sNetworkPolicyName, np.Name) } // Parse CIDR-based parts of rule. @@ -182,7 +180,7 @@ func ParseNetworkPolicy(np *slim_networkingv1.NetworkPolicy) (api.Rules, error) if endpointSelector != nil { egress.ToEndpoints = append(egress.ToEndpoints, *endpointSelector) } else { - log.WithField(logfields.K8sNetworkPolicyName, np.Name).Debug("NetworkPolicyPeer does not have PodSelector or NamespaceSelector") + logger.Debug("NetworkPolicyPeer does not have PodSelector or NamespaceSelector", logfields.K8sNetworkPolicyName, np.Name) } } if rule.IPBlock != nil { @@ -214,7 +212,7 @@ func ParseNetworkPolicy(np *slim_networkingv1.NetworkPolicy) (api.Rules, error) } // Convert the k8s default-deny model to the Cilium default-deny model - //spec: + // spec: // podSelector: {} // policyTypes: // - Ingress @@ -227,7 +225,7 @@ func ParseNetworkPolicy(np *slim_networkingv1.NetworkPolicy) (api.Rules, error) } // Convert the k8s default-deny model to the Cilium default-deny model - //spec: + // spec: // podSelector: {} // policyTypes: // - Egress @@ -240,7 +238,7 @@ func ParseNetworkPolicy(np *slim_networkingv1.NetworkPolicy) (api.Rules, error) // The next patch will pass the UID. rule := api.NewRule(). WithEndpointSelector(api.NewESFromK8sLabelSelector(labels.LabelSourceK8sKeyPrefix, podSelector)). - WithLabels(GetPolicyLabelsv1(np)). + WithLabels(GetPolicyLabelsv1(logger, np)). WithIngressRules(ingresses). WithEgressRules(egresses) @@ -255,9 +253,7 @@ func parsePodSelector(podSelectorIn *slim_metav1.LabelSelector, namespace string podSelector := &slim_metav1.LabelSelector{ MatchLabels: make(map[string]slim_metav1.MatchLabelsValue, len(podSelectorIn.MatchLabels)), } - for k, v := range podSelectorIn.MatchLabels { - podSelector.MatchLabels[k] = v - } + maps.Copy(podSelector.MatchLabels, podSelectorIn.MatchLabels) // The PodSelector should only reflect to the same namespace // the policy is being stored, thus we add the namespace to // the MatchLabels map. diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/node.go b/vendor/github.com/cilium/cilium/pkg/k8s/node.go index 63c185e37e..530c31ba51 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/node.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/node.go @@ -5,11 +5,10 @@ package k8s import ( "fmt" + "log/slog" "net" "strconv" - "github.com/sirupsen/logrus" - "github.com/cilium/cilium/pkg/annotation" "github.com/cilium/cilium/pkg/cidr" slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" @@ -43,12 +42,12 @@ type nodeAddressGroup struct { } // ParseNode parses a kubernetes node to a cilium node -func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node { +func ParseNode(logger *slog.Logger, k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node { addrGroups := make(map[nodeAddressGroup]struct{}) - scopedLog := log.WithFields(logrus.Fields{ - logfields.NodeName: k8sNode.Name, - logfields.K8sNodeID: k8sNode.UID, - }) + scopedLog := logger.With( + logfields.NodeName, k8sNode.Name, + logfields.K8sNodeID, k8sNode.UID, + ) addrs := []nodeTypes.Address{} for _, addr := range k8sNode.Status.Addresses { // We only care about this address types, @@ -73,25 +72,29 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node case ip != nil && ip.To16() != nil: addrGroup.family = slim_corev1.IPv6Protocol default: - scopedLog.WithFields(logrus.Fields{ - logfields.IPAddr: addr.Address, - logfields.Type: addr.Type, - }).Warn("Ignoring invalid node IP") + scopedLog.Warn( + "Ignoring invalid node IP", + logfields.IPAddr, addr.Address, + logfields.Type, addr.Type, + ) continue } _, groupFound := addrGroups[addrGroup] if groupFound { - scopedLog.WithFields(logrus.Fields{ - logfields.Node: k8sNode.Name, - logfields.Type: addr.Type, - }).Warn("Detected multiple IPs of the same address type and family, Cilium will only consider the first IP in the Node resource") + scopedLog.Warn( + "Detected multiple IPs of the same address type and family, Cilium will only consider the first IP in the Node resource", + logfields.Type, addr.Type, + ) continue } addrGroups[addrGroup] = struct{}{} addressType, err := ParseNodeAddressType(addr.Type) if err != nil { - scopedLog.WithError(err).Warn("invalid address type for node") + scopedLog.Warn( + "invalid address type for node", + logfields.Error, err, + ) } na := nodeTypes.Address{ @@ -109,11 +112,19 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node if len(k8sNode.Spec.PodCIDRs) != 0 { if len(k8sNode.Spec.PodCIDRs) > 2 { - scopedLog.WithField("podCIDR", k8sNode.Spec.PodCIDRs).Errorf("Invalid PodCIDRs expected 1 or 2 PodCIDRs, received %d", len(k8sNode.Spec.PodCIDRs)) + scopedLog.Error( + "Invalid PodCIDRs expected 1 or 2 PodCIDRs", + logfields.PodCIDRs, k8sNode.Spec.PodCIDRs, + logfields.LenIPs, len(k8sNode.Spec.PodCIDRs), + ) } else { for _, podCIDR := range k8sNode.Spec.PodCIDRs { if allocCIDR, err := cidr.ParseCIDR(podCIDR); err != nil { - scopedLog.WithError(err).WithField("podCIDR", k8sNode.Spec.PodCIDR).Warn("Invalid PodCIDR value for node") + scopedLog.Warn( + "Invalid PodCIDR value for node", + logfields.Error, err, + logfields.PodCIDRs, k8sNode.Spec.PodCIDRs, + ) } else { if allocCIDR.IP.To4() != nil { newNode.IPv4AllocCIDR = allocCIDR @@ -125,7 +136,11 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node } } else if len(k8sNode.Spec.PodCIDR) != 0 { if allocCIDR, err := cidr.ParseCIDR(k8sNode.Spec.PodCIDR); err != nil { - scopedLog.WithError(err).WithField(logfields.V4Prefix, k8sNode.Spec.PodCIDR).Warn("Invalid PodCIDR value for node") + scopedLog.Warn( + "Invalid PodCIDR value for node", + logfields.Error, err, + logfields.V4Prefix, k8sNode.Spec.PodCIDR, + ) } else { if allocCIDR.IP.To4() != nil { newNode.IPv4AllocCIDR = allocCIDR @@ -153,16 +168,26 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node k8sNodeAddHostIP := func(key string, alias string) { if ciliumInternalIP, ok := annotation.Get(k8sNode, key, alias); !ok || ciliumInternalIP == "" { - scopedLog.Debugf("Missing %s (or %s). Annotation required when IPSec Enabled", key, alias) + scopedLog.Debug( + "Annotation required when IPSec Enabled. Missing key or its alias.", + logfields.Key, key, + logfields.Alias, alias, + ) } else if ip := net.ParseIP(ciliumInternalIP); ip == nil { - scopedLog.Debugf("ParseIP %s error", ciliumInternalIP) + scopedLog.Debug( + "Parse IP error", + logfields.IPAddr, ciliumInternalIP, + ) } else { na := nodeTypes.Address{ Type: addressing.NodeCiliumInternalIP, IP: ip, } addrs = append(addrs, na) - scopedLog.Debugf("Add NodeCiliumInternalIP: %s", ip) + scopedLog.Debug( + "Add NodeCiliumInternalIP", + logfields.IPAddr, ip, + ) } } @@ -181,11 +206,17 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node // In case it's invalid or empty then we fall back to our annotations. if newNode.IPv4AllocCIDR == nil { if ipv4CIDR, ok := annotation.Get(k8sNode, annotation.V4CIDRName, annotation.V4CIDRNameAlias); !ok || ipv4CIDR == "" { - scopedLog.Debug("Empty IPv4 CIDR annotation in node") + scopedLog.Debug( + "Empty IPv4 CIDR annotation in node", + ) } else { allocCIDR, err := cidr.ParseCIDR(ipv4CIDR) if err != nil { - scopedLog.WithError(err).WithField(logfields.V4Prefix, ipv4CIDR).Error("BUG, invalid IPv4 annotation CIDR in node") + scopedLog.Error( + "BUG, invalid IPv4 annotation CIDR in node", + logfields.Error, err, + logfields.V4Prefix, ipv4CIDR, + ) } else { newNode.IPv4AllocCIDR = allocCIDR } @@ -194,11 +225,17 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node if newNode.IPv6AllocCIDR == nil { if ipv6CIDR, ok := annotation.Get(k8sNode, annotation.V6CIDRName, annotation.V6CIDRNameAlias); !ok || ipv6CIDR == "" { - scopedLog.Debug("Empty IPv6 CIDR annotation in node") + scopedLog.Debug( + "Empty IPv6 CIDR annotation in node", + ) } else { allocCIDR, err := cidr.ParseCIDR(ipv6CIDR) if err != nil { - scopedLog.WithError(err).WithField(logfields.V6Prefix, ipv6CIDR).Error("BUG, invalid IPv6 annotation CIDR in node") + scopedLog.Error( + "BUG, invalid IPv6 annotation CIDR in node", + logfields.Error, err, + logfields.V6Prefix, ipv6CIDR, + ) } else { newNode.IPv6AllocCIDR = allocCIDR } @@ -207,9 +244,14 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node if newNode.IPv4HealthIP == nil { if healthIP, ok := annotation.Get(k8sNode, annotation.V4HealthName, annotation.V4HealthNameAlias); !ok || healthIP == "" { - scopedLog.Debug("Empty IPv4 health endpoint annotation in node") + scopedLog.Debug( + "Empty IPv4 health endpoint annotation in node", + ) } else if ip := net.ParseIP(healthIP); ip == nil { - scopedLog.WithField(logfields.V4HealthIP, healthIP).Error("BUG, invalid IPv4 health endpoint annotation in node") + scopedLog.Error( + "BUG, invalid IPv4 health endpoint annotation in node", + logfields.V4HealthIP, healthIP, + ) } else { newNode.IPv4HealthIP = ip } @@ -217,9 +259,14 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node if newNode.IPv6HealthIP == nil { if healthIP, ok := annotation.Get(k8sNode, annotation.V6HealthName, annotation.V6HealthNameAlias); !ok || healthIP == "" { - scopedLog.Debug("Empty IPv6 health endpoint annotation in node") + scopedLog.Debug( + "Empty IPv6 health endpoint annotation in node", + ) } else if ip := net.ParseIP(healthIP); ip == nil { - scopedLog.WithField(logfields.V6HealthIP, healthIP).Error("BUG, invalid IPv6 health endpoint annotation in node") + scopedLog.Error( + "BUG, invalid IPv6 health endpoint annotation in node", + logfields.V6HealthIP, healthIP, + ) } else { newNode.IPv6HealthIP = ip } @@ -227,9 +274,14 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node if newNode.IPv4IngressIP == nil { if ingressIP, ok := annotation.Get(k8sNode, annotation.V4IngressName, annotation.V4IngressNameAlias); !ok || ingressIP == "" { - scopedLog.Debug("Empty IPv4 Ingress annotation in node") + scopedLog.Debug( + "Empty IPv4 Ingress annotation in node", + ) } else if ip := net.ParseIP(ingressIP); ip == nil { - scopedLog.WithField(logfields.V4IngressIP, ingressIP).Error("BUG, invalid IPv4 Ingress annotation in node") + scopedLog.Error( + "BUG, invalid IPv4 Ingress annotation in node", + logfields.V4IngressIP, ingressIP, + ) } else { newNode.IPv4IngressIP = ip } @@ -237,9 +289,14 @@ func ParseNode(k8sNode *slim_corev1.Node, source source.Source) *nodeTypes.Node if newNode.IPv6IngressIP == nil { if ingressIP, ok := annotation.Get(k8sNode, annotation.V6IngressName, annotation.V6IngressNameAlias); !ok || ingressIP == "" { - scopedLog.Debug("Empty IPv6 Ingress annotation in node") + scopedLog.Debug( + "Empty IPv6 Ingress annotation in node", + ) } else if ip := net.ParseIP(ingressIP); ip == nil { - scopedLog.WithField(logfields.V6IngressIP, ingressIP).Error("BUG, invalid IPv6 Ingress annotation in node") + scopedLog.Error( + "BUG, invalid IPv6 Ingress annotation in node", + logfields.V6IngressIP, ingressIP, + ) } else { newNode.IPv6IngressIP = ip } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/resource/resource.go b/vendor/github.com/cilium/cilium/pkg/k8s/resource/resource.go index db75b9be2e..b5b6924001 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/resource/resource.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/resource/resource.go @@ -138,7 +138,9 @@ type Resource[T k8sRuntime.Object] interface { // See also pkg/k8s/resource/example/main.go for a runnable example. func New[T k8sRuntime.Object](lc cell.Lifecycle, lw cache.ListerWatcher, opts ...ResourceOption) Resource[T] { r := &resource[T]{ - lw: lw, + subscribers: make(map[uint64]*subscriber[T]), + needed: make(chan struct{}, 1), + lw: lw, } r.opts.sourceObj = func() k8sRuntime.Object { var obj T @@ -148,7 +150,7 @@ func New[T k8sRuntime.Object](lc cell.Lifecycle, lw cache.ListerWatcher, opts .. o(&r.opts) } r.ctx, r.cancel = context.WithCancel(context.Background()) - r.reset() + r.storeResolver, r.storePromise = promise.New[Store[T]]() lc.Append(r) return r } @@ -159,7 +161,6 @@ type options struct { indexers cache.Indexers // map of the optional custom indexers to be added to the underlying resource informer metricScope string // the scope label used when recording metrics for the resource name string // the name label used for the workqueue metrics - releasable bool // if true, the underlying informer will be stopped when the last subscriber cancels its subscription crdSyncPromise promise.Promise[synced.CRDSync] // optional promise to wait for } @@ -220,23 +221,6 @@ func WithCRDSync(crdSyncPromise promise.Promise[synced.CRDSync]) ResourceOption } } -// WithStoppableInformer marks the resource as releasable. A releasable resource stops -// the underlying informer if the last active subscriber cancels its subscription. -// In this case the resource is stopped and prepared again for a subsequent call to -// either Events() or Store(). -// A subscriber is a consumer who has taken a reference to the store with Store() or that -// is listening to the events stream channel with Events(). -// This option is meant to be used for very specific cases of resources with a high rate -// of updates that can potentially hinder scalability in very large clusters, like -// CiliumNode and CiliumEndpoint. -// For this cases, stopping the informer is required when switching to other data sources -// that scale better. -func WithStoppableInformer() ResourceOption { - return func(o *options) { - o.releasable = true - } -} - type resource[T k8sRuntime.Object] struct { mu lock.RWMutex ctx context.Context @@ -254,12 +238,6 @@ type resource[T k8sRuntime.Object] struct { storePromise promise.Promise[Store[T]] storeResolver promise.Resolver[Store[T]] - - // meaningful for releasable resources only - refsMu lock.Mutex - refs uint64 - resetCtx context.Context - resetCancel context.CancelFunc } var _ Resource[*corev1.Node] = &resource[*corev1.Node]{} @@ -274,14 +252,11 @@ func (r *resource[T]) Store(ctx context.Context) (Store[T], error) { defer r.mu.RUnlock() return r.synchronized } - cache.WaitForCacheSync(ctx.Done(), hasSynced) + if !cache.WaitForCacheSync(ctx.Done(), hasSynced) { + return nil, ctx.Err() + } - // use an error handler to release the resource if the store promise - // is rejected or the context is cancelled before the cache has synchronized. - return promise.MapError(r.storePromise, func(err error) error { - r.release() - return err - }).Await(ctx) + return r.storePromise.Await(ctx) } func (r *resource[T]) metricEventProcessed(eventKind EventKind, status bool) { @@ -321,26 +296,12 @@ func (r *resource[T]) metricEventReceived(action string, valid, equal bool) { } func (r *resource[T]) Start(cell.HookContext) error { - r.start() - return nil -} - -func (r *resource[T]) start() { - // Don't start the resource if it has been definitely stopped - if r.ctx.Err() != nil { - return - } r.wg.Add(1) go r.startWhenNeeded() + return nil } func (r *resource[T]) markNeeded() { - if r.opts.releasable { - r.refsMu.Lock() - r.refs++ - r.refsMu.Unlock() - } - select { case r.needed <- struct{}{}: default: @@ -368,19 +329,16 @@ func (r *resource[T]) startWhenNeeded() { } store, informer := r.newInformer() - r.storeResolver.Resolve(&typedStore[T]{ - store: store, - release: r.release, - }) + r.storeResolver.Resolve(&typedStore[T]{store}) r.wg.Add(1) go func() { defer r.wg.Done() - informer.Run(merge(r.ctx.Done(), r.resetCtx.Done())) + informer.Run(r.ctx.Done()) }() // Wait for cache to be synced before emitting the sync event. - if cache.WaitForCacheSync(merge(r.ctx.Done(), r.resetCtx.Done()), informer.HasSynced) { + if cache.WaitForCacheSync(r.ctx.Done(), informer.HasSynced) { // Emit the sync event for all subscribers. Subscribers // that subscribe afterwards will emit it by checking // r.synchronized. @@ -394,12 +352,6 @@ func (r *resource[T]) startWhenNeeded() { } func (r *resource[T]) Stop(stopCtx cell.HookContext) error { - if r.opts.releasable { - // grab the refs lock to avoid a concurrent restart for releasable resource - r.refsMu.Lock() - defer r.refsMu.Unlock() - } - r.cancel() r.wg.Wait() return nil @@ -475,7 +427,6 @@ func (r *resource[T]) Events(ctx context.Context, opts ...EventsOpt) <-chan Even // Fork a goroutine to process the queued keys and pass them to the subscriber. r.wg.Add(1) go func() { - defer r.release() defer r.wg.Done() defer close(out) @@ -522,7 +473,6 @@ func (r *resource[T]) Events(ctx context.Context, opts ...EventsOpt) <-chan Even defer r.wg.Done() select { case <-r.ctx.Done(): - case <-r.resetCtx.Done(): case <-ctx.Done(): } subCancel() @@ -532,39 +482,6 @@ func (r *resource[T]) Events(ctx context.Context, opts ...EventsOpt) <-chan Even return out } -func (r *resource[T]) release() { - if !r.opts.releasable { - return - } - - // in case of a releasable resource, stop the underlying informer when the last - // reference to it is released. The resource is restarted to be - // ready again in case of a subsequent call to either Events() or Store(). - - r.refsMu.Lock() - defer r.refsMu.Unlock() - - r.refs-- - if r.refs > 0 { - return - } - - r.resetCancel() - r.wg.Wait() - close(r.needed) - - r.reset() - r.start() -} - -func (r *resource[T]) reset() { - r.subscribers = make(map[uint64]*subscriber[T]) - r.needed = make(chan struct{}, 1) - r.synchronized = false - r.storeResolver, r.storePromise = promise.New[Store[T]]() - r.resetCtx, r.resetCancel = context.WithCancel(context.Background()) -} - func (r *resource[T]) resourceName() string { if r.opts.name != "" { return r.opts.name @@ -913,15 +830,3 @@ func getUID(obj k8sRuntime.Object) types.UID { } return meta.GetUID() } - -func merge[T any](c1, c2 <-chan T) <-chan T { - m := make(chan T) - go func() { - select { - case <-c1: - case <-c2: - } - close(m) - }() - return m -} diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/resource/store.go b/vendor/github.com/cilium/cilium/pkg/k8s/resource/store.go index 9dec4cbad0..4dc0b892d5 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/resource/store.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/resource/store.go @@ -34,17 +34,11 @@ type Store[T k8sRuntime.Object] interface { // CacheStore returns the underlying cache.Store instance. Use for temporary // compatibility purposes only! CacheStore() cache.Store - - // Release the store and allows the associated resource to stop its informer if - // this is the last reference to it. - // This is a no-op if the resource is not releasable. - Release() } // typedStore implements Store on top of an untyped cache.Indexer. type typedStore[T k8sRuntime.Object] struct { - store cache.Indexer - release func() + store cache.Indexer } var _ Store[*corev1.Node] = &typedStore[*corev1.Node]{} @@ -95,10 +89,6 @@ func (s *typedStore[T]) CacheStore() cache.Store { return s.store } -func (s *typedStore[T]) Release() { - s.release() -} - type KeyIter interface { // Next returns true if there is a key, false if iteration has finished. Next() bool diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/resource_ctors.go b/vendor/github.com/cilium/cilium/pkg/k8s/resource_ctors.go index 4a19ea5262..6e8ef0e106 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/resource_ctors.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/resource_ctors.go @@ -5,18 +5,19 @@ package k8s import ( "fmt" + "log/slog" "sync" - "github.com/cilium/cilium/pkg/allocator" - "github.com/cilium/cilium/pkg/identity/key" - "github.com/cilium/hive/cell" + "github.com/cloudflare/cfssl/log" "github.com/spf13/pflag" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sRuntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/tools/cache" + "github.com/cilium/cilium/pkg/allocator" + "github.com/cilium/cilium/pkg/identity/key" cilium_api_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" cilium_api_v2alpha1 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1" "github.com/cilium/cilium/pkg/k8s/client" @@ -138,7 +139,6 @@ func CiliumNodeResource(params CiliumResourceParams, opts ...func(*metav1.ListOp ) return resource.New[*cilium_api_v2.CiliumNode](params.Lifecycle, lw, resource.WithMetric("CiliumNode"), - resource.WithStoppableInformer(), resource.WithCRDSync(params.CRDSyncPromise), // optional, can be nil ), nil } @@ -295,7 +295,7 @@ func CiliumBGPPeerConfigResource(params CiliumResourceParams, opts ...func(*meta return resource.New[*cilium_api_v2.CiliumBGPPeerConfig](params.Lifecycle, lw, resource.WithMetric("CiliumBGPPeerConfig"), resource.WithCRDSync(params.CRDSyncPromise)), nil } -func EndpointsResource(lc cell.Lifecycle, cfg Config, cs client.Clientset, opts ...func(*metav1.ListOptions)) (resource.Resource[*Endpoints], error) { +func EndpointsResource(logger *slog.Logger, lc cell.Lifecycle, cfg Config, cs client.Clientset, opts ...func(*metav1.ListOptions)) (resource.Resource[*Endpoints], error) { if !cs.IsEnabled() { return nil, nil } @@ -318,7 +318,9 @@ func EndpointsResource(lc cell.Lifecycle, cfg Config, cs client.Clientset, opts return resource.New[*Endpoints]( lc, lw, - resource.WithLazyTransform(lw.getSourceObj, transformEndpoint), + resource.WithLazyTransform(lw.getSourceObj, func(i any) (any, error) { + return transformEndpoint(logger, i) + }), resource.WithMetric("Endpoint"), resource.WithName("endpoints"), ), nil @@ -380,12 +382,12 @@ func (lw *endpointsListerWatcher) Watch(opts metav1.ListOptions) (watch.Interfac return lw.getListerWatcher().Watch(opts) } -func transformEndpoint(obj any) (any, error) { +func transformEndpoint(logger *slog.Logger, obj any) (any, error) { switch obj := obj.(type) { case *slim_corev1.Endpoints: return ParseEndpoints(obj), nil case *slim_discoveryv1.EndpointSlice: - return ParseEndpointSliceV1(obj), nil + return ParseEndpointSliceV1(logger, obj), nil case *slim_discoveryv1beta1.EndpointSlice: return ParseEndpointSliceV1Beta1(obj), nil default: @@ -415,7 +417,6 @@ func CiliumSlimEndpointResource(params CiliumResourceParams, _ *node.LocalNodeSt }, TransformToCiliumEndpoint), resource.WithMetric("CiliumEndpoint"), resource.WithIndexers(indexers), - resource.WithStoppableInformer(), resource.WithCRDSync(params.CRDSyncPromise), ), nil } @@ -429,8 +430,10 @@ func ciliumEndpointLocalPodIndexFunc(obj any) ([]string, error) { } indices := []string{} if cep.Networking == nil { - log.WithField("ciliumendpoint", cep.GetNamespace()+"/"+cep.GetName()). - Debug("cannot index CiliumEndpoint by node without network status") + log.Debug( + "cannot index CiliumEndpoint by node without network status", + slog.Any("ciliumendpoint", cep.GetNamespace()+"/"+cep.GetName()), + ) return nil, nil } if cep.Networking.NodeIP == node.GetCiliumEndpointNodeIP() { @@ -458,7 +461,6 @@ func CiliumEndpointSliceResource(params CiliumResourceParams, _ *node.LocalNodeS return resource.New[*cilium_api_v2alpha1.CiliumEndpointSlice](params.Lifecycle, lw, resource.WithMetric("CiliumEndpointSlice"), resource.WithIndexers(indexers), - resource.WithStoppableInformer(), resource.WithCRDSync(params.CRDSyncPromise), ), nil } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/service.go b/vendor/github.com/cilium/cilium/pkg/k8s/service.go index 108632133a..f137d7846a 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/service.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/service.go @@ -5,12 +5,12 @@ package k8s import ( "fmt" + "log/slog" "maps" "net" "net/netip" "strings" - "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" "github.com/cilium/cilium/pkg/annotation" @@ -150,7 +150,7 @@ func isValidServiceFrontendIP(netIP net.IP) bool { // latter two, one can set the annotation with the value "LoadBalancer". type exposeSvcType slim_corev1.ServiceType -func newSvcExposureType(svc *slim_corev1.Service) (*exposeSvcType, error) { +func NewSvcExposureType(svc *slim_corev1.Service) (*exposeSvcType, error) { typ, isSet := svc.Annotations[annotation.ServiceTypeExposure] if !isSet { return nil, nil @@ -171,8 +171,8 @@ func newSvcExposureType(svc *slim_corev1.Service) (*exposeSvcType, error) { return &expType, nil } -// canExpose checks whether a given service type can be provisioned. -func (e *exposeSvcType) canExpose(t slim_corev1.ServiceType) bool { +// CanExpose checks whether a given service type can be provisioned. +func (e *exposeSvcType) CanExpose(t slim_corev1.ServiceType) bool { if e == nil { return true } @@ -189,19 +189,23 @@ func ParseServiceID(svc *slim_corev1.Service) ServiceID { } // ParseService parses a Kubernetes service and returns a Service. -func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (ServiceID, *Service) { - scopedLog := log.WithFields(logrus.Fields{ - logfields.K8sSvcName: svc.ObjectMeta.Name, - logfields.K8sNamespace: svc.ObjectMeta.Namespace, - logfields.K8sAPIVersion: svc.TypeMeta.APIVersion, - logfields.K8sSvcType: svc.Spec.Type, - }) +func ParseService(logger *slog.Logger, svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (ServiceID, *Service) { + scopedLog := logger.With( + logfields.K8sSvcName, svc.ObjectMeta.Name, + logfields.K8sNamespace, svc.ObjectMeta.Namespace, + logfields.K8sAPIVersion, svc.TypeMeta.APIVersion, + logfields.K8sSvcType, svc.Spec.Type, + ) var loadBalancerIPs []string svcID := ParseServiceID(svc) - expType, err := newSvcExposureType(svc) + expType, err := NewSvcExposureType(svc) if err != nil { - scopedLog.WithError(err).Warnf("Ignoring %q annotation", annotation.ServiceTypeExposure) + scopedLog.Warn( + "Ignoring annotation", + logfields.Error, err, + logfields.Annotation, annotation.ServiceTypeExposure, + ) } var svcType loadbalancer.SVCType @@ -220,7 +224,9 @@ func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (Service return ServiceID{}, nil default: - scopedLog.Warn("Ignoring k8s service: unsupported type") + scopedLog.Warn( + "Ignoring k8s service: unsupported type", + ) return ServiceID{}, nil } @@ -229,7 +235,7 @@ func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (Service } var clusterIPs []net.IP - if expType.canExpose(slim_corev1.ServiceTypeClusterIP) { + if expType.CanExpose(slim_corev1.ServiceTypeClusterIP) { if len(svc.Spec.ClusterIPs) == 0 { if clsIP := net.ParseIP(svc.Spec.ClusterIP); clsIP != nil { clusterIPs = []net.IP{clsIP} @@ -265,7 +271,7 @@ func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (Service intTrafficPolicy = loadbalancer.SVCTrafficPolicyCluster } - if expType.canExpose(slim_corev1.ServiceTypeLoadBalancer) { + if expType.CanExpose(slim_corev1.ServiceTypeLoadBalancer) { for _, ip := range svc.Status.LoadBalancer.Ingress { if ip.IP != "" && (ip.IPMode == nil || *ip.IPMode == slim_corev1.LoadBalancerIPModeVIP) { loadBalancerIPs = append(loadBalancerIPs, ip.IP) @@ -295,8 +301,12 @@ func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (Service svcInfo.ForwardingMode, err = getAnnotationServiceForwardingMode(svc) if err != nil { - scopedLog.WithError(err).Warnf("Ignoring %q annotation, applying global configuration: %v", - annotation.ServiceForwardingMode, svcInfo.ForwardingMode) + scopedLog.Warn( + "Ignoring annotation, applying global configuration", + logfields.Error, err, + logfields.Annotation, annotation.ServiceForwardingMode, + logfields.GlobalConfiguration, svcInfo.ForwardingMode, + ) } } @@ -306,8 +316,12 @@ func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (Service svcInfo.LoadBalancerAlgorithm, err = getAnnotationServiceLoadBalancingAlgorithm(svc) if err != nil { - scopedLog.WithError(err).Warnf("Ignoring %q annotation, applying global configuration: %v", - annotation.ServiceLoadBalancingAlgorithm, svcInfo.LoadBalancerAlgorithm) + scopedLog.Warn( + "Ignoring annotation, applying global configuration", + logfields.Error, err, + logfields.Annotation, annotation.ServiceLoadBalancingAlgorithm, + logfields.GlobalConfiguration, svcInfo.LoadBalancerAlgorithm, + ) } } @@ -320,8 +334,11 @@ func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (Service svcInfo.SessionAffinityTimeoutSec = uint32(v1.DefaultClientIPServiceAffinitySeconds) } if svcInfo.SessionAffinityTimeoutSec > defaults.SessionAffinityTimeoutMaxFallback { - scopedLog.Warnf("Clamping maximum possible session affinity timeout from %d to %d seconds", - svcInfo.SessionAffinityTimeoutSec, defaults.SessionAffinityTimeoutMaxFallback) + scopedLog.Warn( + "Clamping maximum possible session affinity timeout (seconds)", + logfields.From, svcInfo.SessionAffinityTimeoutSec, + logfields.To, defaults.SessionAffinityTimeoutMaxFallback, + ) svcInfo.SessionAffinityTimeoutSec = defaults.SessionAffinityTimeoutMaxFallback } } @@ -348,7 +365,7 @@ func ParseService(svc *slim_corev1.Service, nodePortAddrs []netip.Addr) (Service svcInfo.Ports[portName] = p } - if expType.canExpose(slim_corev1.ServiceTypeNodePort) && + if expType.CanExpose(slim_corev1.ServiceTypeNodePort) && (svc.Spec.Type == slim_corev1.ServiceTypeNodePort || svc.Spec.Type == slim_corev1.ServiceTypeLoadBalancer) { if option.Config.EnableNodePort { @@ -691,13 +708,9 @@ func (s *Service) UniquePorts() map[string]bool { func NewClusterService(id ServiceID, k8sService *Service, k8sEndpoints *Endpoints) serviceStore.ClusterService { svc := serviceStore.NewClusterService(id.Name, id.Namespace) - for key, value := range k8sService.Labels { - svc.Labels[key] = value - } + maps.Copy(svc.Labels, k8sService.Labels) - for key, value := range k8sService.Selector { - svc.Selector[key] = value - } + maps.Copy(svc.Selector, k8sService.Selector) portConfig := serviceStore.PortConfiguration{} for portName, port := range k8sService.Ports { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go b/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go index 1e1d2bbec7..d1208b07dd 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/service_cache.go @@ -5,6 +5,7 @@ package k8s import ( "context" + "log/slog" "net" "net/netip" "slices" @@ -14,7 +15,6 @@ import ( "github.com/cilium/statedb" "github.com/cilium/stream" "github.com/davecgh/go-spew/spew" - "github.com/sirupsen/logrus" "github.com/spf13/pflag" core_v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" @@ -243,6 +243,7 @@ type ServiceCache interface { // ServiceCacheImpl is a list of services correlated with the matching endpoints. // The Events member will receive events as services. type ServiceCacheImpl struct { + logger *slog.Logger config ServiceCacheConfig // Events may only be read by single consumer. The consumer must acknowledge @@ -278,11 +279,12 @@ type ServiceCacheImpl struct { } // NewServiceCache returns a new ServiceCache -func NewServiceCache(db *statedb.DB, nodeAddrs statedb.Table[datapathTables.NodeAddress], svcMetrics SVCMetrics) *ServiceCacheImpl { +func NewServiceCache(logger *slog.Logger, db *statedb.DB, nodeAddrs statedb.Table[datapathTables.NodeAddress], svcMetrics SVCMetrics) *ServiceCacheImpl { events := make(chan ServiceEvent, option.Config.K8sServiceCacheSize) notifications, emitNotifications, completeNotifications := stream.Multicast[ServiceNotification]() return &ServiceCacheImpl{ + logger: logger, db: db, nodeAddrs: nodeAddrs, services: map[ServiceID]*Service{}, @@ -297,8 +299,8 @@ func NewServiceCache(db *statedb.DB, nodeAddrs statedb.Table[datapathTables.Node } } -func newServiceCache(lc cell.Lifecycle, cfg ServiceCacheConfig, lns *node.LocalNodeStore, db *statedb.DB, nodeAddrs statedb.Table[datapathTables.NodeAddress], metrics SVCMetrics) ServiceCache { - sc := NewServiceCache(db, nodeAddrs, metrics) +func newServiceCache(logger *slog.Logger, lc cell.Lifecycle, cfg ServiceCacheConfig, lns *node.LocalNodeStore, db *statedb.DB, nodeAddrs statedb.Table[datapathTables.NodeAddress], metrics SVCMetrics) ServiceCache { + sc := NewServiceCache(logger, db, nodeAddrs, metrics) sc.config = cfg var wg sync.WaitGroup @@ -434,7 +436,7 @@ func (s *ServiceCacheImpl) UpdateService(k8sSvc *slim_corev1.Service, swg *lock. ) } - svcID, newService := ParseService(k8sSvc, addrs) + svcID, newService := ParseService(s.logger, k8sSvc, addrs) if newService == nil { return svcID } @@ -642,11 +644,8 @@ func (s *ServiceCacheImpl) filterEndpoints(localEndpoints *Endpoints, svc *Servi return localEndpoints } - for _, hint := range backend.HintsForZones { - if hint == s.selfNodeZoneLabel { - filteredEndpoints.Backends[key] = backend - break - } + if slices.Contains(backend.HintsForZones, s.selfNodeZoneLabel) { + filteredEndpoints.Backends[key] = backend } } @@ -697,12 +696,13 @@ func (s *ServiceCacheImpl) correlateEndpoints(id ServiceID) (*Endpoints, bool) { for clusterName, remoteClusterEndpoints := range externalEndpoints.endpoints { for ip, e := range remoteClusterEndpoints.Backends { if _, ok := endpoints.Backends[ip]; ok { - log.WithFields(logrus.Fields{ - logfields.K8sSvcName: id.Name, - logfields.K8sNamespace: id.Namespace, - logfields.IPAddr: ip, - "cluster": clusterName, - }).Warning("Conflicting service backend IP") + s.logger.Warn( + "Conflicting service backend IP", + logfields.K8sSvcName, id.Name, + logfields.K8sNamespace, id.Namespace, + logfields.IPAddr, ip, + logfields.ClusterName, clusterName, + ) } else { e.Preferred = svc.ServiceAffinity == serviceAffinityRemote endpoints.Backends[ip] = e.DeepCopy() @@ -742,7 +742,6 @@ func (s *ServiceCacheImpl) MergeExternalServiceUpdate(service *serviceStore.Clus func (s *ServiceCacheImpl) mergeServiceUpdateLocked(service *serviceStore.ClusterService, oldService *Service, swg *lock.StoppableWaitGroup, opts ...mergeExternalServiceOption) { - scopedLog := log.WithFields(logrus.Fields{logfields.ServiceName: service.String()}) id := ServiceID{Name: service.Name, Namespace: service.Namespace} if slices.Contains(opts, optClusterAware) { @@ -763,13 +762,21 @@ func (s *ServiceCacheImpl) mergeServiceUpdateLocked(service *serviceStore.Cluste if service.Cluster != option.Config.ClusterName && !service.Shared { delete(externalEndpoints.endpoints, service.Cluster) } else { - scopedLog.Debugf("Updating backends to %+v", service.Backends) + s.logger.Debug( + "Updating backends", + logfields.ServiceName, service, + logfields.Backends, service.Backends, + ) + backends := map[cmtypes.AddrCluster]*Backend{} for ipString, portConfig := range service.Backends { addr, err := cmtypes.ParseAddrCluster(ipString) if err != nil { - scopedLog.WithField(logfields.IPAddr, ipString). - Error("Skipping service backend due to invalid IP address") + s.logger.Error( + "Skipping service backend due to invalid IP address", + logfields.ServiceName, service, + logfields.IPAddr, ipString, + ) continue } @@ -821,8 +828,6 @@ func (s *ServiceCacheImpl) MergeExternalServiceDelete(service *serviceStore.Clus } func (s *ServiceCacheImpl) mergeExternalServiceDeleteLocked(service *serviceStore.ClusterService, swg *lock.StoppableWaitGroup, opts ...mergeExternalServiceOption) { - scopedLog := log.WithFields(logrus.Fields{logfields.ServiceName: service.String()}) - id := ServiceID{Name: service.Name, Namespace: service.Namespace} if slices.Contains(opts, optClusterAware) { id.Cluster = service.Cluster @@ -830,7 +835,10 @@ func (s *ServiceCacheImpl) mergeExternalServiceDeleteLocked(service *serviceStor externalEndpoints, ok := s.externalEndpoints[id] if ok { - scopedLog.Debug("Deleting external endpoints") + s.logger.Debug( + "Deleting external endpoints", + logfields.ServiceName, service, + ) oldEPs, _ := s.correlateEndpoints(id) @@ -862,7 +870,10 @@ func (s *ServiceCacheImpl) mergeExternalServiceDeleteLocked(service *serviceStor s.emitEvent(event) } } else { - scopedLog.Debug("Received delete event for non-existing endpoints") + s.logger.Debug( + "Received delete event for non-existing endpoints", + logfields.ServiceName, service, + ) } } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/labels.go b/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/labels.go index 32b2988223..eabee43cb4 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/labels.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/labels.go @@ -7,6 +7,7 @@ package labels import ( "fmt" + "maps" "sort" "strings" @@ -105,14 +106,8 @@ func Conflicts(labels1, labels2 Set) bool { // Merge combines given maps, and does not check for any conflicts // between the maps. In case of conflicts, second map (labels2) wins func Merge(labels1, labels2 Set) Set { - mergedMap := Set{} - - for k, v := range labels1 { - mergedMap[k] = v - } - for k, v := range labels2 { - mergedMap[k] = v - } + mergedMap := maps.Clone(labels1) + maps.Copy(mergedMap, labels2) return mergedMap } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/selector.go b/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/selector.go index d19a9e6788..b6086fc45d 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/selector.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels/selector.go @@ -7,6 +7,7 @@ package labels import ( "fmt" + "maps" "slices" "sort" "strconv" @@ -191,12 +192,7 @@ func NewRequirement(key string, op selection.Operator, vals []string, opts ...fi } func (r *Requirement) hasValue(value string) bool { - for i := range r.strValues { - if r.strValues[i] == value { - return true - } - } - return false + return slices.Contains(r.strValues, value) } // Matches returns true if the Requirement matches the input Labels. @@ -1006,11 +1002,7 @@ func (s ValidatedSetSelector) Requirements() (requirements Requirements, selecta } func (s ValidatedSetSelector) DeepCopySelector() Selector { - res := make(ValidatedSetSelector, len(s)) - for k, v := range s { - res[k] = v - } - return res + return maps.Clone(s) } func (s ValidatedSetSelector) RequiresExactMatch(label string) (value string, found bool) { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1/helpers.go b/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1/helpers.go index d2d08077a0..c7d345c56a 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1/helpers.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1/helpers.go @@ -7,6 +7,8 @@ package v1 import ( "fmt" + "maps" + "slices" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" @@ -47,7 +49,7 @@ func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) { default: return nil, fmt.Errorf("%q is not a valid label selector operator", expr.Operator) } - r, err := labels.NewRequirement(expr.Key, op, append([]string(nil), expr.Values...)) + r, err := labels.NewRequirement(expr.Key, op, slices.Clone(expr.Values)) if err != nil { return nil, err } @@ -66,10 +68,7 @@ func LabelSelectorAsMap(ps *LabelSelector) (map[string]string, error) { if ps == nil { return nil, nil } - selector := map[string]string{} - for k, v := range ps.MatchLabels { - selector[k] = v - } + selector := maps.Clone(ps.MatchLabels) for _, expr := range ps.MatchExpressions { switch expr.Operator { case LabelSelectorOpIn: @@ -145,9 +144,7 @@ func SetAsLabelSelector(ls labels.Set) *LabelSelector { selector := &LabelSelector{ MatchLabels: make(map[string]string, len(ls)), } - for label, value := range ls { - selector.MatchLabels[label] = value - } + maps.Copy(selector.MatchLabels, ls) return selector } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/synced/cell.go b/vendor/github.com/cilium/cilium/pkg/k8s/synced/cell.go index 7e4840a6ba..a2b2bab72b 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/synced/cell.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/synced/cell.go @@ -6,6 +6,7 @@ package synced import ( "context" "errors" + "log/slog" "github.com/cilium/hive/cell" "github.com/cilium/hive/job" @@ -20,6 +21,7 @@ import ( type syncedParams struct { cell.In + Logger *slog.Logger CacheStatus CacheStatus } @@ -33,6 +35,7 @@ var Cell = cell.Module( cell.Provide(func(params syncedParams) *Resources { return &Resources{ + logger: params.Logger, CacheStatus: params.CacheStatus, } }), @@ -81,6 +84,8 @@ var RejectedCRDSyncPromise = func() promise.Promise[CRDSync] { type syncCRDsPromiseParams struct { cell.In + Logger *slog.Logger + Lifecycle cell.Lifecycle Jobs job.Registry Health cell.Health @@ -100,7 +105,7 @@ func newCRDSyncPromise(params syncCRDsPromiseParams) promise.Promise[CRDSync] { g := params.Jobs.NewGroup(params.Health) g.Add(job.OneShot("sync-crds", func(ctx context.Context, health cell.Health) error { - err := SyncCRDs(ctx, params.Clientset, params.ResourceNames, params.Resources, params.APIGroups, params.Config) + err := SyncCRDs(ctx, params.Logger, params.Clientset, params.ResourceNames, params.Resources, params.APIGroups, params.Config) if err != nil { crdSyncResolver.Reject(err) } else { diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/synced/crd.go b/vendor/github.com/cilium/cilium/pkg/k8s/synced/crd.go index 4ae44a3179..157fbc194e 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/synced/crd.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/synced/crd.go @@ -8,7 +8,10 @@ package synced import ( "context" "errors" + "fmt" + "log/slog" + "github.com/cloudflare/cfssl/log" apiextclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" @@ -24,6 +27,8 @@ import ( "github.com/cilium/cilium/pkg/k8s/informer" slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" "github.com/cilium/cilium/pkg/lock" + "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/option" "github.com/cilium/cilium/pkg/time" ) @@ -131,8 +136,8 @@ func AllCiliumCRDResourceNames() []string { // installed inside the K8s cluster. These CRDs are added by the // Cilium Operator. This function will block until it finds all the // CRDs or if a timeout occurs. -func SyncCRDs(ctx context.Context, clientset client.Clientset, crdNames []string, rs *Resources, ag *APIGroups, cfg CRDSyncConfig) error { - crds := newCRDState(crdNames) +func SyncCRDs(ctx context.Context, logger *slog.Logger, clientset client.Clientset, crdNames []string, rs *Resources, ag *APIGroups, cfg CRDSyncConfig) error { + crds := newCRDState(logger, crdNames) listerWatcher := newListWatchFromClient( newCRDGetter(clientset), @@ -194,7 +199,7 @@ func SyncCRDs(ctx context.Context, clientset client.Clientset, crdNames []string // controller will exit after this function. defer ag.RemoveAPI(k8sAPIGroupCRD) - log.Info("Waiting until all Cilium CRDs are available") + logger.Info("Waiting until all Cilium CRDs are available") ticker := time.NewTicker(50 * time.Millisecond) count := 0 @@ -203,12 +208,15 @@ func SyncCRDs(ctx context.Context, clientset client.Clientset, crdNames []string case <-ctx.Done(): err := ctx.Err() if err != nil && !errors.Is(err, context.Canceled) { - log.WithError(err). - Fatalf("Unable to find all Cilium CRDs necessary within "+ + logging.Fatal( + logger, + fmt.Sprintf("Unable to find all Cilium CRDs necessary within "+ "%v timeout. Please ensure that Cilium Operator is "+ "running, as it's responsible for registering all "+ "the Cilium CRDs. The following CRDs were not found: %v", - cfg.CRDWaitTimeout, crds.unSynced()) + cfg.CRDWaitTimeout, crds.unSynced()), + logfields.Error, err, + ) } // If the context was canceled it means the daemon is being stopped // so we can return the context's error. @@ -222,14 +230,17 @@ func SyncCRDs(ctx context.Context, clientset client.Clientset, crdNames []string count++ if count == 20 { count = 0 - log.Infof("Still waiting for Cilium Operator to register the following CRDs: %v", crds.unSynced()) + log.Info( + "Still waiting for Cilium Operator to register CRDs", + logfields.CRDs, crds.unSynced(), + ) } } } } func (s *crdState) add(obj interface{}) { - if pom := informer.CastInformerEvent[slim_metav1.PartialObjectMetadata](obj); pom != nil { + if pom := informer.CastInformerEvent[slim_metav1.PartialObjectMetadata](s.logger, obj); pom != nil { s.Lock() s.m[CRDResourceName(pom.GetName())] = true s.Unlock() @@ -237,7 +248,7 @@ func (s *crdState) add(obj interface{}) { } func (s *crdState) remove(obj interface{}) { - if pom := informer.CastInformerEvent[slim_metav1.PartialObjectMetadata](obj); pom != nil { + if pom := informer.CastInformerEvent[slim_metav1.PartialObjectMetadata](s.logger, obj); pom != nil { s.Lock() s.m[CRDResourceName(pom.GetName())] = false s.Unlock() @@ -273,6 +284,7 @@ func (s *crdState) unSynced() []string { // crdState contains the state of the CRDs inside the cluster. type crdState struct { + logger *slog.Logger lock.Mutex // m is a map which maps the CRD name to its synced state in the cluster. @@ -280,13 +292,14 @@ type crdState struct { m map[string]bool } -func newCRDState(crds []string) crdState { +func newCRDState(logger *slog.Logger, crds []string) crdState { m := make(map[string]bool, len(crds)) for _, name := range crds { m[name] = false } return crdState{ - m: m, + logger: logger, + m: m, } } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/synced/logfields.go b/vendor/github.com/cilium/cilium/pkg/k8s/synced/logfields.go deleted file mode 100644 index 6ed069ca74..0000000000 --- a/vendor/github.com/cilium/cilium/pkg/k8s/synced/logfields.go +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Authors of Cilium - -package synced - -import ( - "github.com/cilium/cilium/pkg/logging" - "github.com/cilium/cilium/pkg/logging/logfields" -) - -// logging field definitions -const ( - // subsysK8s is the value for logfields.LogSubsys - subsysK8s = "k8s" -) - -var ( - // log is the k8s package logger object. - log = logging.DefaultLogger.WithField(logfields.LogSubsys, subsysK8s) -) diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/synced/resources.go b/vendor/github.com/cilium/cilium/pkg/k8s/synced/resources.go index 4512d3e163..3662aa7164 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/synced/resources.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/synced/resources.go @@ -5,17 +5,21 @@ package synced import ( "fmt" + "log/slog" "golang.org/x/sync/errgroup" "k8s.io/client-go/tools/cache" "github.com/cilium/cilium/pkg/lock" + "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/time" ) // Resources maps resource names to channels that are closed upon initial // sync with k8s. type Resources struct { + logger *slog.Logger CacheStatus CacheStatus lock.RWMutex @@ -70,7 +74,10 @@ func (r *Resources) BlockWaitGroupToSyncResources( // Log an error caches have already synchronized, as the caller is making this call too late // and the resource in question was missed in the initial cache sync. if r.CacheStatus.Synchronized() { - log.WithField("kubernetesResource", resourceName).Errorf("BlockWaitGroupToSyncResources called after Caches have already synced") + r.logger.Error( + "BlockWaitGroupToSyncResources called after Caches have already synced", + logfields.Resource, resourceName, + ) return } ch := make(chan struct{}) @@ -84,7 +91,7 @@ func (r *Resources) BlockWaitGroupToSyncResources( r.Unlock() go func() { - scopedLog := log.WithField("kubernetesResource", resourceName) + scopedLog := r.logger.With(logfields.Resource, resourceName) scopedLog.Debug("waiting for cache to synchronize") if ok := cache.WaitForCacheSync(stop, hasSyncedFunc); !ok { select { @@ -100,7 +107,10 @@ func (r *Resources) BlockWaitGroupToSyncResources( r.Unlock() default: // Fatally exit it resource fails to sync - scopedLog.Fatalf("failed to wait for cache to sync") + logging.Fatal( + scopedLog, + "failed to wait for cache to sync", + ) } } else { scopedLog.Debug("cache synced") @@ -130,7 +140,7 @@ func (r *Resources) WaitForCacheSync(resourceNames ...string) { continue } for { - scopedLog := log.WithField("kubernetesResource", resourceName) + scopedLog := r.logger.With(logfields.Resource, resourceName) <-c r.RLock() stopWait := r.stopWait[resourceName] @@ -195,9 +205,17 @@ func (r *Resources) WaitForCacheSyncWithTimeout(timeout time.Duration, resourceN // We reset the timer to wait the timeout period minus the // time since the last event. currTimeout = timeout - time.Since(lastEvent) - log.Debugf("resource %q received event %s ago, waiting for additional %s before timing out", resource, time.Since(lastEvent), currTimeout) + r.logger.Debug( + "received event for resource type, waiting before timeout", + logfields.Resource, resource, + logfields.LastEventReceived, time.Since(lastEvent), + logfields.Timeout, currTimeout, + ) case <-done: - log.Debugf("resource %q cache has synced, stopping timeout watcher", resource) + r.logger.Debug( + "cache has synced, stopping timeout watcher", + logfields.Resource, resource, + ) return nil } } diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/version/version.go b/vendor/github.com/cilium/cilium/pkg/k8s/version/version.go index db2bab9951..1331cde78f 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/version/version.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/version/version.go @@ -8,6 +8,7 @@ package version import ( "context" "fmt" + "log/slog" "github.com/blang/semver/v4" "k8s.io/apimachinery/pkg/api/errors" @@ -15,13 +16,10 @@ import ( "k8s.io/client-go/kubernetes" "github.com/cilium/cilium/pkg/lock" - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/versioncheck" ) -var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "k8s") - // ServerCapabilities is a list of server capabilities derived based on // version, the Kubernetes discovery API, or probing of individual API // endpoints. @@ -160,7 +158,7 @@ func Force(version string) error { return nil } -func endpointSlicesFallbackDiscovery(client kubernetes.Interface) error { +func endpointSlicesFallbackDiscovery(logger *slog.Logger, client kubernetes.Interface) error { // If a k8s version with discovery v1 is used, then do not even bother // checking for v1beta1 cached.mutex.Lock() @@ -188,7 +186,7 @@ func endpointSlicesFallbackDiscovery(client kubernetes.Interface) error { } if errors.IsNotFound(err) { - log.WithError(err).Info("Unable to retrieve EndpointSlices for default/kubernetes. Disabling EndpointSlices") + logger.Info("Unable to retrieve EndpointSlices for default/kubernetes. Disabling EndpointSlices", logfields.Error, err) // StatusNotFound is a safe error, EndpointSlices are // disabled and the agent can continue. return nil @@ -199,13 +197,13 @@ func endpointSlicesFallbackDiscovery(client kubernetes.Interface) error { return fmt.Errorf("unable to validate EndpointSlices support: %w", err) } -func leasesFallbackDiscovery(client kubernetes.Interface, apiDiscoveryEnabled bool) error { +func leasesFallbackDiscovery(logger *slog.Logger, client kubernetes.Interface, apiDiscoveryEnabled bool) error { // apiDiscoveryEnabled is used to fallback leases discovery to directly // probing the API when we cannot discover API groups. // We require to check for Leases capabilities in operator only, which uses Leases // for leader election purposes in HA mode. if !apiDiscoveryEnabled { - log.Debugf("Skipping Leases support fallback discovery") + logger.Debug("Skipping Leases support fallback discovery") return nil } @@ -221,7 +219,7 @@ func leasesFallbackDiscovery(client kubernetes.Interface, apiDiscoveryEnabled bo } if errors.IsNotFound(err) { - log.WithError(err).Info("Unable to retrieve Leases for kube-controller-manager. Disabling LeasesResourceLock") + logger.Info("Unable to retrieve Leases for kube-controller-manager. Disabling LeasesResourceLock", logfields.Error, err) // StatusNotFound is a safe error, Leases are // disabled and the agent can continue return nil @@ -268,7 +266,7 @@ func updateK8sServerVersion(client kubernetes.Interface) error { // Discovery of capabilities only works if the discovery API of the apiserver // is functional. If it is not available, a warning is logged and the discovery // falls back to probing individual API endpoints. -func Update(client kubernetes.Interface, apiDiscoveryEnabled bool) error { +func Update(logger *slog.Logger, client kubernetes.Interface, apiDiscoveryEnabled bool) error { err := updateK8sServerVersion(client) if err != nil { return err @@ -288,21 +286,21 @@ func Update(client kubernetes.Interface, apiDiscoveryEnabled bool) error { // information at a later point because the capabilities are // primiarly used while the agent is starting up. Instead, fall // back to probing API endpoints directly. - log.WithError(err).Warning("Unable to discover API groups and resources") - if err := endpointSlicesFallbackDiscovery(client); err != nil { + logger.Warn("Unable to discover API groups and resources", logfields.Error, err) + if err := endpointSlicesFallbackDiscovery(logger, client); err != nil { return err } - return leasesFallbackDiscovery(client, apiDiscoveryEnabled) + return leasesFallbackDiscovery(logger, client, apiDiscoveryEnabled) } updateServerGroupsAndResources(apiResourceLists) } else { - if err := endpointSlicesFallbackDiscovery(client); err != nil { + if err := endpointSlicesFallbackDiscovery(logger, client); err != nil { return err } - return leasesFallbackDiscovery(client, apiDiscoveryEnabled) + return leasesFallbackDiscovery(logger, client, apiDiscoveryEnabled) } return nil diff --git a/vendor/github.com/cilium/cilium/pkg/k8s/watchers/resources/resources.go b/vendor/github.com/cilium/cilium/pkg/k8s/watchers/resources/resources.go index f2895f8450..16e7b3606e 100644 --- a/vendor/github.com/cilium/cilium/pkg/k8s/watchers/resources/resources.go +++ b/vendor/github.com/cilium/cilium/pkg/k8s/watchers/resources/resources.go @@ -12,6 +12,10 @@ import ( ) const ( + // K8sAPIGroupNetworkingV1Core is the identifier for K8S resources of type networking.k8s.io/v1/NetworkPolicy + K8sAPIGroupNetworkingV1Core = "networking.k8s.io/v1::NetworkPolicy" + // K8sAPIGroupNamespaceV1Core is the identifier for K8s resources of type core/v1/Namespace. + K8sAPIGroupNamespaceV1Core = "core/v1::Namespace" // K8sAPIGroupServiceV1Core is the identifier for K8s resources of type core/v1/Service. K8sAPIGroupServiceV1Core = "core/v1::Service" // K8sAPIGroupPodV1Core is the identifier for K8s resources of type core/v1/Pod. diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/backend.go b/vendor/github.com/cilium/cilium/pkg/kvstore/backend.go index 5170abbf63..7d1341e38b 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/backend.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/backend.go @@ -5,10 +5,13 @@ package kvstore import ( "context" + "log/slog" "google.golang.org/grpc" "github.com/cilium/cilium/api/v1/models" + "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/time" ) @@ -85,7 +88,7 @@ type backendModule interface { // setConfig must configure the backend with the specified options. // This function is called once before newClient(). - setConfig(opts map[string]string) error + setConfig(logger *slog.Logger, opts map[string]string) error // setExtraConfig sets more options in the kvstore that are not able to // be set by strings. @@ -100,7 +103,7 @@ type backendModule interface { // newClient must initializes the backend and create a new kvstore // client which implements the BackendOperations interface - newClient(ctx context.Context, opts *ExtraOptions) (BackendOperations, chan error) + newClient(ctx context.Context, logger *slog.Logger, opts *ExtraOptions) (BackendOperations, chan error) // createInstance creates a new instance of the module createInstance() backendModule @@ -115,7 +118,7 @@ var ( // registerBackend must be called by kvstore backends to register themselves func registerBackend(name string, module backendModule) { if _, ok := registeredBackends[name]; ok { - log.Panicf("backend with name '%s' already registered", name) + logging.Panic(logging.DefaultSlogLogger, "backend already registered", logfields.Name, name) } registeredBackends[name] = module @@ -138,10 +141,6 @@ type BackendOperations interface { // is connected to the kvstore server. Connected(ctx context.Context) <-chan error - // Disconnected returns a channel which is closed whenever the kvstore - // client is not connected to the kvstore server. (Only implemented for etcd) - Disconnected() <-chan struct{} - // Status returns the status of the kvstore client Status() *models.Status diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/cell.go b/vendor/github.com/cilium/cilium/pkg/kvstore/cell.go index 50e0d1dd17..a8f9ec06f4 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/cell.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/cell.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "log/slog" "sync" "github.com/cilium/hive/cell" @@ -27,10 +28,10 @@ var Cell = cell.Module( cell.Config(defaultConfig), - cell.Provide(func(lc cell.Lifecycle, shutdowner hive.Shutdowner, cfg config, opts *ExtraOptions) promise.Promise[BackendOperations] { + cell.Provide(func(logger *slog.Logger, lc cell.Lifecycle, shutdowner hive.Shutdowner, cfg config, opts *ExtraOptions) promise.Promise[BackendOperations] { resolver, promise := promise.New[BackendOperations]() if cfg.KVStore == "" { - log.Info("Skipping connection to kvstore, as not configured") + logger.Info("Skipping connection to kvstore, as not configured") resolver.Reject(errors.New("kvstore not configured")) return promise } @@ -52,18 +53,19 @@ var Cell = cell.Module( go func() { defer wg.Done() - log := log.WithField(logfields.BackendName, cfg.KVStore) - log.Info("Establishing connection to kvstore") - backend, errCh := NewClient(ctx, cfg.KVStore, cfg.KVStoreOpt, opts) + scopedLogger := logger.With(logfields.BackendName, cfg.KVStore) + + scopedLogger.Info("Establishing connection to kvstore") + backend, errCh := NewClient(ctx, scopedLogger, cfg.KVStore, cfg.KVStoreOpt, opts) if err, isErr := <-errCh; isErr { - log.WithError(err).Error("Failed to establish connection to kvstore") + scopedLogger.Error("Failed to establish connection to kvstore", logfields.Error, err) resolver.Reject(fmt.Errorf("failed connecting to kvstore: %w", err)) shutdowner.Shutdown(hive.ShutdownWithError(err)) return } - log.Info("Connection to kvstore successfully established") + scopedLogger.Info("Connection to kvstore successfully established") resolver.Resolve(backend) }() return nil diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/client.go b/vendor/github.com/cilium/cilium/pkg/kvstore/client.go index 5b2ca787df..2e444eab60 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/client.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/client.go @@ -6,8 +6,10 @@ package kvstore import ( "context" "fmt" + "log/slog" - "github.com/cilium/cilium/pkg/time" + "github.com/cilium/cilium/pkg/logging" + "github.com/cilium/cilium/pkg/logging/logfields" ) var ( @@ -18,12 +20,12 @@ var ( defaultClientSet = make(chan struct{}) ) -func initClient(ctx context.Context, module backendModule, opts *ExtraOptions) error { - scopedLog := log.WithField(fieldKVStoreModule, module.getName()) - c, errChan := module.newClient(ctx, opts) +func initClient(ctx context.Context, logger *slog.Logger, module backendModule, opts *ExtraOptions) error { + scopedLog := logger.With(fieldKVStoreModule, module.getName()) + c, errChan := module.newClient(ctx, scopedLog, opts) if c == nil { err := <-errChan - scopedLog.WithError(err).Fatal("Unable to create kvstore client") + logging.Fatal(scopedLog, "Unable to create kvstore client", logfields.Error, err) } defaultClient = c @@ -37,7 +39,7 @@ func initClient(ctx context.Context, module backendModule, opts *ExtraOptions) e go func() { err, isErr := <-errChan if isErr && err != nil { - scopedLog.WithError(err).Fatal("Unable to connect to kvstore") + logging.Fatal(scopedLog, "Unable to connect to kvstore", logfields.Error, err) } }() @@ -51,7 +53,7 @@ func Client() BackendOperations { } // NewClient returns a new kvstore client based on the configuration -func NewClient(ctx context.Context, selectedBackend string, opts map[string]string, options *ExtraOptions) (BackendOperations, chan error) { +func NewClient(ctx context.Context, logger *slog.Logger, selectedBackend string, opts map[string]string, options *ExtraOptions) (BackendOperations, chan error) { // Channel used to report immediate errors, module.newClient will // create and return a different channel, caller doesn't need to know errChan := make(chan error, 1) @@ -63,7 +65,7 @@ func NewClient(ctx context.Context, selectedBackend string, opts map[string]stri return nil, errChan } - if err := module.setConfig(opts); err != nil { + if err := module.setConfig(logger, opts); err != nil { errChan <- err return nil, errChan } @@ -73,28 +75,5 @@ func NewClient(ctx context.Context, selectedBackend string, opts map[string]stri return nil, errChan } - return module.newClient(ctx, options) -} - -// Connected returns a channel which is closed when the following conditions -// are being met at the same time: -// * The kvstore client is configured -// * Connectivity to the kvstore has been established -// * The kvstore has quorum -// -// The channel will *not* be closed if the kvstore client is closed before -// connectivity or quorum has been achieved. It will wait until a new kvstore -// client is configured to again wait for connectivity and quorum. -func Connected() <-chan struct{} { - c := make(chan struct{}) - go func(c chan struct{}) { - for { - if err := <-Client().Connected(context.Background()); err == nil { - close(c) - return - } - time.Sleep(100 * time.Millisecond) - } - }(c) - return c + return module.newClient(ctx, logger, options) } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/config.go b/vendor/github.com/cilium/cilium/pkg/kvstore/config.go index 401c0c2c99..34e3e2bb9e 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/config.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/config.go @@ -6,6 +6,7 @@ package kvstore import ( "context" "fmt" + "log/slog" "sync" "github.com/cilium/cilium/pkg/logging/logfields" @@ -13,20 +14,23 @@ import ( // setOpts validates the specified options against the selected backend and // then modifies the configuration -func setOpts(opts map[string]string, supportedOpts backendOptions) error { +func setOpts(logger *slog.Logger, opts map[string]string, supportedOpts backendOptions) error { errors := 0 for key, val := range opts { opt, ok := supportedOpts[key] if !ok { errors++ - log.WithField(logfields.Key, key).Error("unknown kvstore configuration key") + logger.Error("unknown kvstore configuration key", logfields.Key, key) continue } if opt.validate != nil { if err := opt.validate(val); err != nil { - log.WithError(err).Errorf("invalid value for key %s", key) + logger.Error("invalid value for key", + logfields.Error, err, + logfields.Key, key, + ) errors++ } } @@ -36,9 +40,9 @@ func setOpts(opts map[string]string, supportedOpts backendOptions) error { // if errors have occurred, print the supported configuration keys to // the log if errors > 0 { - log.Error("Supported configuration keys:") + logger.Error("Supported configuration keys:") for key, val := range supportedOpts { - log.Errorf(" %-12s %s", key, val.description) + logger.Error(fmt.Sprintf(" %-12s %s", key, val.description)) } return fmt.Errorf("invalid kvstore configuration, see log for details") @@ -66,13 +70,13 @@ var ( setupOnce sync.Once ) -func setup(ctx context.Context, selectedBackend string, opts map[string]string, goOpts *ExtraOptions) error { +func setup(ctx context.Context, logger *slog.Logger, selectedBackend string, opts map[string]string, goOpts *ExtraOptions) error { module := getBackend(selectedBackend) if module == nil { return fmt.Errorf("unknown key-value store type %q. See cilium.link/err-kvstore for details", selectedBackend) } - if err := module.setConfig(opts); err != nil { + if err := module.setConfig(logger, opts); err != nil { return err } @@ -80,16 +84,16 @@ func setup(ctx context.Context, selectedBackend string, opts map[string]string, return err } - return initClient(ctx, module, goOpts) + return initClient(ctx, logger, module, goOpts) } // Setup sets up the key-value store specified in kvStore and configures it // with the options provided in opts -func Setup(ctx context.Context, selectedBackend string, opts map[string]string, goOpts *ExtraOptions) error { +func Setup(ctx context.Context, logger *slog.Logger, selectedBackend string, opts map[string]string, goOpts *ExtraOptions) error { var err error setupOnce.Do(func() { - err = setup(ctx, selectedBackend, opts, goOpts) + err = setup(ctx, logger, selectedBackend, opts, goOpts) }) return err diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/dummy.go b/vendor/github.com/cilium/cilium/pkg/kvstore/dummy.go index 83d6991e76..52f93d65c8 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/dummy.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/dummy.go @@ -7,6 +7,7 @@ import ( "context" "testing" + "github.com/cilium/hive/hivetest" client "go.etcd.io/etcd/client/v3" "github.com/cilium/cilium/pkg/time" @@ -40,13 +41,13 @@ func SetupDummyWithConfigOpts(tb testing.TB, dummyBackend string, opts map[strin module.setConfigDummy() if opts != nil { - err := module.setConfig(opts) + err := module.setConfig(hivetest.Logger(tb), opts) if err != nil { tb.Fatalf("Unable to set config options for kvstore backend module: %v", err) } } - if err := initClient(context.Background(), module, nil); err != nil { + if err := initClient(context.Background(), hivetest.Logger(tb), module, nil); err != nil { tb.Fatalf("Unable to initialize kvstore client: %v", err) } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/etcd.go b/vendor/github.com/cilium/cilium/pkg/kvstore/etcd.go index 2912c2f5e2..2c47e7d1b9 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/etcd.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/etcd.go @@ -9,12 +9,12 @@ import ( "crypto/tls" "errors" "fmt" + "log/slog" "math/rand/v2" "os" "strconv" "strings" - "github.com/sirupsen/logrus" "go.etcd.io/etcd/api/v3/mvccpb" v3rpcErrors "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/client/pkg/v3/logutil" @@ -30,6 +30,7 @@ import ( "github.com/cilium/cilium/pkg/backoff" "github.com/cilium/cilium/pkg/defaults" "github.com/cilium/cilium/pkg/lock" + "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/option" ciliumrate "github.com/cilium/cilium/pkg/rate" @@ -159,8 +160,8 @@ func (e *etcdModule) getName() string { return EtcdBackendName } -func (e *etcdModule) setConfig(opts map[string]string) error { - return setOpts(opts, e.opts) +func (e *etcdModule) setConfig(logger *slog.Logger, opts map[string]string) error { + return setOpts(logger, opts, e.opts) } func (e *etcdModule) setExtraConfig(opts *ExtraOptions) error { @@ -190,7 +191,7 @@ type clientOptions struct { ListBatchSize int } -func (e *etcdModule) newClient(ctx context.Context, opts *ExtraOptions) (BackendOperations, chan error) { +func (e *etcdModule) newClient(ctx context.Context, logger *slog.Logger, opts *ExtraOptions) (BackendOperations, chan error) { errChan := make(chan error, 10) clientOptions := clientOptions{ @@ -256,22 +257,25 @@ func (e *etcdModule) newClient(ctx context.Context, opts *ExtraOptions) (Backend e.config.Endpoints = []string{endpointsOpt.value} } - log.WithFields(logrus.Fields{ - "ConfigPath": configPath, - "KeepAliveHeartbeat": clientOptions.KeepAliveHeartbeat, - "KeepAliveTimeout": clientOptions.KeepAliveTimeout, - "RateLimit": clientOptions.RateLimit, - "MaxInflight": clientOptions.MaxInflight, - "ListLimit": clientOptions.ListBatchSize, - }).Info("Creating etcd client") + logger.Info( + "Creating etcd client", + logfields.ConfigPath, configPath, + logfields.KeepAliveHeartbeat, clientOptions.KeepAliveHeartbeat, + logfields.KeepAliveTimeout, clientOptions.KeepAliveTimeout, + logfields.RateLimit, clientOptions.RateLimit, + logfields.MaxInflight, clientOptions.MaxInflight, + logfields.ListLimit, clientOptions.ListBatchSize, + ) for { // connectEtcdClient will close errChan when the connection attempt has // been successful - backend, err := connectEtcdClient(ctx, e.config, configPath, errChan, clientOptions, opts) + backend, err := connectEtcdClient(ctx, logger, e.config, configPath, errChan, clientOptions, opts) switch { case os.IsNotExist(err): - log.WithError(err).Info("Waiting for all etcd configuration files to be available") + logger.Info("Waiting for all etcd configuration files to be available", + logfields.Error, err, + ) time.Sleep(5 * time.Second) case err != nil: errChan <- err @@ -295,9 +299,11 @@ func init() { } // Initialize the etcd client logger. - l, err := logutil.CreateDefaultZapLogger(etcdClientDebugLevel()) + l, err := logutil.CreateDefaultZapLogger(etcdClientDebugLevel(logging.DefaultSlogLogger)) if err != nil { - log.WithError(err).Warning("Failed to initialize etcd client logger") + logging.DefaultSlogLogger.Warn("Failed to initialize etcd client logger", + logfields.Error, err, + ) l = zap.NewNop() } etcd3ClientLogger = l.Named("etcd-client") @@ -306,14 +312,14 @@ func init() { // etcdClientDebugLevel translates ETCD_CLIENT_DEBUG into zap log level. // This is a copy of a private etcd client function: // https://github.com/etcd-io/etcd/blob/v3.5.9/client/v3/logger.go#L47-L59 -func etcdClientDebugLevel() zapcore.Level { +func etcdClientDebugLevel(logger *slog.Logger) zapcore.Level { envLevel := os.Getenv("ETCD_CLIENT_DEBUG") if envLevel == "" || envLevel == "true" { return zapcore.InfoLevel } var l zapcore.Level if err := l.Set(envLevel); err != nil { - log.Warning("Invalid value for environment variable 'ETCD_CLIENT_DEBUG'. Using default level: 'info'") + logger.Warn("Invalid value for environment variable 'ETCD_CLIENT_DEBUG'. Using default level: 'info'") return zapcore.InfoLevel } return l @@ -373,7 +379,7 @@ type etcdClient struct { leaseExpiredObservers lock.Map[string, func(string)] // logger is the scoped logger associated with this client - logger logrus.FieldLogger + logger *slog.Logger } type etcdMutex struct { @@ -482,25 +488,7 @@ func (e *etcdClient) Connected(ctx context.Context) <-chan error { return out } -// Disconnected closes the returned channel when the etcd client is -// disconnected after being reconnected. Blocks until the etcd client is first -// connected with the kvstore. -func (e *etcdClient) Disconnected() <-chan struct{} { - <-e.firstSession - limiter := newExpBackoffRateLimiter(e, "etcd-client-disconnected") - defer limiter.Reset() - for { - session, err := e.lockLeaseManager.GetSession(context.Background(), InitLockPath) - if err == nil { - return session.Done() - } - - e.logger.WithError(err).Warning("Failed to acquire lock session") - limiter.Wait(context.TODO()) - } -} - -func connectEtcdClient(ctx context.Context, config *client.Config, cfgPath string, errChan chan error, clientOptions clientOptions, opts *ExtraOptions) (BackendOperations, error) { +func connectEtcdClient(ctx context.Context, logger *slog.Logger, config *client.Config, cfgPath string, errChan chan error, clientOptions clientOptions, opts *ExtraOptions) (BackendOperations, error) { if cfgPath != "" { cfg, err := clientyaml.NewConfig(cfgPath) if err != nil { @@ -556,10 +544,10 @@ func connectEtcdClient(ctx context.Context, config *client.Config, cfgPath strin extraOptions: opts, listBatchSize: clientOptions.ListBatchSize, statusCheckErrors: make(chan error, 128), - logger: log.WithFields(logrus.Fields{ - "endpoints": config.Endpoints, - "config": cfgPath, - }), + logger: logger.With( + logfields.Endpoints, config.Endpoints, + logfields.Config, cfgPath, + ), } initialLimit := clientOptions.RateLimit @@ -567,13 +555,19 @@ func connectEtcdClient(ctx context.Context, config *client.Config, cfgPath strin // initial rate limit to BootstrapRateLimit and apply the standard rate limit // once the caller has signaled that bootstrap is complete by closing the channel. if clientOptions.BootstrapRateLimit > 0 && opts != nil && opts.BootstrapComplete != nil { - ec.logger.WithField(logfields.EtcdQPSLimit, clientOptions.BootstrapRateLimit).Info("Setting client QPS limit for bootstrap") + ec.logger.Info( + "Setting client QPS limit for bootstrap", + logfields.EtcdQPSLimit, clientOptions.BootstrapRateLimit, + ) initialLimit = clientOptions.BootstrapRateLimit go func() { select { case <-ec.client.Ctx().Done(): case <-opts.BootstrapComplete: - ec.logger.WithField(logfields.EtcdQPSLimit, clientOptions.RateLimit).Info("Bootstrap complete, updating client QPS limit") + ec.logger.Info( + "Bootstrap complete, updating client QPS limit", + logfields.EtcdQPSLimit, clientOptions.RateLimit, + ) ec.limiter.SetRateLimit(rate.Limit(clientOptions.RateLimit)) } }() @@ -592,8 +586,8 @@ func connectEtcdClient(ctx context.Context, config *client.Config, cfgPath strin leaseTTL = defaults.KVstoreLeaseTTL } - ec.leaseManager = newEtcdLeaseManager(c, leaseTTL, etcdMaxKeysPerLease, ec.expiredLeaseObserver, ec.logger) - ec.lockLeaseManager = newEtcdLeaseManager(c, defaults.LockLeaseTTL, etcdMaxKeysPerLease, nil, ec.logger) + ec.leaseManager = newEtcdLeaseManager(ec.logger, c, leaseTTL, etcdMaxKeysPerLease, ec.expiredLeaseObserver) + ec.lockLeaseManager = newEtcdLeaseManager(ec.logger, c, defaults.LockLeaseTTL, etcdMaxKeysPerLease, nil) go ec.asyncConnectEtcdClient(errChan) @@ -748,7 +742,10 @@ func (e *etcdClient) LockPath(ctx context.Context, path string) (locker KVLocker func (e *etcdClient) DeletePrefix(ctx context.Context, path string) (err error) { defer func() { - Trace("DeletePrefix", err, logrus.Fields{fieldPrefix: path}) + Trace(e.logger, "DeletePrefix", + logfields.Error, err, + fieldPrefix, path, + ) }() lr, err := e.limiter.Wait(ctx) if err != nil { @@ -775,7 +772,7 @@ func (e *etcdClient) watch(ctx context.Context, prefix string, events emitter) { localCache := watcherCache{} listSignalSent := false - scopedLog := e.logger.WithField(fieldPrefix, prefix) + scopedLog := e.logger.With(fieldPrefix, prefix) scopedLog.Info("Starting watcher") defer func() { @@ -814,9 +811,17 @@ reList: lr.Error(err, -1) if attempt := errLimiter.Attempt(); attempt < 10 { - scopedLog.WithError(Hint(err)).WithField(logfields.Attempt, attempt).Info("Unable to list keys before starting watcher, will retry") + scopedLog.Info( + "Unable to list keys before starting watcher, will retry", + logfields.Error, Hint(err), + logfields.Attempt, attempt, + ) } else { - scopedLog.WithError(Hint(err)).WithField(logfields.Attempt, attempt).Warn("Unable to list keys before starting watcher, will retry") + scopedLog.Warn( + "Unable to list keys before starting watcher, will retry", + logfields.Error, Hint(err), + logfields.Attempt, attempt, + ) } errLimiter.Wait(ctx) @@ -825,10 +830,11 @@ reList: lr.Done() errLimiter.Reset() - scopedLog.WithFields(logrus.Fields{ - logfields.Count: len(kvs), - fieldRev: revision, - }).Info("Successfully listed keys before starting watcher") + scopedLog.Info( + "Successfully listed keys before starting watcher", + logfields.Count, len(kvs), + fieldRev, revision, + ) for _, key := range kvs { t := EventTypeCreate @@ -839,7 +845,11 @@ reList: localCache.MarkInUse(key.Key) if traceEnabled { - scopedLog.Debugf("Emitting list result as %s event for %s=%s", t, key.Key, key.Value) + scopedLog.Debug("Emitting list result", + logfields.EventType, t, + logfields.Key, key.Key, + logfields.Value, key.Value, + ) } if !events.emit(ctx, KeyValueEvent{ @@ -863,7 +873,9 @@ reList: } if traceEnabled { - scopedLog.Debugf("Emitting EventTypeDelete event for %s", k) + scopedLog.Debug("Emitting EventTypeDelete event", + logfields.Key, k, + ) } return events.emit(ctx, event) }) { @@ -879,7 +891,10 @@ reList: } recreateWatcher: - scopedLog.WithField(fieldRev, nextRev).Info("Starting to watch prefix") + scopedLog.Info( + "Starting to watch prefix", + fieldRev, nextRev, + ) lr, err = e.limiter.Wait(ctx) if err != nil { @@ -909,21 +924,28 @@ reList: goto recreateWatcher } - scopedLog := scopedLog.WithField(fieldRev, r.Header.Revision) - if err := r.Err(); err != nil { switch { case errors.Is(err, ErrOperationAbortedByInterceptor): // Aborted on purpose by a custom interceptor. - scopedLog.WithError(Hint(err)).Debug("Etcd watcher aborted") + scopedLog.Debug("Etcd watcher aborted", + logfields.Error, Hint(err), + fieldRev, r.Header.Revision, + ) case errors.Is(err, v3rpcErrors.ErrCompacted): // We tried to watch on a compacted // revision that may no longer exist, // recreate the watcher and try to // watch on the next possible revision - scopedLog.WithError(Hint(err)).Info("Tried watching on compacted revision. Triggering relist of all keys") + scopedLog.Info("Tried watching on compacted revision. Triggering relist of all keys", + logfields.Error, Hint(err), + fieldRev, r.Header.Revision, + ) default: - scopedLog.WithError(Hint(err)).Info("Etcd watcher errored. Triggering relist of all keys") + scopedLog.Info("Etcd watcher errored. Triggering relist of all keys", + logfields.Error, Hint(err), + fieldRev, r.Header.Revision, + ) } // mark all local keys in state for @@ -936,7 +958,9 @@ reList: nextRev = r.Header.Revision + 1 if traceEnabled { - scopedLog.Debugf("Received event from etcd: %+v", r) + scopedLog.Debug("Received event from etcd", + logfields.Response, r, + ) } for _, ev := range r.Events { @@ -958,7 +982,11 @@ reList: } if traceEnabled { - scopedLog.Debugf("Emitting %s event for %s=%s", event.Typ, event.Key, event.Value) + scopedLog.Debug("Emitting event", + logfields.EventType, event.Typ, + logfields.Key, event.Key, + logfields.Value, event.Value, + ) } if !events.emit(ctx, event) { return @@ -969,7 +997,7 @@ reList: } } -func (e *etcdClient) paginatedList(ctx context.Context, log *logrus.Entry, prefix string) (kvs []*mvccpb.KeyValue, revision int64, err error) { +func (e *etcdClient) paginatedList(ctx context.Context, log *slog.Logger, prefix string) (kvs []*mvccpb.KeyValue, revision int64, err error) { start, end := prefix, client.GetPrefixRangeEnd(prefix) for { @@ -982,10 +1010,11 @@ func (e *etcdClient) paginatedList(ctx context.Context, log *logrus.Entry, prefi return nil, 0, err } - log.WithFields(logrus.Fields{ - fieldNumEntries: len(res.Kvs), - fieldRemainingEntries: res.Count - int64(len(res.Kvs)), - }).Debug("Received list response from etcd") + log.Debug( + "Received list response from etcd", + fieldNumEntries, len(res.Kvs), + fieldRemainingEntries, res.Count-int64(len(res.Kvs)), + ) if kvs == nil { kvs = make([]*mvccpb.KeyValue, 0, res.Count) @@ -1013,7 +1042,9 @@ func (e *etcdClient) determineEndpointStatus(ctx context.Context, endpointAddres ctxTimeout, cancel := context.WithTimeout(ctx, statusCheckTimeout) defer cancel() - e.logger.Debugf("Checking status to etcd endpoint %s", endpointAddress) + e.logger.Debug("Checking status to etcd endpoint", + logfields.Endpoints, endpointAddress, + ) status, err := e.client.Status(ctxTimeout, endpointAddress) if err != nil { @@ -1112,8 +1143,10 @@ func (e *etcdClient) statusChecker() { case e.statusCheckErrors <- err: default: // Channel's buffer is full, skip sending errors to the channel but log warnings instead - log.WithError(err). - Warning("Status check error channel is full, dropping this error") + e.logger.Warn( + "Status check error channel is full, dropping this error", + logfields.Error, err, + ) } } @@ -1138,9 +1171,15 @@ func (e *etcdClient) Status() *models.Status { // GetIfLocked returns value of key if the client is still holding the given lock. func (e *etcdClient) GetIfLocked(ctx context.Context, key string, lock KVLocker) (bv []byte, err error) { - defer func() { - Trace("GetIfLocked", err, logrus.Fields{fieldKey: key, fieldValue: string(bv)}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "GetIfLocked", + logfields.Error, err, + fieldKey, key, + fieldValue, string(bv), + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return nil, Hint(err) @@ -1172,9 +1211,15 @@ func (e *etcdClient) GetIfLocked(ctx context.Context, key string, lock KVLocker) // Get returns value of key func (e *etcdClient) Get(ctx context.Context, key string) (bv []byte, err error) { - defer func() { - Trace("Get", err, logrus.Fields{fieldKey: key, fieldValue: string(bv)}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "Get", + logfields.Error, err, + fieldKey, key, + fieldValue, string(bv), + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return nil, Hint(err) @@ -1198,9 +1243,14 @@ func (e *etcdClient) Get(ctx context.Context, key string) (bv []byte, err error) // DeleteIfLocked deletes a key if the client is still holding the given lock. func (e *etcdClient) DeleteIfLocked(ctx context.Context, key string, lock KVLocker) (err error) { - defer func() { - Trace("DeleteIfLocked", err, logrus.Fields{fieldKey: key}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "DeleteIfLocked", + logfields.Error, err, + fieldKey, key, + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return Hint(err) @@ -1226,9 +1276,14 @@ func (e *etcdClient) DeleteIfLocked(ctx context.Context, key string, lock KVLock // Delete deletes a key func (e *etcdClient) Delete(ctx context.Context, key string) (err error) { - defer func() { - Trace("Delete", err, logrus.Fields{fieldKey: key}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "Delete", + logfields.Error, err, + fieldKey, key, + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return Hint(err) @@ -1250,9 +1305,16 @@ func (e *etcdClient) Delete(ctx context.Context, key string) (err error) { // UpdateIfLocked updates a key if the client is still holding the given lock. func (e *etcdClient) UpdateIfLocked(ctx context.Context, key string, value []byte, lease bool, lock KVLocker) (err error) { - defer func() { - Trace("UpdateIfLocked", err, logrus.Fields{fieldKey: key, fieldValue: string(value), fieldAttachLease: lease}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "UpdateIfLocked", + logfields.Error, err, + fieldKey, key, + fieldValue, string(value), + fieldAttachLease, lease, + ) + }() + } var leaseID client.LeaseID if lease { leaseID, err = e.leaseManager.GetLeaseID(ctx, key) @@ -1285,9 +1347,16 @@ func (e *etcdClient) UpdateIfLocked(ctx context.Context, key string, value []byt // Update creates or updates a key func (e *etcdClient) Update(ctx context.Context, key string, value []byte, lease bool) (err error) { - defer func() { - Trace("Update", err, logrus.Fields{fieldKey: key, fieldValue: string(value), fieldAttachLease: lease}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "Update", + logfields.Error, err, + fieldKey, key, + fieldValue, string(value), + fieldAttachLease, lease, + ) + }() + } var leaseID client.LeaseID if lease { leaseID, err = e.leaseManager.GetLeaseID(ctx, key) @@ -1313,9 +1382,17 @@ func (e *etcdClient) Update(ctx context.Context, key string, value []byte, lease // UpdateIfDifferentIfLocked updates a key if the value is different and if the client is still holding the given lock. func (e *etcdClient) UpdateIfDifferentIfLocked(ctx context.Context, key string, value []byte, lease bool, lock KVLocker) (recreated bool, err error) { - defer func() { - Trace("UpdateIfDifferentIfLocked", err, logrus.Fields{fieldKey: key, fieldValue: value, fieldAttachLease: lease, "recreated": recreated}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "UpdateIfDifferentIfLocked", + logfields.Error, err, + fieldKey, key, + fieldValue, string(value), + fieldAttachLease, lease, + fieldRecreated, recreated, + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return false, Hint(err) @@ -1355,9 +1432,17 @@ func (e *etcdClient) UpdateIfDifferentIfLocked(ctx context.Context, key string, // UpdateIfDifferent updates a key if the value is different func (e *etcdClient) UpdateIfDifferent(ctx context.Context, key string, value []byte, lease bool) (recreated bool, err error) { - defer func() { - Trace("UpdateIfDifferent", err, logrus.Fields{fieldKey: key, fieldValue: value, fieldAttachLease: lease, "recreated": recreated}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "UpdateIfDifferent", + logfields.Error, err, + fieldKey, key, + fieldValue, string(value), + fieldAttachLease, lease, + fieldRecreated, recreated, + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return false, Hint(err) @@ -1385,9 +1470,17 @@ func (e *etcdClient) UpdateIfDifferent(ctx context.Context, key string, value [] // CreateOnlyIfLocked atomically creates a key if the client is still holding the given lock or fails if it already exists func (e *etcdClient) CreateOnlyIfLocked(ctx context.Context, key string, value []byte, lease bool, lock KVLocker) (success bool, err error) { - defer func() { - Trace("CreateOnlyIfLocked", err, logrus.Fields{fieldKey: key, fieldValue: value, fieldAttachLease: lease, "success": success}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "CreateOnlyIfLocked", + logfields.Error, err, + fieldKey, key, + fieldValue, string(value), + fieldAttachLease, lease, + fieldSuccess, success, + ) + }() + } var leaseID client.LeaseID if lease { leaseID, err = e.leaseManager.GetLeaseID(ctx, key) @@ -1450,9 +1543,17 @@ func (e *etcdClient) CreateOnlyIfLocked(ctx context.Context, key string, value [ // CreateOnly creates a key with the value and will fail if the key already exists func (e *etcdClient) CreateOnly(ctx context.Context, key string, value []byte, lease bool) (success bool, err error) { - defer func() { - Trace("CreateOnly", err, logrus.Fields{fieldKey: key, fieldValue: value, fieldAttachLease: lease, "success": success}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "CreateOnly", + logfields.Error, err, + fieldKey, key, + fieldValue, string(value), + fieldAttachLease, lease, + fieldSuccess, success, + ) + }() + } var leaseID client.LeaseID if lease { leaseID, err = e.leaseManager.GetLeaseID(ctx, key) @@ -1485,9 +1586,15 @@ func (e *etcdClient) CreateOnly(ctx context.Context, key string, value []byte, l // ListPrefixIfLocked returns a list of keys matching the prefix only if the client is still holding the given lock. func (e *etcdClient) ListPrefixIfLocked(ctx context.Context, prefix string, lock KVLocker) (v KeyValuePairs, err error) { - defer func() { - Trace("ListPrefixIfLocked", err, logrus.Fields{fieldPrefix: prefix, fieldNumEntries: len(v)}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "ListPrefixIfLocked", + logfields.Error, err, + fieldPrefix, prefix, + fieldNumEntries, len(v), + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return nil, Hint(err) @@ -1523,9 +1630,15 @@ func (e *etcdClient) ListPrefixIfLocked(ctx context.Context, prefix string, lock // ListPrefix returns a map of matching keys func (e *etcdClient) ListPrefix(ctx context.Context, prefix string) (v KeyValuePairs, err error) { - defer func() { - Trace("ListPrefix", err, logrus.Fields{fieldPrefix: prefix, fieldNumEntries: len(v)}) - }() + if traceEnabled { + defer func() { + Trace(e.logger, "ListPrefix", + logfields.Error, err, + fieldPrefix, prefix, + fieldNumEntries, len(v), + ) + }() + } lr, err := e.limiter.Wait(ctx) if err != nil { return nil, Hint(err) @@ -1559,7 +1672,10 @@ func (e *etcdClient) Close() { close(e.stopStatusChecker) if err := e.client.Close(); err != nil { - e.logger.WithError(err).Warning("Failed to close etcd client") + e.logger.Warn( + "Failed to close etcd client", + logfields.Error, err, + ) } // Wait until all child goroutines spawned by the lease managers have terminated. @@ -1598,20 +1714,21 @@ func (e *etcdClient) expiredLeaseObserver(key string) { // UserEnforcePresence creates a user in etcd if not already present, and grants the specified roles. func (e *etcdClient) UserEnforcePresence(ctx context.Context, name string, roles []string) error { - scopedLog := e.logger.WithField(FieldUser, name) - - scopedLog.Debug("Creating user") + e.logger.Debug("Creating user", FieldUser, name) _, err := e.client.Auth.UserAddWithOptions(ctx, name, "", &client.UserAddOptions{NoPassword: true}) if err != nil { if errors.Is(err, v3rpcErrors.ErrUserAlreadyExist) { - scopedLog.Debug("User already exists") + e.logger.Debug("User already exists", FieldUser, name) } else { return err } } for _, role := range roles { - scopedLog.WithField(FieldRole, role).Debug("Granting role to user") + e.logger.Debug("Granting role to user", + FieldRole, role, + FieldUser, name, + ) _, err := e.client.Auth.UserGrantRole(ctx, name, role) if err != nil { @@ -1624,13 +1741,11 @@ func (e *etcdClient) UserEnforcePresence(ctx context.Context, name string, roles // UserEnforcePresence deletes a user from etcd, if present. func (e *etcdClient) UserEnforceAbsence(ctx context.Context, name string) error { - scopedLog := e.logger.WithField(FieldUser, name) - - scopedLog.Debug("Deleting user") + e.logger.Debug("Deleting user", FieldUser, name) _, err := e.client.Auth.UserDelete(ctx, name) if err != nil { if errors.Is(err, v3rpcErrors.ErrUserNotFound) { - scopedLog.Debug("User not found") + e.logger.Debug("User not found", FieldUser, name) } else { return err } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/etcd_lease.go b/vendor/github.com/cilium/cilium/pkg/kvstore/etcd_lease.go index 2e0a2f6d97..2e6ae9094a 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/etcd_lease.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/etcd_lease.go @@ -6,15 +6,16 @@ package kvstore import ( "context" "errors" + "log/slog" "strings" "sync" - "github.com/sirupsen/logrus" v3rpcErrors "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" client "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/client/v3/concurrency" "github.com/cilium/cilium/pkg/lock" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/spanstat" "github.com/cilium/cilium/pkg/time" ) @@ -28,7 +29,7 @@ type leaseInfo struct { // which lease is attached to which etcd key. type etcdLeaseManager struct { client *client.Client - log logrus.FieldLogger + log *slog.Logger ttl time.Duration limit uint32 @@ -44,10 +45,10 @@ type etcdLeaseManager struct { } // newEtcdLeaseManager builds and returns a new lease manager instance. -func newEtcdLeaseManager(cl *client.Client, ttl time.Duration, limit uint32, expired func(key string), log logrus.FieldLogger) *etcdLeaseManager { +func newEtcdLeaseManager(logger *slog.Logger, cl *client.Client, ttl time.Duration, limit uint32, expired func(key string)) *etcdLeaseManager { return &etcdLeaseManager{ client: cl, - log: log, + log: logger, ttl: ttl, limit: limit, @@ -254,10 +255,11 @@ func (elm *etcdLeaseManager) newSession(ctx context.Context) (session *concurren elm.wg.Add(1) go elm.waitForExpiration(session) - elm.log.WithFields(logrus.Fields{ - "LeaseID": leaseID, - "TTL": elm.ttl, - }).Info("New lease successfully acquired") + elm.log.Info( + "New lease successfully acquired", + logfields.LeaseID, leaseID, + logfields.TTL, elm.ttl, + ) return session, nil } @@ -275,7 +277,10 @@ func (elm *etcdLeaseManager) waitForExpiration(session *concurrency.Session) { default: } - elm.log.WithField("LeaseID", session.Lease()).Warning("Lease expired") + elm.log.Warn( + "Lease expired", + logfields.LeaseID, session.Lease(), + ) elm.mu.Lock() delete(elm.leases, session.Lease()) diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/lock.go b/vendor/github.com/cilium/cilium/pkg/kvstore/lock.go index b28c74f083..6644a4f366 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/lock.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/lock.go @@ -6,14 +6,15 @@ package kvstore import ( "context" "fmt" + "log/slog" "github.com/davecgh/go-spew/spew" "github.com/google/uuid" - "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/debug" "github.com/cilium/cilium/pkg/defaults" "github.com/cilium/cilium/pkg/lock" + "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/time" ) @@ -66,11 +67,11 @@ func (pl *pathLocks) DebugStatus() string { return str } -func (pl *pathLocks) runGC() { +func (pl *pathLocks) runGC(logger *slog.Logger) { pl.mutex.Lock() for path, owner := range pl.lockPaths { if time.Since(owner.created) > staleLockTimeout { - log.WithField("path", path).Error("Forcefully unlocking local kvstore lock") + logger.Error("Forcefully unlocking local kvstore lock", fieldKey, path) delete(pl.lockPaths, path) } } @@ -113,6 +114,7 @@ type Lock struct { path string id uuid.UUID kvLock KVLocker + logger *slog.Logger } // LockPath locks the specified path. The key for the lock is not the path @@ -120,7 +122,7 @@ type Lock struct { // returned also contains a patch specific local Mutex which will be held. // // It is required to call Unlock() on the returned Lock to unlock -func LockPath(ctx context.Context, backend BackendOperations, path string) (l *Lock, err error) { +func LockPath(ctx context.Context, logger *slog.Logger, backend BackendOperations, path string) (l *Lock, err error) { id, err := kvstoreLocks.lock(ctx, path) if err != nil { return nil, err @@ -129,20 +131,20 @@ func LockPath(ctx context.Context, backend BackendOperations, path string) (l *L lock, err := backend.LockPath(ctx, path) if err != nil { kvstoreLocks.unlock(path, id) - Trace("Failed to lock", err, logrus.Fields{fieldKey: path}) + Trace(logger, "Failed to lock", fieldKey, path) err = fmt.Errorf("error while locking path %s: %w", path, err) return nil, err } - Trace("Successful lock", err, logrus.Fields{fieldKey: path}) - return &Lock{kvLock: lock, path: path, id: id}, err + Trace(logger, "Successful lock", fieldKey, path) + return &Lock{kvLock: lock, path: path, id: id, logger: logger}, err } // RunLockGC inspects all local kvstore locks to determine whether they have // been held longer than the stale lock timeout, and if so, unlocks them // forceably. -func RunLockGC() { - kvstoreLocks.runGC() +func RunLockGC(logger *slog.Logger) { + kvstoreLocks.runGC(logger) } // Unlock unlocks a lock @@ -154,12 +156,15 @@ func (l *Lock) Unlock(ctx context.Context) error { // Unlock kvstore mutex first err := l.kvLock.Unlock(ctx) if err != nil { - log.WithError(err).WithField("path", l.path).Error("Unable to unlock kvstore lock") + l.logger.Error("Unable to unlock kvstore lock", + logfields.Error, err, + fieldKey, l.path, + ) } // unlock local lock even if kvstore cannot be unlocked kvstoreLocks.unlock(l.path, l.id) - Trace("Unlocked", nil, logrus.Fields{fieldKey: l.path}) + Trace(l.logger, "Unlocked", fieldKey, l.path) return err } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/logfields.go b/vendor/github.com/cilium/cilium/pkg/kvstore/logfields.go index c272cbb33c..b8eaa15009 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/logfields.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/logfields.go @@ -4,12 +4,9 @@ package kvstore import ( - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" ) -var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "kvstore") - const ( // fieldKVStoreModule is the name of the kvstore backend (etcd) fieldKVStoreModule = "module" @@ -40,4 +37,8 @@ const ( // FieldRole identifies a role in the kvstore FieldRole = "role" + + fieldRecreated = "recreated" + + fieldSuccess = "success" ) diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/store/cell.go b/vendor/github.com/cilium/cilium/pkg/kvstore/store/cell.go index 74730f7c0c..04ca5411f3 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/store/cell.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/store/cell.go @@ -4,6 +4,8 @@ package store import ( + "log/slog" + "github.com/cilium/hive/cell" "github.com/cilium/cilium/pkg/metrics" @@ -25,23 +27,25 @@ type Factory interface { } type factoryImpl struct { + logger *slog.Logger metrics *Metrics } func (w *factoryImpl) NewSyncStore(clusterName string, backend SyncStoreBackend, prefix string, opts ...WSSOpt) SyncStore { - return newWorkqueueSyncStore(clusterName, backend, prefix, w.metrics, opts...) + return newWorkqueueSyncStore(w.logger, clusterName, backend, prefix, w.metrics, opts...) } func (w *factoryImpl) NewWatchStore(clusterName string, keyCreator KeyCreator, observer Observer, opts ...RWSOpt) WatchStore { - return newRestartableWatchStore(clusterName, keyCreator, observer, w.metrics, opts...) + return newRestartableWatchStore(w.logger, clusterName, keyCreator, observer, w.metrics, opts...) } func (w *factoryImpl) NewWatchStoreManager(backend WatchStoreBackend, clusterName string) WatchStoreManager { - return newWatchStoreManagerSync(backend, clusterName, w) + return newWatchStoreManagerSync(w.logger, backend, clusterName, w) } -func NewFactory(storeMetrics *Metrics) Factory { +func NewFactory(logger *slog.Logger, storeMetrics *Metrics) Factory { return &factoryImpl{ + logger: logger, metrics: storeMetrics, } } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/store/store.go b/vendor/github.com/cilium/cilium/pkg/kvstore/store/store.go index 382bbf49fc..9b06675067 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/store/store.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/store/store.go @@ -6,16 +6,15 @@ package store import ( "context" "fmt" + "log/slog" + "maps" "path" "strings" "sync" - "github.com/sirupsen/logrus" - "github.com/cilium/cilium/pkg/controller" "github.com/cilium/cilium/pkg/kvstore" "github.com/cilium/cilium/pkg/lock" - "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/option" "github.com/cilium/cilium/pkg/time" @@ -30,8 +29,6 @@ const ( var ( controllers controller.Manager - log = logging.DefaultLogger.WithField(logfields.LogSubsys, "shared-store") - kvstoreSyncControllerGroup = controller.NewGroup("kvstore-sync") ) @@ -100,6 +97,7 @@ func (c *Configuration) validate() error { // SharedStore is an instance of a shared store. It is created with // JoinSharedStore() and released with the SharedStore.Close() function. type SharedStore struct { + logger *slog.Logger // conf is a copy of the store configuration. This field is never // mutated after JoinSharedStore() so it is safe to access this without // a lock. @@ -207,12 +205,13 @@ func (kv *KVPair) Unmarshal(key string, data []byte) error { // store is initialized with the contents of the kvstore. An error is returned // if the contents cannot be retrieved synchronously from the kvstore. Starts a // controller to continuously synchronize the store with the kvstore. -func JoinSharedStore(c Configuration) (*SharedStore, error) { +func JoinSharedStore(logger *slog.Logger, c Configuration) (*SharedStore, error) { if err := c.validate(); err != nil { return nil, err } s := &SharedStore{ + logger: logger, conf: c, localKeys: map[string]LocalKey{}, sharedKeys: map[string]Key{}, @@ -223,6 +222,7 @@ func JoinSharedStore(c Configuration) (*SharedStore, error) { s.conf.Context, s.stop = context.WithCancel(s.conf.Context) s.name = "store-" + s.conf.Prefix + s.logger = s.logger.With(logfields.Name, s.name) s.controllerName = "kvstore-sync-" + s.name if err := s.listAndStartWatcher(); err != nil { @@ -271,7 +271,7 @@ func (s *SharedStore) Close(ctx context.Context) { for name, key := range s.localKeys { if err := s.backend.Delete(ctx, s.keyPath(key)); err != nil { - s.getLogger().WithError(err).Warning("Unable to delete key in kvstore") + s.logger.Warn("Unable to delete key in kvstore", logfields.Error, err) } delete(s.localKeys, name) @@ -356,12 +356,7 @@ func (s *SharedStore) NumEntries() int { func (s *SharedStore) SharedKeysMap() map[string]Key { s.mutex.RLock() defer s.mutex.RUnlock() - sharedKeysCopy := make(map[string]Key, len(s.sharedKeys)) - - for k, v := range s.sharedKeys { - sharedKeysCopy[k] = v - } - return sharedKeysCopy + return maps.Clone(s.sharedKeys) } // UpdateLocalKeySync synchronously synchronizes a local key with the kvstore @@ -395,19 +390,13 @@ func (s *SharedStore) DeleteLocalKey(ctx context.Context, key NamedKey) { if ok { if err != nil { - s.getLogger().WithError(err).Warning("Unable to delete key in kvstore") + s.logger.Warn("Unable to delete key in kvstore", logfields.Error, err) } s.onDelete(key) } } -func (s *SharedStore) getLogger() *logrus.Entry { - return log.WithFields(logrus.Fields{ - "storeName": s.name, - }) -} - func (s *SharedStore) updateKey(name string, value []byte) error { newKey := s.conf.KeyCreator() if err := newKey.Unmarshal(name, value); err != nil { @@ -435,16 +424,21 @@ func (s *SharedStore) deleteSharedKey(name string) { _, ok := s.sharedKeys[name] s.mutex.RUnlock() if ok { - s.getLogger().WithFields(logrus.Fields{"key": name, "timeWindow": s.conf.SharedKeyDeleteDelay}). - Warning("Received delete event for key which re-appeared within delay time window") + s.logger.Warn( + "Received delete event for key which re-appeared within delay time window", + logfields.Key, name, + logfields.TimeWindow, s.conf.SharedKeyDeleteDelay, + ) return } s.onDelete(existingKey) }() } else { - s.getLogger().WithField("key", name). - Warning("Unable to find deleted key in local state") + s.logger.Warn( + "Unable to find deleted key in local state", + logfields.Key, name, + ) } } @@ -469,19 +463,19 @@ func (s *SharedStore) listAndStartWatcher() error { func (s *SharedStore) watcher(listDone chan struct{}) { events := s.backend.ListAndWatch(s.conf.Context, s.conf.Prefix) + logger := s.logger for event := range events { if event.Typ == kvstore.EventTypeListDone { - s.getLogger().Debug("Initial list of objects received from kvstore") + logger.Debug("Initial list of objects received from kvstore") close(listDone) continue } - logger := s.getLogger().WithFields(logrus.Fields{ - "key": event.Key, - "eventType": event.Typ, - }) - - logger.Debugf("Received key update via kvstore [value %s]", string(event.Value)) + logger.Debug("Received key update via kvstore", + logfields.Value, string(event.Value), + logfields.Key, event.Key, + logfields.EventType, event.Typ, + ) keyName := strings.TrimPrefix(event.Key, s.conf.Prefix) if keyName[0] == '/' { @@ -491,12 +485,22 @@ func (s *SharedStore) watcher(listDone chan struct{}) { switch event.Typ { case kvstore.EventTypeCreate, kvstore.EventTypeModify: if err := s.updateKey(keyName, event.Value); err != nil { - logger.WithError(err).Warningf("Unable to unmarshal store value: %s", string(event.Value)) + logger.Warn( + "Unable to unmarshal store value", + logfields.Error, err, + logfields.Value, string(event.Value), + logfields.Key, event.Key, + logfields.EventType, event.Typ, + ) } case kvstore.EventTypeDelete: if localKey := s.lookupLocalKey(keyName); localKey != nil { - logger.Warning("Received delete event for local key. Re-creating the key in the kvstore") + logger.Warn( + "Received delete event for local key. Re-creating the key in the kvstore", + logfields.Key, event.Key, + logfields.EventType, event.Typ, + ) s.syncLocalKey(s.conf.Context, localKey, true) } else { diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/store/syncstore.go b/vendor/github.com/cilium/cilium/pkg/kvstore/store/syncstore.go index bc2008ace6..e946d2983f 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/store/syncstore.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/store/syncstore.go @@ -7,13 +7,13 @@ import ( "bytes" "context" "fmt" + "log/slog" "path" "strings" "sync" "sync/atomic" "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" "k8s.io/client-go/util/workqueue" "github.com/cilium/cilium/pkg/kvstore" @@ -74,7 +74,7 @@ type wqSyncStore struct { syncedKey string syncedCallbacks []func(context.Context) - log *logrus.Entry + log *slog.Logger queuedMetric prometheus.Gauge errorsMetric prometheus.Counter syncedMetric prometheus.Gauge @@ -118,7 +118,7 @@ func WSSWithSyncedKeyOverride(key string) WSSOpt { // NewWorkqueueSyncStore returns a SyncStore instance which leverages a workqueue // to coalescence update/delete requests and handle retries in case of errors. -func newWorkqueueSyncStore(clusterName string, backend SyncStoreBackend, prefix string, m *Metrics, opts ...WSSOpt) SyncStore { +func newWorkqueueSyncStore(logger *slog.Logger, clusterName string, backend SyncStoreBackend, prefix string, m *Metrics, opts ...WSSOpt) SyncStore { wss := &wqSyncStore{ backend: backend, prefix: prefix, @@ -129,14 +129,14 @@ func newWorkqueueSyncStore(clusterName string, backend SyncStoreBackend, prefix limiter: workqueue.DefaultTypedControllerRateLimiter[workqueueKey](), syncedKey: prefix, - log: log.WithField(logfields.Prefix, prefix), + log: logger.With(logfields.Prefix, prefix), } for _, opt := range opts { opt(wss) } - wss.log = wss.log.WithField(logfields.ClusterName, wss.source) + wss.log = wss.log.With(logfields.ClusterName, wss.source) wss.workqueue = workqueue.NewTypedRateLimitingQueue(wss.limiter) wss.queuedMetric = m.KVStoreSyncQueueSize.WithLabelValues(kvstore.GetScopeFromKey(prefix), wss.source) wss.errorsMetric = m.KVStoreSyncErrors.WithLabelValues(kvstore.GetScopeFromKey(prefix), wss.source) @@ -154,7 +154,7 @@ func (wss *wqSyncStore) Run(ctx context.Context) { wss.backend.RegisterLeaseExpiredObserver(wss.prefix, wss.handleExpiredLease) wss.backend.RegisterLeaseExpiredObserver(wss.getSyncedKey(), wss.handleExpiredLease) - wss.log.WithField(logfields.Workers, wss.workers).Info("Starting workqueue-based sync store") + wss.log.Info("Starting workqueue-based sync store", logfields.Workers, wss.workers) wg.Add(int(wss.workers)) for i := uint(0); i < wss.workers; i++ { go func() { @@ -187,7 +187,7 @@ func (wss *wqSyncStore) UpsertKey(_ context.Context, k Key) error { prevValue, loaded := wss.state.Swap(key, value) if loaded && bytes.Equal(prevValue, value) { - wss.log.WithField(logfields.Key, k).Debug("ignoring upsert request for already up-to-date key") + wss.log.Debug("ignoring upsert request for already up-to-date key", logfields.Key, k) } else { if !wss.synced.Load() { wss.pendingSync.Store(key, struct{}{}) @@ -209,7 +209,7 @@ func (wss *wqSyncStore) DeleteKey(_ context.Context, k NamedKey) error { wss.workqueue.Add(workqueueKey{value: key}) wss.queuedMetric.Set(float64(wss.workqueue.Len())) } else { - wss.log.WithField(logfields.Key, key).Debug("ignoring delete request for non-existing key") + wss.log.Debug("ignoring delete request for non-existing key", logfields.Key, key) } return nil @@ -268,27 +268,33 @@ func (wss *wqSyncStore) handle(ctx context.Context, item workqueueKey) error { } func (wss *wqSyncStore) handleUpsert(ctx context.Context, key string, value []byte) error { - scopedLog := wss.log.WithField(logfields.Key, key) - err := wss.backend.Update(ctx, wss.keyPath(key), value, wss.withLease) if err != nil { - scopedLog.WithError(err).Warning("Failed upserting key in kvstore. Retrying...") + wss.log.Warn("Failed upserting key in kvstore. Retrying...", + logfields.Error, err, + logfields.Key, key, + ) return err } - scopedLog.Debug("Upserted key in kvstore") + wss.log.Debug("Upserted key in kvstore", + logfields.Key, key, + ) return nil } func (wss *wqSyncStore) handleDelete(ctx context.Context, key string) error { - scopedLog := wss.log.WithField(logfields.Key, key) - if err := wss.backend.Delete(ctx, wss.keyPath(key)); err != nil { - scopedLog.WithError(err).Warning("Failed deleting key from kvstore. Retrying...") + wss.log.Warn("Failed deleting key from kvstore. Retrying...", + logfields.Error, err, + logfields.Key, key, + ) return err } - scopedLog.Debug("Deleted key from kvstore") + wss.log.Debug("Deleted key from kvstore", + logfields.Key, key, + ) return nil } @@ -305,15 +311,19 @@ func (wss *wqSyncStore) handleSync(ctx context.Context, skipCallbacks bool) erro } key := wss.getSyncedKey() - scopedLog := wss.log.WithField(logfields.Key, key) err := wss.backend.Update(ctx, key, []byte(time.Now().Format(time.RFC3339)), wss.withLease) if err != nil { - scopedLog.WithError(err).Warning("Failed upserting synced key in kvstore. Retrying...") + wss.log.Warn("Failed upserting synced key in kvstore. Retrying...", + logfields.Error, err, + logfields.Key, key, + ) return err } - wss.log.Info("Initial synchronization from the external source completed") + wss.log.Info("Initial synchronization from the external source completed", + logfields.Key, key, + ) wss.syncedMetric.Set(metrics.BoolToFloat64(true)) // Execute any callback that might have been registered. @@ -341,7 +351,7 @@ func (wss *wqSyncStore) handleExpiredLease(key string) { key = strings.TrimPrefix(strings.TrimPrefix(key, wss.prefix), "/") _, ok := wss.state.Load(key) if ok { - wss.log.WithField(logfields.Key, key).Debug("enqueuing upsert request for key as the attached lease expired") + wss.log.Debug("enqueuing upsert request for key as the attached lease expired", logfields.Key, key) if !wss.synced.Load() { wss.pendingSync.Store(key, struct{}{}) } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstore.go b/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstore.go index 0287fb0a0d..bfd6aba568 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstore.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstore.go @@ -5,13 +5,14 @@ package store import ( "context" + "log/slog" "strings" "sync/atomic" "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/kvstore" + "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/metrics" "github.com/cilium/cilium/pkg/metrics/metric" @@ -87,7 +88,8 @@ type restartableWatchStore struct { state map[string]*rwsEntry numEntries atomic.Uint64 - log *logrus.Entry + baseLogger *slog.Logger + log *slog.Logger entriesMetric prometheus.Gauge syncMetric metric.Vec[metric.Gauge] } @@ -96,7 +98,7 @@ type restartableWatchStore struct { // restarting the watch operation multiple times, automatically handling // the emission of deletion events for all stale entries (if enabled). It // shall be restarted only once the previous Watch execution terminated. -func newRestartableWatchStore(clusterName string, keyCreator KeyCreator, observer Observer, m *Metrics, opts ...RWSOpt) WatchStore { +func newRestartableWatchStore(logger *slog.Logger, clusterName string, keyCreator KeyCreator, observer Observer, m *Metrics, opts ...RWSOpt) WatchStore { rws := &restartableWatchStore{ source: clusterName, keyCreator: keyCreator, @@ -104,7 +106,8 @@ func newRestartableWatchStore(clusterName string, keyCreator KeyCreator, observe state: make(map[string]*rwsEntry), - log: log, + log: logger, + baseLogger: logger, entriesMetric: metrics.NoOpGauge, syncMetric: m.KVStoreInitialSyncCompleted, } @@ -113,7 +116,8 @@ func newRestartableWatchStore(clusterName string, keyCreator KeyCreator, observe opt(rws) } - rws.log = rws.log.WithField(logfields.ClusterName, rws.source) + rws.baseLogger = rws.baseLogger.With(logfields.ClusterName, rws.source) + rws.log = rws.baseLogger return rws } @@ -128,7 +132,7 @@ func (rws *restartableWatchStore) Watch(ctx context.Context, backend WatchStoreB prefix = prefix + "/" } - rws.log = rws.log.WithField(logfields.Prefix, prefix) + rws.log = rws.baseLogger.With(logfields.Prefix, prefix) syncedMetric := rws.syncMetric.WithLabelValues( kvstore.GetScopeFromKey(prefix), rws.source, "read") @@ -136,7 +140,7 @@ func (rws *restartableWatchStore) Watch(ctx context.Context, backend WatchStoreB syncedMetric.Set(metrics.BoolToFloat64(false)) if rws.watching.Swap(true) { - rws.log.Panic("Cannot start the watch store while still running") + logging.Panic(rws.log, "Cannot start the watch store while still running") } defer func() { @@ -172,10 +176,11 @@ func (rws *restartableWatchStore) Watch(ctx context.Context, backend WatchStoreB } key := strings.TrimPrefix(event.Key, prefix) - rws.log.WithFields(logrus.Fields{ - logfields.Key: key, - logfields.Event: event.Typ, - }).Debug("Received event from kvstore") + rws.log.Debug( + "Received event from kvstore", + logfields.Key, key, + logfields.Event, event.Typ, + ) switch event.Typ { case kvstore.EventTypeCreate, kvstore.EventTypeModify: @@ -201,7 +206,7 @@ func (rws *restartableWatchStore) Synced() bool { // when no watch operation is in progress. func (rws *restartableWatchStore) Drain() { if rws.watching.Swap(true) { - rws.log.Panic("Cannot drain the watch store while still running") + logging.Panic(rws.log, "Cannot drain the watch store while still running") } defer rws.watching.Store(false) @@ -216,7 +221,10 @@ func (rws *restartableWatchStore) Drain() { func (rws *restartableWatchStore) drainKeys(staleOnly bool) { for key, entry := range rws.state { if !staleOnly || entry.stale { - rws.log.WithField(logfields.Key, key).Debug("Emitting deletion event for stale key") + rws.log.Debug( + "Emitting deletion event for stale key", + logfields.Key, key, + ) rws.handleDelete(key) } } @@ -225,10 +233,12 @@ func (rws *restartableWatchStore) drainKeys(staleOnly bool) { func (rws *restartableWatchStore) handleUpsert(key string, value []byte) { entry := &rwsEntry{key: rws.keyCreator()} if err := entry.key.Unmarshal(key, value); err != nil { - rws.log.WithFields(logrus.Fields{ - logfields.Key: key, - logfields.Value: string(value), - }).WithError(err).Warning("Unable to unmarshal value") + rws.log.Warn( + "Unable to unmarshal value", + logfields.Error, err, + logfields.Key, key, + logfields.Value, string(value), + ) return } @@ -241,7 +251,10 @@ func (rws *restartableWatchStore) handleUpsert(key string, value []byte) { func (rws *restartableWatchStore) handleDelete(key string) { entry, ok := rws.state[key] if !ok { - rws.log.WithField(logfields.Key, key).Warning("Received deletion event for unknown key") + rws.log.Warn( + "Received deletion event for unknown key", + logfields.Key, key, + ) return } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstoremgr.go b/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstoremgr.go index 44f85114c7..08c7776d23 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstoremgr.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/store/watchstoremgr.go @@ -5,13 +5,13 @@ package store import ( "context" + "log/slog" "path" "sync" "sync/atomic" - "github.com/sirupsen/logrus" - "github.com/cilium/cilium/pkg/kvstore" + "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" ) @@ -36,13 +36,13 @@ type wsmCommon struct { functions map[string]WSMFunc running atomic.Bool - log *logrus.Entry + log *slog.Logger } -func newWSMCommon(clusterName string) wsmCommon { +func newWSMCommon(logger *slog.Logger, clusterName string) wsmCommon { return wsmCommon{ functions: make(map[string]WSMFunc), - log: log.WithField(logfields.ClusterName, clusterName), + log: logger.With(logfields.ClusterName, clusterName), } } @@ -50,7 +50,7 @@ func newWSMCommon(clusterName string) wsmCommon { // It cannot be called once Run() has started. func (mgr *wsmCommon) Register(prefix string, function WSMFunc) { if mgr.running.Load() { - mgr.log.Panic("Cannot call Register while the watch store manager is running") + logging.Panic(mgr.log, "Cannot call Register while the watch store manager is running") } mgr.functions[prefix] = function @@ -58,24 +58,24 @@ func (mgr *wsmCommon) Register(prefix string, function WSMFunc) { func (mgr *wsmCommon) ready(ctx context.Context, prefix string) { if fn := mgr.functions[prefix]; fn != nil { - mgr.log.WithField(logfields.Prefix, prefix).Debug("Starting function for kvstore prefix") + mgr.log.Debug("Starting function for kvstore prefix", logfields.Prefix, prefix) delete(mgr.functions, prefix) mgr.wg.Add(1) go func() { defer mgr.wg.Done() fn(ctx) - mgr.log.WithField(logfields.Prefix, prefix).Debug("Function terminated for kvstore prefix") + mgr.log.Debug("Function terminated for kvstore prefix", logfields.Prefix, prefix) }() } else { - mgr.log.WithField(logfields.Prefix, prefix).Debug("Received sync event for unregistered prefix") + mgr.log.Debug("Received sync event for unregistered prefix", logfields.Prefix, prefix) } } func (mgr *wsmCommon) run() { mgr.log.Info("Starting watch store manager") if mgr.running.Swap(true) { - mgr.log.Panic("Cannot start the watch store manager twice") + logging.Panic(mgr.log, "Cannot start the watch store manager twice") } } @@ -98,9 +98,9 @@ type wsmSync struct { // This ensures that the synchronization of the keys hosted under the given prefix // have been successfully synchronized from the external source, even in case an // ephemeral kvstore is used. -func newWatchStoreManagerSync(backend WatchStoreBackend, clusterName string, factory Factory) WatchStoreManager { +func newWatchStoreManagerSync(logger *slog.Logger, backend WatchStoreBackend, clusterName string, factory Factory) WatchStoreManager { mgr := wsmSync{ - wsmCommon: newWSMCommon(clusterName), + wsmCommon: newWSMCommon(logger, clusterName), clusterName: clusterName, backend: backend, } @@ -127,9 +127,9 @@ type wsmImmediate struct { // NewWatchStoreManagerImmediate implements the WatchStoreManager interface, // immediately starting the registered functions once Run() is executed. -func NewWatchStoreManagerImmediate(clusterName string) WatchStoreManager { +func NewWatchStoreManagerImmediate(logger *slog.Logger, clusterName string) WatchStoreManager { return &wsmImmediate{ - wsmCommon: newWSMCommon(clusterName), + wsmCommon: newWSMCommon(logger, clusterName), } } diff --git a/vendor/github.com/cilium/cilium/pkg/kvstore/trace.go b/vendor/github.com/cilium/cilium/pkg/kvstore/trace.go index bcbf5b0e27..807a9dbd4d 100644 --- a/vendor/github.com/cilium/cilium/pkg/kvstore/trace.go +++ b/vendor/github.com/cilium/cilium/pkg/kvstore/trace.go @@ -4,7 +4,7 @@ package kvstore import ( - "github.com/sirupsen/logrus" + "log/slog" ) var ( @@ -17,8 +17,11 @@ func EnableTracing() { } // Trace is used to trace kvstore debug messages -func Trace(msg string, err error, fields logrus.Fields) { +func Trace(logger *slog.Logger, msg string, fields ...any) { if traceEnabled { - log.WithError(err).WithFields(fields).Debug(msg) + logger.Debug( + msg, + fields..., + ) } } diff --git a/vendor/github.com/cilium/cilium/pkg/labels/labels.go b/vendor/github.com/cilium/cilium/pkg/labels/labels.go index 6c2acb3d45..909975bd9b 100644 --- a/vendor/github.com/cilium/cilium/pkg/labels/labels.go +++ b/vendor/github.com/cilium/cilium/pkg/labels/labels.go @@ -7,6 +7,7 @@ import ( "bytes" "encoding/json" "fmt" + "maps" "net/netip" "slices" "strings" @@ -625,9 +626,7 @@ func (l Labels) GetModel() []string { // // Labels{Label{key1, value3, source4}, Label{key2, value3, source4}} func (l Labels) MergeLabels(from Labels) { - for k, v := range from { - l[k] = v - } + maps.Copy(l, from) } // Remove is similar to MergeLabels, but returns a new Labels object with the diff --git a/vendor/github.com/cilium/cilium/pkg/labels/oplabels.go b/vendor/github.com/cilium/cilium/pkg/labels/oplabels.go index 4dad8e7ab8..31c1788bf5 100644 --- a/vendor/github.com/cilium/cilium/pkg/labels/oplabels.go +++ b/vendor/github.com/cilium/cilium/pkg/labels/oplabels.go @@ -5,6 +5,7 @@ package labels import ( "fmt" + "maps" "github.com/sirupsen/logrus" @@ -74,13 +75,9 @@ func (o *OpLabels) SplitUserLabelChanges(lbls Labels) (add, del Labels) { func (o *OpLabels) IdentityLabels() Labels { enabled := make(Labels, len(o.Custom)+len(o.OrchestrationIdentity)) - for k, v := range o.Custom { - enabled[k] = v - } + maps.Copy(enabled, o.Custom) - for k, v := range o.OrchestrationIdentity { - enabled[k] = v - } + maps.Copy(enabled, o.OrchestrationIdentity) return enabled } @@ -98,21 +95,13 @@ func (o *OpLabels) GetIdentityLabel(key string) (l Label, found bool) { func (o *OpLabels) AllLabels() Labels { all := make(Labels, len(o.Custom)+len(o.OrchestrationInfo)+len(o.OrchestrationIdentity)+len(o.Disabled)) - for k, v := range o.Custom { - all[k] = v - } + maps.Copy(all, o.Custom) - for k, v := range o.Disabled { - all[k] = v - } + maps.Copy(all, o.Disabled) - for k, v := range o.OrchestrationIdentity { - all[k] = v - } + maps.Copy(all, o.OrchestrationIdentity) - for k, v := range o.OrchestrationInfo { - all[k] = v - } + maps.Copy(all, o.OrchestrationInfo) return all } diff --git a/vendor/github.com/cilium/cilium/pkg/logging/logfields/logfields.go b/vendor/github.com/cilium/cilium/pkg/logging/logfields/logfields.go index 349cce2abe..1f6fd7fae9 100644 --- a/vendor/github.com/cilium/cilium/pkg/logging/logfields/logfields.go +++ b/vendor/github.com/cilium/cilium/pkg/logging/logfields/logfields.go @@ -604,6 +604,8 @@ const ( // K8sNamespace is the namespace something belongs to K8sNamespace = "k8sNamespace" + K8sNamespaceIllegal = "k8sNamespace.illegal" + // K8sIdentityAnnotation is a k8s non-identifying annotations on k8s objects K8sIdentityAnnotation = "k8sIdentityAnnotation" @@ -1332,4 +1334,116 @@ const ( Operation = "operation" KeyPairSN = "keyPairSN" + + AnnotationsOld = "annotationsOld" + + LabelsNew = "labelsNew" + + File = "file" + + Timeout = "timeout" + + EtcdDataDir = "etcdDataDir" + + EtcdClusterName = "etcdClusterName" + + EtcdInitialClusterToken = "etcdInitialClusterToken" + + EtcdListenClientUrl = "loopbackEndpoint" + + EtcdBinary = "etcdBinaryLocation" + + EtcdFlags = "etcdCmd" + + EtcdExitCode = "etcdExitCode" + + EtcdClientConfig = "etcdClientConfig" + + EtcdUsername = "etcdUsername" + + EtcdRoleName = "etcdRoleName" + + EtcdPermission = "etcdPermission" + + EtcdRangeStart = "etcdRangeStart" + + EtcdRangeEnd = "etcdRangeEnd" + + K8sExportName = "K8sExportName" + + ReliablyMissing = "reliablyMissing" + + KVStoreBackendConfigurationSuffix = "kvStoreBackendConfiguration.Suffix" + + KVStoreBackendConfigurationTyp = "kvStoreBackendConfiguration.Typ" + + KVStoreBackendConfigurationBasePath = "kvStoreBackendConfiguration.BasePath" + + ReadFromKVStore = "readFromKVStore" + + TTL = "ttl" + + ConfigPath = "configPath" + + KeepAliveHeartbeat = "keepAliveHeartbeat" + + KeepAliveTimeout = "keepAliveTimeout" + + RateLimit = "rateLimit" + + MaxInflight = "maxInflight" + + ListLimit = "listLimit" + + TimeWindow = "timeWindow" + + Entry = "entry" + + LastEventReceived = "lastEventReceived" + + PodIP = "podIP" + + PodIPs = "podIPs" + + NewPodIP = "newPodIP" + + NewPodIPs = "newPodIPs" + + NewHostIP = "newHostIP" + + OldPodIP = "oldPodIP" + + OldPodIPs = "oldPodIPs" + + OldHostIP = "oldHostIP" + + OldLabels = "oldLabels" + + OldAnnotations = "oldAnnotations" + + NewLabels = "newLabels" + + NewAnnotations = "newAnnotations" + + OldService = "oldService" + + OldEndpoints = "oldEndpoints" + + LenEndpoints = "lenEndpoints" + + LenBackends = "lenBackends" + + EnableK8sTerminatingEndpoint = "enableK8sTerminatingEndpoint" + + CRDs = "CRDs" + + PodCIDRs = "podCIDRs" + + LenIPs = "lenIPs" + + Alias = "alias" + + GlobalConfiguration = "globalConfiguration" + + Annotation = "annotation" ) diff --git a/vendor/github.com/cilium/cilium/pkg/logging/logging.go b/vendor/github.com/cilium/cilium/pkg/logging/logging.go index 9e03b20437..5dd668a81a 100644 --- a/vendor/github.com/cilium/cilium/pkg/logging/logging.go +++ b/vendor/github.com/cilium/cilium/pkg/logging/logging.go @@ -13,6 +13,7 @@ import ( "log/slog" "os" "regexp" + "slices" "strings" "sync/atomic" "time" @@ -368,13 +369,7 @@ func (o LogOptions) validateOpts(logDriver string, supportedOpts map[string]bool return fmt.Errorf("provided configuration key %q is not supported as a logging option for log driver %s", k, logDriver) } if validValues, ok := validKVs[k]; ok { - valid := false - for _, vv := range validValues { - if v == vv { - valid = true - break - } - } + valid := slices.Contains(validValues, v) if !valid { return fmt.Errorf("provided configuration value %q is not a valid value for %q in log driver %s, valid values: %v", v, k, logDriver, validValues) } diff --git a/vendor/github.com/cilium/cilium/pkg/metrics/metrics.go b/vendor/github.com/cilium/cilium/pkg/metrics/metrics.go index 91a7c75a4d..55dd5429b8 100644 --- a/vendor/github.com/cilium/cilium/pkg/metrics/metrics.go +++ b/vendor/github.com/cilium/cilium/pkg/metrics/metrics.go @@ -420,6 +420,9 @@ var ( // ConntrackGCDuration the duration of the conntrack GC process in milliseconds. ConntrackGCDuration = NoOpObserverVec + // ConntrackInterval is the interval in secodns between conntrack GC runs + ConntrackInterval = NoOpGaugeVec + // ConntrackDumpReset marks the count for conntrack dump resets ConntrackDumpResets = NoOpCounterVec @@ -689,6 +692,7 @@ type LegacyMetrics struct { ConntrackGCSize metric.Vec[metric.Gauge] NatGCSize metric.Vec[metric.Gauge] ConntrackGCDuration metric.Vec[metric.Observer] + ConntrackInterval metric.Vec[metric.Gauge] ConntrackDumpResets metric.Vec[metric.Counter] SignalsHandled metric.Vec[metric.Counter] ServicesEventsCount metric.Vec[metric.Counter] @@ -982,6 +986,14 @@ func NewLegacyMetrics() *LegacyMetrics { "labeled by datapath family and completion status", }, []string{LabelDatapathFamily, LabelProtocol, LabelStatus}), + ConntrackInterval: metric.NewGaugeVec(metric.GaugeOpts{ + ConfigName: Namespace + "_" + SubsystemDatapath + "_conntrack_gc_interval_seconds", + Namespace: Namespace, + Subsystem: SubsystemDatapath, + Name: "conntrack_gc_interval_seconds", + Help: "Interval in seconds between conntrack garbage collector runs", + }, []string{"global"}), + ConntrackDumpResets: metric.NewCounterVec(metric.CounterOpts{ ConfigName: Namespace + "_" + SubsystemDatapath + "_conntrack_dump_resets_total", Namespace: Namespace, @@ -1411,6 +1423,7 @@ func NewLegacyMetrics() *LegacyMetrics { ConntrackGCSize = lm.ConntrackGCSize NatGCSize = lm.NatGCSize ConntrackGCDuration = lm.ConntrackGCDuration + ConntrackInterval = lm.ConntrackInterval ConntrackDumpResets = lm.ConntrackDumpResets SignalsHandled = lm.SignalsHandled ServicesEventsCount = lm.ServicesEventsCount diff --git a/vendor/github.com/cilium/cilium/pkg/metrics/metrics_unix.go b/vendor/github.com/cilium/cilium/pkg/metrics/metrics_linux.go similarity index 62% rename from vendor/github.com/cilium/cilium/pkg/metrics/metrics_unix.go rename to vendor/github.com/cilium/cilium/pkg/metrics/metrics_linux.go index 184d3baa71..a8a4606cbf 100644 --- a/vendor/github.com/cilium/cilium/pkg/metrics/metrics_unix.go +++ b/vendor/github.com/cilium/cilium/pkg/metrics/metrics_linux.go @@ -1,24 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Authors of Cilium -//go:build !windows - package metrics -import ( - "golang.org/x/sys/unix" - - "github.com/cilium/cilium/pkg/datapath/linux/probes" -) - -// Errno2Outcome converts a unix.Errno to LabelOutcome -func Errno2Outcome(errno unix.Errno) string { - if errno != 0 { - return LabelValueOutcomeFail - } - - return LabelValueOutcomeSuccess -} +import "github.com/cilium/cilium/pkg/datapath/linux/probes" func enableIfIndexMetric() bool { // On kernels which do not provide ifindex via the FIB, Cilium needs diff --git a/vendor/github.com/cilium/cilium/pkg/metrics/metrics_windows.go b/vendor/github.com/cilium/cilium/pkg/metrics/metrics_other.go similarity index 87% rename from vendor/github.com/cilium/cilium/pkg/metrics/metrics_windows.go rename to vendor/github.com/cilium/cilium/pkg/metrics/metrics_other.go index dc4333ab32..083251c265 100644 --- a/vendor/github.com/cilium/cilium/pkg/metrics/metrics_windows.go +++ b/vendor/github.com/cilium/cilium/pkg/metrics/metrics_other.go @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Authors of Cilium +//go:build !linux + package metrics func enableIfIndexMetric() bool { diff --git a/vendor/github.com/cilium/cilium/pkg/monitor/api/types.go b/vendor/github.com/cilium/cilium/pkg/monitor/api/types.go index 8bb2125fc2..1b3bce4edd 100644 --- a/vendor/github.com/cilium/cilium/pkg/monitor/api/types.go +++ b/vendor/github.com/cilium/cilium/pkg/monitor/api/types.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "net" + "slices" "sort" "strconv" "strings" @@ -138,13 +139,7 @@ func (m *MessageTypeFilter) Type() string { } func (m *MessageTypeFilter) Contains(typ int) bool { - for _, v := range *m { - if v == typ { - return true - } - } - - return false + return slices.Contains(*m, typ) } // Must be synchronized with diff --git a/vendor/github.com/cilium/cilium/pkg/node/address.go b/vendor/github.com/cilium/cilium/pkg/node/address.go index 8bfeea9948..1d58303d05 100644 --- a/vendor/github.com/cilium/cilium/pkg/node/address.go +++ b/vendor/github.com/cilium/cilium/pkg/node/address.go @@ -117,7 +117,7 @@ func setDefaultPrefix(cfg *option.DaemonConfig, device string, node *LocalNode) } node.IPv4AllocCIDR = cidr.NewCIDR(ip4net) - log.WithField(logfields.V4Prefix, node.IPv4AllocCIDR).Info("Using autogenerated IPv4 allocation range") + log.WithField(logfields.V4Prefix, node.IPv4AllocCIDR).Debug("Using autogenerated IPv4 allocation range") } } @@ -147,7 +147,7 @@ func setDefaultPrefix(cfg *option.DaemonConfig, device string, node *LocalNode) } node.IPv6AllocCIDR = cidr.NewCIDR(ip6net) - log.WithField(logfields.V6Prefix, node.IPv6AllocCIDR).Info("Using autogenerated IPv6 allocation range") + log.WithField(logfields.V6Prefix, node.IPv6AllocCIDR).Debug("Using autogenerated IPv6 allocation range") } } } diff --git a/vendor/github.com/cilium/cilium/pkg/option/config.go b/vendor/github.com/cilium/cilium/pkg/option/config.go index 3ee4db8ebe..3da7219f26 100644 --- a/vendor/github.com/cilium/cilium/pkg/option/config.go +++ b/vendor/github.com/cilium/cilium/pkg/option/config.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + "log/slog" "math" "net" "net/netip" @@ -60,9 +61,6 @@ const ( // ClusterMeshHealthPort is the TCP port for ClusterMesh apiserver health API ClusterMeshHealthPort = "clustermesh-health-port" - // AgentLabels are additional labels to identify this agent - AgentLabels = "agent-labels" - // AllowICMPFragNeeded allows ICMP Fragmentation Needed type packets in policy. AllowICMPFragNeeded = "allow-icmp-frag-needed" @@ -823,10 +821,6 @@ const ( // KVstoreConnectivityTimeout is the timeout when performing kvstore operations KVstoreConnectivityTimeout = "kvstore-connectivity-timeout" - // KVstorePodNetworkSupport enables the support for running the Cilium KVstore - // in pod network. - KVstorePodNetworkSupport = "kvstore-pod-network-support" - // IdentityChangeGracePeriod is the name of the // IdentityChangeGracePeriod option IdentityChangeGracePeriod = "identity-change-grace-period" @@ -1301,6 +1295,27 @@ func BindEnvWithLegacyEnvFallback(vp *viper.Viper, optName, legacyEnvName string vp.BindEnv(optName, envName) } +// LogRegisteredSlogOptions logs all options that where bound to viper. +func LogRegisteredSlogOptions(vp *viper.Viper, entry *slog.Logger) { + keys := vp.AllKeys() + slices.Sort(keys) + for _, k := range keys { + ss := vp.GetStringSlice(k) + if len(ss) == 0 { + sm := vp.GetStringMap(k) + for k, v := range sm { + ss = append(ss, fmt.Sprintf("%s=%s", k, v)) + } + } + + if len(ss) > 0 { + entry.Info(fmt.Sprintf(" --%s='%s'", k, strings.Join(ss, ","))) + } else { + entry.Info(fmt.Sprintf(" --%s='%s'", k, vp.GetString(k))) + } + } +} + // LogRegisteredOptions logs all options that where bound to viper. func LogRegisteredOptions(vp *viper.Viper, entry *logrus.Entry) { keys := vp.AllKeys() @@ -1379,9 +1394,6 @@ type DaemonConfig struct { // ClusterMeshHealthPort is the TCP port for ClusterMesh apiserver health API ClusterMeshHealthPort int - // AgentLabels contains additional labels to identify this agent in monitor events. - AgentLabels []string - // IPv6ClusterAllocCIDR is the base CIDR used to allocate IPv6 node // CIDRs if allocation is not performed by an orchestration system IPv6ClusterAllocCIDR string @@ -1794,10 +1806,6 @@ type DaemonConfig struct { // KVstoreConnectivityTimeout is the timeout when performing kvstore operations KVstoreConnectivityTimeout time.Duration - // KVstorePodNetworkSupport enables the support for running the Cilium KVstore - // in pod network. - KVstorePodNetworkSupport bool - // IdentityChangeGracePeriod is the grace period that needs to pass // before an endpoint that has changed its identity will start using // that new identity. During the grace period, the new identity has @@ -2272,7 +2280,6 @@ var ( ToFQDNsMaxIPsPerHost: defaults.ToFQDNsMaxIPsPerHost, KVstorePeriodicSync: defaults.KVstorePeriodicSync, KVstoreConnectivityTimeout: defaults.KVstoreConnectivityTimeout, - KVstorePodNetworkSupport: defaults.KVstorePodNetworkSupport, IdentityChangeGracePeriod: defaults.IdentityChangeGracePeriod, IdentityRestoreGracePeriod: defaults.IdentityRestoreGracePeriodK8s, FixedIdentityMapping: make(map[string]string), @@ -2377,7 +2384,7 @@ func (c *DaemonConfig) AreDevicesRequired() bool { } // NeedBPFHostOnWireGuardDevice returns true if the agent needs to attach -// a BPF program on the Ingress of Cilium's WireGuard device +// cil_from_netdev on the Ingress of Cilium's WireGuard device func (c *DaemonConfig) NeedBPFHostOnWireGuardDevice() bool { if !c.EnableWireguard { return false @@ -2405,6 +2412,27 @@ func (c *DaemonConfig) NeedBPFHostOnWireGuardDevice() bool { return false } +// NeedEgressOnWireGuardDevice returns true if the agent needs to attach +// cil_to_wireguard on the Egress of Cilium's WireGuard device +func (c *DaemonConfig) NeedEgressOnWireGuardDevice() bool { + if !c.EnableWireguard { + return false + } + + // No need to handle rev-NAT xlations in wireguard with tunneling enabled. + if c.TunnelingEnabled() { + return false + } + + // Attaching cil_to_wireguard to cilium_wg0 egress is required for handling + // the rev-NAT xlations when encrypting KPR traffic. + if c.EnableNodePort && c.EnableL7Proxy && c.KubeProxyReplacement == KubeProxyReplacementTrue { + return true + } + + return false +} + // MasqueradingEnabled returns true if either IPv4 or IPv6 masquerading is enabled. func (c *DaemonConfig) MasqueradingEnabled() bool { return c.EnableIPv4Masquerade || c.EnableIPv6Masquerade @@ -2512,12 +2540,7 @@ func (c *DaemonConfig) K8sNetworkPolicyEnabled() bool { } func (c *DaemonConfig) PolicyCIDRMatchesNodes() bool { - for _, mode := range c.PolicyCIDRMatchMode { - if mode == "nodes" { - return true - } - } - return false + return slices.Contains(c.PolicyCIDRMatchMode, "nodes") } // PerNodeLabelsEnabled returns true if per-node labels feature @@ -2560,10 +2583,9 @@ func (c *DaemonConfig) LoadBalancerUsesDSR() bool { c.LoadBalancerModeAnnotation } -// KVstoreEnabledWithoutPodNetworkSupport returns whether Cilium is configured to connect -// to an external KVStore, and the support for running it in pod network is disabled. -func (c *DaemonConfig) KVstoreEnabledWithoutPodNetworkSupport() bool { - return c.KVStore != "" && !c.KVstorePodNetworkSupport +// KVstoreEnabled returns whether Cilium is configured to connect to an external KVStore. +func (c *DaemonConfig) KVstoreEnabled() bool { + return c.KVStore != "" } func (c *DaemonConfig) validateIPv6ClusterAllocCIDR() error { @@ -2817,7 +2839,6 @@ func (c *DaemonConfig) Populate(vp *viper.Viper) { c.AgentHealthPort = vp.GetInt(AgentHealthPort) c.ClusterHealthPort = vp.GetInt(ClusterHealthPort) c.ClusterMeshHealthPort = vp.GetInt(ClusterMeshHealthPort) - c.AgentLabels = vp.GetStringSlice(AgentLabels) c.AllowICMPFragNeeded = vp.GetBool(AllowICMPFragNeeded) c.AllowLocalhost = vp.GetString(AllowLocalhost) c.AnnotateK8sNode = vp.GetBool(AnnotateK8sNode) @@ -2907,7 +2928,6 @@ func (c *DaemonConfig) Populate(vp *viper.Viper) { c.KVstoreLeaseTTL = vp.GetDuration(KVstoreLeaseTTL) c.KVstorePeriodicSync = vp.GetDuration(KVstorePeriodicSync) c.KVstoreConnectivityTimeout = vp.GetDuration(KVstoreConnectivityTimeout) - c.KVstorePodNetworkSupport = vp.GetBool(KVstorePodNetworkSupport) c.KVstoreMaxConsecutiveQuorumErrors = vp.GetUint(KVstoreMaxConsecutiveQuorumErrorsName) c.LabelPrefixFile = vp.GetString(LabelPrefixFile) c.Labels = vp.GetStringSlice(Labels) diff --git a/vendor/github.com/cilium/cilium/pkg/option/daemon.go b/vendor/github.com/cilium/cilium/pkg/option/daemon.go index 003f1cc604..16a918734b 100644 --- a/vendor/github.com/cilium/cilium/pkg/option/daemon.go +++ b/vendor/github.com/cilium/cilium/pkg/option/daemon.go @@ -3,6 +3,8 @@ package option +import "maps" + var ( specPolicyTracing = Option{ Description: "Enable tracing when resolving policy (Debug)", @@ -31,9 +33,7 @@ var ( ) func init() { - for k, v := range DaemonMutableOptionLibrary { - DaemonOptionLibrary[k] = v - } + maps.Copy(DaemonOptionLibrary, DaemonMutableOptionLibrary) } // ParseDaemonOption parses a string as daemon option diff --git a/vendor/github.com/cilium/cilium/pkg/option/endpoint.go b/vendor/github.com/cilium/cilium/pkg/option/endpoint.go index b72049ebe3..14bda6a80d 100644 --- a/vendor/github.com/cilium/cilium/pkg/option/endpoint.go +++ b/vendor/github.com/cilium/cilium/pkg/option/endpoint.go @@ -3,6 +3,8 @@ package option +import "maps" + var ( endpointMutableOptionLibrary = OptionLibrary{ ConntrackAccounting: &specConntrackAccounting, @@ -21,9 +23,5 @@ var ( ) func GetEndpointMutableOptionLibrary() OptionLibrary { - opt := OptionLibrary{} - for k, v := range endpointMutableOptionLibrary { - opt[k] = v - } - return opt + return maps.Clone(endpointMutableOptionLibrary) } diff --git a/vendor/github.com/cilium/cilium/pkg/option/option.go b/vendor/github.com/cilium/cilium/pkg/option/option.go index ad8e0467a3..108b3d9ebd 100644 --- a/vendor/github.com/cilium/cilium/pkg/option/option.go +++ b/vendor/github.com/cilium/cilium/pkg/option/option.go @@ -6,6 +6,7 @@ package option import ( "encoding/json" "fmt" + "maps" "slices" "strings" @@ -60,13 +61,7 @@ const ( // RequiresOption returns true if the option requires the specified option `name`. func (o Option) RequiresOption(name string) bool { - for _, o := range o.Requires { - if o == name { - return true - } - } - - return false + return slices.Contains(o.Requires, name) } type OptionLibrary map[string]*Option @@ -141,11 +136,7 @@ func (l OptionLibrary) Validate(name string, value string) error { type OptionMap map[string]OptionSetting func (om OptionMap) DeepCopy() OptionMap { - cpy := make(OptionMap, len(om)) - for k, v := range om { - cpy[k] = v - } - return cpy + return maps.Clone(om) } // IntOptions member functions with external access do not require diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/http.go b/vendor/github.com/cilium/cilium/pkg/policy/api/http.go index 2239420a1e..78da15c157 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/http.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/http.go @@ -22,8 +22,8 @@ const ( ) // HeaderMatch extends the HeaderValue for matching requirement of a -// named header field against an immediate string, a secret value, or -// a regex. If none of the optional fields is present, then the +// named header field against an immediate string or a secret value. +// If none of the optional fields is present, then the // header value is not matched, only presence of the header is enough. type HeaderMatch struct { // Mismatch identifies what to do in case there is no match. The default is @@ -113,7 +113,6 @@ type PortRuleHTTP struct { // of regular expressions (e.g. that specified by ECMAScript), so this function // may return some false positives. If the rule is invalid, returns an error. func (h *PortRuleHTTP) Sanitize() error { - if h.Path != "" { _, err := regexp.Compile(h.Path) if err != nil { diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go b/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go index 57f61f279b..cc5f787835 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/rule_validation.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "net/netip" + "slices" "strconv" "strings" @@ -566,10 +567,8 @@ func (pr *PortRule) sanitize(ingress bool) error { if len(pr.ServerNames) > 0 && !pr.Rules.IsEmpty() && pr.TerminatingTLS == nil { return fmt.Errorf("ServerNames are not allowed with L7 rules without TLS termination") } - for _, sn := range pr.ServerNames { - if sn == "" { - return errEmptyServerName - } + if slices.Contains(pr.ServerNames, "") { + return errEmptyServerName } if len(pr.Ports) > maxPorts { diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/selector.go b/vendor/github.com/cilium/cilium/pkg/policy/api/selector.go index 7dc6c987fb..f1eafbead2 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/selector.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/selector.go @@ -10,15 +10,13 @@ import ( k8sLbls "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/labels" slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" - validation "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1/validation" + "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1/validation" "github.com/cilium/cilium/pkg/labels" "github.com/cilium/cilium/pkg/logging" "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/metrics" ) -var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "policy-api") - // EndpointSelector is a wrapper for k8s LabelSelector. type EndpointSelector struct { *slim_metav1.LabelSelector `json:",inline"` @@ -169,8 +167,13 @@ func labelSelectorToRequirements(labelSelector *slim_metav1.LabelSelector) *k8sL selector, err := slim_metav1.LabelSelectorAsSelector(labelSelector) if err != nil { metrics.PolicyChangeTotal.WithLabelValues(metrics.LabelValueOutcomeFail).Inc() - log.WithError(err).WithField(logfields.EndpointLabelSelector, - logfields.Repr(labelSelector)).Error("unable to construct selector in label selector") + // FIXME @aanm do we still need to log this error? + logging.DefaultSlogLogger.Error( + "unable to construct selector in label selector", + logfields.LogSubsys, "policy-api", + logfields.Error, err, + logfields.EndpointLabelSelector, labelSelector, + ) return nil } metrics.PolicyChangeTotal.WithLabelValues(metrics.LabelValueOutcomeSuccess).Inc() diff --git a/vendor/github.com/cilium/cilium/pkg/policy/api/utils.go b/vendor/github.com/cilium/cilium/pkg/policy/api/utils.go index f6019b3234..19d8dae0b9 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/api/utils.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/api/utils.go @@ -6,18 +6,13 @@ package api import ( "context" "fmt" + "slices" "strings" ) // Exists returns true if the HTTP rule already exists in the list of rules func (h *PortRuleHTTP) Exists(rules L7Rules) bool { - for _, existingRule := range rules.HTTP { - if h.Equal(existingRule) { - return true - } - } - - return false + return slices.ContainsFunc(rules.HTTP, h.Equal) } // Equal returns true if both HTTP rules are equal @@ -62,24 +57,12 @@ func (h *HeaderMatch) Equal(o *HeaderMatch) bool { // Exists returns true if the DNS rule already exists in the list of rules func (d *PortRuleDNS) Exists(rules L7Rules) bool { - for _, existingRule := range rules.DNS { - if d.Equal(existingRule) { - return true - } - } - - return false + return slices.ContainsFunc(rules.DNS, d.Equal) } // Exists returns true if the L7 rule already exists in the list of rules func (h *PortRuleL7) Exists(rules L7Rules) bool { - for _, existingRule := range rules.L7 { - if h.Equal(existingRule) { - return true - } - } - - return false + return slices.ContainsFunc(rules.L7, h.Equal) } // Equal returns true if both rules are equal diff --git a/vendor/github.com/cilium/cilium/pkg/policy/config.go b/vendor/github.com/cilium/cilium/pkg/policy/config.go index 000d663e3e..21cf75d0e3 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/config.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/config.go @@ -7,14 +7,11 @@ import ( ipcacheTypes "github.com/cilium/cilium/pkg/ipcache/types" "github.com/cilium/cilium/pkg/labels" "github.com/cilium/cilium/pkg/lock" - "github.com/cilium/cilium/pkg/logging" - "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/source" "github.com/cilium/cilium/pkg/time" ) var ( - log = logging.DefaultLogger.WithField(logfields.LogSubsys, "policy") mutex lock.RWMutex // Protects enablePolicy enablePolicy string // Whether policy enforcement is enabled. ) diff --git a/vendor/github.com/cilium/cilium/pkg/policy/l4.go b/vendor/github.com/cilium/cilium/pkg/policy/l4.go index 03a9e8b764..5705208ddc 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/l4.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/l4.go @@ -7,6 +7,7 @@ import ( "bytes" "encoding/json" "fmt" + "log/slog" "math/bits" "sort" "strconv" @@ -15,7 +16,6 @@ import ( "unique" cilium "github.com/cilium/proxy/go/cilium/api" - "github.com/sirupsen/logrus" k8sTypes "k8s.io/apimachinery/pkg/types" "github.com/cilium/cilium/api/v1/models" @@ -154,6 +154,10 @@ func (a StringSet) Merge(b StringSet) StringSet { // PerSelectorPolicy contains policy rules for a CachedSelector, i.e. for a // selection of numerical identities. type PerSelectorPolicy struct { + // L7Parser specifies the L7 protocol parser (optional). If specified as + // an empty string, then means that no L7 proxy redirect is performed. + L7Parser L7ParserType `json:"-"` + // TerminatingTLS is the TLS context for the connection terminated by // the L7 proxy. For egress policy this specifies the server-side TLS // parameters to be applied on the connections originated from the local @@ -175,19 +179,17 @@ type PerSelectorPolicy struct { // TLS handshake. ServerNames StringSet `json:"serverNames,omitempty"` - // isRedirect is 'true' when traffic must be redirected - isRedirect bool `json:"-"` - - // Listener is an optional fully qualified name of a Envoy Listner defined in a CiliumEnvoyConfig CRD that should be - // used for this traffic instead of the default listener + // Listener is an optional fully qualified name of a Envoy Listner defined in a + // CiliumEnvoyConfig CRD that should be used for this traffic instead of the default + // listener Listener string `json:"listener,omitempty"` - // Priority of the listener used when multiple listeners would apply to the same + // Priority of the proxy redirect used when multiple proxy ports would apply to the same // MapStateEntry. // Lower numbers indicate higher priority. Except for the default 0, which indicates the // lowest priority. If higher priority desired, a low unique number like 1, 2, or 3 should // be explicitly specified here. - Priority uint8 `json:"priority,omitempty"` + Priority ListenerPriority `json:"priority,omitempty"` // Pre-computed HTTP rules, computed after rule merging is complete EnvoyHTTPRules *cilium.HttpNetworkPolicyRules `json:"-"` @@ -198,8 +200,8 @@ type PerSelectorPolicy struct { api.L7Rules - // Authentication is the kind of cryptographic authentication required for the traffic to be allowed - // at L3, if any. + // Authentication is the kind of cryptographic authentication required for the traffic to be + // allowed at L3, if any. Authentication *api.Authentication `json:"auth,omitempty"` // IsDeny is set if this L4Filter contains should be denied @@ -209,10 +211,10 @@ type PerSelectorPolicy struct { // Equal returns true if 'a' and 'b' represent the same L7 Rules func (a *PerSelectorPolicy) Equal(b *PerSelectorPolicy) bool { return a == nil && b == nil || a != nil && b != nil && + a.L7Parser == b.L7Parser && a.TerminatingTLS.Equal(b.TerminatingTLS) && a.OriginatingTLS.Equal(b.OriginatingTLS) && a.ServerNames.Equal(b.ServerNames) && - a.isRedirect == b.isRedirect && a.Listener == b.Listener && a.Priority == b.Priority && (a.Authentication == nil && b.Authentication == nil || a.Authentication != nil && a.Authentication.DeepEqual(b.Authentication)) && @@ -229,7 +231,7 @@ func (a *PerSelectorPolicy) GetListener() string { } // GetPriority returns the pritority of the listener of the PerSelectorPolicy. -func (a *PerSelectorPolicy) GetPriority() uint8 { +func (a *PerSelectorPolicy) GetPriority() ListenerPriority { if a == nil { return 0 } @@ -275,13 +277,13 @@ func (a *PerSelectorPolicy) getAuthRequirement() AuthRequirement { } // IsRedirect returns true if the L7Rules are a redirect. -func (a *PerSelectorPolicy) IsRedirect() bool { - return a != nil && a.isRedirect +func (sp *PerSelectorPolicy) IsRedirect() bool { + return sp != nil && sp.L7Parser != "" } // HasL7Rules returns whether the `L7Rules` contains any L7 rules. -func (a *PerSelectorPolicy) HasL7Rules() bool { - return !a.L7Rules.IsEmpty() +func (sp *PerSelectorPolicy) HasL7Rules() bool { + return sp != nil && !sp.L7Rules.IsEmpty() } // L7DataMap contains a map of L7 rules per endpoint where key is a CachedSelector @@ -351,6 +353,54 @@ const ( ParserTypeDNS L7ParserType = "dns" ) +type ListenerPriority = types.ListenerPriority + +// API listener priorities and corresponding defaults for L7 parser types +// 0 - default (low) priority for all proxy redirects +// 1 - highest listener priority +// .. +// 100 - lowest (non-default) listener priority +// 101 - priority for HTTP parser type +// 106 - priority for the Kafka parser type +// 111 - priority for the proxylib parsers +// 116 - priority for TLS interception parsers (can be promoted to HTTP/Kafka/proxylib) +// 121 - priority for DNS parser type +// 126 - default priority for CRD parser type +// 127 - reserved (listener priority passed as 0) +// +// MapStateEntry stores this reverted in 'ProxyPortPriority' where higher numbers have higher +// precedence +const ( + ListenerPriorityNone ListenerPriority = 0 + ListenerPriorityHTTP ListenerPriority = 101 + ListenerPriorityKafka ListenerPriority = 106 + ListenerPriorityProxylib ListenerPriority = 111 + ListenerPriorityTLS ListenerPriority = 116 + ListenerPriorityDNS ListenerPriority = 121 + ListenerPriorityCRD ListenerPriority = 126 +) + +// defaultPriority maps the parser type to an "API listener priority" +func (l7 L7ParserType) defaultPriority() ListenerPriority { + switch l7 { + case ParserTypeNone: + return ListenerPriorityNone // no priority + case ParserTypeHTTP: + return ListenerPriorityHTTP + case ParserTypeKafka: + return ListenerPriorityKafka + default: // proxylib parsers + return ListenerPriorityProxylib + case ParserTypeTLS: + return ListenerPriorityTLS + case ParserTypeDNS: + return ListenerPriorityDNS + case ParserTypeCRD: + // CRD type can have an explicit higher priority in range 1-100 + return ListenerPriorityCRD + } +} + // redirectTypes is a bitmask of redirection types of multiple filters type redirectTypes uint16 @@ -481,9 +531,6 @@ type L4Filter struct { // restriction (such as no L7 rules). Holds references to the cached selectors, which must // be released! PerSelectorPolicies L7DataMap `json:"l7-rules,omitempty"` - // L7Parser specifies the L7 protocol parser (optional). If specified as - // an empty string, then means that no L7 proxy redirect is performed. - L7Parser L7ParserType `json:"-"` // Ingress is true if filter applies at ingress; false if it applies at egress. Ingress bool `json:"-"` // RuleOrigin is a set of rule labels tracking which policy rules are the origin for this @@ -512,11 +559,6 @@ func (l4 *L4Filter) GetPerSelectorPolicies() L7DataMap { return l4.PerSelectorPolicies } -// GetL7Parser returns the L7ParserType of the L4Filter. -func (l4 *L4Filter) GetL7Parser() L7ParserType { - return l4.L7Parser -} - // GetIngress returns whether the L4Filter applies at ingress or egress. func (l4 *L4Filter) GetIngress() bool { return l4.Ingress @@ -534,7 +576,6 @@ func (l4 *L4Filter) Equals(bL4 *L4Filter) bool { l4.PortName == bL4.PortName && l4.Protocol == bL4.Protocol && l4.Ingress == bL4.Ingress && - l4.L7Parser == bL4.L7Parser && l4.wildcard == bL4.wildcard { if len(l4.PerSelectorPolicies) != len(bL4.PerSelectorPolicies) { @@ -596,7 +637,7 @@ func (c *ChangeState) Size() int { // 'redirects' is the map of currently realized redirects, it is used to find the proxy port for any redirects. // p.SelectorCache is used as Identities interface during this call, which only has GetPrefix() that // needs no lock. -func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, changes ChangeState) { +func (l4 *L4Filter) toMapState(logger *slog.Logger, p *EndpointPolicy, features policyFeatures, changes ChangeState) { port := l4.Port proto := l4.U8Proto @@ -605,15 +646,15 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang direction = trafficdirection.Ingress } - logger := log + scopedLog := logger if option.Config.Debug { - logger = log.WithFields(logrus.Fields{ - logfields.EndpointID: p.PolicyOwner.GetID(), - logfields.Port: port, - logfields.PortName: l4.PortName, - logfields.Protocol: proto, - logfields.TrafficDirection: direction, - }) + scopedLog = logger.With( + logfields.EndpointID, p.PolicyOwner.GetID(), + logfields.Port, port, + logfields.PortName, l4.PortName, + logfields.Protocol, proto, + logfields.TrafficDirection, direction, + ) } // resolve named port @@ -642,7 +683,10 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang isL3L4withWildcardPresent := isL4Wildcard && cs != l4.wildcard if isL3L4withWildcardPresent && wildcardRule.covers(currentRule) { - logger.WithField(logfields.EndpointSelector, cs).Debug("ToMapState: Skipping L3/L4 key due to existing L4-only key") + scopedLog.Debug( + "ToMapState: Skipping L3/L4 key due to existing L4-only key", + logfields.EndpointSelector, cs, + ) continue } @@ -669,7 +713,11 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang // Skip unrealized redirects; this happens routineously just // before new redirects are realized. Once created, we are called // again. - logger.WithError(err).WithField(logfields.EndpointSelector, cs).Debugf("Skipping unrealized redirect") + scopedLog.Debug( + "Skipping unrealized redirect", + logfields.Error, err, + logfields.EndpointSelector, cs, + ) continue } } @@ -682,10 +730,16 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang if port == 0 { // Allow-all - logger.WithField(logfields.EndpointSelector, cs).Debug("ToMapState: allow all") + scopedLog.Debug( + "ToMapState: allow all", + logfields.EndpointSelector, cs, + ) } else { // L4 allow - logger.WithField(logfields.EndpointSelector, cs).Debug("ToMapState: L4 allow all") + scopedLog.Debug( + "ToMapState: L4 allow all", + logfields.EndpointSelector, cs, + ) } } continue @@ -694,17 +748,19 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang idents := cs.GetSelections(p.VersionHandle) if option.Config.Debug { if isDenyRule { - logger.WithFields(logrus.Fields{ - logfields.Version: p.VersionHandle, - logfields.EndpointSelector: cs, - logfields.PolicyID: idents, - }).Debug("ToMapState: Denied remote IDs") + scopedLog.Debug( + "ToMapState: Denied remote IDs", + logfields.Version, p.VersionHandle, + logfields.EndpointSelector, cs, + logfields.PolicyID, idents, + ) } else { - logger.WithFields(logrus.Fields{ - logfields.Version: p.VersionHandle, - logfields.EndpointSelector: cs, - logfields.PolicyID: idents, - }).Debug("ToMapState: Allowed remote IDs") + scopedLog.Debug( + "ToMapState: Allowed remote IDs", + logfields.Version, p.VersionHandle, + logfields.EndpointSelector, cs, + logfields.PolicyID, idents, + ) } } for _, id := range idents { @@ -724,11 +780,12 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang } } if option.Config.Debug { - log.WithFields(logrus.Fields{ - logfields.PolicyKeysAdded: changes.Adds, - logfields.PolicyKeysDeleted: changes.Deletes, - logfields.PolicyEntriesOld: changes.old, - }).Debug("ToMapChange changes") + scopedLog.Debug( + "ToMapChange changes", + logfields.PolicyKeysAdded, changes.Adds, + logfields.PolicyKeysDeleted, changes.Deletes, + logfields.PolicyEntriesOld, changes.old, + ) } } @@ -738,12 +795,13 @@ func (l4 *L4Filter) toMapState(p *EndpointPolicy, features policyFeatures, chang // // The caller is responsible for making sure the same identity is not // present in both 'added' and 'deleted'. -func (l4 *L4Filter) IdentitySelectionUpdated(cs types.CachedSelector, added, deleted []identity.NumericIdentity) { - log.WithFields(logrus.Fields{ - logfields.EndpointSelector: cs, - logfields.AddedPolicyID: added, - logfields.DeletedPolicyID: deleted, - }).Debug("identities selected by L4Filter updated") +func (l4 *L4Filter) IdentitySelectionUpdated(logger *slog.Logger, cs types.CachedSelector, added, deleted []identity.NumericIdentity) { + logger.Debug( + "identities selected by L4Filter updated", + logfields.EndpointSelector, cs, + logfields.AddedPolicyID, added, + logfields.DeletedPolicyID, deleted, + ) // Skip updates on wildcard selectors, as datapath and L7 // proxies do not need enumeration of all ids for L3 wildcard. @@ -758,12 +816,15 @@ func (l4 *L4Filter) IdentitySelectionUpdated(cs types.CachedSelector, added, del // that we could not push updates on an unstable policy. l4Policy := l4.policy.Load() if l4Policy != nil { - l4Policy.AccumulateMapChanges(l4, cs, added, deleted) + l4Policy.AccumulateMapChanges(logger, l4, cs, added, deleted) } } -func (l4 *L4Filter) IdentitySelectionCommit(txn *versioned.Tx) { - log.WithField(logfields.NewVersion, txn).Debug("identity selection updates done") +func (l4 *L4Filter) IdentitySelectionCommit(logger *slog.Logger, txn *versioned.Tx) { + logger.Debug( + "identity selection updates done", + logfields.NewVersion, txn, + ) // Push endpoint policy incremental sync. // @@ -808,16 +869,15 @@ func (l4 *L4Filter) cacheFQDNSelector(sel api.FQDNSelector, lbls stringLabels, s } // add L7 rules for all endpoints in the L7DataMap -func (l7 L7DataMap) addPolicyForSelector(rules *api.L7Rules, terminatingTLS, originatingTLS *TLSContext, auth *api.Authentication, deny bool, sni []string, listener string, priority uint8) { - isRedirect := !deny && (listener != "" || terminatingTLS != nil || originatingTLS != nil || len(sni) > 0 || !rules.IsEmpty()) +func (l7 L7DataMap) addPolicyForSelector(l7Parser L7ParserType, rules *api.L7Rules, terminatingTLS, originatingTLS *TLSContext, auth *api.Authentication, deny bool, sni []string, listener string, priority ListenerPriority) { for epsel := range l7 { l7policy := &PerSelectorPolicy{ + L7Parser: l7Parser, TerminatingTLS: terminatingTLS, OriginatingTLS: originatingTLS, Authentication: auth, IsDeny: deny, ServerNames: NewStringSet(sni), - isRedirect: isRedirect, Listener: listener, Priority: priority, } @@ -838,13 +898,17 @@ const ( // getCerts reads certificates out of the PolicyContext, reading from k8s or local files depending on config // and puts the values into the relevant keys in the TLSContext. Note that if the returned TLSContext.FromFile is // `false`, then this will be read from Kubernetes. -func (l4 *L4Filter) getCerts(policyCtx PolicyContext, tls *api.TLSContext, direction TLSDirection) (*TLSContext, error) { +func (l4 *L4Filter) getCerts(logger *slog.Logger, policyCtx PolicyContext, tls *api.TLSContext, direction TLSDirection) (*TLSContext, error) { if tls == nil { return nil, nil } ca, public, private, inlineSecrets, err := policyCtx.GetTLSContext(tls) if err != nil { - log.WithError(err).Warningf("policy: Error getting %s TLS Context.", direction) + logger.Warn( + "policy: Error getting TLS Context", + logfields.Error, err, + logfields.TrafficDirection, direction, + ) return nil, err } @@ -863,7 +927,7 @@ func (l4 *L4Filter) getCerts(policyCtx PolicyContext, tls *api.TLSContext, direc return nil, fmt.Errorf("invalid TLS direction: %s", direction) } } else { - log.Debug("Secret being read from Kubernetes", "secret", k8sTypes.NamespacedName(*tls.Secret)) + logger.Debug("Secret being read from Kubernetes", logfields.Secret, k8sTypes.NamespacedName(*tls.Secret)) } return &TLSContext{ @@ -880,7 +944,7 @@ func (l4 *L4Filter) getCerts(policyCtx PolicyContext, tls *api.TLSContext, direc // filter is derived from. This filter may be associated with a series of L7 // rules via the `rule` parameter. // Not called with an empty peerEndpoints. -func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorSlice, auth *api.Authentication, rule api.Ports, port api.PortProtocol, +func createL4Filter(logger *slog.Logger, policyCtx PolicyContext, peerEndpoints api.EndpointSelectorSlice, auth *api.Authentication, rule api.Ports, port api.PortProtocol, protocol api.L4Proto, ruleLabels stringLabels, ingress bool, fqdns api.FQDNSelectorSlice, ) (*L4Filter, error) { selectorCache := policyCtx.GetSelectorCache() @@ -916,12 +980,13 @@ func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorS l4.cacheFQDNSelectors(fqdns, ruleLabels, selectorCache) } + var l7Parser L7ParserType var terminatingTLS *TLSContext var originatingTLS *TLSContext var rules *api.L7Rules var sni []string listener := "" - var priority uint8 + var priority ListenerPriority pr := rule.GetPortRule() if pr != nil { @@ -930,11 +995,11 @@ func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorS // Get TLS contexts, if any var err error - terminatingTLS, err = l4.getCerts(policyCtx, pr.TerminatingTLS, TerminatingTLS) + terminatingTLS, err = l4.getCerts(logger, policyCtx, pr.TerminatingTLS, TerminatingTLS) if err != nil { return nil, err } - originatingTLS, err = l4.getCerts(policyCtx, pr.OriginatingTLS, OriginatingTLS) + originatingTLS, err = l4.getCerts(logger, policyCtx, pr.OriginatingTLS, OriginatingTLS) if err != nil { return nil, err } @@ -942,7 +1007,7 @@ func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorS // Set parser type to TLS, if TLS. This will be overridden by L7 below, if rules // exists. if terminatingTLS != nil || originatingTLS != nil || len(pr.ServerNames) > 0 { - l4.L7Parser = ParserTypeTLS + l7Parser = ParserTypeTLS } // Determine L7ParserType from rules present. Earlier validation ensures rules @@ -950,22 +1015,29 @@ func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorS if rules != nil { // we need this to redirect DNS UDP (or ANY, which is more useful) if len(rules.DNS) > 0 { - l4.L7Parser = ParserTypeDNS + l7Parser = ParserTypeDNS } else if protocol == api.ProtoTCP { // Other than DNS only support TCP switch { case len(rules.HTTP) > 0: - l4.L7Parser = ParserTypeHTTP + l7Parser = ParserTypeHTTP case len(rules.Kafka) > 0: - l4.L7Parser = ParserTypeKafka + l7Parser = ParserTypeKafka case rules.L7Proto != "": - l4.L7Parser = (L7ParserType)(rules.L7Proto) + l7Parser = (L7ParserType)(rules.L7Proto) } } } - // Override the parser type to CRD is applicable. + // Override the parser type and possibly priority for CRD is applicable. + if pr.Listener != nil { + l7Parser = ParserTypeCRD + } + + // Map parser type to default priority for the given parser type + priority = l7Parser.defaultPriority() + + // Override the parser type and possibly priority for CRD is applicable. if pr.Listener != nil { - l4.L7Parser = ParserTypeCRD ns := policyCtx.GetNamespace() resource := pr.Listener.EnvoyConfig switch resource.Kind { @@ -985,12 +1057,14 @@ func createL4Filter(policyCtx PolicyContext, peerEndpoints api.EndpointSelectorS default: } listener, _ = api.ResourceQualifiedName(ns, resource.Name, pr.Listener.Name, api.ForceNamespace) - priority = pr.Listener.Priority + if pr.Listener.Priority != 0 { + priority = ListenerPriority(pr.Listener.Priority) + } } } - if l4.L7Parser != ParserTypeNone || auth != nil || policyCtx.IsDeny() { - l4.PerSelectorPolicies.addPolicyForSelector(rules, terminatingTLS, originatingTLS, auth, policyCtx.IsDeny(), sni, listener, priority) + if l7Parser != ParserTypeNone || auth != nil || policyCtx.IsDeny() { + l4.PerSelectorPolicies.addPolicyForSelector(l7Parser, rules, terminatingTLS, originatingTLS, auth, policyCtx.IsDeny(), sni, listener, priority) } origin := singleRuleOrigin(ruleLabels) @@ -1022,17 +1096,17 @@ func (l4 *L4Filter) detach(selectorCache *SelectorCache) { // multiple goroutines will be reading the fields from that point on. func (l4 *L4Filter) attach(ctx PolicyContext, l4Policy *L4Policy) policyFeatures { var features policyFeatures - for cs, cp := range l4.PerSelectorPolicies { - if cp != nil { - if cp.isRedirect { + for cs, sp := range l4.PerSelectorPolicies { + if sp != nil { + if sp.L7Parser != "" { features.setFeature(redirectRules) } - if cp.IsDeny { + if sp.IsDeny { features.setFeature(denyRules) } - explicit, authType := getAuthType(cp.Authentication) + explicit, authType := getAuthType(sp.Authentication) if explicit { features.setFeature(authRules) @@ -1050,8 +1124,8 @@ func (l4 *L4Filter) attach(ctx PolicyContext, l4Policy *L4Policy) policyFeatures } // Compute Envoy policies when a policy is ready to be used - if len(cp.L7Rules.HTTP) > 0 { - cp.EnvoyHTTPRules, cp.CanShortCircuit = ctx.GetEnvoyHTTPRules(&cp.L7Rules) + if len(sp.L7Rules.HTTP) > 0 { + sp.EnvoyHTTPRules, sp.CanShortCircuit = ctx.GetEnvoyHTTPRules(&sp.L7Rules) } } } @@ -1067,10 +1141,10 @@ func (l4 *L4Filter) attach(ctx PolicyContext, l4Policy *L4Policy) policyFeatures // // hostWildcardL7 determines if L7 traffic from Host should be // wildcarded (in the relevant daemon mode). -func createL4IngressFilter(policyCtx PolicyContext, fromEndpoints api.EndpointSelectorSlice, auth *api.Authentication, hostWildcardL7 []string, rule api.Ports, port api.PortProtocol, +func createL4IngressFilter(logger *slog.Logger, policyCtx PolicyContext, fromEndpoints api.EndpointSelectorSlice, auth *api.Authentication, hostWildcardL7 []string, rule api.Ports, port api.PortProtocol, protocol api.L4Proto, ruleLabels stringLabels, ) (*L4Filter, error) { - filter, err := createL4Filter(policyCtx, fromEndpoints, auth, rule, port, protocol, ruleLabels, true, nil) + filter, err := createL4Filter(logger, policyCtx, fromEndpoints, auth, rule, port, protocol, ruleLabels, true, nil) if err != nil { return nil, err } @@ -1095,15 +1169,18 @@ func createL4IngressFilter(policyCtx PolicyContext, fromEndpoints api.EndpointSe // specified endpoints and port/protocol for egress traffic, with reference // to the original rules that the filter is derived from. This filter may be // associated with a series of L7 rules via the `rule` parameter. -func createL4EgressFilter(policyCtx PolicyContext, toEndpoints api.EndpointSelectorSlice, auth *api.Authentication, rule api.Ports, port api.PortProtocol, +func createL4EgressFilter(logger *slog.Logger, policyCtx PolicyContext, toEndpoints api.EndpointSelectorSlice, auth *api.Authentication, rule api.Ports, port api.PortProtocol, protocol api.L4Proto, ruleLabels stringLabels, fqdns api.FQDNSelectorSlice, ) (*L4Filter, error) { - return createL4Filter(policyCtx, toEndpoints, auth, rule, port, protocol, ruleLabels, false, fqdns) + return createL4Filter(logger, policyCtx, toEndpoints, auth, rule, port, protocol, ruleLabels, false, fqdns) } // redirectType returns the redirectType for this filter -func (l4 *L4Filter) redirectType() redirectTypes { - switch l4.L7Parser { +func (sp *PerSelectorPolicy) redirectType() redirectTypes { + if sp == nil { + return redirectTypeNone + } + switch sp.L7Parser { case ParserTypeNone: return redirectTypeNone case ParserTypeDNS: @@ -1116,11 +1193,6 @@ func (l4 *L4Filter) redirectType() redirectTypes { } } -// IsRedirect returns true if the L4 filter contains a port redirection -func (l4 *L4Filter) IsRedirect() bool { - return l4.L7Parser != ParserTypeNone -} - // Marshal returns the `L4Filter` in a JSON string. func (l4 *L4Filter) Marshal() string { b, err := json.Marshal(l4) @@ -1514,7 +1586,9 @@ func (l4 *L4DirectionPolicy) attach(ctx PolicyContext, l4Policy *L4Policy) redir var features policyFeatures l4.PortRules.ForEach(func(f *L4Filter) bool { features |= f.attach(ctx, l4Policy) - redirectTypes |= f.redirectType() + for _, sp := range f.PerSelectorPolicies { + redirectTypes |= sp.redirectType() + } return true }) l4.features = features @@ -1649,7 +1723,7 @@ func (l4 *L4Policy) removeUser(user *EndpointPolicy) { // // The caller is responsible for making sure the same identity is not // present in both 'adds' and 'deletes'. -func (l4Policy *L4Policy) AccumulateMapChanges(l4 *L4Filter, cs CachedSelector, adds, deletes []identity.NumericIdentity) { +func (l4Policy *L4Policy) AccumulateMapChanges(logger *slog.Logger, l4 *L4Filter, cs CachedSelector, adds, deletes []identity.NumericIdentity) { port := uint16(l4.Port) proto := l4.U8Proto derivedFrom := l4.RuleOrigin[cs] @@ -1684,15 +1758,16 @@ func (l4Policy *L4Policy) AccumulateMapChanges(l4 *L4Filter, cs CachedSelector, var err error proxyPort, err = epPolicy.LookupRedirectPort(l4.Ingress, string(l4.Protocol), port, listener) if err != nil { - log.WithFields(logrus.Fields{ - logfields.EndpointSelector: cs, - logfields.Port: port, - logfields.Protocol: proto, - logfields.TrafficDirection: direction, - logfields.IsRedirect: redirect, - logfields.Listener: listener, - logfields.ListenerPriority: priority, - }).Warn("AccumulateMapChanges: Missing redirect.") + logger.Warn( + "AccumulateMapChanges: Missing redirect.", + logfields.EndpointSelector, cs, + logfields.Port, port, + logfields.Protocol, proto, + logfields.TrafficDirection, direction, + logfields.IsRedirect, redirect, + logfields.Listener, listener, + logfields.ListenerPriority, priority, + ) continue } } @@ -1708,18 +1783,19 @@ func (l4Policy *L4Policy) AccumulateMapChanges(l4 *L4Filter, cs CachedSelector, if authReq.IsExplicit() { authString = authReq.AuthType().String() } - log.WithFields(logrus.Fields{ - logfields.EndpointSelector: cs, - logfields.AddedPolicyID: adds, - logfields.DeletedPolicyID: deletes, - logfields.Port: port, - logfields.Protocol: proto, - logfields.TrafficDirection: direction, - logfields.IsRedirect: redirect, - logfields.AuthType: authString, - logfields.Listener: listener, - logfields.ListenerPriority: priority, - }).Debug("AccumulateMapChanges") + logger.Debug( + "AccumulateMapChanges", + logfields.EndpointSelector, cs, + logfields.AddedPolicyID, adds, + logfields.DeletedPolicyID, deletes, + logfields.Port, port, + logfields.Protocol, proto, + logfields.TrafficDirection, direction, + logfields.IsRedirect, redirect, + logfields.AuthType, authString, + logfields.Listener, listener, + logfields.ListenerPriority, priority, + ) } epPolicy.policyMapChanges.AccumulateMapChanges(adds, deletes, keysToAdd, value) } @@ -1754,7 +1830,7 @@ func (l4 *L4Policy) detach(selectorCache *SelectorCache, isDelete bool, endpoint if !isDelete { for ePolicy := range l4.users { if endpointID != ePolicy.PolicyOwner.GetID() { - ePolicy.PolicyOwner.RegenerateIfAlive(®eneration.ExternalRegenerationMetadata{ + go ePolicy.PolicyOwner.RegenerateIfAlive(®eneration.ExternalRegenerationMetadata{ Reason: "selector policy has changed because of another endpoint with the same identity", RegenerationLevel: regeneration.RegenerateWithoutDatapath, }) diff --git a/vendor/github.com/cilium/cilium/pkg/policy/lookup.go b/vendor/github.com/cilium/cilium/pkg/policy/lookup.go index 156b45ea77..c04a1672c9 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/lookup.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/lookup.go @@ -46,7 +46,7 @@ type EndpointInfo struct { // This function is only used for testing, but in multiple packages. // // TODO: add support for redirects -func LookupFlow(repo PolicyRepository, flow Flow, srcEP, dstEP *EndpointInfo) (api.Decision, error) { +func LookupFlow(logger *slog.Logger, repo PolicyRepository, flow Flow, srcEP, dstEP *EndpointInfo) (api.Decision, error) { if flow.From.ID == 0 || flow.To.ID == 0 { return api.Undecided, fmt.Errorf("cannot lookup flow: numeric IDs missing") } @@ -84,9 +84,9 @@ func LookupFlow(repo PolicyRepository, flow Flow, srcEP, dstEP *EndpointInfo) (a return api.Undecided, fmt.Errorf("GetSelectorPolicy(from) failed: %w", err) } - epp := selPolSrc.DistillPolicy(srcEP, nil) + epp := selPolSrc.DistillPolicy(logger, srcEP, nil) epp.Ready() - epp.Detach() + epp.Detach(logger) key := EgressKey().WithIdentity(flow.To.ID).WithPortProto(flow.Proto, flow.Dport) entry, _, _ := epp.Lookup(key) if entry.IsDeny() { @@ -98,9 +98,9 @@ func LookupFlow(repo PolicyRepository, flow Flow, srcEP, dstEP *EndpointInfo) (a if err != nil { return api.Undecided, fmt.Errorf("GetSelectorPolicy(to) failed: %w", err) } - epp = selPolDst.DistillPolicy(dstEP, nil) + epp = selPolDst.DistillPolicy(logger, dstEP, nil) epp.Ready() - epp.Detach() + epp.Detach(logger) key = IngressKey().WithIdentity(flow.From.ID).WithPortProto(flow.Proto, flow.Dport) entry, _, _ = epp.Lookup(key) if entry.IsDeny() { @@ -134,11 +134,11 @@ func (ei *EndpointInfo) GetNamedPort(ingress bool, name string, proto u8proto.U8 func (ei *EndpointInfo) PolicyDebug(fields logrus.Fields, msg string) { if ei.Logger != nil { - args := make([]any, 0, len(fields)*2) + attrs := make([]any, 0, len(fields)*2) for k, v := range fields { - args = append(args, k, v) + attrs = append(attrs, k, v) } - ei.Logger.Debug(msg, args...) + ei.Logger.Debug(msg, attrs...) } } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go b/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go index b0f02436cc..d05a2a870a 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/mapstate.go @@ -5,9 +5,9 @@ package policy import ( "iter" + "log/slog" "github.com/hashicorp/go-hclog" - "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/container/bitlpm" "github.com/cilium/cilium/pkg/container/versioned" @@ -91,6 +91,7 @@ var ( // greatly enhances the usefuleness of the Trie and improves lookup, // deletion, and insertion times. type mapState struct { + logger *slog.Logger // entries is the map containing the MapStateEntries entries mapStateMap // trie is a Trie that indexes policy Keys without their identity @@ -165,10 +166,11 @@ func (ms *mapState) forKey(k Key, f func(Key, mapStateEntry) bool) bool { if ok { return f(k, e) } - log.WithFields(logrus.Fields{ - logfields.Stacktrace: hclog.Stacktrace(), - logfields.PolicyKey: k, - }).Errorf("Missing MapStateEntry") + ms.logger.Error( + "Missing MapStateEntry", + logfields.Stacktrace, hclog.Stacktrace(), + logfields.PolicyKey, k, + ) return true } @@ -398,7 +400,7 @@ type mapStateEntry struct { } // newMapStateEntry creates a map state entry. -func newMapStateEntry(derivedFrom ruleOrigin, proxyPort uint16, priority uint8, deny bool, authReq AuthRequirement) mapStateEntry { +func newMapStateEntry(derivedFrom ruleOrigin, proxyPort uint16, priority ListenerPriority, deny bool, authReq AuthRequirement) mapStateEntry { return mapStateEntry{ MapStateEntry: types.NewMapStateEntry(deny, proxyPort, priority, authReq), derivedFromRules: derivedFrom, @@ -418,12 +420,13 @@ func NewMapStateEntry(e MapStateEntry) mapStateEntry { } } -func emptyMapState() mapState { - return newMapState(0) +func emptyMapState(logger *slog.Logger) mapState { + return newMapState(logger, 0) } -func newMapState(size int) mapState { +func newMapState(logger *slog.Logger, size int) mapState { return mapState{ + logger: logger, entries: make(mapStateMap, size), trie: bitlpm.NewTrie[types.LPMKey, IDSet](types.MapStatePrefixLen), } @@ -441,10 +444,11 @@ func (ms *mapState) Get(k Key) (MapStateEntry, bool) { // Get the mapStateEntry that matches the Key. func (ms *mapState) get(k Key) (mapStateEntry, bool) { if k.DestPort == 0 && k.PortPrefixLen() > 0 { - log.WithFields(logrus.Fields{ - logfields.Stacktrace: hclog.Stacktrace(), - logfields.PolicyKey: k, - }).Errorf("mapState.Get: invalid port prefix length for wildcard port") + ms.logger.Error( + "mapState.Get: invalid port prefix length for wildcard port", + logfields.Stacktrace, hclog.Stacktrace(), + logfields.PolicyKey, k, + ) } v, ok := ms.entries[k] @@ -454,10 +458,11 @@ func (ms *mapState) get(k Key) (mapStateEntry, bool) { // insert the Key and MapStateEntry into the MapState func (ms *mapState) insert(k Key, v mapStateEntry) { if k.DestPort == 0 && k.PortPrefixLen() > 0 { - log.WithFields(logrus.Fields{ - logfields.Stacktrace: hclog.Stacktrace(), - logfields.PolicyKey: k, - }).Errorf("mapState.insert: invalid port prefix length for wildcard port") + ms.logger.Error( + "mapState.insert: invalid port prefix length for wildcard port", + logfields.Stacktrace, hclog.Stacktrace(), + logfields.PolicyKey, k, + ) } ms.upsert(k, v) } @@ -732,7 +737,7 @@ func (ms *mapState) insertWithChanges(newKey Key, newEntry mapStateEntry, featur // old entry in 'changes'. // Returns 'true' if changes were made. func (ms *mapState) overrideProxyPortForAuth(newEntry mapStateEntry, k Key, v mapStateEntry, changes ChangeState) bool { - if v.AuthRequirement != newEntry.AuthRequirement && v.AuthRequirement.IsExplicit() { + if v.AuthRequirement.IsExplicit() { // Save the old value first changes.insertOldIfNotExists(k, v) @@ -776,9 +781,9 @@ func (ms *mapState) authPreferredInsert(newKey Key, newEntry mapStateEntry, feat return // bail if covered by deny } if v.ProxyPortPriority > newEntry.ProxyPortPriority { - if !newEntryHasExplicitAuth || v.AuthRequirement == newEntry.AuthRequirement { + if !newEntryHasExplicitAuth { // Covering entry has higher proxy port priority and newEntry has a - // default auth type or the same auth requirement => can bail out + // default auth type => can bail out return } @@ -882,6 +887,7 @@ func (ms *mapState) allowAllIdentities(ingress, egress bool) { // granularity of individual mapstate key-value pairs for both adds // and deletes. 'mutex' must be held for any access. type MapChanges struct { + logger *slog.Logger firstVersion versioned.KeepVersion mutex lock.Mutex changes []mapChange @@ -941,14 +947,16 @@ func (mc *MapChanges) SyncMapChanges(txn *versioned.Tx) { mc.synced = append(mc.synced, mc.changes...) mc.version.Close() mc.version = txn.GetVersionHandle() - log.WithFields(logrus.Fields{ - logfields.NewVersion: mc.version, - }).Debug("SyncMapChanges: Got handle on the new version") + mc.logger.Debug( + "SyncMapChanges: Got handle on the new version", + logfields.NewVersion, mc.version, + ) } else { - log.WithFields(logrus.Fields{ - logfields.Version: mc.firstVersion, - logfields.OldVersion: txn, - }).Debug("SyncMapChanges: Discarding already applied changes") + mc.logger.Debug( + "SyncMapChanges: Discarding already applied changes", + logfields.Version, mc.firstVersion, + logfields.OldVersion, txn, + ) } } mc.changes = nil diff --git a/vendor/github.com/cilium/cilium/pkg/policy/policy.go b/vendor/github.com/cilium/cilium/pkg/policy/policy.go index b4ae208e46..c735ad65c4 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/policy.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/policy.go @@ -30,7 +30,6 @@ func (s *SearchContext) TraceEnabled() bool { // TRACE_ENABLED or TRACE_VERBOSE is enabled in the receiver's SearchContext. func (s *SearchContext) PolicyTrace(format string, a ...interface{}) { if s.TraceEnabled() { - log.Debugf(format, a...) if s.Logging != nil { format = "%-" + s.CallDepth() + "s" + format a = append([]interface{}{""}, a...) @@ -44,7 +43,6 @@ func (s *SearchContext) PolicyTrace(format string, a ...interface{}) { func (s *SearchContext) PolicyTraceVerbose(format string, a ...interface{}) { switch s.Trace { case TRACE_VERBOSE: - log.Debugf(format, a...) if s.Logging != nil { s.Logging.Printf(format, a...) } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/repository.go b/vendor/github.com/cilium/cilium/pkg/policy/repository.go index 8d77907255..fc6b0f32df 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/repository.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/repository.go @@ -7,7 +7,9 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "maps" + "slices" "sync/atomic" cilium "github.com/cilium/proxy/go/cilium/api" @@ -16,6 +18,7 @@ import ( "github.com/cilium/cilium/api/v1/models" "github.com/cilium/cilium/pkg/container/set" "github.com/cilium/cilium/pkg/crypto/certificatemanager" + envoypolicy "github.com/cilium/cilium/pkg/envoy/policy" "github.com/cilium/cilium/pkg/identity" "github.com/cilium/cilium/pkg/identity/identitymanager" ipcachetypes "github.com/cilium/cilium/pkg/ipcache/types" @@ -126,7 +129,6 @@ type PolicyRepository interface { ReplaceByResource(rules api.Rules, resource ipcachetypes.ResourceID) (affectedIDs *set.Set[identity.NumericIdentity], rev uint64, oldRevCnt int) ReplaceByLabels(rules api.Rules, searchLabelsList []labels.LabelArray) (affectedIDs *set.Set[identity.NumericIdentity], rev uint64, oldRevCnt int) Search(lbls labels.LabelArray) (api.Rules, uint64) - SetEnvoyRulesFunc(f func(certificatemanager.SecretManager, *api.L7Rules, string, string) (*cilium.HttpNetworkPolicyRules, bool)) } type GetPolicyStatistics interface { @@ -137,6 +139,7 @@ type GetPolicyStatistics interface { // Repository is a list of policy rules which in combination form the security // policy. A policy repository can be type Repository struct { + logger *slog.Logger // mutex protects the whole policy tree mutex lock.RWMutex @@ -161,12 +164,14 @@ type Repository struct { // PolicyCache tracks the selector policies created from this repo policyCache *policyCache - certManager certificatemanager.CertificateManager - secretManager certificatemanager.SecretManager + certManager certificatemanager.CertificateManager - getEnvoyHTTPRules func(certificatemanager.SecretManager, *api.L7Rules, string, string) (*cilium.HttpNetworkPolicyRules, bool) + metricsManager api.PolicyMetrics + l7RulesTranslator envoypolicy.EnvoyL7RulesTranslator +} - metricsManager api.PolicyMetrics +func (p *Repository) GetEnvoyHTTPRules(l7Rules *api.L7Rules, ns string) (*cilium.HttpNetworkPolicyRules, bool) { + return p.l7RulesTranslator.GetEnvoyHTTPRules(l7Rules, ns) } // GetSelectorCache() returns the selector cache used by the Repository @@ -179,34 +184,25 @@ func (p *Repository) GetAuthTypes(localID, remoteID identity.NumericIdentity) Au return p.policyCache.getAuthTypes(localID, remoteID) } -func (p *Repository) SetEnvoyRulesFunc(f func(certificatemanager.SecretManager, *api.L7Rules, string, string) (*cilium.HttpNetworkPolicyRules, bool)) { - p.getEnvoyHTTPRules = f -} - -func (p *Repository) GetEnvoyHTTPRules(l7Rules *api.L7Rules, ns string) (*cilium.HttpNetworkPolicyRules, bool) { - if p.getEnvoyHTTPRules == nil { - return nil, true - } - return p.getEnvoyHTTPRules(p.secretManager, l7Rules, ns, p.secretManager.GetSecretSyncNamespace()) -} - // NewPolicyRepository creates a new policy repository. func NewPolicyRepository( + logger *slog.Logger, initialIDs identity.IdentityMap, certManager certificatemanager.CertificateManager, - secretManager certificatemanager.SecretManager, + l7RulesTranslator envoypolicy.EnvoyL7RulesTranslator, idmgr identitymanager.IDManager, metricsManager api.PolicyMetrics, ) *Repository { - selectorCache := NewSelectorCache(initialIDs) + selectorCache := NewSelectorCache(logger, initialIDs) repo := &Repository{ - rules: make(map[ruleKey]*rule), - rulesByNamespace: make(map[string]sets.Set[ruleKey]), - rulesByResource: make(map[ipcachetypes.ResourceID]map[ruleKey]*rule), - selectorCache: selectorCache, - certManager: certManager, - secretManager: secretManager, - metricsManager: metricsManager, + logger: logger, + rules: make(map[ruleKey]*rule), + rulesByNamespace: make(map[string]sets.Set[ruleKey]), + rulesByResource: make(map[ipcachetypes.ResourceID]map[ruleKey]*rule), + selectorCache: selectorCache, + certManager: certManager, + metricsManager: metricsManager, + l7RulesTranslator: l7RulesTranslator, } repo.revision.Store(1) repo.policyCache = newPolicyCache(repo, idmgr) @@ -447,7 +443,7 @@ func (p *Repository) resolvePolicyLocked(securityIdentity *identity.Identity) (* } if ingressEnabled { - newL4IngressPolicy, err := matchingRules.resolveL4IngressPolicy(&policyCtx, &ingressCtx) + newL4IngressPolicy, err := matchingRules.resolveL4IngressPolicy(p.logger, &policyCtx, &ingressCtx) if err != nil { return nil, err } @@ -455,7 +451,7 @@ func (p *Repository) resolvePolicyLocked(securityIdentity *identity.Identity) (* } if egressEnabled { - newL4EgressPolicy, err := matchingRules.resolveL4EgressPolicy(&policyCtx, &egressCtx) + newL4EgressPolicy, err := matchingRules.resolveL4EgressPolicy(p.logger, &policyCtx, &egressCtx) if err != nil { return nil, err } @@ -562,13 +558,13 @@ func (p *Repository) computePolicyEnforcementAndRules(securityIdentity *identity // If there only ingress default-allow rules, then insert a wildcard rule if !hasIngressDefaultDeny && ingress { - log.WithField(logfields.Identity, securityIdentity).Debug("Only default-allow policies, synthesizing ingress wildcard-allow rule") + p.logger.Debug("Only default-allow policies, synthesizing ingress wildcard-allow rule", logfields.Identity, securityIdentity) matchingRules = append(matchingRules, wildcardRule(securityIdentity.LabelArray, true /*ingress*/)) } // Same for egress -- synthesize a wildcard rule if !hasEgressDefaultDeny && egress { - log.WithField(logfields.Identity, securityIdentity).Debug("Only default-allow policies, synthesizing egress wildcard-allow rule") + p.logger.Debug("Only default-allow policies, synthesizing egress wildcard-allow rule", logfields.Identity, securityIdentity) matchingRules = append(matchingRules, wildcardRule(securityIdentity.LabelArray, false /*egress*/)) } @@ -647,7 +643,7 @@ func (p *Repository) ReplaceByResource(rules api.Rules, resource ipcachetypes.Re if len(resource) == 0 { // This should never ever be hit, as the caller should have already validated the resource. // Out of paranoia, do nothing. - log.Error("Attempt to replace rules by resource with an empty resource.") + p.logger.Error("Attempt to replace rules by resource with an empty resource.") return } @@ -697,12 +693,9 @@ func (p *Repository) ReplaceByLabels(rules api.Rules, searchLabelsList []labels. // determine outgoing rules for ruleKey, rule := range p.rules { - for _, searchLabels := range searchLabelsList { - if rule.Labels.Contains(searchLabels) { - p.del(ruleKey) - oldRules = append(oldRules, rule) - break - } + if slices.ContainsFunc(searchLabelsList, rule.Labels.Contains) { + p.del(ruleKey) + oldRules = append(oldRules, rule) } } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/resolve.go b/vendor/github.com/cilium/cilium/pkg/policy/resolve.go index f0fcc7337a..8d5424c973 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/resolve.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/resolve.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "iter" + "log/slog" "runtime" "github.com/sirupsen/logrus" @@ -28,7 +29,7 @@ type SelectorPolicy interface { // DistillPolicy returns the policy in terms of connectivity to peer // Identities. - DistillPolicy(owner PolicyOwner, redirects map[string]uint16) *EndpointPolicy + DistillPolicy(logger *slog.Logger, owner PolicyOwner, redirects map[string]uint16) *EndpointPolicy } // selectorPolicy is a structure which contains the resolved policy for a @@ -166,7 +167,7 @@ func (p *selectorPolicy) detach(isDelete bool, endpointID uint64) { // Called without holding the Selector cache or Repository locks. // PolicyOwner (aka Endpoint) is also unlocked during this call, // but the Endpoint's build mutex is held. -func (p *selectorPolicy) DistillPolicy(policyOwner PolicyOwner, redirects map[string]uint16) *EndpointPolicy { +func (p *selectorPolicy) DistillPolicy(logger *slog.Logger, policyOwner PolicyOwner, redirects map[string]uint16) *EndpointPolicy { var calculatedPolicy *EndpointPolicy // EndpointPolicy is initialized while 'GetCurrentVersionHandleFunc' keeps the selector @@ -185,8 +186,9 @@ func (p *selectorPolicy) DistillPolicy(policyOwner PolicyOwner, redirects map[st calculatedPolicy = &EndpointPolicy{ selectorPolicy: p, VersionHandle: version, - policyMapState: newMapState(policyOwner.MapStateSize()), + policyMapState: newMapState(logger, policyOwner.MapStateSize()), policyMapChanges: MapChanges{ + logger: logger, firstVersion: version.Version(), }, PolicyOwner: policyOwner, @@ -205,7 +207,7 @@ func (p *selectorPolicy) DistillPolicy(policyOwner PolicyOwner, redirects map[st // Must come after the 'insertUser()' above to guarantee // PolicyMapChanges will contain all changes that are applied // after the computation of PolicyMapState has started. - calculatedPolicy.toMapState() + calculatedPolicy.toMapState(logger) if !policyOwner.IsHost() { calculatedPolicy.policyMapState.determineAllowLocalhostIngress() } @@ -225,13 +227,17 @@ func (p *EndpointPolicy) Ready() (err error) { // Detach removes EndpointPolicy references from selectorPolicy // to allow the EndpointPolicy to be GC'd. // PolicyOwner (aka Endpoint) is also locked during this call. -func (p *EndpointPolicy) Detach() { +func (p *EndpointPolicy) Detach(logger *slog.Logger) { p.selectorPolicy.removeUser(p) // in case the call was missed previouly if p.Ready() == nil { // succeeded, so it was missed previously _, file, line, _ := runtime.Caller(1) - log.Warningf("Detach: EndpointPolicy was not marked as Ready (%s:%d)", file, line) + logger.Warn( + "Detach: EndpointPolicy was not marked as Ready", + logfields.File, file, + logfields.Line, line, + ) } // Also release the version handle held for incremental updates, if any. // This must be done after the removeUser() call above, so that we do not get a new version @@ -356,9 +362,9 @@ func (p *EndpointPolicy) RevertChanges(changes ChangeState) { // Called without holding the Repository lock. // PolicyOwner (aka Endpoint) is also unlocked during this call, // but the Endpoint's build mutex is held. -func (p *EndpointPolicy) toMapState() { - p.L4Policy.Ingress.toMapState(p) - p.L4Policy.Egress.toMapState(p) +func (p *EndpointPolicy) toMapState(logger *slog.Logger) { + p.L4Policy.Ingress.toMapState(logger, p) + p.L4Policy.Egress.toMapState(logger, p) } // toMapState transforms the L4DirectionPolicy into @@ -367,9 +373,9 @@ func (p *EndpointPolicy) toMapState() { // Called without holding the Repository lock. // PolicyOwner (aka Endpoint) is also unlocked during this call, // but the Endpoint's build mutex is held. -func (l4policy L4DirectionPolicy) toMapState(p *EndpointPolicy) { +func (l4policy L4DirectionPolicy) toMapState(logger *slog.Logger, p *EndpointPolicy) { l4policy.PortRules.ForEach(func(l4 *L4Filter) bool { - l4.toMapState(p, l4policy.features, ChangeState{}) + l4.toMapState(logger, p, l4policy.features, ChangeState{}) return true }) } @@ -386,11 +392,9 @@ func (p *selectorPolicy) RedirectFilters() iter.Seq2[*L4Filter, *PerSelectorPoli func (l4policy L4DirectionPolicy) forEachRedirectFilter(yield func(*L4Filter, *PerSelectorPolicy) bool) bool { ok := true l4policy.PortRules.ForEach(func(l4 *L4Filter) bool { - if l4.IsRedirect() { - for _, ps := range l4.PerSelectorPolicies { - if ps != nil && ps.IsRedirect() { - ok = yield(l4, ps) - } + for _, ps := range l4.PerSelectorPolicies { + if ps != nil && ps.IsRedirect() { + ok = yield(l4, ps) } } return ok @@ -432,9 +436,9 @@ func (p *EndpointPolicy) ConsumeMapChanges() (closer func(), changes ChangeState } // NewEndpointPolicy returns an empty EndpointPolicy stub. -func NewEndpointPolicy(repo PolicyRepository) *EndpointPolicy { +func NewEndpointPolicy(logger *slog.Logger, repo PolicyRepository) *EndpointPolicy { return &EndpointPolicy{ selectorPolicy: newSelectorPolicy(repo.GetSelectorCache()), - policyMapState: emptyMapState(), + policyMapState: emptyMapState(logger), } } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/rule.go b/vendor/github.com/cilium/cilium/pkg/policy/rule.go index aa8e024f40..a11a0d4058 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/rule.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/rule.go @@ -5,6 +5,7 @@ package policy import ( "fmt" + "log/slog" "strconv" "strings" @@ -40,10 +41,10 @@ type rule struct { // IdentitySelectionUpdated is called by the SelectorCache when a new identity is added; // We can ignore it because the endpoint will be regenerated by the nature of // identities being updated. -func (r *rule) IdentitySelectionUpdated(_ policytypes.CachedSelector, _, _ []identity.NumericIdentity) { +func (r *rule) IdentitySelectionUpdated(logger *slog.Logger, selector policytypes.CachedSelector, added, deleted []identity.NumericIdentity) { } -func (d *rule) IdentitySelectionCommit(*versioned.Tx) { +func (d *rule) IdentitySelectionCommit(*slog.Logger, *versioned.Tx) { } func (r *rule) IsPeerSelector() bool { @@ -107,7 +108,7 @@ func (epd *PerSelectorPolicy) appendL7WildcardRule(ctx *SearchContext) api.L7Rul // takesListenerPrecedenceOver returns true if the listener reference in 'l7Rules' takes precedence // over the listener reference in 'other'. func (l7Rules *PerSelectorPolicy) takesListenerPrecedenceOver(other *PerSelectorPolicy) bool { - var priority, otherPriority uint8 + var priority, otherPriority ListenerPriority // decrement by one to wrap the undefined value (0) to be the highest numerical // value of the uint16, which is the lowest possible priority @@ -117,9 +118,21 @@ func (l7Rules *PerSelectorPolicy) takesListenerPrecedenceOver(other *PerSelector return priority < otherPriority } -// mergeListenerReference merges listener reference from 'newL7Rules' to 'l7Rules', giving +// mergeRedirect merges listener reference from 'newL7Rules' to 'l7Rules', giving // precedence to listener with the lowest priority, if any. -func (l7Rules *PerSelectorPolicy) mergeListenerReference(newL7Rules *PerSelectorPolicy) error { +func (l7Rules *PerSelectorPolicy) mergeRedirect(newL7Rules *PerSelectorPolicy) error { + // Merge L7ParserType, if possible + l7Parser, err := l7Rules.L7Parser.Merge(newL7Rules.L7Parser) + if err != nil { + return err + } + + if l7Parser != l7Rules.L7Parser { + // Also copy over the listener priority + l7Rules.L7Parser = l7Parser + l7Rules.Priority = newL7Rules.Priority + } + // Nothing to do if 'newL7Rules' has no listener reference if newL7Rules.Listener == "" { return nil @@ -146,15 +159,9 @@ func (l7Rules *PerSelectorPolicy) mergeListenerReference(newL7Rules *PerSelector return fmt.Errorf("cannot merge conflicting CiliumEnvoyConfig Listeners (%v/%v) with the same priority (%d)", newL7Rules.Listener, l7Rules.Listener, l7Rules.Priority) } +// mergePortProto merges the L7-related data from the filter to merge +// with the L7-related data already in the existing filter. func mergePortProto(ctx *SearchContext, existingFilter, filterToMerge *L4Filter, selectorCache *SelectorCache) (err error) { - // Merge the L7-related data from the filter to merge - // with the L7-related data already in the existing filter. - existingFilter.L7Parser, err = existingFilter.L7Parser.Merge(filterToMerge.L7Parser) - if err != nil { - ctx.PolicyTrace(" Merge conflict: mismatching parsers %s/%s\n", filterToMerge.L7Parser, existingFilter.L7Parser) - return err - } - for cs, newL7Rules := range filterToMerge.PerSelectorPolicies { // 'cs' will be merged or moved (see below), either way it needs // to be removed from the map it is in now. @@ -197,11 +204,8 @@ func mergePortProto(ctx *SearchContext, existingFilter, filterToMerge *L4Filter, newL7Rules = &PerSelectorPolicy{} } - // Merge isRedirect flag - l7Rules.isRedirect = l7Rules.isRedirect || newL7Rules.isRedirect - - // Merge listener reference - if err := l7Rules.mergeListenerReference(newL7Rules); err != nil { + // Merge Redirect + if err := l7Rules.mergeRedirect(newL7Rules); err != nil { ctx.PolicyTrace(" Merge conflict: %s\n", err.Error()) return err } @@ -332,10 +336,10 @@ func mergePortProto(ctx *SearchContext, existingFilter, filterToMerge *L4Filter, // wildcards via 'hostWildcardL7'. That is to say, traffic will be // forwarded to the proxy for endpoints matching those labels, but the proxy // will allow all such traffic. -func mergeIngressPortProto(policyCtx PolicyContext, ctx *SearchContext, endpoints api.EndpointSelectorSlice, auth *api.Authentication, hostWildcardL7 []string, +func mergeIngressPortProto(logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext, endpoints api.EndpointSelectorSlice, auth *api.Authentication, hostWildcardL7 []string, r api.Ports, p api.PortProtocol, proto api.L4Proto, ruleLabels stringLabels, resMap L4PolicyMap) (int, error) { // Create a new L4Filter - filterToMerge, err := createL4IngressFilter(policyCtx, endpoints, auth, hostWildcardL7, r, p, proto, ruleLabels) + filterToMerge, err := createL4IngressFilter(logger, policyCtx, endpoints, auth, hostWildcardL7, r, p, proto, ruleLabels) if err != nil { return 0, err } @@ -400,7 +404,7 @@ func rulePortsCoverSearchContext(ports []api.PortProtocol, ctx *SearchContext) b return false } -func mergeIngress(policyCtx PolicyContext, ctx *SearchContext, fromEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels stringLabels, resMap L4PolicyMap) (int, error) { +func mergeIngress(logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext, fromEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels stringLabels, resMap L4PolicyMap) (int, error) { found := 0 // short-circuit if no endpoint is selected @@ -436,7 +440,7 @@ func mergeIngress(policyCtx PolicyContext, ctx *SearchContext, fromEndpoints api // L3-only rule (with requirements folded into fromEndpoints). if toPorts.Len() == 0 && icmp.Len() == 0 && len(fromEndpoints) > 0 { - cnt, err = mergeIngressPortProto(policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, &api.PortRule{}, api.PortProtocol{Port: "0", Protocol: api.ProtoAny}, api.ProtoAny, ruleLabels, resMap) + cnt, err = mergeIngressPortProto(logger, policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, &api.PortRule{}, api.PortProtocol{Port: "0", Protocol: api.ProtoAny}, api.ProtoAny, ruleLabels, resMap) if err != nil { return found, err } @@ -480,25 +484,25 @@ func mergeIngress(policyCtx PolicyContext, ctx *SearchContext, fromEndpoints api for _, p := range r.GetPortProtocols() { if p.Protocol.IsAny() { - cnt, err := mergeIngressPortProto(policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, api.ProtoTCP, ruleLabels, resMap) + cnt, err := mergeIngressPortProto(logger, policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, api.ProtoTCP, ruleLabels, resMap) if err != nil { return err } found += cnt - cnt, err = mergeIngressPortProto(policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, api.ProtoUDP, ruleLabels, resMap) + cnt, err = mergeIngressPortProto(logger, policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, api.ProtoUDP, ruleLabels, resMap) if err != nil { return err } found += cnt - cnt, err = mergeIngressPortProto(policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, api.ProtoSCTP, ruleLabels, resMap) + cnt, err = mergeIngressPortProto(logger, policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, api.ProtoSCTP, ruleLabels, resMap) if err != nil { return err } found += cnt } else { - cnt, err := mergeIngressPortProto(policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, p.Protocol, ruleLabels, resMap) + cnt, err := mergeIngressPortProto(logger, policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, p.Protocol, ruleLabels, resMap) if err != nil { return err } @@ -527,7 +531,7 @@ func mergeIngress(policyCtx PolicyContext, ctx *SearchContext, fromEndpoints api } for _, p := range r.GetPortProtocols() { - cnt, err := mergeIngressPortProto(policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, p.Protocol, ruleLabels, resMap) + cnt, err := mergeIngressPortProto(logger, policyCtx, ctx, fromEndpoints, auth, hostWildcardL7, r, p, p.Protocol, ruleLabels, resMap) if err != nil { return err } @@ -555,6 +559,7 @@ func (state *traceState) unSelectRule(ctx *SearchContext, labels labels.LabelArr // These requirements are dynamically inserted into a copy of the receiver rule, // as requirements form conjunctions across all rules. func (r *rule) resolveIngressPolicy( + logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext, state *traceState, @@ -578,7 +583,7 @@ func (r *rule) resolveIngressPolicy( } for _, ingressRule := range r.Ingress { fromEndpoints := ingressRule.GetSourceEndpointSelectorsWithRequirements(requirements) - cnt, err := mergeIngress(policyCtx, ctx, fromEndpoints, ingressRule.Authentication, ingressRule.ToPorts, ingressRule.ICMPs, makeStringLabels(r.Rule.Labels), result) + cnt, err := mergeIngress(logger, policyCtx, ctx, fromEndpoints, ingressRule.Authentication, ingressRule.ToPorts, ingressRule.ICMPs, makeStringLabels(r.Rule.Labels), result) if err != nil { return nil, err } @@ -593,7 +598,7 @@ func (r *rule) resolveIngressPolicy( }() for _, ingressRule := range r.IngressDeny { fromEndpoints := ingressRule.GetSourceEndpointSelectorsWithRequirements(requirementsDeny) - cnt, err := mergeIngress(policyCtx, ctx, fromEndpoints, nil, ingressRule.ToPorts, ingressRule.ICMPs, makeStringLabels(r.Rule.Labels), result) + cnt, err := mergeIngress(logger, policyCtx, ctx, fromEndpoints, nil, ingressRule.ToPorts, ingressRule.ICMPs, makeStringLabels(r.Rule.Labels), result) if err != nil { return nil, err } @@ -643,7 +648,7 @@ func (r *rule) getSubjects() []identity.NumericIdentity { // ****************** EGRESS POLICY ****************** -func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels stringLabels, resMap L4PolicyMap, fqdns api.FQDNSelectorSlice) (int, error) { +func mergeEgress(logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.EndpointSelectorSlice, auth *api.Authentication, toPorts, icmp api.PortsIterator, ruleLabels stringLabels, resMap L4PolicyMap, fqdns api.FQDNSelectorSlice) (int, error) { found := 0 // short-circuit if no endpoint is selected @@ -669,7 +674,7 @@ func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.En // L3-only rule (with requirements folded into toEndpoints). if toPorts.Len() == 0 && icmp.Len() == 0 && len(toEndpoints) > 0 { - cnt, err = mergeEgressPortProto(policyCtx, ctx, toEndpoints, auth, &api.PortRule{}, api.PortProtocol{Port: "0", Protocol: api.ProtoAny}, api.ProtoAny, ruleLabels, resMap, fqdns) + cnt, err = mergeEgressPortProto(logger, policyCtx, ctx, toEndpoints, auth, &api.PortRule{}, api.PortProtocol{Port: "0", Protocol: api.ProtoAny}, api.ProtoAny, ruleLabels, resMap, fqdns) if err != nil { return found, err } @@ -707,25 +712,25 @@ func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.En for _, p := range r.GetPortProtocols() { if p.Protocol.IsAny() { - cnt, err := mergeEgressPortProto(policyCtx, ctx, toEndpoints, auth, r, p, api.ProtoTCP, ruleLabels, resMap, fqdns) + cnt, err := mergeEgressPortProto(logger, policyCtx, ctx, toEndpoints, auth, r, p, api.ProtoTCP, ruleLabels, resMap, fqdns) if err != nil { return err } found += cnt - cnt, err = mergeEgressPortProto(policyCtx, ctx, toEndpoints, auth, r, p, api.ProtoUDP, ruleLabels, resMap, fqdns) + cnt, err = mergeEgressPortProto(logger, policyCtx, ctx, toEndpoints, auth, r, p, api.ProtoUDP, ruleLabels, resMap, fqdns) if err != nil { return err } found += cnt - cnt, err = mergeEgressPortProto(policyCtx, ctx, toEndpoints, auth, r, p, api.ProtoSCTP, ruleLabels, resMap, fqdns) + cnt, err = mergeEgressPortProto(logger, policyCtx, ctx, toEndpoints, auth, r, p, api.ProtoSCTP, ruleLabels, resMap, fqdns) if err != nil { return err } found += cnt } else { - cnt, err := mergeEgressPortProto(policyCtx, ctx, toEndpoints, auth, r, p, p.Protocol, ruleLabels, resMap, fqdns) + cnt, err := mergeEgressPortProto(logger, policyCtx, ctx, toEndpoints, auth, r, p, p.Protocol, ruleLabels, resMap, fqdns) if err != nil { return err } @@ -750,7 +755,7 @@ func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.En } for _, p := range r.GetPortProtocols() { - cnt, err := mergeEgressPortProto(policyCtx, ctx, toEndpoints, auth, r, p, p.Protocol, ruleLabels, resMap, fqdns) + cnt, err := mergeEgressPortProto(logger, policyCtx, ctx, toEndpoints, auth, r, p, p.Protocol, ruleLabels, resMap, fqdns) if err != nil { return err } @@ -767,10 +772,10 @@ func mergeEgress(policyCtx PolicyContext, ctx *SearchContext, toEndpoints api.En // port and protocol with the contents of the provided PortRule. If the rule // being merged has conflicting L7 rules with those already in the provided // L4PolicyMap for the specified port-protocol tuple, it returns an error. -func mergeEgressPortProto(policyCtx PolicyContext, ctx *SearchContext, endpoints api.EndpointSelectorSlice, auth *api.Authentication, r api.Ports, p api.PortProtocol, +func mergeEgressPortProto(logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext, endpoints api.EndpointSelectorSlice, auth *api.Authentication, r api.Ports, p api.PortProtocol, proto api.L4Proto, ruleLabels stringLabels, resMap L4PolicyMap, fqdns api.FQDNSelectorSlice) (int, error) { // Create a new L4Filter - filterToMerge, err := createL4EgressFilter(policyCtx, endpoints, auth, r, p, proto, ruleLabels, fqdns) + filterToMerge, err := createL4EgressFilter(logger, policyCtx, endpoints, auth, r, p, proto, ruleLabels, fqdns) if err != nil { return 0, err } @@ -783,6 +788,7 @@ func mergeEgressPortProto(policyCtx PolicyContext, ctx *SearchContext, endpoints } func (r *rule) resolveEgressPolicy( + logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext, state *traceState, @@ -806,7 +812,7 @@ func (r *rule) resolveEgressPolicy( } for _, egressRule := range r.Egress { toEndpoints := egressRule.GetDestinationEndpointSelectorsWithRequirements(requirements) - cnt, err := mergeEgress(policyCtx, ctx, toEndpoints, egressRule.Authentication, egressRule.ToPorts, egressRule.ICMPs, makeStringLabels(r.Rule.Labels), result, egressRule.ToFQDNs) + cnt, err := mergeEgress(logger, policyCtx, ctx, toEndpoints, egressRule.Authentication, egressRule.ToPorts, egressRule.ICMPs, makeStringLabels(r.Rule.Labels), result, egressRule.ToFQDNs) if err != nil { return nil, err } @@ -821,7 +827,7 @@ func (r *rule) resolveEgressPolicy( }() for _, egressRule := range r.EgressDeny { toEndpoints := egressRule.GetDestinationEndpointSelectorsWithRequirements(requirementsDeny) - cnt, err := mergeEgress(policyCtx, ctx, toEndpoints, nil, egressRule.ToPorts, egressRule.ICMPs, makeStringLabels(r.Rule.Labels), result, nil) + cnt, err := mergeEgress(logger, policyCtx, ctx, toEndpoints, nil, egressRule.ToPorts, egressRule.ICMPs, makeStringLabels(r.Rule.Labels), result, nil) if err != nil { return nil, err } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/rules.go b/vendor/github.com/cilium/cilium/pkg/policy/rules.go index bc240a2283..27b17d63e7 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/rules.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/rules.go @@ -4,6 +4,8 @@ package policy import ( + "log/slog" + slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" policyapi "github.com/cilium/cilium/pkg/policy/api" ) @@ -12,7 +14,7 @@ import ( // to be written with []*rule as a receiver. type ruleSlice []*rule -func (rules ruleSlice) resolveL4IngressPolicy(policyCtx PolicyContext, ctx *SearchContext) (L4PolicyMap, error) { +func (rules ruleSlice) resolveL4IngressPolicy(logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext) (L4PolicyMap, error) { result := NewL4PolicyMap() ctx.PolicyTrace("\n") @@ -47,7 +49,7 @@ func (rules ruleSlice) resolveL4IngressPolicy(policyCtx PolicyContext, ctx *Sear ctx.rulesSelect = true for _, r := range matchedRules { - _, err := r.resolveIngressPolicy(policyCtx, ctx, &state, result, requirements, requirementsDeny) + _, err := r.resolveIngressPolicy(logger, policyCtx, ctx, &state, result, requirements, requirementsDeny) if err != nil { return nil, err } @@ -62,7 +64,7 @@ func (rules ruleSlice) resolveL4IngressPolicy(policyCtx PolicyContext, ctx *Sear return result, nil } -func (rules ruleSlice) resolveL4EgressPolicy(policyCtx PolicyContext, ctx *SearchContext) (L4PolicyMap, error) { +func (rules ruleSlice) resolveL4EgressPolicy(logger *slog.Logger, policyCtx PolicyContext, ctx *SearchContext) (L4PolicyMap, error) { result := NewL4PolicyMap() ctx.PolicyTrace("\n") @@ -98,7 +100,7 @@ func (rules ruleSlice) resolveL4EgressPolicy(policyCtx PolicyContext, ctx *Searc for i, r := range matchedRules { state.ruleID = i - _, err := r.resolveEgressPolicy(policyCtx, ctx, &state, result, requirements, requirementsDeny) + _, err := r.resolveEgressPolicy(logger, policyCtx, ctx, &state, result, requirements, requirementsDeny) if err != nil { return nil, err } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go index 71e58a1f88..53fafb5d0a 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache.go @@ -4,10 +4,9 @@ package policy import ( + "log/slog" "sync" - "github.com/sirupsen/logrus" - "github.com/cilium/cilium/api/v1/models" "github.com/cilium/cilium/pkg/container/versioned" "github.com/cilium/cilium/pkg/identity" @@ -54,6 +53,8 @@ type userNotification struct { // SelectorCache caches identities, identity selectors, and the // subsets of identities each selector selects. type SelectorCache struct { + logger *slog.Logger + versioned *versioned.Coordinator mutex lock.RWMutex @@ -191,9 +192,9 @@ func (sc *SelectorCache) handleUserNotifications() { for _, n := range notifications { if n.selector == nil { - n.user.IdentitySelectionCommit(n.txn) + n.user.IdentitySelectionCommit(sc.logger, n.txn) } else { - n.user.IdentitySelectionUpdated(n.selector, n.added, n.deleted) + n.user.IdentitySelectionUpdated(sc.logger, n.selector, n.added, n.deleted) } n.wg.Done() } @@ -239,15 +240,16 @@ func (sc *SelectorCache) queueNotifiedUsersCommit(txn *versioned.Tx, wg *sync.Wa } // NewSelectorCache creates a new SelectorCache with the given identities. -func NewSelectorCache(ids identity.IdentityMap) *SelectorCache { +func NewSelectorCache(logger *slog.Logger, ids identity.IdentityMap) *SelectorCache { sc := &SelectorCache{ + logger: logger, idCache: make(map[identity.NumericIdentity]scIdentity, len(ids)), selectors: make(map[string]*identitySelector), } sc.userCond = sync.NewCond(&sc.userMutex) sc.versioned = &versioned.Coordinator{ Cleaner: sc.oldVersionCleaner, - Logger: log, + Logger: logger, } for nid, lbls := range ids { @@ -259,14 +261,17 @@ func NewSelectorCache(ids identity.IdentityMap) *SelectorCache { func (sc *SelectorCache) RegisterMetrics() { if err := metrics.Register(newSelectorCacheMetrics(sc)); err != nil { - log.WithError(err).Warning("Selector cache metrics registration failed. No metrics will be reported.") + sc.logger.Warn("Selector cache metrics registration failed. No metrics will be reported.", logfields.Error, err) } } // oldVersionCleaner is called from a goroutine without holding any locks func (sc *SelectorCache) oldVersionCleaner(keepVersion versioned.KeepVersion) { // Log before taking the lock so that if we ever have a deadlock here this log line will be seen - log.WithField(logfields.Version, keepVersion).Debug("Cleaning old selector and identity versions") + sc.logger.Debug( + "Cleaning old selector and identity versions", + logfields.Version, keepVersion, + ) // This is called when some versions are no longer needed, from wherever // VersionHandle's may be kept, so we must take the lock to safely access @@ -347,6 +352,7 @@ func (sc *SelectorCache) AddFQDNSelector(user CachedSelectionUser, lbls stringLa // must hold lock for writing func (sc *SelectorCache) addSelectorLocked(user CachedSelectionUser, lbls stringLabels, key string, source selectorSource) (types.CachedSelector, bool) { idSel := &identitySelector{ + logger: sc.logger, key: key, users: make(map[CachedSelectionUser]struct{}), cachedSelections: make(map[identity.NumericIdentity]struct{}), @@ -515,17 +521,19 @@ func (sc *SelectorCache) UpdateIdentities(added, deleted identity.IdentityMap, w // prepopulated with all matching numeric identities. for numericID := range deleted { if old, exists := sc.idCache[numericID]; exists { - log.WithFields(logrus.Fields{ - logfields.NewVersion: txn, - logfields.Identity: numericID, - logfields.Labels: old.lbls, - }).Debug("UpdateIdentities: Deleting identity") + sc.logger.Debug( + "UpdateIdentities: Deleting identity", + logfields.NewVersion, txn, + logfields.Identity, numericID, + logfields.Labels, old.lbls, + ) delete(sc.idCache, numericID) } else { - log.WithFields(logrus.Fields{ - logfields.NewVersion: txn, - logfields.Identity: numericID, - }).Warning("UpdateIdentities: Skipping Delete of a non-existing identity") + sc.logger.Warn( + "UpdateIdentities: Skipping Delete of a non-existing identity", + logfields.NewVersion, txn, + logfields.Identity, numericID, + ) delete(deleted, numericID) } } @@ -536,35 +544,41 @@ func (sc *SelectorCache) UpdateIdentities(added, deleted identity.IdentityMap, w // sorted for the kv-store, so there should // not be too many false negatives. if lbls.Equals(old.lbls) { - log.WithFields(logrus.Fields{ - logfields.NewVersion: txn, - logfields.Identity: numericID, - }).Debug("UpdateIdentities: Skipping add of an existing identical identity") + sc.logger.Debug( + "UpdateIdentities: Skipping add of an existing identical identity", + logfields.NewVersion, txn, + logfields.Identity, numericID, + ) delete(added, numericID) continue } - scopedLog := log.WithFields(logrus.Fields{ - logfields.NewVersion: txn, - logfields.Identity: numericID, - logfields.Labels: old.lbls, - logfields.Labels + "(new)": lbls}, - ) msg := "UpdateIdentities: Updating an existing identity" // Warn if any other ID has their labels change, besides local // host. The local host can have its labels change at runtime if // the kube-apiserver is running on the local host, see // ipcache.TriggerLabelInjection(). if numericID == identity.ReservedIdentityHost { - scopedLog.Debug(msg) + sc.logger.Debug(msg, + logfields.NewVersion, txn, + logfields.Identity, numericID, + logfields.Labels, old.lbls, + logfields.LabelsNew, lbls, + ) } else { - scopedLog.Warning(msg) + sc.logger.Warn(msg, + logfields.NewVersion, txn, + logfields.Identity, numericID, + logfields.Labels, old.lbls, + logfields.LabelsNew, lbls, + ) } } else { - log.WithFields(logrus.Fields{ - logfields.NewVersion: txn, - logfields.Identity: numericID, - logfields.Labels: lbls, - }).Debug("UpdateIdentities: Adding a new identity") + sc.logger.Debug( + "UpdateIdentities: Adding a new identity", + logfields.NewVersion, txn, + logfields.Identity, numericID, + logfields.Labels, lbls, + ) } sc.idCache[numericID] = newIdentity(numericID, lbls) } @@ -613,9 +627,10 @@ func (sc *SelectorCache) UpdateIdentities(added, deleted identity.IdentityMap, w go func(version *versioned.VersionHandle) { wg.Wait() - log.WithFields(logrus.Fields{ - logfields.NewVersion: txn, - }).Debug("UpdateIdentities: Waited for incremental updates to have committed, closing handle on the new version.") + sc.logger.Debug( + "UpdateIdentities: Waited for incremental updates to have committed, closing handle on the new version.", + logfields.NewVersion, txn, + ) version.Close() }(txn.GetVersionHandle()) diff --git a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go index 332396e1e6..ff0a627a9d 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/selectorcache_selector.go @@ -4,11 +4,12 @@ package policy import ( + "log/slog" + "slices" "sort" "sync" "github.com/hashicorp/go-hclog" - "github.com/sirupsen/logrus" "github.com/cilium/cilium/pkg/container/versioned" "github.com/cilium/cilium/pkg/identity" @@ -58,6 +59,7 @@ type CachedSelectionUser types.CachedSelectionUser // so it must always be given to the user as a pointer to the actual type. // (The public methods only expose the CachedSelector interface.) type identitySelector struct { + logger *slog.Logger source selectorSource key string selections versioned.Value[identity.NumericIdentitySlice] @@ -124,10 +126,8 @@ func (l *labelIdentitySelector) xxxMatches(labels labels.LabelArray) bool { func (l *labelIdentitySelector) matchesNamespace(ns string) bool { if len(l.namespaces) > 0 { if ns != "" { - for i := range l.namespaces { - if ns == l.namespaces[i] { - return true - } + if slices.Contains(l.namespaces, ns) { + return true } } // namespace required, but no match @@ -188,10 +188,11 @@ func (i *identitySelector) Equal(b *identitySelector) bool { // guaranteed to receive a notification including the update. func (i *identitySelector) GetSelections(version *versioned.VersionHandle) identity.NumericIdentitySlice { if !version.IsValid() { - log.WithFields(logrus.Fields{ - logfields.Version: version, - logfields.Stacktrace: hclog.Stacktrace(), - }).Error("GetSelections: Invalid VersionHandle finds nothing") + i.logger.Error( + "GetSelections: Invalid VersionHandle finds nothing", + logfields.Version, version, + logfields.Stacktrace, hclog.Stacktrace(), + ) return identity.NumericIdentitySlice{} } return i.selections.At(version) @@ -266,9 +267,7 @@ func (i *identitySelector) updateSelections(nextVersion *versioned.Tx) { // Sort the numeric identities so that the map iteration order // does not matter. This makes testing easier, but may help // identifying changes easier also otherwise. - sort.Slice(selections, func(i, j int) bool { - return selections[i] < selections[j] - }) + slices.Sort(selections) i.setSelections(selections, nextVersion) } @@ -280,7 +279,10 @@ func (i *identitySelector) setSelections(selections identity.NumericIdentitySlic err = i.selections.RemoveAt(nextVersion) } if err != nil { - stacktrace := hclog.Stacktrace() - log.WithError(err).WithField(logfields.Stacktrace, stacktrace).Error("setSelections failed") + i.logger.Error( + "setSelections failed", + logfields.Error, err, + logfields.Stacktrace, hclog.Stacktrace(), + ) } } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/trigger.go b/vendor/github.com/cilium/cilium/pkg/policy/trigger.go index 383e8a7cb1..190e7ef0a2 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/trigger.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/trigger.go @@ -4,6 +4,8 @@ package policy import ( + "log/slog" + "github.com/cilium/cilium/pkg/logging/logfields" ) @@ -14,24 +16,26 @@ import ( // used in policy calculation has changed. func (u *Updater) TriggerPolicyUpdates(reason string) { u.repo.BumpRevision() - log.WithField(logfields.Reason, reason).Info("Triggering full policy recalculation and regeneration of all endpoints") + u.logger.Info("Triggering full policy recalculation and regeneration of all endpoints", logfields.Reason, reason) u.regen.TriggerRegenerateAllEndpoints() } // NewUpdater returns a new Updater instance to handle triggering policy // updates ready for use. -func NewUpdater(r PolicyRepository, regen regenerator) *Updater { +func NewUpdater(logger *slog.Logger, r PolicyRepository, regen regenerator) *Updater { return &Updater{ - regen: regen, - repo: r, + logger: logger, + regen: regen, + repo: r, } } // Updater is responsible for triggering policy updates, in order to perform // policy recalculation. type Updater struct { - repo PolicyRepository - regen regenerator + logger *slog.Logger + repo PolicyRepository + regen regenerator } type regenerator interface { diff --git a/vendor/github.com/cilium/cilium/pkg/policy/types/entry.go b/vendor/github.com/cilium/cilium/pkg/policy/types/entry.go index 9c360759b0..a72821112d 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/types/entry.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/types/entry.go @@ -5,11 +5,12 @@ package types import "strconv" +type ListenerPriority uint8 type ProxyPortPriority uint8 const ( - MaxProxyPortPriority = 255 - MaxListenerPriority = 100 + MaxProxyPortPriority = 127 + MaxListenerPriority = 126 ) // MapStateEntry is the configuration associated with a Key in a @@ -53,9 +54,9 @@ func (e MapStateEntry) String() string { authText } -// NewMapStateEntry creeates a new MapStateEntry +// NewMapStateEntry creates a new MapStateEntry // Listener 'priority' is encoded in ProxyPortPriority, inverted -func NewMapStateEntry(deny bool, proxyPort uint16, priority uint8, authReq AuthRequirement) MapStateEntry { +func NewMapStateEntry(deny bool, proxyPort uint16, priority ListenerPriority, authReq AuthRequirement) MapStateEntry { // Normalize inputs if deny { proxyPort = 0 @@ -66,7 +67,7 @@ func NewMapStateEntry(deny bool, proxyPort uint16, priority uint8, authReq AuthR isDeny: deny, ProxyPort: proxyPort, AuthRequirement: authReq, - }.WithProxyPriority(priority) + }.WithListenerPriority(priority) } func (e MapStateEntry) IsDeny() bool { @@ -94,19 +95,28 @@ func (e MapStateEntry) WithDeny(isDeny bool) MapStateEntry { return e } -// WithProxyPriority returns a MapStateEntry with the given listener priority: +// WithListenerPriority returns a MapStateEntry with the given listener priority: // 0 - default (low) priority for all proxy redirects // 1 - highest listener priority // .. // 100 - lowest (non-default) listener priority -func (e MapStateEntry) WithProxyPriority(priority uint8) MapStateEntry { +// 101 - priority for HTTP parser type +// 106 - priority for the Kafka parser type +// 111 - priority for the proxylib parsers +// 116 - priority for TLS interception parsers (can be promoted to HTTP/Kafka/proxylib) +// 121 - priority for DNS parser type +// 126 - default priority for CRD parser type +// 127 - reserved (listener priority passed as 0) +func (e MapStateEntry) WithListenerPriority(priority ListenerPriority) MapStateEntry { if e.ProxyPort != 0 { if priority > 0 { priority = min(priority, MaxListenerPriority) // invert the priority so that higher number has the - // precedence, priority 1 becomes 254, 100 -> 155 - e.ProxyPortPriority = MaxProxyPortPriority - ProxyPortPriority(priority) + // precedence, priority 1 becomes '127', 100 -> '28', 126 -> '2' + // '1' is reserved for a listener priority passed as 0 + // '0' is reserved for entries without proxy redirect + e.ProxyPortPriority = MaxProxyPortPriority + 1 - ProxyPortPriority(priority) } else { e.ProxyPortPriority = 1 // proxy port without explicit priority } @@ -116,8 +126,10 @@ func (e MapStateEntry) WithProxyPriority(priority uint8) MapStateEntry { // WithProxyPort return the MapStateEntry with proxy port set at the default precedence func (e MapStateEntry) WithProxyPort(proxyPort uint16) MapStateEntry { - e.ProxyPort = proxyPort - e.ProxyPortPriority = 1 // proxy port without explicit priority + if proxyPort > 0 { + e.ProxyPort = proxyPort + e.ProxyPortPriority = 1 // proxy port without explicit priority + } return e } diff --git a/vendor/github.com/cilium/cilium/pkg/policy/types/selector.go b/vendor/github.com/cilium/cilium/pkg/policy/types/selector.go index 4cbbd4d4f3..18d2b7fcfa 100644 --- a/vendor/github.com/cilium/cilium/pkg/policy/types/selector.go +++ b/vendor/github.com/cilium/cilium/pkg/policy/types/selector.go @@ -6,6 +6,7 @@ package types import ( "bytes" "encoding/json" + "log/slog" "strings" "github.com/cilium/cilium/pkg/container/versioned" @@ -90,11 +91,11 @@ func (s CachedSelectorSlice) SelectsAllEndpoints() bool { type CachedSelectionUser interface { // The caller is responsible for making sure the same identity is not // present in both 'added' and 'deleted'. - IdentitySelectionUpdated(selector CachedSelector, added, deleted []identity.NumericIdentity) + IdentitySelectionUpdated(logger *slog.Logger, selector CachedSelector, added, deleted []identity.NumericIdentity) // IdentitySelectionCommit tells the user that all IdentitySelectionUpdated calls relating // to a specific added or removed identity have been made. - IdentitySelectionCommit(*versioned.Tx) + IdentitySelectionCommit(logger *slog.Logger, txn *versioned.Tx) // IsPeerSelector returns true if the selector is used by the policy // engine for selecting traffic for remote peers. False if used for diff --git a/vendor/github.com/cilium/cilium/pkg/promise/promise.go b/vendor/github.com/cilium/cilium/pkg/promise/promise.go index d6a7a5f4e0..d20c1bfd8f 100644 --- a/vendor/github.com/cilium/cilium/pkg/promise/promise.go +++ b/vendor/github.com/cilium/cilium/pkg/promise/promise.go @@ -132,14 +132,3 @@ func Map[A, B any](p Promise[A], transform func(A) B) Promise[B] { return transform(v), nil }) } - -// MapError transforms the error of a rejected promise with the provided function. -func MapError[A any](p Promise[A], transform func(error) error) Promise[A] { - return wrappedPromise[A](func(ctx context.Context) (out A, err error) { - v, err := p.Await(ctx) - if err != nil { - err = transform(err) - } - return v, err - }) -} diff --git a/vendor/github.com/cilium/cilium/pkg/safetime/safetime.go b/vendor/github.com/cilium/cilium/pkg/safetime/safetime.go index cc00c25ac5..68cb169078 100644 --- a/vendor/github.com/cilium/cilium/pkg/safetime/safetime.go +++ b/vendor/github.com/cilium/cilium/pkg/safetime/safetime.go @@ -4,10 +4,9 @@ package safetime import ( + "log/slog" "runtime" - "github.com/sirupsen/logrus" - "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/time" ) @@ -16,24 +15,24 @@ import ( // returns false to indicate the fact. // // Used to workaround a malfunctioning monotonic clock. -func TimeSinceSafe(t time.Time, logger *logrus.Entry) (time.Duration, bool) { +func TimeSinceSafe(t time.Time, logger *slog.Logger) (time.Duration, bool) { n := time.Now() d := n.Sub(t) if d < 0 { - logger = logger.WithFields(logrus.Fields{ - logfields.StartTime: t, - logfields.EndTime: n, - logfields.Duration: d, - }) + scopedLog := logger.With( + logfields.StartTime, t, + logfields.EndTime, n, + logfields.Duration, d, + ) _, file, line, ok := runtime.Caller(1) if ok { - logger = logger.WithFields(logrus.Fields{ - logfields.Path: file, - logfields.Line: line, - }) + scopedLog = scopedLog.With( + logfields.Path, file, + logfields.Line, line, + ) } - logger.Warn("BUG: negative duration") + scopedLog.Warn("BUG: negative duration") return time.Duration(0), false } diff --git a/vendor/github.com/cilium/cilium/pkg/spanstat/spanstat.go b/vendor/github.com/cilium/cilium/pkg/spanstat/spanstat.go index 2557233533..5e9fd8405f 100644 --- a/vendor/github.com/cilium/cilium/pkg/spanstat/spanstat.go +++ b/vendor/github.com/cilium/cilium/pkg/spanstat/spanstat.go @@ -6,16 +6,10 @@ package spanstat import ( "github.com/cilium/cilium/pkg/lock" "github.com/cilium/cilium/pkg/logging" - "github.com/cilium/cilium/pkg/logging/logfields" "github.com/cilium/cilium/pkg/safetime" "github.com/cilium/cilium/pkg/time" ) -var ( - subSystem = "spanstat" - log = logging.DefaultLogger.WithField(logfields.LogSubsys, subSystem) -) - // SpanStat measures the total duration of all time spent in between Start() // and Stop() calls. type SpanStat struct { @@ -58,7 +52,7 @@ func (s *SpanStat) End(success bool) *SpanStat { // must be called with Lock() held func (s *SpanStat) end(success bool) *SpanStat { if !s.spanStart.IsZero() { - d, _ := safetime.TimeSinceSafe(s.spanStart, log) + d, _ := safetime.TimeSinceSafe(s.spanStart, logging.DefaultSlogLogger) if success { s.successDuration += d } else { diff --git a/vendor/github.com/cilium/cilium/stable.txt b/vendor/github.com/cilium/cilium/stable.txt deleted file mode 100644 index 7893098b6f..0000000000 --- a/vendor/github.com/cilium/cilium/stable.txt +++ /dev/null @@ -1 +0,0 @@ -v1.17.1 diff --git a/vendor/github.com/cilium/ebpf/.golangci.yaml b/vendor/github.com/cilium/ebpf/.golangci.yaml index 366d4893f2..8298e59ed8 100644 --- a/vendor/github.com/cilium/ebpf/.golangci.yaml +++ b/vendor/github.com/cilium/ebpf/.golangci.yaml @@ -11,9 +11,21 @@ linters: - typecheck - unused - gofmt + - depguard linters-settings: goimports: # A comma-separated list of prefixes, which, if set, checks import paths # with the given prefixes are grouped after 3rd-party packages. # Default: "" local-prefixes: github.com/cilium/ebpf + depguard: + rules: + no-x-sys-unix: + files: + # Filenames are matched against absolute paths, include **/ at the start. + - '!**/internal/unix/*.go' + - '!**/examples/**/*.go' + - '!**/docs/**/*.go' + deny: + - pkg: golang.org/x/sys/unix + desc: use internal/unix instead diff --git a/vendor/github.com/cilium/ebpf/asm/func.go b/vendor/github.com/cilium/ebpf/asm/func.go index 84a40b2277..7a59acf383 100644 --- a/vendor/github.com/cilium/ebpf/asm/func.go +++ b/vendor/github.com/cilium/ebpf/asm/func.go @@ -5,10 +5,6 @@ package asm // BuiltinFunc is a built-in eBPF function. type BuiltinFunc int32 -func (_ BuiltinFunc) Max() BuiltinFunc { - return maxBuiltinFunc - 1 -} - // eBPF built-in functions // // You can regenerate this list using the following gawk script: @@ -237,8 +233,6 @@ const ( FnUserRingbufDrain FnCgrpStorageGet FnCgrpStorageDelete - - maxBuiltinFunc ) // Call emits a function call. diff --git a/vendor/github.com/cilium/ebpf/asm/func_string.go b/vendor/github.com/cilium/ebpf/asm/func_string.go index 47150bc4f2..6c4ba37892 100644 --- a/vendor/github.com/cilium/ebpf/asm/func_string.go +++ b/vendor/github.com/cilium/ebpf/asm/func_string.go @@ -220,12 +220,11 @@ func _() { _ = x[FnUserRingbufDrain-209] _ = x[FnCgrpStorageGet-210] _ = x[FnCgrpStorageDelete-211] - _ = x[maxBuiltinFunc-212] } -const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFileFnCheckMtuFnForEachMapElemFnSnprintfFnSysBpfFnBtfFindByNameKindFnSysCloseFnTimerInitFnTimerSetCallbackFnTimerStartFnTimerCancelFnGetFuncIpFnGetAttachCookieFnTaskPtRegsFnGetBranchSnapshotFnTraceVprintkFnSkcToUnixSockFnKallsymsLookupNameFnFindVmaFnLoopFnStrncmpFnGetFuncArgFnGetFuncRetFnGetFuncArgCntFnGetRetvalFnSetRetvalFnXdpGetBuffLenFnXdpLoadBytesFnXdpStoreBytesFnCopyFromUserTaskFnSkbSetTstampFnImaFileHashFnKptrXchgFnMapLookupPercpuElemFnSkcToMptcpSockFnDynptrFromMemFnRingbufReserveDynptrFnRingbufSubmitDynptrFnRingbufDiscardDynptrFnDynptrReadFnDynptrWriteFnDynptrDataFnTcpRawGenSyncookieIpv4FnTcpRawGenSyncookieIpv6FnTcpRawCheckSyncookieIpv4FnTcpRawCheckSyncookieIpv6FnKtimeGetTaiNsFnUserRingbufDrainFnCgrpStorageGetFnCgrpStorageDeletemaxBuiltinFunc" +const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFileFnCheckMtuFnForEachMapElemFnSnprintfFnSysBpfFnBtfFindByNameKindFnSysCloseFnTimerInitFnTimerSetCallbackFnTimerStartFnTimerCancelFnGetFuncIpFnGetAttachCookieFnTaskPtRegsFnGetBranchSnapshotFnTraceVprintkFnSkcToUnixSockFnKallsymsLookupNameFnFindVmaFnLoopFnStrncmpFnGetFuncArgFnGetFuncRetFnGetFuncArgCntFnGetRetvalFnSetRetvalFnXdpGetBuffLenFnXdpLoadBytesFnXdpStoreBytesFnCopyFromUserTaskFnSkbSetTstampFnImaFileHashFnKptrXchgFnMapLookupPercpuElemFnSkcToMptcpSockFnDynptrFromMemFnRingbufReserveDynptrFnRingbufSubmitDynptrFnRingbufDiscardDynptrFnDynptrReadFnDynptrWriteFnDynptrDataFnTcpRawGenSyncookieIpv4FnTcpRawGenSyncookieIpv6FnTcpRawCheckSyncookieIpv4FnTcpRawCheckSyncookieIpv6FnKtimeGetTaiNsFnUserRingbufDrainFnCgrpStorageGetFnCgrpStorageDelete" -var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424, 2434, 2450, 2460, 2468, 2487, 2497, 2508, 2526, 2538, 2551, 2562, 2579, 2591, 2610, 2624, 2639, 2659, 2668, 2674, 2683, 2695, 2707, 2722, 2733, 2744, 2759, 2773, 2788, 2806, 2820, 2833, 2843, 2864, 2880, 2895, 2917, 2938, 2960, 2972, 2985, 2997, 3021, 3045, 3071, 3097, 3112, 3130, 3146, 3165, 3179} +var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424, 2434, 2450, 2460, 2468, 2487, 2497, 2508, 2526, 2538, 2551, 2562, 2579, 2591, 2610, 2624, 2639, 2659, 2668, 2674, 2683, 2695, 2707, 2722, 2733, 2744, 2759, 2773, 2788, 2806, 2820, 2833, 2843, 2864, 2880, 2895, 2917, 2938, 2960, 2972, 2985, 2997, 3021, 3045, 3071, 3097, 3112, 3130, 3146, 3165} func (i BuiltinFunc) String() string { if i < 0 || i >= BuiltinFunc(len(_BuiltinFunc_index)-1) { diff --git a/vendor/github.com/cilium/ebpf/attachtype_string.go b/vendor/github.com/cilium/ebpf/attachtype_string.go index bece896bb6..84445a3256 100644 --- a/vendor/github.com/cilium/ebpf/attachtype_string.go +++ b/vendor/github.com/cilium/ebpf/attachtype_string.go @@ -52,6 +52,7 @@ func _() { _ = x[AttachSkReuseportSelectOrMigrate-40] _ = x[AttachPerfEvent-41] _ = x[AttachTraceKprobeMulti-42] + _ = x[AttachTraceKprobeSession-56] _ = x[AttachLSMCgroup-43] _ = x[AttachStructOps-44] _ = x[AttachNetfilter-45] @@ -67,9 +68,9 @@ func _() { _ = x[AttachNetkitPeer-55] } -const _AttachType_name = "NoneCGroupInetEgressCGroupInetSockCreateCGroupSockOpsSkSKBStreamParserSkSKBStreamVerdictCGroupDeviceSkMsgVerdictCGroupInet4BindCGroupInet6BindCGroupInet4ConnectCGroupInet6ConnectCGroupInet4PostBindCGroupInet6PostBindCGroupUDP4SendmsgCGroupUDP6SendmsgLircMode2FlowDissectorCGroupSysctlCGroupUDP4RecvmsgCGroupUDP6RecvmsgCGroupGetsockoptCGroupSetsockoptTraceRawTpTraceFEntryTraceFExitModifyReturnLSMMacTraceIterCgroupInet4GetPeernameCgroupInet6GetPeernameCgroupInet4GetSocknameCgroupInet6GetSocknameXDPDevMapCgroupInetSockReleaseXDPCPUMapSkLookupXDPSkSKBVerdictSkReuseportSelectSkReuseportSelectOrMigratePerfEventTraceKprobeMultiLSMCgroupStructOpsNetfilterTCXIngressTCXEgressTraceUprobeMultiCgroupUnixConnectCgroupUnixSendmsgCgroupUnixRecvmsgCgroupUnixGetpeernameCgroupUnixGetsocknameNetkitPrimaryNetkitPeer" +const _AttachType_name = "NoneCGroupInetEgressCGroupInetSockCreateCGroupSockOpsSkSKBStreamParserSkSKBStreamVerdictCGroupDeviceSkMsgVerdictCGroupInet4BindCGroupInet6BindCGroupInet4ConnectCGroupInet6ConnectCGroupInet4PostBindCGroupInet6PostBindCGroupUDP4SendmsgCGroupUDP6SendmsgLircMode2FlowDissectorCGroupSysctlCGroupUDP4RecvmsgCGroupUDP6RecvmsgCGroupGetsockoptCGroupSetsockoptTraceRawTpTraceFEntryTraceFExitModifyReturnLSMMacTraceIterCgroupInet4GetPeernameCgroupInet6GetPeernameCgroupInet4GetSocknameCgroupInet6GetSocknameXDPDevMapCgroupInetSockReleaseXDPCPUMapSkLookupXDPSkSKBVerdictSkReuseportSelectSkReuseportSelectOrMigratePerfEventTraceKprobeMultiLSMCgroupStructOpsNetfilterTCXIngressTCXEgressTraceUprobeMultiCgroupUnixConnectCgroupUnixSendmsgCgroupUnixRecvmsgCgroupUnixGetpeernameCgroupUnixGetsocknameNetkitPrimaryNetkitPeerTraceKprobeSession" -var _AttachType_index = [...]uint16{0, 4, 20, 40, 53, 70, 88, 100, 112, 127, 142, 160, 178, 197, 216, 233, 250, 259, 272, 284, 301, 318, 334, 350, 360, 371, 381, 393, 399, 408, 430, 452, 474, 496, 505, 526, 535, 543, 546, 558, 575, 601, 610, 626, 635, 644, 653, 663, 672, 688, 705, 722, 739, 760, 781, 794, 804} +var _AttachType_index = [...]uint16{0, 4, 20, 40, 53, 70, 88, 100, 112, 127, 142, 160, 178, 197, 216, 233, 250, 259, 272, 284, 301, 318, 334, 350, 360, 371, 381, 393, 399, 408, 430, 452, 474, 496, 505, 526, 535, 543, 546, 558, 575, 601, 610, 626, 635, 644, 653, 663, 672, 688, 705, 722, 739, 760, 781, 794, 804, 822} func (i AttachType) String() string { if i >= AttachType(len(_AttachType_index)-1) { diff --git a/vendor/github.com/cilium/ebpf/btf/btf.go b/vendor/github.com/cilium/ebpf/btf/btf.go index 880c5ade0c..e8f80c1399 100644 --- a/vendor/github.com/cilium/ebpf/btf/btf.go +++ b/vendor/github.com/cilium/ebpf/btf/btf.go @@ -99,6 +99,10 @@ func (mt *mutableTypes) copy() *mutableTypes { return nil } + // Prevent concurrent modification of mt.copiedTypeIDs. + mt.mu.RLock() + defer mt.mu.RUnlock() + mtCopy := &mutableTypes{ mt.imm, sync.RWMutex{}, @@ -106,10 +110,6 @@ func (mt *mutableTypes) copy() *mutableTypes { make(map[Type]TypeID, len(mt.copiedTypeIDs)), } - // Prevent concurrent modification of mt.copiedTypeIDs. - mt.mu.RLock() - defer mt.mu.RUnlock() - copiesOfCopies := make(map[Type]Type, len(mt.copies)) for orig, copy := range mt.copies { // NB: We make a copy of copy, not orig, so that changes to mutable types diff --git a/vendor/github.com/cilium/ebpf/btf/ext_info.go b/vendor/github.com/cilium/ebpf/btf/ext_info.go index 2c684fe2a7..71dbba8061 100644 --- a/vendor/github.com/cilium/ebpf/btf/ext_info.go +++ b/vendor/github.com/cilium/ebpf/btf/ext_info.go @@ -666,20 +666,19 @@ func parseLineInfos(r io.Reader, bo binary.ByteOrder, strings *stringTable) (map // These records appear after a btf_ext_info_sec header in the line_info // sub-section of .BTF.ext. func parseLineInfoRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, recordNum uint32, offsetInBytes bool) ([]bpfLineInfo, error) { - var li bpfLineInfo - - if exp, got := uint32(binary.Size(li)), recordSize; exp != got { + if exp, got := uint32(binary.Size(bpfLineInfo{})), recordSize; exp != got { // BTF blob's record size is longer than we know how to parse. return nil, fmt.Errorf("expected LineInfo record size %d, but BTF blob contains %d", exp, got) } - out := make([]bpfLineInfo, 0, recordNum) - for i := uint32(0); i < recordNum; i++ { - if err := binary.Read(r, bo, &li); err != nil { - return nil, fmt.Errorf("can't read line info: %v", err) - } + out := make([]bpfLineInfo, recordNum) + if err := binary.Read(r, bo, out); err != nil { + return nil, fmt.Errorf("can't read line info: %v", err) + } - if offsetInBytes { + if offsetInBytes { + for i := range out { + li := &out[i] if li.InsnOff%asm.InstructionSize != 0 { return nil, fmt.Errorf("offset %v is not aligned with instruction size", li.InsnOff) } @@ -688,8 +687,6 @@ func parseLineInfoRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, r // Convert as early as possible. li.InsnOff /= asm.InstructionSize } - - out = append(out, li) } return out, nil diff --git a/vendor/github.com/cilium/ebpf/collection.go b/vendor/github.com/cilium/ebpf/collection.go index 1bda110a40..a7b6cb31bf 100644 --- a/vendor/github.com/cilium/ebpf/collection.go +++ b/vendor/github.com/cilium/ebpf/collection.go @@ -411,15 +411,10 @@ func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collec } // Check for existing MapSpecs in the CollectionSpec for all provided replacement maps. - for name, m := range opts.MapReplacements { - spec, ok := coll.Maps[name] - if !ok { + for name := range opts.MapReplacements { + if _, ok := coll.Maps[name]; !ok { return nil, fmt.Errorf("replacement map %s not found in CollectionSpec", name) } - - if err := spec.Compatible(m); err != nil { - return nil, fmt.Errorf("using replacement map %s: %w", spec.Name, err) - } } if err := populateKallsyms(coll.Programs); err != nil { @@ -494,7 +489,22 @@ func (cl *collectionLoader) loadMap(mapName string) (*Map, error) { return nil, fmt.Errorf("missing map %s", mapName) } + mapSpec = mapSpec.Copy() + + // Defer setting the mmapable flag on maps until load time. This avoids the + // MapSpec having different flags on some kernel versions. Also avoid running + // syscalls during ELF loading, so platforms like wasm can also parse an ELF. + if isDataSection(mapSpec.Name) && haveMmapableMaps() == nil { + mapSpec.Flags |= sys.BPF_F_MMAPABLE + } + if replaceMap, ok := cl.opts.MapReplacements[mapName]; ok { + // Check compatibility with the replacement map after setting + // feature-dependent map flags. + if err := mapSpec.Compatible(replaceMap); err != nil { + return nil, fmt.Errorf("using replacement map %s: %w", mapSpec.Name, err) + } + // Clone the map to avoid closing user's map later on. m, err := replaceMap.Clone() if err != nil { @@ -505,13 +515,6 @@ func (cl *collectionLoader) loadMap(mapName string) (*Map, error) { return m, nil } - // Defer setting the mmapable flag on maps until load time. This avoids the - // MapSpec having different flags on some kernel versions. Also avoid running - // syscalls during ELF loading, so platforms like wasm can also parse an ELF. - if isDataSection(mapSpec.Name) && haveMmapableMaps() == nil { - mapSpec.Flags |= sys.BPF_F_MMAPABLE - } - m, err := newMapWithOptions(mapSpec, cl.opts.Maps) if err != nil { return nil, fmt.Errorf("map %s: %w", mapName, err) diff --git a/vendor/github.com/cilium/ebpf/elf_sections.go b/vendor/github.com/cilium/ebpf/elf_sections.go index 4b58251d9a..43dcfb103e 100644 --- a/vendor/github.com/cilium/ebpf/elf_sections.go +++ b/vendor/github.com/cilium/ebpf/elf_sections.go @@ -18,6 +18,7 @@ var elfSectionDefs = []libbpfElfSectionDef{ {"uretprobe.s+", sys.BPF_PROG_TYPE_KPROBE, 0, _SEC_SLEEPABLE}, {"kprobe.multi+", sys.BPF_PROG_TYPE_KPROBE, sys.BPF_TRACE_KPROBE_MULTI, _SEC_NONE}, {"kretprobe.multi+", sys.BPF_PROG_TYPE_KPROBE, sys.BPF_TRACE_KPROBE_MULTI, _SEC_NONE}, + {"kprobe.session+", sys.BPF_PROG_TYPE_KPROBE, sys.BPF_TRACE_KPROBE_SESSION, _SEC_NONE}, {"uprobe.multi+", sys.BPF_PROG_TYPE_KPROBE, sys.BPF_TRACE_UPROBE_MULTI, _SEC_NONE}, {"uretprobe.multi+", sys.BPF_PROG_TYPE_KPROBE, sys.BPF_TRACE_UPROBE_MULTI, _SEC_NONE}, {"uprobe.multi.s+", sys.BPF_PROG_TYPE_KPROBE, sys.BPF_TRACE_UPROBE_MULTI, _SEC_SLEEPABLE}, @@ -69,6 +70,7 @@ var elfSectionDefs = []libbpfElfSectionDef{ {"sockops", sys.BPF_PROG_TYPE_SOCK_OPS, sys.BPF_CGROUP_SOCK_OPS, _SEC_ATTACHABLE_OPT}, {"sk_skb/stream_parser", sys.BPF_PROG_TYPE_SK_SKB, sys.BPF_SK_SKB_STREAM_PARSER, _SEC_ATTACHABLE_OPT}, {"sk_skb/stream_verdict", sys.BPF_PROG_TYPE_SK_SKB, sys.BPF_SK_SKB_STREAM_VERDICT, _SEC_ATTACHABLE_OPT}, + {"sk_skb/verdict", sys.BPF_PROG_TYPE_SK_SKB, sys.BPF_SK_SKB_VERDICT, _SEC_ATTACHABLE_OPT}, {"sk_skb", sys.BPF_PROG_TYPE_SK_SKB, 0, _SEC_NONE}, {"sk_msg", sys.BPF_PROG_TYPE_SK_MSG, sys.BPF_SK_MSG_VERDICT, _SEC_ATTACHABLE_OPT}, {"lirc_mode2", sys.BPF_PROG_TYPE_LIRC_MODE2, sys.BPF_LIRC_MODE2, _SEC_ATTACHABLE_OPT}, diff --git a/vendor/github.com/cilium/ebpf/features/map.go b/vendor/github.com/cilium/ebpf/features/map.go index 4b16e6af42..2c68ab05db 100644 --- a/vendor/github.com/cilium/ebpf/features/map.go +++ b/vendor/github.com/cilium/ebpf/features/map.go @@ -1,3 +1,5 @@ +//go:build linux + package features import ( diff --git a/vendor/github.com/cilium/ebpf/features/misc.go b/vendor/github.com/cilium/ebpf/features/misc.go index c039020a95..f07ef92adc 100644 --- a/vendor/github.com/cilium/ebpf/features/misc.go +++ b/vendor/github.com/cilium/ebpf/features/misc.go @@ -1,3 +1,5 @@ +//go:build linux + package features import ( diff --git a/vendor/github.com/cilium/ebpf/features/prog.go b/vendor/github.com/cilium/ebpf/features/prog.go index 003bf00646..e71525e5f8 100644 --- a/vendor/github.com/cilium/ebpf/features/prog.go +++ b/vendor/github.com/cilium/ebpf/features/prog.go @@ -1,9 +1,12 @@ +//go:build linux + package features import ( "errors" "fmt" - "os" + "slices" + "strings" "github.com/cilium/ebpf" "github.com/cilium/ebpf/asm" @@ -229,10 +232,6 @@ var helperCache = internal.NewFeatureCache(func(key helperKey) *internal.Feature // // Probe results are cached and persist throughout any process capability changes. func HaveProgramHelper(pt ebpf.ProgramType, helper asm.BuiltinFunc) error { - if helper > helper.Max() { - return os.ErrInvalid - } - return helperCache.Result(helperKey{pt, helper}) } @@ -267,30 +266,59 @@ func haveProgramHelper(pt ebpf.ProgramType, helper asm.BuiltinFunc) error { } prog, err := ebpf.NewProgramWithOptions(spec, ebpf.ProgramOptions{ - LogDisabled: true, + LogLevel: 1, }) if err == nil { prog.Close() } + var verr *ebpf.VerifierError + if !errors.As(err, &verr) { + return err + } + + helperTag := fmt.Sprintf("#%d", helper) + switch { // EACCES occurs when attempting to create a program probe with a helper // while the register args when calling this helper aren't set up properly. // We interpret this as the helper being available, because the verifier // returns EINVAL if the helper is not supported by the running kernel. case errors.Is(err, unix.EACCES): - // TODO: possibly we need to check verifier output here to be sure err = nil // EINVAL occurs when attempting to create a program with an unknown helper. case errors.Is(err, unix.EINVAL): - // TODO: possibly we need to check verifier output here to be sure - err = ebpf.ErrNotSupported + // https://github.com/torvalds/linux/blob/09a0fa92e5b45e99cf435b2fbf5ebcf889cf8780/kernel/bpf/verifier.c#L10663 + if logContainsAll(verr.Log, "invalid func", helperTag) { + return ebpf.ErrNotSupported + } + + // https://github.com/torvalds/linux/blob/09a0fa92e5b45e99cf435b2fbf5ebcf889cf8780/kernel/bpf/verifier.c#L10668 + wrongProgramType := logContainsAll(verr.Log, "program of this type cannot use helper", helperTag) + // https://github.com/torvalds/linux/blob/59b418c7063d30e0a3e1f592d47df096db83185c/kernel/bpf/verifier.c#L10204 + // 4.9 doesn't include # in verifier output. + wrongProgramType = wrongProgramType || logContainsAll(verr.Log, "unknown func") + if wrongProgramType { + return fmt.Errorf("program of this type cannot use helper: %w", ebpf.ErrNotSupported) + } } return err } +func logContainsAll(log []string, needles ...string) bool { + first := max(len(log)-5, 0) // Check last 5 lines. + return slices.ContainsFunc(log[first:], func(line string) bool { + for _, needle := range needles { + if !strings.Contains(line, needle) { + return false + } + } + return true + }) +} + func helperProbeNotImplemented(pt ebpf.ProgramType) bool { switch pt { case ebpf.Extension, ebpf.LSM, ebpf.StructOps, ebpf.Tracing: diff --git a/vendor/github.com/cilium/ebpf/features/version.go b/vendor/github.com/cilium/ebpf/features/version.go index d54d3ea212..124dcd2bc9 100644 --- a/vendor/github.com/cilium/ebpf/features/version.go +++ b/vendor/github.com/cilium/ebpf/features/version.go @@ -1,3 +1,5 @@ +//go:build linux + package features import "github.com/cilium/ebpf/internal/linux" diff --git a/vendor/github.com/cilium/ebpf/info.go b/vendor/github.com/cilium/ebpf/info.go index 56a1f1e9a3..676e8fa6e7 100644 --- a/vendor/github.com/cilium/ebpf/info.go +++ b/vendor/github.com/cilium/ebpf/info.go @@ -185,7 +185,7 @@ type programJitedInfo struct { // subprograms. // // Available from 4.18. - ksyms []uintptr + ksyms []uint64 numKsyms uint32 // insns holds the JITed machine native instructions of the program, @@ -344,7 +344,7 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) { if info.NrJitedKsyms > 0 { pi.jitedInfo.numKsyms = info.NrJitedKsyms - pi.jitedInfo.ksyms = make([]uintptr, info.NrJitedKsyms) + pi.jitedInfo.ksyms = make([]uint64, info.NrJitedKsyms) info2.JitedKsyms = sys.NewSlicePointer(pi.jitedInfo.ksyms) info2.NrJitedKsyms = info.NrJitedKsyms makeSecondCall = true @@ -630,8 +630,25 @@ func (pi *ProgramInfo) VerifiedInstructions() (uint32, bool) { // programs without subprograms (bpf2bpf calls). // // The bool return value indicates whether this optional field is available. +// +// When a kernel address can't fit into uintptr (which is usually the case when +// running 32 bit program on a 64 bit kernel), this returns an empty slice and +// a false. func (pi *ProgramInfo) JitedKsymAddrs() ([]uintptr, bool) { - return pi.jitedInfo.ksyms, len(pi.jitedInfo.ksyms) > 0 + ksyms := make([]uintptr, 0, len(pi.jitedInfo.ksyms)) + if cap(ksyms) == 0 { + return ksyms, false + } + // Check if a kernel address fits into uintptr (it might not when + // using a 32 bit binary on a 64 bit kernel). This check should work + // with any kernel address, since they have 1s at the highest bits. + if a := pi.jitedInfo.ksyms[0]; uint64(uintptr(a)) != a { + return nil, false + } + for _, ksym := range pi.jitedInfo.ksyms { + ksyms = append(ksyms, uintptr(ksym)) + } + return ksyms, true } // JitedInsns returns the JITed machine native instructions of the program. diff --git a/vendor/github.com/cilium/ebpf/internal/feature.go b/vendor/github.com/cilium/ebpf/internal/feature.go index 6399be0851..6f64822e11 100644 --- a/vendor/github.com/cilium/ebpf/internal/feature.go +++ b/vendor/github.com/cilium/ebpf/internal/feature.go @@ -93,7 +93,7 @@ func NewFeatureTest(name string, fn FeatureTestFn, versions ...string) func() er break } - if runtime.GOOS == "linux" && !strings.ContainsRune(version, ':') { + if OnLinux && !strings.ContainsRune(version, ':') { // Allow version numbers without a GOOS prefix on Linux. ft.Version = version break diff --git a/vendor/github.com/cilium/ebpf/internal/goos.go b/vendor/github.com/cilium/ebpf/internal/goos.go new file mode 100644 index 0000000000..0569d5ce0b --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/goos.go @@ -0,0 +1,7 @@ +package internal + +import "runtime" + +const ( + OnLinux = runtime.GOOS == "linux" +) diff --git a/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go b/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go index f93d785849..2cdfb56a58 100644 --- a/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go +++ b/vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go @@ -8,6 +8,8 @@ import ( "slices" "strconv" "strings" + + "github.com/cilium/ebpf/internal" ) var errAmbiguousKsym = errors.New("multiple kernel symbols with the same name") @@ -47,6 +49,10 @@ func Module(name string) (string, error) { // Any symbols missing in the kernel are ignored. Returns an error if multiple // symbols with a given name were found. func AssignModules(symbols map[string]string) error { + if !internal.OnLinux { + return fmt.Errorf("read /proc/kallsyms: %w", internal.ErrNotSupportedOnOS) + } + if len(symbols) == 0 { return nil } @@ -71,6 +77,7 @@ func AssignModules(symbols map[string]string) error { if err != nil { return err } + defer f.Close() if err := assignModules(f, request); err != nil { return fmt.Errorf("assigning symbol modules: %w", err) @@ -161,6 +168,10 @@ func Address(symbol string) (uint64, error) { // Any symbols missing in the kernel are ignored. Returns an error if multiple // addresses were found for a symbol. func AssignAddresses(symbols map[string]uint64) error { + if !internal.OnLinux { + return fmt.Errorf("read /proc/kallsyms: %w", internal.ErrNotSupportedOnOS) + } + if len(symbols) == 0 { return nil } @@ -185,6 +196,7 @@ func AssignAddresses(symbols map[string]uint64) error { if err != nil { return err } + defer f.Close() if err := assignAddresses(f, request); err != nil { return fmt.Errorf("loading symbol addresses: %w", err) diff --git a/vendor/github.com/cilium/ebpf/internal/linux/auxv.go b/vendor/github.com/cilium/ebpf/internal/linux/auxv.go index 98bb5d83ca..10508fd8fc 100644 --- a/vendor/github.com/cilium/ebpf/internal/linux/auxv.go +++ b/vendor/github.com/cilium/ebpf/internal/linux/auxv.go @@ -1,9 +1,11 @@ package linux import ( - "errors" + "fmt" "io" - _ "unsafe" + + "github.com/cilium/ebpf/internal" + "github.com/cilium/ebpf/internal/unix" ) type auxvPairReader interface { @@ -17,11 +19,8 @@ const ( _AT_SYSINFO_EHDR = 33 // Offset to vDSO blob in process image ) -//go:linkname runtime_getAuxv runtime.getAuxv -func runtime_getAuxv() []uintptr - type auxvRuntimeReader struct { - data []uintptr + data [][2]uintptr index int } @@ -37,20 +36,23 @@ func (r *auxvRuntimeReader) ReadAuxvPair() (uint64, uint64, error) { // we manually add the (_AT_NULL, _AT_NULL) pair at the end // that is not provided by the go runtime var tag, value uintptr - if r.index+1 < len(r.data) { - tag, value = r.data[r.index], r.data[r.index+1] + if r.index < len(r.data) { + tag, value = r.data[r.index][0], r.data[r.index][1] } else { tag, value = _AT_NULL, _AT_NULL } - r.index += 2 + r.index += 1 return uint64(tag), uint64(value), nil } func newAuxvRuntimeReader() (auxvPairReader, error) { - data := runtime_getAuxv() + if !internal.OnLinux { + return nil, fmt.Errorf("read auxv from runtime: %w", internal.ErrNotSupportedOnOS) + } - if len(data)%2 != 0 { - return nil, errors.New("malformed auxv passed from runtime") + data, err := unix.Auxv() + if err != nil { + return nil, fmt.Errorf("read auxv from runtime: %w", err) } return &auxvRuntimeReader{ diff --git a/vendor/github.com/cilium/ebpf/internal/sys/syscall.go b/vendor/github.com/cilium/ebpf/internal/sys/syscall.go index e37f4cf671..4fdb74c57a 100644 --- a/vendor/github.com/cilium/ebpf/internal/sys/syscall.go +++ b/vendor/github.com/cilium/ebpf/internal/sys/syscall.go @@ -2,7 +2,6 @@ package sys import ( "runtime" - "syscall" "unsafe" "github.com/cilium/ebpf/internal/unix" @@ -11,7 +10,7 @@ import ( // ENOTSUPP is a Linux internal error code that has leaked into UAPI. // // It is not the same as ENOTSUP or EOPNOTSUPP. -const ENOTSUPP = syscall.Errno(524) +const ENOTSUPP = unix.Errno(524) // BPF wraps SYS_BPF. // @@ -179,12 +178,12 @@ const ( const BPF_TAG_SIZE = 8 const BPF_OBJ_NAME_LEN = 16 -// wrappedErrno wraps syscall.Errno to prevent direct comparisons with +// wrappedErrno wraps [unix.Errno] to prevent direct comparisons with // syscall.E* or unix.E* constants. // // You should never export an error of this type. type wrappedErrno struct { - syscall.Errno + unix.Errno } func (we wrappedErrno) Unwrap() error { @@ -200,10 +199,10 @@ func (we wrappedErrno) Error() string { type syscallError struct { error - errno syscall.Errno + errno unix.Errno } -func Error(err error, errno syscall.Errno) error { +func Error(err error, errno unix.Errno) error { return &syscallError{err, errno} } diff --git a/vendor/github.com/cilium/ebpf/internal/sys/types.go b/vendor/github.com/cilium/ebpf/internal/sys/types.go index 88001c319e..82f3492a83 100644 --- a/vendor/github.com/cilium/ebpf/internal/sys/types.go +++ b/vendor/github.com/cilium/ebpf/internal/sys/types.go @@ -26,6 +26,7 @@ const ( BPF_FIB_LKUP_RET_UNREACHABLE = 2 BPF_FIB_LKUP_RET_UNSUPP_LWT = 6 BPF_FIB_LOOKUP_DIRECT = 1 + BPF_FIB_LOOKUP_MARK = 32 BPF_FIB_LOOKUP_OUTPUT = 2 BPF_FIB_LOOKUP_SKIP_NEIGH = 4 BPF_FIB_LOOKUP_SRC = 16 @@ -68,6 +69,7 @@ const ( BPF_F_NO_COMMON_LRU = 2 BPF_F_NO_PREALLOC = 1 BPF_F_NO_TUNNEL_KEY = 16 + BPF_F_NO_USER_CONV = 262144 BPF_F_NUMA_NODE = 4 BPF_F_PATH_FD = 16384 BPF_F_PEER = 4 @@ -77,17 +79,20 @@ const ( BPF_F_RDONLY_PROG = 128 BPF_F_RECOMPUTE_CSUM = 1 BPF_F_REUSE_STACKID = 1024 + BPF_F_SEGV_ON_FAULT = 131072 BPF_F_SEQ_NUMBER = 8 BPF_F_SKIP_FIELD_MASK = 255 BPF_F_STACK_BUILD_ID = 32 BPF_F_SYSCTL_BASE_NAME = 1 BPF_F_TIMER_ABS = 1 BPF_F_TIMER_CPU_PIN = 2 + BPF_F_TOKEN_FD = 65536 BPF_F_TUNINFO_FLAGS = 16 BPF_F_TUNINFO_IPV6 = 1 BPF_F_UPROBE_MULTI_RETURN = 1 BPF_F_USER_BUILD_ID = 2048 BPF_F_USER_STACK = 256 + BPF_F_VTYPE_BTF_OBJ_FD = 32768 BPF_F_WRONLY = 16 BPF_F_WRONLY_PROG = 256 BPF_F_ZERO_CSUM_TX = 2 @@ -117,6 +122,9 @@ const ( BPF_RINGBUF_BUSY_BIT = 2147483648 BPF_RINGBUF_DISCARD_BIT = 1073741824 BPF_RINGBUF_HDR_SZ = 8 + BPF_SKB_CLOCK_MONOTONIC = 1 + BPF_SKB_CLOCK_REALTIME = 0 + BPF_SKB_CLOCK_TAI = 2 BPF_SKB_TSTAMP_DELIVERY_MONO = 1 BPF_SKB_TSTAMP_UNSPEC = 0 BPF_SK_LOOKUP_F_NO_REUSEPORT = 2 @@ -146,8 +154,6 @@ const ( BPF_SOCK_OPS_VOID = 0 BPF_SOCK_OPS_WRITE_HDR_OPT_CB = 15 BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG = 64 - BPF_STRUCT_OPS_TYPE_bpf_dummy_ops = 0 - BPF_STRUCT_OPS_TYPE_tcp_congestion_ops = 1 BPF_TASK_ITER_ALL_PROCS = 0 BPF_TASK_ITER_ALL_THREADS = 1 BPF_TASK_ITER_PROC_THREADS = 2 @@ -236,7 +242,8 @@ const ( BPF_CGROUP_UNIX_GETSOCKNAME AttachType = 53 BPF_NETKIT_PRIMARY AttachType = 54 BPF_NETKIT_PEER AttachType = 55 - __MAX_BPF_ATTACH_TYPE AttachType = 56 + BPF_TRACE_KPROBE_SESSION AttachType = 56 + __MAX_BPF_ATTACH_TYPE AttachType = 57 ) type Cmd uint32 @@ -279,6 +286,8 @@ const ( BPF_ITER_CREATE Cmd = 33 BPF_LINK_DETACH Cmd = 34 BPF_PROG_BIND_MAP Cmd = 35 + BPF_TOKEN_CREATE Cmd = 36 + __MAX_BPF_CMD Cmd = 37 ) type FunctionId uint32 @@ -523,7 +532,8 @@ const ( BPF_LINK_TYPE_TCX LinkType = 11 BPF_LINK_TYPE_UPROBE_MULTI LinkType = 12 BPF_LINK_TYPE_NETKIT LinkType = 13 - __MAX_BPF_LINK_TYPE LinkType = 14 + BPF_LINK_TYPE_SOCKMAP LinkType = 14 + __MAX_BPF_LINK_TYPE LinkType = 15 ) type MapType uint32 @@ -564,6 +574,8 @@ const ( BPF_MAP_TYPE_BLOOM_FILTER MapType = 30 BPF_MAP_TYPE_USER_RINGBUF MapType = 31 BPF_MAP_TYPE_CGRP_STORAGE MapType = 32 + BPF_MAP_TYPE_ARENA MapType = 33 + __MAX_BPF_MAP_TYPE MapType = 34 ) type ObjType uint32 @@ -623,6 +635,7 @@ const ( BPF_PROG_TYPE_SK_LOOKUP ProgType = 30 BPF_PROG_TYPE_SYSCALL ProgType = 31 BPF_PROG_TYPE_NETFILTER ProgType = 32 + __MAX_BPF_PROG_TYPE ProgType = 33 ) type RetCode uint32 @@ -719,7 +732,7 @@ type MapInfo struct { BtfId uint32 BtfKeyTypeId TypeID BtfValueTypeId TypeID - _ [4]byte + BtfVmlinuxId uint32 MapExtra uint64 } @@ -816,6 +829,8 @@ type BtfLoadAttr struct { BtfLogSize uint32 BtfLogLevel uint32 BtfLogTrueSize uint32 + BtfFlags uint32 + BtfTokenFd int32 } func BtfLoad(attr *BtfLoadAttr) (*FD, error) { @@ -1069,6 +1084,8 @@ type MapCreateAttr struct { BtfValueTypeId TypeID BtfVmlinuxValueTypeId TypeID MapExtra uint64 + ValueTypeBtfObjFd int32 + MapTokenFd int32 } func MapCreate(attr *MapCreateAttr) (*FD, error) { @@ -1362,6 +1379,8 @@ type ProgLoadAttr struct { CoreRelos Pointer CoreReloRecSize uint32 LogTrueSize uint32 + ProgTokenFd int32 + _ [4]byte } func ProgLoad(attr *ProgLoadAttr) (*FD, error) { @@ -1419,6 +1438,7 @@ type RawTracepointOpenAttr struct { Name Pointer ProgFd uint32 _ [4]byte + Cookie uint64 } func RawTracepointOpen(attr *RawTracepointOpenAttr) (*FD, error) { @@ -1460,19 +1480,20 @@ type KprobeLinkInfo struct { Offset uint32 Addr uint64 Missed uint64 - _ [8]byte + Cookie uint64 } type KprobeMultiLinkInfo struct { - Type LinkType - Id LinkID - ProgId uint32 - _ [4]byte - Addrs Pointer - Count uint32 - Flags uint32 - Missed uint64 - _ [24]byte + Type LinkType + Id LinkID + ProgId uint32 + _ [4]byte + Addrs Pointer + Count uint32 + Flags uint32 + Missed uint64 + Cookies uint64 + _ [16]byte } type NetNsLinkInfo struct { diff --git a/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go b/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go index 062bef9ec3..bdadf4d8ea 100644 --- a/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go +++ b/vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go @@ -113,6 +113,10 @@ func sanitizeTracefsPath(path ...string) (string, error) { // but may be also be available at /sys/kernel/debug/tracing if debugfs is mounted. // The available tracefs paths will depends on distribution choices. var getTracefsPath = sync.OnceValues(func() (string, error) { + if !internal.OnLinux { + return "", fmt.Errorf("tracefs: %w", internal.ErrNotSupportedOnOS) + } + for _, p := range []struct { path string fsType int64 diff --git a/vendor/github.com/cilium/ebpf/internal/unix/errno_linux.go b/vendor/github.com/cilium/ebpf/internal/unix/errno_linux.go new file mode 100644 index 0000000000..0c4886bd13 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/unix/errno_linux.go @@ -0,0 +1,29 @@ +package unix + +import ( + "syscall" + + linux "golang.org/x/sys/unix" +) + +type Errno = syscall.Errno + +const ( + E2BIG = linux.E2BIG + EACCES = linux.EACCES + EAGAIN = linux.EAGAIN + EBADF = linux.EBADF + EEXIST = linux.EEXIST + EFAULT = linux.EFAULT + EILSEQ = linux.EILSEQ + EINTR = linux.EINTR + EINVAL = linux.EINVAL + ENODEV = linux.ENODEV + ENOENT = linux.ENOENT + ENOSPC = linux.ENOSPC + EOPNOTSUPP = linux.EOPNOTSUPP + EPERM = linux.EPERM + EPOLLIN = linux.EPOLLIN + ESRCH = linux.ESRCH + ESTALE = linux.ESTALE +) diff --git a/vendor/github.com/cilium/ebpf/internal/unix/errno_other.go b/vendor/github.com/cilium/ebpf/internal/unix/errno_other.go new file mode 100644 index 0000000000..fc2b042b54 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/unix/errno_other.go @@ -0,0 +1,29 @@ +//go:build !linux && !windows + +package unix + +import "syscall" + +type Errno = syscall.Errno + +// Errnos are distinct and non-zero. +const ( + E2BIG Errno = iota + 1 + EACCES + EAGAIN + EBADF + EEXIST + EFAULT + EILSEQ + EINTR + EINVAL + ENODEV + ENOENT + ENOSPC + ENOTSUP + ENOTSUPP + EOPNOTSUPP + EPERM + ESRCH + ESTALE +) diff --git a/vendor/github.com/cilium/ebpf/internal/unix/errno_string_windows.go b/vendor/github.com/cilium/ebpf/internal/unix/errno_string_windows.go new file mode 100644 index 0000000000..6077e983f3 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/unix/errno_string_windows.go @@ -0,0 +1,59 @@ +// Code generated by "stringer -type=Errno -tags=windows -output=errno_string_windows.go"; DO NOT EDIT. + +package unix + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[EPERM-1] + _ = x[ENOENT-2] + _ = x[ESRCH-3] + _ = x[EINTR-4] + _ = x[E2BIG-7] + _ = x[EBADF-9] + _ = x[EAGAIN-11] + _ = x[EACCES-13] + _ = x[EFAULT-14] + _ = x[EEXIST-17] + _ = x[ENODEV-19] + _ = x[EINVAL-22] + _ = x[ENOSPC-28] + _ = x[EILSEQ-42] + _ = x[ENOTSUP-129] + _ = x[EOPNOTSUPP-130] + _ = x[ENOTSUPP-536870912] + _ = x[ESTALE-536870913] +} + +const _Errno_name = "EPERMENOENTESRCHEINTRE2BIGEBADFEAGAINEACCESEFAULTEEXISTENODEVEINVALENOSPCEILSEQENOTSUPEOPNOTSUPPENOTSUPPESTALE" + +var _Errno_map = map[Errno]string{ + 1: _Errno_name[0:5], + 2: _Errno_name[5:11], + 3: _Errno_name[11:16], + 4: _Errno_name[16:21], + 7: _Errno_name[21:26], + 9: _Errno_name[26:31], + 11: _Errno_name[31:37], + 13: _Errno_name[37:43], + 14: _Errno_name[43:49], + 17: _Errno_name[49:55], + 19: _Errno_name[55:61], + 22: _Errno_name[61:67], + 28: _Errno_name[67:73], + 42: _Errno_name[73:79], + 129: _Errno_name[79:86], + 130: _Errno_name[86:96], + 536870912: _Errno_name[96:104], + 536870913: _Errno_name[104:110], +} + +func (i Errno) String() string { + if str, ok := _Errno_map[i]; ok { + return str + } + return "Errno(" + strconv.FormatInt(int64(i), 10) + ")" +} diff --git a/vendor/github.com/cilium/ebpf/internal/unix/errno_windows.go b/vendor/github.com/cilium/ebpf/internal/unix/errno_windows.go new file mode 100644 index 0000000000..7500cd6d4e --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/unix/errno_windows.go @@ -0,0 +1,78 @@ +package unix + +// The code in this file is derived from syscall_unix.go in the Go source code, +// licensed under the MIT license. + +import ( + "errors" + "os" + "syscall" +) + +//go:generate go run golang.org/x/tools/cmd/stringer@latest -type=Errno -tags=windows -output=errno_string_windows.go + +// Windows specific constants for Unix errnos. +// +// The values do not always match Linux, for example EILSEQ and EOPNOTSUPP. +// +// See https://learn.microsoft.com/en-us/cpp/c-runtime-library/errno-constants?view=msvc-170 +const ( + EPERM Errno = 1 + ENOENT Errno = 2 + ESRCH Errno = 3 + EINTR Errno = 4 + E2BIG Errno = 7 + EBADF Errno = 9 + EAGAIN Errno = 11 + EACCES Errno = 13 + EFAULT Errno = 14 + EEXIST Errno = 17 + ENODEV Errno = 19 + EINVAL Errno = 22 + ENFILE Errno = 23 + EMFILE Errno = 24 + ENOSPC Errno = 28 + ENOSYS Errno = 40 + ENOTEMPTY Errno = 41 + EILSEQ Errno = 42 + ENOTSUP Errno = 129 + EOPNOTSUPP Errno = 130 + ETIMEDOUT Errno = 138 + EWOULDBLOCK Errno = 140 +) + +// These constants do not exist on Windows and therefore have a non-zero +// dummy value. +const ( + ENOTSUPP Errno = Errno(syscall.APPLICATION_ERROR) + iota + ESTALE +) + +// Errno is a Windows compatibility shim for Unix errnos. +type Errno uintptr + +func (e Errno) Error() string { + return e.String() +} + +func (e Errno) Is(target error) bool { + switch target { + case os.ErrPermission: + return e == EACCES || e == EPERM + case os.ErrExist: + return e == EEXIST || e == ENOTEMPTY + case os.ErrNotExist: + return e == ENOENT + case errors.ErrUnsupported: + return e == ENOSYS || e == ENOTSUP || e == EOPNOTSUPP + } + return false +} + +func (e Errno) Temporary() bool { + return e == EINTR || e == EMFILE || e == ENFILE || e.Timeout() +} + +func (e Errno) Timeout() bool { + return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT +} diff --git a/vendor/github.com/cilium/ebpf/internal/unix/error.go b/vendor/github.com/cilium/ebpf/internal/unix/error.go new file mode 100644 index 0000000000..48017c1009 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/unix/error.go @@ -0,0 +1,23 @@ +package unix + +import ( + "fmt" + "runtime" + "strings" + + "github.com/cilium/ebpf/internal" +) + +// errNonLinux returns an error which wraps [internal.ErrNotSupportedOnOS] and +// includes the name of the calling function. +func errNonLinux() error { + name := "unknown" + pc, _, _, ok := runtime.Caller(1) + if ok { + name = runtime.FuncForPC(pc).Name() + if pos := strings.LastIndexByte(name, '.'); pos != -1 { + name = name[pos+1:] + } + } + return fmt.Errorf("unix: %s: %w", name, internal.ErrNotSupportedOnOS) +} diff --git a/vendor/github.com/cilium/ebpf/internal/unix/strings_other.go b/vendor/github.com/cilium/ebpf/internal/unix/strings_other.go new file mode 100644 index 0000000000..49e1fe2172 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/unix/strings_other.go @@ -0,0 +1,11 @@ +//go:build !linux && !windows + +package unix + +func BytePtrFromString(s string) (*byte, error) { + return nil, errNonLinux() +} + +func ByteSliceToString(s []byte) string { + return "" +} diff --git a/vendor/github.com/cilium/ebpf/internal/unix/strings_windows.go b/vendor/github.com/cilium/ebpf/internal/unix/strings_windows.go new file mode 100644 index 0000000000..7e3d4da777 --- /dev/null +++ b/vendor/github.com/cilium/ebpf/internal/unix/strings_windows.go @@ -0,0 +1,19 @@ +package unix + +import ( + "syscall" + + "golang.org/x/sys/windows" +) + +func BytePtrFromString(s string) (*byte, error) { + p, err := windows.BytePtrFromString(s) + if err == syscall.EINVAL { + err = EINVAL + } + return p, err +} + +func ByteSliceToString(s []byte) string { + return windows.ByteSliceToString(s) +} diff --git a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go index 144e608d1c..385adf08b8 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go @@ -8,26 +8,6 @@ import ( linux "golang.org/x/sys/unix" ) -const ( - ENOENT = linux.ENOENT - EEXIST = linux.EEXIST - EAGAIN = linux.EAGAIN - ENOSPC = linux.ENOSPC - EINVAL = linux.EINVAL - EPOLLIN = linux.EPOLLIN - EINTR = linux.EINTR - EPERM = linux.EPERM - ESRCH = linux.ESRCH - ENODEV = linux.ENODEV - EBADF = linux.EBADF - E2BIG = linux.E2BIG - EFAULT = linux.EFAULT - EACCES = linux.EACCES - EILSEQ = linux.EILSEQ - EOPNOTSUPP = linux.EOPNOTSUPP - ESTALE = linux.ESTALE -) - const ( BPF_F_NO_PREALLOC = linux.BPF_F_NO_PREALLOC BPF_F_NUMA_NODE = linux.BPF_F_NUMA_NODE @@ -215,3 +195,7 @@ func SchedSetaffinity(pid int, set *CPUSet) error { func SchedGetaffinity(pid int, set *CPUSet) error { return linux.SchedGetaffinity(pid, set) } + +func Auxv() ([][2]uintptr, error) { + return linux.Auxv() +} diff --git a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go index 06cc3a0966..323f7ff34e 100644 --- a/vendor/github.com/cilium/ebpf/internal/unix/types_other.go +++ b/vendor/github.com/cilium/ebpf/internal/unix/types_other.go @@ -3,33 +3,9 @@ package unix import ( - "fmt" - "runtime" "syscall" ) -var errNonLinux = fmt.Errorf("unsupported platform %s/%s", runtime.GOOS, runtime.GOARCH) - -// Errnos are distinct and non-zero. -const ( - ENOENT syscall.Errno = iota + 1 - EEXIST - EAGAIN - ENOSPC - EINVAL - EINTR - EPERM - ESRCH - ENODEV - EBADF - E2BIG - EFAULT - EACCES - EILSEQ - EOPNOTSUPP - ESTALE -) - // Constants are distinct to avoid breaking switch statements. const ( BPF_F_NO_PREALLOC = iota @@ -137,28 +113,28 @@ type Sigset_t struct { Val [4]uint64 } -func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { - return 0, 0, syscall.ENOTSUP +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + return 0, 0, ENOTSUP } func PthreadSigmask(how int, set, oldset *Sigset_t) error { - return errNonLinux + return errNonLinux() } func FcntlInt(fd uintptr, cmd, arg int) (int, error) { - return -1, errNonLinux + return -1, errNonLinux() } func IoctlSetInt(fd int, req uint, value int) error { - return errNonLinux + return errNonLinux() } func Statfs(path string, buf *Statfs_t) error { - return errNonLinux + return errNonLinux() } func Close(fd int) (err error) { - return errNonLinux + return errNonLinux() } type EpollEvent struct { @@ -168,23 +144,23 @@ type EpollEvent struct { } func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { - return 0, errNonLinux + return 0, errNonLinux() } func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { - return errNonLinux + return errNonLinux() } func Eventfd(initval uint, flags int) (fd int, err error) { - return 0, errNonLinux + return 0, errNonLinux() } func Write(fd int, p []byte) (n int, err error) { - return 0, errNonLinux + return 0, errNonLinux() } func EpollCreate1(flag int) (fd int, err error) { - return 0, errNonLinux + return 0, errNonLinux() } type PerfEventMmapPage struct { @@ -214,15 +190,15 @@ type PerfEventMmapPage struct { } func SetNonblock(fd int, nonblocking bool) (err error) { - return errNonLinux + return errNonLinux() } func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { - return []byte{}, errNonLinux + return []byte{}, errNonLinux() } func Munmap(b []byte) (err error) { - return errNonLinux + return errNonLinux() } type PerfEventAttr struct { @@ -247,7 +223,7 @@ type PerfEventAttr struct { } func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) { - return 0, errNonLinux + return 0, errNonLinux() } type Utsname struct { @@ -256,7 +232,7 @@ type Utsname struct { } func Uname(buf *Utsname) (err error) { - return errNonLinux + return errNonLinux() } func Getpid() int { @@ -268,35 +244,27 @@ func Gettid() int { } func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) { - return errNonLinux -} - -func BytePtrFromString(s string) (*byte, error) { - return nil, errNonLinux -} - -func ByteSliceToString(s []byte) string { - return "" + return errNonLinux() } func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) error { - return errNonLinux + return errNonLinux() } func Prlimit(pid, resource int, new, old *Rlimit) error { - return errNonLinux + return errNonLinux() } func Open(path string, mode int, perm uint32) (int, error) { - return -1, errNonLinux + return -1, errNonLinux() } func Fstat(fd int, stat *Stat_t) error { - return errNonLinux + return errNonLinux() } func SetsockoptInt(fd, level, opt, value int) error { - return errNonLinux + return errNonLinux() } type CPUSet struct{} @@ -304,9 +272,13 @@ type CPUSet struct{} func (*CPUSet) Set(int) {} func SchedSetaffinity(pid int, set *CPUSet) error { - return errNonLinux + return errNonLinux() } func SchedGetaffinity(pid int, set *CPUSet) error { - return errNonLinux + return errNonLinux() +} + +func Auxv() ([][2]uintptr, error) { + return nil, errNonLinux() } diff --git a/vendor/github.com/cilium/ebpf/link/kprobe_multi.go b/vendor/github.com/cilium/ebpf/link/kprobe_multi.go index 094cb0538c..f19f9f4c73 100644 --- a/vendor/github.com/cilium/ebpf/link/kprobe_multi.go +++ b/vendor/github.com/cilium/ebpf/link/kprobe_multi.go @@ -37,6 +37,14 @@ type KprobeMultiOptions struct { // Each Cookie is assigned to the Symbol or Address specified at the // corresponding slice index. Cookies []uint64 + + // Session must be true when attaching Programs with the + // [ebpf.AttachTraceKprobeSession] attach type. + // + // This makes a Kprobe execute on both function entry and return. The entry + // program can share a cookie value with the return program and can decide + // whether the return program gets executed. + Session bool } // KprobeMulti attaches the given eBPF program to the entry point of a given set @@ -82,9 +90,14 @@ func kprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions, flags uint32) (Lin return nil, fmt.Errorf("Cookies must be exactly Symbols or Addresses in length: %w", errInvalidInput) } + attachType := sys.BPF_TRACE_KPROBE_MULTI + if opts.Session { + attachType = sys.BPF_TRACE_KPROBE_SESSION + } + attr := &sys.LinkCreateKprobeMultiAttr{ ProgFd: uint32(prog.FD()), - AttachType: sys.BPF_TRACE_KPROBE_MULTI, + AttachType: attachType, KprobeMultiFlags: flags, } @@ -103,21 +116,31 @@ func kprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions, flags uint32) (Lin } fd, err := sys.LinkCreateKprobeMulti(attr) + if err == nil { + return &kprobeMultiLink{RawLink{fd, ""}}, nil + } + if errors.Is(err, unix.ESRCH) { return nil, fmt.Errorf("couldn't find one or more symbols: %w", os.ErrNotExist) } - if errors.Is(err, unix.EINVAL) { - return nil, fmt.Errorf("%w (missing kernel symbol or prog's AttachType not AttachTraceKprobeMulti?)", err) - } - if err != nil { + if opts.Session { + if haveFeatErr := haveBPFLinkKprobeSession(); haveFeatErr != nil { + return nil, haveFeatErr + } + } else { if haveFeatErr := haveBPFLinkKprobeMulti(); haveFeatErr != nil { return nil, haveFeatErr } - return nil, err } - return &kprobeMultiLink{RawLink{fd, ""}}, nil + // Check EINVAL after running feature probes, since it's also returned when + // the kernel doesn't support the multi/session attach types. + if errors.Is(err, unix.EINVAL) { + return nil, fmt.Errorf("%w (missing kernel symbol or prog's AttachType not %s?)", err, ebpf.AttachType(attachType)) + } + + return nil, err } type kprobeMultiLink struct { @@ -189,3 +212,44 @@ var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", fu return nil }, "5.18") + +var haveBPFLinkKprobeSession = internal.NewFeatureTest("bpf_link_kprobe_session", func() error { + prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ + Name: "probe_kps_link", + Type: ebpf.Kprobe, + Instructions: asm.Instructions{ + asm.Mov.Imm(asm.R0, 0), + asm.Return(), + }, + AttachType: ebpf.AttachTraceKprobeSession, + License: "MIT", + }) + if errors.Is(err, unix.E2BIG) { + // Kernel doesn't support AttachType field. + return internal.ErrNotSupported + } + if err != nil { + return err + } + defer prog.Close() + + fd, err := sys.LinkCreateKprobeMulti(&sys.LinkCreateKprobeMultiAttr{ + ProgFd: uint32(prog.FD()), + AttachType: sys.BPF_TRACE_KPROBE_SESSION, + Count: 1, + Syms: sys.NewStringSlicePointer([]string{"vprintk"}), + }) + switch { + case errors.Is(err, unix.EINVAL): + return internal.ErrNotSupported + // If CONFIG_FPROBE isn't set. + case errors.Is(err, unix.EOPNOTSUPP): + return internal.ErrNotSupported + case err != nil: + return err + } + + fd.Close() + + return nil +}, "6.10") diff --git a/vendor/github.com/cilium/ebpf/linker.go b/vendor/github.com/cilium/ebpf/linker.go index 6f97af2784..024b72bbc8 100644 --- a/vendor/github.com/cilium/ebpf/linker.go +++ b/vendor/github.com/cilium/ebpf/linker.go @@ -207,13 +207,19 @@ func flattenPrograms(progs map[string]*ProgramSpec, names []string) { // dependencies of each program. func flattenInstructions(name string, progs map[string]*ProgramSpec, refs map[*ProgramSpec][]string) asm.Instructions { prog := progs[name] + progRefs := refs[prog] + + if len(progRefs) == 0 { + // No references, nothing to do. + return prog.Instructions + } insns := make(asm.Instructions, len(prog.Instructions)) copy(insns, prog.Instructions) // Add all direct references of prog to the list of to be linked programs. - pending := make([]string, len(refs[prog])) - copy(pending, refs[prog]) + pending := make([]string, len(progRefs)) + copy(pending, progRefs) // All references for which we've appended instructions. linked := make(map[string]bool) diff --git a/vendor/github.com/cilium/ebpf/netlify.toml b/vendor/github.com/cilium/ebpf/netlify.toml index 67c83f3b30..764c3b447b 100644 --- a/vendor/github.com/cilium/ebpf/netlify.toml +++ b/vendor/github.com/cilium/ebpf/netlify.toml @@ -2,3 +2,4 @@ base = "docs/" publish = "site/" command = "mkdocs build" + environment = { PYTHON_VERSION = "3.13" } diff --git a/vendor/github.com/cilium/ebpf/prog.go b/vendor/github.com/cilium/ebpf/prog.go index 4f3ce43bfa..8fcae6a3fb 100644 --- a/vendor/github.com/cilium/ebpf/prog.go +++ b/vendor/github.com/cilium/ebpf/prog.go @@ -169,7 +169,7 @@ func (ps *ProgramSpec) Tag() (string, error) { // ProgramSpec.AttachTo, if any. Returns an empty string if the symbol is not // present or not part of a kernel module. func (ps *ProgramSpec) kernelModule() (string, error) { - if ps.AttachTo == "" && ps.targetsKernelModule() { + if ps.targetsKernelModule() { return kallsyms.Module(ps.AttachTo) } diff --git a/vendor/github.com/cilium/ebpf/types.go b/vendor/github.com/cilium/ebpf/types.go index 211b308bbc..d7fb00509d 100644 --- a/vendor/github.com/cilium/ebpf/types.go +++ b/vendor/github.com/cilium/ebpf/types.go @@ -236,6 +236,7 @@ const ( AttachSkReuseportSelectOrMigrate = AttachType(sys.BPF_SK_REUSEPORT_SELECT_OR_MIGRATE) AttachPerfEvent = AttachType(sys.BPF_PERF_EVENT) AttachTraceKprobeMulti = AttachType(sys.BPF_TRACE_KPROBE_MULTI) + AttachTraceKprobeSession = AttachType(sys.BPF_TRACE_KPROBE_SESSION) AttachLSMCgroup = AttachType(sys.BPF_LSM_CGROUP) AttachStructOps = AttachType(sys.BPF_STRUCT_OPS) AttachNetfilter = AttachType(sys.BPF_NETFILTER) diff --git a/vendor/github.com/cilium/hive/cell/invoke.go b/vendor/github.com/cilium/hive/cell/invoke.go index 739b5b62f4..7998242e6d 100644 --- a/vendor/github.com/cilium/hive/cell/invoke.go +++ b/vendor/github.com/cilium/hive/cell/invoke.go @@ -49,7 +49,7 @@ func (inv *invoker) invoke(log *slog.Logger, cont container, logThreshold time.D defer inv.funcs[i].infoMu.Unlock() if err := cont.Invoke(nf.fn, opts...); err != nil { - log.Error("Invoke failed", "error", err, "function", nf.name) + log.Error("Invoke failed", "error", dig.RootCause(err), "function", nf.name) return err } d := time.Since(t0) diff --git a/vendor/github.com/cilium/hive/command.go b/vendor/github.com/cilium/hive/command.go index b398e77539..a79de9788e 100644 --- a/vendor/github.com/cilium/hive/command.go +++ b/vendor/github.com/cilium/hive/command.go @@ -14,10 +14,11 @@ import ( // command can be used to inspect the dependency graph. func (h *Hive) Command() *cobra.Command { cmd := &cobra.Command{ - Use: "hive", - Short: "Inspect the hive", - Run: func(cmd *cobra.Command, args []string) { - h.PrintObjects(os.Stdout, slog.Default()) + Use: "hive", + Short: "Inspect the hive", + SilenceUsage: true, + RunE: func(cmd *cobra.Command, args []string) error { + return h.PrintObjects(os.Stdout, slog.Default()) }, TraverseChildren: false, } @@ -25,10 +26,11 @@ func (h *Hive) Command() *cobra.Command { cmd.AddCommand( &cobra.Command{ - Use: "dot-graph", - Short: "Output the dependencies graph in graphviz dot format", - Run: func(cmd *cobra.Command, args []string) { - h.PrintDotGraph() + Use: "dot-graph", + Short: "Output the dependencies graph in graphviz dot format", + SilenceUsage: true, + RunE: func(cmd *cobra.Command, args []string) error { + return h.PrintDotGraph() }, TraverseChildren: false, }) diff --git a/vendor/github.com/cilium/hive/hive.go b/vendor/github.com/cilium/hive/hive.go index 760fe08436..6ef24a5384 100644 --- a/vendor/github.com/cilium/hive/hive.go +++ b/vendor/github.com/cilium/hive/hive.go @@ -229,6 +229,9 @@ func (h *Hive) Run(log *slog.Logger) error { var errs error if err := h.Start(log, startCtx); err != nil { + if errors.Is(err, ErrPopulate{}) { + return err + } errs = errors.Join(errs, fmt.Errorf("failed to start: %w", err)) } @@ -326,12 +329,27 @@ func (h *Hive) AppendInvoke(invoke func(*slog.Logger, time.Duration) error) { h.invokes = append(h.invokes, invoke) } +type ErrPopulate struct { + err error +} + +// Error implements error. +func (e ErrPopulate) Error() string { + return fmt.Sprintf("failed to populate object graph: %s", dig.RootCause(e.err)) +} + +func (e ErrPopulate) Pretty() string { + return fmt.Sprintf("Failed to populate object graph:\n%+v", e.err) +} + +var _ error = ErrPopulate{} + // Start starts the hive. The context allows cancelling the start. // If context is cancelled and the start hooks do not respect the cancellation // then after 5 more seconds the process will be terminated forcefully. func (h *Hive) Start(log *slog.Logger, ctx context.Context) error { if err := h.Populate(log); err != nil { - return err + return ErrPopulate{err} } defer close(h.fatalOnTimeout(ctx)) @@ -393,9 +411,11 @@ func (h *Hive) Shutdown(opts ...ShutdownOption) { } } -func (h *Hive) PrintObjects(w io.Writer, log *slog.Logger) { +func (h *Hive) PrintObjects(w io.Writer, log *slog.Logger) error { if err := h.Populate(log); err != nil { - panic(fmt.Sprintf("Failed to populate object graph: %s", err)) + err := ErrPopulate{err} + fmt.Fprintf(w, "ERROR: %s\n", err.Pretty()) + return err } fmt.Fprintf(w, "Cells:\n\n") @@ -405,16 +425,16 @@ func (h *Hive) PrintObjects(w io.Writer, log *slog.Logger) { fmt.Fprintln(w) } h.lifecycle.PrintHooks(w) + return nil } -func (h *Hive) PrintDotGraph() { +func (h *Hive) PrintDotGraph() error { if err := h.Populate(slog.Default()); err != nil { - panic(fmt.Sprintf("Failed to populate object graph: %s", err)) - } - - if err := dig.Visualize(h.container, os.Stdout); err != nil { - panic(fmt.Sprintf("Failed to dig.Visualize(): %s", err)) + err := ErrPopulate{err} + fmt.Fprintf(os.Stderr, "ERROR: %s\n", err.Pretty()) + return err } + return dig.Visualize(h.container, os.Stdout) } // getEnvName returns the environment variable to be used for the given option name. @@ -434,10 +454,10 @@ func (h *Hive) ScriptCommands(log *slog.Logger) (map[string]script.Cmd, error) { m["hive/stop"] = hiveStopCmd(h, log) // Gather the commands from the hive. - h.container.Invoke(func(sc ScriptCmds) { + err := h.container.Invoke(func(sc ScriptCmds) { for name, cmd := range sc.Map() { m[name] = cmd } }) - return m, nil + return m, err } diff --git a/vendor/github.com/cilium/hive/hivetest/doc.go b/vendor/github.com/cilium/hive/hivetest/doc.go new file mode 100644 index 0000000000..36d75e4b5e --- /dev/null +++ b/vendor/github.com/cilium/hive/hivetest/doc.go @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +// Package hivetest makes testing components using hive easier. +package hivetest diff --git a/vendor/github.com/cilium/hive/hivetest/lifecycle.go b/vendor/github.com/cilium/hive/hivetest/lifecycle.go new file mode 100644 index 0000000000..40e50607a5 --- /dev/null +++ b/vendor/github.com/cilium/hive/hivetest/lifecycle.go @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Cilium + +package hivetest + +import ( + "context" + "io" + "log/slog" + "testing" + + "github.com/cilium/hive/cell" +) + +// lifecycle implements [cell.Lifecycle] for testing purposes. +type lifecycle struct { + tb testing.TB +} + +var _ (cell.Lifecycle) = (*lifecycle)(nil) + +// Lifecycle returns a [cell.Lifecycle] which executes start hooks immediately +// and queues stop hooks for the end of the test. +func Lifecycle(tb testing.TB) *lifecycle { + return &lifecycle{tb} +} + +func (lc *lifecycle) Append(hook cell.HookInterface) { + lc.tb.Helper() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + if err := hook.Start(ctx); err != nil { + lc.tb.Fatal("Execute start hook:", err) + } + + lc.tb.Cleanup(func() { + lc.tb.Helper() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + if err := hook.Stop(ctx); err != nil && !lc.tb.Failed() { + lc.tb.Fatal("Execute stop hook:", err) + } + }) +} + +// PrintHooks implements cell.Lifecycle. +func (*lifecycle) PrintHooks(io.Writer) { + panic("unimplemented") +} + +// Start implements cell.Lifecycle. +func (*lifecycle) Start(*slog.Logger, context.Context) error { + panic("unimplemented") +} + +// Stop implements cell.Lifecycle. +func (*lifecycle) Stop(*slog.Logger, context.Context) error { + panic("unimplemented") +} diff --git a/vendor/github.com/cilium/hive/hivetest/slog.go b/vendor/github.com/cilium/hive/hivetest/slog.go new file mode 100644 index 0000000000..67df23893f --- /dev/null +++ b/vendor/github.com/cilium/hive/hivetest/slog.go @@ -0,0 +1,109 @@ +package hivetest + +import ( + "bytes" + "context" + "fmt" + "log/slog" + "os" + "slices" + "sync/atomic" + "testing" +) + +// Logger returns a logger which forwards structured logs to t. +func Logger(t testing.TB, opts ...LogOption) *slog.Logger { + // We need to make sure that we don't try to log to `t` after the test has + // completed since that leads to a panic. + var tDone atomic.Bool + t.Cleanup(func() { + tDone.Store(true) + }) + + th := &testHandler{ + tDone: &tDone, + t: t, + } + for _, o := range opts { + o(th) + } + return slog.New(th) +} + +type LogOption func(*testHandler) + +func LogLevel(l slog.Level) LogOption { + return func(th *testHandler) { + th.level = l + } +} + +// Will be accessed by multiple goroutines - needs to appear immutable. +type testHandler struct { + t testing.TB + tDone *atomic.Bool + level slog.Level + fields []groupOrAttr +} + +type groupOrAttr struct { + group string + attrs []slog.Attr +} + +func (th *testHandler) Handle(ctx context.Context, r slog.Record) error { + // This doesn't do the right thing (as we're called from slog), but the API + // doesn't allow us to skip more callframes. + th.t.Helper() + + // This is pretty inefficient if the handler has accumulated a lot of + // context, but necessary to make it trivially thread-safe. If it becomes + // necessary, we can always cache the handler we create here. + var buf bytes.Buffer + var h slog.Handler + h = slog.NewTextHandler(&buf, &slog.HandlerOptions{ + AddSource: true, + }) + for _, ga := range th.fields { + if ga.group != "" { + h = h.WithGroup(ga.group) + } else { + h = h.WithAttrs(ga.attrs) + } + } + if err := h.Handle(ctx, r); err != nil { + return err + } + + defer func() { + if r := recover(); r != nil { + fmt.Fprintf(os.Stderr, "failed to log (likely because the test is no longer running): %v", r) + } + }() + + // This is still TOCTOU racy with the call to log below, but we catch the + // potential panic above. + if th.tDone.Load() { + return fmt.Errorf("cannot log to finished test case") + } + // Chomp the newline. + th.t.Log(string(buf.Bytes()[:buf.Len()-1])) + + return nil +} + +func (th *testHandler) WithGroup(g string) slog.Handler { + nt := *th + nt.fields = append(slices.Clone(th.fields), groupOrAttr{group: g}) + return &nt +} + +func (th *testHandler) WithAttrs(as []slog.Attr) slog.Handler { + nt := *th + nt.fields = append(slices.Clone(th.fields), groupOrAttr{attrs: as}) + return &nt +} + +func (th *testHandler) Enabled(ctx context.Context, l slog.Level) bool { + return th.level <= l +} diff --git a/vendor/github.com/cilium/hive/script.go b/vendor/github.com/cilium/hive/script.go index f4a2a0f211..1289af2dd4 100644 --- a/vendor/github.com/cilium/hive/script.go +++ b/vendor/github.com/cilium/hive/script.go @@ -82,8 +82,8 @@ func hiveScriptCmd(h *Hive, log *slog.Logger) script.Cmd { defer cancel() return nil, h.Stop(log, ctx) default: - h.PrintObjects(s.LogWriter(), log) - return nil, nil + err := h.PrintObjects(s.LogWriter(), log) + return nil, err } }, ) diff --git a/vendor/github.com/cilium/hive/script/cmds.go b/vendor/github.com/cilium/hive/script/cmds.go index 75fb7fbf35..ba98365b9c 100644 --- a/vendor/github.com/cilium/hive/script/cmds.go +++ b/vendor/github.com/cilium/hive/script/cmds.go @@ -256,9 +256,10 @@ func doCompare(s *State, env bool, args ...string) error { } if text1 != text2 { - if s.DoUpdate { - // Updates requested, store the file contents and - // ignore mismatches. + if s.DoUpdate && s.RetryCount > 0 { + // Updates requested and we've already retried at least once + // (and given time for things to settle down). + // Store the file contents and ignore the mismatch. s.FileUpdates[name1] = text2 s.FileUpdates[name2] = text1 return nil diff --git a/vendor/github.com/cilium/hive/script/engine.go b/vendor/github.com/cilium/hive/script/engine.go index b919bb469d..cafa072aee 100644 --- a/vendor/github.com/cilium/hive/script/engine.go +++ b/vendor/github.com/cilium/hive/script/engine.go @@ -198,6 +198,10 @@ func (e *Engine) Execute(s *State, file string, script *bufio.Reader, log io.Wri if retryInterval == 0 { retryInterval = defaultRetryInterval } + maxRetryInterval := e.MaxRetryInterval + if maxRetryInterval == 0 { + maxRetryInterval = defaultMaxRetryInterval + } var ( sectionStart time.Time @@ -331,32 +335,43 @@ func (e *Engine) Execute(s *State, file string, script *bufio.Reader, log io.Wri } cmd.origArgs = expandArgs(s, cmd.rawArgs, regexpArgs) cmd.args = cmd.origArgs + s.RetryCount = 0 // Run the command. err = e.runCommand(s, cmd, impl) if err != nil { if cmd.want == successRetryOnFailure || cmd.want == failureRetryOnSuccess { + retryStart := sectionStart + + // Clear the section start to avoid the deferred endSection() printing a timestamp. + sectionStart = time.Time{} + + // Append the new line that section start omitted and flush the log. + io.WriteString(log, "\n") + s.FlushLog() + // Command wants retries. Retry the whole section - numRetries := 0 - backoff := exponentialBackoff{max: e.MaxRetryInterval, interval: e.RetryInterval} + backoff := exponentialBackoff{max: maxRetryInterval, interval: retryInterval} for err != nil { - s.FlushLog() retryDuration := backoff.get() - s.Logf("(command %q failed, retrying in %s...)\n", line, retryDuration) + fmt.Fprintf(log, "(command %q failed, retrying in %s...)\n", line, retryDuration) select { case <-s.Context().Done(): + s.RetryCount = 0 return lineErr(s.Context().Err()) case <-time.After(retryDuration): } - numRetries++ + s.RetryCount++ for _, cmd := range sectionCmds { impl := e.Cmds[cmd.name] if err = e.runCommand(s, cmd, impl); err != nil { break } } + s.FlushLog() } - s.Logf("(command %q succeeded after %d retries)\n", line, numRetries) + fmt.Fprintf(log, "(command %q succeeded after %d retries in %.3fs)\n", line, s.RetryCount, time.Since(retryStart).Seconds()) + s.RetryCount = 0 } else { if stop := (stopError{}); errors.As(err, &stop) { // Since the 'stop' command halts execution of the entire script, diff --git a/vendor/github.com/cilium/hive/script/state.go b/vendor/github.com/cilium/hive/script/state.go index 44c80cdd56..c512f20391 100644 --- a/vendor/github.com/cilium/hive/script/state.go +++ b/vendor/github.com/cilium/hive/script/state.go @@ -40,6 +40,7 @@ type State struct { Flags *pflag.FlagSet DoUpdate bool FileUpdates map[string]string + RetryCount int BreakOnError bool diff --git a/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.go b/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.go index 9bcd3dc9f2..3e2be1b2a0 100644 --- a/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.go +++ b/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.go @@ -68,6 +68,9 @@ type BpfMetadata struct { // network policy update took longer // Deprecated, has no effect. PolicyUpdateWarningLimit *durationpb.Duration `protobuf:"bytes,9,opt,name=policy_update_warning_limit,json=policyUpdateWarningLimit,proto3" json:"policy_update_warning_limit,omitempty"` + // l7lb_policy_name is the name of the L7LB policy that is enforced on the listener. + // This is optional field. + L7LbPolicyName string `protobuf:"bytes,10,opt,name=l7lb_policy_name,json=l7lbPolicyName,proto3" json:"l7lb_policy_name,omitempty"` } func (x *BpfMetadata) Reset() { @@ -165,6 +168,13 @@ func (x *BpfMetadata) GetPolicyUpdateWarningLimit() *durationpb.Duration { return nil } +func (x *BpfMetadata) GetL7LbPolicyName() string { + if x != nil { + return x.L7LbPolicyName + } + return "" +} + var File_cilium_api_bpf_metadata_proto protoreflect.FileDescriptor var file_cilium_api_bpf_metadata_proto_rawDesc = []byte{ @@ -172,7 +182,7 @@ var file_cilium_api_bpf_metadata_proto_rawDesc = []byte{ 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x63, 0x69, 0x6c, 0x69, 0x75, 0x6d, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa9, 0x03, 0x0a, 0x0b, 0x42, 0x70, 0x66, 0x4d, + 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd3, 0x03, 0x0a, 0x0b, 0x42, 0x70, 0x66, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x70, 0x66, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x70, 0x66, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, @@ -199,10 +209,13 @@ var file_cilium_api_bpf_metadata_proto_rawDesc = []byte{ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x63, 0x69, 0x6c, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x67, - 0x6f, 0x2f, 0x63, 0x69, 0x6c, 0x69, 0x75, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x63, 0x69, 0x6c, - 0x69, 0x75, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x69, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x37, 0x6c, 0x62, 0x5f, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, + 0x37, 0x6c, 0x62, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x2e, 0x5a, + 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x69, 0x6c, 0x69, + 0x75, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x67, 0x6f, 0x2f, 0x63, 0x69, 0x6c, 0x69, + 0x75, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x63, 0x69, 0x6c, 0x69, 0x75, 0x6d, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.validate.go b/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.validate.go index 6759e89e77..09ee33d097 100644 --- a/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.validate.go +++ b/vendor/github.com/cilium/proxy/go/cilium/api/bpf_metadata.pb.validate.go @@ -102,6 +102,8 @@ func (m *BpfMetadata) validate(all bool) error { } } + // no validation rules for L7LbPolicyName + if len(errors) > 0 { return BpfMetadataMultiError(errors) } diff --git a/vendor/github.com/cilium/statedb/any_table.go b/vendor/github.com/cilium/statedb/any_table.go index 36b40a30a3..cbf561b982 100644 --- a/vendor/github.com/cilium/statedb/any_table.go +++ b/vendor/github.com/cilium/statedb/any_table.go @@ -69,8 +69,7 @@ func (t AnyTable) Get(txn ReadTxn, index string, key string) (any, Revision, boo if !ok { break } - secondary, _ := decodeNonUniqueKey(k) - if len(secondary) == len(rawKey) { + if nonUniqueKey(k).secondaryLen() == len(rawKey) { return obj.data, obj.revision, true, nil } } diff --git a/vendor/github.com/cilium/statedb/http.go b/vendor/github.com/cilium/statedb/http.go index 96b1a651fd..80d1dc5556 100644 --- a/vendor/github.com/cilium/statedb/http.go +++ b/vendor/github.com/cilium/statedb/http.go @@ -124,6 +124,9 @@ type QueryResponse struct { func runQuery(indexTxn indexReadTxn, lowerbound bool, queryKey []byte, onObject func(object) error) { var iter *part.Iterator[object] + if !indexTxn.unique { + queryKey = encodeNonUniqueBytes(queryKey) + } if lowerbound { iter = indexTxn.LowerBound(queryKey) } else { @@ -137,8 +140,7 @@ func runQuery(indexTxn indexReadTxn, lowerbound bool, queryKey []byte, onObject match = func(k []byte) bool { return len(k) == len(queryKey) } default: match = func(k []byte) bool { - secondary, _ := decodeNonUniqueKey(k) - return len(secondary) == len(queryKey) + return nonUniqueKey(k).secondaryLen() == len(queryKey) } } for key, obj, ok := iter.Next(); ok; key, obj, ok = iter.Next() { diff --git a/vendor/github.com/cilium/statedb/iterator.go b/vendor/github.com/cilium/statedb/iterator.go index 301ce330d5..903a406bc4 100644 --- a/vendor/github.com/cilium/statedb/iterator.go +++ b/vendor/github.com/cilium/statedb/iterator.go @@ -113,18 +113,21 @@ func nonUniqueSeq[Obj any](iter *part.Iterator[object], prefixSearch bool, searc break } - secondary, primary := decodeNonUniqueKey(key) + nuk := nonUniqueKey(key) + secondaryLen := nuk.secondaryLen() switch { - case !prefixSearch && len(secondary) != len(searchKey): + case !prefixSearch && secondaryLen != len(searchKey): // This a List(), thus secondary key must match length exactly. continue - case prefixSearch && len(secondary) < len(searchKey): + case prefixSearch && secondaryLen < len(searchKey): // This is Prefix(), thus key must be equal or longer to search key. continue } if prefixSearch { + primary := nuk.encodedPrimary() + // When doing a prefix search on a non-unique index we may see the // same object multiple times since multiple keys may point it. // Skip if we've already seen this object. @@ -157,8 +160,10 @@ func nonUniqueLowerBoundSeq[Obj any](iter *part.Iterator[object], searchKey []by // With a non-unique index we have a composite key . // This means we need to check every key that it's larger or equal to the search key. // Just seeking to the first one isn't enough as the secondary key length may vary. - secondary, primary := decodeNonUniqueKey(key) + nuk := nonUniqueKey(key) + secondary := nuk.encodedSecondary() if bytes.Compare(secondary, searchKey) >= 0 { + primary := nuk.encodedPrimary() if _, found := visited[string(primary)]; found { continue } diff --git a/vendor/github.com/cilium/statedb/table.go b/vendor/github.com/cilium/statedb/table.go index c7d41fb1f6..98e84f1e1e 100644 --- a/vendor/github.com/cilium/statedb/table.go +++ b/vendor/github.com/cilium/statedb/table.go @@ -321,8 +321,7 @@ func (t *genTable[Obj]) GetWatch(txn ReadTxn, q Query[Obj]) (obj Obj, revision u } // Check that we have a full match on the key - secondary, _ := decodeNonUniqueKey(key) - if len(secondary) == len(q.key) { + if nonUniqueKey(key).secondaryLen() == len(q.key) { break } } diff --git a/vendor/github.com/cilium/statedb/txn.go b/vendor/github.com/cilium/statedb/txn.go index 6c75c88232..a1a436b684 100644 --- a/vendor/github.com/cilium/statedb/txn.go +++ b/vendor/github.com/cilium/statedb/txn.go @@ -46,8 +46,6 @@ type indexTxn struct { unique bool } -var zeroTxn = txn{} - // txn fulfills the ReadTxn/WriteTxn interface. func (txn *txn) getTxn() *txn { return txn @@ -361,38 +359,57 @@ func (txn *txn) delete(meta TableMeta, guardRevision Revision, data any) (object } const ( - nonUniqueSeparator = 0x0 - nonUniqueSubstitute = 0xfe - nonUniqueSubstitute2 = 0xfd + // nonUniqueSeparator is the byte that delimits the secondary and primary keys. + // It has to be 0x00 for correct ordering, e.g. if secondary prefix is "ab", + // then it must hold that "ab" < "abc", which is only possible if sep=0x00. + nonUniqueSeparator = 0x00 + + // nonUniqueSubstitute is the byte that is used to escape 0x00 and 0x01 in + // order to make sure the non-unique key has only a single 0x00 byte that is + // the separator. + nonUniqueSubstitute = 0x01 ) -// appendEncodePrimary encodes the 'src' (primary key) into 'dst'. -func appendEncodePrimary(dst, src []byte) []byte { +// appendEncode encodes the 'src' into 'dst'. +func appendEncode(dst, src []byte) (int, []byte) { + n := 0 for _, b := range src { switch b { case nonUniqueSeparator: - dst = append(dst, nonUniqueSubstitute) + dst = append(dst, nonUniqueSubstitute, 0x01) + n += 2 case nonUniqueSubstitute: - dst = append(dst, nonUniqueSubstitute2, 0x00) - case nonUniqueSubstitute2: - dst = append(dst, nonUniqueSubstitute2, 0x01) + dst = append(dst, nonUniqueSubstitute, 0x02) + n += 2 default: dst = append(dst, b) + n++ + } + } + return n, dst +} + +func encodedLength(src []byte) int { + n := len(src) + for _, b := range src { + if b == nonUniqueSeparator || b == nonUniqueSubstitute { + n++ } } - return dst + return n +} + +func encodeNonUniqueBytes(src []byte) []byte { + n := encodedLength(src) + if n == len(src) { + // No substitutions needed. + return src + } + _, out := appendEncode(make([]byte, 0, n), src) + return out } // encodeNonUniqueKey constructs the internal key to use with non-unique indexes. -// The key is constructed by concatenating the secondary key with the primary key -// along with the secondary key length. The secondary and primary key are separated -// with by a 0x0 to ensure ordering is defined by the secondary key. To make sure the -// separator does not appear in the primary key it is encoded using this schema: -// -// 0x0 => 0xfe, 0xfe => 0xfd00, 0xfd => 0xfd01 -// -// The schema tries to avoid expansion for encoded small integers, e.g. 0x0000 becomes 0xfefe. -// The length at the end is encoded as unsigned 16-bit big endian. // // This schema allows looking up from the non-unique index with the secondary key by // doing a prefix search. The length is used to safe-guard against indexers that don't @@ -400,27 +417,38 @@ func appendEncodePrimary(dst, src []byte) []byte { // "foobar" to match). func encodeNonUniqueKey(primary, secondary index.Key) []byte { key := make([]byte, 0, - len(secondary)+1 /* separator */ + - len(primary)+ - 2 /* space for few substitutions */ + - 2 /* length */) - key = append(key, secondary...) - key = append(key, nonUniqueSeparator) - key = appendEncodePrimary(key, primary) - // KeySet limits size of key to 16 bits. - return binary.BigEndian.AppendUint16(key, uint16(len(secondary))) + encodedLength(secondary)+ + 1 /* delimiter */ + + encodedLength(primary)+ + 2 /* primary length */) + + _, key = appendEncode(key, secondary) + key = append(key, 0x00) + primaryLen, key := appendEncode(key, primary) + return binary.BigEndian.AppendUint16(key, uint16(primaryLen)) } -func decodeNonUniqueKey(key []byte) (secondary []byte, encPrimary []byte) { - // Non-unique key is [, '\xfe', , ] - if len(key) < 2 { - return nil, nil - } - secondaryLength := int(binary.BigEndian.Uint16(key[len(key)-2:])) - if len(key) < secondaryLength { - return nil, nil +type nonUniqueKey []byte + +func (k nonUniqueKey) primaryLen() int { + // Non-unique key is [, 0x00, , ] + if len(k) <= 3 { + return 0 } - return key[:secondaryLength], key[secondaryLength+1 : len(key)-2] + return int(binary.BigEndian.Uint16(k[len(k)-2:])) +} + +func (k nonUniqueKey) secondaryLen() int { + return len(k) - k.primaryLen() - 3 +} + +func (k nonUniqueKey) encodedPrimary() []byte { + primaryLen := k.primaryLen() + return k[len(k)-2-primaryLen : len(k)-2] +} + +func (k nonUniqueKey) encodedSecondary() []byte { + return k[:k.secondaryLen()] } func (txn *txn) Abort() { diff --git a/vendor/github.com/cilium/statedb/types.go b/vendor/github.com/cilium/statedb/types.go index 418e597322..13d712f06b 100644 --- a/vendor/github.com/cilium/statedb/types.go +++ b/vendor/github.com/cilium/statedb/types.go @@ -344,6 +344,7 @@ func (i Index[Obj, Key]) fromString(s string) (index.Key, error) { return index.Key{}, errFromStringNil } k, err := i.FromString(s) + k = i.encodeKey(k) return k, err } @@ -352,23 +353,30 @@ func (i Index[Obj, Key]) isUnique() bool { return i.Unique } +func (i Index[Obj, Key]) encodeKey(key []byte) []byte { + if !i.Unique { + return encodeNonUniqueBytes(key) + } + return key +} + // Query constructs a query against this index from a key. func (i Index[Obj, Key]) Query(key Key) Query[Obj] { return Query[Obj]{ index: i.Name, - key: i.FromKey(key), + key: i.encodeKey(i.FromKey(key)), } } func (i Index[Obj, Key]) QueryFromObject(obj Obj) Query[Obj] { return Query[Obj]{ index: i.Name, - key: i.FromObject(obj).First(), + key: i.encodeKey(i.FromObject(obj).First()), } } func (i Index[Obj, Key]) ObjectToKey(obj Obj) index.Key { - return i.FromObject(obj).First() + return i.encodeKey(i.FromObject(obj).First()) } // Indexer is the "FromObject" subset of Index[Obj, Key] diff --git a/vendor/github.com/cilium/workerpool/.golangci.yml b/vendor/github.com/cilium/workerpool/.golangci.yml index 267f1c400f..96a7addbce 100644 --- a/vendor/github.com/cilium/workerpool/.golangci.yml +++ b/vendor/github.com/cilium/workerpool/.golangci.yml @@ -1,8 +1,7 @@ # See https://golangci-lint.run/usage/configuration/ for available options. -# Also https://github.com/cilium/cilium/blob/master/.golangci.yaml as a +# Also https://github.com/cilium/cilium/blob/main/.golangci.yaml as a # reference. run: - go: '1.20' timeout: 1m linters: disable-all: true @@ -13,28 +12,28 @@ linters: - bodyclose - containedctx - contextcheck + - copyloopvar - cyclop - decorder - dogsled - dupl - dupword - durationcheck + - err113 - errcheck - errname - errorlint + - exptostd - exhaustive - - exportloopref - forcetypeassert - gocheckcompilerdirectives - gocognit - goconst - gocritic - godot - - goerr113 - gofmt - goheader - goimports - - gomnd - goprintffuncname - gosec - gosimple @@ -42,8 +41,10 @@ linters: - grouper - ineffassign - interfacebloat + - intrange - ireturn - makezero + - mirror - misspell - musttag - nakedret @@ -52,13 +53,16 @@ linters: - nilnil - noctx - nosprintfhostport + - perfsprint - prealloc - predeclared - reassign - revive - rowserrcheck + - sloglint - staticcheck - - tenv + - tagalign + - testifylint - thelper - tparallel - typecheck @@ -66,15 +70,36 @@ linters: - unparam - unused - usestdlibvars + - usetesting - wastedassign - linters-settings: cyclop: skip-tests: true - goheader: template: |- SPDX-License-Identifier: Apache-2.0 Copyright Authors of Cilium govet: enable-all: true + perfsprint: + strconcat: false + sloglint: + no-mixed-args: true + static-msg: true + no-global: "all" + key-naming-case: kebab # be consistent with key names + forbidden-keys: # let's no use reserved log keys + - level + - msg + - source + - time +issues: + # Maximum issues count per one linter. + # Set to 0 to disable (default is 50) + max-issues-per-linter: 0 + # Maximum count of issues with the same text. + # Set to 0 to disable (default is 3) + max-same-issues: 0 + fix: true # fix found issues (if it's supported by the linter). + exclude-use-default: false # default rules exclude doc comments check :( + exclude-generated: strict diff --git a/vendor/github.com/cilium/workerpool/README.md b/vendor/github.com/cilium/workerpool/README.md index 5df02ff0ff..b073964a8e 100644 --- a/vendor/github.com/cilium/workerpool/README.md +++ b/vendor/github.com/cilium/workerpool/README.md @@ -53,7 +53,6 @@ func IsPrime(n int64) bool { func main() { wp := workerpool.New(runtime.NumCPU()) for i, n := 0, int64(1_000_000_000_000_000_000); n < 1_000_000_000_000_000_100; i, n = i+1, n+1 { - n := n // https://golang.org/doc/faq#closures_and_goroutines id := fmt.Sprintf("task #%d", i) // Use Submit to submit tasks for processing. Submit blocks when no // worker is available to pick up the task. diff --git a/vendor/github.com/cilium/workerpool/workerpool.go b/vendor/github.com/cilium/workerpool/workerpool.go index c78af835e0..802acfe617 100644 --- a/vendor/github.com/cilium/workerpool/workerpool.go +++ b/vendor/github.com/cilium/workerpool/workerpool.go @@ -171,7 +171,7 @@ func (wp *WorkerPool) Close() error { // only be called once during the lifetime of a WorkerPool. func (wp *WorkerPool) run(ctx context.Context) { for t := range wp.tasks { - t := t + result := taskResult{id: t.id} wp.results = append(wp.results, &result) wp.workers <- struct{}{} diff --git a/vendor/github.com/containerd/containerd/errdefs/grpc.go b/vendor/github.com/containerd/containerd/errdefs/grpc.go index 7a9b33e05a..11091b1db0 100644 --- a/vendor/github.com/containerd/containerd/errdefs/grpc.go +++ b/vendor/github.com/containerd/containerd/errdefs/grpc.go @@ -45,21 +45,21 @@ func ToGRPC(err error) error { switch { case IsInvalidArgument(err): - return status.Errorf(codes.InvalidArgument, err.Error()) + return status.Error(codes.InvalidArgument, err.Error()) case IsNotFound(err): - return status.Errorf(codes.NotFound, err.Error()) + return status.Error(codes.NotFound, err.Error()) case IsAlreadyExists(err): - return status.Errorf(codes.AlreadyExists, err.Error()) + return status.Error(codes.AlreadyExists, err.Error()) case IsFailedPrecondition(err): - return status.Errorf(codes.FailedPrecondition, err.Error()) + return status.Error(codes.FailedPrecondition, err.Error()) case IsUnavailable(err): - return status.Errorf(codes.Unavailable, err.Error()) + return status.Error(codes.Unavailable, err.Error()) case IsNotImplemented(err): - return status.Errorf(codes.Unimplemented, err.Error()) + return status.Error(codes.Unimplemented, err.Error()) case IsCanceled(err): - return status.Errorf(codes.Canceled, err.Error()) + return status.Error(codes.Canceled, err.Error()) case IsDeadlineExceeded(err): - return status.Errorf(codes.DeadlineExceeded, err.Error()) + return status.Error(codes.DeadlineExceeded, err.Error()) } return err diff --git a/vendor/github.com/containerd/containerd/filters/parser.go b/vendor/github.com/containerd/containerd/filters/parser.go index 32767909b1..790597aaf2 100644 --- a/vendor/github.com/containerd/containerd/filters/parser.go +++ b/vendor/github.com/containerd/containerd/filters/parser.go @@ -121,7 +121,7 @@ loop: case tokenEOF: break loop default: - return nil, p.mkerr(p.scanner.ppos, "unexpected input: %v", string(tok)) + return nil, p.mkerrf(p.scanner.ppos, "unexpected input: %v", string(tok)) } } @@ -226,7 +226,7 @@ func (p *parser) operator() (operator, error) { case "~=": return operatorMatches, nil default: - return 0, p.mkerr(pos, "unsupported operator %q", s) + return 0, p.mkerrf(pos, "unsupported operator %q", s) } case tokenIllegal: return 0, p.mkerr(pos, p.scanner.err) @@ -257,7 +257,7 @@ func (p *parser) unquote(pos int, s string, allowAlts bool) (string, error) { uq, err := unquote(s) if err != nil { - return "", p.mkerr(pos, "unquoting failed: %v", err) + return "", p.mkerrf(pos, "unquoting failed: %v", err) } return uq, nil @@ -281,10 +281,14 @@ func (pe parseError) Error() string { return fmt.Sprintf("[%s]: %v", pe.input, pe.msg) } -func (p *parser) mkerr(pos int, format string, args ...interface{}) error { +func (p *parser) mkerrf(pos int, format string, args ...interface{}) error { + return p.mkerr(pos, fmt.Sprintf(format, args...)) +} + +func (p *parser) mkerr(pos int, msg string) error { return fmt.Errorf("parse error: %w", parseError{ input: p.input, pos: pos, - msg: fmt.Sprintf(format, args...), + msg: msg, }) } diff --git a/vendor/github.com/containerd/containerd/images/image.go b/vendor/github.com/containerd/containerd/images/image.go index b934e34961..8bebae19b3 100644 --- a/vendor/github.com/containerd/containerd/images/image.go +++ b/vendor/github.com/containerd/containerd/images/image.go @@ -378,7 +378,7 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr descs = append(descs, index.Manifests...) default: - if IsLayerType(desc.MediaType) || IsKnownConfig(desc.MediaType) { + if IsLayerType(desc.MediaType) || IsKnownConfig(desc.MediaType) || IsAttestationType(desc.MediaType) { // childless data types. return nil, nil } diff --git a/vendor/github.com/containerd/containerd/images/mediatypes.go b/vendor/github.com/containerd/containerd/images/mediatypes.go index d3b28d42dc..49d2a5b1c5 100644 --- a/vendor/github.com/containerd/containerd/images/mediatypes.go +++ b/vendor/github.com/containerd/containerd/images/mediatypes.go @@ -57,6 +57,9 @@ const ( MediaTypeImageLayerEncrypted = ocispec.MediaTypeImageLayer + "+encrypted" MediaTypeImageLayerGzipEncrypted = ocispec.MediaTypeImageLayerGzip + "+encrypted" + + // In-toto attestation + MediaTypeInToto = "application/vnd.in-toto+json" ) // DiffCompression returns the compression as defined by the layer diff media @@ -186,6 +189,16 @@ func IsKnownConfig(mt string) bool { return false } +// IsAttestationType returns true if the media type is an attestation type +func IsAttestationType(mt string) bool { + switch mt { + case MediaTypeInToto: + return true + default: + return false + } +} + // ChildGCLabels returns the label for a given descriptor to reference it func ChildGCLabels(desc ocispec.Descriptor) []string { mt := desc.MediaType diff --git a/vendor/github.com/containerd/containerd/remotes/handlers.go b/vendor/github.com/containerd/containerd/remotes/handlers.go index 365ff5fc00..14af02769c 100644 --- a/vendor/github.com/containerd/containerd/remotes/handlers.go +++ b/vendor/github.com/containerd/containerd/remotes/handlers.go @@ -81,6 +81,8 @@ func MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string { return "layer-" + key case images.IsKnownConfig(mt): return "config-" + key + case images.IsAttestationType(desc.MediaType): + return "attestation-" + key default: log.G(ctx).Warnf("reference for unknown type: %s", mt) return "unknown-" + key diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/version/version.go index b83e759641..e806164cab 100644 --- a/vendor/github.com/containerd/containerd/version/version.go +++ b/vendor/github.com/containerd/containerd/version/version.go @@ -23,7 +23,7 @@ var ( Package = "github.com/containerd/containerd" // Version holds the complete version number. Filled in at linking time. - Version = "1.7.24+unknown" + Version = "1.7.27+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. diff --git a/vendor/github.com/docker/docker/AUTHORS b/vendor/github.com/docker/docker/AUTHORS index 5f93eeb4e8..88032defe7 100644 --- a/vendor/github.com/docker/docker/AUTHORS +++ b/vendor/github.com/docker/docker/AUTHORS @@ -2,7 +2,9 @@ # This file lists all contributors to the repository. # See hack/generate-authors.sh to make modifications. +7sunarni <710720732@qq.com> Aanand Prasad +Aarni Koskela Aaron Davidson Aaron Feng Aaron Hnatiw @@ -11,6 +13,7 @@ Aaron L. Xu Aaron Lehmann Aaron Welch Aaron Yoshitake +Abdur Rehman Abel Muiño Abhijeet Kasurde Abhinandan Prativadi @@ -24,9 +27,11 @@ Adam Avilla Adam Dobrawy Adam Eijdenberg Adam Kunk +Adam Lamers Adam Miller Adam Mills Adam Pointer +Adam Simon Adam Singer Adam Thornton Adam Walz @@ -119,6 +124,7 @@ amangoel Amen Belayneh Ameya Gawde Amir Goldstein +AmirBuddy Amit Bakshi Amit Krishnan Amit Shukla @@ -168,6 +174,7 @@ Andrey Kolomentsev Andrey Petrov Andrey Stolbovsky André Martins +Andrés Maldonado Andy Chambers andy diller Andy Goldstein @@ -219,6 +226,7 @@ Artur Meyster Arun Gupta Asad Saeeduddin Asbjørn Enge +Ashly Mathew Austin Vazquez averagehuman Avi Das @@ -345,6 +353,7 @@ Chance Zibolski Chander Govindarajan Chanhun Jeong Chao Wang +Charity Kathure Charles Chan Charles Hooper Charles Law @@ -480,6 +489,7 @@ Daniel Farrell Daniel Garcia Daniel Gasienica Daniel Grunwell +Daniel Guns Daniel Helfand Daniel Hiltgen Daniel J Walsh @@ -763,6 +773,7 @@ Frank Macreery Frank Rosquin Frank Villaro-Dixon Frank Yang +François Scala Fred Lifton Frederick F. Kautz IV Frederico F. de Oliveira @@ -798,6 +809,7 @@ GennadySpb Geoff Levand Geoffrey Bachelet Geon Kim +George Adams George Kontridze George Ma George MacRorie @@ -826,6 +838,7 @@ Gopikannan Venugopalsamy Gosuke Miyashita Gou Rao Govinda Fichtner +Grace Choi Grant Millar Grant Reaber Graydon Hoare @@ -966,6 +979,7 @@ James Nugent James Sanders James Turnbull James Watkins-Harvey +Jameson Hyde Jamie Hannaford Jamshid Afshar Jan Breig @@ -1064,13 +1078,16 @@ Jim Perrin Jimmy Cuadra Jimmy Puckett Jimmy Song +jinjiadu Jinsoo Park Jintao Zhang Jiri Appl Jiri Popelka Jiuyue Ma Jiří Župka +jjimbo137 <115816493+jjimbo137@users.noreply.github.com> Joakim Roubert +Joan Grau Joao Fernandes Joao Trindade Joe Beda @@ -1155,6 +1172,7 @@ Josiah Kiehl José Tomás Albornoz Joyce Jang JP +JSchltggr Julian Taylor Julien Barbier Julien Bisconti @@ -1289,6 +1307,7 @@ Laura Brehm Laura Frank Laurent Bernaille Laurent Erignoux +Laurent Goderre Laurie Voss Leandro Motta Barros Leandro Siqueira @@ -1369,6 +1388,7 @@ Madhan Raj Mookkandy Madhav Puri Madhu Venugopal Mageee +maggie44 <64841595+maggie44@users.noreply.github.com> Mahesh Tiyyagura malnick Malte Janduda @@ -1579,6 +1599,7 @@ Muayyad Alsadi Muhammad Zohaib Aslam Mustafa Akın Muthukumar R +Myeongjoon Kim Máximo Cuadros Médi-Rémi Hashim Nace Oroz @@ -1593,6 +1614,7 @@ Natasha Jarus Nate Brennand Nate Eagleson Nate Jones +Nathan Baulch Nathan Carlson Nathan Herald Nathan Hsieh @@ -1655,6 +1677,7 @@ Nuutti Kotivuori nzwsch O.S. Tezer objectified +Octol1ttle Odin Ugedal Oguz Bilgic Oh Jinkyun @@ -1763,6 +1786,7 @@ Pierre Carrier Pierre Dal-Pra Pierre Wacrenier Pierre-Alain RIVIERE +pinglanlu Piotr Bogdan Piotr Karbowski Porjo @@ -1790,6 +1814,7 @@ Quentin Tayssier r0n22 Rachit Sharma Radostin Stoyanov +Rafael Fernández López Rafal Jeczalik Rafe Colton Raghavendra K T @@ -1856,7 +1881,7 @@ Robin Speekenbrink Robin Thoni robpc Rodolfo Carvalho -Rodrigo Campos +Rodrigo Campos Rodrigo Vaz Roel Van Nyen Roger Peppe @@ -1995,6 +2020,7 @@ Sevki Hasirci Shane Canon Shane da Silva Shaun Kaasten +Shaun Thompson shaunol Shawn Landden Shawn Siefkas @@ -2013,6 +2039,7 @@ Shijun Qin Shishir Mahajan Shoubhik Bose Shourya Sarcar +Shreenidhi Shedi Shu-Wai Chow shuai-z Shukui Yang @@ -2100,6 +2127,7 @@ Sébastien Stormacq Sören Tempel Tabakhase Tadej Janež +Tadeusz Dudkiewicz Takuto Sato tang0th Tangi Colin @@ -2107,6 +2135,7 @@ Tatsuki Sugiura Tatsushi Inagaki Taylan Isikdemir Taylor Jones +tcpdumppy <847462026@qq.com> Ted M. Young Tehmasp Chaudhri Tejaswini Duggaraju @@ -2391,6 +2420,7 @@ You-Sheng Yang (楊有勝) youcai Youcef YEKHLEF Youfu Zhang +YR Chen Yu Changchun Yu Chengxia Yu Peng diff --git a/vendor/github.com/docker/docker/api/types/filters/errors.go b/vendor/github.com/docker/docker/api/types/filters/errors.go index f52f694408..b8a690d67a 100644 --- a/vendor/github.com/docker/docker/api/types/filters/errors.go +++ b/vendor/github.com/docker/docker/api/types/filters/errors.go @@ -22,16 +22,3 @@ func (e invalidFilter) Error() string { // InvalidParameter marks this error as ErrInvalidParameter func (e invalidFilter) InvalidParameter() {} - -// unreachableCode is an error indicating that the code path was not expected to be reached. -type unreachableCode struct { - Filter string - Value []string -} - -// System marks this error as ErrSystem -func (e unreachableCode) System() {} - -func (e unreachableCode) Error() string { - return fmt.Sprintf("unreachable code reached for filter: %q with values: %s", e.Filter, e.Value) -} diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go index 0914b2a441..2085ff38f2 100644 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ b/vendor/github.com/docker/docker/api/types/filters/parse.go @@ -200,7 +200,6 @@ func (args Args) Match(field, source string) bool { // Error is not nil only if the filter values are not valid boolean or are conflicting. func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) { fieldValues, ok := args.fields[key] - if !ok { return defaultValue, nil } @@ -211,20 +210,11 @@ func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) { isFalse := fieldValues["0"] || fieldValues["false"] isTrue := fieldValues["1"] || fieldValues["true"] - - conflicting := isFalse && isTrue - invalid := !isFalse && !isTrue - - if conflicting || invalid { + if isFalse == isTrue { + // Either no or conflicting truthy/falsy value were provided return defaultValue, &invalidFilter{key, args.Get(key)} - } else if isFalse { - return false, nil - } else if isTrue { - return true, nil } - - // This code shouldn't be reached. - return defaultValue, &unreachableCode{Filter: key, Value: args.Get(key)} + return isTrue, nil } // ExactMatch returns true if the source matches exactly one of the values. diff --git a/vendor/github.com/docker/docker/api/types/registry/authconfig.go b/vendor/github.com/docker/docker/api/types/registry/authconfig.go index 8e383f6e60..ebd5e4b9e2 100644 --- a/vendor/github.com/docker/docker/api/types/registry/authconfig.go +++ b/vendor/github.com/docker/docker/api/types/registry/authconfig.go @@ -1,17 +1,29 @@ package registry // import "github.com/docker/docker/api/types/registry" import ( + "context" "encoding/base64" "encoding/json" + "fmt" "io" "strings" - - "github.com/pkg/errors" ) // AuthHeader is the name of the header used to send encoded registry // authorization credentials for registry operations (push/pull). const AuthHeader = "X-Registry-Auth" +// RequestAuthConfig is a function interface that clients can supply +// to retry operations after getting an authorization error. +// +// The function must return the [AuthHeader] value ([AuthConfig]), encoded +// in base64url format ([RFC4648, section 5]), which can be decoded by +// [DecodeAuthConfig]. +// +// It must return an error if the privilege request fails. +// +// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5 +type RequestAuthConfig func(context.Context) (string, error) + // AuthConfig contains authorization information for connecting to a Registry. type AuthConfig struct { Username string `json:"username,omitempty"` @@ -85,7 +97,7 @@ func decodeAuthConfigFromReader(rdr io.Reader) (*AuthConfig, error) { } func invalid(err error) error { - return errInvalidParameter{errors.Wrap(err, "invalid X-Registry-Auth header")} + return errInvalidParameter{fmt.Errorf("invalid X-Registry-Auth header: %w", err)} } type errInvalidParameter struct{ error } diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go index 75ee07b15f..b0a4d604f5 100644 --- a/vendor/github.com/docker/docker/api/types/registry/registry.go +++ b/vendor/github.com/docker/docker/api/types/registry/registry.go @@ -9,11 +9,29 @@ import ( // ServiceConfig stores daemon registry services configuration. type ServiceConfig struct { - AllowNondistributableArtifactsCIDRs []*NetIPNet - AllowNondistributableArtifactsHostnames []string - InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"` - IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"` - Mirrors []string + AllowNondistributableArtifactsCIDRs []*NetIPNet `json:"AllowNondistributableArtifactsCIDRs,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. + AllowNondistributableArtifactsHostnames []string `json:"AllowNondistributableArtifactsHostnames,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. + + InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"` + IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"` + Mirrors []string +} + +// MarshalJSON implements a custom marshaler to include legacy fields +// in API responses. +func (sc ServiceConfig) MarshalJSON() ([]byte, error) { + tmp := map[string]interface{}{ + "InsecureRegistryCIDRs": sc.InsecureRegistryCIDRs, + "IndexConfigs": sc.IndexConfigs, + "Mirrors": sc.Mirrors, + } + if sc.AllowNondistributableArtifactsCIDRs != nil { + tmp["AllowNondistributableArtifactsCIDRs"] = nil + } + if sc.AllowNondistributableArtifactsHostnames != nil { + tmp["AllowNondistributableArtifactsHostnames"] = nil + } + return json.Marshal(tmp) } // NetIPNet is the net.IPNet type, which can be marshalled and diff --git a/vendor/github.com/docker/docker/api/types/registry/search.go b/vendor/github.com/docker/docker/api/types/registry/search.go index a0a1eec544..994ca4c6f9 100644 --- a/vendor/github.com/docker/docker/api/types/registry/search.go +++ b/vendor/github.com/docker/docker/api/types/registry/search.go @@ -10,11 +10,12 @@ import ( type SearchOptions struct { RegistryAuth string - // PrivilegeFunc is a [types.RequestPrivilegeFunc] the client can - // supply to retry operations after getting an authorization error. + // PrivilegeFunc is a function that clients can supply to retry operations + // after getting an authorization error. This function returns the registry + // authentication header value in base64 encoded format, or an error if the + // privilege request fails. // - // It must return the registry authentication header value in base64 - // format, or an error if the privilege request fails. + // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. PrivilegeFunc func(context.Context) (string, error) Filters filters.Args Limit int diff --git a/vendor/github.com/docker/docker/errdefs/helpers.go b/vendor/github.com/docker/docker/errdefs/helpers.go index 042de4b7b8..ab76e62736 100644 --- a/vendor/github.com/docker/docker/errdefs/helpers.go +++ b/vendor/github.com/docker/docker/errdefs/helpers.go @@ -14,7 +14,9 @@ func (e errNotFound) Unwrap() error { return e.error } -// NotFound is a helper to create an error of the class with the same name from any error type +// NotFound creates an [ErrNotFound] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrNotFound], func NotFound(err error) error { if err == nil || IsNotFound(err) { return err @@ -34,7 +36,9 @@ func (e errInvalidParameter) Unwrap() error { return e.error } -// InvalidParameter is a helper to create an error of the class with the same name from any error type +// InvalidParameter creates an [ErrInvalidParameter] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrInvalidParameter], func InvalidParameter(err error) error { if err == nil || IsInvalidParameter(err) { return err @@ -54,7 +58,9 @@ func (e errConflict) Unwrap() error { return e.error } -// Conflict is a helper to create an error of the class with the same name from any error type +// Conflict creates an [ErrConflict] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrConflict], func Conflict(err error) error { if err == nil || IsConflict(err) { return err @@ -74,7 +80,9 @@ func (e errUnauthorized) Unwrap() error { return e.error } -// Unauthorized is a helper to create an error of the class with the same name from any error type +// Unauthorized creates an [ErrUnauthorized] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrUnauthorized], func Unauthorized(err error) error { if err == nil || IsUnauthorized(err) { return err @@ -94,7 +102,9 @@ func (e errUnavailable) Unwrap() error { return e.error } -// Unavailable is a helper to create an error of the class with the same name from any error type +// Unavailable creates an [ErrUnavailable] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrUnavailable], func Unavailable(err error) error { if err == nil || IsUnavailable(err) { return err @@ -114,7 +124,9 @@ func (e errForbidden) Unwrap() error { return e.error } -// Forbidden is a helper to create an error of the class with the same name from any error type +// Forbidden creates an [ErrForbidden] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrForbidden], func Forbidden(err error) error { if err == nil || IsForbidden(err) { return err @@ -134,7 +146,9 @@ func (e errSystem) Unwrap() error { return e.error } -// System is a helper to create an error of the class with the same name from any error type +// System creates an [ErrSystem] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrSystem], func System(err error) error { if err == nil || IsSystem(err) { return err @@ -154,7 +168,9 @@ func (e errNotModified) Unwrap() error { return e.error } -// NotModified is a helper to create an error of the class with the same name from any error type +// NotModified creates an [ErrNotModified] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [NotModified], func NotModified(err error) error { if err == nil || IsNotModified(err) { return err @@ -174,7 +190,9 @@ func (e errNotImplemented) Unwrap() error { return e.error } -// NotImplemented is a helper to create an error of the class with the same name from any error type +// NotImplemented creates an [ErrNotImplemented] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrNotImplemented], func NotImplemented(err error) error { if err == nil || IsNotImplemented(err) { return err @@ -194,7 +212,9 @@ func (e errUnknown) Unwrap() error { return e.error } -// Unknown is a helper to create an error of the class with the same name from any error type +// Unknown creates an [ErrUnknown] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrUnknown], func Unknown(err error) error { if err == nil || IsUnknown(err) { return err @@ -214,7 +234,9 @@ func (e errCancelled) Unwrap() error { return e.error } -// Cancelled is a helper to create an error of the class with the same name from any error type +// Cancelled creates an [ErrCancelled] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrCancelled], func Cancelled(err error) error { if err == nil || IsCancelled(err) { return err @@ -234,7 +256,9 @@ func (e errDeadline) Unwrap() error { return e.error } -// Deadline is a helper to create an error of the class with the same name from any error type +// Deadline creates an [ErrDeadline] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrDeadline], func Deadline(err error) error { if err == nil || IsDeadline(err) { return err @@ -254,7 +278,9 @@ func (e errDataLoss) Unwrap() error { return e.error } -// DataLoss is a helper to create an error of the class with the same name from any error type +// DataLoss creates an [ErrDataLoss] error from the given error. +// It returns the error as-is if it is either nil (no error) or already implements +// [ErrDataLoss], func DataLoss(err error) error { if err == nil || IsDataLoss(err) { return err diff --git a/vendor/github.com/docker/docker/errdefs/http_helpers.go b/vendor/github.com/docker/docker/errdefs/http_helpers.go index ebcd789302..0a8fadd48f 100644 --- a/vendor/github.com/docker/docker/errdefs/http_helpers.go +++ b/vendor/github.com/docker/docker/errdefs/http_helpers.go @@ -11,36 +11,37 @@ func FromStatusCode(err error, statusCode int) error { } switch statusCode { case http.StatusNotFound: - err = NotFound(err) + return NotFound(err) case http.StatusBadRequest: - err = InvalidParameter(err) + return InvalidParameter(err) case http.StatusConflict: - err = Conflict(err) + return Conflict(err) case http.StatusUnauthorized: - err = Unauthorized(err) + return Unauthorized(err) case http.StatusServiceUnavailable: - err = Unavailable(err) + return Unavailable(err) case http.StatusForbidden: - err = Forbidden(err) + return Forbidden(err) case http.StatusNotModified: - err = NotModified(err) + return NotModified(err) case http.StatusNotImplemented: - err = NotImplemented(err) + return NotImplemented(err) case http.StatusInternalServerError: - if !IsSystem(err) && !IsUnknown(err) && !IsDataLoss(err) && !IsDeadline(err) && !IsCancelled(err) { - err = System(err) + if IsCancelled(err) || IsSystem(err) || IsUnknown(err) || IsDataLoss(err) || IsDeadline(err) { + return err } + return System(err) default: switch { case statusCode >= 200 && statusCode < 400: // it's a client error + return err case statusCode >= 400 && statusCode < 500: - err = InvalidParameter(err) + return InvalidParameter(err) case statusCode >= 500 && statusCode < 600: - err = System(err) + return System(err) default: - err = Unknown(err) + return Unknown(err) } } - return err } diff --git a/vendor/github.com/docker/docker/errdefs/is.go b/vendor/github.com/docker/docker/errdefs/is.go index f94034cbd7..30ea7e6fec 100644 --- a/vendor/github.com/docker/docker/errdefs/is.go +++ b/vendor/github.com/docker/docker/errdefs/is.go @@ -39,79 +39,79 @@ func getImplementer(err error) error { } } -// IsNotFound returns if the passed in error is an ErrNotFound +// IsNotFound returns if the passed in error is an [ErrNotFound], func IsNotFound(err error) bool { _, ok := getImplementer(err).(ErrNotFound) return ok } -// IsInvalidParameter returns if the passed in error is an ErrInvalidParameter +// IsInvalidParameter returns if the passed in error is an [ErrInvalidParameter]. func IsInvalidParameter(err error) bool { _, ok := getImplementer(err).(ErrInvalidParameter) return ok } -// IsConflict returns if the passed in error is an ErrConflict +// IsConflict returns if the passed in error is an [ErrConflict]. func IsConflict(err error) bool { _, ok := getImplementer(err).(ErrConflict) return ok } -// IsUnauthorized returns if the passed in error is an ErrUnauthorized +// IsUnauthorized returns if the passed in error is an [ErrUnauthorized]. func IsUnauthorized(err error) bool { _, ok := getImplementer(err).(ErrUnauthorized) return ok } -// IsUnavailable returns if the passed in error is an ErrUnavailable +// IsUnavailable returns if the passed in error is an [ErrUnavailable]. func IsUnavailable(err error) bool { _, ok := getImplementer(err).(ErrUnavailable) return ok } -// IsForbidden returns if the passed in error is an ErrForbidden +// IsForbidden returns if the passed in error is an [ErrForbidden]. func IsForbidden(err error) bool { _, ok := getImplementer(err).(ErrForbidden) return ok } -// IsSystem returns if the passed in error is an ErrSystem +// IsSystem returns if the passed in error is an [ErrSystem]. func IsSystem(err error) bool { _, ok := getImplementer(err).(ErrSystem) return ok } -// IsNotModified returns if the passed in error is a NotModified error +// IsNotModified returns if the passed in error is an [ErrNotModified]. func IsNotModified(err error) bool { _, ok := getImplementer(err).(ErrNotModified) return ok } -// IsNotImplemented returns if the passed in error is an ErrNotImplemented +// IsNotImplemented returns if the passed in error is an [ErrNotImplemented]. func IsNotImplemented(err error) bool { _, ok := getImplementer(err).(ErrNotImplemented) return ok } -// IsUnknown returns if the passed in error is an ErrUnknown +// IsUnknown returns if the passed in error is an [ErrUnknown]. func IsUnknown(err error) bool { _, ok := getImplementer(err).(ErrUnknown) return ok } -// IsCancelled returns if the passed in error is an ErrCancelled +// IsCancelled returns if the passed in error is an [ErrCancelled]. func IsCancelled(err error) bool { _, ok := getImplementer(err).(ErrCancelled) return ok } -// IsDeadline returns if the passed in error is an ErrDeadline +// IsDeadline returns if the passed in error is an [ErrDeadline]. func IsDeadline(err error) bool { _, ok := getImplementer(err).(ErrDeadline) return ok } -// IsDataLoss returns if the passed in error is an ErrDataLoss +// IsDataLoss returns if the passed in error is an [ErrDataLoss]. func IsDataLoss(err error) bool { _, ok := getImplementer(err).(ErrDataLoss) return ok diff --git a/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go b/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go new file mode 100644 index 0000000000..6334edb60d --- /dev/null +++ b/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go @@ -0,0 +1,90 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code below was largely copied from golang.org/x/mod@v0.22; +// https://github.com/golang/mod/blob/v0.22.0/internal/lazyregexp/lazyre.go +// with some additional methods added. + +// Package lazyregexp is a thin wrapper over regexp, allowing the use of global +// regexp variables without forcing them to be compiled at init. +package lazyregexp + +import ( + "os" + "regexp" + "strings" + "sync" +) + +// Regexp is a wrapper around [regexp.Regexp], where the underlying regexp will be +// compiled the first time it is needed. +type Regexp struct { + str string + once sync.Once + rx *regexp.Regexp +} + +func (r *Regexp) re() *regexp.Regexp { + r.once.Do(r.build) + return r.rx +} + +func (r *Regexp) build() { + r.rx = regexp.MustCompile(r.str) + r.str = "" +} + +func (r *Regexp) FindSubmatch(s []byte) [][]byte { + return r.re().FindSubmatch(s) +} + +func (r *Regexp) FindAllStringSubmatch(s string, n int) [][]string { + return r.re().FindAllStringSubmatch(s, n) +} + +func (r *Regexp) FindStringSubmatch(s string) []string { + return r.re().FindStringSubmatch(s) +} + +func (r *Regexp) FindStringSubmatchIndex(s string) []int { + return r.re().FindStringSubmatchIndex(s) +} + +func (r *Regexp) ReplaceAllString(src, repl string) string { + return r.re().ReplaceAllString(src, repl) +} + +func (r *Regexp) FindString(s string) string { + return r.re().FindString(s) +} + +func (r *Regexp) FindAllString(s string, n int) []string { + return r.re().FindAllString(s, n) +} + +func (r *Regexp) MatchString(s string) bool { + return r.re().MatchString(s) +} + +func (r *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string { + return r.re().ReplaceAllStringFunc(src, repl) +} + +func (r *Regexp) SubexpNames() []string { + return r.re().SubexpNames() +} + +var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test") + +// New creates a new lazy regexp, delaying the compiling work until it is first +// needed. If the code is being run as part of tests, the regexp compiling will +// happen immediately. +func New(str string) *Regexp { + lr := &Regexp{str: str} + if inTest { + // In tests, always compile the regexps early. + lr.re() + } + return lr +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go b/vendor/github.com/docker/docker/pkg/ioutils/buffer.go deleted file mode 100644 index 466f79294b..0000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go +++ /dev/null @@ -1,51 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "errors" - "io" -) - -var errBufferFull = errors.New("buffer is full") - -type fixedBuffer struct { - buf []byte - pos int - lastRead int -} - -func (b *fixedBuffer) Write(p []byte) (int, error) { - n := copy(b.buf[b.pos:cap(b.buf)], p) - b.pos += n - - if n < len(p) { - if b.pos == cap(b.buf) { - return n, errBufferFull - } - return n, io.ErrShortWrite - } - return n, nil -} - -func (b *fixedBuffer) Read(p []byte) (int, error) { - n := copy(p, b.buf[b.lastRead:b.pos]) - b.lastRead += n - return n, nil -} - -func (b *fixedBuffer) Len() int { - return b.pos - b.lastRead -} - -func (b *fixedBuffer) Cap() int { - return cap(b.buf) -} - -func (b *fixedBuffer) Reset() { - b.pos = 0 - b.lastRead = 0 - b.buf = b.buf[:0] -} - -func (b *fixedBuffer) String() string { - return string(b.buf[b.lastRead:b.pos]) -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go deleted file mode 100644 index 85450bf6b3..0000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go +++ /dev/null @@ -1,193 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "errors" - "io" - "sync" -) - -// maxCap is the highest capacity to use in byte slices that buffer data. -const maxCap = 1e6 - -// minCap is the lowest capacity to use in byte slices that buffer data -const minCap = 64 - -// blockThreshold is the minimum number of bytes in the buffer which will cause -// a write to BytesPipe to block when allocating a new slice. -const blockThreshold = 1e6 - -var ( - // ErrClosed is returned when Write is called on a closed BytesPipe. - // - // Deprecated: this type is only used internally, and will be removed in the next release. - ErrClosed = errors.New("write to closed BytesPipe") - - bufPools = make(map[int]*sync.Pool) - bufPoolsLock sync.Mutex -) - -// BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue). -// All written data may be read at most once. Also, BytesPipe allocates -// and releases new byte slices to adjust to current needs, so the buffer -// won't be overgrown after peak loads. -// -// Deprecated: this type is only used internally, and will be removed in the next release. -type BytesPipe struct { - mu sync.Mutex - wait *sync.Cond - buf []*fixedBuffer - bufLen int - closeErr error // error to return from next Read. set to nil if not closed. - readBlock bool // check read BytesPipe is Wait() or not -} - -// NewBytesPipe creates new BytesPipe, initialized by specified slice. -// If buf is nil, then it will be initialized with slice which cap is 64. -// buf will be adjusted in a way that len(buf) == 0, cap(buf) == cap(buf). -// -// Deprecated: this function is only used internally, and will be removed in the next release. -func NewBytesPipe() *BytesPipe { - bp := &BytesPipe{} - bp.buf = append(bp.buf, getBuffer(minCap)) - bp.wait = sync.NewCond(&bp.mu) - return bp -} - -// Write writes p to BytesPipe. -// It can allocate new []byte slices in a process of writing. -func (bp *BytesPipe) Write(p []byte) (int, error) { - bp.mu.Lock() - defer bp.mu.Unlock() - - written := 0 -loop0: - for { - if bp.closeErr != nil { - return written, ErrClosed - } - - if len(bp.buf) == 0 { - bp.buf = append(bp.buf, getBuffer(64)) - } - // get the last buffer - b := bp.buf[len(bp.buf)-1] - - n, err := b.Write(p) - written += n - bp.bufLen += n - - // errBufferFull is an error we expect to get if the buffer is full - if err != nil && err != errBufferFull { - bp.wait.Broadcast() - return written, err - } - - // if there was enough room to write all then break - if len(p) == n { - break - } - - // more data: write to the next slice - p = p[n:] - - // make sure the buffer doesn't grow too big from this write - for bp.bufLen >= blockThreshold { - if bp.readBlock { - bp.wait.Broadcast() - } - bp.wait.Wait() - if bp.closeErr != nil { - continue loop0 - } - } - - // add new byte slice to the buffers slice and continue writing - nextCap := b.Cap() * 2 - if nextCap > maxCap { - nextCap = maxCap - } - bp.buf = append(bp.buf, getBuffer(nextCap)) - } - bp.wait.Broadcast() - return written, nil -} - -// CloseWithError causes further reads from a BytesPipe to return immediately. -func (bp *BytesPipe) CloseWithError(err error) error { - bp.mu.Lock() - if err != nil { - bp.closeErr = err - } else { - bp.closeErr = io.EOF - } - bp.wait.Broadcast() - bp.mu.Unlock() - return nil -} - -// Close causes further reads from a BytesPipe to return immediately. -func (bp *BytesPipe) Close() error { - return bp.CloseWithError(nil) -} - -// Read reads bytes from BytesPipe. -// Data could be read only once. -func (bp *BytesPipe) Read(p []byte) (n int, err error) { - bp.mu.Lock() - defer bp.mu.Unlock() - if bp.bufLen == 0 { - if bp.closeErr != nil { - return 0, bp.closeErr - } - bp.readBlock = true - bp.wait.Wait() - bp.readBlock = false - if bp.bufLen == 0 && bp.closeErr != nil { - return 0, bp.closeErr - } - } - - for bp.bufLen > 0 { - b := bp.buf[0] - read, _ := b.Read(p) // ignore error since fixedBuffer doesn't really return an error - n += read - bp.bufLen -= read - - if b.Len() == 0 { - // it's empty so return it to the pool and move to the next one - returnBuffer(b) - bp.buf[0] = nil - bp.buf = bp.buf[1:] - } - - if len(p) == read { - break - } - - p = p[read:] - } - - bp.wait.Broadcast() - return -} - -func returnBuffer(b *fixedBuffer) { - b.Reset() - bufPoolsLock.Lock() - pool := bufPools[b.Cap()] - bufPoolsLock.Unlock() - if pool != nil { - pool.Put(b) - } -} - -func getBuffer(size int) *fixedBuffer { - bufPoolsLock.Lock() - pool, ok := bufPools[size] - if !ok { - pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }} - bufPools[size] = pool - } - bufPoolsLock.Unlock() - return pool.Get().(*fixedBuffer) -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go deleted file mode 100644 index 05da97b0e4..0000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go +++ /dev/null @@ -1,163 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "io" - "os" - "path/filepath" -) - -// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a -// temporary file and closing it atomically changes the temporary file to -// destination path. Writing and closing concurrently is not allowed. -// NOTE: umask is not considered for the file's permissions. -func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { - f, err := os.CreateTemp(filepath.Dir(filename), ".tmp-"+filepath.Base(filename)) - if err != nil { - return nil, err - } - - abspath, err := filepath.Abs(filename) - if err != nil { - return nil, err - } - return &atomicFileWriter{ - f: f, - fn: abspath, - perm: perm, - }, nil -} - -// AtomicWriteFile atomically writes data to a file named by filename and with the specified permission bits. -// NOTE: umask is not considered for the file's permissions. -func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { - f, err := NewAtomicFileWriter(filename, perm) - if err != nil { - return err - } - n, err := f.Write(data) - if err == nil && n < len(data) { - err = io.ErrShortWrite - f.(*atomicFileWriter).writeErr = err - } - if err1 := f.Close(); err == nil { - err = err1 - } - return err -} - -type atomicFileWriter struct { - f *os.File - fn string - writeErr error - perm os.FileMode -} - -func (w *atomicFileWriter) Write(dt []byte) (int, error) { - n, err := w.f.Write(dt) - if err != nil { - w.writeErr = err - } - return n, err -} - -func (w *atomicFileWriter) Close() (retErr error) { - defer func() { - if retErr != nil || w.writeErr != nil { - os.Remove(w.f.Name()) - } - }() - if err := w.f.Sync(); err != nil { - w.f.Close() - return err - } - if err := w.f.Close(); err != nil { - return err - } - if err := os.Chmod(w.f.Name(), w.perm); err != nil { - return err - } - if w.writeErr == nil { - return os.Rename(w.f.Name(), w.fn) - } - return nil -} - -// AtomicWriteSet is used to atomically write a set -// of files and ensure they are visible at the same time. -// Must be committed to a new directory. -type AtomicWriteSet struct { - root string -} - -// NewAtomicWriteSet creates a new atomic write set to -// atomically create a set of files. The given directory -// is used as the base directory for storing files before -// commit. If no temporary directory is given the system -// default is used. -func NewAtomicWriteSet(tmpDir string) (*AtomicWriteSet, error) { - td, err := os.MkdirTemp(tmpDir, "write-set-") - if err != nil { - return nil, err - } - - return &AtomicWriteSet{ - root: td, - }, nil -} - -// WriteFile writes a file to the set, guaranteeing the file -// has been synced. -func (ws *AtomicWriteSet) WriteFile(filename string, data []byte, perm os.FileMode) error { - f, err := ws.FileWriter(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) - if err != nil { - return err - } - n, err := f.Write(data) - if err == nil && n < len(data) { - err = io.ErrShortWrite - } - if err1 := f.Close(); err == nil { - err = err1 - } - return err -} - -type syncFileCloser struct { - *os.File -} - -func (w syncFileCloser) Close() error { - err := w.File.Sync() - if err1 := w.File.Close(); err == nil { - err = err1 - } - return err -} - -// FileWriter opens a file writer inside the set. The file -// should be synced and closed before calling commit. -func (ws *AtomicWriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.WriteCloser, error) { - f, err := os.OpenFile(filepath.Join(ws.root, name), flag, perm) - if err != nil { - return nil, err - } - return syncFileCloser{f}, nil -} - -// Cancel cancels the set and removes all temporary data -// created in the set. -func (ws *AtomicWriteSet) Cancel() error { - return os.RemoveAll(ws.root) -} - -// Commit moves all created files to the target directory. The -// target directory must not exist and the parent of the target -// directory must exist. -func (ws *AtomicWriteSet) Commit(target string) error { - return os.Rename(ws.root, target) -} - -// String returns the location the set is writing to. -func (ws *AtomicWriteSet) String() string { - return ws.root -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers.go b/vendor/github.com/docker/docker/pkg/ioutils/readers.go deleted file mode 100644 index e03d3fee75..0000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/readers.go +++ /dev/null @@ -1,172 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "context" - "io" - "runtime/debug" - "sync/atomic" - - // make sure crypto.SHA256, crypto.sha512 and crypto.SHA384 are registered - // TODO remove once https://github.com/opencontainers/go-digest/pull/64 is merged. - _ "crypto/sha256" - _ "crypto/sha512" - - "github.com/containerd/log" -) - -// ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser -// It calls the given callback function when closed. It should be constructed -// with NewReadCloserWrapper -type ReadCloserWrapper struct { - io.Reader - closer func() error - closed atomic.Bool -} - -// Close calls back the passed closer function -func (r *ReadCloserWrapper) Close() error { - if !r.closed.CompareAndSwap(false, true) { - subsequentCloseWarn("ReadCloserWrapper") - return nil - } - return r.closer() -} - -// NewReadCloserWrapper returns a new io.ReadCloser. -func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { - return &ReadCloserWrapper{ - Reader: r, - closer: closer, - } -} - -type readerErrWrapper struct { - reader io.Reader - closer func() -} - -func (r *readerErrWrapper) Read(p []byte) (int, error) { - n, err := r.reader.Read(p) - if err != nil { - r.closer() - } - return n, err -} - -// NewReaderErrWrapper returns a new io.Reader. -func NewReaderErrWrapper(r io.Reader, closer func()) io.Reader { - return &readerErrWrapper{ - reader: r, - closer: closer, - } -} - -// OnEOFReader wraps an io.ReadCloser and a function -// the function will run at the end of file or close the file. -type OnEOFReader struct { - Rc io.ReadCloser - Fn func() -} - -func (r *OnEOFReader) Read(p []byte) (n int, err error) { - n, err = r.Rc.Read(p) - if err == io.EOF { - r.runFunc() - } - return -} - -// Close closes the file and run the function. -func (r *OnEOFReader) Close() error { - err := r.Rc.Close() - r.runFunc() - return err -} - -func (r *OnEOFReader) runFunc() { - if fn := r.Fn; fn != nil { - fn() - r.Fn = nil - } -} - -// cancelReadCloser wraps an io.ReadCloser with a context for cancelling read -// operations. -type cancelReadCloser struct { - cancel func() - pR *io.PipeReader // Stream to read from - pW *io.PipeWriter - closed atomic.Bool -} - -// NewCancelReadCloser creates a wrapper that closes the ReadCloser when the -// context is cancelled. The returned io.ReadCloser must be closed when it is -// no longer needed. -func NewCancelReadCloser(ctx context.Context, in io.ReadCloser) io.ReadCloser { - pR, pW := io.Pipe() - - // Create a context used to signal when the pipe is closed - doneCtx, cancel := context.WithCancel(context.Background()) - - p := &cancelReadCloser{ - cancel: cancel, - pR: pR, - pW: pW, - } - - go func() { - _, err := io.Copy(pW, in) - select { - case <-ctx.Done(): - // If the context was closed, p.closeWithError - // was already called. Calling it again would - // change the error that Read returns. - default: - p.closeWithError(err) - } - in.Close() - }() - go func() { - for { - select { - case <-ctx.Done(): - p.closeWithError(ctx.Err()) - case <-doneCtx.Done(): - return - } - } - }() - - return p -} - -// Read wraps the Read method of the pipe that provides data from the wrapped -// ReadCloser. -func (p *cancelReadCloser) Read(buf []byte) (n int, err error) { - return p.pR.Read(buf) -} - -// closeWithError closes the wrapper and its underlying reader. It will -// cause future calls to Read to return err. -func (p *cancelReadCloser) closeWithError(err error) { - p.pW.CloseWithError(err) - p.cancel() -} - -// Close closes the wrapper its underlying reader. It will cause -// future calls to Read to return io.EOF. -func (p *cancelReadCloser) Close() error { - if !p.closed.CompareAndSwap(false, true) { - subsequentCloseWarn("cancelReadCloser") - return nil - } - p.closeWithError(io.EOF) - return nil -} - -func subsequentCloseWarn(name string) { - log.G(context.TODO()).Error("subsequent attempt to close " + name) - if log.GetLevel() >= log.DebugLevel { - log.G(context.TODO()).Errorf("stack trace: %s", string(debug.Stack())) - } -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go deleted file mode 100644 index d8a8893ff1..0000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go +++ /dev/null @@ -1,98 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "io" - "sync" -) - -// WriteFlusher wraps the Write and Flush operation ensuring that every write -// is a flush. In addition, the Close method can be called to intercept -// Read/Write calls if the targets lifecycle has already ended. -type WriteFlusher struct { - w io.Writer - flusher flusher - flushed chan struct{} - flushedOnce sync.Once - closed chan struct{} - closeLock sync.Mutex -} - -type flusher interface { - Flush() -} - -var errWriteFlusherClosed = io.EOF - -func (wf *WriteFlusher) Write(b []byte) (n int, err error) { - select { - case <-wf.closed: - return 0, errWriteFlusherClosed - default: - } - - n, err = wf.w.Write(b) - wf.Flush() // every write is a flush. - return n, err -} - -// Flush the stream immediately. -func (wf *WriteFlusher) Flush() { - select { - case <-wf.closed: - return - default: - } - - wf.flushedOnce.Do(func() { - close(wf.flushed) - }) - wf.flusher.Flush() -} - -// Flushed returns the state of flushed. -// If it's flushed, return true, or else it return false. -func (wf *WriteFlusher) Flushed() bool { - // BUG(stevvooe): Remove this method. Its use is inherently racy. Seems to - // be used to detect whether or a response code has been issued or not. - // Another hook should be used instead. - var flushed bool - select { - case <-wf.flushed: - flushed = true - default: - } - return flushed -} - -// Close closes the write flusher, disallowing any further writes to the -// target. After the flusher is closed, all calls to write or flush will -// result in an error. -func (wf *WriteFlusher) Close() error { - wf.closeLock.Lock() - defer wf.closeLock.Unlock() - - select { - case <-wf.closed: - return errWriteFlusherClosed - default: - close(wf.closed) - } - return nil -} - -// nopFlusher represents a type which flush operation is nop. -type nopFlusher struct{} - -// Flush is a nop operation. -func (f *nopFlusher) Flush() {} - -// NewWriteFlusher returns a new WriteFlusher. -func NewWriteFlusher(w io.Writer) *WriteFlusher { - var fl flusher - if f, ok := w.(flusher); ok { - fl = f - } else { - fl = &nopFlusher{} - } - return &WriteFlusher{w: w, flusher: fl, closed: make(chan struct{}), flushed: make(chan struct{})} -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers.go b/vendor/github.com/docker/docker/pkg/ioutils/writers.go deleted file mode 100644 index aec8b4c03e..0000000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/writers.go +++ /dev/null @@ -1,81 +0,0 @@ -package ioutils // import "github.com/docker/docker/pkg/ioutils" - -import ( - "io" - "sync/atomic" -) - -// NopWriter represents a type which write operation is nop. -// -// Deprecated: use [io.Discard] instead. This type will be removed in the next release. -type NopWriter struct{} - -func (*NopWriter) Write(buf []byte) (int, error) { - return len(buf), nil -} - -type nopWriteCloser struct { - io.Writer -} - -func (w *nopWriteCloser) Close() error { return nil } - -// NopWriteCloser returns a nopWriteCloser. -// -// Deprecated: This function is no longer used and will be removed in the next release. -func NopWriteCloser(w io.Writer) io.WriteCloser { - return &nopWriteCloser{w} -} - -// NopFlusher represents a type which flush operation is nop. -// -// Deprecated: NopFlusher is only used internally and will be removed in the next release. -type NopFlusher = nopFlusher - -type writeCloserWrapper struct { - io.Writer - closer func() error - closed atomic.Bool -} - -func (r *writeCloserWrapper) Close() error { - if !r.closed.CompareAndSwap(false, true) { - subsequentCloseWarn("WriteCloserWrapper") - return nil - } - return r.closer() -} - -// NewWriteCloserWrapper returns a new io.WriteCloser. -func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser { - return &writeCloserWrapper{ - Writer: r, - closer: closer, - } -} - -// WriteCounter wraps a concrete io.Writer and hold a count of the number -// of bytes written to the writer during a "session". -// This can be convenient when write return is masked -// (e.g., json.Encoder.Encode()) -// -// Deprecated: this type is no longer used and will be removed in the next release. -type WriteCounter struct { - Count int64 - Writer io.Writer -} - -// NewWriteCounter returns a new WriteCounter. -// -// Deprecated: this function is no longer used and will be removed in the next release. -func NewWriteCounter(w io.Writer) *WriteCounter { - return &WriteCounter{ - Writer: w, - } -} - -func (wc *WriteCounter) Write(p []byte) (count int, err error) { - count, err = wc.Writer.Write(p) - wc.Count += int64(count) - return -} diff --git a/vendor/github.com/docker/docker/registry/auth.go b/vendor/github.com/docker/docker/registry/auth.go index 905ccf5f51..8c62b83c07 100644 --- a/vendor/github.com/docker/docker/registry/auth.go +++ b/vendor/github.com/docker/docker/registry/auth.go @@ -66,23 +66,23 @@ func (scs staticCredentialStore) SetRefreshToken(*url.URL, string, string) { // loginV2 tries to login to the v2 registry server. The given registry // endpoint will be pinged to get authorization challenges. These challenges // will be used to authenticate against the registry to validate credentials. -func loginV2(authConfig *registry.AuthConfig, endpoint APIEndpoint, userAgent string) (string, string, error) { - var ( - endpointStr = strings.TrimRight(endpoint.URL.String(), "/") + "/v2/" - modifiers = Headers(userAgent, nil) - authTransport = transport.NewTransport(newTransport(endpoint.TLSConfig), modifiers...) - credentialAuthConfig = *authConfig - creds = loginCredentialStore{authConfig: &credentialAuthConfig} - ) - +func loginV2(authConfig *registry.AuthConfig, endpoint APIEndpoint, userAgent string) (status string, token string, _ error) { + endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/" log.G(context.TODO()).Debugf("attempting v2 login to registry endpoint %s", endpointStr) - loginClient, err := v2AuthHTTPClient(endpoint.URL, authTransport, modifiers, creds, nil) + req, err := http.NewRequest(http.MethodGet, endpointStr, nil) if err != nil { return "", "", err } - req, err := http.NewRequest(http.MethodGet, endpointStr, nil) + var ( + modifiers = Headers(userAgent, nil) + authTrans = transport.NewTransport(newTransport(endpoint.TLSConfig), modifiers...) + credentialAuthConfig = *authConfig + creds = loginCredentialStore{authConfig: &credentialAuthConfig} + ) + + loginClient, err := v2AuthHTTPClient(endpoint.URL, authTrans, modifiers, creds, nil) if err != nil { return "", "", err } @@ -133,12 +133,13 @@ func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifi // files). func ConvertToHostname(url string) string { stripped := url - if strings.HasPrefix(url, "http://") { - stripped = strings.TrimPrefix(url, "http://") - } else if strings.HasPrefix(url, "https://") { - stripped = strings.TrimPrefix(url, "https://") + if strings.HasPrefix(stripped, "http://") { + stripped = strings.TrimPrefix(stripped, "http://") + } else if strings.HasPrefix(stripped, "https://") { + stripped = strings.TrimPrefix(stripped, "https://") } - return strings.SplitN(stripped, "/", 2)[0] + stripped, _, _ = strings.Cut(stripped, "/") + return stripped } // ResolveAuthConfig matches an auth configuration to a server address or a URL diff --git a/vendor/github.com/docker/docker/registry/config.go b/vendor/github.com/docker/docker/registry/config.go index e1b0a0ca14..f8d94ce806 100644 --- a/vendor/github.com/docker/docker/registry/config.go +++ b/vendor/github.com/docker/docker/registry/config.go @@ -4,20 +4,21 @@ import ( "context" "net" "net/url" - "regexp" "strconv" "strings" "github.com/containerd/log" "github.com/distribution/reference" "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/internal/lazyregexp" ) // ServiceOptions holds command line options. type ServiceOptions struct { - AllowNondistributableArtifacts []string `json:"allow-nondistributable-artifacts,omitempty"` - Mirrors []string `json:"registry-mirrors,omitempty"` - InsecureRegistries []string `json:"insecure-registries,omitempty"` + AllowNondistributableArtifacts []string `json:"allow-nondistributable-artifacts,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. + + Mirrors []string `json:"registry-mirrors,omitempty"` + InsecureRegistries []string `json:"insecure-registries,omitempty"` } // serviceConfig holds daemon configuration for the registry service. @@ -56,10 +57,7 @@ var ( } emptyServiceConfig, _ = newServiceConfig(ServiceOptions{}) - validHostPortRegex = regexp.MustCompile(`^` + reference.DomainRegexp.String() + `$`) - - // for mocking in unit tests - lookupIP = net.LookupIP + validHostPortRegex = lazyregexp.New(`^` + reference.DomainRegexp.String() + `$`) // certsDir is used to override defaultCertsDir. certsDir string @@ -83,9 +81,6 @@ func CertsDir() string { // newServiceConfig returns a new instance of ServiceConfig func newServiceConfig(options ServiceOptions) (*serviceConfig, error) { config := &serviceConfig{} - if err := config.loadAllowNondistributableArtifacts(options.AllowNondistributableArtifacts); err != nil { - return nil, err - } if err := config.loadMirrors(options.Mirrors); err != nil { return nil, err } @@ -103,51 +98,12 @@ func (config *serviceConfig) copy() *registry.ServiceConfig { ic[key] = value } return ®istry.ServiceConfig{ - AllowNondistributableArtifactsCIDRs: append([]*registry.NetIPNet(nil), config.AllowNondistributableArtifactsCIDRs...), - AllowNondistributableArtifactsHostnames: append([]string(nil), config.AllowNondistributableArtifactsHostnames...), - InsecureRegistryCIDRs: append([]*registry.NetIPNet(nil), config.InsecureRegistryCIDRs...), - IndexConfigs: ic, - Mirrors: append([]string(nil), config.Mirrors...), + InsecureRegistryCIDRs: append([]*registry.NetIPNet(nil), config.InsecureRegistryCIDRs...), + IndexConfigs: ic, + Mirrors: append([]string(nil), config.Mirrors...), } } -// loadAllowNondistributableArtifacts loads allow-nondistributable-artifacts registries into config. -func (config *serviceConfig) loadAllowNondistributableArtifacts(registries []string) error { - cidrs := map[string]*registry.NetIPNet{} - hostnames := map[string]bool{} - - for _, r := range registries { - if _, err := ValidateIndexName(r); err != nil { - return err - } - if hasScheme(r) { - return invalidParamf("allow-nondistributable-artifacts registry %s should not contain '://'", r) - } - - if _, ipnet, err := net.ParseCIDR(r); err == nil { - // Valid CIDR. - cidrs[ipnet.String()] = (*registry.NetIPNet)(ipnet) - } else if err = validateHostPort(r); err == nil { - // Must be `host:port` if not CIDR. - hostnames[r] = true - } else { - return invalidParamWrapf(err, "allow-nondistributable-artifacts registry %s is not valid", r) - } - } - - config.AllowNondistributableArtifactsCIDRs = make([]*registry.NetIPNet, 0, len(cidrs)) - for _, c := range cidrs { - config.AllowNondistributableArtifactsCIDRs = append(config.AllowNondistributableArtifactsCIDRs, c) - } - - config.AllowNondistributableArtifactsHostnames = make([]string, 0, len(hostnames)) - for h := range hostnames { - config.AllowNondistributableArtifactsHostnames = append(config.AllowNondistributableArtifactsHostnames, h) - } - - return nil -} - // loadMirrors loads mirrors to config, after removing duplicates. // Returns an error if mirrors contains an invalid mirror. func (config *serviceConfig) loadMirrors(mirrors []string) error { @@ -184,7 +140,7 @@ func (config *serviceConfig) loadMirrors(mirrors []string) error { func (config *serviceConfig) loadInsecureRegistries(registries []string) error { // Localhost is by default considered as an insecure registry. This is a // stop-gap for people who are running a private registry on localhost. - registries = append(registries, "127.0.0.0/8") + registries = append(registries, "::1/128", "127.0.0.0/8") var ( insecureRegistryCIDRs = make([]*registry.NetIPNet, 0) @@ -245,25 +201,6 @@ skip: return nil } -// allowNondistributableArtifacts returns true if the provided hostname is part of the list of registries -// that allow push of nondistributable artifacts. -// -// The list can contain elements with CIDR notation to specify a whole subnet. If the subnet contains an IP -// of the registry specified by hostname, true is returned. -// -// hostname should be a URL.Host (`host:port` or `host`) where the `host` part can be either a domain name -// or an IP address. If it is a domain name, then it will be resolved to IP addresses for matching. If -// resolution fails, CIDR matching is not performed. -func (config *serviceConfig) allowNondistributableArtifacts(hostname string) bool { - for _, h := range config.AllowNondistributableArtifactsHostnames { - if h == hostname { - return true - } - } - - return isCIDRMatch(config.AllowNondistributableArtifactsCIDRs, hostname) -} - // isSecureIndex returns false if the provided indexName is part of the list of insecure registries // Insecure registries accept HTTP and/or accept HTTPS with certificates from unknown CAs. // @@ -285,30 +222,37 @@ func (config *serviceConfig) isSecureIndex(indexName string) bool { return !isCIDRMatch(config.InsecureRegistryCIDRs, indexName) } +// for mocking in unit tests. +var lookupIP = net.LookupIP + // isCIDRMatch returns true if URLHost matches an element of cidrs. URLHost is a URL.Host (`host:port` or `host`) // where the `host` part can be either a domain name or an IP address. If it is a domain name, then it will be // resolved to IP addresses for matching. If resolution fails, false is returned. func isCIDRMatch(cidrs []*registry.NetIPNet, URLHost string) bool { + if len(cidrs) == 0 { + return false + } + host, _, err := net.SplitHostPort(URLHost) if err != nil { - // Assume URLHost is of the form `host` without the port and go on. + // Assume URLHost is a host without port and go on. host = URLHost } - addrs, err := lookupIP(host) - if err != nil { - ip := net.ParseIP(host) - if ip != nil { - addrs = []net.IP{ip} + var addresses []net.IP + if ip := net.ParseIP(host); ip != nil { + // Host is an IP-address. + addresses = append(addresses, ip) + } else { + // Try to resolve the host's IP-address. + addresses, err = lookupIP(host) + if err != nil { + // We failed to resolve the host; assume there's no match. + return false } - - // if ip == nil, then `host` is neither an IP nor it could be looked up, - // either because the index is unreachable, or because the index is behind an HTTP proxy. - // So, len(addrs) == 0 and we're not aborting. } - // Try CIDR notation only if addrs has any elements, i.e. if `host`'s IP could be determined. - for _, addr := range addrs { + for _, addr := range addresses { for _, ipnet := range cidrs { // check if the addr falls in the subnet if (*net.IPNet)(ipnet).Contains(addr) { diff --git a/vendor/github.com/docker/docker/registry/registry.go b/vendor/github.com/docker/docker/registry/registry.go index 7866dcd0d8..6b079199dd 100644 --- a/vendor/github.com/docker/docker/registry/registry.go +++ b/vendor/github.com/docker/docker/registry/registry.go @@ -14,6 +14,7 @@ import ( "github.com/containerd/log" "github.com/docker/distribution/registry/client/transport" "github.com/docker/go-connections/tlsconfig" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) // HostCertsDir returns the config directory for a specific host. @@ -115,7 +116,7 @@ func Headers(userAgent string, metaHeaders http.Header) []transport.RequestModif // newTransport returns a new HTTP transport. If tlsConfig is nil, it uses the // default TLS configuration. -func newTransport(tlsConfig *tls.Config) *http.Transport { +func newTransport(tlsConfig *tls.Config) http.RoundTripper { if tlsConfig == nil { tlsConfig = tlsconfig.ServerDefault() } @@ -125,12 +126,14 @@ func newTransport(tlsConfig *tls.Config) *http.Transport { KeepAlive: 30 * time.Second, } - return &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: direct.DialContext, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: tlsConfig, - // TODO(dmcgowan): Call close idle connections when complete and use keep alive - DisableKeepAlives: true, - } + return otelhttp.NewTransport( + &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: direct.DialContext, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: tlsConfig, + // TODO(dmcgowan): Call close idle connections when complete and use keep alive + DisableKeepAlives: true, + }, + ) } diff --git a/vendor/github.com/docker/docker/registry/search_session.go b/vendor/github.com/docker/docker/registry/search_session.go index c334143c6b..a0d25c805e 100644 --- a/vendor/github.com/docker/docker/registry/search_session.go +++ b/vendor/github.com/docker/docker/registry/search_session.go @@ -6,6 +6,7 @@ import ( _ "crypto/sha512" "encoding/json" "fmt" + "io" "net/http" "net/http/cookiejar" "net/url" @@ -15,7 +16,6 @@ import ( "github.com/containerd/log" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/errdefs" - "github.com/docker/docker/pkg/ioutils" "github.com/pkg/errors" ) @@ -76,6 +76,35 @@ func cloneRequest(r *http.Request) *http.Request { return r2 } +// onEOFReader wraps an io.ReadCloser and a function +// the function will run at the end of file or close the file. +type onEOFReader struct { + Rc io.ReadCloser + Fn func() +} + +func (r *onEOFReader) Read(p []byte) (n int, err error) { + n, err = r.Rc.Read(p) + if err == io.EOF { + r.runFunc() + } + return +} + +// Close closes the file and run the function. +func (r *onEOFReader) Close() error { + err := r.Rc.Close() + r.runFunc() + return err +} + +func (r *onEOFReader) runFunc() { + if fn := r.Fn; fn != nil { + fn() + r.Fn = nil + } +} + // RoundTrip changes an HTTP request's headers to add the necessary // authentication-related headers func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { @@ -119,7 +148,7 @@ func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { if len(resp.Header["X-Docker-Token"]) > 0 { tr.token = resp.Header["X-Docker-Token"] } - resp.Body = &ioutils.OnEOFReader{ + resp.Body = &onEOFReader{ Rc: resp.Body, Fn: func() { tr.mu.Lock() diff --git a/vendor/github.com/docker/docker/registry/service.go b/vendor/github.com/docker/docker/registry/service.go index 6881c11057..4d66523c61 100644 --- a/vendor/github.com/docker/docker/registry/service.go +++ b/vendor/github.com/docker/docker/registry/service.go @@ -68,10 +68,11 @@ func (s *Service) Auth(ctx context.Context, authConfig *registry.AuthConfig, use registryHostName = u.Host } - // Lookup endpoints for authentication using "LookupPushEndpoints", which - // excludes mirrors to prevent sending credentials of the upstream registry - // to a mirror. - endpoints, err := s.LookupPushEndpoints(registryHostName) + // Lookup endpoints for authentication but exclude mirrors to prevent + // sending credentials of the upstream registry to a mirror. + s.mu.RLock() + endpoints, err := s.lookupV2Endpoints(registryHostName, false) + s.mu.RUnlock() if err != nil { return "", "", invalidParam(err) } @@ -103,10 +104,9 @@ func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, erro type APIEndpoint struct { Mirror bool URL *url.URL - Version APIVersion // Deprecated: v1 registries are deprecated, and endpoints are always v2. - AllowNondistributableArtifacts bool + AllowNondistributableArtifacts bool // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. Official bool - TrimHostname bool + TrimHostname bool // Deprecated: hostname is now trimmed unconditionally for remote names. This field will be removed in the next release. TLSConfig *tls.Config } @@ -116,7 +116,7 @@ func (s *Service) LookupPullEndpoints(hostname string) (endpoints []APIEndpoint, s.mu.RLock() defer s.mu.RUnlock() - return s.lookupV2Endpoints(hostname) + return s.lookupV2Endpoints(hostname, true) } // LookupPushEndpoints creates a list of v2 endpoints to try to push to, in order of preference. @@ -125,15 +125,7 @@ func (s *Service) LookupPushEndpoints(hostname string) (endpoints []APIEndpoint, s.mu.RLock() defer s.mu.RUnlock() - allEndpoints, err := s.lookupV2Endpoints(hostname) - if err == nil { - for _, endpoint := range allEndpoints { - if !endpoint.Mirror { - endpoints = append(endpoints, endpoint) - } - } - } - return endpoints, err + return s.lookupV2Endpoints(hostname, false) } // IsInsecureRegistry returns true if the registry at given host is configured as diff --git a/vendor/github.com/docker/docker/registry/service_v2.go b/vendor/github.com/docker/docker/registry/service_v2.go index 5d09e11c9c..43754527a2 100644 --- a/vendor/github.com/docker/docker/registry/service_v2.go +++ b/vendor/github.com/docker/docker/registry/service_v2.go @@ -7,38 +7,33 @@ import ( "github.com/docker/go-connections/tlsconfig" ) -func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, err error) { - ana := s.config.allowNondistributableArtifacts(hostname) - +func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]APIEndpoint, error) { + var endpoints []APIEndpoint if hostname == DefaultNamespace || hostname == IndexHostname { - for _, mirror := range s.config.Mirrors { - if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { - mirror = "https://" + mirror - } - mirrorURL, err := url.Parse(mirror) - if err != nil { - return nil, invalidParam(err) - } - mirrorTLSConfig, err := newTLSConfig(mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host)) - if err != nil { - return nil, err + if includeMirrors { + for _, mirror := range s.config.Mirrors { + if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { + mirror = "https://" + mirror + } + mirrorURL, err := url.Parse(mirror) + if err != nil { + return nil, invalidParam(err) + } + mirrorTLSConfig, err := newTLSConfig(mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host)) + if err != nil { + return nil, err + } + endpoints = append(endpoints, APIEndpoint{ + URL: mirrorURL, + Mirror: true, + TLSConfig: mirrorTLSConfig, + }) } - endpoints = append(endpoints, APIEndpoint{ - URL: mirrorURL, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - Mirror: true, - TrimHostname: true, - TLSConfig: mirrorTLSConfig, - }) } endpoints = append(endpoints, APIEndpoint{ - URL: DefaultV2Registry, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - Official: true, - TrimHostname: true, - TLSConfig: tlsconfig.ServerDefault(), - - AllowNondistributableArtifacts: ana, + URL: DefaultV2Registry, + Official: true, + TLSConfig: tlsconfig.ServerDefault(), }) return endpoints, nil @@ -55,10 +50,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e Scheme: "https", Host: hostname, }, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - AllowNondistributableArtifacts: ana, - TrimHostname: true, - TLSConfig: tlsConfig, + TLSConfig: tlsConfig, }, } @@ -68,9 +60,6 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e Scheme: "http", Host: hostname, }, - Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. - AllowNondistributableArtifacts: ana, - TrimHostname: true, // used to check if supposed to be secure via InsecureSkipVerify TLSConfig: tlsConfig, }) diff --git a/vendor/github.com/docker/docker/registry/types.go b/vendor/github.com/docker/docker/registry/types.go index 4926580a6c..02d7f4f383 100644 --- a/vendor/github.com/docker/docker/registry/types.go +++ b/vendor/github.com/docker/docker/registry/types.go @@ -5,27 +5,6 @@ import ( "github.com/docker/docker/api/types/registry" ) -// APIVersion is an integral representation of an API version (presently -// either 1 or 2) -// -// Deprecated: v1 registries are deprecated, and endpoints are always v2. -type APIVersion int - -func (av APIVersion) String() string { - return apiVersions[av] -} - -// API Version identifiers. -const ( - APIVersion1 APIVersion = 1 // Deprecated: v1 registries are deprecated, and endpoints are always v2. - APIVersion2 APIVersion = 2 // Deprecated: v1 registries are deprecated, and endpoints are always v2. -) - -var apiVersions = map[APIVersion]string{ - APIVersion1: "v1", - APIVersion2: "v2", -} - // RepositoryInfo describes a repository type RepositoryInfo struct { Name reference.Named diff --git a/vendor/github.com/go-openapi/errors/.golangci.yml b/vendor/github.com/go-openapi/errors/.golangci.yml index cf88ead324..ee8b9bd1f1 100644 --- a/vendor/github.com/go-openapi/errors/.golangci.yml +++ b/vendor/github.com/go-openapi/errors/.golangci.yml @@ -1,12 +1,6 @@ linters-settings: - govet: - check-shadowing: true - golint: - min-confidence: 0 gocyclo: min-complexity: 45 - maligned: - suggest-new: true dupl: threshold: 200 goconst: @@ -16,8 +10,6 @@ linters-settings: linters: enable-all: true disable: - - errname # this repo doesn't follow the convention advised by this linter - - maligned - unparam - lll - gochecknoinits @@ -30,9 +22,6 @@ linters: - wrapcheck - testpackage - nlreturn - - gomnd - - exhaustivestruct - - goerr113 - errorlint - nestif - godot @@ -40,7 +29,6 @@ linters: - paralleltest - tparallel - thelper - - ifshort - exhaustruct - varnamelen - gci @@ -53,10 +41,15 @@ linters: - forcetypeassert - cyclop # deprecated linters - - deadcode - - interfacer - - scopelint - - varcheck - - structcheck - - golint - - nosnakecase + #- deadcode + #- interfacer + #- scopelint + #- varcheck + #- structcheck + #- golint + #- nosnakecase + #- maligned + #- goerr113 + #- ifshort + #- gomnd + #- exhaustivestruct diff --git a/vendor/github.com/go-openapi/errors/api.go b/vendor/github.com/go-openapi/errors/api.go index 5320cb9630..d6f507f42d 100644 --- a/vendor/github.com/go-openapi/errors/api.go +++ b/vendor/github.com/go-openapi/errors/api.go @@ -185,7 +185,7 @@ func ServeError(rw http.ResponseWriter, r *http.Request, err error) { } func asHTTPCode(input int) int { - if input >= 600 { + if input >= maximumValidHTTPCode { return DefaultHTTPCode } return input diff --git a/vendor/github.com/go-openapi/errors/headers.go b/vendor/github.com/go-openapi/errors/headers.go index dfebe8f95f..6ea1151f41 100644 --- a/vendor/github.com/go-openapi/errors/headers.go +++ b/vendor/github.com/go-openapi/errors/headers.go @@ -21,7 +21,7 @@ import ( ) // Validation represents a failure of a precondition -type Validation struct { +type Validation struct { //nolint: errname code int32 Name string In string diff --git a/vendor/github.com/go-openapi/errors/middleware.go b/vendor/github.com/go-openapi/errors/middleware.go index 963472d1f3..67f80386a2 100644 --- a/vendor/github.com/go-openapi/errors/middleware.go +++ b/vendor/github.com/go-openapi/errors/middleware.go @@ -22,7 +22,7 @@ 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 { +type APIVerificationFailed struct { //nolint: errname Section string `json:"section,omitempty"` MissingSpecification []string `json:"missingSpecification,omitempty"` MissingRegistration []string `json:"missingRegistration,omitempty"` diff --git a/vendor/github.com/go-openapi/errors/parsing.go b/vendor/github.com/go-openapi/errors/parsing.go index 5096e1ea7b..ce1ef9cb67 100644 --- a/vendor/github.com/go-openapi/errors/parsing.go +++ b/vendor/github.com/go-openapi/errors/parsing.go @@ -17,6 +17,7 @@ package errors import ( "encoding/json" "fmt" + "net/http" ) // ParseError represents a parsing error @@ -68,7 +69,7 @@ func NewParseError(name, in, value string, reason error) *ParseError { msg = fmt.Sprintf(parseErrorTemplContent, name, in, value, reason) } return &ParseError{ - code: 400, + code: http.StatusBadRequest, Name: name, In: in, Value: value, diff --git a/vendor/github.com/go-openapi/errors/schema.go b/vendor/github.com/go-openapi/errors/schema.go index cf7ac2ed4d..8f3239dfd9 100644 --- a/vendor/github.com/go-openapi/errors/schema.go +++ b/vendor/github.com/go-openapi/errors/schema.go @@ -17,6 +17,7 @@ package errors import ( "encoding/json" "fmt" + "net/http" "strings" ) @@ -32,12 +33,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 +50,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 +70,17 @@ 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 const ( // CompositeErrorCode remains 422 for backwards-compatibility // and to separate it from validation errors with cause - CompositeErrorCode = 422 + CompositeErrorCode = http.StatusUnprocessableEntity + // InvalidTypeCode is used for any subclass of invalid types - InvalidTypeCode = 600 + iota + InvalidTypeCode = maximumValidHTTPCode + iota RequiredFailCode TooLongFailCode TooShortFailCode @@ -298,10 +302,10 @@ 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) +func TooManyItems(name, in string, maximum int64, value interface{}) *Validation { + msg := fmt.Sprintf(maximumItemsFail, name, in, maximum) if in == "" { - msg = fmt.Sprintf(maxItemsFailNoIn, name, max) + msg = fmt.Sprintf(maximumItemsFailNoIn, name, maximum) } return &Validation{ @@ -314,10 +318,10 @@ 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) +func TooFewItems(name, in string, minimum int64, value interface{}) *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 +332,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 maximumimum validation fails +func ExceedsMaximumInt(name, in string, maximum int64, exclusive bool, value interface{}) *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 +357,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 maximumimum validation fails +func ExceedsMaximumUint(name, in string, maximum uint64, exclusive bool, value interface{}) *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 +382,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 maximumimum validation fails +func ExceedsMaximum(name, in string, maximum float64, exclusive bool, value interface{}) *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, @@ -404,20 +408,20 @@ 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 { +func ExceedsMinimumInt(name, in string, minimum int64, exclusive bool, value interface{}) *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, @@ -429,20 +433,20 @@ 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 { +func ExceedsMinimumUint(name, in string, minimum uint64, exclusive bool, value interface{}) *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, @@ -454,20 +458,20 @@ 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 { +func ExceedsMinimum(name, in string, minimum float64, exclusive bool, value interface{}) *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, @@ -549,12 +553,12 @@ 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 { +func TooLong(name, in string, maximum int64, value interface{}) *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, @@ -566,12 +570,12 @@ 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 { +func TooShort(name, in string, minimum int64, value interface{}) *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{ diff --git a/vendor/github.com/go-openapi/swag/.golangci.yml b/vendor/github.com/go-openapi/swag/.golangci.yml index 80e2be0042..d2fafb8a2b 100644 --- a/vendor/github.com/go-openapi/swag/.golangci.yml +++ b/vendor/github.com/go-openapi/swag/.golangci.yml @@ -1,22 +1,17 @@ linters-settings: - govet: - check-shadowing: true - golint: - min-confidence: 0 gocyclo: min-complexity: 45 - maligned: - suggest-new: true dupl: threshold: 200 goconst: - min-len: 3 + min-len: 2 min-occurrences: 3 linters: enable-all: true disable: - - maligned + - recvcheck + - unparam - lll - gochecknoinits - gochecknoglobals @@ -28,9 +23,6 @@ linters: - wrapcheck - testpackage - nlreturn - - gomnd - - exhaustivestruct - - goerr113 - errorlint - nestif - godot @@ -38,7 +30,6 @@ linters: - paralleltest - tparallel - thelper - - ifshort - exhaustruct - varnamelen - gci @@ -51,10 +42,15 @@ linters: - forcetypeassert - cyclop # deprecated linters - - deadcode - - interfacer - - scopelint - - varcheck - - structcheck - - golint - - nosnakecase + #- deadcode + #- interfacer + #- scopelint + #- varcheck + #- structcheck + #- golint + #- nosnakecase + #- maligned + #- goerr113 + #- ifshort + #- gomnd + #- exhaustivestruct diff --git a/vendor/github.com/go-openapi/swag/errors.go b/vendor/github.com/go-openapi/swag/errors.go new file mode 100644 index 0000000000..6c67fbf92e --- /dev/null +++ b/vendor/github.com/go-openapi/swag/errors.go @@ -0,0 +1,15 @@ +package swag + +type swagError string + +const ( + // ErrYAML is an error raised by YAML utilities + ErrYAML swagError = "yaml error" + + // ErrLoader is an error raised by the file loader utility + ErrLoader swagError = "loader error" +) + +func (e swagError) Error() string { + return string(e) +} diff --git a/vendor/github.com/go-openapi/swag/json.go b/vendor/github.com/go-openapi/swag/json.go index 7e9902ca31..c7caa9908f 100644 --- a/vendor/github.com/go-openapi/swag/json.go +++ b/vendor/github.com/go-openapi/swag/json.go @@ -126,7 +126,8 @@ func ConcatJSON(blobs ...[]byte) []byte { continue // don't know how to concatenate non container objects } - if len(b) < 3 { // yep empty but also the last one, so closing this thing + const minLengthIfNotEmpty = 3 + if len(b) < minLengthIfNotEmpty { // yep empty but also the last one, so closing this thing if i == last && a > 0 { if err := buf.WriteByte(closing); err != nil { log.Println(err) diff --git a/vendor/github.com/go-openapi/swag/loading.go b/vendor/github.com/go-openapi/swag/loading.go index 783442fddf..658a24b789 100644 --- a/vendor/github.com/go-openapi/swag/loading.go +++ b/vendor/github.com/go-openapi/swag/loading.go @@ -168,7 +168,7 @@ func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) { } if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status) + return nil, fmt.Errorf("could not access document at %q [%s]: %w", path, resp.Status, ErrLoader) } return io.ReadAll(resp.Body) diff --git a/vendor/github.com/go-openapi/swag/yaml.go b/vendor/github.com/go-openapi/swag/yaml.go index f59e025932..575346539a 100644 --- a/vendor/github.com/go-openapi/swag/yaml.go +++ b/vendor/github.com/go-openapi/swag/yaml.go @@ -16,7 +16,6 @@ package swag import ( "encoding/json" - "errors" "fmt" "path/filepath" "reflect" @@ -51,7 +50,7 @@ func BytesToYAMLDoc(data []byte) (interface{}, error) { return nil, err } if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode { - return nil, errors.New("only YAML documents that are objects are supported") + return nil, fmt.Errorf("only YAML documents that are objects are supported: %w", ErrYAML) } return &document, nil } @@ -69,31 +68,32 @@ func yamlNode(root *yaml.Node) (interface{}, error) { case yaml.AliasNode: return yamlNode(root.Alias) default: - return nil, fmt.Errorf("unsupported YAML node type: %v", root.Kind) + return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML) } } func yamlDocument(node *yaml.Node) (interface{}, error) { if len(node.Content) != 1 { - return nil, fmt.Errorf("unexpected YAML Document node content length: %d", len(node.Content)) + return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML) } return yamlNode(node.Content[0]) } func yamlMapping(node *yaml.Node) (interface{}, error) { - m := make(JSONMapSlice, len(node.Content)/2) + const sensibleAllocDivider = 2 + m := make(JSONMapSlice, len(node.Content)/sensibleAllocDivider) var j int for i := 0; i < len(node.Content); i += 2 { var nmi JSONMapItem k, err := yamlStringScalarC(node.Content[i]) if err != nil { - return nil, fmt.Errorf("unable to decode YAML map key: %w", err) + return nil, fmt.Errorf("unable to decode YAML map key: %w: %w", err, ErrYAML) } nmi.Key = k v, err := yamlNode(node.Content[i+1]) if err != nil { - return nil, fmt.Errorf("unable to process YAML map value for key %q: %w", k, err) + return nil, fmt.Errorf("unable to process YAML map value for key %q: %w: %w", k, err, ErrYAML) } nmi.Value = v m[j] = nmi @@ -109,7 +109,7 @@ func yamlSequence(node *yaml.Node) (interface{}, error) { v, err := yamlNode(node.Content[i]) if err != nil { - return nil, fmt.Errorf("unable to decode YAML sequence value: %w", err) + return nil, fmt.Errorf("unable to decode YAML sequence value: %w: %w", err, ErrYAML) } s = append(s, v) } @@ -132,19 +132,19 @@ func yamlScalar(node *yaml.Node) (interface{}, error) { case yamlBoolScalar: b, err := strconv.ParseBool(node.Value) if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w", node.Value, err) + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w: %w", node.Value, err, ErrYAML) } return b, nil case yamlIntScalar: i, err := strconv.ParseInt(node.Value, 10, 64) if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w", node.Value, err) + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w: %w", node.Value, err, ErrYAML) } return i, nil case yamlFloatScalar: f, err := strconv.ParseFloat(node.Value, 64) if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w", node.Value, err) + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w: %w", node.Value, err, ErrYAML) } return f, nil case yamlTimestamp: @@ -152,19 +152,19 @@ func yamlScalar(node *yaml.Node) (interface{}, error) { case yamlNull: return nil, nil //nolint:nilnil default: - return nil, fmt.Errorf("YAML tag %q is not supported", node.LongTag()) + return nil, fmt.Errorf("YAML tag %q is not supported: %w", node.LongTag(), ErrYAML) } } func yamlStringScalarC(node *yaml.Node) (string, error) { if node.Kind != yaml.ScalarNode { - return "", fmt.Errorf("expecting a string scalar but got %q", node.Kind) + return "", fmt.Errorf("expecting a string scalar but got %q: %w", node.Kind, ErrYAML) } switch node.LongTag() { case yamlStringScalar, yamlIntScalar, yamlFloatScalar: return node.Value, nil default: - return "", fmt.Errorf("YAML tag %q is not supported as map key", node.LongTag()) + return "", fmt.Errorf("YAML tag %q is not supported as map key: %w", node.LongTag(), ErrYAML) } } @@ -349,7 +349,7 @@ func json2yaml(item interface{}) (*yaml.Node, error) { Value: strconv.FormatBool(val), }, nil default: - return nil, fmt.Errorf("unhandled type: %T", val) + return nil, fmt.Errorf("unhandled type: %T: %w", val, ErrYAML) } } @@ -416,7 +416,7 @@ func transformData(input interface{}) (out interface{}, err error) { case int64: return strconv.FormatInt(k, 10), nil default: - return "", fmt.Errorf("unexpected map key type, got: %T", k) + return "", fmt.Errorf("unexpected map key type, got: %T: %w", k, ErrYAML) } } diff --git a/vendor/github.com/sagikazarmark/slog-shim/.editorconfig b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig similarity index 86% rename from vendor/github.com/sagikazarmark/slog-shim/.editorconfig rename to vendor/github.com/go-viper/mapstructure/v2/.editorconfig index 1fb0e1bec6..1f664d13a5 100644 --- a/vendor/github.com/sagikazarmark/slog-shim/.editorconfig +++ b/vendor/github.com/go-viper/mapstructure/v2/.editorconfig @@ -8,11 +8,11 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -[*.nix] -indent_size = 2 +[*.go] +indent_style = tab [{Makefile,*.mk}] indent_style = tab -[Taskfile.yaml] +[*.nix] indent_size = 2 diff --git a/vendor/github.com/go-viper/mapstructure/v2/.gitignore b/vendor/github.com/go-viper/mapstructure/v2/.gitignore new file mode 100644 index 0000000000..470e7ca2bd --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/.gitignore @@ -0,0 +1,6 @@ +/.devenv/ +/.direnv/ +/.pre-commit-config.yaml +/bin/ +/build/ +/var/ diff --git a/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml new file mode 100644 index 0000000000..763143aa77 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/.golangci.yaml @@ -0,0 +1,23 @@ +run: + timeout: 5m + +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/go-viper/mapstructure) + golint: + min-confidence: 0 + goimports: + local-prefixes: github.com/go-viper/maptstructure + +linters: + disable-all: true + enable: + - gci + - gofmt + - gofumpt + - goimports + - staticcheck + # - stylecheck diff --git a/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md b/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md new file mode 100644 index 0000000000..afd44e5f5f --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/CHANGELOG.md @@ -0,0 +1,104 @@ +> [!WARNING] +> As of v2 of this library, change log can be found in GitHub releases. + +## 1.5.1 + +* Wrap errors so they're compatible with `errors.Is` and `errors.As` [GH-282] +* Fix map of slices not decoding properly in certain cases. [GH-266] + +## 1.5.0 + +* New option `IgnoreUntaggedFields` to ignore decoding to any fields + without `mapstructure` (or the configured tag name) set [GH-277] +* New option `ErrorUnset` which makes it an error if any fields + in a target struct are not set by the decoding process. [GH-225] +* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240] +* Decoding to slice from array no longer crashes [GH-265] +* Decode nested struct pointers to map [GH-271] +* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280] +* Fix issue where fields with `,omitempty` would sometimes decode + into a map with an empty string key [GH-281] + +## 1.4.3 + +* Fix cases where `json.Number` didn't decode properly [GH-261] + +## 1.4.2 + +* Custom name matchers to support any sort of casing, formatting, etc. for + field names. [GH-250] +* Fix possible panic in ComposeDecodeHookFunc [GH-251] + +## 1.4.1 + +* Fix regression where `*time.Time` value would be set to empty and not be sent + to decode hooks properly [GH-232] + +## 1.4.0 + +* A new decode hook type `DecodeHookFuncValue` has been added that has + access to the full values. [GH-183] +* Squash is now supported with embedded fields that are struct pointers [GH-205] +* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206] + +## 1.3.3 + +* Decoding maps from maps creates a settable value for decode hooks [GH-203] + +## 1.3.2 + +* Decode into interface type with a struct value is supported [GH-187] + +## 1.3.1 + +* Squash should only squash embedded structs. [GH-194] + +## 1.3.0 + +* Added `",omitempty"` support. This will ignore zero values in the source + structure when encoding. [GH-145] + +## 1.2.3 + +* Fix duplicate entries in Keys list with pointer values. [GH-185] + +## 1.2.2 + +* Do not add unsettable (unexported) values to the unused metadata key + or "remain" value. [GH-150] + +## 1.2.1 + +* Go modules checksum mismatch fix + +## 1.2.0 + +* Added support to capture unused values in a field using the `",remain"` value + in the mapstructure tag. There is an example to showcase usage. +* Added `DecoderConfig` option to always squash embedded structs +* `json.Number` can decode into `uint` types +* Empty slices are preserved and not replaced with nil slices +* Fix panic that can occur in when decoding a map into a nil slice of structs +* Improved package documentation for godoc + +## 1.1.2 + +* Fix error when decode hook decodes interface implementation into interface + type. [GH-140] + +## 1.1.1 + +* Fix panic that can happen in `decodePtr` + +## 1.1.0 + +* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133] +* Support struct to struct decoding [GH-137] +* If source map value is nil, then destination map value is nil (instead of empty) +* If source slice value is nil, then destination slice value is nil (instead of empty) +* If source pointer is nil, then destination pointer is set to nil (instead of + allocated zero value of type) + +## 1.0.0 + +* Initial tagged stable release. diff --git a/vendor/github.com/go-viper/mapstructure/v2/LICENSE b/vendor/github.com/go-viper/mapstructure/v2/LICENSE new file mode 100644 index 0000000000..f9c841a51e --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +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-viper/mapstructure/v2/README.md b/vendor/github.com/go-viper/mapstructure/v2/README.md new file mode 100644 index 0000000000..dd5ec69ddf --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/README.md @@ -0,0 +1,80 @@ +# mapstructure + +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?branch=main&style=flat-square)](https://github.com/go-viper/mapstructure/actions?query=workflow%3ACI) +[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.18-61CFDD.svg?style=flat-square) + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +```shell +go get github.com/go-viper/mapstructure/v2 +``` + +## Migrating from `github.com/mitchellh/mapstructure` + +[@mitchehllh](https://github.com/mitchellh) announced his intent to archive some of his unmaintained projects (see [here](https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc) and [here](https://github.com/mitchellh/mapstructure/issues/349)). This is a repository achieved the "blessed fork" status. + +You can migrate to this package by changing your import paths in your Go files to `github.com/go-viper/mapstructure/v2`. +The API is the same, so you don't need to change anything else. + +Here is a script that can help you with the migration: + +```shell +sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go') +``` + +If you need more time to migrate your code, that is absolutely fine. + +Some of the latest fixes are backported to the v1 release branch of this package, so you can use the Go modules `replace` feature until you are ready to migrate: + +```shell +replace github.com/mitchellh/mapstructure => github.com/go-viper/mapstructure v1.6.0 +``` + +## Usage & Example + +For usage and examples see the [documentation](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. + +## Credits + +Mapstructure was originally created by [@mitchellh](https://github.com/mitchellh). +This is a maintained fork of the original library. + +Read more about the reasons for the fork [here](https://github.com/mitchellh/mapstructure/issues/349). + +## License + +The project is licensed under the [MIT License](LICENSE). diff --git a/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go new file mode 100644 index 0000000000..1f3c69d4b8 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/decode_hooks.go @@ -0,0 +1,630 @@ +package mapstructure + +import ( + "encoding" + "errors" + "fmt" + "net" + "net/netip" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + var f3 DecodeHookFuncValue + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2, f3} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into a closure to be used directly +// if the type fails to convert we return a closure always erroring to keep the previous behaviour +func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) { + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return f(from.Type(), to.Type(), from.Interface()) + } + case DecodeHookFuncKind: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return f(from.Kind(), to.Kind(), from.Interface()) + } + case DecodeHookFuncValue: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return f(from, to) + } + default: + return func(from reflect.Value, to reflect.Value) (interface{}, error) { + return nil, errors.New("invalid decode hook signature") + } + } +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Value, to reflect.Value, +) (interface{}, error) { + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from.Type(), to.Type(), from.Interface()) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), from.Interface()) + case DecodeHookFuncValue: + return f(from, to) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs)) + for _, f := range fs { + cached = append(cached, cachedDecodeHook(f)) + } + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + var err error + data := f.Interface() + + newFrom := f + for _, c := range cached { + data, err = c(newFrom, t) + if err != nil { + return nil, err + } + newFrom = reflect.ValueOf(data) + } + + return data, nil + } +} + +// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. +// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. +func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { + cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff)) + for _, f := range ff { + cached = append(cached, cachedDecodeHook(f)) + } + return func(a, b reflect.Value) (interface{}, error) { + var allErrs string + var out interface{} + var err error + + for _, c := range cached { + out, err = c(a, b) + if err != nil { + allErrs += err.Error() + "\n" + continue + } + + return out, nil + } + + return nil, errors.New(allErrs) + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.SliceOf(f) { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +// StringToURLHookFunc returns a DecodeHookFunc that converts +// strings to *url.URL. +func StringToURLHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(&url.URL{}) { + return data, nil + } + + // Convert it by parsing + return url.Parse(data.(string)) + } +} + +// StringToIPHookFunc returns a DecodeHookFunc that converts +// strings to net.IP +func StringToIPHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IP{}) { + return data, nil + } + + // Convert it by parsing + ip := net.ParseIP(data.(string)) + if ip == nil { + return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + } + + return ip, nil + } +} + +// StringToIPNetHookFunc returns a DecodeHookFunc that converts +// strings to net.IPNet +func StringToIPNetHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IPNet{}) { + return data, nil + } + + // Convert it by parsing + _, net, err := net.ParseCIDR(data.(string)) + return net, err + } +} + +// StringToTimeHookFunc returns a DecodeHookFunc that converts +// strings to time.Time. +func StringToTimeHookFunc(layout string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Time{}) { + return data, nil + } + + // Convert it by parsing + return time.Parse(layout, data.(string)) + } +} + +// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to +// the decoder. +// +// Note that this is significantly different from the WeaklyTypedInput option +// of the DecoderConfig. +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}, +) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } + return "0", nil + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} + +func RecursiveStructToMapHookFunc() DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + if f.Kind() != reflect.Struct { + return f.Interface(), nil + } + + var i interface{} = struct{}{} + if t.Type() != reflect.TypeOf(&i).Elem() { + return f.Interface(), nil + } + + m := make(map[string]interface{}) + t.Set(reflect.ValueOf(m)) + + return f.Interface(), nil + } +} + +// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies +// strings to the UnmarshalText function, when the target type +// implements the encoding.TextUnmarshaler interface +func TextUnmarshallerHookFunc() DecodeHookFuncType { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + result := reflect.New(t).Interface() + unmarshaller, ok := result.(encoding.TextUnmarshaler) + if !ok { + return data, nil + } + str, ok := data.(string) + if !ok { + str = reflect.Indirect(reflect.ValueOf(&data)).Elem().String() + } + if err := unmarshaller.UnmarshalText([]byte(str)); err != nil { + return nil, err + } + return result, nil + } +} + +// StringToNetIPAddrHookFunc returns a DecodeHookFunc that converts +// strings to netip.Addr. +func StringToNetIPAddrHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(netip.Addr{}) { + return data, nil + } + + // Convert it by parsing + return netip.ParseAddr(data.(string)) + } +} + +// StringToNetIPAddrPortHookFunc returns a DecodeHookFunc that converts +// strings to netip.AddrPort. +func StringToNetIPAddrPortHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(netip.AddrPort{}) { + return data, nil + } + + // Convert it by parsing + return netip.ParseAddrPort(data.(string)) + } +} + +// StringToBasicTypeHookFunc returns a DecodeHookFunc that converts +// strings to basic types. +// int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint, float32, float64, bool, byte, rune, complex64, complex128 +func StringToBasicTypeHookFunc() DecodeHookFunc { + return ComposeDecodeHookFunc( + StringToInt8HookFunc(), + StringToUint8HookFunc(), + StringToInt16HookFunc(), + StringToUint16HookFunc(), + StringToInt32HookFunc(), + StringToUint32HookFunc(), + StringToInt64HookFunc(), + StringToUint64HookFunc(), + StringToIntHookFunc(), + StringToUintHookFunc(), + StringToFloat32HookFunc(), + StringToFloat64HookFunc(), + StringToBoolHookFunc(), + // byte and rune are aliases for uint8 and int32 respectively + // StringToByteHookFunc(), + // StringToRuneHookFunc(), + StringToComplex64HookFunc(), + StringToComplex128HookFunc(), + ) +} + +// StringToInt8HookFunc returns a DecodeHookFunc that converts +// strings to int8. +func StringToInt8HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int8 { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 8) + return int8(i64), err + } +} + +// StringToUint8HookFunc returns a DecodeHookFunc that converts +// strings to uint8. +func StringToUint8HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 8) + return uint8(u64), err + } +} + +// StringToInt16HookFunc returns a DecodeHookFunc that converts +// strings to int16. +func StringToInt16HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int16 { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 16) + return int16(i64), err + } +} + +// StringToUint16HookFunc returns a DecodeHookFunc that converts +// strings to uint16. +func StringToUint16HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 16) + return uint16(u64), err + } +} + +// StringToInt32HookFunc returns a DecodeHookFunc that converts +// strings to int32. +func StringToInt32HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int32 { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 32) + return int32(i64), err + } +} + +// StringToUint32HookFunc returns a DecodeHookFunc that converts +// strings to uint32. +func StringToUint32HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 32) + return uint32(u64), err + } +} + +// StringToInt64HookFunc returns a DecodeHookFunc that converts +// strings to int64. +func StringToInt64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int64 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseInt(data.(string), 0, 64) + } +} + +// StringToUint64HookFunc returns a DecodeHookFunc that converts +// strings to uint64. +func StringToUint64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseUint(data.(string), 0, 64) + } +} + +// StringToIntHookFunc returns a DecodeHookFunc that converts +// strings to int. +func StringToIntHookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Int { + return data, nil + } + + // Convert it by parsing + i64, err := strconv.ParseInt(data.(string), 0, 0) + return int(i64), err + } +} + +// StringToUintHookFunc returns a DecodeHookFunc that converts +// strings to uint. +func StringToUintHookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Uint { + return data, nil + } + + // Convert it by parsing + u64, err := strconv.ParseUint(data.(string), 0, 0) + return uint(u64), err + } +} + +// StringToFloat32HookFunc returns a DecodeHookFunc that converts +// strings to float32. +func StringToFloat32HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Float32 { + return data, nil + } + + // Convert it by parsing + f64, err := strconv.ParseFloat(data.(string), 32) + return float32(f64), err + } +} + +// StringToFloat64HookFunc returns a DecodeHookFunc that converts +// strings to float64. +func StringToFloat64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Float64 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseFloat(data.(string), 64) + } +} + +// StringToBoolHookFunc returns a DecodeHookFunc that converts +// strings to bool. +func StringToBoolHookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Bool { + return data, nil + } + + // Convert it by parsing + return strconv.ParseBool(data.(string)) + } +} + +// StringToByteHookFunc returns a DecodeHookFunc that converts +// strings to byte. +func StringToByteHookFunc() DecodeHookFunc { + return StringToUint8HookFunc() +} + +// StringToRuneHookFunc returns a DecodeHookFunc that converts +// strings to rune. +func StringToRuneHookFunc() DecodeHookFunc { + return StringToInt32HookFunc() +} + +// StringToComplex64HookFunc returns a DecodeHookFunc that converts +// strings to complex64. +func StringToComplex64HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 { + return data, nil + } + + // Convert it by parsing + c128, err := strconv.ParseComplex(data.(string), 64) + return complex64(c128), err + } +} + +// StringToComplex128HookFunc returns a DecodeHookFunc that converts +// strings to complex128. +func StringToComplex128HookFunc() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 { + return data, nil + } + + // Convert it by parsing + return strconv.ParseComplex(data.(string), 128) + } +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/flake.lock b/vendor/github.com/go-viper/mapstructure/v2/flake.lock new file mode 100644 index 0000000000..4bea8154e0 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.lock @@ -0,0 +1,472 @@ +{ + "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1717245169, + "narHash": "sha256-+mW3rTBjGU8p1THJN0lX/Dd/8FbnF+3dB+mJuSaxewE=", + "owner": "cachix", + "repo": "devenv", + "rev": "c3f9f053c077c6f88a3de5276d9178c62baa3fc3", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix", + "nixpkgs": "nixpkgs", + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "python-rewrite", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1717285511, + "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_2" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1717284937, + "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_2": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1717112898, + "narHash": "sha256-7R2ZvOnvd9h8fDd65p0JnB7wXfUvreox3xFdYWd1BnY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6132b0f6e344ce2fe34fc051b72fb46e34f668e0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "flake-utils": "flake-utils_2", + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_3" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/vendor/github.com/sagikazarmark/slog-shim/flake.nix b/vendor/github.com/go-viper/mapstructure/v2/flake.nix similarity index 54% rename from vendor/github.com/sagikazarmark/slog-shim/flake.nix rename to vendor/github.com/go-viper/mapstructure/v2/flake.nix index 7239bbc2ec..4ed0f53311 100644 --- a/vendor/github.com/sagikazarmark/slog-shim/flake.nix +++ b/vendor/github.com/go-viper/mapstructure/v2/flake.nix @@ -1,7 +1,6 @@ { inputs = { - # nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - nixpkgs.url = "github:NixOS/nixpkgs/master"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-parts.url = "github:hercules-ci/flake-parts"; devenv.url = "github:cachix/devenv"; }; @@ -19,38 +18,21 @@ default = { languages = { go.enable = true; - go.package = pkgs.lib.mkDefault pkgs.go_1_21; }; - # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 - containers = pkgs.lib.mkForce { }; - }; - - ci = devenv.shells.default; - - ci_1_19 = { - imports = [ devenv.shells.ci ]; - - languages = { - go.package = pkgs.go_1_19; + pre-commit.hooks = { + nixpkgs-fmt.enable = true; }; - }; - ci_1_20 = { - imports = [ devenv.shells.ci ]; + packages = with pkgs; [ + golangci-lint + ]; - languages = { - go.package = pkgs.go_1_20; - }; + # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 + containers = pkgs.lib.mkForce { }; }; - ci_1_21 = { - imports = [ devenv.shells.ci ]; - - languages = { - go.package = pkgs.go_1_21; - }; - }; + ci = devenv.shells.default; }; }; }; diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go new file mode 100644 index 0000000000..d1c15e474f --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/errors.go @@ -0,0 +1,11 @@ +package errors + +import "errors" + +func New(text string) error { + return errors.New(text) +} + +func As(err error, target interface{}) bool { + return errors.As(err, target) +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go new file mode 100644 index 0000000000..d74e3a0b5a --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join.go @@ -0,0 +1,9 @@ +//go:build go1.20 + +package errors + +import "errors" + +func Join(errs ...error) error { + return errors.Join(errs...) +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go new file mode 100644 index 0000000000..700b40229c --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/internal/errors/join_go1_19.go @@ -0,0 +1,61 @@ +//go:build !go1.20 + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package errors + +// Join returns an error that wraps the given errors. +// Any nil error values are discarded. +// Join returns nil if every value in errs is nil. +// The error formats as the concatenation of the strings obtained +// by calling the Error method of each element of errs, with a newline +// between each string. +// +// A non-nil error returned by Join implements the Unwrap() []error method. +func Join(errs ...error) error { + n := 0 + for _, err := range errs { + if err != nil { + n++ + } + } + if n == 0 { + return nil + } + e := &joinError{ + errs: make([]error, 0, n), + } + for _, err := range errs { + if err != nil { + e.errs = append(e.errs, err) + } + } + return e +} + +type joinError struct { + errs []error +} + +func (e *joinError) Error() string { + // Since Join returns nil if every value in errs is nil, + // e.errs cannot be empty. + if len(e.errs) == 1 { + return e.errs[0].Error() + } + + b := []byte(e.errs[0].Error()) + for _, err := range e.errs[1:] { + b = append(b, '\n') + b = append(b, err.Error()...) + } + // At this point, b has at least one byte '\n'. + // return unsafe.String(&b[0], len(b)) + return string(b) +} + +func (e *joinError) Unwrap() []error { + return e.errs +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go new file mode 100644 index 0000000000..e77e63ba38 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/mapstructure.go @@ -0,0 +1,1620 @@ +// Package mapstructure exposes functionality to convert one arbitrary +// Go type into another, typically to convert a map[string]interface{} +// into a native Go structure. +// +// The Go structure can be arbitrarily complex, containing slices, +// other structs, etc. and the decoder will properly decode nested +// maps and so on into the proper structures in the native Go struct. +// See the examples to see what the decoder is capable of. +// +// The simplest function to start with is Decode. +// +// # Field Tags +// +// When decoding to a struct, mapstructure will use the field name by +// default to perform the mapping. For example, if a struct has a field +// "Username" then mapstructure will look for a key in the source value +// of "username" (case insensitive). +// +// type User struct { +// Username string +// } +// +// You can change the behavior of mapstructure by using struct tags. +// The default struct tag that mapstructure looks for is "mapstructure" +// but you can customize it using DecoderConfig. +// +// # Renaming Fields +// +// To rename the key that mapstructure looks for, use the "mapstructure" +// tag and set a value directly. For example, to change the "username" example +// above to "user": +// +// type User struct { +// Username string `mapstructure:"user"` +// } +// +// # Embedded Structs and Squashing +// +// Embedded structs are treated as if they're another field with that name. +// By default, the two structs below are equivalent when decoding with +// mapstructure: +// +// type Person struct { +// Name string +// } +// +// type Friend struct { +// Person +// } +// +// type Friend struct { +// Person Person +// } +// +// This would require an input that looks like below: +// +// map[string]interface{}{ +// "person": map[string]interface{}{"name": "alice"}, +// } +// +// If your "person" value is NOT nested, then you can append ",squash" to +// your tag value and mapstructure will treat it as if the embedded struct +// were part of the struct directly. Example: +// +// type Friend struct { +// Person `mapstructure:",squash"` +// } +// +// Now the following input would be accepted: +// +// map[string]interface{}{ +// "name": "alice", +// } +// +// When decoding from a struct to a map, the squash tag squashes the struct +// fields into a single map. Using the example structs from above: +// +// Friend{Person: Person{Name: "alice"}} +// +// Will be decoded into a map: +// +// map[string]interface{}{ +// "name": "alice", +// } +// +// DecoderConfig has a field that changes the behavior of mapstructure +// to always squash embedded structs. +// +// # Remainder Values +// +// If there are any unmapped keys in the source value, mapstructure by +// default will silently ignore them. You can error by setting ErrorUnused +// in DecoderConfig. If you're using Metadata you can also maintain a slice +// of the unused keys. +// +// You can also use the ",remain" suffix on your tag to collect all unused +// values in a map. The field with this tag MUST be a map type and should +// probably be a "map[string]interface{}" or "map[interface{}]interface{}". +// See example below: +// +// type Friend struct { +// Name string +// Other map[string]interface{} `mapstructure:",remain"` +// } +// +// Given the input below, Other would be populated with the other +// values that weren't used (everything but "name"): +// +// map[string]interface{}{ +// "name": "bob", +// "address": "123 Maple St.", +// } +// +// # Omit Empty Values +// +// When decoding from a struct to any other value, you may use the +// ",omitempty" suffix on your tag to omit that value if it equates to +// the zero value. The zero value of all types is specified in the Go +// specification. +// +// For example, the zero type of a numeric type is zero ("0"). If the struct +// field value is zero and a numeric type, the field is empty, and it won't +// be encoded into the destination type. +// +// type Source struct { +// Age int `mapstructure:",omitempty"` +// } +// +// # Unexported fields +// +// Since unexported (private) struct fields cannot be set outside the package +// where they are defined, the decoder will simply skip them. +// +// For this output type definition: +// +// type Exported struct { +// private string // this unexported field will be skipped +// Public string +// } +// +// Using this map as input: +// +// map[string]interface{}{ +// "private": "I will be ignored", +// "Public": "I made it through!", +// } +// +// The following struct will be decoded: +// +// type Exported struct { +// private: "" // field is left with an empty string (zero value) +// Public: "I made it through!" +// } +// +// # Other Configuration +// +// mapstructure is highly configurable. See the DecoderConfig struct +// for other features and options that are supported. +package mapstructure + +import ( + "encoding/json" + "fmt" + "reflect" + "sort" + "strconv" + "strings" + + "github.com/go-viper/mapstructure/v2/internal/errors" +) + +// DecodeHookFunc is the callback function that can be used for +// data transformations. See "DecodeHook" in the DecoderConfig +// struct. +// +// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or +// DecodeHookFuncValue. +// Values are a superset of Types (Values can return types), and Types are a +// superset of Kinds (Types can return Kinds) and are generally a richer thing +// to use, but Kinds are simpler if you only need those. +// +// The reason DecodeHookFunc is multi-typed is for backwards compatibility: +// we started with Kinds and then realized Types were the better solution, +// but have a promise to not break backwards compat so we now support +// both. +type DecodeHookFunc interface{} + +// DecodeHookFuncType is a DecodeHookFunc which has complete information about +// the source and target types. +type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) + +// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the +// source and target types. +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) + +// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target +// values. +type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) + +// DecoderConfig is the configuration that is used to create a new decoder +// and allows customization of various aspects of decoding. +type DecoderConfig struct { + // DecodeHook, if set, will be called before any decoding and any + // type conversion (if WeaklyTypedInput is on). This lets you modify + // the values before they're set down onto the resulting struct. The + // DecodeHook is called for every map and value in the input. This means + // that if a struct has embedded fields with squash tags the decode hook + // is called only once with all of the input data, not once for each + // embedded struct. + // + // If an error is returned, the entire decode will fail with that error. + DecodeHook DecodeHookFunc + + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + + // If ErrorUnset is true, then it is an error for there to exist + // fields in the result that were not set in the decoding process + // (extra fields). This only applies to decoding to a struct. This + // will affect all nested structs as well. + ErrorUnset bool + + // ZeroFields, if set to true, will zero fields before writing them. + // For example, a map will be emptied before decoded values are put in + // it. If this is false, a map will be merged. + ZeroFields bool + + // If WeaklyTypedInput is true, the decoder will make the following + // "weak" conversions: + // + // - bools to string (true = "1", false = "0") + // - numbers to string (base 10) + // - bools to int/uint (true = 1, false = 0) + // - strings to int/uint (base implied by prefix) + // - int to bool (true if value != 0) + // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, + // FALSE, false, False. Anything else is an error) + // - empty array = empty map and vice versa + // - negative numbers to overflowed uint values (base 10) + // - slice of maps to a merged map + // - single values are converted to slices if required. Each + // element is weakly decoded. For example: "4" can become []int{4} + // if the target type is an int slice. + // + WeaklyTypedInput bool + + // Squash will squash embedded structs. A squash tag may also be + // added to an individual struct field using a tag. For example: + // + // type Parent struct { + // Child `mapstructure:",squash"` + // } + Squash bool + + // Metadata is the struct that will contain extra metadata about + // the decoding. If this is nil, then no metadata will be tracked. + Metadata *Metadata + + // Result is a pointer to the struct that will contain the decoded + // value. + Result interface{} + + // The tag name that mapstructure reads for field names. This + // defaults to "mapstructure" + TagName string + + // The option of the value in the tag that indicates a field should + // be squashed. This defaults to "squash". + SquashTagOption string + + // IgnoreUntaggedFields ignores all struct fields without explicit + // TagName, comparable to `mapstructure:"-"` as default behaviour. + IgnoreUntaggedFields bool + + // MatchName is the function used to match the map key to the struct + // field name or tag. Defaults to `strings.EqualFold`. This can be used + // to implement case-sensitive tag values, support snake casing, etc. + MatchName func(mapKey, fieldName string) bool + + // DecodeNil, if set to true, will cause the DecodeHook (if present) to run + // even if the input is nil. This can be used to provide default values. + DecodeNil bool +} + +// A Decoder takes a raw interface value and turns it into structured +// data, keeping track of rich error information along the way in case +// anything goes wrong. Unlike the basic top-level Decode method, you can +// more finely control how the Decoder behaves using the DecoderConfig +// structure. The top-level Decode method is just a convenience that sets +// up the most basic Decoder. +type Decoder struct { + config *DecoderConfig + cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error) +} + +// Metadata contains information about decoding a structure that +// is tedious or difficult to get otherwise. +type Metadata struct { + // Keys are the keys of the structure which were successfully decoded + Keys []string + + // Unused is a slice of keys that were found in the raw value but + // weren't decoded since there was no matching field in the result interface + Unused []string + + // Unset is a slice of field names that were found in the result interface + // but weren't set in the decoding process since there was no matching value + // in the input + Unset []string +} + +// Decode takes an input structure and uses reflection to translate it to +// the output structure. output must be a pointer to a map or struct. +func Decode(input interface{}, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecode is the same as Decode but is shorthand to enable +// WeaklyTypedInput. See DecoderConfig for more info. +func WeakDecode(input, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// DecodeMetadata is the same as Decode, but is shorthand to +// enable metadata collection. See DecoderConfig for more info. +func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecodeMetadata is the same as Decode, but is shorthand to +// enable both WeaklyTypedInput and metadata collection. See +// DecoderConfig for more info. +func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// NewDecoder returns a new decoder for the given configuration. Once +// a decoder has been returned, the same configuration must not be used +// again. +func NewDecoder(config *DecoderConfig) (*Decoder, error) { + val := reflect.ValueOf(config.Result) + if val.Kind() != reflect.Ptr { + return nil, errors.New("result must be a pointer") + } + + val = val.Elem() + if !val.CanAddr() { + return nil, errors.New("result must be addressable (a pointer)") + } + + if config.Metadata != nil { + if config.Metadata.Keys == nil { + config.Metadata.Keys = make([]string, 0) + } + + if config.Metadata.Unused == nil { + config.Metadata.Unused = make([]string, 0) + } + + if config.Metadata.Unset == nil { + config.Metadata.Unset = make([]string, 0) + } + } + + if config.TagName == "" { + config.TagName = "mapstructure" + } + + if config.SquashTagOption == "" { + config.SquashTagOption = "squash" + } + + if config.MatchName == nil { + config.MatchName = strings.EqualFold + } + + result := &Decoder{ + config: config, + } + if config.DecodeHook != nil { + result.cachedDecodeHook = cachedDecodeHook(config.DecodeHook) + } + + return result, nil +} + +// Decode decodes the given raw interface to the target pointer specified +// by the configuration. +func (d *Decoder) Decode(input interface{}) error { + err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) + + // Retain some of the original behavior when multiple errors ocurr + var joinedErr interface{ Unwrap() []error } + if errors.As(err, &joinedErr) { + return fmt.Errorf("decoding failed due to the following error(s):\n\n%w", err) + } + + return err +} + +// isNil returns true if the input is nil or a typed nil pointer. +func isNil(input interface{}) bool { + if input == nil { + return true + } + val := reflect.ValueOf(input) + return val.Kind() == reflect.Ptr && val.IsNil() +} + +// Decodes an unknown data type into a specific reflection value. +func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { + var ( + inputVal = reflect.ValueOf(input) + outputKind = getKind(outVal) + decodeNil = d.config.DecodeNil && d.cachedDecodeHook != nil + ) + if isNil(input) { + // Typed nils won't match the "input == nil" below, so reset input. + input = nil + } + if input == nil { + // If the data is nil, then we don't set anything, unless ZeroFields is set + // to true. + if d.config.ZeroFields { + outVal.Set(reflect.Zero(outVal.Type())) + + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + } + if !decodeNil { + return nil + } + } + if !inputVal.IsValid() { + if !decodeNil { + // If the input value is invalid, then we just set the value + // to be the zero value. + outVal.Set(reflect.Zero(outVal.Type())) + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + return nil + } + // Hooks need a valid inputVal, so reset it to zero value of outVal type. + switch outputKind { + case reflect.Struct, reflect.Map: + var mapVal map[string]interface{} + inputVal = reflect.ValueOf(mapVal) // create nil map pointer + case reflect.Slice, reflect.Array: + var sliceVal []interface{} + inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer + default: + inputVal = reflect.Zero(outVal.Type()) + } + } + + if d.cachedDecodeHook != nil { + // We have a DecodeHook, so let's pre-process the input. + var err error + input, err = d.cachedDecodeHook(inputVal, outVal) + if err != nil { + return fmt.Errorf("error decoding '%s': %w", name, err) + } + } + if isNil(input) { + return nil + } + + var err error + addMetaKey := true + switch outputKind { + case reflect.Bool: + err = d.decodeBool(name, input, outVal) + case reflect.Interface: + err = d.decodeBasic(name, input, outVal) + case reflect.String: + err = d.decodeString(name, input, outVal) + case reflect.Int: + err = d.decodeInt(name, input, outVal) + case reflect.Uint: + err = d.decodeUint(name, input, outVal) + case reflect.Float32: + err = d.decodeFloat(name, input, outVal) + case reflect.Complex64: + err = d.decodeComplex(name, input, outVal) + case reflect.Struct: + err = d.decodeStruct(name, input, outVal) + case reflect.Map: + err = d.decodeMap(name, input, outVal) + case reflect.Ptr: + addMetaKey, err = d.decodePtr(name, input, outVal) + case reflect.Slice: + err = d.decodeSlice(name, input, outVal) + case reflect.Array: + err = d.decodeArray(name, input, outVal) + case reflect.Func: + err = d.decodeFunc(name, input, outVal) + default: + // If we reached this point then we weren't able to decode it + return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + } + + // If we reached here, then we successfully decoded SOMETHING, so + // mark the key as used if we're tracking metainput. + if addMetaKey && d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + + return err +} + +// This decodes a basic type (bool, int, string, etc.) and sets the +// value to "data" of that type. +func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { + if val.IsValid() && val.Elem().IsValid() { + elem := val.Elem() + + // If we can't address this element, then its not writable. Instead, + // we make a copy of the value (which is a pointer and therefore + // writable), decode into that, and replace the whole value. + copied := false + if !elem.CanAddr() { + copied = true + + // Make *T + copy := reflect.New(elem.Type()) + + // *T = elem + copy.Elem().Set(elem) + + // Set elem so we decode into it + elem = copy + } + + // Decode. If we have an error then return. We also return right + // away if we're not a copy because that means we decoded directly. + if err := d.decode(name, data, elem); err != nil || !copied { + return err + } + + // If we're a copy, we need to set te final result + val.Set(elem.Elem()) + return nil + } + + dataVal := reflect.ValueOf(data) + + // If the input data is a pointer, and the assigned type is the dereference + // of that exact pointer, then indirect it so that we can assign it. + // Example: *string to string + if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { + dataVal = reflect.Indirect(dataVal) + } + + if !dataVal.IsValid() { + dataVal = reflect.Zero(val.Type()) + } + + dataValType := dataVal.Type() + if !dataValType.AssignableTo(val.Type()) { + return fmt.Errorf( + "'%s' expected type '%s', got '%s'", + name, val.Type(), dataValType) + } + + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + converted := true + switch { + case dataKind == reflect.String: + val.SetString(dataVal.String()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetString("1") + } else { + val.SetString("0") + } + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatInt(dataVal.Int(), 10)) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + switch elemKind { + case reflect.Uint8: + var uints []uint8 + if dataKind == reflect.Array { + uints = make([]uint8, dataVal.Len(), dataVal.Len()) + for i := range uints { + uints[i] = dataVal.Index(i).Interface().(uint8) + } + } else { + uints = dataVal.Interface().([]uint8) + } + val.SetString(string(uints)) + default: + converted = false + } + default: + converted = false + } + + if !converted { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetInt(dataVal.Int()) + case dataKind == reflect.Uint: + val.SetInt(int64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetInt(int64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetInt(1) + } else { + val.SetInt(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseInt(str, 0, val.Type().Bits()) + if err == nil { + val.SetInt(i) + } else { + return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Int64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetInt(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + i := dataVal.Int() + if i < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %d overflows uint", + name, i) + } + val.SetUint(uint64(i)) + case dataKind == reflect.Uint: + val.SetUint(dataVal.Uint()) + case dataKind == reflect.Float32: + f := dataVal.Float() + if f < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %f overflows uint", + name, f) + } + val.SetUint(uint64(f)) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetUint(1) + } else { + val.SetUint(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseUint(str, 0, val.Type().Bits()) + if err == nil { + val.SetUint(i) + } else { + return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := strconv.ParseUint(string(jn), 0, 64) + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetUint(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Bool: + val.SetBool(dataVal.Bool()) + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Int() != 0) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Uint() != 0) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Float() != 0) + case dataKind == reflect.String && d.config.WeaklyTypedInput: + b, err := strconv.ParseBool(dataVal.String()) + if err == nil { + val.SetBool(b) + } else if dataVal.String() == "" { + val.SetBool(false) + } else { + return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'", + name, val, dataVal, data) + } + + return nil +} + +func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetFloat(float64(dataVal.Int())) + case dataKind == reflect.Uint: + val.SetFloat(float64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetFloat(dataVal.Float()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetFloat(1) + } else { + val.SetFloat(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + f, err := strconv.ParseFloat(str, val.Type().Bits()) + if err == nil { + val.SetFloat(f) + } else { + return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Float64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetFloat(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Complex64: + val.SetComplex(dataVal.Complex()) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // By default we overwrite keys in the current map + valMap := val + + // If the map is nil or we're purposely zeroing fields, make a new map + if valMap.IsNil() || d.config.ZeroFields { + // Make a new map to hold our result + mapType := reflect.MapOf(valKeyType, valElemType) + valMap = reflect.MakeMap(mapType) + } + + dataVal := reflect.ValueOf(data) + + // Resolve any levels of indirection + for dataVal.Kind() == reflect.Pointer { + dataVal = reflect.Indirect(dataVal) + } + + // Check input type and based on the input type jump to the proper func + switch dataVal.Kind() { + case reflect.Map: + return d.decodeMapFromMap(name, dataVal, val, valMap) + + case reflect.Struct: + return d.decodeMapFromStruct(name, dataVal, val, valMap) + + case reflect.Array, reflect.Slice: + if d.config.WeaklyTypedInput { + return d.decodeMapFromSlice(name, dataVal, val, valMap) + } + + fallthrough + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + // Special case for BC reasons (covered by tests) + if dataVal.Len() == 0 { + val.Set(valMap) + return nil + } + + for i := 0; i < dataVal.Len(); i++ { + err := d.decode( + name+"["+strconv.Itoa(i)+"]", + dataVal.Index(i).Interface(), val) + if err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // Accumulate errors + var errs []error + + // If the input data is empty, then we just match what the input data is. + if dataVal.Len() == 0 { + if dataVal.IsNil() { + if !val.IsNil() { + val.Set(dataVal) + } + } else { + // Set to empty allocated value + val.Set(valMap) + } + + return nil + } + + for _, k := range dataVal.MapKeys() { + fieldName := name + "[" + k.String() + "]" + + // First decode the key into the proper type + currentKey := reflect.Indirect(reflect.New(valKeyType)) + if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { + errs = append(errs, err) + continue + } + + // Next decode the data into the proper type + v := dataVal.MapIndex(k).Interface() + currentVal := reflect.Indirect(reflect.New(valElemType)) + if err := d.decode(fieldName, v, currentVal); err != nil { + errs = append(errs, err) + continue + } + + valMap.SetMapIndex(currentKey, currentVal) + } + + // Set the built up map to the value + val.Set(valMap) + + return errors.Join(errs...) +} + +func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + typ := dataVal.Type() + for i := 0; i < typ.NumField(); i++ { + // Get the StructField first since this is a cheap operation. If the + // field is unexported, then ignore it. + f := typ.Field(i) + if f.PkgPath != "" { + continue + } + + // Next get the actual value of this field and verify it is assignable + // to the map value. + v := dataVal.Field(i) + if !v.Type().AssignableTo(valMap.Type().Elem()) { + return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + } + + tagValue := f.Tag.Get(d.config.TagName) + keyName := f.Name + + if tagValue == "" && d.config.IgnoreUntaggedFields { + continue + } + + // If Squash is set in the config, we squash the field down. + squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous + + v = dereferencePtrToStructIfNeeded(v, d.config.TagName) + + // Determine the name of the key in the map + if index := strings.Index(tagValue, ","); index != -1 { + if tagValue[:index] == "-" { + continue + } + // If "omitempty" is specified in the tag, it ignores empty values. + if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) { + continue + } + + // If "squash" is specified in the tag, we squash the field down. + squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption) + if squash { + // When squashing, the embedded type can be a pointer to a struct. + if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { + v = v.Elem() + } + + // The final type must be a struct + if v.Kind() != reflect.Struct { + return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + } + } else { + if strings.Index(tagValue[index+1:], "remain") != -1 { + if v.Kind() != reflect.Map { + return fmt.Errorf("error remain-tag field with invalid type: '%s'", v.Type()) + } + + ptr := v.MapRange() + for ptr.Next() { + valMap.SetMapIndex(ptr.Key(), ptr.Value()) + } + continue + } + } + if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" { + keyName = keyNameTagValue + } + } else if len(tagValue) > 0 { + if tagValue == "-" { + continue + } + keyName = tagValue + } + + switch v.Kind() { + // this is an embedded struct, so handle it differently + case reflect.Struct: + x := reflect.New(v.Type()) + x.Elem().Set(v) + + vType := valMap.Type() + vKeyType := vType.Key() + vElemType := vType.Elem() + mType := reflect.MapOf(vKeyType, vElemType) + vMap := reflect.MakeMap(mType) + + // Creating a pointer to a map so that other methods can completely + // overwrite the map if need be (looking at you decodeMapFromMap). The + // indirection allows the underlying map to be settable (CanSet() == true) + // where as reflect.MakeMap returns an unsettable map. + addrVal := reflect.New(vMap.Type()) + reflect.Indirect(addrVal).Set(vMap) + + err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal)) + if err != nil { + return err + } + + // the underlying map may have been completely overwritten so pull + // it indirectly out of the enclosing value. + vMap = reflect.Indirect(addrVal) + + if squash { + for _, k := range vMap.MapKeys() { + valMap.SetMapIndex(k, vMap.MapIndex(k)) + } + } else { + valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) + } + + default: + valMap.SetMapIndex(reflect.ValueOf(keyName), v) + } + } + + if val.CanAddr() { + val.Set(valMap) + } + + return nil +} + +func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { + // If the input data is nil, then we want to just set the output + // pointer to be nil as well. + isNil := data == nil + if !isNil { + switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { + case reflect.Chan, + reflect.Func, + reflect.Interface, + reflect.Map, + reflect.Ptr, + reflect.Slice: + isNil = v.IsNil() + } + } + if isNil { + if !val.IsNil() && val.CanSet() { + nilValue := reflect.New(val.Type()).Elem() + val.Set(nilValue) + } + + return true, nil + } + + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + valType := val.Type() + valElemType := valType.Elem() + if val.CanSet() { + realVal := val + if realVal.IsNil() || d.config.ZeroFields { + realVal = reflect.New(valElemType) + } + + if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { + return false, err + } + + val.Set(realVal) + } else { + if err := d.decode(name, data, reflect.Indirect(val)); err != nil { + return false, err + } + } + return false, nil +} + +func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + dataVal := reflect.Indirect(reflect.ValueOf(data)) + if val.Type() != dataVal.Type() { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + sliceType := reflect.SliceOf(valElemType) + + // If we have a non array/slice type then we first attempt to convert. + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Slice and array we use the normal logic + case dataValKind == reflect.Slice, dataValKind == reflect.Array: + break + + // Empty maps turn into empty slices + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.MakeSlice(sliceType, 0, 0)) + return nil + } + // Create slice of maps of other sizes + return d.decodeSlice(name, []interface{}{data}, val) + + case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: + return d.decodeSlice(name, []byte(dataVal.String()), val) + + // All other types we try to convert to the slice type + // and "lift" it into it. i.e. a string becomes a string slice. + default: + // Just re-try this function with data as a slice. + return d.decodeSlice(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + } + + // If the input value is nil, then don't allocate since empty != nil + if dataValKind != reflect.Array && dataVal.IsNil() { + return nil + } + + valSlice := val + if valSlice.IsNil() || d.config.ZeroFields { + // Make a new slice to hold our result, same size as the original data. + valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + } else if valSlice.Len() > dataVal.Len() { + valSlice = valSlice.Slice(0, dataVal.Len()) + } + + // Accumulate any errors + var errs []error + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + for valSlice.Len() <= i { + valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) + } + currentField := valSlice.Index(i) + + fieldName := name + "[" + strconv.Itoa(i) + "]" + if err := d.decode(fieldName, currentData, currentField); err != nil { + errs = append(errs, err) + } + } + + // Finally, set the value to the slice we built up + val.Set(valSlice) + + return errors.Join(errs...) +} + +func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + arrayType := reflect.ArrayOf(valType.Len(), valElemType) + + valArray := val + + if isComparable(valArray) && valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Empty maps turn into empty arrays + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.Zero(arrayType)) + return nil + } + + // All other types we try to convert to the array type + // and "lift" it into it. i.e. a string becomes a string array. + default: + // Just re-try this function with data as a slice. + return d.decodeArray(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + + } + if dataVal.Len() > arrayType.Len() { + return fmt.Errorf( + "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + } + + // Make a new array to hold our result, same size as the original data. + valArray = reflect.New(arrayType).Elem() + } + + // Accumulate any errors + var errs []error + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + currentField := valArray.Index(i) + + fieldName := name + "[" + strconv.Itoa(i) + "]" + if err := d.decode(fieldName, currentData, currentField); err != nil { + errs = append(errs, err) + } + } + + // Finally, set the value to the array we built up + val.Set(valArray) + + return errors.Join(errs...) +} + +func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + + // If the type of the value to write to and the data match directly, + // then we just set it directly instead of recursing into the structure. + if dataVal.Type() == val.Type() { + val.Set(dataVal) + return nil + } + + dataValKind := dataVal.Kind() + switch dataValKind { + case reflect.Map: + return d.decodeStructFromMap(name, dataVal, val) + + case reflect.Struct: + // Not the most efficient way to do this but we can optimize later if + // we want to. To convert from struct to struct we go to map first + // as an intermediary. + + // Make a new map to hold our result + mapType := reflect.TypeOf((map[string]interface{})(nil)) + mval := reflect.MakeMap(mapType) + + // Creating a pointer to a map so that other methods can completely + // overwrite the map if need be (looking at you decodeMapFromMap). The + // indirection allows the underlying map to be settable (CanSet() == true) + // where as reflect.MakeMap returns an unsettable map. + addrVal := reflect.New(mval.Type()) + + reflect.Indirect(addrVal).Set(mval) + if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil { + return err + } + + result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val) + return result + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { + dataValType := dataVal.Type() + if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { + return fmt.Errorf( + "'%s' needs a map with string keys, has '%s' keys", + name, dataValType.Key().Kind()) + } + + dataValKeys := make(map[reflect.Value]struct{}) + dataValKeysUnused := make(map[interface{}]struct{}) + for _, dataValKey := range dataVal.MapKeys() { + dataValKeys[dataValKey] = struct{}{} + dataValKeysUnused[dataValKey.Interface()] = struct{}{} + } + + targetValKeysUnused := make(map[interface{}]struct{}) + + var errs []error + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = val + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + type field struct { + field reflect.StructField + val reflect.Value + } + + // remainField is set to a valid field set with the "remain" tag if + // we are keeping track of remaining values. + var remainField *field + + fields := []field{} + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + fieldVal := structVal.Field(i) + if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { + // Handle embedded struct pointers as embedded structs. + fieldVal = fieldVal.Elem() + } + + // If "squash" is specified in the tag, we squash the field down. + squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous + remain := false + + // We always parse the tags cause we're looking for other tags too + tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") + for _, tag := range tagParts[1:] { + if tag == d.config.SquashTagOption { + squash = true + break + } + + if tag == "remain" { + remain = true + break + } + } + + if squash { + switch fieldVal.Kind() { + case reflect.Struct: + structs = append(structs, fieldVal) + case reflect.Interface: + if !fieldVal.IsNil() { + structs = append(structs, fieldVal.Elem().Elem()) + } + default: + errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) + } + continue + } + + // Build our field + if remain { + remainField = &field{fieldType, fieldVal} + } else { + // Normal struct field, store it away + fields = append(fields, field{fieldType, fieldVal}) + } + } + } + + // for fieldType, field := range fields { + for _, f := range fields { + field, fieldValue := f.field, f.val + fieldName := field.Name + + tagValue := field.Tag.Get(d.config.TagName) + if tagValue == "" && d.config.IgnoreUntaggedFields { + continue + } + tagValue = strings.SplitN(tagValue, ",", 2)[0] + if tagValue != "" { + fieldName = tagValue + } + + rawMapKey := reflect.ValueOf(fieldName) + rawMapVal := dataVal.MapIndex(rawMapKey) + if !rawMapVal.IsValid() { + // Do a slower search by iterating over each key and + // doing case-insensitive search. + for dataValKey := range dataValKeys { + mK, ok := dataValKey.Interface().(string) + if !ok { + // Not a string key + continue + } + + if d.config.MatchName(mK, fieldName) { + rawMapKey = dataValKey + rawMapVal = dataVal.MapIndex(dataValKey) + break + } + } + + if !rawMapVal.IsValid() { + // There was no matching key in the map for the value in + // the struct. Remember it for potential errors and metadata. + targetValKeysUnused[fieldName] = struct{}{} + continue + } + } + + if !fieldValue.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !fieldValue.CanSet() { + continue + } + + // Delete the key we're using from the unused map so we stop tracking + delete(dataValKeysUnused, rawMapKey.Interface()) + + // If the name is empty string, then we're at the root, and we + // don't dot-join the fields. + if name != "" { + fieldName = name + "." + fieldName + } + + if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { + errs = append(errs, err) + } + } + + // If we have a "remain"-tagged field and we have unused keys then + // we put the unused keys directly into the remain field. + if remainField != nil && len(dataValKeysUnused) > 0 { + // Build a map of only the unused values + remain := map[interface{}]interface{}{} + for key := range dataValKeysUnused { + remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() + } + + // Decode it as-if we were just decoding this map onto our map. + if err := d.decodeMap(name, remain, remainField.val); err != nil { + errs = append(errs, err) + } + + // Set the map to nil so we have none so that the next check will + // not error (ErrorUnused) + dataValKeysUnused = nil + } + + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errs = append(errs, err) + } + + if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { + keys := make([]string, 0, len(targetValKeysUnused)) + for rawKey := range targetValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) + errs = append(errs, err) + } + + if err := errors.Join(errs...); err != nil { + return err + } + + // Add the unused keys to the list of unused keys if we're tracking metadata + if d.config.Metadata != nil { + for rawKey := range dataValKeysUnused { + key := rawKey.(string) + if name != "" { + key = name + "." + key + } + + d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) + } + for rawKey := range targetValKeysUnused { + key := rawKey.(string) + if name != "" { + key = name + "." + key + } + + d.config.Metadata.Unset = append(d.config.Metadata.Unset, key) + } + } + + return nil +} + +func isEmptyValue(v reflect.Value) bool { + switch getKind(v) { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func getKind(val reflect.Value) reflect.Kind { + kind := val.Kind() + + switch { + case kind >= reflect.Int && kind <= reflect.Int64: + return reflect.Int + case kind >= reflect.Uint && kind <= reflect.Uint64: + return reflect.Uint + case kind >= reflect.Float32 && kind <= reflect.Float64: + return reflect.Float32 + case kind >= reflect.Complex64 && kind <= reflect.Complex128: + return reflect.Complex64 + default: + return kind + } +} + +func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool { + for i := 0; i < typ.NumField(); i++ { + f := typ.Field(i) + if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields + return true + } + if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside + return true + } + } + return false +} + +func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value { + if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { + return v + } + deref := v.Elem() + derefT := deref.Type() + if isStructTypeConvertibleToMap(derefT, true, tagName) { + return deref + } + return v +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go new file mode 100644 index 0000000000..d0913fff6c --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_19.go @@ -0,0 +1,44 @@ +//go:build !go1.20 + +package mapstructure + +import "reflect" + +func isComparable(v reflect.Value) bool { + k := v.Kind() + switch k { + case reflect.Invalid: + return false + + case reflect.Array: + switch v.Type().Elem().Kind() { + case reflect.Interface, reflect.Array, reflect.Struct: + for i := 0; i < v.Type().Len(); i++ { + // if !v.Index(i).Comparable() { + if !isComparable(v.Index(i)) { + return false + } + } + return true + } + return v.Type().Comparable() + + case reflect.Interface: + // return v.Elem().Comparable() + return isComparable(v.Elem()) + + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + return false + + // if !v.Field(i).Comparable() { + if !isComparable(v.Field(i)) { + return false + } + } + return true + + default: + return v.Type().Comparable() + } +} diff --git a/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go new file mode 100644 index 0000000000..f8255a1b17 --- /dev/null +++ b/vendor/github.com/go-viper/mapstructure/v2/reflect_go1_20.go @@ -0,0 +1,10 @@ +//go:build go1.20 + +package mapstructure + +import "reflect" + +// TODO: remove once we drop support for Go <1.20 +func isComparable(v reflect.Value) bool { + return v.Comparable() +} diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go index c6d09dae40..720f3cdf57 100644 --- a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go +++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go @@ -14,22 +14,29 @@ import ( ) // SortSlices returns a [cmp.Transformer] option that sorts all []V. -// The less function must be of the form "func(T, T) bool" which is used to -// sort any slice with element type V that is assignable to T. +// The lessOrCompareFunc function must be either +// a less function of the form "func(T, T) bool" or +// a compare function of the format "func(T, T) int" +// which is used to sort any slice with element type V that is assignable to T. // -// The less function must be: +// A less function must be: // - Deterministic: less(x, y) == less(x, y) // - Irreflexive: !less(x, x) // - Transitive: if !less(x, y) and !less(y, z), then !less(x, z) // -// The less function does not have to be "total". That is, if !less(x, y) and -// !less(y, x) for two elements x and y, their relative order is maintained. +// A compare function must be: +// - Deterministic: compare(x, y) == compare(x, y) +// - Irreflexive: compare(x, x) == 0 +// - Transitive: if !less(x, y) and !less(y, z), then !less(x, z) +// +// The function does not have to be "total". That is, if x != y, but +// less or compare report inequality, their relative order is maintained. // // SortSlices can be used in conjunction with [EquateEmpty]. -func SortSlices(lessFunc interface{}) cmp.Option { - vf := reflect.ValueOf(lessFunc) - if !function.IsType(vf.Type(), function.Less) || vf.IsNil() { - panic(fmt.Sprintf("invalid less function: %T", lessFunc)) +func SortSlices(lessOrCompareFunc interface{}) cmp.Option { + vf := reflect.ValueOf(lessOrCompareFunc) + if (!function.IsType(vf.Type(), function.Less) && !function.IsType(vf.Type(), function.Compare)) || vf.IsNil() { + panic(fmt.Sprintf("invalid less or compare function: %T", lessOrCompareFunc)) } ss := sliceSorter{vf.Type().In(0), vf} return cmp.FilterValues(ss.filter, cmp.Transformer("cmpopts.SortSlices", ss.sort)) @@ -79,28 +86,40 @@ func (ss sliceSorter) checkSort(v reflect.Value) { } func (ss sliceSorter) less(v reflect.Value, i, j int) bool { vx, vy := v.Index(i), v.Index(j) - return ss.fnc.Call([]reflect.Value{vx, vy})[0].Bool() + vo := ss.fnc.Call([]reflect.Value{vx, vy})[0] + if vo.Kind() == reflect.Bool { + return vo.Bool() + } else { + return vo.Int() < 0 + } } -// SortMaps returns a [cmp.Transformer] option that flattens map[K]V types to be a -// sorted []struct{K, V}. The less function must be of the form -// "func(T, T) bool" which is used to sort any map with key K that is -// assignable to T. +// SortMaps returns a [cmp.Transformer] option that flattens map[K]V types to be +// a sorted []struct{K, V}. The lessOrCompareFunc function must be either +// a less function of the form "func(T, T) bool" or +// a compare function of the format "func(T, T) int" +// which is used to sort any map with key K that is assignable to T. // // Flattening the map into a slice has the property that [cmp.Equal] is able to // use [cmp.Comparer] options on K or the K.Equal method if it exists. // -// The less function must be: +// A less function must be: // - Deterministic: less(x, y) == less(x, y) // - Irreflexive: !less(x, x) // - Transitive: if !less(x, y) and !less(y, z), then !less(x, z) // - Total: if x != y, then either less(x, y) or less(y, x) // +// A compare function must be: +// - Deterministic: compare(x, y) == compare(x, y) +// - Irreflexive: compare(x, x) == 0 +// - Transitive: if compare(x, y) < 0 and compare(y, z) < 0, then compare(x, z) < 0 +// - Total: if x != y, then compare(x, y) != 0 +// // SortMaps can be used in conjunction with [EquateEmpty]. -func SortMaps(lessFunc interface{}) cmp.Option { - vf := reflect.ValueOf(lessFunc) - if !function.IsType(vf.Type(), function.Less) || vf.IsNil() { - panic(fmt.Sprintf("invalid less function: %T", lessFunc)) +func SortMaps(lessOrCompareFunc interface{}) cmp.Option { + vf := reflect.ValueOf(lessOrCompareFunc) + if (!function.IsType(vf.Type(), function.Less) && !function.IsType(vf.Type(), function.Compare)) || vf.IsNil() { + panic(fmt.Sprintf("invalid less or compare function: %T", lessOrCompareFunc)) } ms := mapSorter{vf.Type().In(0), vf} return cmp.FilterValues(ms.filter, cmp.Transformer("cmpopts.SortMaps", ms.sort)) @@ -143,5 +162,10 @@ func (ms mapSorter) checkSort(v reflect.Value) { } func (ms mapSorter) less(v reflect.Value, i, j int) bool { vx, vy := v.Index(i).Field(0), v.Index(j).Field(0) - return ms.fnc.Call([]reflect.Value{vx, vy})[0].Bool() + vo := ms.fnc.Call([]reflect.Value{vx, vy})[0] + if vo.Kind() == reflect.Bool { + return vo.Bool() + } else { + return vo.Int() < 0 + } } diff --git a/vendor/github.com/google/go-cmp/cmp/internal/function/func.go b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go index d127d43623..def01a6be3 100644 --- a/vendor/github.com/google/go-cmp/cmp/internal/function/func.go +++ b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go @@ -19,6 +19,7 @@ const ( tbFunc // func(T) bool ttbFunc // func(T, T) bool + ttiFunc // func(T, T) int trbFunc // func(T, R) bool tibFunc // func(T, I) bool trFunc // func(T) R @@ -28,11 +29,13 @@ const ( Transformer = trFunc // func(T) R ValueFilter = ttbFunc // func(T, T) bool Less = ttbFunc // func(T, T) bool + Compare = ttiFunc // func(T, T) int ValuePredicate = tbFunc // func(T) bool KeyValuePredicate = trbFunc // func(T, R) bool ) var boolType = reflect.TypeOf(true) +var intType = reflect.TypeOf(0) // IsType reports whether the reflect.Type is of the specified function type. func IsType(t reflect.Type, ft funcType) bool { @@ -49,6 +52,10 @@ func IsType(t reflect.Type, ft funcType) bool { if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == boolType { return true } + case ttiFunc: // func(T, T) int + if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == intType { + return true + } case trbFunc: // func(T, R) bool if ni == 2 && no == 1 && t.Out(0) == boolType { return true diff --git a/vendor/github.com/google/go-cmp/cmp/options.go b/vendor/github.com/google/go-cmp/cmp/options.go index 754496f3b3..ba3fce81ff 100644 --- a/vendor/github.com/google/go-cmp/cmp/options.go +++ b/vendor/github.com/google/go-cmp/cmp/options.go @@ -232,7 +232,15 @@ func (validator) apply(s *state, vx, vy reflect.Value) { if t := s.curPath.Index(-2).Type(); t.Name() != "" { // Named type with unexported fields. name = fmt.Sprintf("%q.%v", t.PkgPath(), t.Name()) // e.g., "path/to/package".MyType - if _, ok := reflect.New(t).Interface().(error); ok { + isProtoMessage := func(t reflect.Type) bool { + m, ok := reflect.PointerTo(t).MethodByName("ProtoReflect") + return ok && m.Type.NumIn() == 1 && m.Type.NumOut() == 1 && + m.Type.Out(0).PkgPath() == "google.golang.org/protobuf/reflect/protoreflect" && + m.Type.Out(0).Name() == "Message" + } + if isProtoMessage(t) { + help = `consider using "google.golang.org/protobuf/testing/protocmp".Transform to compare proto.Message types` + } else if _, ok := reflect.New(t).Interface().(error); ok { help = "consider using cmpopts.EquateErrors to compare error values" } else if t.Comparable() { help = "consider using cmpopts.EquateComparable to compare comparable Go types" diff --git a/vendor/github.com/google/go-github/v68/github/orgs_rules.go b/vendor/github.com/google/go-github/v68/github/orgs_rules.go deleted file mode 100644 index 37c06a7333..0000000000 --- a/vendor/github.com/google/go-github/v68/github/orgs_rules.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2023 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "fmt" -) - -// GetAllOrganizationRulesets gets all the rulesets for the specified organization. -// -// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-all-organization-repository-rulesets -// -//meta:operation GET /orgs/{org}/rulesets -func (s *OrganizationsService) GetAllOrganizationRulesets(ctx context.Context, org string) ([]*Ruleset, *Response, error) { - u := fmt.Sprintf("orgs/%v/rulesets", org) - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var rulesets []*Ruleset - resp, err := s.client.Do(ctx, req, &rulesets) - if err != nil { - return nil, resp, err - } - - return rulesets, resp, nil -} - -// CreateOrganizationRuleset creates a ruleset for the specified organization. -// -// GitHub API docs: https://docs.github.com/rest/orgs/rules#create-an-organization-repository-ruleset -// -//meta:operation POST /orgs/{org}/rulesets -func (s *OrganizationsService) CreateOrganizationRuleset(ctx context.Context, org string, rs *Ruleset) (*Ruleset, *Response, error) { - u := fmt.Sprintf("orgs/%v/rulesets", org) - - req, err := s.client.NewRequest("POST", u, rs) - if err != nil { - return nil, nil, err - } - - var ruleset *Ruleset - resp, err := s.client.Do(ctx, req, &ruleset) - if err != nil { - return nil, resp, err - } - - return ruleset, resp, nil -} - -// GetOrganizationRuleset gets a ruleset from the specified organization. -// -// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-an-organization-repository-ruleset -// -//meta:operation GET /orgs/{org}/rulesets/{ruleset_id} -func (s *OrganizationsService) GetOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Ruleset, *Response, error) { - u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var ruleset *Ruleset - resp, err := s.client.Do(ctx, req, &ruleset) - if err != nil { - return nil, resp, err - } - - return ruleset, resp, nil -} - -// UpdateOrganizationRuleset updates a ruleset from the specified organization. -// -// GitHub API docs: https://docs.github.com/rest/orgs/rules#update-an-organization-repository-ruleset -// -//meta:operation PUT /orgs/{org}/rulesets/{ruleset_id} -func (s *OrganizationsService) UpdateOrganizationRuleset(ctx context.Context, org string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { - u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) - - req, err := s.client.NewRequest("PUT", u, rs) - if err != nil { - return nil, nil, err - } - - var ruleset *Ruleset - resp, err := s.client.Do(ctx, req, &ruleset) - if err != nil { - return nil, resp, err - } - - return ruleset, resp, nil -} - -// DeleteOrganizationRuleset deletes a ruleset from the specified organization. -// -// GitHub API docs: https://docs.github.com/rest/orgs/rules#delete-an-organization-repository-ruleset -// -//meta:operation DELETE /orgs/{org}/rulesets/{ruleset_id} -func (s *OrganizationsService) DeleteOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Response, error) { - u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) - - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/v68/github/packages.go b/vendor/github.com/google/go-github/v68/github/packages.go deleted file mode 100644 index ef7df07405..0000000000 --- a/vendor/github.com/google/go-github/v68/github/packages.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2020 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -// Package represents a GitHub package. -type Package struct { - ID *int64 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - PackageType *string `json:"package_type,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - Owner *User `json:"owner,omitempty"` - PackageVersion *PackageVersion `json:"package_version,omitempty"` - Registry *PackageRegistry `json:"registry,omitempty"` - URL *string `json:"url,omitempty"` - VersionCount *int64 `json:"version_count,omitempty"` - Visibility *string `json:"visibility,omitempty"` - Repository *Repository `json:"repository,omitempty"` -} - -func (p Package) String() string { - return Stringify(p) -} - -// PackageVersion represents a GitHub package version. -type PackageVersion struct { - ID *int64 `json:"id,omitempty"` - Version *string `json:"version,omitempty"` - Summary *string `json:"summary,omitempty"` - Body *string `json:"body,omitempty"` - BodyHTML *string `json:"body_html,omitempty"` - Release *PackageRelease `json:"release,omitempty"` - Manifest *string `json:"manifest,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - TagName *string `json:"tag_name,omitempty"` - TargetCommitish *string `json:"target_commitish,omitempty"` - TargetOID *string `json:"target_oid,omitempty"` - Draft *bool `json:"draft,omitempty"` - Prerelease *bool `json:"prerelease,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - PackageFiles []*PackageFile `json:"package_files,omitempty"` - Author *User `json:"author,omitempty"` - InstallationCommand *string `json:"installation_command,omitempty"` - Metadata *PackageMetadata `json:"metadata,omitempty"` - PackageHTMLURL *string `json:"package_html_url,omitempty"` - Name *string `json:"name,omitempty"` - URL *string `json:"url,omitempty"` -} - -func (pv PackageVersion) String() string { - return Stringify(pv) -} - -// PackageRelease represents a GitHub package version release. -type PackageRelease struct { - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - ID *int64 `json:"id,omitempty"` - TagName *string `json:"tag_name,omitempty"` - TargetCommitish *string `json:"target_commitish,omitempty"` - Name *string `json:"name,omitempty"` - Draft *bool `json:"draft,omitempty"` - Author *User `json:"author,omitempty"` - Prerelease *bool `json:"prerelease,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - PublishedAt *Timestamp `json:"published_at,omitempty"` -} - -func (r PackageRelease) String() string { - return Stringify(r) -} - -// PackageFile represents a GitHub package version release file. -type PackageFile struct { - DownloadURL *string `json:"download_url,omitempty"` - ID *int64 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - SHA256 *string `json:"sha256,omitempty"` - SHA1 *string `json:"sha1,omitempty"` - MD5 *string `json:"md5,omitempty"` - ContentType *string `json:"content_type,omitempty"` - State *string `json:"state,omitempty"` - Author *User `json:"author,omitempty"` - Size *int64 `json:"size,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` -} - -func (pf PackageFile) String() string { - return Stringify(pf) -} - -// PackageRegistry represents a GitHub package registry. -type PackageRegistry struct { - AboutURL *string `json:"about_url,omitempty"` - Name *string `json:"name,omitempty"` - Type *string `json:"type,omitempty"` - URL *string `json:"url,omitempty"` - Vendor *string `json:"vendor,omitempty"` -} - -func (r PackageRegistry) String() string { - return Stringify(r) -} - -// PackageListOptions represents the optional list options for a package. -type PackageListOptions struct { - // Visibility of packages "public", "internal" or "private". - Visibility *string `url:"visibility,omitempty"` - - // PackageType represents the type of package. - // It can be one of "npm", "maven", "rubygems", "nuget", "docker", or "container". - PackageType *string `url:"package_type,omitempty"` - - // State of package either "active" or "deleted". - State *string `url:"state,omitempty"` - - ListOptions -} - -// PackageMetadata represents metadata from a package. -type PackageMetadata struct { - PackageType *string `json:"package_type,omitempty"` - Container *PackageContainerMetadata `json:"container,omitempty"` -} - -func (r PackageMetadata) String() string { - return Stringify(r) -} - -// PackageContainerMetadata represents container metadata for docker container packages. -type PackageContainerMetadata struct { - Tags []string `json:"tags,omitempty"` -} - -func (r PackageContainerMetadata) String() string { - return Stringify(r) -} diff --git a/vendor/github.com/google/go-github/v68/github/repos_rules.go b/vendor/github.com/google/go-github/v68/github/repos_rules.go deleted file mode 100644 index b113553a24..0000000000 --- a/vendor/github.com/google/go-github/v68/github/repos_rules.go +++ /dev/null @@ -1,995 +0,0 @@ -// Copyright 2023 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package github - -import ( - "context" - "encoding/json" - "fmt" -) - -// BypassActor represents the bypass actors from a ruleset. -type BypassActor struct { - ActorID *int64 `json:"actor_id,omitempty"` - // Possible values for ActorType are: RepositoryRole, Team, Integration, OrganizationAdmin - ActorType *string `json:"actor_type,omitempty"` - // Possible values for BypassMode are: always, pull_request - BypassMode *string `json:"bypass_mode,omitempty"` -} - -// RulesetLink represents a single link object from GitHub ruleset request _links. -type RulesetLink struct { - HRef *string `json:"href,omitempty"` -} - -// RulesetLinks represents the "_links" object in a Ruleset. -type RulesetLinks struct { - Self *RulesetLink `json:"self,omitempty"` -} - -// RulesetRefConditionParameters represents the conditions object for ref_names. -type RulesetRefConditionParameters struct { - Include []string `json:"include"` - Exclude []string `json:"exclude"` -} - -// RulesetRepositoryNamesConditionParameters represents the conditions object for repository_names. -type RulesetRepositoryNamesConditionParameters struct { - Include []string `json:"include"` - Exclude []string `json:"exclude"` - Protected *bool `json:"protected,omitempty"` -} - -// RulesetRepositoryIDsConditionParameters represents the conditions object for repository_ids. -type RulesetRepositoryIDsConditionParameters struct { - RepositoryIDs []int64 `json:"repository_ids,omitempty"` -} - -// RulesetRepositoryPropertyTargetParameters represents a repository_property name and values to be used for targeting. -type RulesetRepositoryPropertyTargetParameters struct { - Name string `json:"name"` - Values []string `json:"property_values"` - Source *string `json:"source,omitempty"` -} - -// RulesetRepositoryPropertyConditionParameters represents the conditions object for repository_property. -type RulesetRepositoryPropertyConditionParameters struct { - Include []RulesetRepositoryPropertyTargetParameters `json:"include"` - Exclude []RulesetRepositoryPropertyTargetParameters `json:"exclude"` -} - -// RulesetConditions represents the conditions object in a ruleset. -// Set either RepositoryName or RepositoryID or RepositoryProperty, not more than one. -type RulesetConditions struct { - RefName *RulesetRefConditionParameters `json:"ref_name,omitempty"` - RepositoryName *RulesetRepositoryNamesConditionParameters `json:"repository_name,omitempty"` - RepositoryID *RulesetRepositoryIDsConditionParameters `json:"repository_id,omitempty"` - RepositoryProperty *RulesetRepositoryPropertyConditionParameters `json:"repository_property,omitempty"` -} - -// RulePatternParameters represents the rule pattern parameters. -type RulePatternParameters struct { - Name *string `json:"name,omitempty"` - // If Negate is true, the rule will fail if the pattern matches. - Negate *bool `json:"negate,omitempty"` - // Possible values for Operator are: starts_with, ends_with, contains, regex - Operator string `json:"operator"` - Pattern string `json:"pattern"` -} - -// RuleFileParameters represents a list of file paths. -type RuleFileParameters struct { - RestrictedFilePaths *[]string `json:"restricted_file_paths"` -} - -// RuleMaxFilePathLengthParameters represents the max_file_path_length rule parameters. -type RuleMaxFilePathLengthParameters struct { - MaxFilePathLength int `json:"max_file_path_length"` -} - -// RuleFileExtensionRestrictionParameters represents the file_extension_restriction rule parameters. -type RuleFileExtensionRestrictionParameters struct { - RestrictedFileExtensions []string `json:"restricted_file_extensions"` -} - -// RuleMaxFileSizeParameters represents the max_file_size rule parameters. -type RuleMaxFileSizeParameters struct { - MaxFileSize int64 `json:"max_file_size"` -} - -// UpdateAllowsFetchAndMergeRuleParameters represents the update rule parameters. -type UpdateAllowsFetchAndMergeRuleParameters struct { - UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge"` -} - -// RequiredDeploymentEnvironmentsRuleParameters represents the required_deployments rule parameters. -type RequiredDeploymentEnvironmentsRuleParameters struct { - RequiredDeploymentEnvironments []string `json:"required_deployment_environments"` -} - -// PullRequestRuleParameters represents the pull_request rule parameters. -type PullRequestRuleParameters struct { - DismissStaleReviewsOnPush bool `json:"dismiss_stale_reviews_on_push"` - RequireCodeOwnerReview bool `json:"require_code_owner_review"` - RequireLastPushApproval bool `json:"require_last_push_approval"` - RequiredApprovingReviewCount int `json:"required_approving_review_count"` - RequiredReviewThreadResolution bool `json:"required_review_thread_resolution"` -} - -// RuleRequiredStatusChecks represents the RequiredStatusChecks for the RequiredStatusChecksRuleParameters object. -type RuleRequiredStatusChecks struct { - Context string `json:"context"` - IntegrationID *int64 `json:"integration_id,omitempty"` -} - -// MergeQueueRuleParameters represents the merge_queue rule parameters. -type MergeQueueRuleParameters struct { - CheckResponseTimeoutMinutes int `json:"check_response_timeout_minutes"` - // Possible values for GroupingStrategy are: ALLGREEN, HEADGREEN - GroupingStrategy string `json:"grouping_strategy"` - MaxEntriesToBuild int `json:"max_entries_to_build"` - MaxEntriesToMerge int `json:"max_entries_to_merge"` - // Possible values for MergeMethod are: MERGE, SQUASH, REBASE - MergeMethod string `json:"merge_method"` - MinEntriesToMerge int `json:"min_entries_to_merge"` - MinEntriesToMergeWaitMinutes int `json:"min_entries_to_merge_wait_minutes"` -} - -// RequiredStatusChecksRuleParameters represents the required_status_checks rule parameters. -type RequiredStatusChecksRuleParameters struct { - DoNotEnforceOnCreate *bool `json:"do_not_enforce_on_create,omitempty"` - RequiredStatusChecks []RuleRequiredStatusChecks `json:"required_status_checks"` - StrictRequiredStatusChecksPolicy bool `json:"strict_required_status_checks_policy"` -} - -// RuleRequiredWorkflow represents the Workflow for the RequireWorkflowsRuleParameters object. -type RuleRequiredWorkflow struct { - Path string `json:"path"` - Ref *string `json:"ref,omitempty"` - RepositoryID *int64 `json:"repository_id,omitempty"` - Sha *string `json:"sha,omitempty"` -} - -// RequiredWorkflowsRuleParameters represents the workflows rule parameters. -type RequiredWorkflowsRuleParameters struct { - DoNotEnforceOnCreate bool `json:"do_not_enforce_on_create,omitempty"` - RequiredWorkflows []*RuleRequiredWorkflow `json:"workflows"` -} - -// RuleRequiredCodeScanningTool represents a single required code-scanning tool for the RequiredCodeScanningParameters object. -type RuleRequiredCodeScanningTool struct { - AlertsThreshold string `json:"alerts_threshold"` - SecurityAlertsThreshold string `json:"security_alerts_threshold"` - Tool string `json:"tool"` -} - -// RequiredCodeScanningRuleParameters represents the code_scanning rule parameters. -type RequiredCodeScanningRuleParameters struct { - RequiredCodeScanningTools []*RuleRequiredCodeScanningTool `json:"code_scanning_tools"` -} - -// RepositoryRule represents a GitHub Rule. -type RepositoryRule struct { - Type string `json:"type"` - Parameters *json.RawMessage `json:"parameters,omitempty"` - RulesetSourceType string `json:"ruleset_source_type"` - RulesetSource string `json:"ruleset_source"` - RulesetID int64 `json:"ruleset_id"` -} - -// RepositoryRulesetEditedChanges represents the changes made to a repository ruleset. -type RepositoryRulesetEditedChanges struct { - Name *RepositoryRulesetEditedSource `json:"name,omitempty"` - Enforcement *RepositoryRulesetEditedSource `json:"enforcement,omitempty"` - Conditions *RepositoryRulesetEditedConditions `json:"conditions,omitempty"` - Rules *RepositoryRulesetEditedRules `json:"rules,omitempty"` -} - -// RepositoryRulesetEditedSource represents a source change for the ruleset. -type RepositoryRulesetEditedSource struct { - From *string `json:"from,omitempty"` -} - -// RepositoryRulesetEditedSources represents multiple source changes for the ruleset. -type RepositoryRulesetEditedSources struct { - From []string `json:"from,omitempty"` -} - -// RepositoryRulesetEditedConditions holds changes to conditions in a ruleset. -type RepositoryRulesetEditedConditions struct { - Added []*RepositoryRulesetRefCondition `json:"added,omitempty"` - Deleted []*RepositoryRulesetRefCondition `json:"deleted,omitempty"` - Updated []*RepositoryRulesetEditedUpdatedConditions `json:"updated,omitempty"` -} - -// RepositoryRulesetEditedRules holds changes to rules in a ruleset. -type RepositoryRulesetEditedRules struct { - Added []*RepositoryRulesetRule `json:"added,omitempty"` - Deleted []*RepositoryRulesetRule `json:"deleted,omitempty"` - Updated []*RepositoryRulesetUpdatedRules `json:"updated,omitempty"` -} - -// RepositoryRulesetRefCondition represents a reference condition for the ruleset. -type RepositoryRulesetRefCondition struct { - RefName *RulesetRefConditionParameters `json:"ref_name,omitempty"` -} - -// RepositoryRulesetEditedUpdatedConditions holds updates to conditions in a ruleset. -type RepositoryRulesetEditedUpdatedConditions struct { - Condition *RepositoryRulesetRefCondition `json:"condition,omitempty"` - Changes *RepositoryRulesetUpdatedConditionsEdited `json:"changes,omitempty"` -} - -// RepositoryRulesetUpdatedConditionsEdited holds the edited updates to conditions in a ruleset. -type RepositoryRulesetUpdatedConditionsEdited struct { - ConditionType *RepositoryRulesetEditedSource `json:"condition_type,omitempty"` - Target *RepositoryRulesetEditedSource `json:"target,omitempty"` - Include *RepositoryRulesetEditedSources `json:"include,omitempty"` - Exclude *RepositoryRulesetEditedSources `json:"exclude,omitempty"` -} - -// RepositoryRulesetUpdatedRules holds updates to rules in a ruleset. -type RepositoryRulesetUpdatedRules struct { - Rule *RepositoryRulesetRule `json:"rule,omitempty"` - Changes *RepositoryRulesetEditedRuleChanges `json:"changes,omitempty"` -} - -// RepositoryRulesetEditedRuleChanges holds changes made to a rule in a ruleset. -type RepositoryRulesetEditedRuleChanges struct { - Configuration *RepositoryRulesetEditedSources `json:"configuration,omitempty"` - RuleType *RepositoryRulesetEditedSources `json:"rule_type,omitempty"` - Pattern *RepositoryRulesetEditedSources `json:"pattern,omitempty"` -} - -// RepositoryRuleset represents the structure of a ruleset associated with a GitHub repository. -type RepositoryRuleset struct { - ID int64 `json:"id"` - Name string `json:"name"` - // Possible values for target: "branch", "tag", "push" - Target *string `json:"target,omitempty"` - // Possible values for source type: "Repository", "Organization" - SourceType *string `json:"source_type,omitempty"` - Source string `json:"source"` - // Possible values for enforcement: "disabled", "active", "evaluate" - Enforcement string `json:"enforcement"` - BypassActors []*BypassActor `json:"bypass_actors,omitempty"` - // Possible values for current user can bypass: "always", "pull_requests_only", "never" - CurrentUserCanBypass *string `json:"current_user_can_bypass,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Links *RepositoryRulesetLink `json:"_links,omitempty"` - Conditions json.RawMessage `json:"conditions,omitempty"` - Rules []*RepositoryRulesetRule `json:"rules,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` -} - -// RepositoryRulesetRule represents individual rules which are present in a repository's ruleset. -type RepositoryRulesetRule struct { - Creation *RepositoryRulesetRuleType `json:"creation,omitempty"` - Update *RepositoryRulesetUpdateRule `json:"update,omitempty"` - Deletion *RepositoryRulesetRuleType `json:"deletion,omitempty"` - RequiredLinearHistory *RepositoryRulesetRuleType `json:"required_linear_history,omitempty"` - MergeQueue *RepositoryRulesetMergeQueueRule `json:"merge_queue,omitempty"` - RequiredDeployments *RepositoryRulesetRequiredDeploymentsRule `json:"required_deployments,omitempty"` - RequiredSignatures *RepositoryRulesetRuleType `json:"required_signatures,omitempty"` - PullRequest *RepositoryRulesetPullRequestRule `json:"pull_request,omitempty"` - RequiredStatusChecks *RepositoryRulesetRequiredStatusChecksRule `json:"required_status_checks,omitempty"` - NonFastForward *RepositoryRulesetRuleType `json:"non_fast_forward,omitempty"` - CommitMessagePattern *RepositoryRulesetPatternRule `json:"commit_message_pattern,omitempty"` - CommitAuthorEmailPattern *RepositoryRulesetPatternRule `json:"commit_author_email_pattern,omitempty"` - CommitterEmailPattern *RepositoryRulesetPatternRule `json:"committer_email_pattern,omitempty"` - BranchNamePattern *RepositoryRulesetPatternRule `json:"branch_name_pattern,omitempty"` - TagNamePattern *RepositoryRulesetPatternRule `json:"tag_name_pattern,omitempty"` - FilePathRestriction *RepositoryRulesetFilePathRestrictionRule `json:"file_path_restriction,omitempty"` - MaxFilePathLength *RepositoryRulesetMaxFilePathLengthRule `json:"max_file_path_length,omitempty"` - FileExtensionRestriction *RepositoryRulesetFileExtensionRestrictionRule `json:"file_extension_restriction,omitempty"` - MaxFileSize *RepositoryRulesetMaxFileSizeRule `json:"max_file_size,omitempty"` - Workflows *RepositoryRulesetWorkflowsRule `json:"workflows,omitempty"` - CodeScanning *RepositoryRulesetCodeScanningRule `json:"code_scanning,omitempty"` -} - -// RepositoryRulesetLink represents Links associated with a repository's rulesets. These links are used to provide more information about the ruleset. -type RepositoryRulesetLink struct { - Self *RulesetLink `json:"self,omitempty"` - HTML *RulesetLink `json:"html,omitempty"` -} - -// RepositoryRulesetRuleType represents the type of a ruleset rule. -type RepositoryRulesetRuleType struct { - Type string `json:"type"` -} - -// RepositoryRulesetUpdateRule defines an update rule for the repository. -type RepositoryRulesetUpdateRule struct { - // Type can be one of: "update". - Type string `json:"type"` - Parameters *UpdateAllowsFetchAndMergeRuleParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetMergeQueueRule defines a merge queue rule for the repository. -type RepositoryRulesetMergeQueueRule struct { - // Type can be one of: "merge_queue". - Type string `json:"type"` - Parameters *MergeQueueRuleParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetRequiredDeploymentsRule defines a rule for required deployments. -type RepositoryRulesetRequiredDeploymentsRule struct { - // Type can be one of: "required_deployments". - Type string `json:"type"` - Parameters *RequiredDeploymentEnvironmentsRuleParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetPullRequestRule defines a rule for pull requests. -type RepositoryRulesetPullRequestRule struct { - // Type can be one of: "pull_request". - - Type string `json:"type"` - Parameters *PullRequestRuleParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetRequiredStatusChecksRule defines a rule for required status checks. -type RepositoryRulesetRequiredStatusChecksRule struct { - // Type can be one of: "required_status_checks". - - Type string `json:"type"` - Parameters *RequiredStatusChecksRuleParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetPatternRule defines a pattern rule for the repository. -type RepositoryRulesetPatternRule struct { - Type string `json:"type"` - Parameters *RulePatternParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetFilePathRestrictionRule defines a file path restriction rule for the repository. -type RepositoryRulesetFilePathRestrictionRule struct { - // Type can be one of: "file_path_restriction". - Type string `json:"type"` - Parameters *RuleFileParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetMaxFilePathLengthRule defines a maximum file path length rule for the repository. -type RepositoryRulesetMaxFilePathLengthRule struct { - // Type can be one of: "max_file_path_length". - - Type string `json:"type"` - Parameters *RuleMaxFilePathLengthParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetFileExtensionRestrictionRule defines a file extension restriction rule for the repository. -type RepositoryRulesetFileExtensionRestrictionRule struct { - // Type can be one of: "file_extension_restriction". - Type string `json:"type"` - Parameters *RuleFileExtensionRestrictionParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetMaxFileSizeRule defines a maximum file size rule for the repository. -type RepositoryRulesetMaxFileSizeRule struct { - // Type can be one of: "max_file_size". - Type string `json:"type"` - Parameters *RuleMaxFileSizeParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetWorkflowsRule defines a workflow rule for the repository. -type RepositoryRulesetWorkflowsRule struct { - // Type can be one of: "workflows". - Type string `json:"type"` - Parameters *RequiredWorkflowsRuleParameters `json:"parameters,omitempty"` -} - -// RepositoryRulesetCodeScanningRule defines a code scanning rule for the repository. -type RepositoryRulesetCodeScanningRule struct { - // Type can be one of: "code_scanning". - Type string `json:"type"` - Parameters *RuleCodeScanningParameters `json:"parameters,omitempty"` -} - -// RuleCodeScanningParameters defines parameters for code scanning rules. -type RuleCodeScanningParameters struct { - CodeScanningTools []*CodeScanningTool `json:"code_scanning_tools,omitempty"` -} - -// CodeScanningTool defines a specific tool used for code scanning. -type CodeScanningTool struct { - AlertsThreshold string `json:"alerts_threshold"` - SecurityAlertsThreshold string `json:"security_alerts_threshold"` - Tool string `json:"tool"` -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -// This helps us handle the fact that RepositoryRule parameter field can be of numerous types. -func (r *RepositoryRule) UnmarshalJSON(data []byte) error { - type rule RepositoryRule - var repositoryRule rule - if err := json.Unmarshal(data, &repositoryRule); err != nil { - return err - } - - r.RulesetID = repositoryRule.RulesetID - r.RulesetSourceType = repositoryRule.RulesetSourceType - r.RulesetSource = repositoryRule.RulesetSource - r.Type = repositoryRule.Type - - switch repositoryRule.Type { - case "creation", "deletion", "non_fast_forward", "required_linear_history", "required_signatures": - r.Parameters = nil - case "update": - if repositoryRule.Parameters == nil { - r.Parameters = nil - return nil - } - params := UpdateAllowsFetchAndMergeRuleParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "merge_queue": - if repositoryRule.Parameters == nil { - r.Parameters = nil - return nil - } - params := MergeQueueRuleParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "required_deployments": - params := RequiredDeploymentEnvironmentsRuleParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "commit_message_pattern", "commit_author_email_pattern", "committer_email_pattern", "branch_name_pattern", "tag_name_pattern": - params := RulePatternParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "pull_request": - params := PullRequestRuleParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "required_status_checks": - params := RequiredStatusChecksRuleParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "workflows": - params := RequiredWorkflowsRuleParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "file_path_restriction": - params := RuleFileParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "code_scanning": - params := RequiredCodeScanningRuleParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "max_file_path_length": - params := RuleMaxFilePathLengthParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "file_extension_restriction": - params := RuleFileExtensionRestrictionParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - case "max_file_size": - params := RuleMaxFileSizeParameters{} - if err := json.Unmarshal(*repositoryRule.Parameters, ¶ms); err != nil { - return err - } - bytes, _ := json.Marshal(params) - rawParams := json.RawMessage(bytes) - - r.Parameters = &rawParams - default: - r.Type = "" - r.Parameters = nil - return fmt.Errorf("RepositoryRule.Type %q is not yet implemented, unable to unmarshal (%#v)", repositoryRule.Type, repositoryRule) - } - - return nil -} - -// NewMergeQueueRule creates a rule to only allow merges via a merge queue. -func NewMergeQueueRule(params *MergeQueueRuleParameters) (rule *RepositoryRule) { - if params != nil { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "merge_queue", - Parameters: &rawParams, - } - } - return &RepositoryRule{ - Type: "merge_queue", - } -} - -// NewCreationRule creates a rule to only allow users with bypass permission to create matching refs. -func NewCreationRule() (rule *RepositoryRule) { - return &RepositoryRule{ - Type: "creation", - } -} - -// NewUpdateRule creates a rule to only allow users with bypass permission to update matching refs. -func NewUpdateRule(params *UpdateAllowsFetchAndMergeRuleParameters) (rule *RepositoryRule) { - if params != nil { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "update", - Parameters: &rawParams, - } - } - return &RepositoryRule{ - Type: "update", - } -} - -// NewDeletionRule creates a rule to only allow users with bypass permissions to delete matching refs. -func NewDeletionRule() (rule *RepositoryRule) { - return &RepositoryRule{ - Type: "deletion", - } -} - -// NewRequiredLinearHistoryRule creates a rule to prevent merge commits from being pushed to matching branches. -func NewRequiredLinearHistoryRule() (rule *RepositoryRule) { - return &RepositoryRule{ - Type: "required_linear_history", - } -} - -// NewRequiredDeploymentsRule creates a rule to require environments to be successfully deployed before they can be merged into the matching branches. -func NewRequiredDeploymentsRule(params *RequiredDeploymentEnvironmentsRuleParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "required_deployments", - Parameters: &rawParams, - } -} - -// NewRequiredSignaturesRule creates a rule a to require commits pushed to matching branches to have verified signatures. -func NewRequiredSignaturesRule() (rule *RepositoryRule) { - return &RepositoryRule{ - Type: "required_signatures", - } -} - -// NewPullRequestRule creates a rule to require all commits be made to a non-target branch and submitted via a pull request before they can be merged. -func NewPullRequestRule(params *PullRequestRuleParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "pull_request", - Parameters: &rawParams, - } -} - -// NewRequiredStatusChecksRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. -func NewRequiredStatusChecksRule(params *RequiredStatusChecksRuleParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "required_status_checks", - Parameters: &rawParams, - } -} - -// NewNonFastForwardRule creates a rule as part to prevent users with push access from force pushing to matching branches. -func NewNonFastForwardRule() (rule *RepositoryRule) { - return &RepositoryRule{ - Type: "non_fast_forward", - } -} - -// NewCommitMessagePatternRule creates a rule to restrict commit message patterns being pushed to matching branches. -func NewCommitMessagePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "commit_message_pattern", - Parameters: &rawParams, - } -} - -// NewCommitAuthorEmailPatternRule creates a rule to restrict commits with author email patterns being merged into matching branches. -func NewCommitAuthorEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "commit_author_email_pattern", - Parameters: &rawParams, - } -} - -// NewCommitterEmailPatternRule creates a rule to restrict commits with committer email patterns being merged into matching branches. -func NewCommitterEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "committer_email_pattern", - Parameters: &rawParams, - } -} - -// NewBranchNamePatternRule creates a rule to restrict branch patterns from being merged into matching branches. -func NewBranchNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "branch_name_pattern", - Parameters: &rawParams, - } -} - -// NewTagNamePatternRule creates a rule to restrict tag patterns contained in non-target branches from being merged into matching branches. -func NewTagNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "tag_name_pattern", - Parameters: &rawParams, - } -} - -// NewRequiredWorkflowsRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. -func NewRequiredWorkflowsRule(params *RequiredWorkflowsRuleParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "workflows", - Parameters: &rawParams, - } -} - -// NewRequiredCodeScanningRule creates a rule to require which tools must provide code scanning results before the reference is updated. -func NewRequiredCodeScanningRule(params *RequiredCodeScanningRuleParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "code_scanning", - Parameters: &rawParams, - } -} - -// NewFilePathRestrictionRule creates a rule to restrict file paths from being pushed to. -func NewFilePathRestrictionRule(params *RuleFileParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "file_path_restriction", - Parameters: &rawParams, - } -} - -// NewMaxFilePathLengthRule creates a rule to restrict file paths longer than the limit from being pushed. -func NewMaxFilePathLengthRule(params *RuleMaxFilePathLengthParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "max_file_path_length", - Parameters: &rawParams, - } -} - -// NewFileExtensionRestrictionRule creates a rule to restrict file extensions from being pushed to a commit. -func NewFileExtensionRestrictionRule(params *RuleFileExtensionRestrictionParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "file_extension_restriction", - Parameters: &rawParams, - } -} - -// NewMaxFileSizeRule creates a rule to restrict file sizes from being pushed to a commit. -func NewMaxFileSizeRule(params *RuleMaxFileSizeParameters) (rule *RepositoryRule) { - bytes, _ := json.Marshal(params) - - rawParams := json.RawMessage(bytes) - - return &RepositoryRule{ - Type: "max_file_size", - Parameters: &rawParams, - } -} - -// Ruleset represents a GitHub ruleset object. -type Ruleset struct { - ID *int64 `json:"id,omitempty"` - Name string `json:"name"` - // Possible values for Target are branch, tag, push - Target *string `json:"target,omitempty"` - // Possible values for SourceType are: Repository, Organization - SourceType *string `json:"source_type,omitempty"` - Source string `json:"source"` - // Possible values for Enforcement are: disabled, active, evaluate - Enforcement string `json:"enforcement"` - BypassActors []*BypassActor `json:"bypass_actors,omitempty"` - NodeID *string `json:"node_id,omitempty"` - Links *RulesetLinks `json:"_links,omitempty"` - Conditions *RulesetConditions `json:"conditions,omitempty"` - Rules []*RepositoryRule `json:"rules,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` -} - -// rulesetNoOmitBypassActors represents a GitHub ruleset object. The struct does not omit bypassActors if the field is nil or an empty array is passed. -type rulesetNoOmitBypassActors struct { - ID *int64 `json:"id,omitempty"` - Name string `json:"name"` - // Possible values for Target are branch, tag - Target *string `json:"target,omitempty"` - // Possible values for SourceType are: Repository, Organization - SourceType *string `json:"source_type,omitempty"` - Source string `json:"source"` - // Possible values for Enforcement are: disabled, active, evaluate - Enforcement string `json:"enforcement"` - BypassActors []*BypassActor `json:"bypass_actors"` - NodeID *string `json:"node_id,omitempty"` - Links *RulesetLinks `json:"_links,omitempty"` - Conditions *RulesetConditions `json:"conditions,omitempty"` - Rules []*RepositoryRule `json:"rules,omitempty"` -} - -// GetRulesForBranch gets all the rules that apply to the specified branch. -// -// GitHub API docs: https://docs.github.com/rest/repos/rules#get-rules-for-a-branch -// -//meta:operation GET /repos/{owner}/{repo}/rules/branches/{branch} -func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string) ([]*RepositoryRule, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch) - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var rules []*RepositoryRule - resp, err := s.client.Do(ctx, req, &rules) - if err != nil { - return nil, resp, err - } - - return rules, resp, nil -} - -// GetAllRulesets gets all the rules that apply to the specified repository. -// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. -// -// GitHub API docs: https://docs.github.com/rest/repos/rules#get-all-repository-rulesets -// -//meta:operation GET /repos/{owner}/{repo}/rulesets -func (s *RepositoriesService) GetAllRulesets(ctx context.Context, owner, repo string, includesParents bool) ([]*Ruleset, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/rulesets?includes_parents=%v", owner, repo, includesParents) - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var ruleset []*Ruleset - resp, err := s.client.Do(ctx, req, &ruleset) - if err != nil { - return nil, resp, err - } - - return ruleset, resp, nil -} - -// CreateRuleset creates a ruleset for the specified repository. -// -// GitHub API docs: https://docs.github.com/rest/repos/rules#create-a-repository-ruleset -// -//meta:operation POST /repos/{owner}/{repo}/rulesets -func (s *RepositoriesService) CreateRuleset(ctx context.Context, owner, repo string, rs *Ruleset) (*Ruleset, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/rulesets", owner, repo) - - req, err := s.client.NewRequest("POST", u, rs) - if err != nil { - return nil, nil, err - } - - var ruleset *Ruleset - resp, err := s.client.Do(ctx, req, &ruleset) - if err != nil { - return nil, resp, err - } - - return ruleset, resp, nil -} - -// GetRuleset gets a ruleset for the specified repository. -// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. -// -// GitHub API docs: https://docs.github.com/rest/repos/rules#get-a-repository-ruleset -// -//meta:operation GET /repos/{owner}/{repo}/rulesets/{ruleset_id} -func (s *RepositoriesService) GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*Ruleset, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/rulesets/%v?includes_parents=%v", owner, repo, rulesetID, includesParents) - - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, nil, err - } - - var ruleset *Ruleset - resp, err := s.client.Do(ctx, req, &ruleset) - if err != nil { - return nil, resp, err - } - - return ruleset, resp, nil -} - -// UpdateRuleset updates a ruleset for the specified repository. -// -// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset -// -//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} -func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) - - req, err := s.client.NewRequest("PUT", u, rs) - if err != nil { - return nil, nil, err - } - - var ruleset *Ruleset - resp, err := s.client.Do(ctx, req, &ruleset) - if err != nil { - return nil, resp, err - } - - return ruleset, resp, nil -} - -// UpdateRulesetNoBypassActor updates a ruleset for the specified repository. -// -// This function is necessary as the UpdateRuleset function does not marshal ByPassActor if passed as nil or an empty array. -// -// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset -// -//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} -func (s *RepositoriesService) UpdateRulesetNoBypassActor(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) - - rsNoBypassActor := &rulesetNoOmitBypassActors{} - - if rs != nil { - rsNoBypassActor = &rulesetNoOmitBypassActors{ - ID: rs.ID, - Name: rs.Name, - Target: rs.Target, - SourceType: rs.SourceType, - Source: rs.Source, - Enforcement: rs.Enforcement, - BypassActors: rs.BypassActors, - NodeID: rs.NodeID, - Links: rs.Links, - Conditions: rs.Conditions, - Rules: rs.Rules, - } - } - - req, err := s.client.NewRequest("PUT", u, rsNoBypassActor) - if err != nil { - return nil, nil, err - } - - var ruleSet *Ruleset - resp, err := s.client.Do(ctx, req, &ruleSet) - if err != nil { - return nil, resp, err - } - - return ruleSet, resp, nil -} - -// DeleteRuleset deletes a ruleset for the specified repository. -// -// GitHub API docs: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset -// -//meta:operation DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id} -func (s *RepositoriesService) DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) { - u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) - - req, err := s.client.NewRequest("DELETE", u, nil) - if err != nil { - return nil, err - } - - return s.client.Do(ctx, req, nil) -} diff --git a/vendor/github.com/google/go-github/v68/AUTHORS b/vendor/github.com/google/go-github/v70/AUTHORS similarity index 100% rename from vendor/github.com/google/go-github/v68/AUTHORS rename to vendor/github.com/google/go-github/v70/AUTHORS diff --git a/vendor/github.com/google/go-github/v68/LICENSE b/vendor/github.com/google/go-github/v70/LICENSE similarity index 100% rename from vendor/github.com/google/go-github/v68/LICENSE rename to vendor/github.com/google/go-github/v70/LICENSE diff --git a/vendor/github.com/google/go-github/v68/github/actions.go b/vendor/github.com/google/go-github/v70/github/actions.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions.go rename to vendor/github.com/google/go-github/v70/github/actions.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_artifacts.go b/vendor/github.com/google/go-github/v70/github/actions_artifacts.go similarity index 87% rename from vendor/github.com/google/go-github/v68/github/actions_artifacts.go rename to vendor/github.com/google/go-github/v70/github/actions_artifacts.go index e05a9a8402..2b560fa05d 100644 --- a/vendor/github.com/google/go-github/v68/github/actions_artifacts.go +++ b/vendor/github.com/google/go-github/v70/github/actions_artifacts.go @@ -142,6 +142,14 @@ func (s *ActionsService) GetArtifact(ctx context.Context, owner, repo string, ar func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo string, artifactID int64, maxRedirects int) (*url.URL, *Response, error) { u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v/zip", owner, repo, artifactID) + if s.client.RateLimitRedirectionalEndpoints { + return s.downloadArtifactWithRateLimit(ctx, u, maxRedirects) + } + + return s.downloadArtifactWithoutRateLimit(ctx, u, maxRedirects) +} + +func (s *ActionsService) downloadArtifactWithoutRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) if err != nil { return nil, nil, err @@ -149,7 +157,7 @@ func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo strin defer resp.Body.Close() if resp.StatusCode != http.StatusFound { - return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %v", resp.Status) } parsedURL, err := url.Parse(resp.Header.Get("Location")) @@ -160,6 +168,26 @@ func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo strin return parsedURL, newResponse(resp), nil } +func (s *ActionsService) downloadArtifactWithRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + url, resp, err := s.client.bareDoUntilFound(ctx, req, maxRedirects) + if err != nil { + return nil, resp, err + } + defer resp.Body.Close() + + // If we didn't receive a valid Location in a 302 response + if url == nil { + return nil, resp, fmt.Errorf("unexpected status code: %v", resp.Status) + } + + return url, resp, nil +} + // DeleteArtifact deletes a workflow run artifact. // // GitHub API docs: https://docs.github.com/rest/actions/artifacts#delete-an-artifact diff --git a/vendor/github.com/google/go-github/v68/github/actions_cache.go b/vendor/github.com/google/go-github/v70/github/actions_cache.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_cache.go rename to vendor/github.com/google/go-github/v70/github/actions_cache.go diff --git a/vendor/github.com/google/go-github/v70/github/actions_hosted_runners.go b/vendor/github.com/google/go-github/v70/github/actions_hosted_runners.go new file mode 100644 index 0000000000..dbe1f6b5b1 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/actions_hosted_runners.go @@ -0,0 +1,376 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" +) + +// HostedRunnerPublicIP represents the details of a public IP for GitHub-hosted runner. +type HostedRunnerPublicIP struct { + Enabled bool `json:"enabled"` // Whether public IP is enabled. + Prefix string `json:"prefix"` // The prefix for the public IP. Example: 20.80.208.150 + Length int `json:"length"` // The length of the IP prefix. Example: 28 +} + +// HostedRunnerMachineSpec represents the details of a particular machine specification for GitHub-hosted runner. +type HostedRunnerMachineSpec struct { + ID string `json:"id"` // The ID used for the `size` parameter when creating a new runner. Example: 8-core + CPUCores int `json:"cpu_cores"` // The number of cores. Example: 8 + MemoryGB int `json:"memory_gb"` // The available RAM for the machine spec. Example: 32 + StorageGB int `json:"storage_gb"` // The available SSD storage for the machine spec. Example: 300 +} + +// HostedRunner represents a single GitHub-hosted runner with additional details. +type HostedRunner struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + RunnerGroupID *int64 `json:"runner_group_id,omitempty"` + Platform *string `json:"platform,omitempty"` + ImageDetails *HostedRunnerImageDetail `json:"image_details,omitempty"` + MachineSizeDetails *HostedRunnerMachineSpec `json:"machine_size_details,omitempty"` + Status *string `json:"status,omitempty"` + MaximumRunners *int64 `json:"maximum_runners,omitempty"` + PublicIPEnabled *bool `json:"public_ip_enabled,omitempty"` + PublicIPs []*HostedRunnerPublicIP `json:"public_ips,omitempty"` + LastActiveOn *Timestamp `json:"last_active_on,omitempty"` +} + +// HostedRunnerImageDetail represents the image details of a GitHub-hosted runners. +type HostedRunnerImageDetail struct { + ID *string `json:"id"` // The ID of the image. Use this ID for the `image` parameter when creating a new larger runner. Example: ubuntu-20.04 + SizeGB *int64 `json:"size_gb"` // Image size in GB. Example: 86 + DisplayName *string `json:"display_name"` // Display name for this image. Example: 20.04 + Source *string `json:"source"` // The image provider. Example: github, partner, custom + Version *string `json:"version"` // The image version of the hosted runner pool. Example: latest +} + +// HostedRunners represents a collection of GitHub-hosted runners for an organization. +type HostedRunners struct { + TotalCount int `json:"total_count"` + Runners []*HostedRunner `json:"runners"` +} + +// ListHostedRunners lists all the GitHub-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#list-github-hosted-runners-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners +func (s *ActionsService) ListHostedRunners(ctx context.Context, org string, opts *ListOptions) (*HostedRunners, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &HostedRunners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// HostedRunnerImage represents the image of GitHub-hosted runners. +// To list all available images, use GET /actions/hosted-runners/images/github-owned or GET /actions/hosted-runners/images/partner. +type HostedRunnerImage struct { + ID string `json:"id"` + Source string `json:"source"` + Version string `json:"version"` +} + +// HostedRunnerRequest specifies body parameters to Hosted Runner configuration. +type HostedRunnerRequest struct { + Name string `json:"name,omitempty"` + Image HostedRunnerImage `json:"image,omitempty"` + RunnerGroupID int64 `json:"runner_group_id,omitempty"` + Size string `json:"size,omitempty"` + MaximumRunners int64 `json:"maximum_runners,omitempty"` + EnableStaticIP bool `json:"enable_static_ip,omitempty"` + ImageVersion string `json:"image_version,omitempty"` +} + +// validateCreateHostedRunnerRequest validates the provided HostedRunnerRequest to ensure +// that all required fields are properly set and that no invalid fields are present for hosted runner create request. +// +// If any of these conditions are violated, an appropriate error message is returned. +// Otherwise, nil is returned, indicating the request is valid. +func validateCreateHostedRunnerRequest(request *HostedRunnerRequest) error { + if request.Size == "" { + return errors.New("size is required for creating a hosted runner") + } + if request.Image == (HostedRunnerImage{}) { + return errors.New("image is required for creating a hosted runner") + } + if request.Name == "" { + return errors.New("name is required for creating a hosted runner") + } + if request.RunnerGroupID == 0 { + return errors.New("runner group ID is required for creating a hosted runner") + } + if request.ImageVersion != "" { + return errors.New("imageVersion should not be set directly; use the Image struct to specify image details") + } + return nil +} + +// CreateHostedRunner creates a GitHub-hosted runner for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#create-a-github-hosted-runner-for-an-organization +// +//meta:operation POST /orgs/{org}/actions/hosted-runners +func (s *ActionsService) CreateHostedRunner(ctx context.Context, org string, request *HostedRunnerRequest) (*HostedRunner, *Response, error) { + if err := validateCreateHostedRunnerRequest(request); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("orgs/%v/actions/hosted-runners", org) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} + +// HostedRunnerImageSpecs represents the details of a GitHub-hosted runner image. +type HostedRunnerImageSpecs struct { + ID string `json:"id"` + Platform string `json:"platform"` + SizeGB int `json:"size_gb"` + DisplayName string `json:"display_name"` + Source string `json:"source"` +} + +// HostedRunnerImages represents the response containing the total count and details of runner images. +type HostedRunnerImages struct { + TotalCount int `json:"total_count"` + Images []*HostedRunnerImageSpecs `json:"images"` +} + +// GetHostedRunnerGitHubOwnedImages gets the list of GitHub-owned images available for GitHub-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-github-owned-images-for-github-hosted-runners-in-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/images/github-owned +func (s *ActionsService) GetHostedRunnerGitHubOwnedImages(ctx context.Context, org string) (*HostedRunnerImages, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/github-owned", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunnerImages := new(HostedRunnerImages) + resp, err := s.client.Do(ctx, req, hostedRunnerImages) + if err != nil { + return nil, resp, err + } + + return hostedRunnerImages, resp, nil +} + +// GetHostedRunnerPartnerImages gets the list of partner images available for GitHub-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-partner-images-for-github-hosted-runners-in-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/images/partner +func (s *ActionsService) GetHostedRunnerPartnerImages(ctx context.Context, org string) (*HostedRunnerImages, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/images/partner", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunnerImages := new(HostedRunnerImages) + resp, err := s.client.Do(ctx, req, hostedRunnerImages) + if err != nil { + return nil, resp, err + } + + return hostedRunnerImages, resp, nil +} + +// HostedRunnerPublicIPLimits represents the static public IP limits for GitHub-hosted runners. +type HostedRunnerPublicIPLimits struct { + PublicIPs *PublicIPUsage `json:"public_ips"` +} + +// PublicIPUsage provides details of static public IP limits for GitHub-hosted runners. +type PublicIPUsage struct { + Maximum int64 `json:"maximum"` // The maximum number of static public IP addresses that can be used for Hosted Runners. Example: 50 + CurrentUsage int64 `json:"current_usage"` // The current number of static public IP addresses in use by Hosted Runners. Example: 17 +} + +// GetHostedRunnerLimits gets the GitHub-hosted runners Static public IP Limits for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-limits-on-github-hosted-runners-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/limits +func (s *ActionsService) GetHostedRunnerLimits(ctx context.Context, org string) (*HostedRunnerPublicIPLimits, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/limits", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + publicIPLimits := new(HostedRunnerPublicIPLimits) + resp, err := s.client.Do(ctx, req, publicIPLimits) + if err != nil { + return nil, resp, err + } + + return publicIPLimits, resp, nil +} + +// HostedRunnerMachineSpecs represents the response containing the total count and details of machine specs for GitHub-hosted runners. +type HostedRunnerMachineSpecs struct { + TotalCount int `json:"total_count"` + MachineSpecs []*HostedRunnerMachineSpec `json:"machine_specs"` +} + +// GetHostedRunnerMachineSpecs gets the list of machine specs available for GitHub-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-github-hosted-runners-machine-specs-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/machine-sizes +func (s *ActionsService) GetHostedRunnerMachineSpecs(ctx context.Context, org string) (*HostedRunnerMachineSpecs, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/machine-sizes", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + machineSpecs := new(HostedRunnerMachineSpecs) + resp, err := s.client.Do(ctx, req, machineSpecs) + if err != nil { + return nil, resp, err + } + + return machineSpecs, resp, nil +} + +// HostedRunnerPlatforms represents the response containing the total count and platforms for GitHub-hosted runners. +type HostedRunnerPlatforms struct { + TotalCount int `json:"total_count"` + Platforms []string `json:"platforms"` +} + +// GetHostedRunnerPlatforms gets list of platforms available for GitHub-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-platforms-for-github-hosted-runners-in-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/platforms +func (s *ActionsService) GetHostedRunnerPlatforms(ctx context.Context, org string) (*HostedRunnerPlatforms, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/platforms", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + platforms := new(HostedRunnerPlatforms) + resp, err := s.client.Do(ctx, req, platforms) + if err != nil { + return nil, resp, err + } + + return platforms, resp, nil +} + +// GetHostedRunner gets a GitHub-hosted runner in an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#get-a-github-hosted-runner-for-an-organization +// +//meta:operation GET /orgs/{org}/actions/hosted-runners/{hosted_runner_id} +func (s *ActionsService) GetHostedRunner(ctx context.Context, org string, runnerID int64) (*HostedRunner, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/%v", org, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} + +// validateUpdateHostedRunnerRequest validates the provided HostedRunnerRequest to ensure +// that no disallowed updates are made for a hosted runner update request. +// +// If any of these conditions are violated, an appropriate error message is returned. +// Otherwise, nil is returned, indicating the request is valid for an update. +func validateUpdateHostedRunnerRequest(request *HostedRunnerRequest) error { + if request.Size != "" { + return errors.New("size cannot be updated, API does not support updating size") + } + if request.Image != (HostedRunnerImage{}) { + return errors.New("image struct should not be set directly; use the ImageVersion to specify version details") + } + return nil +} + +// UpdateHostedRunner updates a GitHub-hosted runner for an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#update-a-github-hosted-runner-for-an-organization +// +//meta:operation PATCH /orgs/{org}/actions/hosted-runners/{hosted_runner_id} +func (s *ActionsService) UpdateHostedRunner(ctx context.Context, org string, runnerID int64, updateReq HostedRunnerRequest) (*HostedRunner, *Response, error) { + if err := validateUpdateHostedRunnerRequest(&updateReq); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/%v", org, runnerID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} + +// DeleteHostedRunner deletes GitHub-hosted runner from an organization. +// +// GitHub API docs: https://docs.github.com/rest/actions/hosted-runners#delete-a-github-hosted-runner-for-an-organization +// +//meta:operation DELETE /orgs/{org}/actions/hosted-runners/{hosted_runner_id} +func (s *ActionsService) DeleteHostedRunner(ctx context.Context, org string, runnerID int64) (*HostedRunner, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/hosted-runners/%v", org, runnerID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_oidc.go b/vendor/github.com/google/go-github/v70/github/actions_oidc.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_oidc.go rename to vendor/github.com/google/go-github/v70/github/actions_oidc.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go b/vendor/github.com/google/go-github/v70/github/actions_permissions_enterprise.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_permissions_enterprise.go rename to vendor/github.com/google/go-github/v70/github/actions_permissions_enterprise.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go b/vendor/github.com/google/go-github/v70/github/actions_permissions_orgs.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_permissions_orgs.go rename to vendor/github.com/google/go-github/v70/github/actions_permissions_orgs.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_required_workflows.go b/vendor/github.com/google/go-github/v70/github/actions_required_workflows.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_required_workflows.go rename to vendor/github.com/google/go-github/v70/github/actions_required_workflows.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_runner_groups.go b/vendor/github.com/google/go-github/v70/github/actions_runner_groups.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_runner_groups.go rename to vendor/github.com/google/go-github/v70/github/actions_runner_groups.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_runners.go b/vendor/github.com/google/go-github/v70/github/actions_runners.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_runners.go rename to vendor/github.com/google/go-github/v70/github/actions_runners.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_secrets.go b/vendor/github.com/google/go-github/v70/github/actions_secrets.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_secrets.go rename to vendor/github.com/google/go-github/v70/github/actions_secrets.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_variables.go b/vendor/github.com/google/go-github/v70/github/actions_variables.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_variables.go rename to vendor/github.com/google/go-github/v70/github/actions_variables.go diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go b/vendor/github.com/google/go-github/v70/github/actions_workflow_jobs.go similarity index 86% rename from vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go rename to vendor/github.com/google/go-github/v70/github/actions_workflow_jobs.go index 84bbe5aa46..10067c8b26 100644 --- a/vendor/github.com/google/go-github/v68/github/actions_workflow_jobs.go +++ b/vendor/github.com/google/go-github/v70/github/actions_workflow_jobs.go @@ -150,6 +150,14 @@ func (s *ActionsService) GetWorkflowJobByID(ctx context.Context, owner, repo str func (s *ActionsService) GetWorkflowJobLogs(ctx context.Context, owner, repo string, jobID int64, maxRedirects int) (*url.URL, *Response, error) { u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/logs", owner, repo, jobID) + if s.client.RateLimitRedirectionalEndpoints { + return s.getWorkflowJobLogsWithRateLimit(ctx, u, maxRedirects) + } + + return s.getWorkflowJobLogsWithoutRateLimit(ctx, u, maxRedirects) +} + +func (s *ActionsService) getWorkflowJobLogsWithoutRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) if err != nil { return nil, nil, err @@ -157,9 +165,29 @@ func (s *ActionsService) GetWorkflowJobLogs(ctx context.Context, owner, repo str defer resp.Body.Close() if resp.StatusCode != http.StatusFound { - return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %v", resp.Status) } parsedURL, err := url.Parse(resp.Header.Get("Location")) return parsedURL, newResponse(resp), err } + +func (s *ActionsService) getWorkflowJobLogsWithRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + url, resp, err := s.client.bareDoUntilFound(ctx, req, maxRedirects) + if err != nil { + return nil, resp, err + } + defer resp.Body.Close() + + // If we didn't receive a valid Location in a 302 response + if url == nil { + return nil, resp, fmt.Errorf("unexpected status code: %v", resp.Status) + } + + return url, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go b/vendor/github.com/google/go-github/v70/github/actions_workflow_runs.go similarity index 82% rename from vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go rename to vendor/github.com/google/go-github/v70/github/actions_workflow_runs.go index 122ea1d0e2..20b9cfcd50 100644 --- a/vendor/github.com/google/go-github/v68/github/actions_workflow_runs.go +++ b/vendor/github.com/google/go-github/v70/github/actions_workflow_runs.go @@ -204,6 +204,7 @@ func (s *ActionsService) ListRepositoryWorkflowRuns(ctx context.Context, owner, } // GetWorkflowRunByID gets a specific workflow run by ID. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run // @@ -226,6 +227,7 @@ func (s *ActionsService) GetWorkflowRunByID(ctx context.Context, owner, repo str } // GetWorkflowRunAttempt gets a specific workflow run attempt. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run-attempt // @@ -252,6 +254,7 @@ func (s *ActionsService) GetWorkflowRunAttempt(ctx context.Context, owner, repo } // GetWorkflowRunAttemptLogs gets a redirect URL to download a plain text file of logs for a workflow run for attempt number. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve a workflow run ID from the DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-attempt-logs // @@ -259,6 +262,14 @@ func (s *ActionsService) GetWorkflowRunAttempt(ctx context.Context, owner, repo func (s *ActionsService) GetWorkflowRunAttemptLogs(ctx context.Context, owner, repo string, runID int64, attemptNumber int, maxRedirects int) (*url.URL, *Response, error) { u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/attempts/%v/logs", owner, repo, runID, attemptNumber) + if s.client.RateLimitRedirectionalEndpoints { + return s.getWorkflowRunAttemptLogsWithRateLimit(ctx, u, maxRedirects) + } + + return s.getWorkflowRunAttemptLogsWithoutRateLimit(ctx, u, maxRedirects) +} + +func (s *ActionsService) getWorkflowRunAttemptLogsWithoutRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) if err != nil { return nil, nil, err @@ -266,14 +277,35 @@ func (s *ActionsService) GetWorkflowRunAttemptLogs(ctx context.Context, owner, r defer resp.Body.Close() if resp.StatusCode != http.StatusFound { - return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %v", resp.Status) } parsedURL, err := url.Parse(resp.Header.Get("Location")) return parsedURL, newResponse(resp), err } +func (s *ActionsService) getWorkflowRunAttemptLogsWithRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + url, resp, err := s.client.bareDoUntilFound(ctx, req, maxRedirects) + if err != nil { + return nil, resp, err + } + defer resp.Body.Close() + + // If we didn't receive a valid Location in a 302 response + if url == nil { + return nil, resp, fmt.Errorf("unexpected status code: %v", resp.Status) + } + + return url, resp, nil +} + // RerunWorkflowByID re-runs a workflow by ID. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID a the DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-workflow // @@ -290,6 +322,7 @@ func (s *ActionsService) RerunWorkflowByID(ctx context.Context, owner, repo stri } // RerunFailedJobsByID re-runs all of the failed jobs and their dependent jobs in a workflow run by ID. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-failed-jobs-from-a-workflow-run // @@ -307,6 +340,8 @@ func (s *ActionsService) RerunFailedJobsByID(ctx context.Context, owner, repo st // RerunJobByID re-runs a job and its dependent jobs in a workflow run by ID. // +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. +// // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-job-from-a-workflow-run // //meta:operation POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun @@ -322,6 +357,7 @@ func (s *ActionsService) RerunJobByID(ctx context.Context, owner, repo string, j } // CancelWorkflowRunByID cancels a workflow run by ID. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#cancel-a-workflow-run // @@ -338,6 +374,7 @@ func (s *ActionsService) CancelWorkflowRunByID(ctx context.Context, owner, repo } // GetWorkflowRunLogs gets a redirect URL to download a plain text file of logs for a workflow run. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-logs // @@ -345,6 +382,14 @@ func (s *ActionsService) CancelWorkflowRunByID(ctx context.Context, owner, repo func (s *ActionsService) GetWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64, maxRedirects int) (*url.URL, *Response, error) { u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID) + if s.client.RateLimitRedirectionalEndpoints { + return s.getWorkflowRunLogsWithRateLimit(ctx, u, maxRedirects) + } + + return s.getWorkflowRunLogsWithoutRateLimit(ctx, u, maxRedirects) +} + +func (s *ActionsService) getWorkflowRunLogsWithoutRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) if err != nil { return nil, nil, err @@ -359,7 +404,28 @@ func (s *ActionsService) GetWorkflowRunLogs(ctx context.Context, owner, repo str return parsedURL, newResponse(resp), err } +func (s *ActionsService) getWorkflowRunLogsWithRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + url, resp, err := s.client.bareDoUntilFound(ctx, req, maxRedirects) + if err != nil { + return nil, resp, err + } + defer resp.Body.Close() + + // If we didn't receive a valid Location in a 302 response + if url == nil { + return nil, resp, fmt.Errorf("unexpected status code: %v", resp.Status) + } + + return url, resp, nil +} + // DeleteWorkflowRun deletes a workflow run by ID. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-a-workflow-run // @@ -376,6 +442,7 @@ func (s *ActionsService) DeleteWorkflowRun(ctx context.Context, owner, repo stri } // DeleteWorkflowRunLogs deletes all logs for a workflow run. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-workflow-run-logs // @@ -392,6 +459,7 @@ func (s *ActionsService) DeleteWorkflowRunLogs(ctx context.Context, owner, repo } // GetWorkflowRunUsageByID gets a specific workflow usage run by run ID in the unit of billable milliseconds. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-workflow-run-usage // @@ -414,6 +482,7 @@ func (s *ActionsService) GetWorkflowRunUsageByID(ctx context.Context, owner, rep } // GetPendingDeployments get all deployment environments for a workflow run that are waiting for protection rules to pass. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-pending-deployments-for-a-workflow-run // @@ -436,6 +505,7 @@ func (s *ActionsService) GetPendingDeployments(ctx context.Context, owner, repo } // PendingDeployments approve or reject pending deployments that are waiting on approval by a required reviewer. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-pending-deployments-for-a-workflow-run // @@ -458,6 +528,7 @@ func (s *ActionsService) PendingDeployments(ctx context.Context, owner, repo str } // ReviewCustomDeploymentProtectionRule approves or rejects custom deployment protection rules provided by a GitHub App for a workflow run. +// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent. // // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-custom-deployment-protection-rules-for-a-workflow-run // diff --git a/vendor/github.com/google/go-github/v68/github/actions_workflows.go b/vendor/github.com/google/go-github/v70/github/actions_workflows.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/actions_workflows.go rename to vendor/github.com/google/go-github/v70/github/actions_workflows.go diff --git a/vendor/github.com/google/go-github/v68/github/activity.go b/vendor/github.com/google/go-github/v70/github/activity.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/activity.go rename to vendor/github.com/google/go-github/v70/github/activity.go diff --git a/vendor/github.com/google/go-github/v68/github/activity_events.go b/vendor/github.com/google/go-github/v70/github/activity_events.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/activity_events.go rename to vendor/github.com/google/go-github/v70/github/activity_events.go diff --git a/vendor/github.com/google/go-github/v68/github/activity_notifications.go b/vendor/github.com/google/go-github/v70/github/activity_notifications.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/activity_notifications.go rename to vendor/github.com/google/go-github/v70/github/activity_notifications.go diff --git a/vendor/github.com/google/go-github/v68/github/activity_star.go b/vendor/github.com/google/go-github/v70/github/activity_star.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/activity_star.go rename to vendor/github.com/google/go-github/v70/github/activity_star.go diff --git a/vendor/github.com/google/go-github/v68/github/activity_watching.go b/vendor/github.com/google/go-github/v70/github/activity_watching.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/activity_watching.go rename to vendor/github.com/google/go-github/v70/github/activity_watching.go diff --git a/vendor/github.com/google/go-github/v68/github/admin.go b/vendor/github.com/google/go-github/v70/github/admin.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/admin.go rename to vendor/github.com/google/go-github/v70/github/admin.go diff --git a/vendor/github.com/google/go-github/v68/github/admin_orgs.go b/vendor/github.com/google/go-github/v70/github/admin_orgs.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/admin_orgs.go rename to vendor/github.com/google/go-github/v70/github/admin_orgs.go diff --git a/vendor/github.com/google/go-github/v68/github/admin_stats.go b/vendor/github.com/google/go-github/v70/github/admin_stats.go similarity index 94% rename from vendor/github.com/google/go-github/v68/github/admin_stats.go rename to vendor/github.com/google/go-github/v70/github/admin_stats.go index f012d7984c..a6e406beca 100644 --- a/vendor/github.com/google/go-github/v68/github/admin_stats.go +++ b/vendor/github.com/google/go-github/v70/github/admin_stats.go @@ -118,13 +118,13 @@ func (s GistStats) String() string { return Stringify(s) } -// PullStats represents the number of total, merged, mergable and unmergeable +// PullStats represents the number of total, merged, mergeable and unmergeable // pull-requests. type PullStats struct { - TotalPulls *int `json:"total_pulls,omitempty"` - MergedPulls *int `json:"merged_pulls,omitempty"` - MergablePulls *int `json:"mergeable_pulls,omitempty"` - UnmergablePulls *int `json:"unmergeable_pulls,omitempty"` + TotalPulls *int `json:"total_pulls,omitempty"` + MergedPulls *int `json:"merged_pulls,omitempty"` + MergeablePulls *int `json:"mergeable_pulls,omitempty"` + UnmergeablePulls *int `json:"unmergeable_pulls,omitempty"` } func (s PullStats) String() string { diff --git a/vendor/github.com/google/go-github/v68/github/admin_users.go b/vendor/github.com/google/go-github/v70/github/admin_users.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/admin_users.go rename to vendor/github.com/google/go-github/v70/github/admin_users.go diff --git a/vendor/github.com/google/go-github/v68/github/apps.go b/vendor/github.com/google/go-github/v70/github/apps.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/apps.go rename to vendor/github.com/google/go-github/v70/github/apps.go diff --git a/vendor/github.com/google/go-github/v68/github/apps_hooks.go b/vendor/github.com/google/go-github/v70/github/apps_hooks.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/apps_hooks.go rename to vendor/github.com/google/go-github/v70/github/apps_hooks.go diff --git a/vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go b/vendor/github.com/google/go-github/v70/github/apps_hooks_deliveries.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/apps_hooks_deliveries.go rename to vendor/github.com/google/go-github/v70/github/apps_hooks_deliveries.go diff --git a/vendor/github.com/google/go-github/v68/github/apps_installation.go b/vendor/github.com/google/go-github/v70/github/apps_installation.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/apps_installation.go rename to vendor/github.com/google/go-github/v70/github/apps_installation.go diff --git a/vendor/github.com/google/go-github/v68/github/apps_manifest.go b/vendor/github.com/google/go-github/v70/github/apps_manifest.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/apps_manifest.go rename to vendor/github.com/google/go-github/v70/github/apps_manifest.go diff --git a/vendor/github.com/google/go-github/v68/github/apps_marketplace.go b/vendor/github.com/google/go-github/v70/github/apps_marketplace.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/apps_marketplace.go rename to vendor/github.com/google/go-github/v70/github/apps_marketplace.go diff --git a/vendor/github.com/google/go-github/v68/github/attestations.go b/vendor/github.com/google/go-github/v70/github/attestations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/attestations.go rename to vendor/github.com/google/go-github/v70/github/attestations.go diff --git a/vendor/github.com/google/go-github/v68/github/authorizations.go b/vendor/github.com/google/go-github/v70/github/authorizations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/authorizations.go rename to vendor/github.com/google/go-github/v70/github/authorizations.go diff --git a/vendor/github.com/google/go-github/v68/github/billing.go b/vendor/github.com/google/go-github/v70/github/billing.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/billing.go rename to vendor/github.com/google/go-github/v70/github/billing.go diff --git a/vendor/github.com/google/go-github/v68/github/checks.go b/vendor/github.com/google/go-github/v70/github/checks.go similarity index 99% rename from vendor/github.com/google/go-github/v68/github/checks.go rename to vendor/github.com/google/go-github/v70/github/checks.go index 711be207c2..2f0f65bf92 100644 --- a/vendor/github.com/google/go-github/v68/github/checks.go +++ b/vendor/github.com/google/go-github/v70/github/checks.go @@ -87,8 +87,8 @@ type CheckSuite struct { // The following fields are only populated by Webhook events. HeadCommit *Commit `json:"head_commit,omitempty"` LatestCheckRunsCount *int64 `json:"latest_check_runs_count,omitempty"` - Rerequstable *bool `json:"rerequestable,omitempty"` - RunsRerequstable *bool `json:"runs_rerequestable,omitempty"` + Rerequestable *bool `json:"rerequestable,omitempty"` + RunsRerequestable *bool `json:"runs_rerequestable,omitempty"` } func (c CheckRun) String() string { diff --git a/vendor/github.com/google/go-github/v68/github/code_scanning.go b/vendor/github.com/google/go-github/v70/github/code_scanning.go similarity index 98% rename from vendor/github.com/google/go-github/v68/github/code_scanning.go rename to vendor/github.com/google/go-github/v70/github/code_scanning.go index a8fca98a92..19a88241d3 100644 --- a/vendor/github.com/google/go-github/v68/github/code_scanning.go +++ b/vendor/github.com/google/go-github/v70/github/code_scanning.go @@ -141,6 +141,15 @@ type AlertListOptions struct { // The name of a code scanning tool. Only results by this tool will be listed. ToolName string `url:"tool_name,omitempty"` + // The GUID of a code scanning tool. Only results by this tool will be listed. + ToolGUID string `url:"tool_guid,omitempty"` + + // The direction to sort the results by. Possible values are: asc, desc. Default: desc. + Direction string `url:"direction,omitempty"` + + // The property by which to sort the results. Possible values are: created, updated. Default: created. + Sort string `url:"sort,omitempty"` + ListCursorOptions // Add ListOptions so offset pagination with integer type "page" query parameter is accepted @@ -391,7 +400,7 @@ func (s *CodeScanningService) UploadSarif(ctx context.Context, owner, repo strin return nil, nil, err } - // This will always return an error without unmarshalling the data + // This will always return an error without unmarshaling the data resp, err := s.client.Do(ctx, req, nil) // Even though there was an error, we still return the response // in case the caller wants to inspect it further. diff --git a/vendor/github.com/google/go-github/v68/github/codesofconduct.go b/vendor/github.com/google/go-github/v70/github/codesofconduct.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/codesofconduct.go rename to vendor/github.com/google/go-github/v70/github/codesofconduct.go diff --git a/vendor/github.com/google/go-github/v68/github/codespaces.go b/vendor/github.com/google/go-github/v70/github/codespaces.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/codespaces.go rename to vendor/github.com/google/go-github/v70/github/codespaces.go diff --git a/vendor/github.com/google/go-github/v68/github/codespaces_secrets.go b/vendor/github.com/google/go-github/v70/github/codespaces_secrets.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/codespaces_secrets.go rename to vendor/github.com/google/go-github/v70/github/codespaces_secrets.go diff --git a/vendor/github.com/google/go-github/v68/github/copilot.go b/vendor/github.com/google/go-github/v70/github/copilot.go similarity index 97% rename from vendor/github.com/google/go-github/v68/github/copilot.go rename to vendor/github.com/google/go-github/v70/github/copilot.go index a2b2aa0995..b9adfcb4ee 100644 --- a/vendor/github.com/google/go-github/v68/github/copilot.go +++ b/vendor/github.com/google/go-github/v70/github/copilot.go @@ -307,7 +307,7 @@ func (s *CopilotService) ListCopilotSeats(ctx context.Context, org string, opts // // To paginate through all seats, populate 'Page' with the number of the last page. // -// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-enterprise +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-enterprise // //meta:operation GET /enterprises/{enterprise}/copilot/billing/seats func (s *CopilotService) ListCopilotEnterpriseSeats(ctx context.Context, enterprise string, opts *ListOptions) (*ListCopilotSeatsResponse, *Response, error) { @@ -467,7 +467,7 @@ func (s *CopilotService) GetSeatDetails(ctx context.Context, org, user string) ( // GetEnterpriseMetrics gets Copilot usage metrics for an enterprise. // -// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise // //meta:operation GET /enterprises/{enterprise}/copilot/metrics func (s *CopilotService) GetEnterpriseMetrics(ctx context.Context, enterprise string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { @@ -493,7 +493,7 @@ func (s *CopilotService) GetEnterpriseMetrics(ctx context.Context, enterprise st // GetEnterpriseTeamMetrics gets Copilot usage metrics for an enterprise team. // -// GitHub API docs: https://docs.github.com/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise-team +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/copilot/copilot-metrics#get-copilot-metrics-for-an-enterprise-team // //meta:operation GET /enterprises/{enterprise}/team/{team_slug}/copilot/metrics func (s *CopilotService) GetEnterpriseTeamMetrics(ctx context.Context, enterprise, team string, opts *CopilotMetricsListOptions) ([]*CopilotMetrics, *Response, error) { diff --git a/vendor/github.com/google/go-github/v68/github/dependabot.go b/vendor/github.com/google/go-github/v70/github/dependabot.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/dependabot.go rename to vendor/github.com/google/go-github/v70/github/dependabot.go diff --git a/vendor/github.com/google/go-github/v68/github/dependabot_alerts.go b/vendor/github.com/google/go-github/v70/github/dependabot_alerts.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/dependabot_alerts.go rename to vendor/github.com/google/go-github/v70/github/dependabot_alerts.go diff --git a/vendor/github.com/google/go-github/v68/github/dependabot_secrets.go b/vendor/github.com/google/go-github/v70/github/dependabot_secrets.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/dependabot_secrets.go rename to vendor/github.com/google/go-github/v70/github/dependabot_secrets.go diff --git a/vendor/github.com/google/go-github/v68/github/dependency_graph.go b/vendor/github.com/google/go-github/v70/github/dependency_graph.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/dependency_graph.go rename to vendor/github.com/google/go-github/v70/github/dependency_graph.go diff --git a/vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go b/vendor/github.com/google/go-github/v70/github/dependency_graph_snapshots.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/dependency_graph_snapshots.go rename to vendor/github.com/google/go-github/v70/github/dependency_graph_snapshots.go diff --git a/vendor/github.com/google/go-github/v68/github/doc.go b/vendor/github.com/google/go-github/v70/github/doc.go similarity index 89% rename from vendor/github.com/google/go-github/v68/github/doc.go rename to vendor/github.com/google/go-github/v70/github/doc.go index 4a0f163a0b..befbd8b8db 100644 --- a/vendor/github.com/google/go-github/v68/github/doc.go +++ b/vendor/github.com/google/go-github/v70/github/doc.go @@ -8,7 +8,7 @@ Package github provides a client for using the GitHub API. Usage: - import "github.com/google/go-github/v68/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) + import "github.com/google/go-github/v70/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) import "github.com/google/go-github/github" // with go modules disabled Construct a new GitHub client, then use the various services on the client to @@ -138,11 +138,17 @@ To detect this condition of error, you can check if its type is # Conditional Requests -The GitHub API has good support for conditional requests which will help -prevent you from burning through your rate limit, as well as help speed up your -application. go-github does not handle conditional requests directly, but is -instead designed to work with a caching http.Transport. We recommend using -https://github.com/gregjones/httpcache for that. +The GitHub REST API has good support for conditional HTTP requests +via the ETag header which will help prevent you from burning through your +rate limit, as well as help speed up your application. go-github does not +handle conditional requests directly, but is instead designed to work with a +caching http.Transport. + +Typically, an RFC 7234 compliant HTTP cache such as https://github.com/gregjones/httpcache +is recommended. Alternatively, the https://github.com/bored-engineer/github-conditional-http-transport +package relies on (undocumented) GitHub specific cache logic and is +recommended when making requests using short-lived credentials such as a +GitHub App installation token. Learn more about GitHub conditional requests at https://docs.github.com/rest/overview/resources-in-the-rest-api#conditional-requests. diff --git a/vendor/github.com/google/go-github/v68/github/emojis.go b/vendor/github.com/google/go-github/v70/github/emojis.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/emojis.go rename to vendor/github.com/google/go-github/v70/github/emojis.go diff --git a/vendor/github.com/google/go-github/v68/github/enterprise.go b/vendor/github.com/google/go-github/v70/github/enterprise.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/enterprise.go rename to vendor/github.com/google/go-github/v70/github/enterprise.go diff --git a/vendor/github.com/google/go-github/v70/github/enterprise_actions_hosted_runners.go b/vendor/github.com/google/go-github/v70/github/enterprise_actions_hosted_runners.go new file mode 100644 index 0000000000..e82ba9b806 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/enterprise_actions_hosted_runners.go @@ -0,0 +1,234 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHostedRunners lists all the GitHub-hosted runners for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#list-github-hosted-runners-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners +func (s *EnterpriseService) ListHostedRunners(ctx context.Context, enterprise string, opts *ListOptions) (*HostedRunners, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &HostedRunners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// CreateHostedRunner creates a GitHub-hosted runner for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#create-a-github-hosted-runner-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/actions/hosted-runners +func (s *EnterpriseService) CreateHostedRunner(ctx context.Context, enterprise string, request *HostedRunnerRequest) (*HostedRunner, *Response, error) { + if err := validateCreateHostedRunnerRequest(request); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners", enterprise) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} + +// GetHostedRunnerGitHubOwnedImages gets the list of GitHub-owned images available for GitHub-hosted runners for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-github-owned-images-for-github-hosted-runners-in-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/images/github-owned +func (s *EnterpriseService) GetHostedRunnerGitHubOwnedImages(ctx context.Context, enterprise string) (*HostedRunnerImages, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/github-owned", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunnerImages := new(HostedRunnerImages) + resp, err := s.client.Do(ctx, req, hostedRunnerImages) + if err != nil { + return nil, resp, err + } + + return hostedRunnerImages, resp, nil +} + +// GetHostedRunnerPartnerImages gets the list of partner images available for GitHub-hosted runners for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-partner-images-for-github-hosted-runners-in-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/images/partner +func (s *EnterpriseService) GetHostedRunnerPartnerImages(ctx context.Context, enterprise string) (*HostedRunnerImages, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/images/partner", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunnerImages := new(HostedRunnerImages) + resp, err := s.client.Do(ctx, req, hostedRunnerImages) + if err != nil { + return nil, resp, err + } + + return hostedRunnerImages, resp, nil +} + +// GetHostedRunnerLimits gets the GitHub-hosted runners Static public IP Limits for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-limits-on-github-hosted-runners-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/limits +func (s *EnterpriseService) GetHostedRunnerLimits(ctx context.Context, enterprise string) (*HostedRunnerPublicIPLimits, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/limits", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + publicIPLimits := new(HostedRunnerPublicIPLimits) + resp, err := s.client.Do(ctx, req, publicIPLimits) + if err != nil { + return nil, resp, err + } + + return publicIPLimits, resp, nil +} + +// GetHostedRunnerMachineSpecs gets the list of machine specs available for GitHub-hosted runners for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-github-hosted-runners-machine-specs-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/machine-sizes +func (s *EnterpriseService) GetHostedRunnerMachineSpecs(ctx context.Context, enterprise string) (*HostedRunnerMachineSpecs, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/machine-sizes", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + machineSpecs := new(HostedRunnerMachineSpecs) + resp, err := s.client.Do(ctx, req, machineSpecs) + if err != nil { + return nil, resp, err + } + + return machineSpecs, resp, nil +} + +// GetHostedRunnerPlatforms gets list of platforms available for GitHub-hosted runners for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-platforms-for-github-hosted-runners-in-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/platforms +func (s *EnterpriseService) GetHostedRunnerPlatforms(ctx context.Context, enterprise string) (*HostedRunnerPlatforms, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/platforms", enterprise) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + platforms := new(HostedRunnerPlatforms) + resp, err := s.client.Do(ctx, req, platforms) + if err != nil { + return nil, resp, err + } + + return platforms, resp, nil +} + +// GetHostedRunner gets a GitHub-hosted runner in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#get-a-github-hosted-runner-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/actions/hosted-runners/{hosted_runner_id} +func (s *EnterpriseService) GetHostedRunner(ctx context.Context, enterprise string, runnerID int64) (*HostedRunner, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/%v", enterprise, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} + +// UpdateHostedRunner updates a GitHub-hosted runner for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#update-a-github-hosted-runner-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/actions/hosted-runners/{hosted_runner_id} +func (s *EnterpriseService) UpdateHostedRunner(ctx context.Context, enterprise string, runnerID int64, updateReq HostedRunnerRequest) (*HostedRunner, *Response, error) { + if err := validateUpdateHostedRunnerRequest(&updateReq); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/%v", enterprise, runnerID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} + +// DeleteHostedRunner deletes GitHub-hosted runner from an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/hosted-runners#delete-a-github-hosted-runner-for-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/actions/hosted-runners/{hosted_runner_id} +func (s *EnterpriseService) DeleteHostedRunner(ctx context.Context, enterprise string, runnerID int64) (*HostedRunner, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/hosted-runners/%v", enterprise, runnerID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + hostedRunner := new(HostedRunner) + resp, err := s.client.Do(ctx, req, hostedRunner) + if err != nil { + return nil, resp, err + } + + return hostedRunner, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go b/vendor/github.com/google/go-github/v70/github/enterprise_actions_runner_groups.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/enterprise_actions_runner_groups.go rename to vendor/github.com/google/go-github/v70/github/enterprise_actions_runner_groups.go diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go b/vendor/github.com/google/go-github/v70/github/enterprise_actions_runners.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/enterprise_actions_runners.go rename to vendor/github.com/google/go-github/v70/github/enterprise_actions_runners.go diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go b/vendor/github.com/google/go-github/v70/github/enterprise_audit_log.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/enterprise_audit_log.go rename to vendor/github.com/google/go-github/v70/github/enterprise_audit_log.go diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go b/vendor/github.com/google/go-github/v70/github/enterprise_code_security_and_analysis.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/enterprise_code_security_and_analysis.go rename to vendor/github.com/google/go-github/v70/github/enterprise_code_security_and_analysis.go diff --git a/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes.go b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes.go new file mode 100644 index 0000000000..e14836eb02 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes.go @@ -0,0 +1,163 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// NodeQueryOptions specifies the optional parameters to the EnterpriseService +// Node management APIs. +type NodeQueryOptions struct { + // UUID filters issues based on the node UUID. + UUID *string `url:"uuid,omitempty"` + + // ClusterRoles filters the cluster roles from the cluster configuration file. + ClusterRoles *string `url:"cluster_roles,omitempty"` +} + +// ClusterStatus represents a response from the ClusterStatus and ReplicationStatus methods. +type ClusterStatus struct { + Status *string `json:"status,omitempty"` + Nodes []*ClusterStatusNode `json:"nodes"` +} + +// ClusterStatusNode represents the status of a cluster node. +type ClusterStatusNode struct { + Hostname *string `json:"hostname,omitempty"` + Status *string `json:"status,omitempty"` + Services []*ClusterStatusNodeServiceItem `json:"services"` +} + +// ClusterStatusNodeServiceItem represents the status of a service running on a cluster node. +type ClusterStatusNodeServiceItem struct { + Status *string `json:"status,omitempty"` + Name *string `json:"name,omitempty"` + Details *string `json:"details,omitempty"` +} + +// SystemRequirements represents a response from the CheckSystemRequirements method. +type SystemRequirements struct { + Status *string `json:"status,omitempty"` + Nodes []*SystemRequirementsNode `json:"nodes"` +} + +// SystemRequirementsNode represents the status of a system node. +type SystemRequirementsNode struct { + Hostname *string `json:"hostname,omitempty"` + Status *string `json:"status,omitempty"` + RolesStatus []*SystemRequirementsNodeRoleStatus `json:"roles_status"` +} + +// SystemRequirementsNodeRoleStatus represents the status of a role on a system node. +type SystemRequirementsNodeRoleStatus struct { + Status *string `json:"status,omitempty"` + Role *string `json:"role,omitempty"` +} + +// NodeReleaseVersion represents a response from the GetNodeReleaseVersions method. +type NodeReleaseVersion struct { + Hostname *string `json:"hostname,omitempty"` + Version *ReleaseVersion `json:"version"` +} + +// ReleaseVersion holds the release version information of the node. +type ReleaseVersion struct { + Version *string `json:"version,omitempty"` + Platform *string `json:"platform,omitempty"` + BuildID *string `json:"build_id,omitempty"` + BuildDate *string `json:"build_date,omitempty"` +} + +// CheckSystemRequirements checks if GHES system nodes meet the system requirements. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-system-requirement-check-results-for-configured-cluster-nodes +// +//meta:operation GET /manage/v1/checks/system-requirements +func (s *EnterpriseService) CheckSystemRequirements(ctx context.Context) (*SystemRequirements, *Response, error) { + u := "manage/v1/checks/system-requirements" + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + systemRequirements := new(SystemRequirements) + resp, err := s.client.Do(ctx, req, systemRequirements) + if err != nil { + return nil, resp, err + } + + return systemRequirements, resp, nil +} + +// ClusterStatus gets the status of all services running on each cluster node. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-status-of-services-running-on-all-cluster-nodes +// +//meta:operation GET /manage/v1/cluster/status +func (s *EnterpriseService) ClusterStatus(ctx context.Context) (*ClusterStatus, *Response, error) { + u := "manage/v1/cluster/status" + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + clusterStatus := new(ClusterStatus) + resp, err := s.client.Do(ctx, req, clusterStatus) + if err != nil { + return nil, resp, err + } + + return clusterStatus, resp, nil +} + +// ReplicationStatus gets the status of all services running on each replica node. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-status-of-services-running-on-all-replica-nodes +// +//meta:operation GET /manage/v1/replication/status +func (s *EnterpriseService) ReplicationStatus(ctx context.Context, opts *NodeQueryOptions) (*ClusterStatus, *Response, error) { + u, err := addOptions("manage/v1/replication/status", opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + status := new(ClusterStatus) + resp, err := s.client.Do(ctx, req, status) + if err != nil { + return nil, resp, err + } + + return status, resp, nil +} + +// GetNodeReleaseVersions gets the version information deployed to each node. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-all-ghes-release-versions-for-all-nodes +// +//meta:operation GET /manage/v1/version +func (s *EnterpriseService) GetNodeReleaseVersions(ctx context.Context, opts *NodeQueryOptions) ([]*NodeReleaseVersion, *Response, error) { + u, err := addOptions("manage/v1/version", opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var releaseVersions []*NodeReleaseVersion + resp, err := s.client.Do(ctx, req, &releaseVersions) + if err != nil { + return nil, resp, err + } + + return releaseVersions, resp, nil +} diff --git a/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_config.go b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_config.go new file mode 100644 index 0000000000..10fb8590e4 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_config.go @@ -0,0 +1,516 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" +) + +// ConfigApplyOptions is a struct to hold the options for the ConfigApply API and the response. +type ConfigApplyOptions struct { + // RunID is the ID of the run to get the status of. If empty a random one will be generated. + RunID *string `json:"run_id,omitempty"` +} + +// ConfigApplyStatus is a struct to hold the response from the ConfigApply API. +type ConfigApplyStatus struct { + Running *bool `json:"running,omitempty"` + Successful *bool `json:"successful,omitempty"` + Nodes []*ConfigApplyStatusNode `json:"nodes"` +} + +// ConfigApplyStatusNode is a struct to hold the response from the ConfigApply API. +type ConfigApplyStatusNode struct { + Hostname *string `json:"hostname,omitempty"` + Running *bool `json:"running,omitempty"` + Successful *bool `json:"successful,omitempty"` + RunID *string `json:"run_id,omitempty"` +} + +// ConfigApplyEventsOptions is used to enable pagination. +type ConfigApplyEventsOptions struct { + LastRequestID *string `url:"last_request_id,omitempty"` +} + +// ConfigApplyEvents is a struct to hold the response from the ConfigApplyEvents API. +type ConfigApplyEvents struct { + Nodes []*ConfigApplyEventsNode `json:"nodes"` +} + +// ConfigApplyEventsNode is a struct to hold the response from the ConfigApplyEvents API. +type ConfigApplyEventsNode struct { + Node *string `json:"node,omitempty"` + LastRequestID *string `json:"last_request_id,omitempty"` + Events []*ConfigApplyEventsNodeEvent `json:"events"` +} + +// ConfigApplyEventsNodeEvent is a struct to hold the response from the ConfigApplyEvents API. +type ConfigApplyEventsNodeEvent struct { + Timestamp *Timestamp `json:"timestamp,omitempty"` + SeverityText *string `json:"severity_text,omitempty"` + Body *string `json:"body,omitempty"` + EventName *string `json:"event_name,omitempty"` + Topology *string `json:"topology,omitempty"` + Hostname *string `json:"hostname,omitempty"` + ConfigRunID *string `json:"config_run_id,omitempty"` + TraceID *string `json:"trace_id,omitempty"` + SpanID *string `json:"span_id,omitempty"` + SpanParentID *int64 `json:"span_parent_id,omitempty"` + SpanDepth *int `json:"span_depth,omitempty"` +} + +// InitialConfigOptions is a struct to hold the options for the InitialConfig API. +type InitialConfigOptions struct { + License string `url:"license"` + Password string `url:"password"` +} + +// LicenseStatus is a struct to hold the response from the License API. +type LicenseStatus struct { + AdvancedSecurityEnabled *bool `json:"advancedSecurityEnabled,omitempty"` + AdvancedSecuritySeats *int `json:"advancedSecuritySeats,omitempty"` + ClusterSupport *bool `json:"clusterSupport,omitempty"` + Company *string `json:"company,omitempty"` + CroquetSupport *bool `json:"croquetSupport,omitempty"` + CustomTerms *bool `json:"customTerms,omitempty"` + Evaluation *bool `json:"evaluation,omitempty"` + ExpireAt *Timestamp `json:"expireAt,omitempty"` + InsightsEnabled *bool `json:"insightsEnabled,omitempty"` + InsightsExpireAt *Timestamp `json:"insightsExpireAt,omitempty"` + LearningLabEvaluationExpires *Timestamp `json:"learningLabEvaluationExpires,omitempty"` + LearningLabSeats *int `json:"learningLabSeats,omitempty"` + Perpetual *bool `json:"perpetual,omitempty"` + ReferenceNumber *string `json:"referenceNumber,omitempty"` + Seats *int `json:"seats,omitempty"` + SSHAllowed *bool `json:"sshAllowed,omitempty"` + SupportKey *string `json:"supportKey,omitempty"` + UnlimitedSeating *bool `json:"unlimitedSeating,omitempty"` +} + +// UploadLicenseOptions is a struct to hold the options for the UploadLicense API. +type UploadLicenseOptions struct { + License string `url:"license"` +} + +// LicenseCheck is a struct to hold the response from the LicenseStatus API. +type LicenseCheck struct { + Status *string `json:"status,omitempty"` +} + +// ConfigSettings is a struct to hold the response from the Settings API. +// There are many fields that link to other structs. +type ConfigSettings struct { + PrivateMode *bool `json:"private_mode,omitempty"` + PublicPages *bool `json:"public_pages,omitempty"` + SubdomainIsolation *bool `json:"subdomain_isolation,omitempty"` + SignupEnabled *bool `json:"signup_enabled,omitempty"` + GithubHostname *string `json:"github_hostname,omitempty"` + IdenticonsHost *string `json:"identicons_host,omitempty"` + HTTPProxy *string `json:"http_proxy,omitempty"` + AuthMode *string `json:"auth_mode,omitempty"` + ExpireSessions *bool `json:"expire_sessions,omitempty"` + AdminPassword *string `json:"admin_password,omitempty"` + ConfigurationID *int64 `json:"configuration_id,omitempty"` + ConfigurationRunCount *int `json:"configuration_run_count,omitempty"` + Avatar *ConfigSettingsAvatar `json:"avatar,omitempty"` + Customer *ConfigSettingsCustomer `json:"customer,omitempty"` + License *ConfigSettingsLicenseSettings `json:"license,omitempty"` + GithubSSL *ConfigSettingsGithubSSL `json:"github_ssl,omitempty"` + LDAP *ConfigSettingsLDAP `json:"ldap,omitempty"` + CAS *ConfigSettingsCAS `json:"cas,omitempty"` + SAML *ConfigSettingsSAML `json:"saml,omitempty"` + GithubOAuth *ConfigSettingsGithubOAuth `json:"github_oauth,omitempty"` + SMTP *ConfigSettingsSMTP `json:"smtp,omitempty"` + NTP *ConfigSettingsNTP `json:"ntp,omitempty"` + Timezone *string `json:"timezone,omitempty"` + SNMP *ConfigSettingsSNMP `json:"snmp,omitempty"` + Syslog *ConfigSettingsSyslog `json:"syslog,omitempty"` + Assets *string `json:"assets,omitempty"` + Pages *ConfigSettingsPagesSettings `json:"pages,omitempty"` + Collectd *ConfigSettingsCollectd `json:"collectd,omitempty"` + Mapping *ConfigSettingsMapping `json:"mapping,omitempty"` + LoadBalancer *string `json:"load_balancer,omitempty"` +} + +// ConfigSettingsAvatar is a struct to hold the response from the Settings API. +type ConfigSettingsAvatar struct { + Enabled *bool `json:"enabled,omitempty"` + URI *string `json:"uri,omitempty"` +} + +// ConfigSettingsCustomer is a struct to hold the response from the Settings API. +type ConfigSettingsCustomer struct { + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` + UUID *string `json:"uuid,omitempty"` + Secret *string `json:"secret,omitempty"` + PublicKeyData *string `json:"public_key_data,omitempty"` +} + +// ConfigSettingsLicenseSettings is a struct to hold the response from the Settings API. +type ConfigSettingsLicenseSettings struct { + Seats *int `json:"seats,omitempty"` + Evaluation *bool `json:"evaluation,omitempty"` + Perpetual *bool `json:"perpetual,omitempty"` + UnlimitedSeating *bool `json:"unlimited_seating,omitempty"` + SupportKey *string `json:"support_key,omitempty"` + SSHAllowed *bool `json:"ssh_allowed,omitempty"` + ClusterSupport *bool `json:"cluster_support,omitempty"` + ExpireAt *Timestamp `json:"expire_at,omitempty"` +} + +// ConfigSettingsGithubSSL is a struct to hold the response from the Settings API. +type ConfigSettingsGithubSSL struct { + Enabled *bool `json:"enabled,omitempty"` + Cert *string `json:"cert,omitempty"` + Key *string `json:"key,omitempty"` +} + +// ConfigSettingsLDAP is a struct to hold the response from the Settings API. +type ConfigSettingsLDAP struct { + Host *string `json:"host,omitempty"` + Port *int `json:"port,omitempty"` + Base []string `json:"base,omitempty"` + UID *string `json:"uid,omitempty"` + BindDN *string `json:"bind_dn,omitempty"` + Password *string `json:"password,omitempty"` + Method *string `json:"method,omitempty"` + SearchStrategy *string `json:"search_strategy,omitempty"` + UserGroups []string `json:"user_groups,omitempty"` + AdminGroup *string `json:"admin_group,omitempty"` + VirtualAttributeEnabled *bool `json:"virtual_attribute_enabled,omitempty"` + RecursiveGroupSearch *bool `json:"recursive_group_search,omitempty"` + PosixSupport *bool `json:"posix_support,omitempty"` + UserSyncEmails *bool `json:"user_sync_emails,omitempty"` + UserSyncKeys *bool `json:"user_sync_keys,omitempty"` + UserSyncInterval *int `json:"user_sync_interval,omitempty"` + TeamSyncInterval *int `json:"team_sync_interval,omitempty"` + SyncEnabled *bool `json:"sync_enabled,omitempty"` + Reconciliation *ConfigSettingsLDAPReconciliation `json:"reconciliation,omitempty"` + Profile *ConfigSettingsLDAPProfile `json:"profile,omitempty"` +} + +// ConfigSettingsLDAPReconciliation is part of the ConfigSettingsLDAP struct. +type ConfigSettingsLDAPReconciliation struct { + User *string `json:"user,omitempty"` + Org *string `json:"org,omitempty"` +} + +// ConfigSettingsLDAPProfile is part of the ConfigSettingsLDAP struct. +type ConfigSettingsLDAPProfile struct { + UID *string `json:"uid,omitempty"` + Name *string `json:"name,omitempty"` + Mail *string `json:"mail,omitempty"` + Key *string `json:"key,omitempty"` +} + +// ConfigSettingsCAS is a struct to hold the response from the Settings API. +type ConfigSettingsCAS struct { + URL *string `json:"url,omitempty"` +} + +// ConfigSettingsSAML is a struct to hold the response from the Settings API. +type ConfigSettingsSAML struct { + SSOURL *string `json:"sso_url,omitempty"` + Certificate *string `json:"certificate,omitempty"` + CertificatePath *string `json:"certificate_path,omitempty"` + Issuer *string `json:"issuer,omitempty"` + IDPInitiatedSSO *bool `json:"idp_initiated_sso,omitempty"` + DisableAdminDemote *bool `json:"disable_admin_demote,omitempty"` +} + +// ConfigSettingsGithubOAuth is a struct to hold the response from the Settings API. +type ConfigSettingsGithubOAuth struct { + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + OrganizationName *string `json:"organization_name,omitempty"` + OrganizationTeam *string `json:"organization_team,omitempty"` +} + +// ConfigSettingsSMTP is a struct to hold the response from the Settings API. +type ConfigSettingsSMTP struct { + Enabled *bool `json:"enabled,omitempty"` + Address *string `json:"address,omitempty"` + Authentication *string `json:"authentication,omitempty"` + Port *string `json:"port,omitempty"` + Domain *string `json:"domain,omitempty"` + Username *string `json:"username,omitempty"` + UserName *string `json:"user_name,omitempty"` + EnableStarttlsAuto *bool `json:"enable_starttls_auto,omitempty"` + Password *string `json:"password,omitempty"` + DiscardToNoreplyAddress *bool `json:"discard-to-noreply-address,omitempty"` + SupportAddress *string `json:"support_address,omitempty"` + SupportAddressType *string `json:"support_address_type,omitempty"` + NoreplyAddress *string `json:"noreply_address,omitempty"` +} + +// ConfigSettingsNTP is a struct to hold the response from the Settings API. +type ConfigSettingsNTP struct { + PrimaryServer *string `json:"primary_server,omitempty"` + SecondaryServer *string `json:"secondary_server,omitempty"` +} + +// ConfigSettingsSNMP is a struct to hold the response from the Settings API. +type ConfigSettingsSNMP struct { + Enabled *bool `json:"enabled,omitempty"` + Community *string `json:"community,omitempty"` +} + +// ConfigSettingsSyslog is a struct to hold the response from the Settings API. +type ConfigSettingsSyslog struct { + Enabled *bool `json:"enabled,omitempty"` + Server *string `json:"server,omitempty"` + ProtocolName *string `json:"protocol_name,omitempty"` +} + +// ConfigSettingsPagesSettings is a struct to hold the response from the Settings API. +type ConfigSettingsPagesSettings struct { + Enabled *bool `json:"enabled,omitempty"` +} + +// ConfigSettingsCollectd is a struct to hold the response from the Settings API. +type ConfigSettingsCollectd struct { + Enabled *bool `json:"enabled,omitempty"` + Server *string `json:"server,omitempty"` + Port *int `json:"port,omitempty"` + Encryption *string `json:"encryption,omitempty"` + Username *string `json:"username,omitempty"` + Password *string `json:"password,omitempty"` +} + +// ConfigSettingsMapping is a struct to hold the response from the Settings API. +type ConfigSettingsMapping struct { + Enabled *bool `json:"enabled,omitempty"` + Tileserver *string `json:"tileserver,omitempty"` + Basemap *string `json:"basemap,omitempty"` + Token *string `json:"token,omitempty"` +} + +// NodeMetadataStatus is a struct to hold the response from the NodeMetadata API. +type NodeMetadataStatus struct { + Topology *string `json:"topology,omitempty"` + Nodes []*NodeDetails `json:"nodes"` +} + +// NodeDetails is a struct to hold the response from the NodeMetadata API. +type NodeDetails struct { + Hostname *string `json:"hostname,omitempty"` + UUID *string `json:"uuid,omitempty"` + ClusterRoles []string `json:"cluster_roles,omitempty"` +} + +// ConfigApplyEvents gets events from the command ghe-config-apply. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#list-events-from-ghe-config-apply +// +//meta:operation GET /manage/v1/config/apply/events +func (s *EnterpriseService) ConfigApplyEvents(ctx context.Context, opts *ConfigApplyEventsOptions) (*ConfigApplyEvents, *Response, error) { + u, err := addOptions("manage/v1/config/apply/events", opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + configApplyEvents := new(ConfigApplyEvents) + resp, err := s.client.Do(ctx, req, configApplyEvents) + if err != nil { + return nil, resp, err + } + + return configApplyEvents, resp, nil +} + +// InitialConfig initializes the GitHub Enterprise instance with a license and password. +// After initializing the instance, you need to run an apply to apply the configuration. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#initialize-instance-configuration-with-license-and-password +// +//meta:operation POST /manage/v1/config/init +func (s *EnterpriseService) InitialConfig(ctx context.Context, license, password string) (*Response, error) { + u := "manage/v1/config/init" + + opts := &InitialConfigOptions{ + License: license, + Password: password, + } + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// License gets the current license information for the GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-enterprise-license-information +// +//meta:operation GET /manage/v1/config/license +func (s *EnterpriseService) License(ctx context.Context) ([]*LicenseStatus, *Response, error) { + u := "manage/v1/config/license" + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var licenseStatus []*LicenseStatus + resp, err := s.client.Do(ctx, req, &licenseStatus) + if err != nil { + return nil, resp, err + } + + return licenseStatus, resp, nil +} + +// UploadLicense uploads a new license to the GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#upload-an-enterprise-license +// +//meta:operation PUT /manage/v1/config/license +func (s *EnterpriseService) UploadLicense(ctx context.Context, license string) (*Response, error) { + u := "manage/v1/config/license" + opts := &UploadLicenseOptions{ + License: license, + } + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// LicenseStatus gets the current license status for the GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#check-a-license +// +//meta:operation GET /manage/v1/config/license/check +func (s *EnterpriseService) LicenseStatus(ctx context.Context) ([]*LicenseCheck, *Response, error) { + u := "manage/v1/config/license/check" + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var checks []*LicenseCheck + resp, err := s.client.Do(ctx, req, &checks) + if err != nil { + return nil, resp, err + } + + return checks, resp, nil +} + +// NodeMetadata gets the metadata for all nodes in the GitHub Enterprise instance. +// This is required for clustered setups. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-ghes-node-metadata-for-all-nodes +// +//meta:operation GET /manage/v1/config/nodes +func (s *EnterpriseService) NodeMetadata(ctx context.Context, opts *NodeQueryOptions) (*NodeMetadataStatus, *Response, error) { + u, err := addOptions("manage/v1/config/nodes", opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + status := new(NodeMetadataStatus) + resp, err := s.client.Do(ctx, req, status) + if err != nil { + return nil, resp, err + } + + return status, resp, nil +} + +// Settings gets the current configuration settings for the GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-ghes-settings +// +//meta:operation GET /manage/v1/config/settings +func (s *EnterpriseService) Settings(ctx context.Context) (*ConfigSettings, *Response, error) { + u := "manage/v1/config/settings" + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + configSettings := new(ConfigSettings) + resp, err := s.client.Do(ctx, req, configSettings) + if err != nil { + return nil, resp, err + } + + return configSettings, resp, nil +} + +// UpdateSettings updates the configuration settings for the GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#set-settings +// +//meta:operation PUT /manage/v1/config/settings +func (s *EnterpriseService) UpdateSettings(ctx context.Context, opts *ConfigSettings) (*Response, error) { + u := "manage/v1/config/settings" + + if opts == nil { + return nil, errors.New("opts should not be nil") + } + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ConfigApply triggers a configuration apply run on the GitHub Enterprise instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#trigger-a-ghe-config-apply-run +// +//meta:operation POST /manage/v1/config/apply +func (s *EnterpriseService) ConfigApply(ctx context.Context, opts *ConfigApplyOptions) (*ConfigApplyOptions, *Response, error) { + u := "manage/v1/config/apply" + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + configApplyOptions := new(ConfigApplyOptions) + resp, err := s.client.Do(ctx, req, configApplyOptions) + if err != nil { + return nil, resp, err + } + return configApplyOptions, resp, nil +} + +// ConfigApplyStatus gets the status of a ghe-config-apply run on the GitHub Enterprise instance. +// You can request lat one or specific id one. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-status-of-a-ghe-config-apply-run +// +//meta:operation GET /manage/v1/config/apply +func (s *EnterpriseService) ConfigApplyStatus(ctx context.Context, opts *ConfigApplyOptions) (*ConfigApplyStatus, *Response, error) { + u := "manage/v1/config/apply" + req, err := s.client.NewRequest("GET", u, opts) + if err != nil { + return nil, nil, err + } + + status := new(ConfigApplyStatus) + resp, err := s.client.Do(ctx, req, status) + if err != nil { + return nil, resp, err + } + return status, resp, nil +} diff --git a/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_maintenance.go b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_maintenance.go new file mode 100644 index 0000000000..3b1de92df1 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_maintenance.go @@ -0,0 +1,94 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// MaintenanceOperationStatus represents the message to be displayed when the instance gets a maintenance operation request. +type MaintenanceOperationStatus struct { + Hostname *string `json:"hostname,omitempty"` + UUID *string `json:"uuid,omitempty"` + Message *string `json:"message,omitempty"` +} + +// MaintenanceStatus represents the status of maintenance mode for all nodes. +type MaintenanceStatus struct { + Hostname *string `json:"hostname,omitempty"` + UUID *string `json:"uuid,omitempty"` + Status *string `json:"status,omitempty"` + ScheduledTime *Timestamp `json:"scheduled_time,omitempty"` + ConnectionServices []*ConnectionServiceItem `json:"connection_services,omitempty"` + CanUnsetMaintenance *bool `json:"can_unset_maintenance,omitempty"` + IPExceptionList []string `json:"ip_exception_list,omitempty"` + MaintenanceModeMessage *string `json:"maintenance_mode_message,omitempty"` +} + +// ConnectionServiceItem represents the connection services for the maintenance status. +type ConnectionServiceItem struct { + Name *string `json:"name,omitempty"` + Number *int `json:"number,omitempty"` +} + +// MaintenanceOptions represents the options for setting the maintenance mode for the instance. +// When can be a string, so we can't use a Timestamp type. +type MaintenanceOptions struct { + Enabled bool `json:"enabled"` + UUID *string `json:"uuid,omitempty"` + When *string `json:"when,omitempty"` + IPExceptionList []string `json:"ip_exception_list,omitempty"` + MaintenanceModeMessage *string `json:"maintenance_mode_message,omitempty"` +} + +// GetMaintenanceStatus gets the status of maintenance mode for all nodes. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-status-of-maintenance-mode +// +//meta:operation GET /manage/v1/maintenance +func (s *EnterpriseService) GetMaintenanceStatus(ctx context.Context, opts *NodeQueryOptions) ([]*MaintenanceStatus, *Response, error) { + u, err := addOptions("manage/v1/maintenance", opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var status []*MaintenanceStatus + resp, err := s.client.Do(ctx, req, &status) + if err != nil { + return nil, resp, err + } + + return status, resp, nil +} + +// CreateMaintenance sets the maintenance mode for the instance. +// With the enable parameter we can control to put instance into maintenance mode or not. With false we can disable the maintenance mode. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#set-the-status-of-maintenance-mode +// +//meta:operation POST /manage/v1/maintenance +func (s *EnterpriseService) CreateMaintenance(ctx context.Context, enable bool, opts *MaintenanceOptions) ([]*MaintenanceOperationStatus, *Response, error) { + u := "manage/v1/maintenance" + + opts.Enabled = enable + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + var i []*MaintenanceOperationStatus + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} diff --git a/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_ssh.go b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_ssh.go new file mode 100644 index 0000000000..77d2521659 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/enterprise_manage_ghes_ssh.go @@ -0,0 +1,99 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// SSHKeyStatus represents the status of a SSH key operation. +type SSHKeyStatus struct { + Hostname *string `json:"hostname,omitempty"` + UUID *string `json:"uuid,omitempty"` + Message *string `json:"message,omitempty"` + Modified *bool `json:"modified,omitempty"` +} + +// SSHKeyOptions specifies the parameters to the SSH create and delete functions. +type SSHKeyOptions struct { + // Key is the SSH key to add to the instance. + Key string `json:"key"` +} + +// ClusterSSHKey represents the SSH keys configured for the instance. +type ClusterSSHKey struct { + Key *string `json:"key,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +// DeleteSSHKey deletes the SSH key from the instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#delete-a-ssh-key +// +//meta:operation DELETE /manage/v1/access/ssh +func (s *EnterpriseService) DeleteSSHKey(ctx context.Context, key string) ([]*SSHKeyStatus, *Response, error) { + u := "manage/v1/access/ssh" + opts := &SSHKeyOptions{ + Key: key, + } + req, err := s.client.NewRequest("DELETE", u, opts) + if err != nil { + return nil, nil, err + } + + var sshStatus []*SSHKeyStatus + resp, err := s.client.Do(ctx, req, &sshStatus) + if err != nil { + return nil, resp, err + } + + return sshStatus, resp, nil +} + +// GetSSHKey gets the SSH keys configured for the instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#get-the-configured-ssh-keys +// +//meta:operation GET /manage/v1/access/ssh +func (s *EnterpriseService) GetSSHKey(ctx context.Context) ([]*ClusterSSHKey, *Response, error) { + u := "manage/v1/access/ssh" + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var sshKeys []*ClusterSSHKey + resp, err := s.client.Do(ctx, req, &sshKeys) + if err != nil { + return nil, resp, err + } + + return sshKeys, resp, nil +} + +// CreateSSHKey adds a new SSH key to the instance. +// +// GitHub API docs: https://docs.github.com/enterprise-server@3.15/rest/enterprise-admin/manage-ghes#set-a-new-ssh-key +// +//meta:operation POST /manage/v1/access/ssh +func (s *EnterpriseService) CreateSSHKey(ctx context.Context, key string) ([]*SSHKeyStatus, *Response, error) { + u := "manage/v1/access/ssh" + opts := &SSHKeyOptions{ + Key: key, + } + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + var sshKeyResponse []*SSHKeyStatus + resp, err := s.client.Do(ctx, req, &sshKeyResponse) + if err != nil { + return nil, resp, err + } + + return sshKeyResponse, resp, nil +} diff --git a/vendor/github.com/google/go-github/v70/github/enterprise_network_configurations.go b/vendor/github.com/google/go-github/v70/github/enterprise_network_configurations.go new file mode 100644 index 0000000000..a6a690d786 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/enterprise_network_configurations.go @@ -0,0 +1,139 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListEnterpriseNetworkConfigurations lists all hosted compute network configurations configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/network-configurations#list-hosted-compute-network-configurations-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/network-configurations +func (s *EnterpriseService) ListEnterpriseNetworkConfigurations(ctx context.Context, enterprise string, opts *ListOptions) (*NetworkConfigurations, *Response, error) { + u := fmt.Sprintf("enterprises/%v/network-configurations", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + networks := &NetworkConfigurations{} + resp, err := s.client.Do(ctx, req, networks) + if err != nil { + return nil, resp, err + } + return networks, resp, nil +} + +// CreateEnterpriseNetworkConfiguration creates a hosted compute network configuration for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/network-configurations#create-a-hosted-compute-network-configuration-for-an-enterprise +// +//meta:operation POST /enterprises/{enterprise}/network-configurations +func (s *EnterpriseService) CreateEnterpriseNetworkConfiguration(ctx context.Context, enterprise string, createReq NetworkConfigurationRequest) (*NetworkConfiguration, *Response, error) { + if err := validateNetworkConfigurationRequest(createReq); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("enterprises/%v/network-configurations", enterprise) + req, err := s.client.NewRequest("POST", u, createReq) + if err != nil { + return nil, nil, err + } + + network := &NetworkConfiguration{} + resp, err := s.client.Do(ctx, req, network) + if err != nil { + return nil, resp, err + } + + return network, resp, nil +} + +// GetEnterpriseNetworkConfiguration gets a hosted compute network configuration configured in an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/network-configurations#get-a-hosted-compute-network-configuration-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/network-configurations/{network_configuration_id} +func (s *EnterpriseService) GetEnterpriseNetworkConfiguration(ctx context.Context, enterprise, networkID string) (*NetworkConfiguration, *Response, error) { + u := fmt.Sprintf("enterprises/%v/network-configurations/%v", enterprise, networkID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + network := &NetworkConfiguration{} + resp, err := s.client.Do(ctx, req, network) + if err != nil { + return nil, resp, err + } + return network, resp, nil +} + +// UpdateEnterpriseNetworkConfiguration updates a hosted compute network configuration for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/network-configurations#update-a-hosted-compute-network-configuration-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/network-configurations/{network_configuration_id} +func (s *EnterpriseService) UpdateEnterpriseNetworkConfiguration(ctx context.Context, enterprise, networkID string, updateReq NetworkConfigurationRequest) (*NetworkConfiguration, *Response, error) { + if err := validateNetworkConfigurationRequest(updateReq); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("enterprises/%v/network-configurations/%v", enterprise, networkID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + network := &NetworkConfiguration{} + resp, err := s.client.Do(ctx, req, network) + if err != nil { + return nil, resp, err + } + return network, resp, nil +} + +// DeleteEnterpriseNetworkConfiguration deletes a hosted compute network configuration from an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/network-configurations#delete-a-hosted-compute-network-configuration-from-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/network-configurations/{network_configuration_id} +func (s *EnterpriseService) DeleteEnterpriseNetworkConfiguration(ctx context.Context, enterprise, networkID string) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/network-configurations/%v", enterprise, networkID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// GetEnterpriseNetworkSettingsResource gets a hosted compute network settings resource configured for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/network-configurations#get-a-hosted-compute-network-settings-resource-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/network-settings/{network_settings_id} +func (s *EnterpriseService) GetEnterpriseNetworkSettingsResource(ctx context.Context, enterprise, networkID string) (*NetworkSettingsResource, *Response, error) { + u := fmt.Sprintf("enterprises/%v/network-settings/%v", enterprise, networkID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resource := &NetworkSettingsResource{} + resp, err := s.client.Do(ctx, req, resource) + if err != nil { + return nil, resp, err + } + return resource, resp, err +} diff --git a/vendor/github.com/google/go-github/v68/github/enterprise_properties.go b/vendor/github.com/google/go-github/v70/github/enterprise_properties.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/enterprise_properties.go rename to vendor/github.com/google/go-github/v70/github/enterprise_properties.go diff --git a/vendor/github.com/google/go-github/v70/github/enterprise_rules.go b/vendor/github.com/google/go-github/v70/github/enterprise_rules.go new file mode 100644 index 0000000000..f438223370 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/enterprise_rules.go @@ -0,0 +1,118 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CreateRepositoryRuleset creates a repository ruleset for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/rules#create-an-enterprise-repository-ruleset +// +//meta:operation POST /enterprises/{enterprise}/rulesets +func (s *EnterpriseService) CreateRepositoryRuleset(ctx context.Context, enterprise string, ruleset RepositoryRuleset) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("enterprises/%v/rulesets", enterprise) + + req, err := s.client.NewRequest("POST", u, ruleset) + if err != nil { + return nil, nil, err + } + + var rs *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// GetRepositoryRuleset gets a repository ruleset for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/rules#get-an-enterprise-repository-ruleset +// +//meta:operation GET /enterprises/{enterprise}/rulesets/{ruleset_id} +func (s *EnterpriseService) GetRepositoryRuleset(ctx context.Context, enterprise string, rulesetID int64) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("enterprises/%v/rulesets/%v", enterprise, rulesetID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateRepositoryRuleset updates a repository ruleset for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/rules#update-an-enterprise-repository-ruleset +// +//meta:operation PUT /enterprises/{enterprise}/rulesets/{ruleset_id} +func (s *EnterpriseService) UpdateRepositoryRuleset(ctx context.Context, enterprise string, rulesetID int64, ruleset RepositoryRuleset) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("enterprises/%v/rulesets/%v", enterprise, rulesetID) + + req, err := s.client.NewRequest("PUT", u, ruleset) + if err != nil { + return nil, nil, err + } + + var rs *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// UpdateRepositoryRulesetClearBypassActor clears the bypass actors for a repository ruleset for the specified enterprise. +// +// This function is necessary as the UpdateRepositoryRuleset function does not marshal ByPassActor if passed as an empty array. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/rules#update-an-enterprise-repository-ruleset +// +//meta:operation PUT /enterprises/{enterprise}/rulesets/{ruleset_id} +func (s *EnterpriseService) UpdateRepositoryRulesetClearBypassActor(ctx context.Context, enterprise string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/rulesets/%v", enterprise, rulesetID) + + rsClearBypassActor := rulesetClearBypassActors{} + + req, err := s.client.NewRequest("PUT", u, rsClearBypassActor) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DeleteRepositoryRuleset deletes a repository ruleset from the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/rules#delete-an-enterprise-repository-ruleset +// +//meta:operation DELETE /enterprises/{enterprise}/rulesets/{ruleset_id} +func (s *EnterpriseService) DeleteRepositoryRuleset(ctx context.Context, enterprise string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/rulesets/%v", enterprise, rulesetID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/event.go b/vendor/github.com/google/go-github/v70/github/event.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/event.go rename to vendor/github.com/google/go-github/v70/github/event.go diff --git a/vendor/github.com/google/go-github/v68/github/event_types.go b/vendor/github.com/google/go-github/v70/github/event_types.go similarity index 96% rename from vendor/github.com/google/go-github/v68/github/event_types.go rename to vendor/github.com/google/go-github/v70/github/event_types.go index 37e62c2fab..6a6caf19dd 100644 --- a/vendor/github.com/google/go-github/v68/github/event_types.go +++ b/vendor/github.com/google/go-github/v70/github/event_types.go @@ -858,8 +858,10 @@ type MergeGroup struct { // // GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhook-events-and-payloads#merge_group type MergeGroupEvent struct { - // The action that was performed. Currently, can only be checks_requested. + // The action that was performed. Possible values are: "checks_requested", "destroyed". Action *string `json:"action,omitempty"` + // Reason is populated when the action is "destroyed". Possible values: "merged", "invalidated", "dequeued". + Reason *string `json:"reason,omitempty"` // The merge group. MergeGroup *MergeGroup `json:"merge_group,omitempty"` @@ -1521,14 +1523,73 @@ type RepositoryImportEvent struct { // // GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#repository_ruleset type RepositoryRulesetEvent struct { - Action *string `json:"action,omitempty"` - Enterprise *Enterprise `json:"enterprise,omitempty"` - Installation *Installation `json:"installation,omitempty"` - Organization *Organization `json:"organization,omitempty"` - Repository *Repository `json:"repository,omitempty"` - RepositoryRuleset *RepositoryRuleset `json:"repository_ruleset"` - Changes *RepositoryRulesetEditedChanges `json:"changes,omitempty"` - Sender *User `json:"sender"` + Action *string `json:"action,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repository *Repository `json:"repository,omitempty"` + RepositoryRuleset *RepositoryRuleset `json:"repository_ruleset"` + Changes *RepositoryRulesetChanges `json:"changes,omitempty"` + Sender *User `json:"sender"` +} + +// RepositoryRulesetChanges represents the changes made to a repository ruleset. +type RepositoryRulesetChanges struct { + Name *RepositoryRulesetChangeSource `json:"name,omitempty"` + Enforcement *RepositoryRulesetChangeSource `json:"enforcement,omitempty"` + Conditions *RepositoryRulesetChangedConditions `json:"conditions,omitempty"` + Rules *RepositoryRulesetChangedRules `json:"rules,omitempty"` +} + +// RepositoryRulesetChangeSource represents a source change for the ruleset. +type RepositoryRulesetChangeSource struct { + From *string `json:"from,omitempty"` +} + +// RepositoryRulesetChangeSources represents multiple source changes for the ruleset. +type RepositoryRulesetChangeSources struct { + From []string `json:"from,omitempty"` +} + +// RepositoryRulesetChangedConditions holds changes to conditions in a ruleset. +type RepositoryRulesetChangedConditions struct { + Added []*RepositoryRulesetConditions `json:"added,omitempty"` + Deleted []*RepositoryRulesetConditions `json:"deleted,omitempty"` + Updated []*RepositoryRulesetUpdatedConditions `json:"updated,omitempty"` +} + +// RepositoryRulesetUpdatedConditions represents the edited updates to conditions in a ruleset. +type RepositoryRulesetUpdatedConditions struct { + Condition *RepositoryRulesetConditions `json:"condition,omitempty"` + Changes *RepositoryRulesetUpdatedCondition `json:"changes,omitempty"` +} + +// RepositoryRulesetUpdatedCondition represents the changes to a condition in a ruleset. +type RepositoryRulesetUpdatedCondition struct { + ConditionType *RepositoryRulesetChangeSource `json:"condition_type,omitempty"` + Target *RepositoryRulesetChangeSource `json:"target,omitempty"` + Include *RepositoryRulesetChangeSources `json:"include,omitempty"` + Exclude *RepositoryRulesetChangeSources `json:"exclude,omitempty"` +} + +// RepositoryRulesetChangedRules holds changes to rules in a ruleset. +type RepositoryRulesetChangedRules struct { + Added []*RepositoryRule `json:"added,omitempty"` + Deleted []*RepositoryRule `json:"deleted,omitempty"` + Updated []*RepositoryRulesetUpdatedRules `json:"updated,omitempty"` +} + +// RepositoryRulesetUpdatedRules holds updates to rules in a ruleset. +type RepositoryRulesetUpdatedRules struct { + Rule *RepositoryRule `json:"rule,omitempty"` + Changes *RepositoryRulesetChangedRule `json:"changes,omitempty"` +} + +// RepositoryRulesetChangedRule holds changes made to a rule in a ruleset. +type RepositoryRulesetChangedRule struct { + Configuration *RepositoryRulesetChangeSource `json:"configuration,omitempty"` + RuleType *RepositoryRulesetChangeSource `json:"rule_type,omitempty"` + Pattern *RepositoryRulesetChangeSource `json:"pattern,omitempty"` } // RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved. diff --git a/vendor/github.com/google/go-github/v68/github/gists.go b/vendor/github.com/google/go-github/v70/github/gists.go similarity index 99% rename from vendor/github.com/google/go-github/v68/github/gists.go rename to vendor/github.com/google/go-github/v70/github/gists.go index 08180c6d30..ee4314b986 100644 --- a/vendor/github.com/google/go-github/v68/github/gists.go +++ b/vendor/github.com/google/go-github/v70/github/gists.go @@ -1,6 +1,6 @@ // Copyright 2013 The go-github AUTHORS. All rights reserved. // -// Use of this source code is governed by BSD-style +// Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github diff --git a/vendor/github.com/google/go-github/v68/github/gists_comments.go b/vendor/github.com/google/go-github/v70/github/gists_comments.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/gists_comments.go rename to vendor/github.com/google/go-github/v70/github/gists_comments.go diff --git a/vendor/github.com/google/go-github/v68/github/git.go b/vendor/github.com/google/go-github/v70/github/git.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/git.go rename to vendor/github.com/google/go-github/v70/github/git.go diff --git a/vendor/github.com/google/go-github/v68/github/git_blobs.go b/vendor/github.com/google/go-github/v70/github/git_blobs.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/git_blobs.go rename to vendor/github.com/google/go-github/v70/github/git_blobs.go diff --git a/vendor/github.com/google/go-github/v68/github/git_commits.go b/vendor/github.com/google/go-github/v70/github/git_commits.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/git_commits.go rename to vendor/github.com/google/go-github/v70/github/git_commits.go diff --git a/vendor/github.com/google/go-github/v68/github/git_refs.go b/vendor/github.com/google/go-github/v70/github/git_refs.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/git_refs.go rename to vendor/github.com/google/go-github/v70/github/git_refs.go diff --git a/vendor/github.com/google/go-github/v68/github/git_tags.go b/vendor/github.com/google/go-github/v70/github/git_tags.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/git_tags.go rename to vendor/github.com/google/go-github/v70/github/git_tags.go diff --git a/vendor/github.com/google/go-github/v68/github/git_trees.go b/vendor/github.com/google/go-github/v70/github/git_trees.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/git_trees.go rename to vendor/github.com/google/go-github/v70/github/git_trees.go diff --git a/vendor/github.com/google/go-github/v68/github/github-accessors.go b/vendor/github.com/google/go-github/v70/github/github-accessors.go similarity index 90% rename from vendor/github.com/google/go-github/v68/github/github-accessors.go rename to vendor/github.com/google/go-github/v70/github/github-accessors.go index 0800c02c6c..ec029df241 100644 --- a/vendor/github.com/google/go-github/v68/github/github-accessors.go +++ b/vendor/github.com/google/go-github/v70/github/github-accessors.go @@ -1934,20 +1934,20 @@ func (b *BypassActor) GetActorID() int64 { return *b.ActorID } -// GetActorType returns the ActorType field if it's non-nil, zero value otherwise. -func (b *BypassActor) GetActorType() string { - if b == nil || b.ActorType == nil { - return "" +// GetActorType returns the ActorType field. +func (b *BypassActor) GetActorType() *BypassActorType { + if b == nil { + return nil } - return *b.ActorType + return b.ActorType } -// GetBypassMode returns the BypassMode field if it's non-nil, zero value otherwise. -func (b *BypassActor) GetBypassMode() string { - if b == nil || b.BypassMode == nil { - return "" +// GetBypassMode returns the BypassMode field. +func (b *BypassActor) GetBypassMode() *BypassMode { + if b == nil { + return nil } - return *b.BypassMode + return b.BypassMode } // GetApp returns the App field. @@ -2358,20 +2358,20 @@ func (c *CheckSuite) GetRepository() *Repository { return c.Repository } -// GetRerequstable returns the Rerequstable field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetRerequstable() bool { - if c == nil || c.Rerequstable == nil { +// GetRerequestable returns the Rerequestable field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetRerequestable() bool { + if c == nil || c.Rerequestable == nil { return false } - return *c.Rerequstable + return *c.Rerequestable } -// GetRunsRerequstable returns the RunsRerequstable field if it's non-nil, zero value otherwise. -func (c *CheckSuite) GetRunsRerequstable() bool { - if c == nil || c.RunsRerequstable == nil { +// GetRunsRerequestable returns the RunsRerequestable field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetRunsRerequestable() bool { + if c == nil || c.RunsRerequestable == nil { return false } - return *c.RunsRerequstable + return *c.RunsRerequestable } // GetStatus returns the Status field if it's non-nil, zero value otherwise. @@ -2462,6 +2462,70 @@ func (c *CheckSuitePreferenceResults) GetRepository() *Repository { return c.Repository } +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (c *ClusterSSHKey) GetFingerprint() string { + if c == nil || c.Fingerprint == nil { + return "" + } + return *c.Fingerprint +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (c *ClusterSSHKey) GetKey() string { + if c == nil || c.Key == nil { + return "" + } + return *c.Key +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *ClusterStatus) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (c *ClusterStatusNode) GetHostname() string { + if c == nil || c.Hostname == nil { + return "" + } + return *c.Hostname +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *ClusterStatusNode) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetDetails returns the Details field if it's non-nil, zero value otherwise. +func (c *ClusterStatusNodeServiceItem) GetDetails() string { + if c == nil || c.Details == nil { + return "" + } + return *c.Details +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *ClusterStatusNodeServiceItem) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *ClusterStatusNodeServiceItem) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + // GetBody returns the Body field if it's non-nil, zero value otherwise. func (c *CodeOfConduct) GetBody() string { if c == nil || c.Body == nil { @@ -4038,304 +4102,1400 @@ func (c *CommunityHealthMetrics) GetUpdatedAt() Timestamp { return *c.UpdatedAt } -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (c *ContentReference) GetID() int64 { - if c == nil || c.ID == nil { - return 0 +// GetLastRequestID returns the LastRequestID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNode) GetLastRequestID() string { + if c == nil || c.LastRequestID == nil { + return "" } - return *c.ID + return *c.LastRequestID } -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (c *ContentReference) GetNodeID() string { - if c == nil || c.NodeID == nil { +// GetNode returns the Node field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNode) GetNode() string { + if c == nil || c.Node == nil { return "" } - return *c.NodeID + return *c.Node } -// GetReference returns the Reference field if it's non-nil, zero value otherwise. -func (c *ContentReference) GetReference() string { - if c == nil || c.Reference == nil { +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetBody() string { + if c == nil || c.Body == nil { return "" } - return *c.Reference + return *c.Body } -// GetAction returns the Action field if it's non-nil, zero value otherwise. -func (c *ContentReferenceEvent) GetAction() string { - if c == nil || c.Action == nil { +// GetConfigRunID returns the ConfigRunID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetConfigRunID() string { + if c == nil || c.ConfigRunID == nil { return "" } - return *c.Action + return *c.ConfigRunID } -// GetContentReference returns the ContentReference field. -func (c *ContentReferenceEvent) GetContentReference() *ContentReference { - if c == nil { - return nil +// GetEventName returns the EventName field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetEventName() string { + if c == nil || c.EventName == nil { + return "" } - return c.ContentReference + return *c.EventName } -// GetInstallation returns the Installation field. -func (c *ContentReferenceEvent) GetInstallation() *Installation { - if c == nil { - return nil +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetHostname() string { + if c == nil || c.Hostname == nil { + return "" } - return c.Installation + return *c.Hostname } -// GetRepo returns the Repo field. -func (c *ContentReferenceEvent) GetRepo() *Repository { - if c == nil { - return nil +// GetSeverityText returns the SeverityText field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetSeverityText() string { + if c == nil || c.SeverityText == nil { + return "" } - return c.Repo + return *c.SeverityText } -// GetSender returns the Sender field. -func (c *ContentReferenceEvent) GetSender() *User { - if c == nil { - return nil +// GetSpanDepth returns the SpanDepth field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetSpanDepth() int { + if c == nil || c.SpanDepth == nil { + return 0 } - return c.Sender + return *c.SpanDepth } -// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetAvatarURL() string { - if c == nil || c.AvatarURL == nil { +// GetSpanID returns the SpanID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetSpanID() string { + if c == nil || c.SpanID == nil { return "" } - return *c.AvatarURL + return *c.SpanID } -// GetContributions returns the Contributions field if it's non-nil, zero value otherwise. -func (c *Contributor) GetContributions() int { - if c == nil || c.Contributions == nil { +// GetSpanParentID returns the SpanParentID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetSpanParentID() int64 { + if c == nil || c.SpanParentID == nil { return 0 } - return *c.Contributions + return *c.SpanParentID } -// GetEmail returns the Email field if it's non-nil, zero value otherwise. -func (c *Contributor) GetEmail() string { - if c == nil || c.Email == nil { - return "" +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetTimestamp() Timestamp { + if c == nil || c.Timestamp == nil { + return Timestamp{} } - return *c.Email + return *c.Timestamp } -// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetEventsURL() string { - if c == nil || c.EventsURL == nil { +// GetTopology returns the Topology field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetTopology() string { + if c == nil || c.Topology == nil { return "" } - return *c.EventsURL + return *c.Topology } -// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetFollowersURL() string { - if c == nil || c.FollowersURL == nil { +// GetTraceID returns the TraceID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsNodeEvent) GetTraceID() string { + if c == nil || c.TraceID == nil { return "" } - return *c.FollowersURL + return *c.TraceID } -// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetFollowingURL() string { - if c == nil || c.FollowingURL == nil { +// GetLastRequestID returns the LastRequestID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyEventsOptions) GetLastRequestID() string { + if c == nil || c.LastRequestID == nil { return "" } - return *c.FollowingURL + return *c.LastRequestID } -// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetGistsURL() string { - if c == nil || c.GistsURL == nil { +// GetRunID returns the RunID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyOptions) GetRunID() string { + if c == nil || c.RunID == nil { return "" } - return *c.GistsURL + return *c.RunID } -// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. -func (c *Contributor) GetGravatarID() string { - if c == nil || c.GravatarID == nil { - return "" +// GetRunning returns the Running field if it's non-nil, zero value otherwise. +func (c *ConfigApplyStatus) GetRunning() bool { + if c == nil || c.Running == nil { + return false } - return *c.GravatarID + return *c.Running } -// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetHTMLURL() string { - if c == nil || c.HTMLURL == nil { - return "" +// GetSuccessful returns the Successful field if it's non-nil, zero value otherwise. +func (c *ConfigApplyStatus) GetSuccessful() bool { + if c == nil || c.Successful == nil { + return false } - return *c.HTMLURL + return *c.Successful } -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (c *Contributor) GetID() int64 { - if c == nil || c.ID == nil { - return 0 +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (c *ConfigApplyStatusNode) GetHostname() string { + if c == nil || c.Hostname == nil { + return "" } - return *c.ID + return *c.Hostname } -// GetLogin returns the Login field if it's non-nil, zero value otherwise. -func (c *Contributor) GetLogin() string { - if c == nil || c.Login == nil { +// GetRunID returns the RunID field if it's non-nil, zero value otherwise. +func (c *ConfigApplyStatusNode) GetRunID() string { + if c == nil || c.RunID == nil { return "" } - return *c.Login + return *c.RunID } -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (c *Contributor) GetName() string { - if c == nil || c.Name == nil { - return "" +// GetRunning returns the Running field if it's non-nil, zero value otherwise. +func (c *ConfigApplyStatusNode) GetRunning() bool { + if c == nil || c.Running == nil { + return false } - return *c.Name + return *c.Running } -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (c *Contributor) GetNodeID() string { - if c == nil || c.NodeID == nil { - return "" +// GetSuccessful returns the Successful field if it's non-nil, zero value otherwise. +func (c *ConfigApplyStatusNode) GetSuccessful() bool { + if c == nil || c.Successful == nil { + return false } - return *c.NodeID + return *c.Successful } -// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetOrganizationsURL() string { - if c == nil || c.OrganizationsURL == nil { +// GetAdminPassword returns the AdminPassword field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetAdminPassword() string { + if c == nil || c.AdminPassword == nil { return "" } - return *c.OrganizationsURL + return *c.AdminPassword } -// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetReceivedEventsURL() string { - if c == nil || c.ReceivedEventsURL == nil { +// GetAssets returns the Assets field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetAssets() string { + if c == nil || c.Assets == nil { return "" } - return *c.ReceivedEventsURL + return *c.Assets } -// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetReposURL() string { - if c == nil || c.ReposURL == nil { +// GetAuthMode returns the AuthMode field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetAuthMode() string { + if c == nil || c.AuthMode == nil { return "" } - return *c.ReposURL + return *c.AuthMode } -// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. -func (c *Contributor) GetSiteAdmin() bool { - if c == nil || c.SiteAdmin == nil { - return false +// GetAvatar returns the Avatar field. +func (c *ConfigSettings) GetAvatar() *ConfigSettingsAvatar { + if c == nil { + return nil } - return *c.SiteAdmin + return c.Avatar } -// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetStarredURL() string { - if c == nil || c.StarredURL == nil { - return "" +// GetCAS returns the CAS field. +func (c *ConfigSettings) GetCAS() *ConfigSettingsCAS { + if c == nil { + return nil } - return *c.StarredURL + return c.CAS } -// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetSubscriptionsURL() string { - if c == nil || c.SubscriptionsURL == nil { - return "" +// GetCollectd returns the Collectd field. +func (c *ConfigSettings) GetCollectd() *ConfigSettingsCollectd { + if c == nil { + return nil } - return *c.SubscriptionsURL + return c.Collectd } -// GetType returns the Type field if it's non-nil, zero value otherwise. -func (c *Contributor) GetType() string { - if c == nil || c.Type == nil { - return "" +// GetConfigurationID returns the ConfigurationID field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetConfigurationID() int64 { + if c == nil || c.ConfigurationID == nil { + return 0 } - return *c.Type + return *c.ConfigurationID } -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (c *Contributor) GetURL() string { - if c == nil || c.URL == nil { - return "" +// GetConfigurationRunCount returns the ConfigurationRunCount field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetConfigurationRunCount() int { + if c == nil || c.ConfigurationRunCount == nil { + return 0 } - return *c.URL + return *c.ConfigurationRunCount } -// GetAuthor returns the Author field. -func (c *ContributorStats) GetAuthor() *Contributor { +// GetCustomer returns the Customer field. +func (c *ConfigSettings) GetCustomer() *ConfigSettingsCustomer { if c == nil { return nil } - return c.Author + return c.Customer } -// GetTotal returns the Total field if it's non-nil, zero value otherwise. -func (c *ContributorStats) GetTotal() int { - if c == nil || c.Total == nil { - return 0 +// GetExpireSessions returns the ExpireSessions field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetExpireSessions() bool { + if c == nil || c.ExpireSessions == nil { + return false } - return *c.Total + return *c.ExpireSessions } -// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. -func (c *CopilotDotcomChatModel) GetCustomModelTrainingDate() string { - if c == nil || c.CustomModelTrainingDate == nil { +// GetGithubHostname returns the GithubHostname field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetGithubHostname() string { + if c == nil || c.GithubHostname == nil { return "" } - return *c.CustomModelTrainingDate + return *c.GithubHostname } -// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. -func (c *CopilotDotcomPullRequestsModel) GetCustomModelTrainingDate() string { - if c == nil || c.CustomModelTrainingDate == nil { - return "" +// GetGithubOAuth returns the GithubOAuth field. +func (c *ConfigSettings) GetGithubOAuth() *ConfigSettingsGithubOAuth { + if c == nil { + return nil } - return *c.CustomModelTrainingDate + return c.GithubOAuth } -// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. -func (c *CopilotIDEChatModel) GetCustomModelTrainingDate() string { - if c == nil || c.CustomModelTrainingDate == nil { - return "" +// GetGithubSSL returns the GithubSSL field. +func (c *ConfigSettings) GetGithubSSL() *ConfigSettingsGithubSSL { + if c == nil { + return nil } - return *c.CustomModelTrainingDate + return c.GithubSSL } -// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. -func (c *CopilotIDECodeCompletionsModel) GetCustomModelTrainingDate() string { - if c == nil || c.CustomModelTrainingDate == nil { +// GetHTTPProxy returns the HTTPProxy field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetHTTPProxy() string { + if c == nil || c.HTTPProxy == nil { return "" } - return *c.CustomModelTrainingDate + return *c.HTTPProxy } -// GetCopilotDotcomChat returns the CopilotDotcomChat field. -func (c *CopilotMetrics) GetCopilotDotcomChat() *CopilotDotcomChat { - if c == nil { - return nil +// GetIdenticonsHost returns the IdenticonsHost field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetIdenticonsHost() string { + if c == nil || c.IdenticonsHost == nil { + return "" } - return c.CopilotDotcomChat + return *c.IdenticonsHost } -// GetCopilotDotcomPullRequests returns the CopilotDotcomPullRequests field. -func (c *CopilotMetrics) GetCopilotDotcomPullRequests() *CopilotDotcomPullRequests { +// GetLDAP returns the LDAP field. +func (c *ConfigSettings) GetLDAP() *ConfigSettingsLDAP { if c == nil { return nil } - return c.CopilotDotcomPullRequests + return c.LDAP } -// GetCopilotIDEChat returns the CopilotIDEChat field. -func (c *CopilotMetrics) GetCopilotIDEChat() *CopilotIDEChat { +// GetLicense returns the License field. +func (c *ConfigSettings) GetLicense() *ConfigSettingsLicenseSettings { + if c == nil { + return nil + } + return c.License +} + +// GetLoadBalancer returns the LoadBalancer field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetLoadBalancer() string { + if c == nil || c.LoadBalancer == nil { + return "" + } + return *c.LoadBalancer +} + +// GetMapping returns the Mapping field. +func (c *ConfigSettings) GetMapping() *ConfigSettingsMapping { + if c == nil { + return nil + } + return c.Mapping +} + +// GetNTP returns the NTP field. +func (c *ConfigSettings) GetNTP() *ConfigSettingsNTP { + if c == nil { + return nil + } + return c.NTP +} + +// GetPages returns the Pages field. +func (c *ConfigSettings) GetPages() *ConfigSettingsPagesSettings { + if c == nil { + return nil + } + return c.Pages +} + +// GetPrivateMode returns the PrivateMode field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetPrivateMode() bool { + if c == nil || c.PrivateMode == nil { + return false + } + return *c.PrivateMode +} + +// GetPublicPages returns the PublicPages field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetPublicPages() bool { + if c == nil || c.PublicPages == nil { + return false + } + return *c.PublicPages +} + +// GetSAML returns the SAML field. +func (c *ConfigSettings) GetSAML() *ConfigSettingsSAML { + if c == nil { + return nil + } + return c.SAML +} + +// GetSignupEnabled returns the SignupEnabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetSignupEnabled() bool { + if c == nil || c.SignupEnabled == nil { + return false + } + return *c.SignupEnabled +} + +// GetSMTP returns the SMTP field. +func (c *ConfigSettings) GetSMTP() *ConfigSettingsSMTP { + if c == nil { + return nil + } + return c.SMTP +} + +// GetSNMP returns the SNMP field. +func (c *ConfigSettings) GetSNMP() *ConfigSettingsSNMP { + if c == nil { + return nil + } + return c.SNMP +} + +// GetSubdomainIsolation returns the SubdomainIsolation field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetSubdomainIsolation() bool { + if c == nil || c.SubdomainIsolation == nil { + return false + } + return *c.SubdomainIsolation +} + +// GetSyslog returns the Syslog field. +func (c *ConfigSettings) GetSyslog() *ConfigSettingsSyslog { + if c == nil { + return nil + } + return c.Syslog +} + +// GetTimezone returns the Timezone field if it's non-nil, zero value otherwise. +func (c *ConfigSettings) GetTimezone() string { + if c == nil || c.Timezone == nil { + return "" + } + return *c.Timezone +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsAvatar) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetURI returns the URI field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsAvatar) GetURI() string { + if c == nil || c.URI == nil { + return "" + } + return *c.URI +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCAS) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCollectd) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetEncryption returns the Encryption field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCollectd) GetEncryption() string { + if c == nil || c.Encryption == nil { + return "" + } + return *c.Encryption +} + +// GetPassword returns the Password field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCollectd) GetPassword() string { + if c == nil || c.Password == nil { + return "" + } + return *c.Password +} + +// GetPort returns the Port field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCollectd) GetPort() int { + if c == nil || c.Port == nil { + return 0 + } + return *c.Port +} + +// GetServer returns the Server field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCollectd) GetServer() string { + if c == nil || c.Server == nil { + return "" + } + return *c.Server +} + +// GetUsername returns the Username field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCollectd) GetUsername() string { + if c == nil || c.Username == nil { + return "" + } + return *c.Username +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCustomer) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCustomer) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetPublicKeyData returns the PublicKeyData field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCustomer) GetPublicKeyData() string { + if c == nil || c.PublicKeyData == nil { + return "" + } + return *c.PublicKeyData +} + +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCustomer) GetSecret() string { + if c == nil || c.Secret == nil { + return "" + } + return *c.Secret +} + +// GetUUID returns the UUID field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsCustomer) GetUUID() string { + if c == nil || c.UUID == nil { + return "" + } + return *c.UUID +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsGithubOAuth) GetClientID() string { + if c == nil || c.ClientID == nil { + return "" + } + return *c.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsGithubOAuth) GetClientSecret() string { + if c == nil || c.ClientSecret == nil { + return "" + } + return *c.ClientSecret +} + +// GetOrganizationName returns the OrganizationName field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsGithubOAuth) GetOrganizationName() string { + if c == nil || c.OrganizationName == nil { + return "" + } + return *c.OrganizationName +} + +// GetOrganizationTeam returns the OrganizationTeam field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsGithubOAuth) GetOrganizationTeam() string { + if c == nil || c.OrganizationTeam == nil { + return "" + } + return *c.OrganizationTeam +} + +// GetCert returns the Cert field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsGithubSSL) GetCert() string { + if c == nil || c.Cert == nil { + return "" + } + return *c.Cert +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsGithubSSL) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsGithubSSL) GetKey() string { + if c == nil || c.Key == nil { + return "" + } + return *c.Key +} + +// GetAdminGroup returns the AdminGroup field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetAdminGroup() string { + if c == nil || c.AdminGroup == nil { + return "" + } + return *c.AdminGroup +} + +// GetBindDN returns the BindDN field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetBindDN() string { + if c == nil || c.BindDN == nil { + return "" + } + return *c.BindDN +} + +// GetHost returns the Host field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetHost() string { + if c == nil || c.Host == nil { + return "" + } + return *c.Host +} + +// GetMethod returns the Method field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetMethod() string { + if c == nil || c.Method == nil { + return "" + } + return *c.Method +} + +// GetPassword returns the Password field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetPassword() string { + if c == nil || c.Password == nil { + return "" + } + return *c.Password +} + +// GetPort returns the Port field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetPort() int { + if c == nil || c.Port == nil { + return 0 + } + return *c.Port +} + +// GetPosixSupport returns the PosixSupport field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetPosixSupport() bool { + if c == nil || c.PosixSupport == nil { + return false + } + return *c.PosixSupport +} + +// GetProfile returns the Profile field. +func (c *ConfigSettingsLDAP) GetProfile() *ConfigSettingsLDAPProfile { + if c == nil { + return nil + } + return c.Profile +} + +// GetReconciliation returns the Reconciliation field. +func (c *ConfigSettingsLDAP) GetReconciliation() *ConfigSettingsLDAPReconciliation { + if c == nil { + return nil + } + return c.Reconciliation +} + +// GetRecursiveGroupSearch returns the RecursiveGroupSearch field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetRecursiveGroupSearch() bool { + if c == nil || c.RecursiveGroupSearch == nil { + return false + } + return *c.RecursiveGroupSearch +} + +// GetSearchStrategy returns the SearchStrategy field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetSearchStrategy() string { + if c == nil || c.SearchStrategy == nil { + return "" + } + return *c.SearchStrategy +} + +// GetSyncEnabled returns the SyncEnabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetSyncEnabled() bool { + if c == nil || c.SyncEnabled == nil { + return false + } + return *c.SyncEnabled +} + +// GetTeamSyncInterval returns the TeamSyncInterval field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetTeamSyncInterval() int { + if c == nil || c.TeamSyncInterval == nil { + return 0 + } + return *c.TeamSyncInterval +} + +// GetUID returns the UID field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetUID() string { + if c == nil || c.UID == nil { + return "" + } + return *c.UID +} + +// GetUserSyncEmails returns the UserSyncEmails field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetUserSyncEmails() bool { + if c == nil || c.UserSyncEmails == nil { + return false + } + return *c.UserSyncEmails +} + +// GetUserSyncInterval returns the UserSyncInterval field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetUserSyncInterval() int { + if c == nil || c.UserSyncInterval == nil { + return 0 + } + return *c.UserSyncInterval +} + +// GetUserSyncKeys returns the UserSyncKeys field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetUserSyncKeys() bool { + if c == nil || c.UserSyncKeys == nil { + return false + } + return *c.UserSyncKeys +} + +// GetVirtualAttributeEnabled returns the VirtualAttributeEnabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAP) GetVirtualAttributeEnabled() bool { + if c == nil || c.VirtualAttributeEnabled == nil { + return false + } + return *c.VirtualAttributeEnabled +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAPProfile) GetKey() string { + if c == nil || c.Key == nil { + return "" + } + return *c.Key +} + +// GetMail returns the Mail field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAPProfile) GetMail() string { + if c == nil || c.Mail == nil { + return "" + } + return *c.Mail +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAPProfile) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetUID returns the UID field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAPProfile) GetUID() string { + if c == nil || c.UID == nil { + return "" + } + return *c.UID +} + +// GetOrg returns the Org field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAPReconciliation) GetOrg() string { + if c == nil || c.Org == nil { + return "" + } + return *c.Org +} + +// GetUser returns the User field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLDAPReconciliation) GetUser() string { + if c == nil || c.User == nil { + return "" + } + return *c.User +} + +// GetClusterSupport returns the ClusterSupport field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetClusterSupport() bool { + if c == nil || c.ClusterSupport == nil { + return false + } + return *c.ClusterSupport +} + +// GetEvaluation returns the Evaluation field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetEvaluation() bool { + if c == nil || c.Evaluation == nil { + return false + } + return *c.Evaluation +} + +// GetExpireAt returns the ExpireAt field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetExpireAt() Timestamp { + if c == nil || c.ExpireAt == nil { + return Timestamp{} + } + return *c.ExpireAt +} + +// GetPerpetual returns the Perpetual field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetPerpetual() bool { + if c == nil || c.Perpetual == nil { + return false + } + return *c.Perpetual +} + +// GetSeats returns the Seats field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetSeats() int { + if c == nil || c.Seats == nil { + return 0 + } + return *c.Seats +} + +// GetSSHAllowed returns the SSHAllowed field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetSSHAllowed() bool { + if c == nil || c.SSHAllowed == nil { + return false + } + return *c.SSHAllowed +} + +// GetSupportKey returns the SupportKey field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetSupportKey() string { + if c == nil || c.SupportKey == nil { + return "" + } + return *c.SupportKey +} + +// GetUnlimitedSeating returns the UnlimitedSeating field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsLicenseSettings) GetUnlimitedSeating() bool { + if c == nil || c.UnlimitedSeating == nil { + return false + } + return *c.UnlimitedSeating +} + +// GetBasemap returns the Basemap field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsMapping) GetBasemap() string { + if c == nil || c.Basemap == nil { + return "" + } + return *c.Basemap +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsMapping) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetTileserver returns the Tileserver field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsMapping) GetTileserver() string { + if c == nil || c.Tileserver == nil { + return "" + } + return *c.Tileserver +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsMapping) GetToken() string { + if c == nil || c.Token == nil { + return "" + } + return *c.Token +} + +// GetPrimaryServer returns the PrimaryServer field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsNTP) GetPrimaryServer() string { + if c == nil || c.PrimaryServer == nil { + return "" + } + return *c.PrimaryServer +} + +// GetSecondaryServer returns the SecondaryServer field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsNTP) GetSecondaryServer() string { + if c == nil || c.SecondaryServer == nil { + return "" + } + return *c.SecondaryServer +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsPagesSettings) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetCertificate returns the Certificate field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSAML) GetCertificate() string { + if c == nil || c.Certificate == nil { + return "" + } + return *c.Certificate +} + +// GetCertificatePath returns the CertificatePath field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSAML) GetCertificatePath() string { + if c == nil || c.CertificatePath == nil { + return "" + } + return *c.CertificatePath +} + +// GetDisableAdminDemote returns the DisableAdminDemote field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSAML) GetDisableAdminDemote() bool { + if c == nil || c.DisableAdminDemote == nil { + return false + } + return *c.DisableAdminDemote +} + +// GetIDPInitiatedSSO returns the IDPInitiatedSSO field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSAML) GetIDPInitiatedSSO() bool { + if c == nil || c.IDPInitiatedSSO == nil { + return false + } + return *c.IDPInitiatedSSO +} + +// GetIssuer returns the Issuer field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSAML) GetIssuer() string { + if c == nil || c.Issuer == nil { + return "" + } + return *c.Issuer +} + +// GetSSOURL returns the SSOURL field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSAML) GetSSOURL() string { + if c == nil || c.SSOURL == nil { + return "" + } + return *c.SSOURL +} + +// GetAddress returns the Address field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetAddress() string { + if c == nil || c.Address == nil { + return "" + } + return *c.Address +} + +// GetAuthentication returns the Authentication field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetAuthentication() string { + if c == nil || c.Authentication == nil { + return "" + } + return *c.Authentication +} + +// GetDiscardToNoreplyAddress returns the DiscardToNoreplyAddress field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetDiscardToNoreplyAddress() bool { + if c == nil || c.DiscardToNoreplyAddress == nil { + return false + } + return *c.DiscardToNoreplyAddress +} + +// GetDomain returns the Domain field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetDomain() string { + if c == nil || c.Domain == nil { + return "" + } + return *c.Domain +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetEnableStarttlsAuto returns the EnableStarttlsAuto field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetEnableStarttlsAuto() bool { + if c == nil || c.EnableStarttlsAuto == nil { + return false + } + return *c.EnableStarttlsAuto +} + +// GetNoreplyAddress returns the NoreplyAddress field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetNoreplyAddress() string { + if c == nil || c.NoreplyAddress == nil { + return "" + } + return *c.NoreplyAddress +} + +// GetPassword returns the Password field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetPassword() string { + if c == nil || c.Password == nil { + return "" + } + return *c.Password +} + +// GetPort returns the Port field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetPort() string { + if c == nil || c.Port == nil { + return "" + } + return *c.Port +} + +// GetSupportAddress returns the SupportAddress field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetSupportAddress() string { + if c == nil || c.SupportAddress == nil { + return "" + } + return *c.SupportAddress +} + +// GetSupportAddressType returns the SupportAddressType field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetSupportAddressType() string { + if c == nil || c.SupportAddressType == nil { + return "" + } + return *c.SupportAddressType +} + +// GetUsername returns the Username field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetUsername() string { + if c == nil || c.Username == nil { + return "" + } + return *c.Username +} + +// GetUserName returns the UserName field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSMTP) GetUserName() string { + if c == nil || c.UserName == nil { + return "" + } + return *c.UserName +} + +// GetCommunity returns the Community field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSNMP) GetCommunity() string { + if c == nil || c.Community == nil { + return "" + } + return *c.Community +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSNMP) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSyslog) GetEnabled() bool { + if c == nil || c.Enabled == nil { + return false + } + return *c.Enabled +} + +// GetProtocolName returns the ProtocolName field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSyslog) GetProtocolName() string { + if c == nil || c.ProtocolName == nil { + return "" + } + return *c.ProtocolName +} + +// GetServer returns the Server field if it's non-nil, zero value otherwise. +func (c *ConfigSettingsSyslog) GetServer() string { + if c == nil || c.Server == nil { + return "" + } + return *c.Server +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *ConnectionServiceItem) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (c *ConnectionServiceItem) GetNumber() int { + if c == nil || c.Number == nil { + return 0 + } + return *c.Number +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetReference returns the Reference field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetReference() string { + if c == nil || c.Reference == nil { + return "" + } + return *c.Reference +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *ContentReferenceEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetContentReference returns the ContentReference field. +func (c *ContentReferenceEvent) GetContentReference() *ContentReference { + if c == nil { + return nil + } + return c.ContentReference +} + +// GetInstallation returns the Installation field. +func (c *ContentReferenceEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetRepo returns the Repo field. +func (c *ContentReferenceEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *ContentReferenceEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetAvatarURL() string { + if c == nil || c.AvatarURL == nil { + return "" + } + return *c.AvatarURL +} + +// GetContributions returns the Contributions field if it's non-nil, zero value otherwise. +func (c *Contributor) GetContributions() int { + if c == nil || c.Contributions == nil { + return 0 + } + return *c.Contributions +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEventsURL() string { + if c == nil || c.EventsURL == nil { + return "" + } + return *c.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowersURL() string { + if c == nil || c.FollowersURL == nil { + return "" + } + return *c.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowingURL() string { + if c == nil || c.FollowingURL == nil { + return "" + } + return *c.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGistsURL() string { + if c == nil || c.GistsURL == nil { + return "" + } + return *c.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGravatarID() string { + if c == nil || c.GravatarID == nil { + return "" + } + return *c.GravatarID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *Contributor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *Contributor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetOrganizationsURL() string { + if c == nil || c.OrganizationsURL == nil { + return "" + } + return *c.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReceivedEventsURL() string { + if c == nil || c.ReceivedEventsURL == nil { + return "" + } + return *c.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReposURL() string { + if c == nil || c.ReposURL == nil { + return "" + } + return *c.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSiteAdmin() bool { + if c == nil || c.SiteAdmin == nil { + return false + } + return *c.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetStarredURL() string { + if c == nil || c.StarredURL == nil { + return "" + } + return *c.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSubscriptionsURL() string { + if c == nil || c.SubscriptionsURL == nil { + return "" + } + return *c.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *Contributor) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAuthor returns the Author field. +func (c *ContributorStats) GetAuthor() *Contributor { + if c == nil { + return nil + } + return c.Author +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *ContributorStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotDotcomPullRequestsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDEChatModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCustomModelTrainingDate returns the CustomModelTrainingDate field if it's non-nil, zero value otherwise. +func (c *CopilotIDECodeCompletionsModel) GetCustomModelTrainingDate() string { + if c == nil || c.CustomModelTrainingDate == nil { + return "" + } + return *c.CustomModelTrainingDate +} + +// GetCopilotDotcomChat returns the CopilotDotcomChat field. +func (c *CopilotMetrics) GetCopilotDotcomChat() *CopilotDotcomChat { + if c == nil { + return nil + } + return c.CopilotDotcomChat +} + +// GetCopilotDotcomPullRequests returns the CopilotDotcomPullRequests field. +func (c *CopilotMetrics) GetCopilotDotcomPullRequests() *CopilotDotcomPullRequests { + if c == nil { + return nil + } + return c.CopilotDotcomPullRequests +} + +// GetCopilotIDEChat returns the CopilotIDEChat field. +func (c *CopilotMetrics) GetCopilotIDEChat() *CopilotIDEChat { if c == nil { return nil } @@ -9022,6 +10182,134 @@ func (h *HookStats) GetTotalHooks() int { return *h.TotalHooks } +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetImageDetails returns the ImageDetails field. +func (h *HostedRunner) GetImageDetails() *HostedRunnerImageDetail { + if h == nil { + return nil + } + return h.ImageDetails +} + +// GetLastActiveOn returns the LastActiveOn field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetLastActiveOn() Timestamp { + if h == nil || h.LastActiveOn == nil { + return Timestamp{} + } + return *h.LastActiveOn +} + +// GetMachineSizeDetails returns the MachineSizeDetails field. +func (h *HostedRunner) GetMachineSizeDetails() *HostedRunnerMachineSpec { + if h == nil { + return nil + } + return h.MachineSizeDetails +} + +// GetMaximumRunners returns the MaximumRunners field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetMaximumRunners() int64 { + if h == nil || h.MaximumRunners == nil { + return 0 + } + return *h.MaximumRunners +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetName() string { + if h == nil || h.Name == nil { + return "" + } + return *h.Name +} + +// GetPlatform returns the Platform field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetPlatform() string { + if h == nil || h.Platform == nil { + return "" + } + return *h.Platform +} + +// GetPublicIPEnabled returns the PublicIPEnabled field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetPublicIPEnabled() bool { + if h == nil || h.PublicIPEnabled == nil { + return false + } + return *h.PublicIPEnabled +} + +// GetRunnerGroupID returns the RunnerGroupID field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetRunnerGroupID() int64 { + if h == nil || h.RunnerGroupID == nil { + return 0 + } + return *h.RunnerGroupID +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (h *HostedRunner) GetStatus() string { + if h == nil || h.Status == nil { + return "" + } + return *h.Status +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (h *HostedRunnerImageDetail) GetDisplayName() string { + if h == nil || h.DisplayName == nil { + return "" + } + return *h.DisplayName +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HostedRunnerImageDetail) GetID() string { + if h == nil || h.ID == nil { + return "" + } + return *h.ID +} + +// GetSizeGB returns the SizeGB field if it's non-nil, zero value otherwise. +func (h *HostedRunnerImageDetail) GetSizeGB() int64 { + if h == nil || h.SizeGB == nil { + return 0 + } + return *h.SizeGB +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (h *HostedRunnerImageDetail) GetSource() string { + if h == nil || h.Source == nil { + return "" + } + return *h.Source +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (h *HostedRunnerImageDetail) GetVersion() string { + if h == nil || h.Version == nil { + return "" + } + return *h.Version +} + +// GetPublicIPs returns the PublicIPs field. +func (h *HostedRunnerPublicIPLimits) GetPublicIPs() *PublicIPUsage { + if h == nil { + return nil + } + return h.PublicIPs +} + // GetGroupDescription returns the GroupDescription field if it's non-nil, zero value otherwise. func (i *IDPGroup) GetGroupDescription() string { if i == nil || i.GroupDescription == nil { @@ -10534,6 +11822,14 @@ func (i *Issue) GetTitle() string { return *i.Title } +// GetType returns the Type field. +func (i *Issue) GetType() *IssueType { + if i == nil { + return nil + } + return i.Type +} + // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (i *Issue) GetUpdatedAt() Timestamp { if i == nil || i.UpdatedAt == nil { @@ -11203,31 +12499,87 @@ func (i *IssuesSearchResult) GetTotal() int { if i == nil || i.Total == nil { return 0 } - return *i.Total + return *i.Total +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetClosedIssues() int { + if i == nil || i.ClosedIssues == nil { + return 0 + } + return *i.ClosedIssues +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetOpenIssues() int { + if i == nil || i.OpenIssues == nil { + return 0 + } + return *i.OpenIssues +} + +// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetTotalIssues() int { + if i == nil || i.TotalIssues == nil { + return 0 + } + return *i.TotalIssues +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (i *IssueType) GetColor() string { + if i == nil || i.Color == nil { + return "" + } + return *i.Color +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueType) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (i *IssueType) GetDescription() string { + if i == nil || i.Description == nil { + return "" + } + return *i.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueType) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID } -// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. -func (i *IssueStats) GetClosedIssues() int { - if i == nil || i.ClosedIssues == nil { - return 0 +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (i *IssueType) GetName() string { + if i == nil || i.Name == nil { + return "" } - return *i.ClosedIssues + return *i.Name } -// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. -func (i *IssueStats) GetOpenIssues() int { - if i == nil || i.OpenIssues == nil { - return 0 +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *IssueType) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" } - return *i.OpenIssues + return *i.NodeID } -// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. -func (i *IssueStats) GetTotalIssues() int { - if i == nil || i.TotalIssues == nil { - return 0 +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueType) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} } - return *i.TotalIssues + return *i.UpdatedAt } // GetEncodedJITConfig returns the EncodedJITConfig field if it's non-nil, zero value otherwise. @@ -11638,6 +12990,158 @@ func (l *License) GetURL() string { return *l.URL } +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (l *LicenseCheck) GetStatus() string { + if l == nil || l.Status == nil { + return "" + } + return *l.Status +} + +// GetAdvancedSecurityEnabled returns the AdvancedSecurityEnabled field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetAdvancedSecurityEnabled() bool { + if l == nil || l.AdvancedSecurityEnabled == nil { + return false + } + return *l.AdvancedSecurityEnabled +} + +// GetAdvancedSecuritySeats returns the AdvancedSecuritySeats field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetAdvancedSecuritySeats() int { + if l == nil || l.AdvancedSecuritySeats == nil { + return 0 + } + return *l.AdvancedSecuritySeats +} + +// GetClusterSupport returns the ClusterSupport field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetClusterSupport() bool { + if l == nil || l.ClusterSupport == nil { + return false + } + return *l.ClusterSupport +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetCompany() string { + if l == nil || l.Company == nil { + return "" + } + return *l.Company +} + +// GetCroquetSupport returns the CroquetSupport field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetCroquetSupport() bool { + if l == nil || l.CroquetSupport == nil { + return false + } + return *l.CroquetSupport +} + +// GetCustomTerms returns the CustomTerms field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetCustomTerms() bool { + if l == nil || l.CustomTerms == nil { + return false + } + return *l.CustomTerms +} + +// GetEvaluation returns the Evaluation field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetEvaluation() bool { + if l == nil || l.Evaluation == nil { + return false + } + return *l.Evaluation +} + +// GetExpireAt returns the ExpireAt field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetExpireAt() Timestamp { + if l == nil || l.ExpireAt == nil { + return Timestamp{} + } + return *l.ExpireAt +} + +// GetInsightsEnabled returns the InsightsEnabled field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetInsightsEnabled() bool { + if l == nil || l.InsightsEnabled == nil { + return false + } + return *l.InsightsEnabled +} + +// GetInsightsExpireAt returns the InsightsExpireAt field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetInsightsExpireAt() Timestamp { + if l == nil || l.InsightsExpireAt == nil { + return Timestamp{} + } + return *l.InsightsExpireAt +} + +// GetLearningLabEvaluationExpires returns the LearningLabEvaluationExpires field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetLearningLabEvaluationExpires() Timestamp { + if l == nil || l.LearningLabEvaluationExpires == nil { + return Timestamp{} + } + return *l.LearningLabEvaluationExpires +} + +// GetLearningLabSeats returns the LearningLabSeats field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetLearningLabSeats() int { + if l == nil || l.LearningLabSeats == nil { + return 0 + } + return *l.LearningLabSeats +} + +// GetPerpetual returns the Perpetual field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetPerpetual() bool { + if l == nil || l.Perpetual == nil { + return false + } + return *l.Perpetual +} + +// GetReferenceNumber returns the ReferenceNumber field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetReferenceNumber() string { + if l == nil || l.ReferenceNumber == nil { + return "" + } + return *l.ReferenceNumber +} + +// GetSeats returns the Seats field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetSeats() int { + if l == nil || l.Seats == nil { + return 0 + } + return *l.Seats +} + +// GetSSHAllowed returns the SSHAllowed field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetSSHAllowed() bool { + if l == nil || l.SSHAllowed == nil { + return false + } + return *l.SSHAllowed +} + +// GetSupportKey returns the SupportKey field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetSupportKey() string { + if l == nil || l.SupportKey == nil { + return "" + } + return *l.SupportKey +} + +// GetUnlimitedSeating returns the UnlimitedSeating field if it's non-nil, zero value otherwise. +func (l *LicenseStatus) GetUnlimitedSeating() bool { + if l == nil || l.UnlimitedSeating == nil { + return false + } + return *l.UnlimitedSeating +} + // GetFrom returns the From field if it's non-nil, zero value otherwise. func (l *LinearHistoryRequirementEnforcementLevelChanges) GetFrom() string { if l == nil || l.From == nil { @@ -11982,6 +13486,102 @@ func (l *LockBranch) GetEnabled() bool { return *l.Enabled } +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (m *MaintenanceOperationStatus) GetHostname() string { + if m == nil || m.Hostname == nil { + return "" + } + return *m.Hostname +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (m *MaintenanceOperationStatus) GetMessage() string { + if m == nil || m.Message == nil { + return "" + } + return *m.Message +} + +// GetUUID returns the UUID field if it's non-nil, zero value otherwise. +func (m *MaintenanceOperationStatus) GetUUID() string { + if m == nil || m.UUID == nil { + return "" + } + return *m.UUID +} + +// GetMaintenanceModeMessage returns the MaintenanceModeMessage field if it's non-nil, zero value otherwise. +func (m *MaintenanceOptions) GetMaintenanceModeMessage() string { + if m == nil || m.MaintenanceModeMessage == nil { + return "" + } + return *m.MaintenanceModeMessage +} + +// GetUUID returns the UUID field if it's non-nil, zero value otherwise. +func (m *MaintenanceOptions) GetUUID() string { + if m == nil || m.UUID == nil { + return "" + } + return *m.UUID +} + +// GetWhen returns the When field if it's non-nil, zero value otherwise. +func (m *MaintenanceOptions) GetWhen() string { + if m == nil || m.When == nil { + return "" + } + return *m.When +} + +// GetCanUnsetMaintenance returns the CanUnsetMaintenance field if it's non-nil, zero value otherwise. +func (m *MaintenanceStatus) GetCanUnsetMaintenance() bool { + if m == nil || m.CanUnsetMaintenance == nil { + return false + } + return *m.CanUnsetMaintenance +} + +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (m *MaintenanceStatus) GetHostname() string { + if m == nil || m.Hostname == nil { + return "" + } + return *m.Hostname +} + +// GetMaintenanceModeMessage returns the MaintenanceModeMessage field if it's non-nil, zero value otherwise. +func (m *MaintenanceStatus) GetMaintenanceModeMessage() string { + if m == nil || m.MaintenanceModeMessage == nil { + return "" + } + return *m.MaintenanceModeMessage +} + +// GetScheduledTime returns the ScheduledTime field if it's non-nil, zero value otherwise. +func (m *MaintenanceStatus) GetScheduledTime() Timestamp { + if m == nil || m.ScheduledTime == nil { + return Timestamp{} + } + return *m.ScheduledTime +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (m *MaintenanceStatus) GetStatus() string { + if m == nil || m.Status == nil { + return "" + } + return *m.Status +} + +// GetUUID returns the UUID field if it's non-nil, zero value otherwise. +func (m *MaintenanceStatus) GetUUID() string { + if m == nil || m.UUID == nil { + return "" + } + return *m.UUID +} + // GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. func (m *MarketplacePendingChange) GetEffectiveDate() Timestamp { if m == nil || m.EffectiveDate == nil { @@ -12638,6 +14238,14 @@ func (m *MergeGroupEvent) GetOrg() *Organization { return m.Org } +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (m *MergeGroupEvent) GetReason() string { + if m == nil || m.Reason == nil { + return "" + } + return *m.Reason +} + // GetRepo returns the Repo field. func (m *MergeGroupEvent) GetRepo() *Repository { if m == nil { @@ -13110,6 +14718,102 @@ func (m *MostRecentInstance) GetState() string { return *m.State } +// GetComputeService returns the ComputeService field. +func (n *NetworkConfiguration) GetComputeService() *ComputeService { + if n == nil { + return nil + } + return n.ComputeService +} + +// GetCreatedOn returns the CreatedOn field if it's non-nil, zero value otherwise. +func (n *NetworkConfiguration) GetCreatedOn() Timestamp { + if n == nil || n.CreatedOn == nil { + return Timestamp{} + } + return *n.CreatedOn +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (n *NetworkConfiguration) GetID() string { + if n == nil || n.ID == nil { + return "" + } + return *n.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (n *NetworkConfiguration) GetName() string { + if n == nil || n.Name == nil { + return "" + } + return *n.Name +} + +// GetComputeService returns the ComputeService field. +func (n *NetworkConfigurationRequest) GetComputeService() *ComputeService { + if n == nil { + return nil + } + return n.ComputeService +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (n *NetworkConfigurationRequest) GetName() string { + if n == nil || n.Name == nil { + return "" + } + return *n.Name +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (n *NetworkConfigurations) GetTotalCount() int64 { + if n == nil || n.TotalCount == nil { + return 0 + } + return *n.TotalCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (n *NetworkSettingsResource) GetID() string { + if n == nil || n.ID == nil { + return "" + } + return *n.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (n *NetworkSettingsResource) GetName() string { + if n == nil || n.Name == nil { + return "" + } + return *n.Name +} + +// GetNetworkConfigurationID returns the NetworkConfigurationID field if it's non-nil, zero value otherwise. +func (n *NetworkSettingsResource) GetNetworkConfigurationID() string { + if n == nil || n.NetworkConfigurationID == nil { + return "" + } + return *n.NetworkConfigurationID +} + +// GetRegion returns the Region field if it's non-nil, zero value otherwise. +func (n *NetworkSettingsResource) GetRegion() string { + if n == nil || n.Region == nil { + return "" + } + return *n.Region +} + +// GetSubnetID returns the SubnetID field if it's non-nil, zero value otherwise. +func (n *NetworkSettingsResource) GetSubnetID() string { + if n == nil || n.SubnetID == nil { + return "" + } + return *n.SubnetID +} + // GetBase returns the Base field if it's non-nil, zero value otherwise. func (n *NewPullRequest) GetBase() string { if n == nil || n.Base == nil { @@ -13203,23 +14907,79 @@ func (n *NewTeam) GetParentTeamID() int64 { if n == nil || n.ParentTeamID == nil { return 0 } - return *n.ParentTeamID + return *n.ParentTeamID +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPermission() string { + if n == nil || n.Permission == nil { + return "" + } + return *n.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPrivacy() string { + if n == nil || n.Privacy == nil { + return "" + } + return *n.Privacy +} + +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (n *NodeDetails) GetHostname() string { + if n == nil || n.Hostname == nil { + return "" + } + return *n.Hostname +} + +// GetUUID returns the UUID field if it's non-nil, zero value otherwise. +func (n *NodeDetails) GetUUID() string { + if n == nil || n.UUID == nil { + return "" + } + return *n.UUID +} + +// GetTopology returns the Topology field if it's non-nil, zero value otherwise. +func (n *NodeMetadataStatus) GetTopology() string { + if n == nil || n.Topology == nil { + return "" + } + return *n.Topology +} + +// GetClusterRoles returns the ClusterRoles field if it's non-nil, zero value otherwise. +func (n *NodeQueryOptions) GetClusterRoles() string { + if n == nil || n.ClusterRoles == nil { + return "" + } + return *n.ClusterRoles } -// GetPermission returns the Permission field if it's non-nil, zero value otherwise. -func (n *NewTeam) GetPermission() string { - if n == nil || n.Permission == nil { +// GetUUID returns the UUID field if it's non-nil, zero value otherwise. +func (n *NodeQueryOptions) GetUUID() string { + if n == nil || n.UUID == nil { return "" } - return *n.Permission + return *n.UUID } -// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. -func (n *NewTeam) GetPrivacy() string { - if n == nil || n.Privacy == nil { +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (n *NodeReleaseVersion) GetHostname() string { + if n == nil || n.Hostname == nil { return "" } - return *n.Privacy + return *n.Hostname +} + +// GetVersion returns the Version field. +func (n *NodeReleaseVersion) GetVersion() *ReleaseVersion { + if n == nil { + return nil + } + return n.Version } // GetID returns the ID field if it's non-nil, zero value otherwise. @@ -14054,6 +15814,22 @@ func (p *Package) GetCreatedAt() Timestamp { return *p.CreatedAt } +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *Package) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (p *Package) GetEcosystem() string { + if p == nil || p.Ecosystem == nil { + return "" + } + return *p.Ecosystem +} + // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. func (p *Package) GetHTMLURL() string { if p == nil || p.HTMLURL == nil { @@ -14078,6 +15854,14 @@ func (p *Package) GetName() string { return *p.Name } +// GetNamespace returns the Namespace field if it's non-nil, zero value otherwise. +func (p *Package) GetNamespace() string { + if p == nil || p.Namespace == nil { + return "" + } + return *p.Namespace +} + // GetOwner returns the Owner field. func (p *Package) GetOwner() *User { if p == nil { @@ -14110,14 +15894,6 @@ func (p *Package) GetRegistry() *PackageRegistry { return p.Registry } -// GetRepository returns the Repository field. -func (p *Package) GetRepository() *Repository { - if p == nil { - return nil - } - return p.Repository -} - // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. func (p *Package) GetUpdatedAt() Timestamp { if p == nil || p.UpdatedAt == nil { @@ -14163,175 +15939,471 @@ func (p *PackageEvent) GetInstallation() *Installation { if p == nil { return nil } - return p.Installation + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PackageEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPackage returns the Package field. +func (p *PackageEvent) GetPackage() *Package { + if p == nil { + return nil + } + return p.Package +} + +// GetRepo returns the Repo field. +func (p *PackageEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PackageEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetLabels returns the Labels map if it's non-nil, an empty map otherwise. +func (p *PackageEventContainerMetadata) GetLabels() map[string]any { + if p == nil || p.Labels == nil { + return map[string]any{} + } + return p.Labels +} + +// GetManifest returns the Manifest map if it's non-nil, an empty map otherwise. +func (p *PackageEventContainerMetadata) GetManifest() map[string]any { + if p == nil || p.Manifest == nil { + return map[string]any{} + } + return p.Manifest +} + +// GetTag returns the Tag field. +func (p *PackageEventContainerMetadata) GetTag() *PackageEventContainerMetadataTag { + if p == nil { + return nil + } + return p.Tag +} + +// GetDigest returns the Digest field if it's non-nil, zero value otherwise. +func (p *PackageEventContainerMetadataTag) GetDigest() string { + if p == nil || p.Digest == nil { + return "" + } + return *p.Digest +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageEventContainerMetadataTag) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetAuthor returns the Author field. +func (p *PackageFile) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetContentType() string { + if p == nil || p.ContentType == nil { + return "" + } + return *p.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetDownloadURL() string { + if p == nil || p.DownloadURL == nil { + return "" + } + return *p.DownloadURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetMD5 returns the MD5 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetMD5() string { + if p == nil || p.MD5 == nil { + return "" + } + return *p.MD5 +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetSHA1 returns the SHA1 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA1() string { + if p == nil || p.SHA1 == nil { + return "" + } + return *p.SHA1 +} + +// GetSHA256 returns the SHA256 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA256() string { + if p == nil || p.SHA256 == nil { + return "" + } + return *p.SHA256 +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSize() int64 { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetVisibility() string { + if p == nil || p.Visibility == nil { + return "" + } + return *p.Visibility +} + +// GetContainer returns the Container field. +func (p *PackageMetadata) GetContainer() *PackageContainerMetadata { + if p == nil { + return nil + } + return p.Container +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageMetadata) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetAuthor returns the Author map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetAuthor() map[string]string { + if p == nil || p.Author == nil { + return map[string]string{} + } + return p.Author +} + +// GetBin returns the Bin map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetBin() map[string]any { + if p == nil || p.Bin == nil { + return map[string]any{} + } + return p.Bin +} + +// GetBugs returns the Bugs map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetBugs() map[string]string { + if p == nil || p.Bugs == nil { + return map[string]string{} + } + return p.Bugs +} + +// GetCommitOID returns the CommitOID field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetCommitOID() string { + if p == nil || p.CommitOID == nil { + return "" + } + return *p.CommitOID +} + +// GetDeletedByID returns the DeletedByID field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetDeletedByID() int64 { + if p == nil || p.DeletedByID == nil { + return 0 + } + return *p.DeletedByID +} + +// GetDependencies returns the Dependencies map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetDependencies() map[string]string { + if p == nil || p.Dependencies == nil { + return map[string]string{} + } + return p.Dependencies } -// GetOrg returns the Org field. -func (p *PackageEvent) GetOrg() *Organization { - if p == nil { - return nil +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetDescription() string { + if p == nil || p.Description == nil { + return "" } - return p.Org + return *p.Description } -// GetPackage returns the Package field. -func (p *PackageEvent) GetPackage() *Package { - if p == nil { - return nil +// GetDevDependencies returns the DevDependencies map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetDevDependencies() map[string]string { + if p == nil || p.DevDependencies == nil { + return map[string]string{} } - return p.Package + return p.DevDependencies } -// GetRepo returns the Repo field. -func (p *PackageEvent) GetRepo() *Repository { - if p == nil { - return nil +// GetDirectories returns the Directories map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetDirectories() map[string]string { + if p == nil || p.Directories == nil { + return map[string]string{} } - return p.Repo + return p.Directories } -// GetSender returns the Sender field. -func (p *PackageEvent) GetSender() *User { - if p == nil { - return nil +// GetDist returns the Dist map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetDist() map[string]string { + if p == nil || p.Dist == nil { + return map[string]string{} } - return p.Sender + return p.Dist } -// GetAuthor returns the Author field. -func (p *PackageFile) GetAuthor() *User { - if p == nil { - return nil +// GetEngines returns the Engines map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetEngines() map[string]string { + if p == nil || p.Engines == nil { + return map[string]string{} } - return p.Author + return p.Engines } -// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetContentType() string { - if p == nil || p.ContentType == nil { +// GetGitHead returns the GitHead field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetGitHead() string { + if p == nil || p.GitHead == nil { return "" } - return *p.ContentType + return *p.GitHead } -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetCreatedAt() Timestamp { - if p == nil || p.CreatedAt == nil { - return Timestamp{} +// GetHasShrinkwrap returns the HasShrinkwrap field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetHasShrinkwrap() bool { + if p == nil || p.HasShrinkwrap == nil { + return false } - return *p.CreatedAt + return *p.HasShrinkwrap } -// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetDownloadURL() string { - if p == nil || p.DownloadURL == nil { +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetHomepage() string { + if p == nil || p.Homepage == nil { return "" } - return *p.DownloadURL + return *p.Homepage } // GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetID() int64 { +func (p *PackageNPMMetadata) GetID() string { if p == nil || p.ID == nil { - return 0 + return "" } return *p.ID } -// GetMD5 returns the MD5 field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetMD5() string { - if p == nil || p.MD5 == nil { +// GetInstallationCommand returns the InstallationCommand field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetInstallationCommand() string { + if p == nil || p.InstallationCommand == nil { return "" } - return *p.MD5 + return *p.InstallationCommand +} + +// GetLicense returns the License field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetLicense() string { + if p == nil || p.License == nil { + return "" + } + return *p.License +} + +// GetMain returns the Main field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetMain() string { + if p == nil || p.Main == nil { + return "" + } + return *p.Main +} + +// GetMan returns the Man map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetMan() map[string]any { + if p == nil || p.Man == nil { + return map[string]any{} + } + return p.Man } // GetName returns the Name field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetName() string { +func (p *PackageNPMMetadata) GetName() string { if p == nil || p.Name == nil { return "" } return *p.Name } -// GetSHA1 returns the SHA1 field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetSHA1() string { - if p == nil || p.SHA1 == nil { +// GetNodeVersion returns the NodeVersion field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetNodeVersion() string { + if p == nil || p.NodeVersion == nil { return "" } - return *p.SHA1 + return *p.NodeVersion } -// GetSHA256 returns the SHA256 field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetSHA256() string { - if p == nil || p.SHA256 == nil { +// GetNPMUser returns the NPMUser field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetNPMUser() string { + if p == nil || p.NPMUser == nil { return "" } - return *p.SHA256 + return *p.NPMUser } -// GetSize returns the Size field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetSize() int64 { - if p == nil || p.Size == nil { - return 0 +// GetNPMVersion returns the NPMVersion field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetNPMVersion() string { + if p == nil || p.NPMVersion == nil { + return "" } - return *p.Size + return *p.NPMVersion } -// GetState returns the State field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetState() string { - if p == nil || p.State == nil { - return "" +// GetOptionalDependencies returns the OptionalDependencies map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetOptionalDependencies() map[string]string { + if p == nil || p.OptionalDependencies == nil { + return map[string]string{} } - return *p.State + return p.OptionalDependencies } -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *PackageFile) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} +// GetPeerDependencies returns the PeerDependencies map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetPeerDependencies() map[string]string { + if p == nil || p.PeerDependencies == nil { + return map[string]string{} } - return *p.UpdatedAt + return p.PeerDependencies } -// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. -func (p *PackageListOptions) GetPackageType() string { - if p == nil || p.PackageType == nil { - return "" +// GetPublishedViaActions returns the PublishedViaActions field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetPublishedViaActions() bool { + if p == nil || p.PublishedViaActions == nil { + return false } - return *p.PackageType + return *p.PublishedViaActions } -// GetState returns the State field if it's non-nil, zero value otherwise. -func (p *PackageListOptions) GetState() string { - if p == nil || p.State == nil { +// GetReadme returns the Readme field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetReadme() string { + if p == nil || p.Readme == nil { return "" } - return *p.State + return *p.Readme } -// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. -func (p *PackageListOptions) GetVisibility() string { - if p == nil || p.Visibility == nil { - return "" +// GetReleaseID returns the ReleaseID field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetReleaseID() int64 { + if p == nil || p.ReleaseID == nil { + return 0 } - return *p.Visibility + return *p.ReleaseID } -// GetContainer returns the Container field. -func (p *PackageMetadata) GetContainer() *PackageContainerMetadata { - if p == nil { - return nil +// GetRepository returns the Repository map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetRepository() map[string]string { + if p == nil || p.Repository == nil { + return map[string]string{} } - return p.Container + return p.Repository } -// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. -func (p *PackageMetadata) GetPackageType() string { - if p == nil || p.PackageType == nil { +// GetScripts returns the Scripts map if it's non-nil, an empty map otherwise. +func (p *PackageNPMMetadata) GetScripts() map[string]any { + if p == nil || p.Scripts == nil { + return map[string]any{} + } + return p.Scripts +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (p *PackageNPMMetadata) GetVersion() string { + if p == nil || p.Version == nil { return "" } - return *p.PackageType + return *p.Version +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageNugetMetadata) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name } // GetAboutURL returns the AboutURL field if it's non-nil, zero value otherwise. @@ -14470,14 +16542,6 @@ func (p *PackageVersion) GetAuthor() *User { return p.Author } -// GetBody returns the Body field if it's non-nil, zero value otherwise. -func (p *PackageVersion) GetBody() string { - if p == nil || p.Body == nil { - return "" - } - return *p.Body -} - // GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetBodyHTML() string { if p == nil || p.BodyHTML == nil { @@ -14486,6 +16550,14 @@ func (p *PackageVersion) GetBodyHTML() string { return *p.BodyHTML } +// GetContainerMetadata returns the ContainerMetadata field. +func (p *PackageVersion) GetContainerMetadata() *PackageEventContainerMetadata { + if p == nil { + return nil + } + return p.ContainerMetadata +} + // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetCreatedAt() Timestamp { if p == nil || p.CreatedAt == nil { @@ -14494,6 +16566,22 @@ func (p *PackageVersion) GetCreatedAt() Timestamp { return *p.CreatedAt } +// GetDeletedAt returns the DeletedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetDeletedAt() Timestamp { + if p == nil || p.DeletedAt == nil { + return Timestamp{} + } + return *p.DeletedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + // GetDraft returns the Draft field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetDraft() bool { if p == nil || p.Draft == nil { @@ -14526,6 +16614,14 @@ func (p *PackageVersion) GetInstallationCommand() string { return *p.InstallationCommand } +// GetLicense returns the License field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetLicense() string { + if p == nil || p.License == nil { + return "" + } + return *p.License +} + // GetManifest returns the Manifest field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetManifest() string { if p == nil || p.Manifest == nil { @@ -14534,14 +16630,6 @@ func (p *PackageVersion) GetManifest() string { return *p.Manifest } -// GetMetadata returns the Metadata field. -func (p *PackageVersion) GetMetadata() *PackageMetadata { - if p == nil { - return nil - } - return p.Metadata -} - // GetName returns the Name field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetName() string { if p == nil || p.Name == nil { @@ -14550,6 +16638,14 @@ func (p *PackageVersion) GetName() string { return *p.Name } +// GetNPMMetadata returns the NPMMetadata field. +func (p *PackageVersion) GetNPMMetadata() *PackageNPMMetadata { + if p == nil { + return nil + } + return p.NPMMetadata +} + // GetPackageHTMLURL returns the PackageHTMLURL field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetPackageHTMLURL() string { if p == nil || p.PackageHTMLURL == nil { @@ -14558,6 +16654,14 @@ func (p *PackageVersion) GetPackageHTMLURL() string { return *p.PackageHTMLURL } +// GetPackageURL returns the PackageURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetPackageURL() string { + if p == nil || p.PackageURL == nil { + return "" + } + return *p.PackageURL +} + // GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetPrerelease() bool { if p == nil || p.Prerelease == nil { @@ -14574,60 +16678,148 @@ func (p *PackageVersion) GetRelease() *PackageRelease { return p.Release } +// GetRubyMetadata returns the RubyMetadata map if it's non-nil, an empty map otherwise. +func (p *PackageVersion) GetRubyMetadata() map[string]any { + if p == nil || p.RubyMetadata == nil { + return map[string]any{} + } + return p.RubyMetadata +} + +// GetSourceURL returns the SourceURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetSourceURL() string { + if p == nil || p.SourceURL == nil { + return "" + } + return *p.SourceURL +} + // GetSummary returns the Summary field if it's non-nil, zero value otherwise. func (p *PackageVersion) GetSummary() string { if p == nil || p.Summary == nil { return "" } - return *p.Summary + return *p.Summary +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTagName() string { + if p == nil || p.TagName == nil { + return "" + } + return *p.TagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetCommitish() string { + if p == nil || p.TargetCommitish == nil { + return "" + } + return *p.TargetCommitish +} + +// GetTargetOID returns the TargetOID field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetOID() string { + if p == nil || p.TargetOID == nil { + return "" + } + return *p.TargetOID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetVersion() string { + if p == nil || p.Version == nil { + return "" + } + return *p.Version +} + +// GetInfo returns the Info field. +func (p *PackageVersionBody) GetInfo() *PackageVersionBodyInfo { + if p == nil { + return nil + } + return p.Info +} + +// GetRepo returns the Repo field. +func (p *PackageVersionBody) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetCollection returns the Collection field if it's non-nil, zero value otherwise. +func (p *PackageVersionBodyInfo) GetCollection() bool { + if p == nil || p.Collection == nil { + return false + } + return *p.Collection } -// GetTagName returns the TagName field if it's non-nil, zero value otherwise. -func (p *PackageVersion) GetTagName() string { - if p == nil || p.TagName == nil { - return "" +// GetMode returns the Mode field if it's non-nil, zero value otherwise. +func (p *PackageVersionBodyInfo) GetMode() int64 { + if p == nil || p.Mode == nil { + return 0 } - return *p.TagName + return *p.Mode } -// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. -func (p *PackageVersion) GetTargetCommitish() string { - if p == nil || p.TargetCommitish == nil { +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageVersionBodyInfo) GetName() string { + if p == nil || p.Name == nil { return "" } - return *p.TargetCommitish + return *p.Name } -// GetTargetOID returns the TargetOID field if it's non-nil, zero value otherwise. -func (p *PackageVersion) GetTargetOID() string { - if p == nil || p.TargetOID == nil { +// GetOID returns the OID field if it's non-nil, zero value otherwise. +func (p *PackageVersionBodyInfo) GetOID() string { + if p == nil || p.OID == nil { return "" } - return *p.TargetOID + return *p.OID } -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *PackageVersion) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PackageVersionBodyInfo) GetPath() string { + if p == nil || p.Path == nil { + return "" } - return *p.UpdatedAt + return *p.Path } -// GetURL returns the URL field if it's non-nil, zero value otherwise. -func (p *PackageVersion) GetURL() string { - if p == nil || p.URL == nil { - return "" +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PackageVersionBodyInfo) GetSize() int64 { + if p == nil || p.Size == nil { + return 0 } - return *p.URL + return *p.Size } -// GetVersion returns the Version field if it's non-nil, zero value otherwise. -func (p *PackageVersion) GetVersion() string { - if p == nil || p.Version == nil { +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (p *PackageVersionBodyInfo) GetType() string { + if p == nil || p.Type == nil { return "" } - return *p.Version + return *p.Type } // GetAction returns the Action field if it's non-nil, zero value otherwise. @@ -15206,6 +17398,54 @@ func (p *PagesUpdate) GetSource() *PagesSource { return p.Source } +// GetBuildType returns the BuildType field if it's non-nil, zero value otherwise. +func (p *PagesUpdateWithoutCNAME) GetBuildType() string { + if p == nil || p.BuildType == nil { + return "" + } + return *p.BuildType +} + +// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise. +func (p *PagesUpdateWithoutCNAME) GetHTTPSEnforced() bool { + if p == nil || p.HTTPSEnforced == nil { + return false + } + return *p.HTTPSEnforced +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *PagesUpdateWithoutCNAME) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetSource returns the Source field. +func (p *PagesUpdateWithoutCNAME) GetSource() *PagesSource { + if p == nil { + return nil + } + return p.Source +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PatternRuleParameters) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNegate returns the Negate field if it's non-nil, zero value otherwise. +func (p *PatternRuleParameters) GetNegate() bool { + if p == nil || p.Negate == nil { + return false + } + return *p.Negate +} + // GetCurrentUserCanApprove returns the CurrentUserCanApprove field if it's non-nil, zero value otherwise. func (p *PendingDeployment) GetCurrentUserCanApprove() bool { if p == nil || p.CurrentUserCanApprove == nil { @@ -15342,6 +17582,14 @@ func (p *PersonalAccessToken) GetTokenExpiresAt() Timestamp { return *p.TokenExpiresAt } +// GetTokenID returns the TokenID field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenID() int64 { + if p == nil || p.TokenID == nil { + return 0 + } + return *p.TokenID +} + // GetTokenLastUsedAt returns the TokenLastUsedAt field if it's non-nil, zero value otherwise. func (p *PersonalAccessToken) GetTokenLastUsedAt() Timestamp { if p == nil || p.TokenLastUsedAt == nil { @@ -15350,6 +17598,14 @@ func (p *PersonalAccessToken) GetTokenLastUsedAt() Timestamp { return *p.TokenLastUsedAt } +// GetTokenName returns the TokenName field if it's non-nil, zero value otherwise. +func (p *PersonalAccessToken) GetTokenName() string { + if p == nil || p.TokenName == nil { + return "" + } + return *p.TokenName +} + // GetOrg returns the Org map if it's non-nil, an empty map otherwise. func (p *PersonalAccessTokenPermissions) GetOrg() map[string]string { if p == nil || p.Org == nil { @@ -17750,6 +20006,14 @@ func (p *PullRequestReviewThreadEvent) GetThread() *PullRequestThread { return p.Thread } +// GetAutomaticCopilotCodeReviewEnabled returns the AutomaticCopilotCodeReviewEnabled field if it's non-nil, zero value otherwise. +func (p *PullRequestRuleParameters) GetAutomaticCopilotCodeReviewEnabled() bool { + if p == nil || p.AutomaticCopilotCodeReviewEnabled == nil { + return false + } + return *p.AutomaticCopilotCodeReviewEnabled +} + // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *PullRequestTargetEvent) GetAction() string { if p == nil || p.Action == nil { @@ -17886,12 +20150,12 @@ func (p *PullRequestThread) GetNodeID() string { return *p.NodeID } -// GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise. -func (p *PullStats) GetMergablePulls() int { - if p == nil || p.MergablePulls == nil { +// GetMergeablePulls returns the MergeablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergeablePulls() int { + if p == nil || p.MergeablePulls == nil { return 0 } - return *p.MergablePulls + return *p.MergeablePulls } // GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise. @@ -17910,12 +20174,12 @@ func (p *PullStats) GetTotalPulls() int { return *p.TotalPulls } -// GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise. -func (p *PullStats) GetUnmergablePulls() int { - if p == nil || p.UnmergablePulls == nil { +// GetUnmergeablePulls returns the UnmergeablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetUnmergeablePulls() int { + if p == nil || p.UnmergeablePulls == nil { return 0 } - return *p.UnmergablePulls + return *p.UnmergeablePulls } // GetCommits returns the Commits field if it's non-nil, zero value otherwise. @@ -18502,6 +20766,14 @@ func (r *Reaction) GetContent() string { return *r.Content } +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *Reaction) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + // GetID returns the ID field if it's non-nil, zero value otherwise. func (r *Reaction) GetID() int64 { if r == nil || r.ID == nil { @@ -18830,6 +21102,38 @@ func (r *ReleaseEvent) GetSender() *User { return r.Sender } +// GetBuildDate returns the BuildDate field if it's non-nil, zero value otherwise. +func (r *ReleaseVersion) GetBuildDate() string { + if r == nil || r.BuildDate == nil { + return "" + } + return *r.BuildDate +} + +// GetBuildID returns the BuildID field if it's non-nil, zero value otherwise. +func (r *ReleaseVersion) GetBuildID() string { + if r == nil || r.BuildID == nil { + return "" + } + return *r.BuildID +} + +// GetPlatform returns the Platform field if it's non-nil, zero value otherwise. +func (r *ReleaseVersion) GetPlatform() string { + if r == nil || r.Platform == nil { + return "" + } + return *r.Platform +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (r *ReleaseVersion) GetVersion() string { + if r == nil || r.Version == nil { + return "" + } + return *r.Version +} + // GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. func (r *RemoveToken) GetExpiresAt() Timestamp { if r == nil || r.ExpiresAt == nil { @@ -20806,12 +23110,12 @@ func (r *RepositoryRelease) GetZipballURL() string { return *r.ZipballURL } -// GetParameters returns the Parameters field if it's non-nil, zero value otherwise. -func (r *RepositoryRule) GetParameters() json.RawMessage { - if r == nil || r.Parameters == nil { - return json.RawMessage{} +// GetConditions returns the Conditions field. +func (r *RepositoryRuleset) GetConditions() *RepositoryRulesetConditions { + if r == nil { + return nil } - return *r.Parameters + return r.Conditions } // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. @@ -20822,16 +23126,24 @@ func (r *RepositoryRuleset) GetCreatedAt() Timestamp { return *r.CreatedAt } -// GetCurrentUserCanBypass returns the CurrentUserCanBypass field if it's non-nil, zero value otherwise. -func (r *RepositoryRuleset) GetCurrentUserCanBypass() string { - if r == nil || r.CurrentUserCanBypass == nil { - return "" +// GetCurrentUserCanBypass returns the CurrentUserCanBypass field. +func (r *RepositoryRuleset) GetCurrentUserCanBypass() *BypassMode { + if r == nil { + return nil + } + return r.CurrentUserCanBypass +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryRuleset) GetID() int64 { + if r == nil || r.ID == nil { + return 0 } - return *r.CurrentUserCanBypass + return *r.ID } // GetLinks returns the Links field. -func (r *RepositoryRuleset) GetLinks() *RepositoryRulesetLink { +func (r *RepositoryRuleset) GetLinks() *RepositoryRulesetLinks { if r == nil { return nil } @@ -20846,20 +23158,28 @@ func (r *RepositoryRuleset) GetNodeID() string { return *r.NodeID } -// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. -func (r *RepositoryRuleset) GetSourceType() string { - if r == nil || r.SourceType == nil { - return "" +// GetRules returns the Rules field. +func (r *RepositoryRuleset) GetRules() *RepositoryRulesetRules { + if r == nil { + return nil } - return *r.SourceType + return r.Rules } -// GetTarget returns the Target field if it's non-nil, zero value otherwise. -func (r *RepositoryRuleset) GetTarget() string { - if r == nil || r.Target == nil { - return "" +// GetSourceType returns the SourceType field. +func (r *RepositoryRuleset) GetSourceType() *RulesetSourceType { + if r == nil { + return nil } - return *r.Target + return r.SourceType +} + +// GetTarget returns the Target field. +func (r *RepositoryRuleset) GetTarget() *RulesetTarget { + if r == nil { + return nil + } + return r.Target } // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. @@ -20870,16 +23190,32 @@ func (r *RepositoryRuleset) GetUpdatedAt() Timestamp { return *r.UpdatedAt } -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetCodeScanningRule) GetParameters() *RuleCodeScanningParameters { +// GetConfiguration returns the Configuration field. +func (r *RepositoryRulesetChangedRule) GetConfiguration() *RepositoryRulesetChangeSource { + if r == nil { + return nil + } + return r.Configuration +} + +// GetPattern returns the Pattern field. +func (r *RepositoryRulesetChangedRule) GetPattern() *RepositoryRulesetChangeSource { + if r == nil { + return nil + } + return r.Pattern +} + +// GetRuleType returns the RuleType field. +func (r *RepositoryRulesetChangedRule) GetRuleType() *RepositoryRulesetChangeSource { if r == nil { return nil } - return r.Parameters + return r.RuleType } // GetConditions returns the Conditions field. -func (r *RepositoryRulesetEditedChanges) GetConditions() *RepositoryRulesetEditedConditions { +func (r *RepositoryRulesetChanges) GetConditions() *RepositoryRulesetChangedConditions { if r == nil { return nil } @@ -20887,7 +23223,7 @@ func (r *RepositoryRulesetEditedChanges) GetConditions() *RepositoryRulesetEdite } // GetEnforcement returns the Enforcement field. -func (r *RepositoryRulesetEditedChanges) GetEnforcement() *RepositoryRulesetEditedSource { +func (r *RepositoryRulesetChanges) GetEnforcement() *RepositoryRulesetChangeSource { if r == nil { return nil } @@ -20895,7 +23231,7 @@ func (r *RepositoryRulesetEditedChanges) GetEnforcement() *RepositoryRulesetEdit } // GetName returns the Name field. -func (r *RepositoryRulesetEditedChanges) GetName() *RepositoryRulesetEditedSource { +func (r *RepositoryRulesetChanges) GetName() *RepositoryRulesetChangeSource { if r == nil { return nil } @@ -20903,59 +23239,67 @@ func (r *RepositoryRulesetEditedChanges) GetName() *RepositoryRulesetEditedSourc } // GetRules returns the Rules field. -func (r *RepositoryRulesetEditedChanges) GetRules() *RepositoryRulesetEditedRules { +func (r *RepositoryRulesetChanges) GetRules() *RepositoryRulesetChangedRules { if r == nil { return nil } return r.Rules } -// GetConfiguration returns the Configuration field. -func (r *RepositoryRulesetEditedRuleChanges) GetConfiguration() *RepositoryRulesetEditedSources { +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetChangeSource) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetOrganizationID returns the OrganizationID field. +func (r *RepositoryRulesetConditions) GetOrganizationID() *RepositoryRulesetOrganizationIDsConditionParameters { if r == nil { return nil } - return r.Configuration + return r.OrganizationID } -// GetPattern returns the Pattern field. -func (r *RepositoryRulesetEditedRuleChanges) GetPattern() *RepositoryRulesetEditedSources { +// GetOrganizationName returns the OrganizationName field. +func (r *RepositoryRulesetConditions) GetOrganizationName() *RepositoryRulesetOrganizationNamesConditionParameters { if r == nil { return nil } - return r.Pattern + return r.OrganizationName } -// GetRuleType returns the RuleType field. -func (r *RepositoryRulesetEditedRuleChanges) GetRuleType() *RepositoryRulesetEditedSources { +// GetRefName returns the RefName field. +func (r *RepositoryRulesetConditions) GetRefName() *RepositoryRulesetRefConditionParameters { if r == nil { return nil } - return r.RuleType + return r.RefName } -// GetFrom returns the From field if it's non-nil, zero value otherwise. -func (r *RepositoryRulesetEditedSource) GetFrom() string { - if r == nil || r.From == nil { - return "" +// GetRepositoryID returns the RepositoryID field. +func (r *RepositoryRulesetConditions) GetRepositoryID() *RepositoryRulesetRepositoryIDsConditionParameters { + if r == nil { + return nil } - return *r.From + return r.RepositoryID } -// GetChanges returns the Changes field. -func (r *RepositoryRulesetEditedUpdatedConditions) GetChanges() *RepositoryRulesetUpdatedConditionsEdited { +// GetRepositoryName returns the RepositoryName field. +func (r *RepositoryRulesetConditions) GetRepositoryName() *RepositoryRulesetRepositoryNamesConditionParameters { if r == nil { return nil } - return r.Changes + return r.RepositoryName } -// GetCondition returns the Condition field. -func (r *RepositoryRulesetEditedUpdatedConditions) GetCondition() *RepositoryRulesetRefCondition { +// GetRepositoryProperty returns the RepositoryProperty field. +func (r *RepositoryRulesetConditions) GetRepositoryProperty() *RepositoryRulesetRepositoryPropertyConditionParameters { if r == nil { return nil } - return r.Condition + return r.RepositoryProperty } // GetAction returns the Action field if it's non-nil, zero value otherwise. @@ -20967,7 +23311,7 @@ func (r *RepositoryRulesetEvent) GetAction() string { } // GetChanges returns the Changes field. -func (r *RepositoryRulesetEvent) GetChanges() *RepositoryRulesetEditedChanges { +func (r *RepositoryRulesetEvent) GetChanges() *RepositoryRulesetChanges { if r == nil { return nil } @@ -21022,24 +23366,16 @@ func (r *RepositoryRulesetEvent) GetSender() *User { return r.Sender } -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetFileExtensionRestrictionRule) GetParameters() *RuleFileExtensionRestrictionParameters { - if r == nil { - return nil - } - return r.Parameters -} - -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetFilePathRestrictionRule) GetParameters() *RuleFileParameters { - if r == nil { - return nil +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetLink) GetHRef() string { + if r == nil || r.HRef == nil { + return "" } - return r.Parameters + return *r.HRef } // GetHTML returns the HTML field. -func (r *RepositoryRulesetLink) GetHTML() *RulesetLink { +func (r *RepositoryRulesetLinks) GetHTML() *RepositoryRulesetLink { if r == nil { return nil } @@ -21047,79 +23383,31 @@ func (r *RepositoryRulesetLink) GetHTML() *RulesetLink { } // GetSelf returns the Self field. -func (r *RepositoryRulesetLink) GetSelf() *RulesetLink { +func (r *RepositoryRulesetLinks) GetSelf() *RepositoryRulesetLink { if r == nil { return nil } return r.Self } -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetMaxFilePathLengthRule) GetParameters() *RuleMaxFilePathLengthParameters { - if r == nil { - return nil - } - return r.Parameters -} - -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetMaxFileSizeRule) GetParameters() *RuleMaxFileSizeParameters { - if r == nil { - return nil - } - return r.Parameters -} - -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetMergeQueueRule) GetParameters() *MergeQueueRuleParameters { - if r == nil { - return nil - } - return r.Parameters -} - -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetPatternRule) GetParameters() *RulePatternParameters { - if r == nil { - return nil - } - return r.Parameters -} - -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetPullRequestRule) GetParameters() *PullRequestRuleParameters { - if r == nil { - return nil - } - return r.Parameters -} - -// GetRefName returns the RefName field. -func (r *RepositoryRulesetRefCondition) GetRefName() *RulesetRefConditionParameters { - if r == nil { - return nil - } - return r.RefName -} - -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetRequiredDeploymentsRule) GetParameters() *RequiredDeploymentEnvironmentsRuleParameters { - if r == nil { - return nil +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetRepositoryNamesConditionParameters) GetProtected() bool { + if r == nil || r.Protected == nil { + return false } - return r.Parameters + return *r.Protected } -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetRequiredStatusChecksRule) GetParameters() *RequiredStatusChecksRuleParameters { - if r == nil { - return nil +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (r *RepositoryRulesetRepositoryPropertyTargetParameters) GetSource() string { + if r == nil || r.Source == nil { + return "" } - return r.Parameters + return *r.Source } // GetBranchNamePattern returns the BranchNamePattern field. -func (r *RepositoryRulesetRule) GetBranchNamePattern() *RepositoryRulesetPatternRule { +func (r *RepositoryRulesetRules) GetBranchNamePattern() *PatternRuleParameters { if r == nil { return nil } @@ -21127,7 +23415,7 @@ func (r *RepositoryRulesetRule) GetBranchNamePattern() *RepositoryRulesetPattern } // GetCodeScanning returns the CodeScanning field. -func (r *RepositoryRulesetRule) GetCodeScanning() *RepositoryRulesetCodeScanningRule { +func (r *RepositoryRulesetRules) GetCodeScanning() *CodeScanningRuleParameters { if r == nil { return nil } @@ -21135,7 +23423,7 @@ func (r *RepositoryRulesetRule) GetCodeScanning() *RepositoryRulesetCodeScanning } // GetCommitAuthorEmailPattern returns the CommitAuthorEmailPattern field. -func (r *RepositoryRulesetRule) GetCommitAuthorEmailPattern() *RepositoryRulesetPatternRule { +func (r *RepositoryRulesetRules) GetCommitAuthorEmailPattern() *PatternRuleParameters { if r == nil { return nil } @@ -21143,7 +23431,7 @@ func (r *RepositoryRulesetRule) GetCommitAuthorEmailPattern() *RepositoryRuleset } // GetCommitMessagePattern returns the CommitMessagePattern field. -func (r *RepositoryRulesetRule) GetCommitMessagePattern() *RepositoryRulesetPatternRule { +func (r *RepositoryRulesetRules) GetCommitMessagePattern() *PatternRuleParameters { if r == nil { return nil } @@ -21151,7 +23439,7 @@ func (r *RepositoryRulesetRule) GetCommitMessagePattern() *RepositoryRulesetPatt } // GetCommitterEmailPattern returns the CommitterEmailPattern field. -func (r *RepositoryRulesetRule) GetCommitterEmailPattern() *RepositoryRulesetPatternRule { +func (r *RepositoryRulesetRules) GetCommitterEmailPattern() *PatternRuleParameters { if r == nil { return nil } @@ -21159,7 +23447,7 @@ func (r *RepositoryRulesetRule) GetCommitterEmailPattern() *RepositoryRulesetPat } // GetCreation returns the Creation field. -func (r *RepositoryRulesetRule) GetCreation() *RepositoryRulesetRuleType { +func (r *RepositoryRulesetRules) GetCreation() *EmptyRuleParameters { if r == nil { return nil } @@ -21167,7 +23455,7 @@ func (r *RepositoryRulesetRule) GetCreation() *RepositoryRulesetRuleType { } // GetDeletion returns the Deletion field. -func (r *RepositoryRulesetRule) GetDeletion() *RepositoryRulesetRuleType { +func (r *RepositoryRulesetRules) GetDeletion() *EmptyRuleParameters { if r == nil { return nil } @@ -21175,7 +23463,7 @@ func (r *RepositoryRulesetRule) GetDeletion() *RepositoryRulesetRuleType { } // GetFileExtensionRestriction returns the FileExtensionRestriction field. -func (r *RepositoryRulesetRule) GetFileExtensionRestriction() *RepositoryRulesetFileExtensionRestrictionRule { +func (r *RepositoryRulesetRules) GetFileExtensionRestriction() *FileExtensionRestrictionRuleParameters { if r == nil { return nil } @@ -21183,7 +23471,7 @@ func (r *RepositoryRulesetRule) GetFileExtensionRestriction() *RepositoryRuleset } // GetFilePathRestriction returns the FilePathRestriction field. -func (r *RepositoryRulesetRule) GetFilePathRestriction() *RepositoryRulesetFilePathRestrictionRule { +func (r *RepositoryRulesetRules) GetFilePathRestriction() *FilePathRestrictionRuleParameters { if r == nil { return nil } @@ -21191,7 +23479,7 @@ func (r *RepositoryRulesetRule) GetFilePathRestriction() *RepositoryRulesetFileP } // GetMaxFilePathLength returns the MaxFilePathLength field. -func (r *RepositoryRulesetRule) GetMaxFilePathLength() *RepositoryRulesetMaxFilePathLengthRule { +func (r *RepositoryRulesetRules) GetMaxFilePathLength() *MaxFilePathLengthRuleParameters { if r == nil { return nil } @@ -21199,7 +23487,7 @@ func (r *RepositoryRulesetRule) GetMaxFilePathLength() *RepositoryRulesetMaxFile } // GetMaxFileSize returns the MaxFileSize field. -func (r *RepositoryRulesetRule) GetMaxFileSize() *RepositoryRulesetMaxFileSizeRule { +func (r *RepositoryRulesetRules) GetMaxFileSize() *MaxFileSizeRuleParameters { if r == nil { return nil } @@ -21207,7 +23495,7 @@ func (r *RepositoryRulesetRule) GetMaxFileSize() *RepositoryRulesetMaxFileSizeRu } // GetMergeQueue returns the MergeQueue field. -func (r *RepositoryRulesetRule) GetMergeQueue() *RepositoryRulesetMergeQueueRule { +func (r *RepositoryRulesetRules) GetMergeQueue() *MergeQueueRuleParameters { if r == nil { return nil } @@ -21215,7 +23503,7 @@ func (r *RepositoryRulesetRule) GetMergeQueue() *RepositoryRulesetMergeQueueRule } // GetNonFastForward returns the NonFastForward field. -func (r *RepositoryRulesetRule) GetNonFastForward() *RepositoryRulesetRuleType { +func (r *RepositoryRulesetRules) GetNonFastForward() *EmptyRuleParameters { if r == nil { return nil } @@ -21223,7 +23511,7 @@ func (r *RepositoryRulesetRule) GetNonFastForward() *RepositoryRulesetRuleType { } // GetPullRequest returns the PullRequest field. -func (r *RepositoryRulesetRule) GetPullRequest() *RepositoryRulesetPullRequestRule { +func (r *RepositoryRulesetRules) GetPullRequest() *PullRequestRuleParameters { if r == nil { return nil } @@ -21231,7 +23519,7 @@ func (r *RepositoryRulesetRule) GetPullRequest() *RepositoryRulesetPullRequestRu } // GetRequiredDeployments returns the RequiredDeployments field. -func (r *RepositoryRulesetRule) GetRequiredDeployments() *RepositoryRulesetRequiredDeploymentsRule { +func (r *RepositoryRulesetRules) GetRequiredDeployments() *RequiredDeploymentsRuleParameters { if r == nil { return nil } @@ -21239,7 +23527,7 @@ func (r *RepositoryRulesetRule) GetRequiredDeployments() *RepositoryRulesetRequi } // GetRequiredLinearHistory returns the RequiredLinearHistory field. -func (r *RepositoryRulesetRule) GetRequiredLinearHistory() *RepositoryRulesetRuleType { +func (r *RepositoryRulesetRules) GetRequiredLinearHistory() *EmptyRuleParameters { if r == nil { return nil } @@ -21247,7 +23535,7 @@ func (r *RepositoryRulesetRule) GetRequiredLinearHistory() *RepositoryRulesetRul } // GetRequiredSignatures returns the RequiredSignatures field. -func (r *RepositoryRulesetRule) GetRequiredSignatures() *RepositoryRulesetRuleType { +func (r *RepositoryRulesetRules) GetRequiredSignatures() *EmptyRuleParameters { if r == nil { return nil } @@ -21255,7 +23543,7 @@ func (r *RepositoryRulesetRule) GetRequiredSignatures() *RepositoryRulesetRuleTy } // GetRequiredStatusChecks returns the RequiredStatusChecks field. -func (r *RepositoryRulesetRule) GetRequiredStatusChecks() *RepositoryRulesetRequiredStatusChecksRule { +func (r *RepositoryRulesetRules) GetRequiredStatusChecks() *RequiredStatusChecksRuleParameters { if r == nil { return nil } @@ -21263,7 +23551,7 @@ func (r *RepositoryRulesetRule) GetRequiredStatusChecks() *RepositoryRulesetRequ } // GetTagNamePattern returns the TagNamePattern field. -func (r *RepositoryRulesetRule) GetTagNamePattern() *RepositoryRulesetPatternRule { +func (r *RepositoryRulesetRules) GetTagNamePattern() *PatternRuleParameters { if r == nil { return nil } @@ -21271,7 +23559,7 @@ func (r *RepositoryRulesetRule) GetTagNamePattern() *RepositoryRulesetPatternRul } // GetUpdate returns the Update field. -func (r *RepositoryRulesetRule) GetUpdate() *RepositoryRulesetUpdateRule { +func (r *RepositoryRulesetRules) GetUpdate() *UpdateRuleParameters { if r == nil { return nil } @@ -21279,7 +23567,7 @@ func (r *RepositoryRulesetRule) GetUpdate() *RepositoryRulesetUpdateRule { } // GetWorkflows returns the Workflows field. -func (r *RepositoryRulesetRule) GetWorkflows() *RepositoryRulesetWorkflowsRule { +func (r *RepositoryRulesetRules) GetWorkflows() *WorkflowsRuleParameters { if r == nil { return nil } @@ -21287,7 +23575,7 @@ func (r *RepositoryRulesetRule) GetWorkflows() *RepositoryRulesetWorkflowsRule { } // GetConditionType returns the ConditionType field. -func (r *RepositoryRulesetUpdatedConditionsEdited) GetConditionType() *RepositoryRulesetEditedSource { +func (r *RepositoryRulesetUpdatedCondition) GetConditionType() *RepositoryRulesetChangeSource { if r == nil { return nil } @@ -21295,7 +23583,7 @@ func (r *RepositoryRulesetUpdatedConditionsEdited) GetConditionType() *Repositor } // GetExclude returns the Exclude field. -func (r *RepositoryRulesetUpdatedConditionsEdited) GetExclude() *RepositoryRulesetEditedSources { +func (r *RepositoryRulesetUpdatedCondition) GetExclude() *RepositoryRulesetChangeSources { if r == nil { return nil } @@ -21303,7 +23591,7 @@ func (r *RepositoryRulesetUpdatedConditionsEdited) GetExclude() *RepositoryRules } // GetInclude returns the Include field. -func (r *RepositoryRulesetUpdatedConditionsEdited) GetInclude() *RepositoryRulesetEditedSources { +func (r *RepositoryRulesetUpdatedCondition) GetInclude() *RepositoryRulesetChangeSources { if r == nil { return nil } @@ -21311,7 +23599,7 @@ func (r *RepositoryRulesetUpdatedConditionsEdited) GetInclude() *RepositoryRules } // GetTarget returns the Target field. -func (r *RepositoryRulesetUpdatedConditionsEdited) GetTarget() *RepositoryRulesetEditedSource { +func (r *RepositoryRulesetUpdatedCondition) GetTarget() *RepositoryRulesetChangeSource { if r == nil { return nil } @@ -21319,35 +23607,35 @@ func (r *RepositoryRulesetUpdatedConditionsEdited) GetTarget() *RepositoryRulese } // GetChanges returns the Changes field. -func (r *RepositoryRulesetUpdatedRules) GetChanges() *RepositoryRulesetEditedRuleChanges { +func (r *RepositoryRulesetUpdatedConditions) GetChanges() *RepositoryRulesetUpdatedCondition { if r == nil { return nil } return r.Changes } -// GetRule returns the Rule field. -func (r *RepositoryRulesetUpdatedRules) GetRule() *RepositoryRulesetRule { +// GetCondition returns the Condition field. +func (r *RepositoryRulesetUpdatedConditions) GetCondition() *RepositoryRulesetConditions { if r == nil { return nil } - return r.Rule + return r.Condition } -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetUpdateRule) GetParameters() *UpdateAllowsFetchAndMergeRuleParameters { +// GetChanges returns the Changes field. +func (r *RepositoryRulesetUpdatedRules) GetChanges() *RepositoryRulesetChangedRule { if r == nil { return nil } - return r.Parameters + return r.Changes } -// GetParameters returns the Parameters field. -func (r *RepositoryRulesetWorkflowsRule) GetParameters() *RequiredWorkflowsRuleParameters { +// GetRule returns the Rule field. +func (r *RepositoryRulesetUpdatedRules) GetRule() *RepositoryRule { if r == nil { return nil } - return r.Parameters + return r.Rule } // GetCommit returns the Commit field. @@ -21838,32 +24126,8 @@ func (r *Rule) GetSeverity() string { return *r.Severity } -// GetRestrictedFilePaths returns the RestrictedFilePaths field if it's non-nil, zero value otherwise. -func (r *RuleFileParameters) GetRestrictedFilePaths() []string { - if r == nil || r.RestrictedFilePaths == nil { - return nil - } - return *r.RestrictedFilePaths -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *RulePatternParameters) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - -// GetNegate returns the Negate field if it's non-nil, zero value otherwise. -func (r *RulePatternParameters) GetNegate() bool { - if r == nil || r.Negate == nil { - return false - } - return *r.Negate -} - // GetIntegrationID returns the IntegrationID field if it's non-nil, zero value otherwise. -func (r *RuleRequiredStatusChecks) GetIntegrationID() int64 { +func (r *RuleStatusCheck) GetIntegrationID() int64 { if r == nil || r.IntegrationID == nil { return 0 } @@ -21871,7 +24135,7 @@ func (r *RuleRequiredStatusChecks) GetIntegrationID() int64 { } // GetRef returns the Ref field if it's non-nil, zero value otherwise. -func (r *RuleRequiredWorkflow) GetRef() string { +func (r *RuleWorkflow) GetRef() string { if r == nil || r.Ref == nil { return "" } @@ -21879,147 +24143,19 @@ func (r *RuleRequiredWorkflow) GetRef() string { } // GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. -func (r *RuleRequiredWorkflow) GetRepositoryID() int64 { +func (r *RuleWorkflow) GetRepositoryID() int64 { if r == nil || r.RepositoryID == nil { return 0 } return *r.RepositoryID } -// GetSha returns the Sha field if it's non-nil, zero value otherwise. -func (r *RuleRequiredWorkflow) GetSha() string { - if r == nil || r.Sha == nil { - return "" - } - return *r.Sha -} - -// GetConditions returns the Conditions field. -func (r *Ruleset) GetConditions() *RulesetConditions { - if r == nil { - return nil - } - return r.Conditions -} - -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (r *Ruleset) GetCreatedAt() Timestamp { - if r == nil || r.CreatedAt == nil { - return Timestamp{} - } - return *r.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (r *Ruleset) GetID() int64 { - if r == nil || r.ID == nil { - return 0 - } - return *r.ID -} - -// GetLinks returns the Links field. -func (r *Ruleset) GetLinks() *RulesetLinks { - if r == nil { - return nil - } - return r.Links -} - -// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. -func (r *Ruleset) GetNodeID() string { - if r == nil || r.NodeID == nil { - return "" - } - return *r.NodeID -} - -// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. -func (r *Ruleset) GetSourceType() string { - if r == nil || r.SourceType == nil { - return "" - } - return *r.SourceType -} - -// GetTarget returns the Target field if it's non-nil, zero value otherwise. -func (r *Ruleset) GetTarget() string { - if r == nil || r.Target == nil { - return "" - } - return *r.Target -} - -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (r *Ruleset) GetUpdatedAt() Timestamp { - if r == nil || r.UpdatedAt == nil { - return Timestamp{} - } - return *r.UpdatedAt -} - -// GetRefName returns the RefName field. -func (r *RulesetConditions) GetRefName() *RulesetRefConditionParameters { - if r == nil { - return nil - } - return r.RefName -} - -// GetRepositoryID returns the RepositoryID field. -func (r *RulesetConditions) GetRepositoryID() *RulesetRepositoryIDsConditionParameters { - if r == nil { - return nil - } - return r.RepositoryID -} - -// GetRepositoryName returns the RepositoryName field. -func (r *RulesetConditions) GetRepositoryName() *RulesetRepositoryNamesConditionParameters { - if r == nil { - return nil - } - return r.RepositoryName -} - -// GetRepositoryProperty returns the RepositoryProperty field. -func (r *RulesetConditions) GetRepositoryProperty() *RulesetRepositoryPropertyConditionParameters { - if r == nil { - return nil - } - return r.RepositoryProperty -} - -// GetHRef returns the HRef field if it's non-nil, zero value otherwise. -func (r *RulesetLink) GetHRef() string { - if r == nil || r.HRef == nil { - return "" - } - return *r.HRef -} - -// GetSelf returns the Self field. -func (r *RulesetLinks) GetSelf() *RulesetLink { - if r == nil { - return nil - } - return r.Self -} - -// GetProtected returns the Protected field if it's non-nil, zero value otherwise. -func (r *RulesetRepositoryNamesConditionParameters) GetProtected() bool { - if r == nil || r.Protected == nil { - return false - } - return *r.Protected -} - -// GetSource returns the Source field if it's non-nil, zero value otherwise. -func (r *RulesetRepositoryPropertyTargetParameters) GetSource() string { - if r == nil || r.Source == nil { +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RuleWorkflow) GetSHA() string { + if r == nil || r.SHA == nil { return "" } - return *r.Source + return *r.SHA } // GetBusy returns the Busy field if it's non-nil, zero value otherwise. @@ -22470,6 +24606,46 @@ func (s *ScanningAnalysis) GetWarning() string { return *s.Warning } +// GetDisplay returns the Display field if it's non-nil, zero value otherwise. +func (s *SCIMDisplayReference) GetDisplay() string { + if s == nil || s.Display == nil { + return "" + } + return *s.Display +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (s *SCIMGroupAttributes) GetDisplayName() string { + if s == nil || s.DisplayName == nil { + return "" + } + return *s.DisplayName +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (s *SCIMGroupAttributes) GetExternalID() string { + if s == nil || s.ExternalID == nil { + return "" + } + return *s.ExternalID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SCIMGroupAttributes) GetID() string { + if s == nil || s.ID == nil { + return "" + } + return *s.ID +} + +// GetMeta returns the Meta field. +func (s *SCIMGroupAttributes) GetMeta() *SCIMMeta { + if s == nil { + return nil + } + return s.Meta +} + // GetCreated returns the Created field if it's non-nil, zero value otherwise. func (s *SCIMMeta) GetCreated() Timestamp { if s == nil || s.Created == nil { @@ -22502,6 +24678,30 @@ func (s *SCIMMeta) GetResourceType() string { return *s.ResourceType } +// GetItemsPerPage returns the ItemsPerPage field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedGroups) GetItemsPerPage() int { + if s == nil || s.ItemsPerPage == nil { + return 0 + } + return *s.ItemsPerPage +} + +// GetStartIndex returns the StartIndex field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedGroups) GetStartIndex() int { + if s == nil || s.StartIndex == nil { + return 0 + } + return *s.StartIndex +} + +// GetTotalResults returns the TotalResults field if it's non-nil, zero value otherwise. +func (s *SCIMProvisionedGroups) GetTotalResults() int { + if s == nil || s.TotalResults == nil { + return 0 + } + return *s.TotalResults +} + // GetItemsPerPage returns the ItemsPerPage field if it's non-nil, zero value otherwise. func (s *SCIMProvisionedIdentities) GetItemsPerPage() int { if s == nil || s.ItemsPerPage == nil { @@ -23534,6 +25734,38 @@ func (s *SponsorshipTier) GetFrom() string { return *s.From } +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (s *SSHKeyStatus) GetHostname() string { + if s == nil || s.Hostname == nil { + return "" + } + return *s.Hostname +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (s *SSHKeyStatus) GetMessage() string { + if s == nil || s.Message == nil { + return "" + } + return *s.Message +} + +// GetModified returns the Modified field if it's non-nil, zero value otherwise. +func (s *SSHKeyStatus) GetModified() bool { + if s == nil || s.Modified == nil { + return false + } + return *s.Modified +} + +// GetUUID returns the UUID field if it's non-nil, zero value otherwise. +func (s *SSHKeyStatus) GetUUID() string { + if s == nil || s.UUID == nil { + return "" + } + return *s.UUID +} + // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (s *SSHSigningKey) GetCreatedAt() Timestamp { if s == nil || s.CreatedAt == nil { @@ -23814,6 +26046,46 @@ func (s *Subscription) GetURL() string { return *s.URL } +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SystemRequirements) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetHostname returns the Hostname field if it's non-nil, zero value otherwise. +func (s *SystemRequirementsNode) GetHostname() string { + if s == nil || s.Hostname == nil { + return "" + } + return *s.Hostname +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SystemRequirementsNode) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (s *SystemRequirementsNodeRoleStatus) GetRole() string { + if s == nil || s.Role == nil { + return "" + } + return *s.Role +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SystemRequirementsNodeRoleStatus) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + // GetMessage returns the Message field if it's non-nil, zero value otherwise. func (t *Tag) GetMessage() string { if t == nil || t.Message == nil { @@ -24014,6 +26286,14 @@ func (t *Team) GetNodeID() string { return *t.NodeID } +// GetNotificationSetting returns the NotificationSetting field if it's non-nil, zero value otherwise. +func (t *Team) GetNotificationSetting() string { + if t == nil || t.NotificationSetting == nil { + return "" + } + return *t.NotificationSetting +} + // GetOrganization returns the Organization field. func (t *Team) GetOrganization() *Organization { if t == nil { @@ -25390,14 +27670,6 @@ func (u *User) GetID() int64 { return *u.ID } -// GetInheritedFrom returns the InheritedFrom field. -func (u *User) GetInheritedFrom() *Team { - if u == nil { - return nil - } - return u.InheritedFrom -} - // GetLdapDn returns the LdapDn field if it's non-nil, zero value otherwise. func (u *User) GetLdapDn() string { if u == nil || u.LdapDn == nil { @@ -26942,6 +29214,14 @@ func (w *Workflows) GetTotalCount() int { return *w.TotalCount } +// GetDoNotEnforceOnCreate returns the DoNotEnforceOnCreate field if it's non-nil, zero value otherwise. +func (w *WorkflowsRuleParameters) GetDoNotEnforceOnCreate() bool { + if w == nil || w.DoNotEnforceOnCreate == nil { + return false + } + return *w.DoNotEnforceOnCreate +} + // GetBillable returns the Billable field. func (w *WorkflowUsage) GetBillable() *WorkflowBillMap { if w == nil { diff --git a/vendor/github.com/google/go-github/v68/github/github.go b/vendor/github.com/google/go-github/v70/github/github.go similarity index 86% rename from vendor/github.com/google/go-github/v68/github/github.go rename to vendor/github.com/google/go-github/v70/github/github.go index 4e5a33c67e..f31473edff 100644 --- a/vendor/github.com/google/go-github/v68/github/github.go +++ b/vendor/github.com/google/go-github/v70/github/github.go @@ -19,6 +19,7 @@ import ( "net/http" "net/url" "reflect" + "regexp" "strconv" "strings" "sync" @@ -28,7 +29,7 @@ import ( ) const ( - Version = "v68.0.0" + Version = "v70.0.0" defaultAPIVersion = "2022-11-28" defaultBaseURL = "https://api.github.com/" @@ -38,7 +39,9 @@ const ( headerAPIVersion = "X-Github-Api-Version" headerRateLimit = "X-Ratelimit-Limit" headerRateRemaining = "X-Ratelimit-Remaining" + headerRateUsed = "X-Ratelimit-Used" headerRateReset = "X-Ratelimit-Reset" + headerRateResource = "X-Ratelimit-Resource" headerOTP = "X-Github-Otp" headerRetryAfter = "Retry-After" @@ -155,8 +158,9 @@ var errNonNilContext = errors.New("context must be non-nil") // A Client manages communication with the GitHub API. type Client struct { - clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. - client *http.Client // HTTP client used to communicate with the API. + clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. + client *http.Client // HTTP client used to communicate with the API. + clientIgnoreRedirects *http.Client // HTTP client used to communicate with the API on endpoints where we don't want to follow redirects. // Base URL for API requests. Defaults to the public GitHub API, but can be // set to a domain endpoint to use with GitHub Enterprise. BaseURL should @@ -173,6 +177,13 @@ type Client struct { rateLimits [Categories]Rate // Rate limits for the client as determined by the most recent API calls. secondaryRateLimitReset time.Time // Secondary rate limit reset for the client as determined by the most recent API calls. + // If specified, Client will block requests for at most this duration in case of reaching a secondary + // rate limit + MaxSecondaryRateLimitRetryAfterDuration time.Duration + + // Whether to respect rate limit headers on endpoints that return 302 redirections to artifacts + RateLimitRedirectionalEndpoints bool + common service // Reuse a single struct instead of allocating one for each service on the heap. // Services used for talking to different parts of the GitHub API. @@ -394,6 +405,14 @@ func (c *Client) initialize() { if c.client == nil { c.client = &http.Client{} } + // Copy the main http client into the IgnoreRedirects one, overriding the `CheckRedirect` func + c.clientIgnoreRedirects = &http.Client{} + c.clientIgnoreRedirects.Transport = c.client.Transport + c.clientIgnoreRedirects.Timeout = c.client.Timeout + c.clientIgnoreRedirects.Jar = c.client.Jar + c.clientIgnoreRedirects.CheckRedirect = func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + } if c.BaseURL == nil { c.BaseURL, _ = url.Parse(defaultBaseURL) } @@ -448,11 +467,12 @@ func (c *Client) copy() *Client { c.clientMu.Lock() // can't use *c here because that would copy mutexes by value. clone := Client{ - client: &http.Client{}, - UserAgent: c.UserAgent, - BaseURL: c.BaseURL, - UploadURL: c.UploadURL, - secondaryRateLimitReset: c.secondaryRateLimitReset, + client: &http.Client{}, + UserAgent: c.UserAgent, + BaseURL: c.BaseURL, + UploadURL: c.UploadURL, + RateLimitRedirectionalEndpoints: c.RateLimitRedirectionalEndpoints, + secondaryRateLimitReset: c.secondaryRateLimitReset, } c.clientMu.Unlock() if c.client != nil { @@ -506,7 +526,7 @@ func WithVersion(version string) RequestOption { // request body. func (c *Client) NewRequest(method, urlStr string, body interface{}, opts ...RequestOption) (*http.Request, error) { if !strings.HasSuffix(c.BaseURL.Path, "/") { - return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + return nil, fmt.Errorf("baseURL must have a trailing slash, but %q does not", c.BaseURL) } u, err := c.BaseURL.Parse(urlStr) @@ -552,7 +572,7 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}, opts ...Req // Body is sent with Content-Type: application/x-www-form-urlencoded. func (c *Client) NewFormRequest(urlStr string, body io.Reader, opts ...RequestOption) (*http.Request, error) { if !strings.HasSuffix(c.BaseURL.Path, "/") { - return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + return nil, fmt.Errorf("baseURL must have a trailing slash, but %q does not", c.BaseURL) } u, err := c.BaseURL.Parse(urlStr) @@ -584,7 +604,7 @@ func (c *Client) NewFormRequest(urlStr string, body io.Reader, opts ...RequestOp // Relative URLs should always be specified without a preceding slash. func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string, opts ...RequestOption) (*http.Request, error) { if !strings.HasSuffix(c.UploadURL.Path, "/") { - return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL) + return nil, fmt.Errorf("uploadURL must have a trailing slash, but %q does not", c.UploadURL) } u, err := c.UploadURL.Parse(urlStr) if err != nil { @@ -750,11 +770,17 @@ func parseRate(r *http.Response) Rate { if remaining := r.Header.Get(headerRateRemaining); remaining != "" { rate.Remaining, _ = strconv.Atoi(remaining) } + if used := r.Header.Get(headerRateUsed); used != "" { + rate.Used, _ = strconv.Atoi(used) + } if reset := r.Header.Get(headerRateReset); reset != "" { if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { rate.Reset = Timestamp{time.Unix(v, 0)} } } + if resource := r.Header.Get(headerRateResource); resource != "" { + rate.Resource = resource + } return rate } @@ -801,19 +827,23 @@ func parseTokenExpiration(r *http.Response) Timestamp { type requestContext uint8 const ( - bypassRateLimitCheck requestContext = iota + // BypassRateLimitCheck prevents a pre-emptive check for exceeded primary rate limits + // Specify this by providing a context with this key, e.g. + // context.WithValue(context.Background(), github.BypassRateLimitCheck, true) + BypassRateLimitCheck requestContext = iota + SleepUntilPrimaryRateLimitResetWhenRateLimited ) -// BareDo sends an API request and lets you handle the api response. If an error -// or API Error occurs, the error will contain more information. Otherwise you -// are supposed to read and close the response's Body. If rate limit is exceeded -// and reset time is in the future, BareDo returns *RateLimitError immediately -// without making a network API call. +// bareDo sends an API request using `caller` http.Client passed in the parameters +// and lets you handle the api response. If an error or API Error occurs, the error +// will contain more information. Otherwise you are supposed to read and close the +// response's Body. If rate limit is exceeded and reset time is in the future, +// bareDo returns *RateLimitError immediately without making a network API call. // // The provided ctx must be non-nil, if it is nil an error is returned. If it is // canceled or times out, ctx.Err() will be returned. -func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, error) { +func (c *Client) bareDo(ctx context.Context, caller *http.Client, req *http.Request) (*Response, error) { if ctx == nil { return nil, errNonNilContext } @@ -822,7 +852,7 @@ func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, erro rateLimitCategory := GetRateLimitCategory(req.Method, req.URL.Path) - if bypass := ctx.Value(bypassRateLimitCheck); bypass == nil { + if bypass := ctx.Value(BypassRateLimitCheck); bypass == nil { // If we've hit rate limit, don't make further requests before Reset time. if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { return &Response{ @@ -838,7 +868,7 @@ func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, erro } } - resp, err := c.client.Do(req) + resp, err := caller.Do(req) var response *Response if resp != nil { response = newResponse(resp) @@ -897,12 +927,16 @@ func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, erro return response, err } // retry the request once when the rate limit has reset - return c.BareDo(context.WithValue(req.Context(), SleepUntilPrimaryRateLimitResetWhenRateLimited, nil), req) + return c.bareDo(context.WithValue(req.Context(), SleepUntilPrimaryRateLimitResetWhenRateLimited, nil), caller, req) } // Update the secondary rate limit if we hit it. rerr, ok := err.(*AbuseRateLimitError) if ok && rerr.RetryAfter != nil { + // if a max duration is specified, make sure that we are waiting at most this duration + if c.MaxSecondaryRateLimitRetryAfterDuration > 0 && rerr.GetRetryAfter() > c.MaxSecondaryRateLimitRetryAfterDuration { + rerr.RetryAfter = &c.MaxSecondaryRateLimitRetryAfterDuration + } c.rateMu.Lock() c.secondaryRateLimitReset = time.Now().Add(*rerr.RetryAfter) c.rateMu.Unlock() @@ -911,6 +945,72 @@ func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, erro return response, err } +// BareDo sends an API request and lets you handle the api response. If an error +// or API Error occurs, the error will contain more information. Otherwise you +// are supposed to read and close the response's Body. If rate limit is exceeded +// and reset time is in the future, BareDo returns *RateLimitError immediately +// without making a network API call. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it is +// canceled or times out, ctx.Err() will be returned. +func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, error) { + return c.bareDo(ctx, c.client, req) +} + +// bareDoIgnoreRedirects has the exact same behavior as BareDo but stops at the first +// redirection code returned by the API. If a redirection is returned by the api, bareDoIgnoreRedirects +// returns a *RedirectionError. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it is +// canceled or times out, ctx.Err() will be returned. +func (c *Client) bareDoIgnoreRedirects(ctx context.Context, req *http.Request) (*Response, error) { + return c.bareDo(ctx, c.clientIgnoreRedirects, req) +} + +var errInvalidLocation = errors.New("invalid or empty Location header in redirection response") + +// bareDoUntilFound has the exact same behavior as BareDo but only follows 301s, up to maxRedirects times. If it receives +// a 302, it will parse the Location header into a *url.URL and return that. +// This is useful for endpoints that return a 302 in successful cases but still might return 301s for +// permanent redirections. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it is +// canceled or times out, ctx.Err() will be returned. +func (c *Client) bareDoUntilFound(ctx context.Context, req *http.Request, maxRedirects int) (*url.URL, *Response, error) { + response, err := c.bareDoIgnoreRedirects(ctx, req) + if err != nil { + rerr, ok := err.(*RedirectionError) + if ok { + // If we receive a 302, transform potential relative locations into absolute and return it. + if rerr.StatusCode == http.StatusFound { + if rerr.Location == nil { + return nil, nil, errInvalidLocation + } + newURL := c.BaseURL.ResolveReference(rerr.Location) + return newURL, response, nil + } + // If permanent redirect response is returned, follow it + if maxRedirects > 0 && rerr.StatusCode == http.StatusMovedPermanently { + if rerr.Location == nil { + return nil, nil, errInvalidLocation + } + newURL := c.BaseURL.ResolveReference(rerr.Location) + newRequest := req.Clone(ctx) + newRequest.URL = newURL + return c.bareDoUntilFound(ctx, newRequest, maxRedirects-1) + } + // If we reached the maximum amount of redirections, return an error + if maxRedirects <= 0 && rerr.StatusCode == http.StatusMovedPermanently { + return nil, response, fmt.Errorf("reached the maximum amount of redirections: %w", err) + } + return nil, response, fmt.Errorf("unexpected redirection response: %w", err) + } + } + + // If we don't receive a redirection, forward the response and potential error + return nil, response, err +} + // Do sends an API request and returns the API response. The API response is // JSON decoded and stored in the value pointed to by v, or returned as an // error if an API error has occurred. If v implements the io.Writer interface, @@ -1034,7 +1134,8 @@ GitHub API docs: https://docs.github.com/rest/#client-errors type ErrorResponse struct { Response *http.Response `json:"-"` // HTTP response that caused this error Message string `json:"message"` // error message - Errors []Error `json:"errors"` // more detail on individual errors + //nolint:sliceofpointers + Errors []Error `json:"errors"` // more detail on individual errors // Block is only populated on certain types of errors such as code 451. Block *ErrorBlock `json:"block,omitempty"` // Most errors will also include a documentation_url field pointing @@ -1196,6 +1297,40 @@ func (r *AbuseRateLimitError) Is(target error) bool { compareHTTPResponse(r.Response, v.Response) } +// RedirectionError represents a response that returned a redirect status code: +// +// 301 (Moved Permanently) +// 302 (Found) +// 303 (See Other) +// 307 (Temporary Redirect) +// 308 (Permanent Redirect) +// +// If there was a valid Location header included, it will be parsed to a URL. You should use +// `BaseURL.ResolveReference()` to enrich it with the correct hostname where needed. +type RedirectionError struct { + Response *http.Response // HTTP response that caused this error + StatusCode int + Location *url.URL // location header of the redirection if present +} + +func (r *RedirectionError) Error() string { + return fmt.Sprintf("%v %v: %d location %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.StatusCode, sanitizeURL(r.Location)) +} + +// Is returns whether the provided error equals this error. +func (r *RedirectionError) Is(target error) bool { + v, ok := target.(*RedirectionError) + if !ok { + return false + } + + return r.StatusCode == v.StatusCode && + (r.Location == v.Location || // either both locations are nil or exactly the same pointer + r.Location != nil && v.Location != nil && r.Location.String() == v.Location.String()) // or they are both not nil and marshaled identically +} + // sanitizeURL redacts the client_secret parameter from the URL which may be // exposed to the user. func sanitizeURL(uri *url.URL) *url.URL { @@ -1260,7 +1395,8 @@ func (e *Error) UnmarshalJSON(data []byte) error { // // The error type will be *RateLimitError for rate limit exceeded errors, // *AcceptedError for 202 Accepted status codes, -// and *TwoFactorAuthError for two-factor authentication errors. +// *TwoFactorAuthError for two-factor authentication errors, +// and *RedirectionError for redirect status codes (only happens when ignoring redirections). func CheckResponse(r *http.Response) error { if r.StatusCode == http.StatusAccepted { return &AcceptedError{} @@ -1302,6 +1438,25 @@ func CheckResponse(r *http.Response) error { abuseRateLimitError.RetryAfter = retryAfter } return abuseRateLimitError + // Check that the status code is a redirection and return a sentinel error that can be used to handle special cases + // where 302 is considered a successful result. + // This should never happen with the default `CheckRedirect`, because it would return a `url.Error` that should be handled upstream. + case r.StatusCode == http.StatusMovedPermanently || + r.StatusCode == http.StatusFound || + r.StatusCode == http.StatusSeeOther || + r.StatusCode == http.StatusTemporaryRedirect || + r.StatusCode == http.StatusPermanentRedirect: + + locationStr := r.Header.Get("Location") + var location *url.URL + if locationStr != "" { + location, _ = url.Parse(locationStr) + } + return &RedirectionError{ + Response: errorResponse.Response, + StatusCode: r.StatusCode, + Location: location, + } default: return errorResponse } @@ -1616,3 +1771,18 @@ type roundTripperFunc func(*http.Request) (*http.Response, error) func (fn roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return fn(r) } + +var runIDFromURLRE = regexp.MustCompile(`repos/.*/actions/runs/(\d+)/deployment_protection_rule$`) + +// GetRunID is a Helper Function used to extract the workflow RunID from the *DeploymentProtectionRuleEvent.DeploymentCallBackURL. +func (e *DeploymentProtectionRuleEvent) GetRunID() (int64, error) { + match := runIDFromURLRE.FindStringSubmatch(*e.DeploymentCallbackURL) + if len(match) != 2 { + return -1, errors.New("no match") + } + runID, err := strconv.ParseInt(match[1], 10, 64) + if err != nil { + return -1, err + } + return runID, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/gitignore.go b/vendor/github.com/google/go-github/v70/github/gitignore.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/gitignore.go rename to vendor/github.com/google/go-github/v70/github/gitignore.go diff --git a/vendor/github.com/google/go-github/v68/github/interactions.go b/vendor/github.com/google/go-github/v70/github/interactions.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/interactions.go rename to vendor/github.com/google/go-github/v70/github/interactions.go diff --git a/vendor/github.com/google/go-github/v68/github/interactions_orgs.go b/vendor/github.com/google/go-github/v70/github/interactions_orgs.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/interactions_orgs.go rename to vendor/github.com/google/go-github/v70/github/interactions_orgs.go diff --git a/vendor/github.com/google/go-github/v68/github/interactions_repos.go b/vendor/github.com/google/go-github/v70/github/interactions_repos.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/interactions_repos.go rename to vendor/github.com/google/go-github/v70/github/interactions_repos.go diff --git a/vendor/github.com/google/go-github/v68/github/issue_import.go b/vendor/github.com/google/go-github/v70/github/issue_import.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/issue_import.go rename to vendor/github.com/google/go-github/v70/github/issue_import.go diff --git a/vendor/github.com/google/go-github/v68/github/issues.go b/vendor/github.com/google/go-github/v70/github/issues.go similarity index 96% rename from vendor/github.com/google/go-github/v68/github/issues.go rename to vendor/github.com/google/go-github/v70/github/issues.go index a2652b3497..6d3a6b15c5 100644 --- a/vendor/github.com/google/go-github/v68/github/issues.go +++ b/vendor/github.com/google/go-github/v70/github/issues.go @@ -55,6 +55,7 @@ type Issue struct { Assignees []*User `json:"assignees,omitempty"` NodeID *string `json:"node_id,omitempty"` Draft *bool `json:"draft,omitempty"` + Type *IssueType `json:"type,omitempty"` // TextMatches is only populated from search results that request text matches // See: search.go and https://docs.github.com/rest/search/#text-match-metadata @@ -129,6 +130,18 @@ type PullRequestLinks struct { MergedAt *Timestamp `json:"merged_at,omitempty"` } +// IssueType represents the type of issue. +// For now it shows up when receiveing an Issue event. +type IssueType struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Color *string `json:"color,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + // List the issues for the authenticated user. If all is true, list issues // across all the user's visible repositories including owned, member, and // organization repositories; if false, list only owned and member diff --git a/vendor/github.com/google/go-github/v68/github/issues_assignees.go b/vendor/github.com/google/go-github/v70/github/issues_assignees.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/issues_assignees.go rename to vendor/github.com/google/go-github/v70/github/issues_assignees.go diff --git a/vendor/github.com/google/go-github/v68/github/issues_comments.go b/vendor/github.com/google/go-github/v70/github/issues_comments.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/issues_comments.go rename to vendor/github.com/google/go-github/v70/github/issues_comments.go diff --git a/vendor/github.com/google/go-github/v68/github/issues_events.go b/vendor/github.com/google/go-github/v70/github/issues_events.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/issues_events.go rename to vendor/github.com/google/go-github/v70/github/issues_events.go diff --git a/vendor/github.com/google/go-github/v68/github/issues_labels.go b/vendor/github.com/google/go-github/v70/github/issues_labels.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/issues_labels.go rename to vendor/github.com/google/go-github/v70/github/issues_labels.go diff --git a/vendor/github.com/google/go-github/v68/github/issues_milestones.go b/vendor/github.com/google/go-github/v70/github/issues_milestones.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/issues_milestones.go rename to vendor/github.com/google/go-github/v70/github/issues_milestones.go diff --git a/vendor/github.com/google/go-github/v68/github/issues_timeline.go b/vendor/github.com/google/go-github/v70/github/issues_timeline.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/issues_timeline.go rename to vendor/github.com/google/go-github/v70/github/issues_timeline.go diff --git a/vendor/github.com/google/go-github/v68/github/licenses.go b/vendor/github.com/google/go-github/v70/github/licenses.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/licenses.go rename to vendor/github.com/google/go-github/v70/github/licenses.go diff --git a/vendor/github.com/google/go-github/v68/github/markdown.go b/vendor/github.com/google/go-github/v70/github/markdown.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/markdown.go rename to vendor/github.com/google/go-github/v70/github/markdown.go diff --git a/vendor/github.com/google/go-github/v68/github/messages.go b/vendor/github.com/google/go-github/v70/github/messages.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/messages.go rename to vendor/github.com/google/go-github/v70/github/messages.go diff --git a/vendor/github.com/google/go-github/v68/github/meta.go b/vendor/github.com/google/go-github/v70/github/meta.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/meta.go rename to vendor/github.com/google/go-github/v70/github/meta.go diff --git a/vendor/github.com/google/go-github/v68/github/migrations.go b/vendor/github.com/google/go-github/v70/github/migrations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/migrations.go rename to vendor/github.com/google/go-github/v70/github/migrations.go diff --git a/vendor/github.com/google/go-github/v68/github/migrations_source_import.go b/vendor/github.com/google/go-github/v70/github/migrations_source_import.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/migrations_source_import.go rename to vendor/github.com/google/go-github/v70/github/migrations_source_import.go diff --git a/vendor/github.com/google/go-github/v68/github/migrations_user.go b/vendor/github.com/google/go-github/v70/github/migrations_user.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/migrations_user.go rename to vendor/github.com/google/go-github/v70/github/migrations_user.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs.go b/vendor/github.com/google/go-github/v70/github/orgs.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs.go rename to vendor/github.com/google/go-github/v70/github/orgs.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go b/vendor/github.com/google/go-github/v70/github/orgs_actions_allowed.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_actions_allowed.go rename to vendor/github.com/google/go-github/v70/github/orgs_actions_allowed.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go b/vendor/github.com/google/go-github/v70/github/orgs_actions_permissions.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_actions_permissions.go rename to vendor/github.com/google/go-github/v70/github/orgs_actions_permissions.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_attestations.go b/vendor/github.com/google/go-github/v70/github/orgs_attestations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_attestations.go rename to vendor/github.com/google/go-github/v70/github/orgs_attestations.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_audit_log.go b/vendor/github.com/google/go-github/v70/github/orgs_audit_log.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_audit_log.go rename to vendor/github.com/google/go-github/v70/github/orgs_audit_log.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go b/vendor/github.com/google/go-github/v70/github/orgs_codesecurity_configurations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_codesecurity_configurations.go rename to vendor/github.com/google/go-github/v70/github/orgs_codesecurity_configurations.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go b/vendor/github.com/google/go-github/v70/github/orgs_credential_authorizations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_credential_authorizations.go rename to vendor/github.com/google/go-github/v70/github/orgs_credential_authorizations.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go b/vendor/github.com/google/go-github/v70/github/orgs_custom_repository_roles.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_custom_repository_roles.go rename to vendor/github.com/google/go-github/v70/github/orgs_custom_repository_roles.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks.go b/vendor/github.com/google/go-github/v70/github/orgs_hooks.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_hooks.go rename to vendor/github.com/google/go-github/v70/github/orgs_hooks.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go b/vendor/github.com/google/go-github/v70/github/orgs_hooks_configuration.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_hooks_configuration.go rename to vendor/github.com/google/go-github/v70/github/orgs_hooks_configuration.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go b/vendor/github.com/google/go-github/v70/github/orgs_hooks_deliveries.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_hooks_deliveries.go rename to vendor/github.com/google/go-github/v70/github/orgs_hooks_deliveries.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_members.go b/vendor/github.com/google/go-github/v70/github/orgs_members.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_members.go rename to vendor/github.com/google/go-github/v70/github/orgs_members.go diff --git a/vendor/github.com/google/go-github/v70/github/orgs_network_configurations.go b/vendor/github.com/google/go-github/v70/github/orgs_network_configurations.go new file mode 100644 index 0000000000..82a819c204 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/orgs_network_configurations.go @@ -0,0 +1,236 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "regexp" +) + +// ComputeService represents a hosted compute service the network configuration supports. +type ComputeService string + +const ( + ComputeServiceNone ComputeService = "none" + ComputeServiceActions ComputeService = "actions" + ComputeServiceCodespaces ComputeService = "codespaces" +) + +// NetworkConfigurations represents a hosted compute network configuration. This type is identical +// for enterprise and organization endpoints. +type NetworkConfigurations struct { + TotalCount *int64 `json:"total_count,omitempty"` + NetworkConfigurations []*NetworkConfiguration `json:"network_configurations,omitempty"` +} + +// NetworkConfiguration represents a hosted compute network configurations. This type is identical +// for enterprise and organization endpoints. +type NetworkConfiguration struct { + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + ComputeService *ComputeService `json:"compute_service,omitempty"` + NetworkSettingsIDs []string `json:"network_settings_ids,omitempty"` + CreatedOn *Timestamp `json:"created_on"` +} + +// NetworkSettingsResource represents a hosted compute network settings resource. This type is identical +// for enterprise and organization endpoints. +type NetworkSettingsResource struct { + ID *string `json:"id,omitempty"` + NetworkConfigurationID *string `json:"network_configuration_id,omitempty"` + Name *string `json:"name,omitempty"` + SubnetID *string `json:"subnet_id,omitempty"` + Region *string `json:"region,omitempty"` +} + +func validateComputeService(compute *ComputeService) error { + if compute == nil { + return nil + } + if *compute != ComputeServiceNone && *compute != ComputeServiceActions { + return errors.New("compute service can only be one of: none, actions") + } + return nil +} + +var validNetworkNameRE = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`) + +func validateNetworkName(name string) error { + if len(name) < 1 || len(name) > 100 { + return errors.New("must be between 1 and 100 characters") + } + if !validNetworkNameRE.MatchString(name) { + return errors.New("may only contain upper and lowercase letters a-z, numbers 0-9, '.', '-', and '_'") + } + return nil +} + +func validateNetworkSettingsID(settingsID []string) error { + if len(settingsID) != 1 { + return errors.New("exactly one network settings id must be specified") + } + return nil +} + +func validateNetworkConfigurationRequest(req NetworkConfigurationRequest) error { + networkName := req.GetName() + if err := validateNetworkName(networkName); err != nil { + return err + } + + computeService := req.GetComputeService() + if err := validateComputeService(computeService); err != nil { + return err + } + + networkIDs := req.NetworkSettingsIDs + if err := validateNetworkSettingsID(networkIDs); err != nil { + return err + } + return nil +} + +// NetworkConfigurationRequest represents a request to create or update a network configuration for an organization. +type NetworkConfigurationRequest struct { + Name *string `json:"name,omitempty"` + ComputeService *ComputeService `json:"compute_service,omitempty"` + NetworkSettingsIDs []string `json:"network_settings_ids,omitempty"` +} + +// ListNetworkConfigurations lists all hosted compute network configurations configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/network-configurations#list-hosted-compute-network-configurations-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/network-configurations +func (s *OrganizationsService) ListNetworkConfigurations(ctx context.Context, org string, opts *ListOptions) (*NetworkConfigurations, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/network-configurations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + configurations := &NetworkConfigurations{} + resp, err := s.client.Do(ctx, req, configurations) + if err != nil { + return nil, resp, err + } + return configurations, resp, nil +} + +// CreateNetworkConfiguration creates a hosted compute network configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/network-configurations#create-a-hosted-compute-network-configuration-for-an-organization +// +//meta:operation POST /orgs/{org}/settings/network-configurations +func (s *OrganizationsService) CreateNetworkConfiguration(ctx context.Context, org string, createReq NetworkConfigurationRequest) (*NetworkConfiguration, *Response, error) { + if err := validateNetworkConfigurationRequest(createReq); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("orgs/%v/settings/network-configurations", org) + req, err := s.client.NewRequest("POST", u, createReq) + if err != nil { + return nil, nil, err + } + + configuration := &NetworkConfiguration{} + resp, err := s.client.Do(ctx, req, configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// GetNetworkConfiguration gets a hosted compute network configuration configured in an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/network-configurations#get-a-hosted-compute-network-configuration-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/network-configurations/{network_configuration_id} +func (s *OrganizationsService) GetNetworkConfiguration(ctx context.Context, org, networkID string) (*NetworkConfiguration, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/network-configurations/%v", org, networkID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + configuration := &NetworkConfiguration{} + resp, err := s.client.Do(ctx, req, configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// UpdateNetworkConfiguration updates a hosted compute network configuration for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/network-configurations#update-a-hosted-compute-network-configuration-for-an-organization +// +//meta:operation PATCH /orgs/{org}/settings/network-configurations/{network_configuration_id} +func (s *OrganizationsService) UpdateNetworkConfiguration(ctx context.Context, org, networkID string, updateReq NetworkConfigurationRequest) (*NetworkConfiguration, *Response, error) { + if err := validateNetworkConfigurationRequest(updateReq); err != nil { + return nil, nil, fmt.Errorf("validation failed: %w", err) + } + + u := fmt.Sprintf("orgs/%v/settings/network-configurations/%v", org, networkID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + configuration := &NetworkConfiguration{} + resp, err := s.client.Do(ctx, req, configuration) + if err != nil { + return nil, resp, err + } + return configuration, resp, nil +} + +// DeleteNetworkConfigurations deletes a hosted compute network configuration from an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/network-configurations#delete-a-hosted-compute-network-configuration-from-an-organization +// +//meta:operation DELETE /orgs/{org}/settings/network-configurations/{network_configuration_id} +func (s *OrganizationsService) DeleteNetworkConfigurations(ctx context.Context, org, networkID string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/settings/network-configurations/%v", org, networkID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + configuration := &NetworkConfiguration{} + resp, err := s.client.Do(ctx, req, configuration) + if err != nil { + return resp, err + } + return resp, nil +} + +// GetNetworkConfigurationResource gets a hosted compute network settings resource configured for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/network-configurations#get-a-hosted-compute-network-settings-resource-for-an-organization +// +//meta:operation GET /orgs/{org}/settings/network-settings/{network_settings_id} +func (s *OrganizationsService) GetNetworkConfigurationResource(ctx context.Context, org, networkID string) (*NetworkSettingsResource, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/network-settings/%v", org, networkID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resource := &NetworkSettingsResource{} + resp, err := s.client.Do(ctx, req, resource) + if err != nil { + return nil, resp, err + } + return resource, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go b/vendor/github.com/google/go-github/v70/github/orgs_organization_roles.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_organization_roles.go rename to vendor/github.com/google/go-github/v70/github/orgs_organization_roles.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go b/vendor/github.com/google/go-github/v70/github/orgs_outside_collaborators.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_outside_collaborators.go rename to vendor/github.com/google/go-github/v70/github/orgs_outside_collaborators.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_packages.go b/vendor/github.com/google/go-github/v70/github/orgs_packages.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_packages.go rename to vendor/github.com/google/go-github/v70/github/orgs_packages.go diff --git a/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go b/vendor/github.com/google/go-github/v70/github/orgs_personal_access_tokens.go similarity index 98% rename from vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go rename to vendor/github.com/google/go-github/v70/github/orgs_personal_access_tokens.go index af083744e8..276fbbb494 100644 --- a/vendor/github.com/google/go-github/v68/github/orgs_personal_access_tokens.go +++ b/vendor/github.com/google/go-github/v70/github/orgs_personal_access_tokens.go @@ -44,6 +44,12 @@ type PersonalAccessToken struct { // Date and time when the associated fine-grained personal access token expires. TokenExpiresAt *Timestamp `json:"token_expires_at"` + // TokenID + TokenID *int64 `json:"token_id"` + + // TokenName + TokenName *string `json:"token_name"` + // Date and time when the associated fine-grained personal access token was last used for authentication. TokenLastUsedAt *Timestamp `json:"token_last_used_at"` } diff --git a/vendor/github.com/google/go-github/v68/github/orgs_properties.go b/vendor/github.com/google/go-github/v70/github/orgs_properties.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_properties.go rename to vendor/github.com/google/go-github/v70/github/orgs_properties.go diff --git a/vendor/github.com/google/go-github/v70/github/orgs_rules.go b/vendor/github.com/google/go-github/v70/github/orgs_rules.go new file mode 100644 index 0000000000..8cb2e5d1f9 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/orgs_rules.go @@ -0,0 +1,140 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAllRepositoryRulesets gets all the repository rulesets for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-all-organization-repository-rulesets +// +//meta:operation GET /orgs/{org}/rulesets +func (s *OrganizationsService) GetAllRepositoryRulesets(ctx context.Context, org string) ([]*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rulesets []*RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rulesets) + if err != nil { + return nil, resp, err + } + + return rulesets, resp, nil +} + +// CreateRepositoryRuleset creates a repository ruleset for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#create-an-organization-repository-ruleset +// +//meta:operation POST /orgs/{org}/rulesets +func (s *OrganizationsService) CreateRepositoryRuleset(ctx context.Context, org string, ruleset RepositoryRuleset) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets", org) + + req, err := s.client.NewRequest("POST", u, ruleset) + if err != nil { + return nil, nil, err + } + + var rs *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// GetRepositoryRuleset gets a repository ruleset for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#get-an-organization-repository-ruleset +// +//meta:operation GET /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) GetRepositoryRuleset(ctx context.Context, org string, rulesetID int64) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateRepositoryRuleset updates a repository ruleset for the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#update-an-organization-repository-ruleset +// +//meta:operation PUT /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) UpdateRepositoryRuleset(ctx context.Context, org string, rulesetID int64, ruleset RepositoryRuleset) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("PUT", u, ruleset) + if err != nil { + return nil, nil, err + } + + var rs *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// UpdateRepositoryRulesetClearBypassActor clears the bypass actors for a repository ruleset for the specified organization. +// +// This function is necessary as the UpdateRepositoryRuleset function does not marshal ByPassActor if passed as an empty array. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#update-an-organization-repository-ruleset +// +//meta:operation PUT /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) UpdateRepositoryRulesetClearBypassActor(ctx context.Context, org string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + rsClearBypassActor := rulesetClearBypassActors{} + + req, err := s.client.NewRequest("PUT", u, rsClearBypassActor) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DeleteRepositoryRuleset deletes a repository ruleset from the specified organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/rules#delete-an-organization-repository-ruleset +// +//meta:operation DELETE /orgs/{org}/rulesets/{ruleset_id} +func (s *OrganizationsService) DeleteRepositoryRuleset(ctx context.Context, org string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go b/vendor/github.com/google/go-github/v70/github/orgs_security_managers.go similarity index 88% rename from vendor/github.com/google/go-github/v68/github/orgs_security_managers.go rename to vendor/github.com/google/go-github/v70/github/orgs_security_managers.go index 0803772732..b8562a2fd7 100644 --- a/vendor/github.com/google/go-github/v68/github/orgs_security_managers.go +++ b/vendor/github.com/google/go-github/v70/github/orgs_security_managers.go @@ -12,6 +12,8 @@ import ( // ListSecurityManagerTeams lists all security manager teams for an organization. // +// Deprecated: Please use `client.Organizations.ListTeamsAssignedToOrgRole` instead. +// // GitHub API docs: https://docs.github.com/rest/orgs/security-managers#list-security-manager-teams // //meta:operation GET /orgs/{org}/security-managers @@ -34,6 +36,8 @@ func (s *OrganizationsService) ListSecurityManagerTeams(ctx context.Context, org // AddSecurityManagerTeam adds a team to the list of security managers for an organization. // +// Deprecated: Please use `client.Organizations.AssignOrgRoleToTeam` instead. +// // GitHub API docs: https://docs.github.com/rest/orgs/security-managers#add-a-security-manager-team // //meta:operation PUT /orgs/{org}/security-managers/teams/{team_slug} @@ -49,6 +53,8 @@ func (s *OrganizationsService) AddSecurityManagerTeam(ctx context.Context, org, // RemoveSecurityManagerTeam removes a team from the list of security managers for an organization. // +// Deprecated: Please use `client.Organizations.RemoveOrgRoleFromTeam` instead. +// // GitHub API docs: https://docs.github.com/rest/orgs/security-managers#remove-a-security-manager-team // //meta:operation DELETE /orgs/{org}/security-managers/teams/{team_slug} diff --git a/vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go b/vendor/github.com/google/go-github/v70/github/orgs_users_blocking.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/orgs_users_blocking.go rename to vendor/github.com/google/go-github/v70/github/orgs_users_blocking.go diff --git a/vendor/github.com/google/go-github/v70/github/packages.go b/vendor/github.com/google/go-github/v70/github/packages.go new file mode 100644 index 0000000000..e7c327963c --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/packages.go @@ -0,0 +1,318 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" +) + +// Package represents a GitHub package. +type Package struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + PackageType *string `json:"package_type,omitempty"` // One of "npm", "maven", "rubygems", "docker", "nuget", "container". For webhook events "container" is "CONTAINER" + HTMLURL *string `json:"html_url,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Owner *User `json:"owner,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + + // The following are only populated for webhook events + Namespace *string `json:"namespace,omitempty"` + Description *string `json:"description,omitempty"` + Ecosystem *string `json:"ecosystem,omitempty"` + PackageVersion *PackageVersion `json:"package_version,omitempty"` + Registry *PackageRegistry `json:"registry,omitempty"` + + // The following are NOT populated for webhook events + URL *string `json:"url,omitempty"` + VersionCount *int64 `json:"version_count,omitempty"` +} + +func (p Package) String() string { + return Stringify(p) +} + +// PackageVersion represents a GitHub package version. +type PackageVersion struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + PackageHTMLURL *string `json:"package_html_url,omitempty"` + License *string `json:"license,omitempty"` + Description *string `json:"description,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Metadata json.RawMessage `json:"metadata,omitempty"` // For webhook events this will be []interface, else it will be of type PackageMetadata + + // The following are only populated for webhook events + Version *string `json:"version,omitempty"` + Summary *string `json:"summary,omitempty"` + Body json.RawMessage `json:"body,omitempty"` // Can either be a string or of type PackageVersionBody + BodyHTML *string `json:"body_html,omitempty"` + Release *PackageRelease `json:"release,omitempty"` + Manifest *string `json:"manifest,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + TargetOID *string `json:"target_oid,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + ContainerMetadata *PackageEventContainerMetadata `json:"container_metadata,omitempty"` + DockerMetadata []interface{} `json:"docker_metadata,omitempty"` + NPMMetadata *PackageNPMMetadata `json:"npm_metadata,omitempty"` + NugetMetadata []*PackageNugetMetadata `json:"nuget_metadata,omitempty"` + RubyMetadata map[string]any `json:"ruby_metadata,omitempty"` + PackageFiles []*PackageFile `json:"package_files,omitempty"` + PackageURL *string `json:"package_url,omitempty"` + Author *User `json:"author,omitempty"` + SourceURL *string `json:"source_url,omitempty"` + InstallationCommand *string `json:"installation_command,omitempty"` + + // The following are NOT populated for webhook events + DeletedAt *Timestamp `json:"deleted_at,omitempty"` +} + +// GetBody returns the body field as a string if it's valid. +func (pv *PackageVersion) GetBody() (body string, ok bool) { + if pv == nil || pv.Body == nil { + return "", false + } + + if err := json.Unmarshal(pv.Body, &body); err != nil { + return "", false + } + + return body, true +} + +// GetBodyAsPackageVersionBody returns the body field as a PackageVersionBody if it's valid. +func (pv *PackageVersion) GetBodyAsPackageVersionBody() (body *PackageVersionBody, ok bool) { + if pv == nil || pv.Body == nil { + return nil, false + } + + if err := json.Unmarshal(pv.Body, &body); err != nil { + return nil, false + } + + return body, true +} + +// GetMetadata returns the metadata field as PackageMetadata if it's valid. +func (pv *PackageVersion) GetMetadata() (metadata *PackageMetadata, ok bool) { + if pv == nil || pv.Metadata == nil { + return nil, false + } + + if err := json.Unmarshal(pv.Metadata, &metadata); err != nil { + return nil, false + } + + return metadata, true +} + +// GetRawMetadata returns the metadata field as a json.RawMessage. +func (pv *PackageVersion) GetRawMetadata() json.RawMessage { + if pv == nil || pv.Metadata == nil { + return json.RawMessage{} + } + + return pv.Metadata +} + +func (pv PackageVersion) String() string { + return Stringify(pv) +} + +// PackageRelease represents a GitHub package version release. +type PackageRelease struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Draft *bool `json:"draft,omitempty"` + Author *User `json:"author,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` +} + +func (r PackageRelease) String() string { + return Stringify(r) +} + +// PackageFile represents a GitHub package version release file. +type PackageFile struct { + DownloadURL *string `json:"download_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + SHA256 *string `json:"sha256,omitempty"` + SHA1 *string `json:"sha1,omitempty"` + MD5 *string `json:"md5,omitempty"` + ContentType *string `json:"content_type,omitempty"` + State *string `json:"state,omitempty"` + Author *User `json:"author,omitempty"` + Size *int64 `json:"size,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (pf PackageFile) String() string { + return Stringify(pf) +} + +// PackageRegistry represents a GitHub package registry. +type PackageRegistry struct { + AboutURL *string `json:"about_url,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` + URL *string `json:"url,omitempty"` + Vendor *string `json:"vendor,omitempty"` +} + +func (r PackageRegistry) String() string { + return Stringify(r) +} + +// PackageListOptions represents the optional list options for a package. +type PackageListOptions struct { + // Visibility of packages "public", "internal" or "private". + Visibility *string `url:"visibility,omitempty"` + + // PackageType represents the type of package. + // It can be one of "npm", "maven", "rubygems", "nuget", "docker", or "container". + PackageType *string `url:"package_type,omitempty"` + + // State of package either "active" or "deleted". + State *string `url:"state,omitempty"` + + ListOptions +} + +// PackageMetadata represents metadata from a package. +type PackageMetadata struct { + PackageType *string `json:"package_type,omitempty"` + Container *PackageContainerMetadata `json:"container,omitempty"` +} + +func (r PackageMetadata) String() string { + return Stringify(r) +} + +// PackageContainerMetadata represents container metadata for docker container packages. +type PackageContainerMetadata struct { + Tags []string `json:"tags,omitempty"` +} + +func (r PackageContainerMetadata) String() string { + return Stringify(r) +} + +// PackageVersionBody represents the body field of a package version. +type PackageVersionBody struct { + Repo *Repository `json:"repository,omitempty"` + Info *PackageVersionBodyInfo `json:"info,omitempty"` +} + +func (b PackageVersionBody) String() string { + return Stringify(b) +} + +// PackageVersionBodyInfo represents the info field of a PackageVersionBody. +type PackageVersionBodyInfo struct { + Type *string `json:"type,omitempty"` + OID *string `json:"oid,omitempty"` + Mode *int64 `json:"mode,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + Size *int64 `json:"size,omitempty"` + Collection *bool `json:"collection,omitempty"` +} + +func (bi PackageVersionBodyInfo) String() string { + return Stringify(bi) +} + +// PackageEventContainerMetadata represents metadata for container packages as part of a webhook event. +// See also PackageContainerMetadata. +type PackageEventContainerMetadata struct { + Labels map[string]any `json:"labels,omitempty"` + Manifest map[string]any `json:"manifest,omitempty"` + Tag *PackageEventContainerMetadataTag `json:"tag,omitempty"` +} + +func (m PackageEventContainerMetadata) String() string { + return Stringify(m) +} + +// PackageEventContainerMetadataTag represents a tag of a GitHub container package. +type PackageEventContainerMetadataTag struct { + Name *string `json:"name,omitempty"` + Digest *string `json:"digest,omitempty"` +} + +func (mt PackageEventContainerMetadataTag) String() string { + return Stringify(mt) +} + +// PackageNugetMetadata represents nuget metadata for a GitHub package. +type PackageNugetMetadata struct { + ID json.RawMessage `json:"id,omitempty"` // Can either be a int64 or string + Name *string `json:"name,omitempty"` + Value json.RawMessage `json:"value,omitempty"` // Can either be a bool, string, integer or object +} + +func (nm PackageNugetMetadata) String() string { + return Stringify(nm) +} + +// PackageNPMMetadata represents NPM metadata for a GitHub package. +type PackageNPMMetadata struct { + Name *string `json:"name,omitempty"` + Version *string `json:"version,omitempty"` + NPMUser *string `json:"npm_user,omitempty"` + Author map[string]string `json:"author,omitempty"` + Bugs map[string]string `json:"bugs,omitempty"` + Dependencies map[string]string `json:"dependencies,omitempty"` + DevDependencies map[string]string `json:"dev_dependencies,omitempty"` + PeerDependencies map[string]string `json:"peer_dependencies,omitempty"` + OptionalDependencies map[string]string `json:"optional_dependencies,omitempty"` + Description *string `json:"description,omitempty"` + Dist map[string]string `json:"dist,omitempty"` + GitHead *string `json:"git_head,omitempty"` + Homepage *string `json:"homepage,omitempty"` + License *string `json:"license,omitempty"` + Main *string `json:"main,omitempty"` + Repository map[string]string `json:"repository,omitempty"` + Scripts map[string]any `json:"scripts,omitempty"` + ID *string `json:"id,omitempty"` + NodeVersion *string `json:"node_version,omitempty"` + NPMVersion *string `json:"npm_version,omitempty"` + HasShrinkwrap *bool `json:"has_shrinkwrap,omitempty"` + Maintainers []interface{} `json:"maintainers,omitempty"` + Contributors []interface{} `json:"contributors,omitempty"` + Engines map[string]string `json:"engines,omitempty"` + Keywords []string `json:"keywords,omitempty"` + Files []string `json:"files,omitempty"` + Bin map[string]any `json:"bin,omitempty"` + Man map[string]any `json:"man,omitempty"` + Directories map[string]string `json:"directories,omitempty"` + OS []string `json:"os,omitempty"` + CPU []string `json:"cpu,omitempty"` + Readme *string `json:"readme,omitempty"` + InstallationCommand *string `json:"installation_command,omitempty"` + ReleaseID *int64 `json:"release_id,omitempty"` + CommitOID *string `json:"commit_oid,omitempty"` + PublishedViaActions *bool `json:"published_via_actions,omitempty"` + DeletedByID *int64 `json:"deleted_by_id,omitempty"` +} + +func (nm PackageNPMMetadata) String() string { + return Stringify(nm) +} diff --git a/vendor/github.com/google/go-github/v68/github/pulls.go b/vendor/github.com/google/go-github/v70/github/pulls.go similarity index 83% rename from vendor/github.com/google/go-github/v68/github/pulls.go rename to vendor/github.com/google/go-github/v70/github/pulls.go index 35ceda4467..f3c6e929c1 100644 --- a/vendor/github.com/google/go-github/v68/github/pulls.go +++ b/vendor/github.com/google/go-github/v70/github/pulls.go @@ -28,49 +28,51 @@ type PullRequestAutoMerge struct { // PullRequest represents a GitHub pull request on a repository. type PullRequest struct { - ID *int64 `json:"id,omitempty"` - Number *int `json:"number,omitempty"` - State *string `json:"state,omitempty"` - Locked *bool `json:"locked,omitempty"` - Title *string `json:"title,omitempty"` - Body *string `json:"body,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` - ClosedAt *Timestamp `json:"closed_at,omitempty"` - MergedAt *Timestamp `json:"merged_at,omitempty"` - Labels []*Label `json:"labels,omitempty"` - User *User `json:"user,omitempty"` - Draft *bool `json:"draft,omitempty"` - Merged *bool `json:"merged,omitempty"` - Mergeable *bool `json:"mergeable,omitempty"` - MergeableState *string `json:"mergeable_state,omitempty"` - MergedBy *User `json:"merged_by,omitempty"` - MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` - Rebaseable *bool `json:"rebaseable,omitempty"` - Comments *int `json:"comments,omitempty"` - Commits *int `json:"commits,omitempty"` - Additions *int `json:"additions,omitempty"` - Deletions *int `json:"deletions,omitempty"` - ChangedFiles *int `json:"changed_files,omitempty"` - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - IssueURL *string `json:"issue_url,omitempty"` - StatusesURL *string `json:"statuses_url,omitempty"` - DiffURL *string `json:"diff_url,omitempty"` - PatchURL *string `json:"patch_url,omitempty"` - CommitsURL *string `json:"commits_url,omitempty"` - CommentsURL *string `json:"comments_url,omitempty"` - ReviewCommentsURL *string `json:"review_comments_url,omitempty"` - ReviewCommentURL *string `json:"review_comment_url,omitempty"` - ReviewComments *int `json:"review_comments,omitempty"` - Assignee *User `json:"assignee,omitempty"` - Assignees []*User `json:"assignees,omitempty"` - Milestone *Milestone `json:"milestone,omitempty"` - MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` - AuthorAssociation *string `json:"author_association,omitempty"` - NodeID *string `json:"node_id,omitempty"` - RequestedReviewers []*User `json:"requested_reviewers,omitempty"` - AutoMerge *PullRequestAutoMerge `json:"auto_merge,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + MergedAt *Timestamp `json:"merged_at,omitempty"` + Labels []*Label `json:"labels,omitempty"` + User *User `json:"user,omitempty"` + Draft *bool `json:"draft,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + ReviewCommentsURL *string `json:"review_comments_url,omitempty"` + ReviewCommentURL *string `json:"review_comment_url,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RequestedReviewers []*User `json:"requested_reviewers,omitempty"` + AutoMerge *PullRequestAutoMerge `json:"auto_merge,omitempty"` + + // These fields are not populated by the List operation. + Merged *bool `json:"merged,omitempty"` + Mergeable *bool `json:"mergeable,omitempty"` + MergeableState *string `json:"mergeable_state,omitempty"` + Rebaseable *bool `json:"rebaseable,omitempty"` + MergedBy *User `json:"merged_by,omitempty"` + MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` + Comments *int `json:"comments,omitempty"` + Commits *int `json:"commits,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + ChangedFiles *int `json:"changed_files,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + ReviewComments *int `json:"review_comments,omitempty"` // RequestedTeams is populated as part of the PullRequestEvent. // See, https://docs.github.com/developers/webhooks-and-events/github-event-types#pullrequestevent for an example. @@ -167,10 +169,12 @@ func (s *PullRequestsService) List(ctx context.Context, owner string, repo strin return pulls, resp, nil } -// ListPullRequestsWithCommit returns pull requests associated with a commit SHA. +// ListPullRequestsWithCommit returns pull requests associated with a commit SHA +// or branch name. // -// The results may include open and closed pull requests. -// By default, the PullRequestListOptions State filters for "open". +// The results may include open and closed pull requests. If the commit SHA is +// not present in the repository's default branch, the result will only include +// open pull requests. // // GitHub API docs: https://docs.github.com/rest/commits/commits#list-pull-requests-associated-with-a-commit // diff --git a/vendor/github.com/google/go-github/v68/github/pulls_comments.go b/vendor/github.com/google/go-github/v70/github/pulls_comments.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/pulls_comments.go rename to vendor/github.com/google/go-github/v70/github/pulls_comments.go diff --git a/vendor/github.com/google/go-github/v68/github/pulls_reviewers.go b/vendor/github.com/google/go-github/v70/github/pulls_reviewers.go similarity index 95% rename from vendor/github.com/google/go-github/v68/github/pulls_reviewers.go rename to vendor/github.com/google/go-github/v70/github/pulls_reviewers.go index 9dd60ae688..526047937e 100644 --- a/vendor/github.com/google/go-github/v68/github/pulls_reviewers.go +++ b/vendor/github.com/google/go-github/v70/github/pulls_reviewers.go @@ -85,11 +85,8 @@ func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo str func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) { // reviewers.Reviewers may be empty if the caller wants to remove teams, but not users. Unlike AddReviewers, // "reviewers" is a required param here. Reference: https://github.com/google/go-github/issues/3336 - removeRequest := removeReviewersRequest{ - NodeID: reviewers.NodeID, - Reviewers: reviewers.Reviewers, - TeamReviewers: reviewers.TeamReviewers, - } + // The type `removeReviewersRequest` is required because the struct tags are different from `ReviewersRequest`. + removeRequest := removeReviewersRequest(reviewers) if removeRequest.Reviewers == nil { // GitHub accepts the empty list, but rejects null. Removing `omitempty` is not enough - we also have to promote nil to []. diff --git a/vendor/github.com/google/go-github/v68/github/pulls_reviews.go b/vendor/github.com/google/go-github/v70/github/pulls_reviews.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/pulls_reviews.go rename to vendor/github.com/google/go-github/v70/github/pulls_reviews.go diff --git a/vendor/github.com/google/go-github/v68/github/pulls_threads.go b/vendor/github.com/google/go-github/v70/github/pulls_threads.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/pulls_threads.go rename to vendor/github.com/google/go-github/v70/github/pulls_threads.go diff --git a/vendor/github.com/google/go-github/v68/github/rate_limit.go b/vendor/github.com/google/go-github/v70/github/rate_limit.go similarity index 85% rename from vendor/github.com/google/go-github/v68/github/rate_limit.go rename to vendor/github.com/google/go-github/v70/github/rate_limit.go index 5b01b573d8..6236eba8fb 100644 --- a/vendor/github.com/google/go-github/v68/github/rate_limit.go +++ b/vendor/github.com/google/go-github/v70/github/rate_limit.go @@ -12,14 +12,22 @@ type RateLimitService service // Rate represents the rate limit for the current client. type Rate struct { - // The number of requests per hour the client is currently limited to. + // The maximum number of requests that you can make per hour. Limit int `json:"limit"` - // The number of remaining requests the client can make this hour. + // The number of requests remaining in the current rate limit window. Remaining int `json:"remaining"` - // The time at which the current rate limit will reset. + // The number of requests you have made in the current rate limit window. + Used int `json:"used"` + + // The time at which the current rate limit window resets, in UTC epoch seconds. Reset Timestamp `json:"reset"` + + // The rate limit resource that the request counted against. + // For more information about the different resources, see REST API endpoints for rate limits. + // GitHub API docs: https://docs.github.com/en/rest/rate-limit/rate-limit#get-rate-limit-status-for-the-authenticated-user + Resource string `json:"resource,omitempty"` } func (r Rate) String() string { @@ -77,7 +85,7 @@ func (s *RateLimitService) Get(ctx context.Context) (*RateLimits, *Response, err }) // This resource is not subject to rate limits. - ctx = context.WithValue(ctx, bypassRateLimitCheck, true) + ctx = context.WithValue(ctx, BypassRateLimitCheck, true) resp, err := s.client.Do(ctx, req, response) if err != nil { return nil, resp, err diff --git a/vendor/github.com/google/go-github/v68/github/reactions.go b/vendor/github.com/google/go-github/v70/github/reactions.go similarity index 99% rename from vendor/github.com/google/go-github/v68/github/reactions.go rename to vendor/github.com/google/go-github/v70/github/reactions.go index 9f9f72faee..e982322037 100644 --- a/vendor/github.com/google/go-github/v68/github/reactions.go +++ b/vendor/github.com/google/go-github/v70/github/reactions.go @@ -26,7 +26,8 @@ type Reaction struct { // Content is the type of reaction. // Possible values are: // "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". - Content *string `json:"content,omitempty"` + Content *string `json:"content,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` } // Reactions represents a summary of GitHub reactions. diff --git a/vendor/github.com/google/go-github/v68/github/repos.go b/vendor/github.com/google/go-github/v70/github/repos.go similarity index 99% rename from vendor/github.com/google/go-github/v68/github/repos.go rename to vendor/github.com/google/go-github/v70/github/repos.go index 9faed401f8..c4ef5d5987 100644 --- a/vendor/github.com/google/go-github/v68/github/repos.go +++ b/vendor/github.com/google/go-github/v70/github/repos.go @@ -833,7 +833,7 @@ func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, ow // GetAutomatedSecurityFixes checks if the automated security fixes for a repository are enabled. // -// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-automated-security-fixes-are-enabled-for-a-repository +// GitHub API docs: https://docs.github.com/rest/repos/repos#check-if-dependabot-security-updates-are-enabled-for-a-repository // //meta:operation GET /repos/{owner}/{repo}/automated-security-fixes func (s *RepositoriesService) GetAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*AutomatedSecurityFixes, *Response, error) { @@ -854,7 +854,7 @@ func (s *RepositoriesService) GetAutomatedSecurityFixes(ctx context.Context, own // EnableAutomatedSecurityFixes enables the automated security fixes for a repository. // -// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-automated-security-fixes +// GitHub API docs: https://docs.github.com/rest/repos/repos#enable-dependabot-security-updates // //meta:operation PUT /repos/{owner}/{repo}/automated-security-fixes func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { @@ -870,7 +870,7 @@ func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, // DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository. // -// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-automated-security-fixes +// GitHub API docs: https://docs.github.com/rest/repos/repos#disable-dependabot-security-updates // //meta:operation DELETE /repos/{owner}/{repo}/automated-security-fixes func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_access.go b/vendor/github.com/google/go-github/v70/github/repos_actions_access.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_actions_access.go rename to vendor/github.com/google/go-github/v70/github/repos_actions_access.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go b/vendor/github.com/google/go-github/v70/github/repos_actions_allowed.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_actions_allowed.go rename to vendor/github.com/google/go-github/v70/github/repos_actions_allowed.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go b/vendor/github.com/google/go-github/v70/github/repos_actions_permissions.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_actions_permissions.go rename to vendor/github.com/google/go-github/v70/github/repos_actions_permissions.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_attestations.go b/vendor/github.com/google/go-github/v70/github/repos_attestations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_attestations.go rename to vendor/github.com/google/go-github/v70/github/repos_attestations.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_autolinks.go b/vendor/github.com/google/go-github/v70/github/repos_autolinks.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_autolinks.go rename to vendor/github.com/google/go-github/v70/github/repos_autolinks.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_codeowners.go b/vendor/github.com/google/go-github/v70/github/repos_codeowners.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_codeowners.go rename to vendor/github.com/google/go-github/v70/github/repos_codeowners.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_collaborators.go b/vendor/github.com/google/go-github/v70/github/repos_collaborators.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_collaborators.go rename to vendor/github.com/google/go-github/v70/github/repos_collaborators.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_comments.go b/vendor/github.com/google/go-github/v70/github/repos_comments.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_comments.go rename to vendor/github.com/google/go-github/v70/github/repos_comments.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_commits.go b/vendor/github.com/google/go-github/v70/github/repos_commits.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_commits.go rename to vendor/github.com/google/go-github/v70/github/repos_commits.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_community_health.go b/vendor/github.com/google/go-github/v70/github/repos_community_health.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_community_health.go rename to vendor/github.com/google/go-github/v70/github/repos_community_health.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_contents.go b/vendor/github.com/google/go-github/v70/github/repos_contents.go similarity index 92% rename from vendor/github.com/google/go-github/v68/github/repos_contents.go rename to vendor/github.com/google/go-github/v70/github/repos_contents.go index 3a0c266b5e..013993e5be 100644 --- a/vendor/github.com/google/go-github/v68/github/repos_contents.go +++ b/vendor/github.com/google/go-github/v70/github/repos_contents.go @@ -254,7 +254,7 @@ func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path return nil, directoryContent, resp, nil } - return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) + return nil, nil, resp, fmt.Errorf("unmarshaling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) } // CreateFile creates a new file in a repository at the given path and returns @@ -348,6 +348,15 @@ func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo st if opts != nil && opts.Ref != "" { u += fmt.Sprintf("/%s", opts.Ref) } + + if s.client.RateLimitRedirectionalEndpoints { + return s.getArchiveLinkWithRateLimit(ctx, u, maxRedirects) + } + + return s.getArchiveLinkWithoutRateLimit(ctx, u, maxRedirects) +} + +func (s *RepositoriesService) getArchiveLinkWithoutRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects) if err != nil { return nil, nil, err @@ -355,7 +364,7 @@ func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo st defer resp.Body.Close() if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusFound { - return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %v", resp.Status) } parsedURL, err := url.Parse(resp.Header.Get("Location")) @@ -365,3 +374,23 @@ func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo st return parsedURL, newResponse(resp), nil } + +func (s *RepositoriesService) getArchiveLinkWithRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) { + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + url, resp, err := s.client.bareDoUntilFound(ctx, req, maxRedirects) + if err != nil { + return nil, resp, err + } + defer resp.Body.Close() + + // If we didn't receive a valid Location in a 302 response + if url == nil { + return nil, resp, fmt.Errorf("unexpected status code: %v", resp.Status) + } + + return url, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go b/vendor/github.com/google/go-github/v70/github/repos_deployment_branch_policies.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_deployment_branch_policies.go rename to vendor/github.com/google/go-github/v70/github/repos_deployment_branch_policies.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go b/vendor/github.com/google/go-github/v70/github/repos_deployment_protection_rules.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_deployment_protection_rules.go rename to vendor/github.com/google/go-github/v70/github/repos_deployment_protection_rules.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_deployments.go b/vendor/github.com/google/go-github/v70/github/repos_deployments.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_deployments.go rename to vendor/github.com/google/go-github/v70/github/repos_deployments.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_environments.go b/vendor/github.com/google/go-github/v70/github/repos_environments.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_environments.go rename to vendor/github.com/google/go-github/v70/github/repos_environments.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_forks.go b/vendor/github.com/google/go-github/v70/github/repos_forks.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_forks.go rename to vendor/github.com/google/go-github/v70/github/repos_forks.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks.go b/vendor/github.com/google/go-github/v70/github/repos_hooks.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_hooks.go rename to vendor/github.com/google/go-github/v70/github/repos_hooks.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go b/vendor/github.com/google/go-github/v70/github/repos_hooks_configuration.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_hooks_configuration.go rename to vendor/github.com/google/go-github/v70/github/repos_hooks_configuration.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go b/vendor/github.com/google/go-github/v70/github/repos_hooks_deliveries.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_hooks_deliveries.go rename to vendor/github.com/google/go-github/v70/github/repos_hooks_deliveries.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_invitations.go b/vendor/github.com/google/go-github/v70/github/repos_invitations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_invitations.go rename to vendor/github.com/google/go-github/v70/github/repos_invitations.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_keys.go b/vendor/github.com/google/go-github/v70/github/repos_keys.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_keys.go rename to vendor/github.com/google/go-github/v70/github/repos_keys.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_lfs.go b/vendor/github.com/google/go-github/v70/github/repos_lfs.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_lfs.go rename to vendor/github.com/google/go-github/v70/github/repos_lfs.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_merging.go b/vendor/github.com/google/go-github/v70/github/repos_merging.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_merging.go rename to vendor/github.com/google/go-github/v70/github/repos_merging.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_pages.go b/vendor/github.com/google/go-github/v70/github/repos_pages.go similarity index 91% rename from vendor/github.com/google/go-github/v68/github/repos_pages.go rename to vendor/github.com/google/go-github/v70/github/repos_pages.go index 6b9ba76e44..930f6000b7 100644 --- a/vendor/github.com/google/go-github/v68/github/repos_pages.go +++ b/vendor/github.com/google/go-github/v70/github/repos_pages.go @@ -170,7 +170,36 @@ func (s *RepositoriesService) UpdatePages(ctx context.Context, owner, repo strin if err != nil { return resp, err } + return resp, nil +} + +// PagesUpdateWithoutCNAME defines parameters for updating a GitHub Pages site on GitHub Enterprise Servers. +// Sending a request with a CNAME (any value, empty string, or null) results in a 400 error: "Custom domains are not available for GitHub Pages". +type PagesUpdateWithoutCNAME struct { + BuildType *string `json:"build_type,omitempty"` + Source *PagesSource `json:"source,omitempty"` + Public *bool `json:"public,omitempty"` + HTTPSEnforced *bool `json:"https_enforced,omitempty"` +} + +// UpdatePagesGHES updates GitHub Pages for the named repo in GitHub Enterprise Servers. +// +// GitHub API docs: https://docs.github.com/rest/pages/pages#update-information-about-a-github-pages-site +// +//meta:operation PUT /repos/{owner}/{repo}/pages +func (s *RepositoriesService) UpdatePagesGHES(ctx context.Context, owner, repo string, opts *PagesUpdateWithoutCNAME) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } return resp, nil } diff --git a/vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go b/vendor/github.com/google/go-github/v70/github/repos_prereceive_hooks.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_prereceive_hooks.go rename to vendor/github.com/google/go-github/v70/github/repos_prereceive_hooks.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_properties.go b/vendor/github.com/google/go-github/v70/github/repos_properties.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_properties.go rename to vendor/github.com/google/go-github/v70/github/repos_properties.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_releases.go b/vendor/github.com/google/go-github/v70/github/repos_releases.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_releases.go rename to vendor/github.com/google/go-github/v70/github/repos_releases.go diff --git a/vendor/github.com/google/go-github/v70/github/repos_rules.go b/vendor/github.com/google/go-github/v70/github/repos_rules.go new file mode 100644 index 0000000000..d38e35cdd7 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/repos_rules.go @@ -0,0 +1,227 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// rulesetNoOmitBypassActors represents a GitHub ruleset object. The struct does not omit bypassActors if the field is nil or an empty array is passed. +type rulesetNoOmitBypassActors struct { + ID *int64 `json:"id,omitempty"` + Name string `json:"name"` + Target *RulesetTarget `json:"target,omitempty"` + SourceType *RulesetSourceType `json:"source_type,omitempty"` + Source string `json:"source"` + Enforcement RulesetEnforcement `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors"` + CurrentUserCanBypass *BypassMode `json:"current_user_can_bypass,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Links *RepositoryRulesetLinks `json:"_links,omitempty"` + Conditions *RepositoryRulesetConditions `json:"conditions,omitempty"` + Rules *RepositoryRulesetRules `json:"rules,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +// rulesetClearBypassActors is used to clear the bypass actors when modifying a GitHub ruleset object. +type rulesetClearBypassActors struct { + BypassActors []*BypassActor `json:"bypass_actors"` +} + +// GetRulesForBranch gets all the repository rules that apply to the specified branch. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-rules-for-a-branch +// +//meta:operation GET /repos/{owner}/{repo}/rules/branches/{branch} +func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string) (*BranchRules, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rules *BranchRules + resp, err := s.client.Do(ctx, req, &rules) + if err != nil { + return nil, resp, err + } + + return rules, resp, nil +} + +// GetAllRulesets gets all the repository rulesets for the specified repository. +// If includesParents is true, rulesets configured at the organization or enterprise level that apply to the repository will be returned. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-all-repository-rulesets +// +//meta:operation GET /repos/{owner}/{repo}/rulesets +func (s *RepositoriesService) GetAllRulesets(ctx context.Context, owner, repo string, includesParents bool) ([]*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets?includes_parents=%v", owner, repo, includesParents) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset []*RepositoryRuleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// CreateRuleset creates a repository ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#create-a-repository-ruleset +// +//meta:operation POST /repos/{owner}/{repo}/rulesets +func (s *RepositoriesService) CreateRuleset(ctx context.Context, owner, repo string, ruleset RepositoryRuleset) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets", owner, repo) + + req, err := s.client.NewRequest("POST", u, ruleset) + if err != nil { + return nil, nil, err + } + + var rs *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// GetRuleset gets a repository ruleset for the specified repository. +// If includesParents is true, rulesets configured at the organization or enterprise level that apply to the repository will be returned. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#get-a-repository-ruleset +// +//meta:operation GET /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v?includes_parents=%v", owner, repo, rulesetID, includesParents) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var ruleset *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &ruleset) + if err != nil { + return nil, resp, err + } + + return ruleset, resp, nil +} + +// UpdateRuleset updates a repository ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, ruleset RepositoryRuleset) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + req, err := s.client.NewRequest("PUT", u, ruleset) + if err != nil { + return nil, nil, err + } + + var rs *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// UpdateRulesetClearBypassActor clears the bypass actors for a repository ruleset for the specified repository. +// +// This function is necessary as the UpdateRuleset function does not marshal ByPassActor if passed as an empty array. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRulesetClearBypassActor(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + rsClearBypassActor := rulesetClearBypassActors{} + + req, err := s.client.NewRequest("PUT", u, rsClearBypassActor) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// UpdateRulesetNoBypassActor updates a repository ruleset for the specified repository. +// +// This function is necessary as the UpdateRuleset function does not marshal ByPassActor if passed as an empty array. +// +// Deprecated: Use UpdateRulesetClearBypassActor instead. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRulesetNoBypassActor(ctx context.Context, owner, repo string, rulesetID int64, ruleset RepositoryRuleset) (*RepositoryRuleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + rsNoBypassActor := rulesetNoOmitBypassActors{ + ID: ruleset.ID, + Name: ruleset.Name, + Target: ruleset.Target, + SourceType: ruleset.SourceType, + Source: ruleset.Source, + Enforcement: ruleset.Enforcement, + BypassActors: ruleset.BypassActors, + NodeID: ruleset.NodeID, + Links: ruleset.Links, + Conditions: ruleset.Conditions, + Rules: ruleset.Rules, + } + + req, err := s.client.NewRequest("PUT", u, rsNoBypassActor) + if err != nil { + return nil, nil, err + } + + var rs *RepositoryRuleset + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// DeleteRuleset deletes a repository ruleset for the specified repository. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset +// +//meta:operation DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v68/github/repos_stats.go b/vendor/github.com/google/go-github/v70/github/repos_stats.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_stats.go rename to vendor/github.com/google/go-github/v70/github/repos_stats.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_statuses.go b/vendor/github.com/google/go-github/v70/github/repos_statuses.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_statuses.go rename to vendor/github.com/google/go-github/v70/github/repos_statuses.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_tags.go b/vendor/github.com/google/go-github/v70/github/repos_tags.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_tags.go rename to vendor/github.com/google/go-github/v70/github/repos_tags.go diff --git a/vendor/github.com/google/go-github/v68/github/repos_traffic.go b/vendor/github.com/google/go-github/v70/github/repos_traffic.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/repos_traffic.go rename to vendor/github.com/google/go-github/v70/github/repos_traffic.go diff --git a/vendor/github.com/google/go-github/v70/github/rules.go b/vendor/github.com/google/go-github/v70/github/rules.go new file mode 100644 index 0000000000..985f0aac10 --- /dev/null +++ b/vendor/github.com/google/go-github/v70/github/rules.go @@ -0,0 +1,1208 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" + "reflect" +) + +// RulesetTarget represents a GitHub ruleset target. +type RulesetTarget string + +// This is the set of GitHub ruleset targets. +const ( + RulesetTargetBranch RulesetTarget = "branch" + RulesetTargetTag RulesetTarget = "tag" + RulesetTargetPush RulesetTarget = "push" +) + +// RulesetSourceType represents a GitHub ruleset source type. +type RulesetSourceType string + +// This is the set of GitHub ruleset source types. +const ( + RulesetSourceTypeRepository RulesetSourceType = "Repository" + RulesetSourceTypeOrganization RulesetSourceType = "Organization" + RulesetSourceTypeEnterprise RulesetSourceType = "Enterprise" +) + +// RulesetEnforcement represents a GitHub ruleset enforcement. +type RulesetEnforcement string + +// This is the set of GitHub ruleset enforcements. +const ( + RulesetEnforcementDisabled RulesetEnforcement = "disabled" + RulesetEnforcementActive RulesetEnforcement = "active" + RulesetEnforcementEvaluate RulesetEnforcement = "evaluate" +) + +// BypassActorType represents a GitHub ruleset bypass actor type. +type BypassActorType string + +// This is the set of GitHub ruleset bypass actor types. +const ( + BypassActorTypeIntegration BypassActorType = "Integration" + BypassActorTypeOrganizationAdmin BypassActorType = "OrganizationAdmin" + BypassActorTypeRepositoryRole BypassActorType = "RepositoryRole" + BypassActorTypeTeam BypassActorType = "Team" + BypassActorTypeDeployKey BypassActorType = "DeployKey" +) + +// BypassMode represents a GitHub ruleset bypass mode. +type BypassMode string + +// This is the set of GitHub ruleset bypass modes. +const ( + BypassModeAlways BypassMode = "always" + BypassModePullRequest BypassMode = "pull_request" + BypassModeNever BypassMode = "never" +) + +// RepositoryRuleType represents a GitHub ruleset rule type. +type RepositoryRuleType string + +// This is the set of GitHub ruleset rule types. +const ( + RulesetRuleTypeCreation RepositoryRuleType = "creation" + RulesetRuleTypeUpdate RepositoryRuleType = "update" + RulesetRuleTypeDeletion RepositoryRuleType = "deletion" + RulesetRuleTypeRequiredLinearHistory RepositoryRuleType = "required_linear_history" + RulesetRuleTypeMergeQueue RepositoryRuleType = "merge_queue" + RulesetRuleTypeRequiredDeployments RepositoryRuleType = "required_deployments" + RulesetRuleTypeRequiredSignatures RepositoryRuleType = "required_signatures" + RulesetRuleTypePullRequest RepositoryRuleType = "pull_request" + RulesetRuleTypeRequiredStatusChecks RepositoryRuleType = "required_status_checks" + RulesetRuleTypeNonFastForward RepositoryRuleType = "non_fast_forward" + RulesetRuleTypeCommitMessagePattern RepositoryRuleType = "commit_message_pattern" + RulesetRuleTypeCommitAuthorEmailPattern RepositoryRuleType = "commit_author_email_pattern" + RulesetRuleTypeCommitterEmailPattern RepositoryRuleType = "committer_email_pattern" + RulesetRuleTypeBranchNamePattern RepositoryRuleType = "branch_name_pattern" + RulesetRuleTypeTagNamePattern RepositoryRuleType = "tag_name_pattern" + RulesetRuleTypeFilePathRestriction RepositoryRuleType = "file_path_restriction" + RulesetRuleTypeMaxFilePathLength RepositoryRuleType = "max_file_path_length" + RulesetRuleTypeFileExtensionRestriction RepositoryRuleType = "file_extension_restriction" + RulesetRuleTypeMaxFileSize RepositoryRuleType = "max_file_size" + RulesetRuleTypeWorkflows RepositoryRuleType = "workflows" + RulesetRuleTypeCodeScanning RepositoryRuleType = "code_scanning" +) + +// MergeGroupingStrategy models a GitHub merge grouping strategy. +type MergeGroupingStrategy string + +// This is the set of GitHub merge grouping strategies. +const ( + MergeGroupingStrategyAllGreen MergeGroupingStrategy = "ALLGREEN" + MergeGroupingStrategyHeadGreen MergeGroupingStrategy = "HEADGREEN" +) + +// MergeMethod models a GitHub merge method. +type MergeMethod string + +// This is the set of GitHub merge methods. +const ( + MergeMethodMerge MergeMethod = "merge" + MergeMethodRebase MergeMethod = "rebase" + MergeMethodSquash MergeMethod = "squash" +) + +// PatternRuleOperator models a GitHub pattern rule operator. +type PatternRuleOperator string + +// This is the set of GitHub pattern rule operators. +const ( + PatternRuleOperatorStartsWith PatternRuleOperator = "starts_with" + PatternRuleOperatorEndsWith PatternRuleOperator = "ends_with" + PatternRuleOperatorContains PatternRuleOperator = "contains" + PatternRuleOperatorRegex PatternRuleOperator = "regex" +) + +// CodeScanningAlertsThreshold models a GitHub code scanning alerts threshold. +type CodeScanningAlertsThreshold string + +// This is the set of GitHub code scanning alerts thresholds. +const ( + CodeScanningAlertsThresholdNone CodeScanningAlertsThreshold = "none" + CodeScanningAlertsThresholdErrors CodeScanningAlertsThreshold = "errors" + CodeScanningAlertsThresholdErrorsAndWarnings CodeScanningAlertsThreshold = "errors_and_warnings" + CodeScanningAlertsThresholdAll CodeScanningAlertsThreshold = "all" +) + +// CodeScanningSecurityAlertsThreshold models a GitHub code scanning security alerts threshold. +type CodeScanningSecurityAlertsThreshold string + +// This is the set of GitHub code scanning security alerts thresholds. +const ( + CodeScanningSecurityAlertsThresholdNone CodeScanningSecurityAlertsThreshold = "none" + CodeScanningSecurityAlertsThresholdCritical CodeScanningSecurityAlertsThreshold = "critical" + CodeScanningSecurityAlertsThresholdHighOrHigher CodeScanningSecurityAlertsThreshold = "high_or_higher" + CodeScanningSecurityAlertsThresholdMediumOrHigher CodeScanningSecurityAlertsThreshold = "medium_or_higher" + CodeScanningSecurityAlertsThresholdAll CodeScanningSecurityAlertsThreshold = "all" +) + +// RepositoryRuleset represents a GitHub ruleset object. +type RepositoryRuleset struct { + ID *int64 `json:"id,omitempty"` + Name string `json:"name"` + Target *RulesetTarget `json:"target,omitempty"` + SourceType *RulesetSourceType `json:"source_type,omitempty"` + Source string `json:"source"` + Enforcement RulesetEnforcement `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors,omitempty"` + CurrentUserCanBypass *BypassMode `json:"current_user_can_bypass,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Links *RepositoryRulesetLinks `json:"_links,omitempty"` + Conditions *RepositoryRulesetConditions `json:"conditions,omitempty"` + Rules *RepositoryRulesetRules `json:"rules,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +// BypassActor represents the bypass actors from a ruleset. +type BypassActor struct { + ActorID *int64 `json:"actor_id,omitempty"` + ActorType *BypassActorType `json:"actor_type,omitempty"` + BypassMode *BypassMode `json:"bypass_mode,omitempty"` +} + +// RepositoryRulesetLinks represents the "_links" object in a Ruleset. +type RepositoryRulesetLinks struct { + Self *RepositoryRulesetLink `json:"self,omitempty"` + HTML *RepositoryRulesetLink `json:"html,omitempty"` +} + +// RepositoryRulesetLink represents a single link object from GitHub ruleset request _links. +type RepositoryRulesetLink struct { + HRef *string `json:"href,omitempty"` +} + +// RepositoryRulesetConditions represents the conditions object in a ruleset. +// Set either RepositoryName or RepositoryID or RepositoryProperty, not more than one. +type RepositoryRulesetConditions struct { + RefName *RepositoryRulesetRefConditionParameters `json:"ref_name,omitempty"` + RepositoryID *RepositoryRulesetRepositoryIDsConditionParameters `json:"repository_id,omitempty"` + RepositoryName *RepositoryRulesetRepositoryNamesConditionParameters `json:"repository_name,omitempty"` + RepositoryProperty *RepositoryRulesetRepositoryPropertyConditionParameters `json:"repository_property,omitempty"` + OrganizationID *RepositoryRulesetOrganizationIDsConditionParameters `json:"organization_id,omitempty"` + OrganizationName *RepositoryRulesetOrganizationNamesConditionParameters `json:"organization_name,omitempty"` +} + +// RepositoryRulesetRefConditionParameters represents the conditions object for ref_names. +type RepositoryRulesetRefConditionParameters struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` +} + +// RepositoryRulesetRepositoryIDsConditionParameters represents the conditions object for repository_id. +type RepositoryRulesetRepositoryIDsConditionParameters struct { + RepositoryIDs []int64 `json:"repository_ids,omitempty"` +} + +// RepositoryRulesetRepositoryNamesConditionParameters represents the conditions object for repository_name. +type RepositoryRulesetRepositoryNamesConditionParameters struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` + Protected *bool `json:"protected,omitempty"` +} + +// RepositoryRulesetRepositoryPropertyConditionParameters represents the conditions object for repository_property. +type RepositoryRulesetRepositoryPropertyConditionParameters struct { + Include []*RepositoryRulesetRepositoryPropertyTargetParameters `json:"include"` + Exclude []*RepositoryRulesetRepositoryPropertyTargetParameters `json:"exclude"` +} + +// RepositoryRulesetRepositoryPropertyTargetParameters represents a repository_property name and values to be used for targeting. +type RepositoryRulesetRepositoryPropertyTargetParameters struct { + Name string `json:"name"` + PropertyValues []string `json:"property_values"` + Source *string `json:"source,omitempty"` +} + +// RepositoryRulesetOrganizationIDsConditionParameters represents the conditions object for organization_id. +type RepositoryRulesetOrganizationIDsConditionParameters struct { + OrganizationIDs []int64 `json:"organization_ids,omitempty"` +} + +// RepositoryRulesetOrganizationNamesConditionParameters represents the conditions object for organization_name. +type RepositoryRulesetOrganizationNamesConditionParameters struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` +} + +// RepositoryRule represents a GitHub ruleset rule object. +type RepositoryRule struct { + Type RepositoryRuleType `json:"type"` + Parameters any `json:"parameters,omitempty"` +} + +// RepositoryRulesetRules represents a GitHub ruleset rules object. +// This type doesn't have JSON annotations as it uses custom marshaling. +type RepositoryRulesetRules struct { + Creation *EmptyRuleParameters + Update *UpdateRuleParameters + Deletion *EmptyRuleParameters + RequiredLinearHistory *EmptyRuleParameters + MergeQueue *MergeQueueRuleParameters + RequiredDeployments *RequiredDeploymentsRuleParameters + RequiredSignatures *EmptyRuleParameters + PullRequest *PullRequestRuleParameters + RequiredStatusChecks *RequiredStatusChecksRuleParameters + NonFastForward *EmptyRuleParameters + CommitMessagePattern *PatternRuleParameters + CommitAuthorEmailPattern *PatternRuleParameters + CommitterEmailPattern *PatternRuleParameters + BranchNamePattern *PatternRuleParameters + TagNamePattern *PatternRuleParameters + FilePathRestriction *FilePathRestrictionRuleParameters + MaxFilePathLength *MaxFilePathLengthRuleParameters + FileExtensionRestriction *FileExtensionRestrictionRuleParameters + MaxFileSize *MaxFileSizeRuleParameters + Workflows *WorkflowsRuleParameters + CodeScanning *CodeScanningRuleParameters +} + +// BranchRules represents the rules active for a GitHub repository branch. +// This type doesn't have JSON annotations as it uses custom marshaling. +type BranchRules struct { + Creation []*BranchRuleMetadata + Update []*UpdateBranchRule + Deletion []*BranchRuleMetadata + RequiredLinearHistory []*BranchRuleMetadata + MergeQueue []*MergeQueueBranchRule + RequiredDeployments []*RequiredDeploymentsBranchRule + RequiredSignatures []*BranchRuleMetadata + PullRequest []*PullRequestBranchRule + RequiredStatusChecks []*RequiredStatusChecksBranchRule + NonFastForward []*BranchRuleMetadata + CommitMessagePattern []*PatternBranchRule + CommitAuthorEmailPattern []*PatternBranchRule + CommitterEmailPattern []*PatternBranchRule + BranchNamePattern []*PatternBranchRule + TagNamePattern []*PatternBranchRule + FilePathRestriction []*FilePathRestrictionBranchRule + MaxFilePathLength []*MaxFilePathLengthBranchRule + FileExtensionRestriction []*FileExtensionRestrictionBranchRule + MaxFileSize []*MaxFileSizeBranchRule + Workflows []*WorkflowsBranchRule + CodeScanning []*CodeScanningBranchRule +} + +// BranchRuleMetadata represents the metadata for a branch rule. +type BranchRuleMetadata struct { + RulesetSourceType RulesetSourceType `json:"ruleset_source_type"` + RulesetSource string `json:"ruleset_source"` + RulesetID int64 `json:"ruleset_id"` +} + +// UpdateBranchRule represents an update branch rule. +type UpdateBranchRule struct { + BranchRuleMetadata + Parameters UpdateRuleParameters `json:"parameters"` +} + +// MergeQueueBranchRule represents a merge queue branch rule. +type MergeQueueBranchRule struct { + BranchRuleMetadata + Parameters MergeQueueRuleParameters `json:"parameters"` +} + +// RequiredDeploymentsBranchRule represents a required deployments branch rule. +type RequiredDeploymentsBranchRule struct { + BranchRuleMetadata + Parameters RequiredDeploymentsRuleParameters `json:"parameters"` +} + +// PullRequestBranchRule represents a pull request branch rule. +type PullRequestBranchRule struct { + BranchRuleMetadata + Parameters PullRequestRuleParameters `json:"parameters"` +} + +// RequiredStatusChecksBranchRule represents a required status checks branch rule. +type RequiredStatusChecksBranchRule struct { + BranchRuleMetadata + Parameters RequiredStatusChecksRuleParameters `json:"parameters"` +} + +// PatternBranchRule represents a pattern branch rule. +type PatternBranchRule struct { + BranchRuleMetadata + Parameters PatternRuleParameters `json:"parameters"` +} + +// FilePathRestrictionBranchRule represents a file path restriction branch rule. +type FilePathRestrictionBranchRule struct { + BranchRuleMetadata + Parameters FilePathRestrictionRuleParameters `json:"parameters"` +} + +// MaxFilePathLengthBranchRule represents a max file path length branch rule. +type MaxFilePathLengthBranchRule struct { + BranchRuleMetadata + Parameters MaxFilePathLengthRuleParameters `json:"parameters"` +} + +// FileExtensionRestrictionBranchRule represents a file extension restriction branch rule. +type FileExtensionRestrictionBranchRule struct { + BranchRuleMetadata + Parameters FileExtensionRestrictionRuleParameters `json:"parameters"` +} + +// MaxFileSizeBranchRule represents a max file size branch rule. +type MaxFileSizeBranchRule struct { + BranchRuleMetadata + Parameters MaxFileSizeRuleParameters `json:"parameters"` +} + +// WorkflowsBranchRule represents a workflows branch rule. +type WorkflowsBranchRule struct { + BranchRuleMetadata + Parameters WorkflowsRuleParameters `json:"parameters"` +} + +// CodeScanningBranchRule represents a code scanning branch rule. +type CodeScanningBranchRule struct { + BranchRuleMetadata + Parameters CodeScanningRuleParameters `json:"parameters"` +} + +// EmptyRuleParameters represents the parameters for a rule with no options. +type EmptyRuleParameters struct{} + +// UpdateRuleParameters represents the update rule parameters. +type UpdateRuleParameters struct { + UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge,omitempty"` +} + +// MergeQueueRuleParameters represents the merge_queue rule parameters. +type MergeQueueRuleParameters struct { + CheckResponseTimeoutMinutes int `json:"check_response_timeout_minutes"` + GroupingStrategy MergeGroupingStrategy `json:"grouping_strategy"` + MaxEntriesToBuild int `json:"max_entries_to_build"` + MaxEntriesToMerge int `json:"max_entries_to_merge"` + MergeMethod MergeMethod `json:"merge_method"` + MinEntriesToMerge int `json:"min_entries_to_merge"` + MinEntriesToMergeWaitMinutes int `json:"min_entries_to_merge_wait_minutes"` +} + +// RequiredDeploymentsRuleParameters represents the required deployments rule parameters. +type RequiredDeploymentsRuleParameters struct { + RequiredDeploymentEnvironments []string `json:"required_deployment_environments"` +} + +// PullRequestRuleParameters represents the pull_request rule parameters. +type PullRequestRuleParameters struct { + AllowedMergeMethods []MergeMethod `json:"allowed_merge_methods"` + AutomaticCopilotCodeReviewEnabled *bool `json:"automatic_copilot_code_review_enabled,omitempty"` + DismissStaleReviewsOnPush bool `json:"dismiss_stale_reviews_on_push"` + RequireCodeOwnerReview bool `json:"require_code_owner_review"` + RequireLastPushApproval bool `json:"require_last_push_approval"` + RequiredApprovingReviewCount int `json:"required_approving_review_count"` + RequiredReviewThreadResolution bool `json:"required_review_thread_resolution"` +} + +// RequiredStatusChecksRuleParameters represents the required status checks rule parameters. +type RequiredStatusChecksRuleParameters struct { + DoNotEnforceOnCreate *bool `json:"do_not_enforce_on_create,omitempty"` + RequiredStatusChecks []*RuleStatusCheck `json:"required_status_checks"` + StrictRequiredStatusChecksPolicy bool `json:"strict_required_status_checks_policy"` +} + +// RuleStatusCheck represents a status checks for the required status checks rule parameters. +type RuleStatusCheck struct { + Context string `json:"context"` + IntegrationID *int64 `json:"integration_id,omitempty"` +} + +// PatternRuleParameters represents the parameters for a pattern rule. +type PatternRuleParameters struct { + Name *string `json:"name,omitempty"` + // If Negate is true, the rule will fail if the pattern matches. + Negate *bool `json:"negate,omitempty"` + Operator PatternRuleOperator `json:"operator"` + Pattern string `json:"pattern"` +} + +// FilePathRestrictionRuleParameters represents the file path restriction rule parameters. +type FilePathRestrictionRuleParameters struct { + RestrictedFilePaths []string `json:"restricted_file_paths"` +} + +// MaxFilePathLengthRuleParameters represents the max file path length rule parameters. +type MaxFilePathLengthRuleParameters struct { + MaxFilePathLength int `json:"max_file_path_length"` +} + +// FileExtensionRestrictionRuleParameters represents the file extension restriction rule parameters. +type FileExtensionRestrictionRuleParameters struct { + RestrictedFileExtensions []string `json:"restricted_file_extensions"` +} + +// MaxFileSizeRuleParameters represents the max file size rule parameters. +type MaxFileSizeRuleParameters struct { + MaxFileSize int64 `json:"max_file_size"` +} + +// WorkflowsRuleParameters represents the workflows rule parameters. +type WorkflowsRuleParameters struct { + DoNotEnforceOnCreate *bool `json:"do_not_enforce_on_create,omitempty"` + Workflows []*RuleWorkflow `json:"workflows"` +} + +// RuleWorkflow represents a Workflow for the workflows rule parameters. +type RuleWorkflow struct { + Path string `json:"path"` + Ref *string `json:"ref,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + SHA *string `json:"sha,omitempty"` +} + +// CodeScanningRuleParameters represents the code scanning rule parameters. +type CodeScanningRuleParameters struct { + CodeScanningTools []*RuleCodeScanningTool `json:"code_scanning_tools"` +} + +// RuleCodeScanningTool represents a single code scanning tool for the code scanning parameters. +type RuleCodeScanningTool struct { + AlertsThreshold CodeScanningAlertsThreshold `json:"alerts_threshold"` + SecurityAlertsThreshold CodeScanningSecurityAlertsThreshold `json:"security_alerts_threshold"` + Tool string `json:"tool"` +} + +// repositoryRulesetRuleWrapper is a helper type to marshal & unmarshal a ruleset rule. +type repositoryRulesetRuleWrapper struct { + Type RepositoryRuleType `json:"type"` + Parameters json.RawMessage `json:"parameters,omitempty"` +} + +// MarshalJSON is a custom JSON marshaler for RulesetRules. +func (r *RepositoryRulesetRules) MarshalJSON() ([]byte, error) { + // The RepositoryRulesetRules type marshals to between 1 and 21 rules. + // If new rules are added to RepositoryRulesetRules the capacity below needs increasing + rawRules := make([]json.RawMessage, 0, 21) + + if r.Creation != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeCreation, r.Creation) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.Update != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeUpdate, r.Update) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.Deletion != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeDeletion, r.Deletion) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.RequiredLinearHistory != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeRequiredLinearHistory, r.RequiredLinearHistory) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.MergeQueue != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeMergeQueue, r.MergeQueue) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.RequiredDeployments != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeRequiredDeployments, r.RequiredDeployments) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.RequiredSignatures != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeRequiredSignatures, r.RequiredSignatures) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.PullRequest != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypePullRequest, r.PullRequest) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.RequiredStatusChecks != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeRequiredStatusChecks, r.RequiredStatusChecks) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.NonFastForward != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeNonFastForward, r.NonFastForward) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.CommitMessagePattern != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeCommitMessagePattern, r.CommitMessagePattern) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.CommitAuthorEmailPattern != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeCommitAuthorEmailPattern, r.CommitAuthorEmailPattern) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.CommitterEmailPattern != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeCommitterEmailPattern, r.CommitterEmailPattern) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.BranchNamePattern != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeBranchNamePattern, r.BranchNamePattern) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.TagNamePattern != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeTagNamePattern, r.TagNamePattern) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.FilePathRestriction != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeFilePathRestriction, r.FilePathRestriction) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.MaxFilePathLength != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeMaxFilePathLength, r.MaxFilePathLength) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.FileExtensionRestriction != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeFileExtensionRestriction, r.FileExtensionRestriction) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.MaxFileSize != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeMaxFileSize, r.MaxFileSize) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.Workflows != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeWorkflows, r.Workflows) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + if r.CodeScanning != nil { + bytes, err := marshalRepositoryRulesetRule(RulesetRuleTypeCodeScanning, r.CodeScanning) + if err != nil { + return nil, err + } + rawRules = append(rawRules, json.RawMessage(bytes)) + } + + return json.Marshal(rawRules) +} + +// marshalRepositoryRulesetRule is a helper function to marshal a ruleset rule. +// +// TODO: Benchmark the code that uses reflection. +// TODO: Use a generator here instead of reflection if there is a significant performance hit. +func marshalRepositoryRulesetRule[T any](t RepositoryRuleType, params T) ([]byte, error) { + paramsType := reflect.TypeFor[T]() + + if paramsType.Kind() == reflect.Pointer && (reflect.ValueOf(params).IsNil() || reflect.ValueOf(params).Elem().IsZero()) { + return json.Marshal(repositoryRulesetRuleWrapper{Type: t}) + } + + bytes, err := json.Marshal(params) + if err != nil { + return nil, err + } + + return json.Marshal(repositoryRulesetRuleWrapper{Type: t, Parameters: json.RawMessage(bytes)}) +} + +// UnmarshalJSON is a custom JSON unmarshaler for RulesetRules. +func (r *RepositoryRulesetRules) UnmarshalJSON(data []byte) error { + var wrappers []*repositoryRulesetRuleWrapper + + if err := json.Unmarshal(data, &wrappers); err != nil { + return err + } + + for _, w := range wrappers { + switch w.Type { + case RulesetRuleTypeCreation: + r.Creation = &EmptyRuleParameters{} + case RulesetRuleTypeUpdate: + r.Update = &UpdateRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.Update); err != nil { + return err + } + } + case RulesetRuleTypeDeletion: + r.Deletion = &EmptyRuleParameters{} + case RulesetRuleTypeRequiredLinearHistory: + r.RequiredLinearHistory = &EmptyRuleParameters{} + case RulesetRuleTypeMergeQueue: + r.MergeQueue = &MergeQueueRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.MergeQueue); err != nil { + return err + } + } + case RulesetRuleTypeRequiredDeployments: + r.RequiredDeployments = &RequiredDeploymentsRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.RequiredDeployments); err != nil { + return err + } + } + case RulesetRuleTypeRequiredSignatures: + r.RequiredSignatures = &EmptyRuleParameters{} + case RulesetRuleTypePullRequest: + r.PullRequest = &PullRequestRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.PullRequest); err != nil { + return err + } + } + case RulesetRuleTypeRequiredStatusChecks: + r.RequiredStatusChecks = &RequiredStatusChecksRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.RequiredStatusChecks); err != nil { + return err + } + } + case RulesetRuleTypeNonFastForward: + r.NonFastForward = &EmptyRuleParameters{} + case RulesetRuleTypeCommitMessagePattern: + r.CommitMessagePattern = &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.CommitMessagePattern); err != nil { + return err + } + } + case RulesetRuleTypeCommitAuthorEmailPattern: + r.CommitAuthorEmailPattern = &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.CommitAuthorEmailPattern); err != nil { + return err + } + } + case RulesetRuleTypeCommitterEmailPattern: + r.CommitterEmailPattern = &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.CommitterEmailPattern); err != nil { + return err + } + } + case RulesetRuleTypeBranchNamePattern: + r.BranchNamePattern = &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.BranchNamePattern); err != nil { + return err + } + } + case RulesetRuleTypeTagNamePattern: + r.TagNamePattern = &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.TagNamePattern); err != nil { + return err + } + } + case RulesetRuleTypeFilePathRestriction: + r.FilePathRestriction = &FilePathRestrictionRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.FilePathRestriction); err != nil { + return err + } + } + case RulesetRuleTypeMaxFilePathLength: + r.MaxFilePathLength = &MaxFilePathLengthRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.MaxFilePathLength); err != nil { + return err + } + } + case RulesetRuleTypeFileExtensionRestriction: + r.FileExtensionRestriction = &FileExtensionRestrictionRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.FileExtensionRestriction); err != nil { + return err + } + } + case RulesetRuleTypeMaxFileSize: + r.MaxFileSize = &MaxFileSizeRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.MaxFileSize); err != nil { + return err + } + } + case RulesetRuleTypeWorkflows: + r.Workflows = &WorkflowsRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.Workflows); err != nil { + return err + } + } + case RulesetRuleTypeCodeScanning: + r.CodeScanning = &CodeScanningRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, r.CodeScanning); err != nil { + return err + } + } + } + } + + return nil +} + +// branchRuleWrapper is a helper type to unmarshal a branch rule. +type branchRuleWrapper struct { + Type RepositoryRuleType `json:"type"` + BranchRuleMetadata + Parameters json.RawMessage `json:"parameters,omitempty"` +} + +// UnmarshalJSON is a custom JSON unmarshaler for BranchRules. +func (r *BranchRules) UnmarshalJSON(data []byte) error { + var wrappers []*branchRuleWrapper + + if err := json.Unmarshal(data, &wrappers); err != nil { + return err + } + + for _, w := range wrappers { + switch w.Type { + case RulesetRuleTypeCreation: + r.Creation = append(r.Creation, &BranchRuleMetadata{RulesetSourceType: w.RulesetSourceType, RulesetSource: w.RulesetSource, RulesetID: w.RulesetID}) + case RulesetRuleTypeUpdate: + params := &UpdateRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.Update = append(r.Update, &UpdateBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeDeletion: + r.Deletion = append(r.Deletion, &BranchRuleMetadata{RulesetSourceType: w.RulesetSourceType, RulesetSource: w.RulesetSource, RulesetID: w.RulesetID}) + case RulesetRuleTypeRequiredLinearHistory: + r.RequiredLinearHistory = append(r.RequiredLinearHistory, &BranchRuleMetadata{RulesetSourceType: w.RulesetSourceType, RulesetSource: w.RulesetSource, RulesetID: w.RulesetID}) + case RulesetRuleTypeMergeQueue: + params := &MergeQueueRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.MergeQueue = append(r.MergeQueue, &MergeQueueBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeRequiredDeployments: + params := &RequiredDeploymentsRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.RequiredDeployments = append(r.RequiredDeployments, &RequiredDeploymentsBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeRequiredSignatures: + r.RequiredSignatures = append(r.RequiredSignatures, &BranchRuleMetadata{RulesetSourceType: w.RulesetSourceType, RulesetSource: w.RulesetSource, RulesetID: w.RulesetID}) + case RulesetRuleTypePullRequest: + params := &PullRequestRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.PullRequest = append(r.PullRequest, &PullRequestBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeRequiredStatusChecks: + params := &RequiredStatusChecksRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.RequiredStatusChecks = append(r.RequiredStatusChecks, &RequiredStatusChecksBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeNonFastForward: + r.NonFastForward = append(r.NonFastForward, &BranchRuleMetadata{RulesetSourceType: w.RulesetSourceType, RulesetSource: w.RulesetSource, RulesetID: w.RulesetID}) + case RulesetRuleTypeCommitMessagePattern: + params := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.CommitMessagePattern = append(r.CommitMessagePattern, &PatternBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeCommitAuthorEmailPattern: + params := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.CommitAuthorEmailPattern = append(r.CommitAuthorEmailPattern, &PatternBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeCommitterEmailPattern: + params := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.CommitterEmailPattern = append(r.CommitterEmailPattern, &PatternBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeBranchNamePattern: + params := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.BranchNamePattern = append(r.BranchNamePattern, &PatternBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeTagNamePattern: + params := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.TagNamePattern = append(r.TagNamePattern, &PatternBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeFilePathRestriction: + params := &FilePathRestrictionRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.FilePathRestriction = append(r.FilePathRestriction, &FilePathRestrictionBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeMaxFilePathLength: + params := &MaxFilePathLengthRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.MaxFilePathLength = append(r.MaxFilePathLength, &MaxFilePathLengthBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeFileExtensionRestriction: + params := &FileExtensionRestrictionRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.FileExtensionRestriction = append(r.FileExtensionRestriction, &FileExtensionRestrictionBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeMaxFileSize: + params := &MaxFileSizeRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.MaxFileSize = append(r.MaxFileSize, &MaxFileSizeBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeWorkflows: + params := &WorkflowsRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.Workflows = append(r.Workflows, &WorkflowsBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + case RulesetRuleTypeCodeScanning: + params := &CodeScanningRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, params); err != nil { + return err + } + } + + r.CodeScanning = append(r.CodeScanning, &CodeScanningBranchRule{BranchRuleMetadata: w.BranchRuleMetadata, Parameters: *params}) + } + } + + return nil +} + +// UnmarshalJSON is a custom JSON unmarshaler for RulesetRule. +func (r *RepositoryRule) UnmarshalJSON(data []byte) error { + w := repositoryRulesetRuleWrapper{} + + if err := json.Unmarshal(data, &w); err != nil { + return err + } + + r.Type = w.Type + + switch r.Type { + case RulesetRuleTypeCreation: + r.Parameters = nil + case RulesetRuleTypeUpdate: + p := &UpdateRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeDeletion: + r.Parameters = nil + case RulesetRuleTypeRequiredLinearHistory: + r.Parameters = nil + case RulesetRuleTypeMergeQueue: + p := &MergeQueueRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeRequiredDeployments: + p := &RequiredDeploymentsRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeRequiredSignatures: + r.Parameters = nil + case RulesetRuleTypePullRequest: + p := &PullRequestRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeRequiredStatusChecks: + p := &RequiredStatusChecksRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeNonFastForward: + r.Parameters = nil + case RulesetRuleTypeCommitMessagePattern: + p := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeCommitAuthorEmailPattern: + p := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeCommitterEmailPattern: + p := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeBranchNamePattern: + p := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeTagNamePattern: + p := &PatternRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeFilePathRestriction: + p := &FilePathRestrictionRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeMaxFilePathLength: + p := &MaxFilePathLengthRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeFileExtensionRestriction: + p := &FileExtensionRestrictionRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeMaxFileSize: + p := &MaxFileSizeRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeWorkflows: + p := &WorkflowsRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + case RulesetRuleTypeCodeScanning: + p := &CodeScanningRuleParameters{} + + if w.Parameters != nil { + if err := json.Unmarshal(w.Parameters, p); err != nil { + return err + } + } + + r.Parameters = p + } + + return nil +} diff --git a/vendor/github.com/google/go-github/v68/github/scim.go b/vendor/github.com/google/go-github/v70/github/scim.go similarity index 78% rename from vendor/github.com/google/go-github/v68/github/scim.go rename to vendor/github.com/google/go-github/v70/github/scim.go index 4b34c1663c..70f063caa9 100644 --- a/vendor/github.com/google/go-github/v68/github/scim.go +++ b/vendor/github.com/google/go-github/v70/github/scim.go @@ -17,6 +17,26 @@ import ( // GitHub API docs: https://docs.github.com/rest/scim type SCIMService service +// SCIMGroupAttributes represents supported SCIM Group attributes. +// +// GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/enterprise-admin/scim#list-provisioned-scim-groups-for-an-enterprise +type SCIMGroupAttributes struct { + DisplayName *string `json:"displayName,omitempty"` // The name of the group, suitable for display to end-users. (Optional.) + Members []*SCIMDisplayReference `json:"members,omitempty"` // (Optional.) + Schemas []string `json:"schemas,omitempty"` // (Optional.) + ExternalID *string `json:"externalId,omitempty"` // (Optional.) + // Only populated as a result of calling ListSCIMProvisionedIdentitiesOptions: + ID *string `json:"id,omitempty"` + Meta *SCIMMeta `json:"meta,omitempty"` +} + +// SCIMDisplayReference represents a JSON SCIM (System for Cross-domain Identity Management) resource. +type SCIMDisplayReference struct { + Value string `json:"value"` // (Required.) + Ref string `json:"$ref"` // (Required.) + Display *string `json:"display,omitempty"` // (Optional.) +} + // SCIMUserAttributes represents supported SCIM User attributes. // // GitHub API docs: https://docs.github.com/rest/scim#supported-scim-user-attributes @@ -56,6 +76,15 @@ type SCIMMeta struct { Location *string `json:"location,omitempty"` } +// SCIMProvisionedGroups represents the result of calling ListSCIMProvisionedGroupsForEnterprise. +type SCIMProvisionedGroups struct { + Schemas []string `json:"schemas,omitempty"` + TotalResults *int `json:"totalResults,omitempty"` + ItemsPerPage *int `json:"itemsPerPage,omitempty"` + StartIndex *int `json:"startIndex,omitempty"` + Resources []*SCIMGroupAttributes `json:"Resources,omitempty"` +} + // SCIMProvisionedIdentities represents the result of calling ListSCIMProvisionedIdentities. type SCIMProvisionedIdentities struct { Schemas []string `json:"schemas,omitempty"` @@ -217,3 +246,25 @@ func (s *SCIMService) DeleteSCIMUserFromOrg(ctx context.Context, org, scimUserID return s.client.Do(ctx, req, nil) } + +// ListSCIMProvisionedGroupsForEnterprise lists SCIM provisioned groups for an enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/scim#list-provisioned-scim-groups-for-an-enterprise +// +//meta:operation GET /scim/v2/enterprises/{enterprise}/Groups +func (s *SCIMService) ListSCIMProvisionedGroupsForEnterprise(ctx context.Context, enterprise string, opts *ListSCIMProvisionedIdentitiesOptions) (*SCIMProvisionedGroups, *Response, error) { + u := fmt.Sprintf("scim/v2/enterprises/%v/Groups", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(SCIMProvisionedGroups) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} diff --git a/vendor/github.com/google/go-github/v68/github/search.go b/vendor/github.com/google/go-github/v70/github/search.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/search.go rename to vendor/github.com/google/go-github/v70/github/search.go diff --git a/vendor/github.com/google/go-github/v68/github/secret_scanning.go b/vendor/github.com/google/go-github/v70/github/secret_scanning.go similarity index 95% rename from vendor/github.com/google/go-github/v68/github/secret_scanning.go rename to vendor/github.com/google/go-github/v70/github/secret_scanning.go index fc0fe0cd8c..4eeeba3df7 100644 --- a/vendor/github.com/google/go-github/v68/github/secret_scanning.go +++ b/vendor/github.com/google/go-github/v70/github/secret_scanning.go @@ -68,6 +68,16 @@ type SecretScanningAlertListOptions struct { // Valid resolutions are false_positive, wont_fix, revoked, pattern_edited, pattern_deleted or used_in_tests. Resolution string `url:"resolution,omitempty"` + // A comma-separated list of validities that, when present, will return alerts that match the validities in this list. + // Valid options are active, inactive, and unknown. + Validity string `url:"validity,omitempty"` + + // The direction to sort the results by. Possible values are: asc, desc. Default: desc. + Direction string `url:"direction,omitempty"` + + // The property by which to sort the results. Possible values are: created, updated. Default: created. + Sort string `url:"sort,omitempty"` + ListCursorOptions // List options can vary on the Enterprise type. diff --git a/vendor/github.com/google/go-github/v68/github/security_advisories.go b/vendor/github.com/google/go-github/v70/github/security_advisories.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/security_advisories.go rename to vendor/github.com/google/go-github/v70/github/security_advisories.go diff --git a/vendor/github.com/google/go-github/v68/github/strings.go b/vendor/github.com/google/go-github/v70/github/strings.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/strings.go rename to vendor/github.com/google/go-github/v70/github/strings.go diff --git a/vendor/github.com/google/go-github/v68/github/teams.go b/vendor/github.com/google/go-github/v70/github/teams.go similarity index 99% rename from vendor/github.com/google/go-github/v68/github/teams.go rename to vendor/github.com/google/go-github/v70/github/teams.go index 579e5b828b..d334110f4a 100644 --- a/vendor/github.com/google/go-github/v68/github/teams.go +++ b/vendor/github.com/google/go-github/v70/github/teams.go @@ -37,6 +37,9 @@ type Team struct { // Default is "secret". Privacy *string `json:"privacy,omitempty"` + // NotificationSetting can be one of: "notifications_enabled", "notifications_disabled". + NotificationSetting *string `json:"notification_setting,omitempty"` + MembersCount *int `json:"members_count,omitempty"` ReposCount *int `json:"repos_count,omitempty"` Organization *Organization `json:"organization,omitempty"` diff --git a/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go b/vendor/github.com/google/go-github/v70/github/teams_discussion_comments.go similarity index 99% rename from vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go rename to vendor/github.com/google/go-github/v70/github/teams_discussion_comments.go index eba6fdf46a..70bcbbc95b 100644 --- a/vendor/github.com/google/go-github/v68/github/teams_discussion_comments.go +++ b/vendor/github.com/google/go-github/v70/github/teams_discussion_comments.go @@ -167,8 +167,8 @@ func (s *TeamsService) CreateCommentByID(ctx context.Context, orgID, teamID int6 // GitHub API docs: https://docs.github.com/rest/teams/discussion-comments#create-a-discussion-comment // //meta:operation POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments -func (s *TeamsService) CreateCommentBySlug(ctx context.Context, org, slug string, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { - u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discsusionNumber) +func (s *TeamsService) CreateCommentBySlug(ctx context.Context, org, slug string, discussionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discussionNumber) req, err := s.client.NewRequest("POST", u, comment) if err != nil { return nil, nil, err diff --git a/vendor/github.com/google/go-github/v68/github/teams_discussions.go b/vendor/github.com/google/go-github/v70/github/teams_discussions.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/teams_discussions.go rename to vendor/github.com/google/go-github/v70/github/teams_discussions.go diff --git a/vendor/github.com/google/go-github/v68/github/teams_members.go b/vendor/github.com/google/go-github/v70/github/teams_members.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/teams_members.go rename to vendor/github.com/google/go-github/v70/github/teams_members.go diff --git a/vendor/github.com/google/go-github/v68/github/timestamp.go b/vendor/github.com/google/go-github/v70/github/timestamp.go similarity index 94% rename from vendor/github.com/google/go-github/v68/github/timestamp.go rename to vendor/github.com/google/go-github/v70/github/timestamp.go index dc1045cf74..71660193bb 100644 --- a/vendor/github.com/google/go-github/v68/github/timestamp.go +++ b/vendor/github.com/google/go-github/v70/github/timestamp.go @@ -10,7 +10,7 @@ import ( "time" ) -// Timestamp represents a time that can be unmarshalled from a JSON string +// Timestamp represents a time that can be unmarshaled from a JSON string // formatted as either an RFC3339 or Unix timestamp. This is necessary for some // fields since the GitHub API is inconsistent in how it represents times. All // exported methods of time.Time can be called on Timestamp. diff --git a/vendor/github.com/google/go-github/v68/github/users.go b/vendor/github.com/google/go-github/v70/github/users.go similarity index 99% rename from vendor/github.com/google/go-github/v68/github/users.go rename to vendor/github.com/google/go-github/v70/github/users.go index 60f1e06a69..28db59c5e1 100644 --- a/vendor/github.com/google/go-github/v68/github/users.go +++ b/vendor/github.com/google/go-github/v70/github/users.go @@ -77,7 +77,7 @@ type User struct { Assignment *string `json:"assignment,omitempty"` // InheritedFrom identifies the team that a user inherited their organization role // from. This is only populated when calling the ListUsersAssignedToOrgRole method. - InheritedFrom *Team `json:"inherited_from,omitempty"` + InheritedFrom []*Team `json:"inherited_from,omitempty"` } func (u User) String() string { diff --git a/vendor/github.com/google/go-github/v68/github/users_administration.go b/vendor/github.com/google/go-github/v70/github/users_administration.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_administration.go rename to vendor/github.com/google/go-github/v70/github/users_administration.go diff --git a/vendor/github.com/google/go-github/v68/github/users_attestations.go b/vendor/github.com/google/go-github/v70/github/users_attestations.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_attestations.go rename to vendor/github.com/google/go-github/v70/github/users_attestations.go diff --git a/vendor/github.com/google/go-github/v68/github/users_blocking.go b/vendor/github.com/google/go-github/v70/github/users_blocking.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_blocking.go rename to vendor/github.com/google/go-github/v70/github/users_blocking.go diff --git a/vendor/github.com/google/go-github/v68/github/users_emails.go b/vendor/github.com/google/go-github/v70/github/users_emails.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_emails.go rename to vendor/github.com/google/go-github/v70/github/users_emails.go diff --git a/vendor/github.com/google/go-github/v68/github/users_followers.go b/vendor/github.com/google/go-github/v70/github/users_followers.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_followers.go rename to vendor/github.com/google/go-github/v70/github/users_followers.go diff --git a/vendor/github.com/google/go-github/v68/github/users_gpg_keys.go b/vendor/github.com/google/go-github/v70/github/users_gpg_keys.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_gpg_keys.go rename to vendor/github.com/google/go-github/v70/github/users_gpg_keys.go diff --git a/vendor/github.com/google/go-github/v68/github/users_keys.go b/vendor/github.com/google/go-github/v70/github/users_keys.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_keys.go rename to vendor/github.com/google/go-github/v70/github/users_keys.go diff --git a/vendor/github.com/google/go-github/v68/github/users_packages.go b/vendor/github.com/google/go-github/v70/github/users_packages.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_packages.go rename to vendor/github.com/google/go-github/v70/github/users_packages.go diff --git a/vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go b/vendor/github.com/google/go-github/v70/github/users_ssh_signing_keys.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/users_ssh_signing_keys.go rename to vendor/github.com/google/go-github/v70/github/users_ssh_signing_keys.go diff --git a/vendor/github.com/google/go-github/v68/github/with_appengine.go b/vendor/github.com/google/go-github/v70/github/with_appengine.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/with_appengine.go rename to vendor/github.com/google/go-github/v70/github/with_appengine.go diff --git a/vendor/github.com/google/go-github/v68/github/without_appengine.go b/vendor/github.com/google/go-github/v70/github/without_appengine.go similarity index 100% rename from vendor/github.com/google/go-github/v68/github/without_appengine.go rename to vendor/github.com/google/go-github/v70/github/without_appengine.go diff --git a/vendor/github.com/hashicorp/hcl/.gitignore b/vendor/github.com/hashicorp/hcl/.gitignore deleted file mode 100644 index 15586a2b54..0000000000 --- a/vendor/github.com/hashicorp/hcl/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -y.output - -# ignore intellij files -.idea -*.iml -*.ipr -*.iws - -*.test diff --git a/vendor/github.com/hashicorp/hcl/.travis.yml b/vendor/github.com/hashicorp/hcl/.travis.yml deleted file mode 100644 index cb63a32161..0000000000 --- a/vendor/github.com/hashicorp/hcl/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -sudo: false - -language: go - -go: - - 1.x - - tip - -branches: - only: - - master - -script: make test diff --git a/vendor/github.com/hashicorp/hcl/LICENSE b/vendor/github.com/hashicorp/hcl/LICENSE deleted file mode 100644 index c33dcc7c92..0000000000 --- a/vendor/github.com/hashicorp/hcl/LICENSE +++ /dev/null @@ -1,354 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses” Notice - - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. - diff --git a/vendor/github.com/hashicorp/hcl/Makefile b/vendor/github.com/hashicorp/hcl/Makefile deleted file mode 100644 index 84fd743f5c..0000000000 --- a/vendor/github.com/hashicorp/hcl/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -TEST?=./... - -default: test - -fmt: generate - go fmt ./... - -test: generate - go get -t ./... - go test $(TEST) $(TESTARGS) - -generate: - go generate ./... - -updatedeps: - go get -u golang.org/x/tools/cmd/stringer - -.PHONY: default generate test updatedeps diff --git a/vendor/github.com/hashicorp/hcl/README.md b/vendor/github.com/hashicorp/hcl/README.md deleted file mode 100644 index c8223326dd..0000000000 --- a/vendor/github.com/hashicorp/hcl/README.md +++ /dev/null @@ -1,125 +0,0 @@ -# HCL - -[![GoDoc](https://godoc.org/github.com/hashicorp/hcl?status.png)](https://godoc.org/github.com/hashicorp/hcl) [![Build Status](https://travis-ci.org/hashicorp/hcl.svg?branch=master)](https://travis-ci.org/hashicorp/hcl) - -HCL (HashiCorp Configuration Language) is a configuration language built -by HashiCorp. The goal of HCL is to build a structured configuration language -that is both human and machine friendly for use with command-line tools, but -specifically targeted towards DevOps tools, servers, etc. - -HCL is also fully JSON compatible. That is, JSON can be used as completely -valid input to a system expecting HCL. This helps makes systems -interoperable with other systems. - -HCL is heavily inspired by -[libucl](https://github.com/vstakhov/libucl), -nginx configuration, and others similar. - -## Why? - -A common question when viewing HCL is to ask the question: why not -JSON, YAML, etc.? - -Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com) -used a variety of configuration languages from full programming languages -such as Ruby to complete data structure languages such as JSON. What we -learned is that some people wanted human-friendly configuration languages -and some people wanted machine-friendly languages. - -JSON fits a nice balance in this, but is fairly verbose and most -importantly doesn't support comments. With YAML, we found that beginners -had a really hard time determining what the actual structure was, and -ended up guessing more often than not whether to use a hyphen, colon, etc. -in order to represent some configuration key. - -Full programming languages such as Ruby enable complex behavior -a configuration language shouldn't usually allow, and also forces -people to learn some set of Ruby. - -Because of this, we decided to create our own configuration language -that is JSON-compatible. Our configuration language (HCL) is designed -to be written and modified by humans. The API for HCL allows JSON -as an input so that it is also machine-friendly (machines can generate -JSON instead of trying to generate HCL). - -Our goal with HCL is not to alienate other configuration languages. -It is instead to provide HCL as a specialized language for our tools, -and JSON as the interoperability layer. - -## Syntax - -For a complete grammar, please see the parser itself. A high-level overview -of the syntax and grammar is listed here. - - * Single line comments start with `#` or `//` - - * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments - are not allowed. A multi-line comment (also known as a block comment) - terminates at the first `*/` found. - - * Values are assigned with the syntax `key = value` (whitespace doesn't - matter). The value can be any primitive: a string, number, boolean, - object, or list. - - * Strings are double-quoted and can contain any UTF-8 characters. - Example: `"Hello, World"` - - * Multi-line strings start with `<- - echo %Path% - - go version - - go env - - go get -t ./... - -build_script: -- cmd: go test -v ./... diff --git a/vendor/github.com/hashicorp/hcl/decoder.go b/vendor/github.com/hashicorp/hcl/decoder.go deleted file mode 100644 index d9a00f21d4..0000000000 --- a/vendor/github.com/hashicorp/hcl/decoder.go +++ /dev/null @@ -1,769 +0,0 @@ -package hcl - -import ( - "errors" - "fmt" - "reflect" - "sort" - "strconv" - "strings" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/parser" - "github.com/hashicorp/hcl/hcl/token" -) - -// This is the tag to use with structures to have settings for HCL -const tagName = "hcl" - -var ( - // nodeType holds a reference to the type of ast.Node - nodeType reflect.Type = findNodeType() -) - -// Unmarshal accepts a byte slice as input and writes the -// data to the value pointed to by v. -func Unmarshal(bs []byte, v interface{}) error { - root, err := parse(bs) - if err != nil { - return err - } - - return DecodeObject(v, root) -} - -// Decode reads the given input and decodes it into the structure -// given by `out`. -func Decode(out interface{}, in string) error { - obj, err := Parse(in) - if err != nil { - return err - } - - return DecodeObject(out, obj) -} - -// DecodeObject is a lower-level version of Decode. It decodes a -// raw Object into the given output. -func DecodeObject(out interface{}, n ast.Node) error { - val := reflect.ValueOf(out) - if val.Kind() != reflect.Ptr { - return errors.New("result must be a pointer") - } - - // If we have the file, we really decode the root node - if f, ok := n.(*ast.File); ok { - n = f.Node - } - - var d decoder - return d.decode("root", n, val.Elem()) -} - -type decoder struct { - stack []reflect.Kind -} - -func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error { - k := result - - // If we have an interface with a valid value, we use that - // for the check. - if result.Kind() == reflect.Interface { - elem := result.Elem() - if elem.IsValid() { - k = elem - } - } - - // Push current onto stack unless it is an interface. - if k.Kind() != reflect.Interface { - d.stack = append(d.stack, k.Kind()) - - // Schedule a pop - defer func() { - d.stack = d.stack[:len(d.stack)-1] - }() - } - - switch k.Kind() { - case reflect.Bool: - return d.decodeBool(name, node, result) - case reflect.Float32, reflect.Float64: - return d.decodeFloat(name, node, result) - case reflect.Int, reflect.Int32, reflect.Int64: - return d.decodeInt(name, node, result) - case reflect.Interface: - // When we see an interface, we make our own thing - return d.decodeInterface(name, node, result) - case reflect.Map: - return d.decodeMap(name, node, result) - case reflect.Ptr: - return d.decodePtr(name, node, result) - case reflect.Slice: - return d.decodeSlice(name, node, result) - case reflect.String: - return d.decodeString(name, node, result) - case reflect.Struct: - return d.decodeStruct(name, node, result) - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()), - } - } -} - -func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - if n.Token.Type == token.BOOL { - v, err := strconv.ParseBool(n.Token.Text) - if err != nil { - return err - } - - result.Set(reflect.ValueOf(v)) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER { - v, err := strconv.ParseFloat(n.Token.Text, 64) - if err != nil { - return err - } - - result.Set(reflect.ValueOf(v).Convert(result.Type())) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - switch n.Token.Type { - case token.NUMBER: - v, err := strconv.ParseInt(n.Token.Text, 0, 0) - if err != nil { - return err - } - - if result.Kind() == reflect.Interface { - result.Set(reflect.ValueOf(int(v))) - } else { - result.SetInt(v) - } - return nil - case token.STRING: - v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0) - if err != nil { - return err - } - - if result.Kind() == reflect.Interface { - result.Set(reflect.ValueOf(int(v))) - } else { - result.SetInt(v) - } - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type %T", name, node), - } -} - -func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error { - // When we see an ast.Node, we retain the value to enable deferred decoding. - // Very useful in situations where we want to preserve ast.Node information - // like Pos - if result.Type() == nodeType && result.CanSet() { - result.Set(reflect.ValueOf(node)) - return nil - } - - var set reflect.Value - redecode := true - - // For testing types, ObjectType should just be treated as a list. We - // set this to a temporary var because we want to pass in the real node. - testNode := node - if ot, ok := node.(*ast.ObjectType); ok { - testNode = ot.List - } - - switch n := testNode.(type) { - case *ast.ObjectList: - // If we're at the root or we're directly within a slice, then we - // decode objects into map[string]interface{}, otherwise we decode - // them into lists. - if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { - var temp map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeMap( - reflect.MapOf( - reflect.TypeOf(""), - tempVal.Type().Elem())) - - set = result - } else { - var temp []map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items)) - set = result - } - case *ast.ObjectType: - // If we're at the root or we're directly within a slice, then we - // decode objects into map[string]interface{}, otherwise we decode - // them into lists. - if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice { - var temp map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeMap( - reflect.MapOf( - reflect.TypeOf(""), - tempVal.Type().Elem())) - - set = result - } else { - var temp []map[string]interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, 1) - set = result - } - case *ast.ListType: - var temp []interface{} - tempVal := reflect.ValueOf(temp) - result := reflect.MakeSlice( - reflect.SliceOf(tempVal.Type().Elem()), 0, 0) - set = result - case *ast.LiteralType: - switch n.Token.Type { - case token.BOOL: - var result bool - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.FLOAT: - var result float64 - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.NUMBER: - var result int - set = reflect.Indirect(reflect.New(reflect.TypeOf(result))) - case token.STRING, token.HEREDOC: - set = reflect.Indirect(reflect.New(reflect.TypeOf(""))) - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node), - } - } - default: - return fmt.Errorf( - "%s: cannot decode into interface: %T", - name, node) - } - - // Set the result to what its supposed to be, then reset - // result so we don't reflect into this method anymore. - result.Set(set) - - if redecode { - // Revisit the node so that we can use the newly instantiated - // thing and populate it. - if err := d.decode(name, node, result); err != nil { - return err - } - } - - return nil -} - -func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error { - if item, ok := node.(*ast.ObjectItem); ok { - node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} - } - - if ot, ok := node.(*ast.ObjectType); ok { - node = ot.List - } - - n, ok := node.(*ast.ObjectList) - if !ok { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: not an object type for map (%T)", name, node), - } - } - - // If we have an interface, then we can address the interface, - // but not the slice itself, so get the element but set the interface - set := result - if result.Kind() == reflect.Interface { - result = result.Elem() - } - - resultType := result.Type() - resultElemType := resultType.Elem() - resultKeyType := resultType.Key() - if resultKeyType.Kind() != reflect.String { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: map must have string keys", name), - } - } - - // Make a map if it is nil - resultMap := result - if result.IsNil() { - resultMap = reflect.MakeMap( - reflect.MapOf(resultKeyType, resultElemType)) - } - - // Go through each element and decode it. - done := make(map[string]struct{}) - for _, item := range n.Items { - if item.Val == nil { - continue - } - - // github.com/hashicorp/terraform/issue/5740 - if len(item.Keys) == 0 { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: map must have string keys", name), - } - } - - // Get the key we're dealing with, which is the first item - keyStr := item.Keys[0].Token.Value().(string) - - // If we've already processed this key, then ignore it - if _, ok := done[keyStr]; ok { - continue - } - - // Determine the value. If we have more than one key, then we - // get the objectlist of only these keys. - itemVal := item.Val - if len(item.Keys) > 1 { - itemVal = n.Filter(keyStr) - done[keyStr] = struct{}{} - } - - // Make the field name - fieldName := fmt.Sprintf("%s.%s", name, keyStr) - - // Get the key/value as reflection values - key := reflect.ValueOf(keyStr) - val := reflect.Indirect(reflect.New(resultElemType)) - - // If we have a pre-existing value in the map, use that - oldVal := resultMap.MapIndex(key) - if oldVal.IsValid() { - val.Set(oldVal) - } - - // Decode! - if err := d.decode(fieldName, itemVal, val); err != nil { - return err - } - - // Set the value on the map - resultMap.SetMapIndex(key, val) - } - - // Set the final map if we can - set.Set(resultMap) - return nil -} - -func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error { - // Create an element of the concrete (non pointer) type and decode - // into that. Then set the value of the pointer to this type. - resultType := result.Type() - resultElemType := resultType.Elem() - val := reflect.New(resultElemType) - if err := d.decode(name, node, reflect.Indirect(val)); err != nil { - return err - } - - result.Set(val) - return nil -} - -func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error { - // If we have an interface, then we can address the interface, - // but not the slice itself, so get the element but set the interface - set := result - if result.Kind() == reflect.Interface { - result = result.Elem() - } - // Create the slice if it isn't nil - resultType := result.Type() - resultElemType := resultType.Elem() - if result.IsNil() { - resultSliceType := reflect.SliceOf(resultElemType) - result = reflect.MakeSlice( - resultSliceType, 0, 0) - } - - // Figure out the items we'll be copying into the slice - var items []ast.Node - switch n := node.(type) { - case *ast.ObjectList: - items = make([]ast.Node, len(n.Items)) - for i, item := range n.Items { - items[i] = item - } - case *ast.ObjectType: - items = []ast.Node{n} - case *ast.ListType: - items = n.List - default: - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("unknown slice type: %T", node), - } - } - - for i, item := range items { - fieldName := fmt.Sprintf("%s[%d]", name, i) - - // Decode - val := reflect.Indirect(reflect.New(resultElemType)) - - // if item is an object that was decoded from ambiguous JSON and - // flattened, make sure it's expanded if it needs to decode into a - // defined structure. - item := expandObject(item, val) - - if err := d.decode(fieldName, item, val); err != nil { - return err - } - - // Append it onto the slice - result = reflect.Append(result, val) - } - - set.Set(result) - return nil -} - -// expandObject detects if an ambiguous JSON object was flattened to a List which -// should be decoded into a struct, and expands the ast to properly deocode. -func expandObject(node ast.Node, result reflect.Value) ast.Node { - item, ok := node.(*ast.ObjectItem) - if !ok { - return node - } - - elemType := result.Type() - - // our target type must be a struct - switch elemType.Kind() { - case reflect.Ptr: - switch elemType.Elem().Kind() { - case reflect.Struct: - //OK - default: - return node - } - case reflect.Struct: - //OK - default: - return node - } - - // A list value will have a key and field name. If it had more fields, - // it wouldn't have been flattened. - if len(item.Keys) != 2 { - return node - } - - keyToken := item.Keys[0].Token - item.Keys = item.Keys[1:] - - // we need to un-flatten the ast enough to decode - newNode := &ast.ObjectItem{ - Keys: []*ast.ObjectKey{ - { - Token: keyToken, - }, - }, - Val: &ast.ObjectType{ - List: &ast.ObjectList{ - Items: []*ast.ObjectItem{item}, - }, - }, - } - - return newNode -} - -func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error { - switch n := node.(type) { - case *ast.LiteralType: - switch n.Token.Type { - case token.NUMBER: - result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type())) - return nil - case token.STRING, token.HEREDOC: - result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type())) - return nil - } - } - - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unknown type for string %T", name, node), - } -} - -func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error { - var item *ast.ObjectItem - if it, ok := node.(*ast.ObjectItem); ok { - item = it - node = it.Val - } - - if ot, ok := node.(*ast.ObjectType); ok { - node = ot.List - } - - // Handle the special case where the object itself is a literal. Previously - // the yacc parser would always ensure top-level elements were arrays. The new - // parser does not make the same guarantees, thus we need to convert any - // top-level literal elements into a list. - if _, ok := node.(*ast.LiteralType); ok && item != nil { - node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} - } - - list, ok := node.(*ast.ObjectList) - if !ok { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node), - } - } - - // This slice will keep track of all the structs we'll be decoding. - // There can be more than one struct if there are embedded structs - // that are squashed. - structs := make([]reflect.Value, 1, 5) - structs[0] = result - - // Compile the list of all the fields that we're going to be decoding - // from all the structs. - type field struct { - field reflect.StructField - val reflect.Value - } - fields := []field{} - for len(structs) > 0 { - structVal := structs[0] - structs = structs[1:] - - structType := structVal.Type() - for i := 0; i < structType.NumField(); i++ { - fieldType := structType.Field(i) - tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") - - // Ignore fields with tag name "-" - if tagParts[0] == "-" { - continue - } - - if fieldType.Anonymous { - fieldKind := fieldType.Type.Kind() - if fieldKind != reflect.Struct { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: unsupported type to struct: %s", - fieldType.Name, fieldKind), - } - } - - // We have an embedded field. We "squash" the fields down - // if specified in the tag. - squash := false - for _, tag := range tagParts[1:] { - if tag == "squash" { - squash = true - break - } - } - - if squash { - structs = append( - structs, result.FieldByName(fieldType.Name)) - continue - } - } - - // Normal struct field, store it away - fields = append(fields, field{fieldType, structVal.Field(i)}) - } - } - - usedKeys := make(map[string]struct{}) - decodedFields := make([]string, 0, len(fields)) - decodedFieldsVal := make([]reflect.Value, 0) - unusedKeysVal := make([]reflect.Value, 0) - - // fill unusedNodeKeys with keys from the AST - // a slice because we have to do equals case fold to match Filter - unusedNodeKeys := make(map[string][]token.Pos, 0) - for i, item := range list.Items { - for _, k := range item.Keys { - // isNestedJSON returns true for e.g. bar in - // { "foo": { "bar": {...} } } - // This isn't an unused node key, so we want to skip it - isNestedJSON := i > 0 && len(item.Keys) > 1 - if !isNestedJSON && (k.Token.JSON || k.Token.Type == token.IDENT) { - fn := k.Token.Value().(string) - sl := unusedNodeKeys[fn] - unusedNodeKeys[fn] = append(sl, k.Token.Pos) - } - } - } - - for _, f := range fields { - field, fieldValue := f.field, f.val - if !fieldValue.IsValid() { - // This should never happen - panic("field is not valid") - } - - // If we can't set the field, then it is unexported or something, - // and we just continue onwards. - if !fieldValue.CanSet() { - continue - } - - fieldName := field.Name - - tagValue := field.Tag.Get(tagName) - tagParts := strings.SplitN(tagValue, ",", 2) - if len(tagParts) >= 2 { - switch tagParts[1] { - case "decodedFields": - decodedFieldsVal = append(decodedFieldsVal, fieldValue) - continue - case "key": - if item == nil { - return &parser.PosError{ - Pos: node.Pos(), - Err: fmt.Errorf("%s: %s asked for 'key', impossible", - name, fieldName), - } - } - - fieldValue.SetString(item.Keys[0].Token.Value().(string)) - continue - case "unusedKeyPositions": - unusedKeysVal = append(unusedKeysVal, fieldValue) - continue - } - } - - if tagParts[0] != "" { - fieldName = tagParts[0] - } - - // Determine the element we'll use to decode. If it is a single - // match (only object with the field), then we decode it exactly. - // If it is a prefix match, then we decode the matches. - filter := list.Filter(fieldName) - - prefixMatches := filter.Children() - matches := filter.Elem() - if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 { - continue - } - - // Track the used keys - usedKeys[fieldName] = struct{}{} - unusedNodeKeys = removeCaseFold(unusedNodeKeys, fieldName) - - // Create the field name and decode. We range over the elements - // because we actually want the value. - fieldName = fmt.Sprintf("%s.%s", name, fieldName) - if len(prefixMatches.Items) > 0 { - if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil { - return err - } - } - for _, match := range matches.Items { - var decodeNode ast.Node = match.Val - if ot, ok := decodeNode.(*ast.ObjectType); ok { - decodeNode = &ast.ObjectList{Items: ot.List.Items} - } - - if err := d.decode(fieldName, decodeNode, fieldValue); err != nil { - return err - } - } - - decodedFields = append(decodedFields, field.Name) - } - - if len(decodedFieldsVal) > 0 { - // Sort it so that it is deterministic - sort.Strings(decodedFields) - - for _, v := range decodedFieldsVal { - v.Set(reflect.ValueOf(decodedFields)) - } - } - - if len(unusedNodeKeys) > 0 { - // like decodedFields, populated the unusedKeys field(s) - for _, v := range unusedKeysVal { - v.Set(reflect.ValueOf(unusedNodeKeys)) - } - } - - return nil -} - -// findNodeType returns the type of ast.Node -func findNodeType() reflect.Type { - var nodeContainer struct { - Node ast.Node - } - value := reflect.ValueOf(nodeContainer).FieldByName("Node") - return value.Type() -} - -func removeCaseFold(xs map[string][]token.Pos, y string) map[string][]token.Pos { - var toDel []string - - for i := range xs { - if strings.EqualFold(i, y) { - toDel = append(toDel, i) - } - } - for _, i := range toDel { - delete(xs, i) - } - return xs -} diff --git a/vendor/github.com/hashicorp/hcl/hcl.go b/vendor/github.com/hashicorp/hcl/hcl.go deleted file mode 100644 index 575a20b50b..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl.go +++ /dev/null @@ -1,11 +0,0 @@ -// Package hcl decodes HCL into usable Go structures. -// -// hcl input can come in either pure HCL format or JSON format. -// It can be parsed into an AST, and then decoded into a structure, -// or it can be decoded directly from a string into a structure. -// -// If you choose to parse HCL into a raw AST, the benefit is that you -// can write custom visitor implementations to implement custom -// semantic checks. By default, HCL does not perform any semantic -// checks. -package hcl diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go deleted file mode 100644 index f5b6b93b94..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go +++ /dev/null @@ -1,226 +0,0 @@ -// Package ast declares the types used to represent syntax trees for HCL -// (HashiCorp Configuration Language) -package ast - -import ( - "fmt" - "strings" - - "github.com/hashicorp/hcl/hcl/token" -) - -// Node is an element in the abstract syntax tree. -type Node interface { - node() - Pos() token.Pos -} - -func (File) node() {} -func (ObjectList) node() {} -func (ObjectKey) node() {} -func (ObjectItem) node() {} -func (Comment) node() {} -func (CommentGroup) node() {} -func (ObjectType) node() {} -func (LiteralType) node() {} -func (ListType) node() {} - -var unknownPos token.Pos - -// File represents a single HCL file -type File struct { - Node Node // usually a *ObjectList - Comments []*CommentGroup // list of all comments in the source -} - -func (f *File) Pos() token.Pos { - return f.Node.Pos() -} - -// ObjectList represents a list of ObjectItems. An HCL file itself is an -// ObjectList. -type ObjectList struct { - Items []*ObjectItem -} - -func (o *ObjectList) Add(item *ObjectItem) { - o.Items = append(o.Items, item) -} - -// Filter filters out the objects with the given key list as a prefix. -// -// The returned list of objects contain ObjectItems where the keys have -// this prefix already stripped off. This might result in objects with -// zero-length key lists if they have no children. -// -// If no matches are found, an empty ObjectList (non-nil) is returned. -func (o *ObjectList) Filter(keys ...string) *ObjectList { - var result ObjectList - for _, item := range o.Items { - // If there aren't enough keys, then ignore this - if len(item.Keys) < len(keys) { - continue - } - - match := true - for i, key := range item.Keys[:len(keys)] { - key := key.Token.Value().(string) - if key != keys[i] && !strings.EqualFold(key, keys[i]) { - match = false - break - } - } - if !match { - continue - } - - // Strip off the prefix from the children - newItem := *item - newItem.Keys = newItem.Keys[len(keys):] - result.Add(&newItem) - } - - return &result -} - -// Children returns further nested objects (key length > 0) within this -// ObjectList. This should be used with Filter to get at child items. -func (o *ObjectList) Children() *ObjectList { - var result ObjectList - for _, item := range o.Items { - if len(item.Keys) > 0 { - result.Add(item) - } - } - - return &result -} - -// Elem returns items in the list that are direct element assignments -// (key length == 0). This should be used with Filter to get at elements. -func (o *ObjectList) Elem() *ObjectList { - var result ObjectList - for _, item := range o.Items { - if len(item.Keys) == 0 { - result.Add(item) - } - } - - return &result -} - -func (o *ObjectList) Pos() token.Pos { - // If an Object has no members, it won't have a first item - // to use as position - if len(o.Items) == 0 { - return unknownPos - } - // Return the uninitialized position - return o.Items[0].Pos() -} - -// ObjectItem represents a HCL Object Item. An item is represented with a key -// (or keys). It can be an assignment or an object (both normal and nested) -type ObjectItem struct { - // keys is only one length long if it's of type assignment. If it's a - // nested object it can be larger than one. In that case "assign" is - // invalid as there is no assignments for a nested object. - Keys []*ObjectKey - - // assign contains the position of "=", if any - Assign token.Pos - - // val is the item itself. It can be an object,list, number, bool or a - // string. If key length is larger than one, val can be only of type - // Object. - Val Node - - LeadComment *CommentGroup // associated lead comment - LineComment *CommentGroup // associated line comment -} - -func (o *ObjectItem) Pos() token.Pos { - // If a parsed object has no keys, there is no position - // for its first element. - if len(o.Keys) == 0 { - return unknownPos - } - - return o.Keys[0].Pos() -} - -// ObjectKeys are either an identifier or of type string. -type ObjectKey struct { - Token token.Token -} - -func (o *ObjectKey) Pos() token.Pos { - return o.Token.Pos -} - -// LiteralType represents a literal of basic type. Valid types are: -// token.NUMBER, token.FLOAT, token.BOOL and token.STRING -type LiteralType struct { - Token token.Token - - // comment types, only used when in a list - LeadComment *CommentGroup - LineComment *CommentGroup -} - -func (l *LiteralType) Pos() token.Pos { - return l.Token.Pos -} - -// ListStatement represents a HCL List type -type ListType struct { - Lbrack token.Pos // position of "[" - Rbrack token.Pos // position of "]" - List []Node // the elements in lexical order -} - -func (l *ListType) Pos() token.Pos { - return l.Lbrack -} - -func (l *ListType) Add(node Node) { - l.List = append(l.List, node) -} - -// ObjectType represents a HCL Object Type -type ObjectType struct { - Lbrace token.Pos // position of "{" - Rbrace token.Pos // position of "}" - List *ObjectList // the nodes in lexical order -} - -func (o *ObjectType) Pos() token.Pos { - return o.Lbrace -} - -// Comment node represents a single //, # style or /*- style commment -type Comment struct { - Start token.Pos // position of / or # - Text string -} - -func (c *Comment) Pos() token.Pos { - return c.Start -} - -// CommentGroup node represents a sequence of comments with no other tokens and -// no empty lines between. -type CommentGroup struct { - List []*Comment // len(List) > 0 -} - -func (c *CommentGroup) Pos() token.Pos { - return c.List[0].Pos() -} - -//------------------------------------------------------------------- -// GoStringer -//------------------------------------------------------------------- - -func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } -func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) } diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go b/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go deleted file mode 100644 index ba07ad42b0..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/ast/walk.go +++ /dev/null @@ -1,52 +0,0 @@ -package ast - -import "fmt" - -// WalkFunc describes a function to be called for each node during a Walk. The -// returned node can be used to rewrite the AST. Walking stops the returned -// bool is false. -type WalkFunc func(Node) (Node, bool) - -// Walk traverses an AST in depth-first order: It starts by calling fn(node); -// node must not be nil. If fn returns true, Walk invokes fn recursively for -// each of the non-nil children of node, followed by a call of fn(nil). The -// returned node of fn can be used to rewrite the passed node to fn. -func Walk(node Node, fn WalkFunc) Node { - rewritten, ok := fn(node) - if !ok { - return rewritten - } - - switch n := node.(type) { - case *File: - n.Node = Walk(n.Node, fn) - case *ObjectList: - for i, item := range n.Items { - n.Items[i] = Walk(item, fn).(*ObjectItem) - } - case *ObjectKey: - // nothing to do - case *ObjectItem: - for i, k := range n.Keys { - n.Keys[i] = Walk(k, fn).(*ObjectKey) - } - - if n.Val != nil { - n.Val = Walk(n.Val, fn) - } - case *LiteralType: - // nothing to do - case *ListType: - for i, l := range n.List { - n.List[i] = Walk(l, fn) - } - case *ObjectType: - n.List = Walk(n.List, fn).(*ObjectList) - default: - // should we panic here? - fmt.Printf("unknown type: %T\n", n) - } - - fn(nil) - return rewritten -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/error.go b/vendor/github.com/hashicorp/hcl/hcl/parser/error.go deleted file mode 100644 index 5c99381dfb..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/parser/error.go +++ /dev/null @@ -1,17 +0,0 @@ -package parser - -import ( - "fmt" - - "github.com/hashicorp/hcl/hcl/token" -) - -// PosError is a parse error that contains a position. -type PosError struct { - Pos token.Pos - Err error -} - -func (e *PosError) Error() string { - return fmt.Sprintf("At %s: %s", e.Pos, e.Err) -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go deleted file mode 100644 index 64c83bcfb5..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go +++ /dev/null @@ -1,532 +0,0 @@ -// Package parser implements a parser for HCL (HashiCorp Configuration -// Language) -package parser - -import ( - "bytes" - "errors" - "fmt" - "strings" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/scanner" - "github.com/hashicorp/hcl/hcl/token" -) - -type Parser struct { - sc *scanner.Scanner - - // Last read token - tok token.Token - commaPrev token.Token - - comments []*ast.CommentGroup - leadComment *ast.CommentGroup // last lead comment - lineComment *ast.CommentGroup // last line comment - - enableTrace bool - indent int - n int // buffer size (max = 1) -} - -func newParser(src []byte) *Parser { - return &Parser{ - sc: scanner.New(src), - } -} - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func Parse(src []byte) (*ast.File, error) { - // normalize all line endings - // since the scanner and output only work with "\n" line endings, we may - // end up with dangling "\r" characters in the parsed data. - src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1) - - p := newParser(src) - return p.Parse() -} - -var errEofToken = errors.New("EOF token found") - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func (p *Parser) Parse() (*ast.File, error) { - f := &ast.File{} - var err, scerr error - p.sc.Error = func(pos token.Pos, msg string) { - scerr = &PosError{Pos: pos, Err: errors.New(msg)} - } - - f.Node, err = p.objectList(false) - if scerr != nil { - return nil, scerr - } - if err != nil { - return nil, err - } - - f.Comments = p.comments - return f, nil -} - -// objectList parses a list of items within an object (generally k/v pairs). -// The parameter" obj" tells this whether to we are within an object (braces: -// '{', '}') or just at the top level. If we're within an object, we end -// at an RBRACE. -func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) { - defer un(trace(p, "ParseObjectList")) - node := &ast.ObjectList{} - - for { - if obj { - tok := p.scan() - p.unscan() - if tok.Type == token.RBRACE { - break - } - } - - n, err := p.objectItem() - if err == errEofToken { - break // we are finished - } - - // we don't return a nil node, because might want to use already - // collected items. - if err != nil { - return node, err - } - - node.Add(n) - - // object lists can be optionally comma-delimited e.g. when a list of maps - // is being expressed, so a comma is allowed here - it's simply consumed - tok := p.scan() - if tok.Type != token.COMMA { - p.unscan() - } - } - return node, nil -} - -func (p *Parser) consumeComment() (comment *ast.Comment, endline int) { - endline = p.tok.Pos.Line - - // count the endline if it's multiline comment, ie starting with /* - if len(p.tok.Text) > 1 && p.tok.Text[1] == '*' { - // don't use range here - no need to decode Unicode code points - for i := 0; i < len(p.tok.Text); i++ { - if p.tok.Text[i] == '\n' { - endline++ - } - } - } - - comment = &ast.Comment{Start: p.tok.Pos, Text: p.tok.Text} - p.tok = p.sc.Scan() - return -} - -func (p *Parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) { - var list []*ast.Comment - endline = p.tok.Pos.Line - - for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endline+n { - var comment *ast.Comment - comment, endline = p.consumeComment() - list = append(list, comment) - } - - // add comment group to the comments list - comments = &ast.CommentGroup{List: list} - p.comments = append(p.comments, comments) - - return -} - -// objectItem parses a single object item -func (p *Parser) objectItem() (*ast.ObjectItem, error) { - defer un(trace(p, "ParseObjectItem")) - - keys, err := p.objectKey() - if len(keys) > 0 && err == errEofToken { - // We ignore eof token here since it is an error if we didn't - // receive a value (but we did receive a key) for the item. - err = nil - } - if len(keys) > 0 && err != nil && p.tok.Type == token.RBRACE { - // This is a strange boolean statement, but what it means is: - // We have keys with no value, and we're likely in an object - // (since RBrace ends an object). For this, we set err to nil so - // we continue and get the error below of having the wrong value - // type. - err = nil - - // Reset the token type so we don't think it completed fine. See - // objectType which uses p.tok.Type to check if we're done with - // the object. - p.tok.Type = token.EOF - } - if err != nil { - return nil, err - } - - o := &ast.ObjectItem{ - Keys: keys, - } - - if p.leadComment != nil { - o.LeadComment = p.leadComment - p.leadComment = nil - } - - switch p.tok.Type { - case token.ASSIGN: - o.Assign = p.tok.Pos - o.Val, err = p.object() - if err != nil { - return nil, err - } - case token.LBRACE: - o.Val, err = p.objectType() - if err != nil { - return nil, err - } - default: - keyStr := make([]string, 0, len(keys)) - for _, k := range keys { - keyStr = append(keyStr, k.Token.Text) - } - - return nil, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf( - "key '%s' expected start of object ('{') or assignment ('=')", - strings.Join(keyStr, " ")), - } - } - - // key=#comment - // val - if p.lineComment != nil { - o.LineComment, p.lineComment = p.lineComment, nil - } - - // do a look-ahead for line comment - p.scan() - if len(keys) > 0 && o.Val.Pos().Line == keys[0].Pos().Line && p.lineComment != nil { - o.LineComment = p.lineComment - p.lineComment = nil - } - p.unscan() - return o, nil -} - -// objectKey parses an object key and returns a ObjectKey AST -func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { - keyCount := 0 - keys := make([]*ast.ObjectKey, 0) - - for { - tok := p.scan() - switch tok.Type { - case token.EOF: - // It is very important to also return the keys here as well as - // the error. This is because we need to be able to tell if we - // did parse keys prior to finding the EOF, or if we just found - // a bare EOF. - return keys, errEofToken - case token.ASSIGN: - // assignment or object only, but not nested objects. this is not - // allowed: `foo bar = {}` - if keyCount > 1 { - return nil, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("nested object expected: LBRACE got: %s", p.tok.Type), - } - } - - if keyCount == 0 { - return nil, &PosError{ - Pos: p.tok.Pos, - Err: errors.New("no object keys found!"), - } - } - - return keys, nil - case token.LBRACE: - var err error - - // If we have no keys, then it is a syntax error. i.e. {{}} is not - // allowed. - if len(keys) == 0 { - err = &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type), - } - } - - // object - return keys, err - case token.IDENT, token.STRING: - keyCount++ - keys = append(keys, &ast.ObjectKey{Token: p.tok}) - case token.ILLEGAL: - return keys, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("illegal character"), - } - default: - return keys, &PosError{ - Pos: p.tok.Pos, - Err: fmt.Errorf("expected: IDENT | STRING | ASSIGN | LBRACE got: %s", p.tok.Type), - } - } - } -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) object() (ast.Node, error) { - defer un(trace(p, "ParseType")) - tok := p.scan() - - switch tok.Type { - case token.NUMBER, token.FLOAT, token.BOOL, token.STRING, token.HEREDOC: - return p.literalType() - case token.LBRACE: - return p.objectType() - case token.LBRACK: - return p.listType() - case token.COMMENT: - // implement comment - case token.EOF: - return nil, errEofToken - } - - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("Unknown token: %+v", tok), - } -} - -// objectType parses an object type and returns a ObjectType AST -func (p *Parser) objectType() (*ast.ObjectType, error) { - defer un(trace(p, "ParseObjectType")) - - // we assume that the currently scanned token is a LBRACE - o := &ast.ObjectType{ - Lbrace: p.tok.Pos, - } - - l, err := p.objectList(true) - - // if we hit RBRACE, we are good to go (means we parsed all Items), if it's - // not a RBRACE, it's an syntax error and we just return it. - if err != nil && p.tok.Type != token.RBRACE { - return nil, err - } - - // No error, scan and expect the ending to be a brace - if tok := p.scan(); tok.Type != token.RBRACE { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type), - } - } - - o.List = l - o.Rbrace = p.tok.Pos // advanced via parseObjectList - return o, nil -} - -// listType parses a list type and returns a ListType AST -func (p *Parser) listType() (*ast.ListType, error) { - defer un(trace(p, "ParseListType")) - - // we assume that the currently scanned token is a LBRACK - l := &ast.ListType{ - Lbrack: p.tok.Pos, - } - - needComma := false - for { - tok := p.scan() - if needComma { - switch tok.Type { - case token.COMMA, token.RBRACK: - default: - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error parsing list, expected comma or list end, got: %s", - tok.Type), - } - } - } - switch tok.Type { - case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: - node, err := p.literalType() - if err != nil { - return nil, err - } - - // If there is a lead comment, apply it - if p.leadComment != nil { - node.LeadComment = p.leadComment - p.leadComment = nil - } - - l.Add(node) - needComma = true - case token.COMMA: - // get next list item or we are at the end - // do a look-ahead for line comment - p.scan() - if p.lineComment != nil && len(l.List) > 0 { - lit, ok := l.List[len(l.List)-1].(*ast.LiteralType) - if ok { - lit.LineComment = p.lineComment - l.List[len(l.List)-1] = lit - p.lineComment = nil - } - } - p.unscan() - - needComma = false - continue - case token.LBRACE: - // Looks like a nested object, so parse it out - node, err := p.objectType() - if err != nil { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error while trying to parse object within list: %s", err), - } - } - l.Add(node) - needComma = true - case token.LBRACK: - node, err := p.listType() - if err != nil { - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf( - "error while trying to parse list within list: %s", err), - } - } - l.Add(node) - case token.RBRACK: - // finished - l.Rbrack = p.tok.Pos - return l, nil - default: - return nil, &PosError{ - Pos: tok.Pos, - Err: fmt.Errorf("unexpected token while parsing list: %s", tok.Type), - } - } - } -} - -// literalType parses a literal type and returns a LiteralType AST -func (p *Parser) literalType() (*ast.LiteralType, error) { - defer un(trace(p, "ParseLiteral")) - - return &ast.LiteralType{ - Token: p.tok, - }, nil -} - -// scan returns the next token from the underlying scanner. If a token has -// been unscanned then read that instead. In the process, it collects any -// comment groups encountered, and remembers the last lead and line comments. -func (p *Parser) scan() token.Token { - // If we have a token on the buffer, then return it. - if p.n != 0 { - p.n = 0 - return p.tok - } - - // Otherwise read the next token from the scanner and Save it to the buffer - // in case we unscan later. - prev := p.tok - p.tok = p.sc.Scan() - - if p.tok.Type == token.COMMENT { - var comment *ast.CommentGroup - var endline int - - // fmt.Printf("p.tok.Pos.Line = %+v prev: %d endline %d \n", - // p.tok.Pos.Line, prev.Pos.Line, endline) - if p.tok.Pos.Line == prev.Pos.Line { - // The comment is on same line as the previous token; it - // cannot be a lead comment but may be a line comment. - comment, endline = p.consumeCommentGroup(0) - if p.tok.Pos.Line != endline { - // The next token is on a different line, thus - // the last comment group is a line comment. - p.lineComment = comment - } - } - - // consume successor comments, if any - endline = -1 - for p.tok.Type == token.COMMENT { - comment, endline = p.consumeCommentGroup(1) - } - - if endline+1 == p.tok.Pos.Line && p.tok.Type != token.RBRACE { - switch p.tok.Type { - case token.RBRACE, token.RBRACK: - // Do not count for these cases - default: - // The next token is following on the line immediately after the - // comment group, thus the last comment group is a lead comment. - p.leadComment = comment - } - } - - } - - return p.tok -} - -// unscan pushes the previously read token back onto the buffer. -func (p *Parser) unscan() { - p.n = 1 -} - -// ---------------------------------------------------------------------------- -// Parsing support - -func (p *Parser) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) - - i := 2 * p.indent - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *Parser, msg string) *Parser { - p.printTrace(msg, "(") - p.indent++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *Parser) { - p.indent-- - p.printTrace(")") -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go deleted file mode 100644 index 7c038d12a2..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go +++ /dev/null @@ -1,789 +0,0 @@ -package printer - -import ( - "bytes" - "fmt" - "sort" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/token" -) - -const ( - blank = byte(' ') - newline = byte('\n') - tab = byte('\t') - infinity = 1 << 30 // offset or line -) - -var ( - unindent = []byte("\uE123") // in the private use space -) - -type printer struct { - cfg Config - prev token.Pos - - comments []*ast.CommentGroup // may be nil, contains all comments - standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node) - - enableTrace bool - indentTrace int -} - -type ByPosition []*ast.CommentGroup - -func (b ByPosition) Len() int { return len(b) } -func (b ByPosition) Swap(i, j int) { b[i], b[j] = b[j], b[i] } -func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) } - -// collectComments comments all standalone comments which are not lead or line -// comment -func (p *printer) collectComments(node ast.Node) { - // first collect all comments. This is already stored in - // ast.File.(comments) - ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { - switch t := nn.(type) { - case *ast.File: - p.comments = t.Comments - return nn, false - } - return nn, true - }) - - standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0) - for _, c := range p.comments { - standaloneComments[c.Pos()] = c - } - - // next remove all lead and line comments from the overall comment map. - // This will give us comments which are standalone, comments which are not - // assigned to any kind of node. - ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { - switch t := nn.(type) { - case *ast.LiteralType: - if t.LeadComment != nil { - for _, comment := range t.LeadComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - - if t.LineComment != nil { - for _, comment := range t.LineComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - case *ast.ObjectItem: - if t.LeadComment != nil { - for _, comment := range t.LeadComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - - if t.LineComment != nil { - for _, comment := range t.LineComment.List { - if _, ok := standaloneComments[comment.Pos()]; ok { - delete(standaloneComments, comment.Pos()) - } - } - } - } - - return nn, true - }) - - for _, c := range standaloneComments { - p.standaloneComments = append(p.standaloneComments, c) - } - - sort.Sort(ByPosition(p.standaloneComments)) -} - -// output prints creates b printable HCL output and returns it. -func (p *printer) output(n interface{}) []byte { - var buf bytes.Buffer - - switch t := n.(type) { - case *ast.File: - // File doesn't trace so we add the tracing here - defer un(trace(p, "File")) - return p.output(t.Node) - case *ast.ObjectList: - defer un(trace(p, "ObjectList")) - - var index int - for { - // Determine the location of the next actual non-comment - // item. If we're at the end, the next item is at "infinity" - var nextItem token.Pos - if index != len(t.Items) { - nextItem = t.Items[index].Pos() - } else { - nextItem = token.Pos{Offset: infinity, Line: infinity} - } - - // Go through the standalone comments in the file and print out - // the comments that we should be for this object item. - for _, c := range p.standaloneComments { - // Go through all the comments in the group. The group - // should be printed together, not separated by double newlines. - printed := false - newlinePrinted := false - for _, comment := range c.List { - // We only care about comments after the previous item - // we've printed so that comments are printed in the - // correct locations (between two objects for example). - // And before the next item. - if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { - // if we hit the end add newlines so we can print the comment - // we don't do this if prev is invalid which means the - // beginning of the file since the first comment should - // be at the first line. - if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) { - buf.Write([]byte{newline, newline}) - newlinePrinted = true - } - - // Write the actual comment. - buf.WriteString(comment.Text) - buf.WriteByte(newline) - - // Set printed to true to note that we printed something - printed = true - } - } - - // If we're not at the last item, write a new line so - // that there is a newline separating this comment from - // the next object. - if printed && index != len(t.Items) { - buf.WriteByte(newline) - } - } - - if index == len(t.Items) { - break - } - - buf.Write(p.output(t.Items[index])) - if index != len(t.Items)-1 { - // Always write a newline to separate us from the next item - buf.WriteByte(newline) - - // Need to determine if we're going to separate the next item - // with a blank line. The logic here is simple, though there - // are a few conditions: - // - // 1. The next object is more than one line away anyways, - // so we need an empty line. - // - // 2. The next object is not a "single line" object, so - // we need an empty line. - // - // 3. This current object is not a single line object, - // so we need an empty line. - current := t.Items[index] - next := t.Items[index+1] - if next.Pos().Line != t.Items[index].Pos().Line+1 || - !p.isSingleLineObject(next) || - !p.isSingleLineObject(current) { - buf.WriteByte(newline) - } - } - index++ - } - case *ast.ObjectKey: - buf.WriteString(t.Token.Text) - case *ast.ObjectItem: - p.prev = t.Pos() - buf.Write(p.objectItem(t)) - case *ast.LiteralType: - buf.Write(p.literalType(t)) - case *ast.ListType: - buf.Write(p.list(t)) - case *ast.ObjectType: - buf.Write(p.objectType(t)) - default: - fmt.Printf(" unknown type: %T\n", n) - } - - return buf.Bytes() -} - -func (p *printer) literalType(lit *ast.LiteralType) []byte { - result := []byte(lit.Token.Text) - switch lit.Token.Type { - case token.HEREDOC: - // Clear the trailing newline from heredocs - if result[len(result)-1] == '\n' { - result = result[:len(result)-1] - } - - // Poison lines 2+ so that we don't indent them - result = p.heredocIndent(result) - case token.STRING: - // If this is a multiline string, poison lines 2+ so we don't - // indent them. - if bytes.IndexRune(result, '\n') >= 0 { - result = p.heredocIndent(result) - } - } - - return result -} - -// objectItem returns the printable HCL form of an object item. An object type -// starts with one/multiple keys and has a value. The value might be of any -// type. -func (p *printer) objectItem(o *ast.ObjectItem) []byte { - defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text))) - var buf bytes.Buffer - - if o.LeadComment != nil { - for _, comment := range o.LeadComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - // If key and val are on different lines, treat line comments like lead comments. - if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line { - for _, comment := range o.LineComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - for i, k := range o.Keys { - buf.WriteString(k.Token.Text) - buf.WriteByte(blank) - - // reach end of key - if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 { - buf.WriteString("=") - buf.WriteByte(blank) - } - } - - buf.Write(p.output(o.Val)) - - if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line { - buf.WriteByte(blank) - for _, comment := range o.LineComment.List { - buf.WriteString(comment.Text) - } - } - - return buf.Bytes() -} - -// objectType returns the printable HCL form of an object type. An object type -// begins with a brace and ends with a brace. -func (p *printer) objectType(o *ast.ObjectType) []byte { - defer un(trace(p, "ObjectType")) - var buf bytes.Buffer - buf.WriteString("{") - - var index int - var nextItem token.Pos - var commented, newlinePrinted bool - for { - // Determine the location of the next actual non-comment - // item. If we're at the end, the next item is the closing brace - if index != len(o.List.Items) { - nextItem = o.List.Items[index].Pos() - } else { - nextItem = o.Rbrace - } - - // Go through the standalone comments in the file and print out - // the comments that we should be for this object item. - for _, c := range p.standaloneComments { - printed := false - var lastCommentPos token.Pos - for _, comment := range c.List { - // We only care about comments after the previous item - // we've printed so that comments are printed in the - // correct locations (between two objects for example). - // And before the next item. - if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { - // If there are standalone comments and the initial newline has not - // been printed yet, do it now. - if !newlinePrinted { - newlinePrinted = true - buf.WriteByte(newline) - } - - // add newline if it's between other printed nodes - if index > 0 { - commented = true - buf.WriteByte(newline) - } - - // Store this position - lastCommentPos = comment.Pos() - - // output the comment itself - buf.Write(p.indent(p.heredocIndent([]byte(comment.Text)))) - - // Set printed to true to note that we printed something - printed = true - - /* - if index != len(o.List.Items) { - buf.WriteByte(newline) // do not print on the end - } - */ - } - } - - // Stuff to do if we had comments - if printed { - // Always write a newline - buf.WriteByte(newline) - - // If there is another item in the object and our comment - // didn't hug it directly, then make sure there is a blank - // line separating them. - if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 { - buf.WriteByte(newline) - } - } - } - - if index == len(o.List.Items) { - p.prev = o.Rbrace - break - } - - // At this point we are sure that it's not a totally empty block: print - // the initial newline if it hasn't been printed yet by the previous - // block about standalone comments. - if !newlinePrinted { - buf.WriteByte(newline) - newlinePrinted = true - } - - // check if we have adjacent one liner items. If yes we'll going to align - // the comments. - var aligned []*ast.ObjectItem - for _, item := range o.List.Items[index:] { - // we don't group one line lists - if len(o.List.Items) == 1 { - break - } - - // one means a oneliner with out any lead comment - // two means a oneliner with lead comment - // anything else might be something else - cur := lines(string(p.objectItem(item))) - if cur > 2 { - break - } - - curPos := item.Pos() - - nextPos := token.Pos{} - if index != len(o.List.Items)-1 { - nextPos = o.List.Items[index+1].Pos() - } - - prevPos := token.Pos{} - if index != 0 { - prevPos = o.List.Items[index-1].Pos() - } - - // fmt.Println("DEBUG ----------------") - // fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos) - // fmt.Printf("cur = %+v curPos: %s\n", cur, curPos) - // fmt.Printf("next = %+v nextPos: %s\n", next, nextPos) - - if curPos.Line+1 == nextPos.Line { - aligned = append(aligned, item) - index++ - continue - } - - if curPos.Line-1 == prevPos.Line { - aligned = append(aligned, item) - index++ - - // finish if we have a new line or comment next. This happens - // if the next item is not adjacent - if curPos.Line+1 != nextPos.Line { - break - } - continue - } - - break - } - - // put newlines if the items are between other non aligned items. - // newlines are also added if there is a standalone comment already, so - // check it too - if !commented && index != len(aligned) { - buf.WriteByte(newline) - } - - if len(aligned) >= 1 { - p.prev = aligned[len(aligned)-1].Pos() - - items := p.alignedItems(aligned) - buf.Write(p.indent(items)) - } else { - p.prev = o.List.Items[index].Pos() - - buf.Write(p.indent(p.objectItem(o.List.Items[index]))) - index++ - } - - buf.WriteByte(newline) - } - - buf.WriteString("}") - return buf.Bytes() -} - -func (p *printer) alignedItems(items []*ast.ObjectItem) []byte { - var buf bytes.Buffer - - // find the longest key and value length, needed for alignment - var longestKeyLen int // longest key length - var longestValLen int // longest value length - for _, item := range items { - key := len(item.Keys[0].Token.Text) - val := len(p.output(item.Val)) - - if key > longestKeyLen { - longestKeyLen = key - } - - if val > longestValLen { - longestValLen = val - } - } - - for i, item := range items { - if item.LeadComment != nil { - for _, comment := range item.LeadComment.List { - buf.WriteString(comment.Text) - buf.WriteByte(newline) - } - } - - for i, k := range item.Keys { - keyLen := len(k.Token.Text) - buf.WriteString(k.Token.Text) - for i := 0; i < longestKeyLen-keyLen+1; i++ { - buf.WriteByte(blank) - } - - // reach end of key - if i == len(item.Keys)-1 && len(item.Keys) == 1 { - buf.WriteString("=") - buf.WriteByte(blank) - } - } - - val := p.output(item.Val) - valLen := len(val) - buf.Write(val) - - if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil { - for i := 0; i < longestValLen-valLen+1; i++ { - buf.WriteByte(blank) - } - - for _, comment := range item.LineComment.List { - buf.WriteString(comment.Text) - } - } - - // do not print for the last item - if i != len(items)-1 { - buf.WriteByte(newline) - } - } - - return buf.Bytes() -} - -// list returns the printable HCL form of an list type. -func (p *printer) list(l *ast.ListType) []byte { - if p.isSingleLineList(l) { - return p.singleLineList(l) - } - - var buf bytes.Buffer - buf.WriteString("[") - buf.WriteByte(newline) - - var longestLine int - for _, item := range l.List { - // for now we assume that the list only contains literal types - if lit, ok := item.(*ast.LiteralType); ok { - lineLen := len(lit.Token.Text) - if lineLen > longestLine { - longestLine = lineLen - } - } - } - - haveEmptyLine := false - for i, item := range l.List { - // If we have a lead comment, then we want to write that first - leadComment := false - if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil { - leadComment = true - - // Ensure an empty line before every element with a - // lead comment (except the first item in a list). - if !haveEmptyLine && i != 0 { - buf.WriteByte(newline) - } - - for _, comment := range lit.LeadComment.List { - buf.Write(p.indent([]byte(comment.Text))) - buf.WriteByte(newline) - } - } - - // also indent each line - val := p.output(item) - curLen := len(val) - buf.Write(p.indent(val)) - - // if this item is a heredoc, then we output the comma on - // the next line. This is the only case this happens. - comma := []byte{','} - if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { - buf.WriteByte(newline) - comma = p.indent(comma) - } - - buf.Write(comma) - - if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil { - // if the next item doesn't have any comments, do not align - buf.WriteByte(blank) // align one space - for i := 0; i < longestLine-curLen; i++ { - buf.WriteByte(blank) - } - - for _, comment := range lit.LineComment.List { - buf.WriteString(comment.Text) - } - } - - buf.WriteByte(newline) - - // Ensure an empty line after every element with a - // lead comment (except the first item in a list). - haveEmptyLine = leadComment && i != len(l.List)-1 - if haveEmptyLine { - buf.WriteByte(newline) - } - } - - buf.WriteString("]") - return buf.Bytes() -} - -// isSingleLineList returns true if: -// * they were previously formatted entirely on one line -// * they consist entirely of literals -// * there are either no heredoc strings or the list has exactly one element -// * there are no line comments -func (printer) isSingleLineList(l *ast.ListType) bool { - for _, item := range l.List { - if item.Pos().Line != l.Lbrack.Line { - return false - } - - lit, ok := item.(*ast.LiteralType) - if !ok { - return false - } - - if lit.Token.Type == token.HEREDOC && len(l.List) != 1 { - return false - } - - if lit.LineComment != nil { - return false - } - } - - return true -} - -// singleLineList prints a simple single line list. -// For a definition of "simple", see isSingleLineList above. -func (p *printer) singleLineList(l *ast.ListType) []byte { - buf := &bytes.Buffer{} - - buf.WriteString("[") - for i, item := range l.List { - if i != 0 { - buf.WriteString(", ") - } - - // Output the item itself - buf.Write(p.output(item)) - - // The heredoc marker needs to be at the end of line. - if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { - buf.WriteByte(newline) - } - } - - buf.WriteString("]") - return buf.Bytes() -} - -// indent indents the lines of the given buffer for each non-empty line -func (p *printer) indent(buf []byte) []byte { - var prefix []byte - if p.cfg.SpacesWidth != 0 { - for i := 0; i < p.cfg.SpacesWidth; i++ { - prefix = append(prefix, blank) - } - } else { - prefix = []byte{tab} - } - - var res []byte - bol := true - for _, c := range buf { - if bol && c != '\n' { - res = append(res, prefix...) - } - - res = append(res, c) - bol = c == '\n' - } - return res -} - -// unindent removes all the indentation from the tombstoned lines -func (p *printer) unindent(buf []byte) []byte { - var res []byte - for i := 0; i < len(buf); i++ { - skip := len(buf)-i <= len(unindent) - if !skip { - skip = !bytes.Equal(unindent, buf[i:i+len(unindent)]) - } - if skip { - res = append(res, buf[i]) - continue - } - - // We have a marker. we have to backtrace here and clean out - // any whitespace ahead of our tombstone up to a \n - for j := len(res) - 1; j >= 0; j-- { - if res[j] == '\n' { - break - } - - res = res[:j] - } - - // Skip the entire unindent marker - i += len(unindent) - 1 - } - - return res -} - -// heredocIndent marks all the 2nd and further lines as unindentable -func (p *printer) heredocIndent(buf []byte) []byte { - var res []byte - bol := false - for _, c := range buf { - if bol && c != '\n' { - res = append(res, unindent...) - } - res = append(res, c) - bol = c == '\n' - } - return res -} - -// isSingleLineObject tells whether the given object item is a single -// line object such as "obj {}". -// -// A single line object: -// -// * has no lead comments (hence multi-line) -// * has no assignment -// * has no values in the stanza (within {}) -// -func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool { - // If there is a lead comment, can't be one line - if val.LeadComment != nil { - return false - } - - // If there is assignment, we always break by line - if val.Assign.IsValid() { - return false - } - - // If it isn't an object type, then its not a single line object - ot, ok := val.Val.(*ast.ObjectType) - if !ok { - return false - } - - // If the object has no items, it is single line! - return len(ot.List.Items) == 0 -} - -func lines(txt string) int { - endline := 1 - for i := 0; i < len(txt); i++ { - if txt[i] == '\n' { - endline++ - } - } - return endline -} - -// ---------------------------------------------------------------------------- -// Tracing support - -func (p *printer) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - i := 2 * p.indentTrace - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *printer, msg string) *printer { - p.printTrace(msg, "(") - p.indentTrace++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *printer) { - p.indentTrace-- - p.printTrace(")") -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go deleted file mode 100644 index 6617ab8e7a..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package printer implements printing of AST nodes to HCL format. -package printer - -import ( - "bytes" - "io" - "text/tabwriter" - - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/parser" -) - -var DefaultConfig = Config{ - SpacesWidth: 2, -} - -// A Config node controls the output of Fprint. -type Config struct { - SpacesWidth int // if set, it will use spaces instead of tabs for alignment -} - -func (c *Config) Fprint(output io.Writer, node ast.Node) error { - p := &printer{ - cfg: *c, - comments: make([]*ast.CommentGroup, 0), - standaloneComments: make([]*ast.CommentGroup, 0), - // enableTrace: true, - } - - p.collectComments(node) - - if _, err := output.Write(p.unindent(p.output(node))); err != nil { - return err - } - - // flush tabwriter, if any - var err error - if tw, _ := output.(*tabwriter.Writer); tw != nil { - err = tw.Flush() - } - - return err -} - -// Fprint "pretty-prints" an HCL node to output -// It calls Config.Fprint with default settings. -func Fprint(output io.Writer, node ast.Node) error { - return DefaultConfig.Fprint(output, node) -} - -// Format formats src HCL and returns the result. -func Format(src []byte) ([]byte, error) { - node, err := parser.Parse(src) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - if err := DefaultConfig.Fprint(&buf, node); err != nil { - return nil, err - } - - // Add trailing newline to result - buf.WriteString("\n") - return buf.Bytes(), nil -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go deleted file mode 100644 index 624a18fe3a..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go +++ /dev/null @@ -1,652 +0,0 @@ -// Package scanner implements a scanner for HCL (HashiCorp Configuration -// Language) source text. -package scanner - -import ( - "bytes" - "fmt" - "os" - "regexp" - "unicode" - "unicode/utf8" - - "github.com/hashicorp/hcl/hcl/token" -) - -// eof represents a marker rune for the end of the reader. -const eof = rune(0) - -// Scanner defines a lexical scanner -type Scanner struct { - buf *bytes.Buffer // Source buffer for advancing and scanning - src []byte // Source buffer for immutable access - - // Source Position - srcPos token.Pos // current position - prevPos token.Pos // previous position, used for peek() method - - lastCharLen int // length of last character in bytes - lastLineLen int // length of last line in characters (for correct column reporting) - - tokStart int // token text start position - tokEnd int // token text end position - - // Error is called for each error encountered. If no Error - // function is set, the error is reported to os.Stderr. - Error func(pos token.Pos, msg string) - - // ErrorCount is incremented by one for each error encountered. - ErrorCount int - - // tokPos is the start position of most recently scanned token; set by - // Scan. The Filename field is always left untouched by the Scanner. If - // an error is reported (via Error) and Position is invalid, the scanner is - // not inside a token. - tokPos token.Pos -} - -// New creates and initializes a new instance of Scanner using src as -// its source content. -func New(src []byte) *Scanner { - // even though we accept a src, we read from a io.Reader compatible type - // (*bytes.Buffer). So in the future we might easily change it to streaming - // read. - b := bytes.NewBuffer(src) - s := &Scanner{ - buf: b, - src: src, - } - - // srcPosition always starts with 1 - s.srcPos.Line = 1 - return s -} - -// next reads the next rune from the bufferred reader. Returns the rune(0) if -// an error occurs (or io.EOF is returned). -func (s *Scanner) next() rune { - ch, size, err := s.buf.ReadRune() - if err != nil { - // advance for error reporting - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - return eof - } - - // remember last position - s.prevPos = s.srcPos - - s.srcPos.Column++ - s.lastCharLen = size - s.srcPos.Offset += size - - if ch == utf8.RuneError && size == 1 { - s.err("illegal UTF-8 encoding") - return ch - } - - if ch == '\n' { - s.srcPos.Line++ - s.lastLineLen = s.srcPos.Column - s.srcPos.Column = 0 - } - - if ch == '\x00' { - s.err("unexpected null character (0x00)") - return eof - } - - if ch == '\uE123' { - s.err("unicode code point U+E123 reserved for internal use") - return utf8.RuneError - } - - // debug - // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) - return ch -} - -// unread unreads the previous read Rune and updates the source position -func (s *Scanner) unread() { - if err := s.buf.UnreadRune(); err != nil { - panic(err) // this is user fault, we should catch it - } - s.srcPos = s.prevPos // put back last position -} - -// peek returns the next rune without advancing the reader. -func (s *Scanner) peek() rune { - peek, _, err := s.buf.ReadRune() - if err != nil { - return eof - } - - s.buf.UnreadRune() - return peek -} - -// Scan scans the next token and returns the token. -func (s *Scanner) Scan() token.Token { - ch := s.next() - - // skip white space - for isWhitespace(ch) { - ch = s.next() - } - - var tok token.Type - - // token text markings - s.tokStart = s.srcPos.Offset - s.lastCharLen - - // token position, initial next() is moving the offset by one(size of rune - // actually), though we are interested with the starting point - s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen - if s.srcPos.Column > 0 { - // common case: last character was not a '\n' - s.tokPos.Line = s.srcPos.Line - s.tokPos.Column = s.srcPos.Column - } else { - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - s.tokPos.Line = s.srcPos.Line - 1 - s.tokPos.Column = s.lastLineLen - } - - switch { - case isLetter(ch): - tok = token.IDENT - lit := s.scanIdentifier() - if lit == "true" || lit == "false" { - tok = token.BOOL - } - case isDecimal(ch): - tok = s.scanNumber(ch) - default: - switch ch { - case eof: - tok = token.EOF - case '"': - tok = token.STRING - s.scanString() - case '#', '/': - tok = token.COMMENT - s.scanComment(ch) - case '.': - tok = token.PERIOD - ch = s.peek() - if isDecimal(ch) { - tok = token.FLOAT - ch = s.scanMantissa(ch) - ch = s.scanExponent(ch) - } - case '<': - tok = token.HEREDOC - s.scanHeredoc() - case '[': - tok = token.LBRACK - case ']': - tok = token.RBRACK - case '{': - tok = token.LBRACE - case '}': - tok = token.RBRACE - case ',': - tok = token.COMMA - case '=': - tok = token.ASSIGN - case '+': - tok = token.ADD - case '-': - if isDecimal(s.peek()) { - ch := s.next() - tok = s.scanNumber(ch) - } else { - tok = token.SUB - } - default: - s.err("illegal char") - } - } - - // finish token ending - s.tokEnd = s.srcPos.Offset - - // create token literal - var tokenText string - if s.tokStart >= 0 { - tokenText = string(s.src[s.tokStart:s.tokEnd]) - } - s.tokStart = s.tokEnd // ensure idempotency of tokenText() call - - return token.Token{ - Type: tok, - Pos: s.tokPos, - Text: tokenText, - } -} - -func (s *Scanner) scanComment(ch rune) { - // single line comments - if ch == '#' || (ch == '/' && s.peek() != '*') { - if ch == '/' && s.peek() != '/' { - s.err("expected '/' for comment") - return - } - - ch = s.next() - for ch != '\n' && ch >= 0 && ch != eof { - ch = s.next() - } - if ch != eof && ch >= 0 { - s.unread() - } - return - } - - // be sure we get the character after /* This allows us to find comment's - // that are not erminated - if ch == '/' { - s.next() - ch = s.next() // read character after "/*" - } - - // look for /* - style comments - for { - if ch < 0 || ch == eof { - s.err("comment not terminated") - break - } - - ch0 := ch - ch = s.next() - if ch0 == '*' && ch == '/' { - break - } - } -} - -// scanNumber scans a HCL number definition starting with the given rune -func (s *Scanner) scanNumber(ch rune) token.Type { - if ch == '0' { - // check for hexadecimal, octal or float - ch = s.next() - if ch == 'x' || ch == 'X' { - // hexadecimal - ch = s.next() - found := false - for isHexadecimal(ch) { - ch = s.next() - found = true - } - - if !found { - s.err("illegal hexadecimal number") - } - - if ch != eof { - s.unread() - } - - return token.NUMBER - } - - // now it's either something like: 0421(octal) or 0.1231(float) - illegalOctal := false - for isDecimal(ch) { - ch = s.next() - if ch == '8' || ch == '9' { - // this is just a possibility. For example 0159 is illegal, but - // 0159.23 is valid. So we mark a possible illegal octal. If - // the next character is not a period, we'll print the error. - illegalOctal = true - } - } - - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if illegalOctal { - s.err("illegal octal number") - } - - if ch != eof { - s.unread() - } - return token.NUMBER - } - - s.scanMantissa(ch) - ch = s.next() // seek forward - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if ch != eof { - s.unread() - } - return token.NUMBER -} - -// scanMantissa scans the mantissa beginning from the rune. It returns the next -// non decimal rune. It's used to determine wheter it's a fraction or exponent. -func (s *Scanner) scanMantissa(ch rune) rune { - scanned := false - for isDecimal(ch) { - ch = s.next() - scanned = true - } - - if scanned && ch != eof { - s.unread() - } - return ch -} - -// scanFraction scans the fraction after the '.' rune -func (s *Scanner) scanFraction(ch rune) rune { - if ch == '.' { - ch = s.peek() // we peek just to see if we can move forward - ch = s.scanMantissa(ch) - } - return ch -} - -// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' -// rune. -func (s *Scanner) scanExponent(ch rune) rune { - if ch == 'e' || ch == 'E' { - ch = s.next() - if ch == '-' || ch == '+' { - ch = s.next() - } - ch = s.scanMantissa(ch) - } - return ch -} - -// scanHeredoc scans a heredoc string -func (s *Scanner) scanHeredoc() { - // Scan the second '<' in example: '<= len(identBytes) && identRegexp.Match(s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) { - break - } - - // Not an anchor match, record the start of a new line - lineStart = s.srcPos.Offset - } - - if ch == eof { - s.err("heredoc not terminated") - return - } - } - - return -} - -// scanString scans a quoted string -func (s *Scanner) scanString() { - braces := 0 - for { - // '"' opening already consumed - // read character after quote - ch := s.next() - - if (ch == '\n' && braces == 0) || ch < 0 || ch == eof { - s.err("literal not terminated") - return - } - - if ch == '"' && braces == 0 { - break - } - - // If we're going into a ${} then we can ignore quotes for awhile - if braces == 0 && ch == '$' && s.peek() == '{' { - braces++ - s.next() - } else if braces > 0 && ch == '{' { - braces++ - } - if braces > 0 && ch == '}' { - braces-- - } - - if ch == '\\' { - s.scanEscape() - } - } - - return -} - -// scanEscape scans an escape sequence -func (s *Scanner) scanEscape() rune { - // http://en.cppreference.com/w/cpp/language/escape - ch := s.next() // read character after '/' - switch ch { - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': - // nothing to do - case '0', '1', '2', '3', '4', '5', '6', '7': - // octal notation - ch = s.scanDigits(ch, 8, 3) - case 'x': - // hexademical notation - ch = s.scanDigits(s.next(), 16, 2) - case 'u': - // universal character name - ch = s.scanDigits(s.next(), 16, 4) - case 'U': - // universal character name - ch = s.scanDigits(s.next(), 16, 8) - default: - s.err("illegal char escape") - } - return ch -} - -// scanDigits scans a rune with the given base for n times. For example an -// octal notation \184 would yield in scanDigits(ch, 8, 3) -func (s *Scanner) scanDigits(ch rune, base, n int) rune { - start := n - for n > 0 && digitVal(ch) < base { - ch = s.next() - if ch == eof { - // If we see an EOF, we halt any more scanning of digits - // immediately. - break - } - - n-- - } - if n > 0 { - s.err("illegal char escape") - } - - if n != start && ch != eof { - // we scanned all digits, put the last non digit char back, - // only if we read anything at all - s.unread() - } - - return ch -} - -// scanIdentifier scans an identifier and returns the literal string -func (s *Scanner) scanIdentifier() string { - offs := s.srcPos.Offset - s.lastCharLen - ch := s.next() - for isLetter(ch) || isDigit(ch) || ch == '-' || ch == '.' { - ch = s.next() - } - - if ch != eof { - s.unread() // we got identifier, put back latest char - } - - return string(s.src[offs:s.srcPos.Offset]) -} - -// recentPosition returns the position of the character immediately after the -// character or token returned by the last call to Scan. -func (s *Scanner) recentPosition() (pos token.Pos) { - pos.Offset = s.srcPos.Offset - s.lastCharLen - switch { - case s.srcPos.Column > 0: - // common case: last character was not a '\n' - pos.Line = s.srcPos.Line - pos.Column = s.srcPos.Column - case s.lastLineLen > 0: - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - pos.Line = s.srcPos.Line - 1 - pos.Column = s.lastLineLen - default: - // at the beginning of the source - pos.Line = 1 - pos.Column = 1 - } - return -} - -// err prints the error of any scanning to s.Error function. If the function is -// not defined, by default it prints them to os.Stderr -func (s *Scanner) err(msg string) { - s.ErrorCount++ - pos := s.recentPosition() - - if s.Error != nil { - s.Error(pos, msg) - return - } - - fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) -} - -// isHexadecimal returns true if the given rune is a letter -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) -} - -// isDigit returns true if the given rune is a decimal digit -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) -} - -// isDecimal returns true if the given rune is a decimal number -func isDecimal(ch rune) bool { - return '0' <= ch && ch <= '9' -} - -// isHexadecimal returns true if the given rune is an hexadecimal number -func isHexadecimal(ch rune) bool { - return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' -} - -// isWhitespace returns true if the rune is a space, tab, newline or carriage return -func isWhitespace(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' -} - -// digitVal returns the integer value of a given octal,decimal or hexadecimal rune -func digitVal(ch rune) int { - switch { - case '0' <= ch && ch <= '9': - return int(ch - '0') - case 'a' <= ch && ch <= 'f': - return int(ch - 'a' + 10) - case 'A' <= ch && ch <= 'F': - return int(ch - 'A' + 10) - } - return 16 // larger than any legal digit val -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go deleted file mode 100644 index 5f981eaa2f..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go +++ /dev/null @@ -1,241 +0,0 @@ -package strconv - -import ( - "errors" - "unicode/utf8" -) - -// ErrSyntax indicates that a value does not have the right syntax for the target type. -var ErrSyntax = errors.New("invalid syntax") - -// Unquote interprets s as a single-quoted, double-quoted, -// or backquoted Go string literal, returning the string value -// that s quotes. (If s is single-quoted, it would be a Go -// character literal; Unquote returns the corresponding -// one-character string.) -func Unquote(s string) (t string, err error) { - n := len(s) - if n < 2 { - return "", ErrSyntax - } - quote := s[0] - if quote != s[n-1] { - return "", ErrSyntax - } - s = s[1 : n-1] - - if quote != '"' { - return "", ErrSyntax - } - if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') { - return "", ErrSyntax - } - - // Is it trivial? Avoid allocation. - if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') { - switch quote { - case '"': - return s, nil - case '\'': - r, size := utf8.DecodeRuneInString(s) - if size == len(s) && (r != utf8.RuneError || size != 1) { - return s, nil - } - } - } - - var runeTmp [utf8.UTFMax]byte - buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. - for len(s) > 0 { - // If we're starting a '${}' then let it through un-unquoted. - // Specifically: we don't unquote any characters within the `${}` - // section. - if s[0] == '$' && len(s) > 1 && s[1] == '{' { - buf = append(buf, '$', '{') - s = s[2:] - - // Continue reading until we find the closing brace, copying as-is - braces := 1 - for len(s) > 0 && braces > 0 { - r, size := utf8.DecodeRuneInString(s) - if r == utf8.RuneError { - return "", ErrSyntax - } - - s = s[size:] - - n := utf8.EncodeRune(runeTmp[:], r) - buf = append(buf, runeTmp[:n]...) - - switch r { - case '{': - braces++ - case '}': - braces-- - } - } - if braces != 0 { - return "", ErrSyntax - } - if len(s) == 0 { - // If there's no string left, we're done! - break - } else { - // If there's more left, we need to pop back up to the top of the loop - // in case there's another interpolation in this string. - continue - } - } - - if s[0] == '\n' { - return "", ErrSyntax - } - - c, multibyte, ss, err := unquoteChar(s, quote) - if err != nil { - return "", err - } - s = ss - if c < utf8.RuneSelf || !multibyte { - buf = append(buf, byte(c)) - } else { - n := utf8.EncodeRune(runeTmp[:], c) - buf = append(buf, runeTmp[:n]...) - } - if quote == '\'' && len(s) != 0 { - // single-quoted must be single character - return "", ErrSyntax - } - } - return string(buf), nil -} - -// contains reports whether the string contains the byte c. -func contains(s string, c byte) bool { - for i := 0; i < len(s); i++ { - if s[i] == c { - return true - } - } - return false -} - -func unhex(b byte) (v rune, ok bool) { - c := rune(b) - switch { - case '0' <= c && c <= '9': - return c - '0', true - case 'a' <= c && c <= 'f': - return c - 'a' + 10, true - case 'A' <= c && c <= 'F': - return c - 'A' + 10, true - } - return -} - -func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) { - // easy cases - switch c := s[0]; { - case c == quote && (quote == '\'' || quote == '"'): - err = ErrSyntax - return - case c >= utf8.RuneSelf: - r, size := utf8.DecodeRuneInString(s) - return r, true, s[size:], nil - case c != '\\': - return rune(s[0]), false, s[1:], nil - } - - // hard case: c is backslash - if len(s) <= 1 { - err = ErrSyntax - return - } - c := s[1] - s = s[2:] - - switch c { - case 'a': - value = '\a' - case 'b': - value = '\b' - case 'f': - value = '\f' - case 'n': - value = '\n' - case 'r': - value = '\r' - case 't': - value = '\t' - case 'v': - value = '\v' - case 'x', 'u', 'U': - n := 0 - switch c { - case 'x': - n = 2 - case 'u': - n = 4 - case 'U': - n = 8 - } - var v rune - if len(s) < n { - err = ErrSyntax - return - } - for j := 0; j < n; j++ { - x, ok := unhex(s[j]) - if !ok { - err = ErrSyntax - return - } - v = v<<4 | x - } - s = s[n:] - if c == 'x' { - // single-byte string, possibly not UTF-8 - value = v - break - } - if v > utf8.MaxRune { - err = ErrSyntax - return - } - value = v - multibyte = true - case '0', '1', '2', '3', '4', '5', '6', '7': - v := rune(c) - '0' - if len(s) < 2 { - err = ErrSyntax - return - } - for j := 0; j < 2; j++ { // one digit already; two more - x := rune(s[j]) - '0' - if x < 0 || x > 7 { - err = ErrSyntax - return - } - v = (v << 3) | x - } - s = s[2:] - if v > 255 { - err = ErrSyntax - return - } - value = v - case '\\': - value = '\\' - case '\'', '"': - if c != quote { - err = ErrSyntax - return - } - value = rune(c) - default: - err = ErrSyntax - return - } - tail = s - return -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/position.go b/vendor/github.com/hashicorp/hcl/hcl/token/position.go deleted file mode 100644 index 59c1bb72d4..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/token/position.go +++ /dev/null @@ -1,46 +0,0 @@ -package token - -import "fmt" - -// Pos describes an arbitrary source position -// including the file, line, and column location. -// A Position is valid if the line number is > 0. -type Pos struct { - Filename string // filename, if any - Offset int // offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (character count) -} - -// IsValid returns true if the position is valid. -func (p *Pos) IsValid() bool { return p.Line > 0 } - -// String returns a string in one of several forms: -// -// file:line:column valid position with file name -// line:column valid position without file name -// file invalid position with file name -// - invalid position without file name -func (p Pos) String() string { - s := p.Filename - if p.IsValid() { - if s != "" { - s += ":" - } - s += fmt.Sprintf("%d:%d", p.Line, p.Column) - } - if s == "" { - s = "-" - } - return s -} - -// Before reports whether the position p is before u. -func (p Pos) Before(u Pos) bool { - return u.Offset > p.Offset || u.Line > p.Line -} - -// After reports whether the position p is after u. -func (p Pos) After(u Pos) bool { - return u.Offset < p.Offset || u.Line < p.Line -} diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/vendor/github.com/hashicorp/hcl/hcl/token/token.go deleted file mode 100644 index e37c0664ec..0000000000 --- a/vendor/github.com/hashicorp/hcl/hcl/token/token.go +++ /dev/null @@ -1,219 +0,0 @@ -// Package token defines constants representing the lexical tokens for HCL -// (HashiCorp Configuration Language) -package token - -import ( - "fmt" - "strconv" - "strings" - - hclstrconv "github.com/hashicorp/hcl/hcl/strconv" -) - -// Token defines a single HCL token which can be obtained via the Scanner -type Token struct { - Type Type - Pos Pos - Text string - JSON bool -} - -// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) -type Type int - -const ( - // Special tokens - ILLEGAL Type = iota - EOF - COMMENT - - identifier_beg - IDENT // literals - literal_beg - NUMBER // 12345 - FLOAT // 123.45 - BOOL // true,false - STRING // "abc" - HEREDOC // < 0 { - // Pop the current item - n := len(frontier) - item := frontier[n-1] - frontier = frontier[:n-1] - - switch v := item.Val.(type) { - case *ast.ObjectType: - items, frontier = flattenObjectType(v, item, items, frontier) - case *ast.ListType: - items, frontier = flattenListType(v, item, items, frontier) - default: - items = append(items, item) - } - } - - // Reverse the list since the frontier model runs things backwards - for i := len(items)/2 - 1; i >= 0; i-- { - opp := len(items) - 1 - i - items[i], items[opp] = items[opp], items[i] - } - - // Done! Set the original items - list.Items = items - return n, true - }) -} - -func flattenListType( - ot *ast.ListType, - item *ast.ObjectItem, - items []*ast.ObjectItem, - frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { - // If the list is empty, keep the original list - if len(ot.List) == 0 { - items = append(items, item) - return items, frontier - } - - // All the elements of this object must also be objects! - for _, subitem := range ot.List { - if _, ok := subitem.(*ast.ObjectType); !ok { - items = append(items, item) - return items, frontier - } - } - - // Great! We have a match go through all the items and flatten - for _, elem := range ot.List { - // Add it to the frontier so that we can recurse - frontier = append(frontier, &ast.ObjectItem{ - Keys: item.Keys, - Assign: item.Assign, - Val: elem, - LeadComment: item.LeadComment, - LineComment: item.LineComment, - }) - } - - return items, frontier -} - -func flattenObjectType( - ot *ast.ObjectType, - item *ast.ObjectItem, - items []*ast.ObjectItem, - frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { - // If the list has no items we do not have to flatten anything - if ot.List.Items == nil { - items = append(items, item) - return items, frontier - } - - // All the elements of this object must also be objects! - for _, subitem := range ot.List.Items { - if _, ok := subitem.Val.(*ast.ObjectType); !ok { - items = append(items, item) - return items, frontier - } - } - - // Great! We have a match go through all the items and flatten - for _, subitem := range ot.List.Items { - // Copy the new key - keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys)) - copy(keys, item.Keys) - copy(keys[len(item.Keys):], subitem.Keys) - - // Add it to the frontier so that we can recurse - frontier = append(frontier, &ast.ObjectItem{ - Keys: keys, - Assign: item.Assign, - Val: subitem.Val, - LeadComment: item.LeadComment, - LineComment: item.LineComment, - }) - } - - return items, frontier -} diff --git a/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/vendor/github.com/hashicorp/hcl/json/parser/parser.go deleted file mode 100644 index 125a5f0729..0000000000 --- a/vendor/github.com/hashicorp/hcl/json/parser/parser.go +++ /dev/null @@ -1,313 +0,0 @@ -package parser - -import ( - "errors" - "fmt" - - "github.com/hashicorp/hcl/hcl/ast" - hcltoken "github.com/hashicorp/hcl/hcl/token" - "github.com/hashicorp/hcl/json/scanner" - "github.com/hashicorp/hcl/json/token" -) - -type Parser struct { - sc *scanner.Scanner - - // Last read token - tok token.Token - commaPrev token.Token - - enableTrace bool - indent int - n int // buffer size (max = 1) -} - -func newParser(src []byte) *Parser { - return &Parser{ - sc: scanner.New(src), - } -} - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func Parse(src []byte) (*ast.File, error) { - p := newParser(src) - return p.Parse() -} - -var errEofToken = errors.New("EOF token found") - -// Parse returns the fully parsed source and returns the abstract syntax tree. -func (p *Parser) Parse() (*ast.File, error) { - f := &ast.File{} - var err, scerr error - p.sc.Error = func(pos token.Pos, msg string) { - scerr = fmt.Errorf("%s: %s", pos, msg) - } - - // The root must be an object in JSON - object, err := p.object() - if scerr != nil { - return nil, scerr - } - if err != nil { - return nil, err - } - - // We make our final node an object list so it is more HCL compatible - f.Node = object.List - - // Flatten it, which finds patterns and turns them into more HCL-like - // AST trees. - flattenObjects(f.Node) - - return f, nil -} - -func (p *Parser) objectList() (*ast.ObjectList, error) { - defer un(trace(p, "ParseObjectList")) - node := &ast.ObjectList{} - - for { - n, err := p.objectItem() - if err == errEofToken { - break // we are finished - } - - // we don't return a nil node, because might want to use already - // collected items. - if err != nil { - return node, err - } - - node.Add(n) - - // Check for a followup comma. If it isn't a comma, then we're done - if tok := p.scan(); tok.Type != token.COMMA { - break - } - } - - return node, nil -} - -// objectItem parses a single object item -func (p *Parser) objectItem() (*ast.ObjectItem, error) { - defer un(trace(p, "ParseObjectItem")) - - keys, err := p.objectKey() - if err != nil { - return nil, err - } - - o := &ast.ObjectItem{ - Keys: keys, - } - - switch p.tok.Type { - case token.COLON: - pos := p.tok.Pos - o.Assign = hcltoken.Pos{ - Filename: pos.Filename, - Offset: pos.Offset, - Line: pos.Line, - Column: pos.Column, - } - - o.Val, err = p.objectValue() - if err != nil { - return nil, err - } - } - - return o, nil -} - -// objectKey parses an object key and returns a ObjectKey AST -func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { - keyCount := 0 - keys := make([]*ast.ObjectKey, 0) - - for { - tok := p.scan() - switch tok.Type { - case token.EOF: - return nil, errEofToken - case token.STRING: - keyCount++ - keys = append(keys, &ast.ObjectKey{ - Token: p.tok.HCLToken(), - }) - case token.COLON: - // If we have a zero keycount it means that we never got - // an object key, i.e. `{ :`. This is a syntax error. - if keyCount == 0 { - return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) - } - - // Done - return keys, nil - case token.ILLEGAL: - return nil, errors.New("illegal") - default: - return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) - } - } -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) objectValue() (ast.Node, error) { - defer un(trace(p, "ParseObjectValue")) - tok := p.scan() - - switch tok.Type { - case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING: - return p.literalType() - case token.LBRACE: - return p.objectType() - case token.LBRACK: - return p.listType() - case token.EOF: - return nil, errEofToken - } - - return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok) -} - -// object parses any type of object, such as number, bool, string, object or -// list. -func (p *Parser) object() (*ast.ObjectType, error) { - defer un(trace(p, "ParseType")) - tok := p.scan() - - switch tok.Type { - case token.LBRACE: - return p.objectType() - case token.EOF: - return nil, errEofToken - } - - return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok) -} - -// objectType parses an object type and returns a ObjectType AST -func (p *Parser) objectType() (*ast.ObjectType, error) { - defer un(trace(p, "ParseObjectType")) - - // we assume that the currently scanned token is a LBRACE - o := &ast.ObjectType{} - - l, err := p.objectList() - - // if we hit RBRACE, we are good to go (means we parsed all Items), if it's - // not a RBRACE, it's an syntax error and we just return it. - if err != nil && p.tok.Type != token.RBRACE { - return nil, err - } - - o.List = l - return o, nil -} - -// listType parses a list type and returns a ListType AST -func (p *Parser) listType() (*ast.ListType, error) { - defer un(trace(p, "ParseListType")) - - // we assume that the currently scanned token is a LBRACK - l := &ast.ListType{} - - for { - tok := p.scan() - switch tok.Type { - case token.NUMBER, token.FLOAT, token.STRING: - node, err := p.literalType() - if err != nil { - return nil, err - } - - l.Add(node) - case token.COMMA: - continue - case token.LBRACE: - node, err := p.objectType() - if err != nil { - return nil, err - } - - l.Add(node) - case token.BOOL: - // TODO(arslan) should we support? not supported by HCL yet - case token.LBRACK: - // TODO(arslan) should we support nested lists? Even though it's - // written in README of HCL, it's not a part of the grammar - // (not defined in parse.y) - case token.RBRACK: - // finished - return l, nil - default: - return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type) - } - - } -} - -// literalType parses a literal type and returns a LiteralType AST -func (p *Parser) literalType() (*ast.LiteralType, error) { - defer un(trace(p, "ParseLiteral")) - - return &ast.LiteralType{ - Token: p.tok.HCLToken(), - }, nil -} - -// scan returns the next token from the underlying scanner. If a token has -// been unscanned then read that instead. -func (p *Parser) scan() token.Token { - // If we have a token on the buffer, then return it. - if p.n != 0 { - p.n = 0 - return p.tok - } - - p.tok = p.sc.Scan() - return p.tok -} - -// unscan pushes the previously read token back onto the buffer. -func (p *Parser) unscan() { - p.n = 1 -} - -// ---------------------------------------------------------------------------- -// Parsing support - -func (p *Parser) printTrace(a ...interface{}) { - if !p.enableTrace { - return - } - - const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " - const n = len(dots) - fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column) - - i := 2 * p.indent - for i > n { - fmt.Print(dots) - i -= n - } - // i <= n - fmt.Print(dots[0:i]) - fmt.Println(a...) -} - -func trace(p *Parser, msg string) *Parser { - p.printTrace(msg, "(") - p.indent++ - return p -} - -// Usage pattern: defer un(trace(p, "...")) -func un(p *Parser) { - p.indent-- - p.printTrace(")") -} diff --git a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go deleted file mode 100644 index fe3f0f0950..0000000000 --- a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go +++ /dev/null @@ -1,451 +0,0 @@ -package scanner - -import ( - "bytes" - "fmt" - "os" - "unicode" - "unicode/utf8" - - "github.com/hashicorp/hcl/json/token" -) - -// eof represents a marker rune for the end of the reader. -const eof = rune(0) - -// Scanner defines a lexical scanner -type Scanner struct { - buf *bytes.Buffer // Source buffer for advancing and scanning - src []byte // Source buffer for immutable access - - // Source Position - srcPos token.Pos // current position - prevPos token.Pos // previous position, used for peek() method - - lastCharLen int // length of last character in bytes - lastLineLen int // length of last line in characters (for correct column reporting) - - tokStart int // token text start position - tokEnd int // token text end position - - // Error is called for each error encountered. If no Error - // function is set, the error is reported to os.Stderr. - Error func(pos token.Pos, msg string) - - // ErrorCount is incremented by one for each error encountered. - ErrorCount int - - // tokPos is the start position of most recently scanned token; set by - // Scan. The Filename field is always left untouched by the Scanner. If - // an error is reported (via Error) and Position is invalid, the scanner is - // not inside a token. - tokPos token.Pos -} - -// New creates and initializes a new instance of Scanner using src as -// its source content. -func New(src []byte) *Scanner { - // even though we accept a src, we read from a io.Reader compatible type - // (*bytes.Buffer). So in the future we might easily change it to streaming - // read. - b := bytes.NewBuffer(src) - s := &Scanner{ - buf: b, - src: src, - } - - // srcPosition always starts with 1 - s.srcPos.Line = 1 - return s -} - -// next reads the next rune from the bufferred reader. Returns the rune(0) if -// an error occurs (or io.EOF is returned). -func (s *Scanner) next() rune { - ch, size, err := s.buf.ReadRune() - if err != nil { - // advance for error reporting - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - return eof - } - - if ch == utf8.RuneError && size == 1 { - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - s.err("illegal UTF-8 encoding") - return ch - } - - // remember last position - s.prevPos = s.srcPos - - s.srcPos.Column++ - s.lastCharLen = size - s.srcPos.Offset += size - - if ch == '\n' { - s.srcPos.Line++ - s.lastLineLen = s.srcPos.Column - s.srcPos.Column = 0 - } - - // debug - // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) - return ch -} - -// unread unreads the previous read Rune and updates the source position -func (s *Scanner) unread() { - if err := s.buf.UnreadRune(); err != nil { - panic(err) // this is user fault, we should catch it - } - s.srcPos = s.prevPos // put back last position -} - -// peek returns the next rune without advancing the reader. -func (s *Scanner) peek() rune { - peek, _, err := s.buf.ReadRune() - if err != nil { - return eof - } - - s.buf.UnreadRune() - return peek -} - -// Scan scans the next token and returns the token. -func (s *Scanner) Scan() token.Token { - ch := s.next() - - // skip white space - for isWhitespace(ch) { - ch = s.next() - } - - var tok token.Type - - // token text markings - s.tokStart = s.srcPos.Offset - s.lastCharLen - - // token position, initial next() is moving the offset by one(size of rune - // actually), though we are interested with the starting point - s.tokPos.Offset = s.srcPos.Offset - s.lastCharLen - if s.srcPos.Column > 0 { - // common case: last character was not a '\n' - s.tokPos.Line = s.srcPos.Line - s.tokPos.Column = s.srcPos.Column - } else { - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - s.tokPos.Line = s.srcPos.Line - 1 - s.tokPos.Column = s.lastLineLen - } - - switch { - case isLetter(ch): - lit := s.scanIdentifier() - if lit == "true" || lit == "false" { - tok = token.BOOL - } else if lit == "null" { - tok = token.NULL - } else { - s.err("illegal char") - } - case isDecimal(ch): - tok = s.scanNumber(ch) - default: - switch ch { - case eof: - tok = token.EOF - case '"': - tok = token.STRING - s.scanString() - case '.': - tok = token.PERIOD - ch = s.peek() - if isDecimal(ch) { - tok = token.FLOAT - ch = s.scanMantissa(ch) - ch = s.scanExponent(ch) - } - case '[': - tok = token.LBRACK - case ']': - tok = token.RBRACK - case '{': - tok = token.LBRACE - case '}': - tok = token.RBRACE - case ',': - tok = token.COMMA - case ':': - tok = token.COLON - case '-': - if isDecimal(s.peek()) { - ch := s.next() - tok = s.scanNumber(ch) - } else { - s.err("illegal char") - } - default: - s.err("illegal char: " + string(ch)) - } - } - - // finish token ending - s.tokEnd = s.srcPos.Offset - - // create token literal - var tokenText string - if s.tokStart >= 0 { - tokenText = string(s.src[s.tokStart:s.tokEnd]) - } - s.tokStart = s.tokEnd // ensure idempotency of tokenText() call - - return token.Token{ - Type: tok, - Pos: s.tokPos, - Text: tokenText, - } -} - -// scanNumber scans a HCL number definition starting with the given rune -func (s *Scanner) scanNumber(ch rune) token.Type { - zero := ch == '0' - pos := s.srcPos - - s.scanMantissa(ch) - ch = s.next() // seek forward - if ch == 'e' || ch == 'E' { - ch = s.scanExponent(ch) - return token.FLOAT - } - - if ch == '.' { - ch = s.scanFraction(ch) - if ch == 'e' || ch == 'E' { - ch = s.next() - ch = s.scanExponent(ch) - } - return token.FLOAT - } - - if ch != eof { - s.unread() - } - - // If we have a larger number and this is zero, error - if zero && pos != s.srcPos { - s.err("numbers cannot start with 0") - } - - return token.NUMBER -} - -// scanMantissa scans the mantissa beginning from the rune. It returns the next -// non decimal rune. It's used to determine wheter it's a fraction or exponent. -func (s *Scanner) scanMantissa(ch rune) rune { - scanned := false - for isDecimal(ch) { - ch = s.next() - scanned = true - } - - if scanned && ch != eof { - s.unread() - } - return ch -} - -// scanFraction scans the fraction after the '.' rune -func (s *Scanner) scanFraction(ch rune) rune { - if ch == '.' { - ch = s.peek() // we peek just to see if we can move forward - ch = s.scanMantissa(ch) - } - return ch -} - -// scanExponent scans the remaining parts of an exponent after the 'e' or 'E' -// rune. -func (s *Scanner) scanExponent(ch rune) rune { - if ch == 'e' || ch == 'E' { - ch = s.next() - if ch == '-' || ch == '+' { - ch = s.next() - } - ch = s.scanMantissa(ch) - } - return ch -} - -// scanString scans a quoted string -func (s *Scanner) scanString() { - braces := 0 - for { - // '"' opening already consumed - // read character after quote - ch := s.next() - - if ch == '\n' || ch < 0 || ch == eof { - s.err("literal not terminated") - return - } - - if ch == '"' { - break - } - - // If we're going into a ${} then we can ignore quotes for awhile - if braces == 0 && ch == '$' && s.peek() == '{' { - braces++ - s.next() - } else if braces > 0 && ch == '{' { - braces++ - } - if braces > 0 && ch == '}' { - braces-- - } - - if ch == '\\' { - s.scanEscape() - } - } - - return -} - -// scanEscape scans an escape sequence -func (s *Scanner) scanEscape() rune { - // http://en.cppreference.com/w/cpp/language/escape - ch := s.next() // read character after '/' - switch ch { - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"': - // nothing to do - case '0', '1', '2', '3', '4', '5', '6', '7': - // octal notation - ch = s.scanDigits(ch, 8, 3) - case 'x': - // hexademical notation - ch = s.scanDigits(s.next(), 16, 2) - case 'u': - // universal character name - ch = s.scanDigits(s.next(), 16, 4) - case 'U': - // universal character name - ch = s.scanDigits(s.next(), 16, 8) - default: - s.err("illegal char escape") - } - return ch -} - -// scanDigits scans a rune with the given base for n times. For example an -// octal notation \184 would yield in scanDigits(ch, 8, 3) -func (s *Scanner) scanDigits(ch rune, base, n int) rune { - for n > 0 && digitVal(ch) < base { - ch = s.next() - n-- - } - if n > 0 { - s.err("illegal char escape") - } - - // we scanned all digits, put the last non digit char back - s.unread() - return ch -} - -// scanIdentifier scans an identifier and returns the literal string -func (s *Scanner) scanIdentifier() string { - offs := s.srcPos.Offset - s.lastCharLen - ch := s.next() - for isLetter(ch) || isDigit(ch) || ch == '-' { - ch = s.next() - } - - if ch != eof { - s.unread() // we got identifier, put back latest char - } - - return string(s.src[offs:s.srcPos.Offset]) -} - -// recentPosition returns the position of the character immediately after the -// character or token returned by the last call to Scan. -func (s *Scanner) recentPosition() (pos token.Pos) { - pos.Offset = s.srcPos.Offset - s.lastCharLen - switch { - case s.srcPos.Column > 0: - // common case: last character was not a '\n' - pos.Line = s.srcPos.Line - pos.Column = s.srcPos.Column - case s.lastLineLen > 0: - // last character was a '\n' - // (we cannot be at the beginning of the source - // since we have called next() at least once) - pos.Line = s.srcPos.Line - 1 - pos.Column = s.lastLineLen - default: - // at the beginning of the source - pos.Line = 1 - pos.Column = 1 - } - return -} - -// err prints the error of any scanning to s.Error function. If the function is -// not defined, by default it prints them to os.Stderr -func (s *Scanner) err(msg string) { - s.ErrorCount++ - pos := s.recentPosition() - - if s.Error != nil { - s.Error(pos, msg) - return - } - - fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) -} - -// isHexadecimal returns true if the given rune is a letter -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) -} - -// isHexadecimal returns true if the given rune is a decimal digit -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) -} - -// isHexadecimal returns true if the given rune is a decimal number -func isDecimal(ch rune) bool { - return '0' <= ch && ch <= '9' -} - -// isHexadecimal returns true if the given rune is an hexadecimal number -func isHexadecimal(ch rune) bool { - return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' -} - -// isWhitespace returns true if the rune is a space, tab, newline or carriage return -func isWhitespace(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' -} - -// digitVal returns the integer value of a given octal,decimal or hexadecimal rune -func digitVal(ch rune) int { - switch { - case '0' <= ch && ch <= '9': - return int(ch - '0') - case 'a' <= ch && ch <= 'f': - return int(ch - 'a' + 10) - case 'A' <= ch && ch <= 'F': - return int(ch - 'A' + 10) - } - return 16 // larger than any legal digit val -} diff --git a/vendor/github.com/hashicorp/hcl/json/token/position.go b/vendor/github.com/hashicorp/hcl/json/token/position.go deleted file mode 100644 index 59c1bb72d4..0000000000 --- a/vendor/github.com/hashicorp/hcl/json/token/position.go +++ /dev/null @@ -1,46 +0,0 @@ -package token - -import "fmt" - -// Pos describes an arbitrary source position -// including the file, line, and column location. -// A Position is valid if the line number is > 0. -type Pos struct { - Filename string // filename, if any - Offset int // offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (character count) -} - -// IsValid returns true if the position is valid. -func (p *Pos) IsValid() bool { return p.Line > 0 } - -// String returns a string in one of several forms: -// -// file:line:column valid position with file name -// line:column valid position without file name -// file invalid position with file name -// - invalid position without file name -func (p Pos) String() string { - s := p.Filename - if p.IsValid() { - if s != "" { - s += ":" - } - s += fmt.Sprintf("%d:%d", p.Line, p.Column) - } - if s == "" { - s = "-" - } - return s -} - -// Before reports whether the position p is before u. -func (p Pos) Before(u Pos) bool { - return u.Offset > p.Offset || u.Line > p.Line -} - -// After reports whether the position p is after u. -func (p Pos) After(u Pos) bool { - return u.Offset < p.Offset || u.Line < p.Line -} diff --git a/vendor/github.com/hashicorp/hcl/json/token/token.go b/vendor/github.com/hashicorp/hcl/json/token/token.go deleted file mode 100644 index 95a0c3eee6..0000000000 --- a/vendor/github.com/hashicorp/hcl/json/token/token.go +++ /dev/null @@ -1,118 +0,0 @@ -package token - -import ( - "fmt" - "strconv" - - hcltoken "github.com/hashicorp/hcl/hcl/token" -) - -// Token defines a single HCL token which can be obtained via the Scanner -type Token struct { - Type Type - Pos Pos - Text string -} - -// Type is the set of lexical tokens of the HCL (HashiCorp Configuration Language) -type Type int - -const ( - // Special tokens - ILLEGAL Type = iota - EOF - - identifier_beg - literal_beg - NUMBER // 12345 - FLOAT // 123.45 - BOOL // true,false - STRING // "abc" - NULL // null - literal_end - identifier_end - - operator_beg - LBRACK // [ - LBRACE // { - COMMA // , - PERIOD // . - COLON // : - - RBRACK // ] - RBRACE // } - - operator_end -) - -var tokens = [...]string{ - ILLEGAL: "ILLEGAL", - - EOF: "EOF", - - NUMBER: "NUMBER", - FLOAT: "FLOAT", - BOOL: "BOOL", - STRING: "STRING", - NULL: "NULL", - - LBRACK: "LBRACK", - LBRACE: "LBRACE", - COMMA: "COMMA", - PERIOD: "PERIOD", - COLON: "COLON", - - RBRACK: "RBRACK", - RBRACE: "RBRACE", -} - -// String returns the string corresponding to the token tok. -func (t Type) String() string { - s := "" - if 0 <= t && t < Type(len(tokens)) { - s = tokens[t] - } - if s == "" { - s = "token(" + strconv.Itoa(int(t)) + ")" - } - return s -} - -// IsIdentifier returns true for tokens corresponding to identifiers and basic -// type literals; it returns false otherwise. -func (t Type) IsIdentifier() bool { return identifier_beg < t && t < identifier_end } - -// IsLiteral returns true for tokens corresponding to basic type literals; it -// returns false otherwise. -func (t Type) IsLiteral() bool { return literal_beg < t && t < literal_end } - -// IsOperator returns true for tokens corresponding to operators and -// delimiters; it returns false otherwise. -func (t Type) IsOperator() bool { return operator_beg < t && t < operator_end } - -// String returns the token's literal text. Note that this is only -// applicable for certain token types, such as token.IDENT, -// token.STRING, etc.. -func (t Token) String() string { - return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text) -} - -// HCLToken converts this token to an HCL token. -// -// The token type must be a literal type or this will panic. -func (t Token) HCLToken() hcltoken.Token { - switch t.Type { - case BOOL: - return hcltoken.Token{Type: hcltoken.BOOL, Text: t.Text} - case FLOAT: - return hcltoken.Token{Type: hcltoken.FLOAT, Text: t.Text} - case NULL: - return hcltoken.Token{Type: hcltoken.STRING, Text: ""} - case NUMBER: - return hcltoken.Token{Type: hcltoken.NUMBER, Text: t.Text} - case STRING: - return hcltoken.Token{Type: hcltoken.STRING, Text: t.Text, JSON: true} - default: - panic(fmt.Sprintf("unimplemented HCLToken for type: %s", t.Type)) - } -} diff --git a/vendor/github.com/hashicorp/hcl/lex.go b/vendor/github.com/hashicorp/hcl/lex.go deleted file mode 100644 index d9993c2928..0000000000 --- a/vendor/github.com/hashicorp/hcl/lex.go +++ /dev/null @@ -1,38 +0,0 @@ -package hcl - -import ( - "unicode" - "unicode/utf8" -) - -type lexModeValue byte - -const ( - lexModeUnknown lexModeValue = iota - lexModeHcl - lexModeJson -) - -// lexMode returns whether we're going to be parsing in JSON -// mode or HCL mode. -func lexMode(v []byte) lexModeValue { - var ( - r rune - w int - offset int - ) - - for { - r, w = utf8.DecodeRune(v[offset:]) - offset += w - if unicode.IsSpace(r) { - continue - } - if r == '{' { - return lexModeJson - } - break - } - - return lexModeHcl -} diff --git a/vendor/github.com/hashicorp/hcl/parse.go b/vendor/github.com/hashicorp/hcl/parse.go deleted file mode 100644 index 1fca53c4ce..0000000000 --- a/vendor/github.com/hashicorp/hcl/parse.go +++ /dev/null @@ -1,39 +0,0 @@ -package hcl - -import ( - "fmt" - - "github.com/hashicorp/hcl/hcl/ast" - hclParser "github.com/hashicorp/hcl/hcl/parser" - jsonParser "github.com/hashicorp/hcl/json/parser" -) - -// ParseBytes accepts as input byte slice and returns ast tree. -// -// Input can be either JSON or HCL -func ParseBytes(in []byte) (*ast.File, error) { - return parse(in) -} - -// ParseString accepts input as a string and returns ast tree. -func ParseString(input string) (*ast.File, error) { - return parse([]byte(input)) -} - -func parse(in []byte) (*ast.File, error) { - switch lexMode(in) { - case lexModeHcl: - return hclParser.Parse(in) - case lexModeJson: - return jsonParser.Parse(in) - } - - return nil, fmt.Errorf("unknown config format") -} - -// Parse parses the given input and returns the root object. -// -// The input format can be either HCL or JSON. -func Parse(input string) (*ast.File, error) { - return parse([]byte(input)) -} diff --git a/vendor/github.com/klauspost/compress/.goreleaser.yml b/vendor/github.com/klauspost/compress/.goreleaser.yml index a22953805c..4528059ca6 100644 --- a/vendor/github.com/klauspost/compress/.goreleaser.yml +++ b/vendor/github.com/klauspost/compress/.goreleaser.yml @@ -1,5 +1,5 @@ -# This is an example goreleaser.yaml file with some sane defaults. -# Make sure to check the documentation at http://goreleaser.com +version: 2 + before: hooks: - ./gen.sh @@ -99,7 +99,7 @@ archives: checksum: name_template: 'checksums.txt' snapshot: - name_template: "{{ .Tag }}-next" + version_template: "{{ .Tag }}-next" changelog: sort: asc filters: diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index 05c7359e48..de264c85a5 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -16,6 +16,27 @@ This package provides various compression algorithms. # changelog +* Sep 23rd, 2024 - [1.17.10](https://github.com/klauspost/compress/releases/tag/v1.17.10) + * gzhttp: Add TransportAlwaysDecompress option. https://github.com/klauspost/compress/pull/978 + * gzhttp: Add supported decompress request body by @mirecl in https://github.com/klauspost/compress/pull/1002 + * s2: Add EncodeBuffer buffer recycling callback https://github.com/klauspost/compress/pull/982 + * zstd: Improve memory usage on small streaming encodes https://github.com/klauspost/compress/pull/1007 + * flate: read data written with partial flush by @vajexal in https://github.com/klauspost/compress/pull/996 + +* Jun 12th, 2024 - [1.17.9](https://github.com/klauspost/compress/releases/tag/v1.17.9) + * s2: Reduce ReadFrom temporary allocations https://github.com/klauspost/compress/pull/949 + * flate, zstd: Shave some bytes off amd64 matchLen by @greatroar in https://github.com/klauspost/compress/pull/963 + * Upgrade zip/zlib to 1.22.4 upstream https://github.com/klauspost/compress/pull/970 https://github.com/klauspost/compress/pull/971 + * zstd: BuildDict fails with RLE table https://github.com/klauspost/compress/pull/951 + +* Apr 9th, 2024 - [1.17.8](https://github.com/klauspost/compress/releases/tag/v1.17.8) + * zstd: Reject blocks where reserved values are not 0 https://github.com/klauspost/compress/pull/885 + * zstd: Add RLE detection+encoding https://github.com/klauspost/compress/pull/938 + +* Feb 21st, 2024 - [1.17.7](https://github.com/klauspost/compress/releases/tag/v1.17.7) + * s2: Add AsyncFlush method: Complete the block without flushing by @Jille in https://github.com/klauspost/compress/pull/927 + * s2: Fix literal+repeat exceeds dst crash https://github.com/klauspost/compress/pull/930 + * Feb 5th, 2024 - [1.17.6](https://github.com/klauspost/compress/releases/tag/v1.17.6) * zstd: Fix incorrect repeat coding in best mode https://github.com/klauspost/compress/pull/923 * s2: Fix DecodeConcurrent deadlock on errors https://github.com/klauspost/compress/pull/925 @@ -81,7 +102,7 @@ https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/comp * zstd: Various minor improvements by @greatroar in https://github.com/klauspost/compress/pull/788 https://github.com/klauspost/compress/pull/794 https://github.com/klauspost/compress/pull/795 * s2: Fix huge block overflow https://github.com/klauspost/compress/pull/779 * s2: Allow CustomEncoder fallback https://github.com/klauspost/compress/pull/780 - * gzhttp: Suppport ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799 + * gzhttp: Support ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799 * Mar 13, 2023 - [v1.16.1](https://github.com/klauspost/compress/releases/tag/v1.16.1) * zstd: Speed up + improve best encoder by @greatroar in https://github.com/klauspost/compress/pull/776 @@ -136,7 +157,7 @@ https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/comp * zstd: Add [WithDecodeAllCapLimit](https://pkg.go.dev/github.com/klauspost/compress@v1.15.10/zstd#WithDecodeAllCapLimit) https://github.com/klauspost/compress/pull/649 * Add Go 1.19 - deprecate Go 1.16 https://github.com/klauspost/compress/pull/651 * flate: Improve level 5+6 compression https://github.com/klauspost/compress/pull/656 - * zstd: Improve "better" compresssion https://github.com/klauspost/compress/pull/657 + * zstd: Improve "better" compression https://github.com/klauspost/compress/pull/657 * s2: Improve "best" compression https://github.com/klauspost/compress/pull/658 * s2: Improve "better" compression. https://github.com/klauspost/compress/pull/635 * s2: Slightly faster non-assembly decompression https://github.com/klauspost/compress/pull/646 @@ -339,7 +360,7 @@ While the release has been extensively tested, it is recommended to testing when * s2: Fix binaries. * Feb 25, 2021 (v1.11.8) - * s2: Fixed occational out-of-bounds write on amd64. Upgrade recommended. + * s2: Fixed occasional out-of-bounds write on amd64. Upgrade recommended. * s2: Add AMD64 assembly for better mode. 25-50% faster. [#315](https://github.com/klauspost/compress/pull/315) * s2: Less upfront decoder allocation. [#322](https://github.com/klauspost/compress/pull/322) * zstd: Faster "compression" of incompressible data. [#314](https://github.com/klauspost/compress/pull/314) @@ -518,7 +539,7 @@ While the release has been extensively tested, it is recommended to testing when * Feb 19, 2016: Faster bit writer, level -2 is 15% faster, level 1 is 4% faster. * Feb 19, 2016: Handle small payloads faster in level 1-3. * Feb 19, 2016: Added faster level 2 + 3 compression modes. -* Feb 19, 2016: [Rebalanced compression levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/), so there is a more even progresssion in terms of compression. New default level is 5. +* Feb 19, 2016: [Rebalanced compression levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/), so there is a more even progression in terms of compression. New default level is 5. * Feb 14, 2016: Snappy: Merge upstream changes. * Feb 14, 2016: Snappy: Fix aggressive skipping. * Feb 14, 2016: Snappy: Update benchmark. diff --git a/vendor/github.com/klauspost/compress/fse/decompress.go b/vendor/github.com/klauspost/compress/fse/decompress.go index cc05d0f7ea..0c7dd4ffef 100644 --- a/vendor/github.com/klauspost/compress/fse/decompress.go +++ b/vendor/github.com/klauspost/compress/fse/decompress.go @@ -15,7 +15,7 @@ const ( // It is possible, but by no way guaranteed that corrupt data will // return an error. // It is up to the caller to verify integrity of the returned data. -// Use a predefined Scrach to set maximum acceptable output size. +// Use a predefined Scratch to set maximum acceptable output size. func Decompress(b []byte, s *Scratch) ([]byte, error) { s, err := s.prepare(b) if err != nil { diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go index 54bd08b25c..0f56b02d74 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress.go +++ b/vendor/github.com/klauspost/compress/huff0/decompress.go @@ -1136,7 +1136,7 @@ func (s *Scratch) matches(ct cTable, w io.Writer) { errs++ } if errs > 0 { - fmt.Fprintf(w, "%d errros in base, stopping\n", errs) + fmt.Fprintf(w, "%d errors in base, stopping\n", errs) continue } // Ensure that all combinations are covered. @@ -1152,7 +1152,7 @@ func (s *Scratch) matches(ct cTable, w io.Writer) { errs++ } if errs > 20 { - fmt.Fprintf(w, "%d errros, stopping\n", errs) + fmt.Fprintf(w, "%d errors, stopping\n", errs) break } } diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go index 03744fbc76..9c28840c3b 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -598,7 +598,9 @@ func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) { printf("RLE set to 0x%x, code: %v", symb, v) } case compModeFSE: - println("Reading table for", tableIndex(i)) + if debugDecoder { + println("Reading table for", tableIndex(i)) + } if seq.fse == nil || seq.fse.preDefined { seq.fse = fseDecoderPool.Get().(*fseDecoder) } diff --git a/vendor/github.com/klauspost/compress/zstd/enc_better.go b/vendor/github.com/klauspost/compress/zstd/enc_better.go index a4f5bf91fc..84a79fde76 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_better.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_better.go @@ -179,9 +179,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -210,12 +210,12 @@ encodeLoop: // Index match start+1 (long) -> s - 1 index0 := s + repOff - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -241,9 +241,9 @@ encodeLoop: if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) { // Consider history as well. var seq seq - lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) + length := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -270,11 +270,11 @@ encodeLoop: } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff2 + s += length + repOff2 nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -708,9 +708,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -738,12 +738,12 @@ encodeLoop: blk.sequences = append(blk.sequences, seq) // Index match start+1 (long) -> s - 1 - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -772,9 +772,9 @@ encodeLoop: if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) { // Consider history as well. var seq seq - lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) + length := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -801,11 +801,11 @@ encodeLoop: } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff2 + s += length + repOff2 nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop diff --git a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go index a154c18f74..d36be7bd8c 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go @@ -138,9 +138,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -166,11 +166,11 @@ encodeLoop: println("repeat sequence", seq, "next s:", s) } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -798,9 +798,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -826,11 +826,11 @@ encodeLoop: println("repeat sequence", seq, "next s:", s) } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop diff --git a/vendor/github.com/klauspost/compress/zstd/encoder.go b/vendor/github.com/klauspost/compress/zstd/encoder.go index 72af7ef0fe..8f8223cd3a 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder.go @@ -6,6 +6,7 @@ package zstd import ( "crypto/rand" + "errors" "fmt" "io" "math" @@ -149,6 +150,9 @@ func (e *Encoder) ResetContentSize(w io.Writer, size int64) { // and write CRC if requested. func (e *Encoder) Write(p []byte) (n int, err error) { s := &e.state + if s.eofWritten { + return 0, ErrEncoderClosed + } for len(p) > 0 { if len(p)+len(s.filling) < e.o.blockSize { if e.o.crc { @@ -202,7 +206,7 @@ func (e *Encoder) nextBlock(final bool) error { return nil } if final && len(s.filling) > 0 { - s.current = e.EncodeAll(s.filling, s.current[:0]) + s.current = e.encodeAll(s.encoder, s.filling, s.current[:0]) var n2 int n2, s.err = s.w.Write(s.current) if s.err != nil { @@ -288,6 +292,9 @@ func (e *Encoder) nextBlock(final bool) error { s.filling, s.current, s.previous = s.previous[:0], s.filling, s.current s.nInput += int64(len(s.current)) s.wg.Add(1) + if final { + s.eofWritten = true + } go func(src []byte) { if debugEncoder { println("Adding block,", len(src), "bytes, final:", final) @@ -303,9 +310,6 @@ func (e *Encoder) nextBlock(final bool) error { blk := enc.Block() enc.Encode(blk, src) blk.last = final - if final { - s.eofWritten = true - } // Wait for pending writes. s.wWg.Wait() if s.writeErr != nil { @@ -401,12 +405,20 @@ func (e *Encoder) Flush() error { if len(s.filling) > 0 { err := e.nextBlock(false) if err != nil { + // Ignore Flush after Close. + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } return err } } s.wg.Wait() s.wWg.Wait() if s.err != nil { + // Ignore Flush after Close. + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } return s.err } return s.writeErr @@ -422,6 +434,9 @@ func (e *Encoder) Close() error { } err := e.nextBlock(true) if err != nil { + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } return err } if s.frameContentSize > 0 { @@ -459,6 +474,11 @@ func (e *Encoder) Close() error { } _, s.err = s.w.Write(frame) } + if s.err == nil { + s.err = ErrEncoderClosed + return nil + } + return s.err } @@ -469,6 +489,15 @@ func (e *Encoder) Close() error { // Data compressed with EncodeAll can be decoded with the Decoder, // using either a stream or DecodeAll. func (e *Encoder) EncodeAll(src, dst []byte) []byte { + e.init.Do(e.initialize) + enc := <-e.encoders + defer func() { + e.encoders <- enc + }() + return e.encodeAll(enc, src, dst) +} + +func (e *Encoder) encodeAll(enc encoder, src, dst []byte) []byte { if len(src) == 0 { if e.o.fullZero { // Add frame header. @@ -491,13 +520,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte { } return dst } - e.init.Do(e.initialize) - enc := <-e.encoders - defer func() { - // Release encoder reference to last block. - // If a non-single block is needed the encoder will reset again. - e.encoders <- enc - }() + // Use single segments when above minimum window and below window size. single := len(src) <= e.o.windowSize && len(src) > MinWindowSize if e.o.single != nil { diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go index 53e160f7e5..e47af66e7c 100644 --- a/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -146,7 +146,9 @@ func (d *frameDec) reset(br byteBuffer) error { } return err } - printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3) + if debugDecoder { + printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3) + } windowLog := 10 + (wd >> 3) windowBase := uint64(1) << windowLog windowAdd := (windowBase / 8) * uint64(wd&0x7) diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go index 8adabd8287..c59f17e07a 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go @@ -146,7 +146,7 @@ func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) default: - return true, fmt.Errorf("sequenceDecs_decode returned erronous code %d", errCode) + return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode) } s.seqSize += ctx.litRemain @@ -292,7 +292,7 @@ func (s *sequenceDecs) decode(seqs []seqVals) error { return io.ErrUnexpectedEOF } - return fmt.Errorf("sequenceDecs_decode_amd64 returned erronous code %d", errCode) + return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode) } if ctx.litRemain < 0 { diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s index 5b06174b89..f5591fa1e8 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s @@ -1814,7 +1814,7 @@ TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32 MOVQ 40(SP), AX ADDQ AX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R10, 32(SP) // outBase += outPosition @@ -2376,7 +2376,7 @@ TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32 MOVQ 40(SP), CX ADDQ CX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R9, 32(SP) // outBase += outPosition @@ -2896,7 +2896,7 @@ TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32 MOVQ 40(SP), AX ADDQ AX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R10, 32(SP) // outBase += outPosition @@ -3560,7 +3560,7 @@ TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32 MOVQ 40(SP), CX ADDQ CX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R9, 32(SP) // outBase += outPosition diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go index 4be7cc7367..066bef2a4f 100644 --- a/vendor/github.com/klauspost/compress/zstd/zstd.go +++ b/vendor/github.com/klauspost/compress/zstd/zstd.go @@ -88,6 +88,10 @@ var ( // Close has been called. ErrDecoderClosed = errors.New("decoder used after Close") + // ErrEncoderClosed will be returned if the Encoder was used after + // Close has been called. + ErrEncoderClosed = errors.New("encoder used after Close") + // ErrDecoderNilInput is returned when a nil Reader was provided // and an operation other than Reset/DecodeAll/Close was attempted. ErrDecoderNilInput = errors.New("nil input provided as reader") diff --git a/vendor/github.com/magiconair/properties/.gitignore b/vendor/github.com/magiconair/properties/.gitignore deleted file mode 100644 index e7081ff522..0000000000 --- a/vendor/github.com/magiconair/properties/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.sublime-project -*.sublime-workspace -*.un~ -*.swp -.idea/ -*.iml diff --git a/vendor/github.com/magiconair/properties/CHANGELOG.md b/vendor/github.com/magiconair/properties/CHANGELOG.md deleted file mode 100644 index 842e8e24fb..0000000000 --- a/vendor/github.com/magiconair/properties/CHANGELOG.md +++ /dev/null @@ -1,205 +0,0 @@ -## Changelog - -### [1.8.7](https://github.com/magiconair/properties/tree/v1.8.7) - 08 Dec 2022 - - * [PR #65](https://github.com/magiconair/properties/pull/65): Speedup Merge - - Thanks to [@AdityaVallabh](https://github.com/AdityaVallabh) for the patch. - - * [PR #66](https://github.com/magiconair/properties/pull/66): use github actions - -### [1.8.6](https://github.com/magiconair/properties/tree/v1.8.6) - 23 Feb 2022 - - * [PR #57](https://github.com/magiconair/properties/pull/57):Fix "unreachable code" lint error - - Thanks to [@ellie](https://github.com/ellie) for the patch. - - * [PR #63](https://github.com/magiconair/properties/pull/63): Make TestMustGetParsedDuration backwards compatible - - This patch ensures that the `TestMustGetParsedDuration` still works with `go1.3` to make the - author happy until it affects real users. - - Thanks to [@maage](https://github.com/maage) for the patch. - -### [1.8.5](https://github.com/magiconair/properties/tree/v1.8.5) - 24 Mar 2021 - - * [PR #55](https://github.com/magiconair/properties/pull/55): Fix: Encoding Bug in Comments - - When reading comments \ are loaded correctly, but when writing they are then - replaced by \\. This leads to wrong comments when writing and reading multiple times. - - Thanks to [@doxsch](https://github.com/doxsch) for the patch. - -### [1.8.4](https://github.com/magiconair/properties/tree/v1.8.4) - 23 Sep 2020 - - * [PR #50](https://github.com/magiconair/properties/pull/50): enhance error message for circular references - - Thanks to [@sriv](https://github.com/sriv) for the patch. - -### [1.8.3](https://github.com/magiconair/properties/tree/v1.8.3) - 14 Sep 2020 - - * [PR #49](https://github.com/magiconair/properties/pull/49): Include the key in error message causing the circular reference - - The change is include the key in the error message which is causing the circular - reference when parsing/loading the properties files. - - Thanks to [@haroon-sheikh](https://github.com/haroon-sheikh) for the patch. - -### [1.8.2](https://github.com/magiconair/properties/tree/v1.8.2) - 25 Aug 2020 - - * [PR #36](https://github.com/magiconair/properties/pull/36): Escape backslash on write - - This patch ensures that backslashes are escaped on write. Existing applications which - rely on the old behavior may need to be updated. - - Thanks to [@apesternikov](https://github.com/apesternikov) for the patch. - - * [PR #42](https://github.com/magiconair/properties/pull/42): Made Content-Type check whitespace agnostic in LoadURL() - - Thanks to [@aliras1](https://github.com/aliras1) for the patch. - - * [PR #41](https://github.com/magiconair/properties/pull/41): Make key/value separator configurable on Write() - - Thanks to [@mkjor](https://github.com/mkjor) for the patch. - - * [PR #40](https://github.com/magiconair/properties/pull/40): Add method to return a sorted list of keys - - Thanks to [@mkjor](https://github.com/mkjor) for the patch. - -### [1.8.1](https://github.com/magiconair/properties/tree/v1.8.1) - 10 May 2019 - - * [PR #35](https://github.com/magiconair/properties/pull/35): Close body always after request - - This patch ensures that in `LoadURL` the response body is always closed. - - Thanks to [@liubog2008](https://github.com/liubog2008) for the patch. - -### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018 - - * [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading - - This adds the option to disable property expansion during loading. - - Thanks to [@kmala](https://github.com/kmala) for the patch. - -### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018 - - * [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases. - - See PR for an example. - - Thanks to [@yobert](https://github.com/yobert) for the fix. - -### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018 - - * [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value - - Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail - with a `circular reference error`. - - Thanks to [@yobert](https://github.com/yobert) for the fix. - -### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017 - - * [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces - - * [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled - - Thanks to [@mgurov](https://github.com/mgurov) for the fix. - -### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017 - - * [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically - * [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map - -### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017 - - * [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency - * [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc) - -### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017 - - * [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER` - * [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs - * [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy - * [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function - -### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016 - - * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL. - * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string. - * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe) - -### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015 - - * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags. - -### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015 - - * Vendored in gopkg.in/check.v1 - -### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015 - - * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs) - -### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015 - - * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references. - -### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015 - - * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) - -### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015 - - * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty - * Add clickable links to README - -### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014 - - * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with - [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). - -### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014 - - * Added support for single and multi-line comments (reading, writing and updating) - * The order of keys is now preserved - * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry - * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method - * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) - -### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014 - - * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one - -### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014 - - * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string - -### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014 - - * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys - * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties - -### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014 - -* Added support for time.Duration -* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom) -* Changed default of MustXXX() failure from panic to log.Fatal - -### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014 - -* Added MustGet... functions -* Added support for int and uint with range checks on 32 bit platforms - -### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014 - -* Renamed from goproperties to properties -* Added support for expansion of environment vars in - filenames and value expressions -* Fixed bug where value expressions were not at the - start of the string - -### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014 - -* Initial release diff --git a/vendor/github.com/magiconair/properties/LICENSE.md b/vendor/github.com/magiconair/properties/LICENSE.md deleted file mode 100644 index 79c87e3e6f..0000000000 --- a/vendor/github.com/magiconair/properties/LICENSE.md +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2013-2020, Frank Schroeder - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/magiconair/properties/README.md b/vendor/github.com/magiconair/properties/README.md deleted file mode 100644 index e2edda025b..0000000000 --- a/vendor/github.com/magiconair/properties/README.md +++ /dev/null @@ -1,128 +0,0 @@ -[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases) -[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties) -[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE) -[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) - -# Overview - -#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why. - -properties is a Go library for reading and writing properties files. - -It supports reading from multiple files or URLs and Spring style recursive -property expansion of expressions like `${key}` to their corresponding value. -Value expressions can refer to other keys like in `${key}` or to environment -variables like in `${USER}`. Filenames can also contain environment variables -like in `/home/${USER}/myapp.properties`. - -Properties can be decoded into structs, maps, arrays and values through -struct tags. - -Comments and the order of keys are preserved. Comments can be modified -and can be written to the output. - -The properties library supports both ISO-8859-1 and UTF-8 encoded data. - -Starting from version 1.3.0 the behavior of the MustXXX() functions is -configurable by providing a custom `ErrorHandler` function. The default has -changed from `panic` to `log.Fatal` but this is configurable and custom -error handling functions can be provided. See the package documentation for -details. - -Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) - -## Getting Started - -```go -import ( - "flag" - "github.com/magiconair/properties" -) - -func main() { - // init from a file - p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8) - - // or multiple files - p = properties.MustLoadFiles([]string{ - "${HOME}/config.properties", - "${HOME}/config-${USER}.properties", - }, properties.UTF8, true) - - // or from a map - p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"}) - - // or from a string - p = properties.MustLoadString("key=value\nabc=def") - - // or from a URL - p = properties.MustLoadURL("http://host/path") - - // or from multiple URLs - p = properties.MustLoadURL([]string{ - "http://host/config", - "http://host/config-${USER}", - }, true) - - // or from flags - p.MustFlag(flag.CommandLine) - - // get values through getters - host := p.MustGetString("host") - port := p.GetInt("port", 8080) - - // or through Decode - type Config struct { - Host string `properties:"host"` - Port int `properties:"port,default=9000"` - Accept []string `properties:"accept,default=image/png;image;gif"` - Timeout time.Duration `properties:"timeout,default=5s"` - } - var cfg Config - if err := p.Decode(&cfg); err != nil { - log.Fatal(err) - } -} - -``` - -## Installation and Upgrade - -``` -$ go get -u github.com/magiconair/properties -``` - -## License - -2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details. - -## ToDo - -* Dump contents with passwords and secrets obscured - -## Updated Git tags - -#### 13 Feb 2018 - -I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags -and I've only recently learned that this doesn't play well with `git describe` 😞 - -I have replaced all lightweight tags with signed tags using this script which should -retain the commit date, name and email address. Please run `git pull --tags` to update them. - -Worst case you have to reclone the repo. - -```shell -#!/bin/bash -tag=$1 -echo "Updating $tag" -date=$(git show ${tag}^0 --format=%aD | head -1) -email=$(git show ${tag}^0 --format=%aE | head -1) -name=$(git show ${tag}^0 --format=%aN | head -1) -GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag} -``` - -I apologize for the inconvenience. - -Frank - diff --git a/vendor/github.com/magiconair/properties/decode.go b/vendor/github.com/magiconair/properties/decode.go deleted file mode 100644 index 8e6aa441d9..0000000000 --- a/vendor/github.com/magiconair/properties/decode.go +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "reflect" - "strconv" - "strings" - "time" -) - -// Decode assigns property values to exported fields of a struct. -// -// Decode traverses v recursively and returns an error if a value cannot be -// converted to the field type or a required value is missing for a field. -// -// The following type dependent decodings are used: -// -// String, boolean, numeric fields have the value of the property key assigned. -// The property key name is the name of the field. A different key and a default -// value can be set in the field's tag. Fields without default value are -// required. If the value cannot be converted to the field type an error is -// returned. -// -// time.Duration fields have the result of time.ParseDuration() assigned. -// -// time.Time fields have the vaule of time.Parse() assigned. The default layout -// is time.RFC3339 but can be set in the field's tag. -// -// Arrays and slices of string, boolean, numeric, time.Duration and time.Time -// fields have the value interpreted as a comma separated list of values. The -// individual values are trimmed of whitespace and empty values are ignored. A -// default value can be provided as a semicolon separated list in the field's -// tag. -// -// Struct fields are decoded recursively using the field name plus "." as -// prefix. The prefix (without dot) can be overridden in the field's tag. -// Default values are not supported in the field's tag. Specify them on the -// fields of the inner struct instead. -// -// Map fields must have a key of type string and are decoded recursively by -// using the field's name plus ".' as prefix and the next element of the key -// name as map key. The prefix (without dot) can be overridden in the field's -// tag. Default values are not supported. -// -// Examples: -// -// // Field is ignored. -// Field int `properties:"-"` -// -// // Field is assigned value of 'Field'. -// Field int -// -// // Field is assigned value of 'myName'. -// Field int `properties:"myName"` -// -// // Field is assigned value of key 'myName' and has a default -// // value 15 if the key does not exist. -// Field int `properties:"myName,default=15"` -// -// // Field is assigned value of key 'Field' and has a default -// // value 15 if the key does not exist. -// Field int `properties:",default=15"` -// -// // Field is assigned value of key 'date' and the date -// // is in format 2006-01-02 -// Field time.Time `properties:"date,layout=2006-01-02"` -// -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas. -// Field []string -// -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas and has a default -// // value ["a", "b", "c"] if the key does not exist. -// Field []string `properties:",default=a;b;c"` -// -// // Field is decoded recursively with "Field." as key prefix. -// Field SomeStruct -// -// // Field is decoded recursively with "myName." as key prefix. -// Field SomeStruct `properties:"myName"` -// -// // Field is decoded recursively with "Field." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string -// -// // Field is decoded recursively with "myName." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string `properties:"myName"` -func (p *Properties) Decode(x interface{}) error { - t, v := reflect.TypeOf(x), reflect.ValueOf(x) - if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct { - return fmt.Errorf("not a pointer to struct: %s", t) - } - if err := dec(p, "", nil, nil, v); err != nil { - return err - } - return nil -} - -func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error { - t := v.Type() - - // value returns the property value for key or the default if provided. - value := func() (string, error) { - if val, ok := p.Get(key); ok { - return val, nil - } - if def != nil { - return *def, nil - } - return "", fmt.Errorf("missing required key %s", key) - } - - // conv converts a string to a value of the given type. - conv := func(s string, t reflect.Type) (val reflect.Value, err error) { - var v interface{} - - switch { - case isDuration(t): - v, err = time.ParseDuration(s) - - case isTime(t): - layout := opts["layout"] - if layout == "" { - layout = time.RFC3339 - } - v, err = time.Parse(layout, s) - - case isBool(t): - v, err = boolVal(s), nil - - case isString(t): - v, err = s, nil - - case isFloat(t): - v, err = strconv.ParseFloat(s, 64) - - case isInt(t): - v, err = strconv.ParseInt(s, 10, 64) - - case isUint(t): - v, err = strconv.ParseUint(s, 10, 64) - - default: - return reflect.Zero(t), fmt.Errorf("unsupported type %s", t) - } - if err != nil { - return reflect.Zero(t), err - } - return reflect.ValueOf(v).Convert(t), nil - } - - // keydef returns the property key and the default value based on the - // name of the struct field and the options in the tag. - keydef := func(f reflect.StructField) (string, *string, map[string]string) { - _key, _opts := parseTag(f.Tag.Get("properties")) - - var _def *string - if d, ok := _opts["default"]; ok { - _def = &d - } - if _key != "" { - return _key, _def, _opts - } - return f.Name, _def, _opts - } - - switch { - case isDuration(t) || isTime(t) || isBool(t) || isString(t) || isFloat(t) || isInt(t) || isUint(t): - s, err := value() - if err != nil { - return err - } - val, err := conv(s, t) - if err != nil { - return err - } - v.Set(val) - - case isPtr(t): - return dec(p, key, def, opts, v.Elem()) - - case isStruct(t): - for i := 0; i < v.NumField(); i++ { - fv := v.Field(i) - fk, def, opts := keydef(t.Field(i)) - if !fv.CanSet() { - return fmt.Errorf("cannot set %s", t.Field(i).Name) - } - if fk == "-" { - continue - } - if key != "" { - fk = key + "." + fk - } - if err := dec(p, fk, def, opts, fv); err != nil { - return err - } - } - return nil - - case isArray(t): - val, err := value() - if err != nil { - return err - } - vals := split(val, ";") - a := reflect.MakeSlice(t, 0, len(vals)) - for _, s := range vals { - val, err := conv(s, t.Elem()) - if err != nil { - return err - } - a = reflect.Append(a, val) - } - v.Set(a) - - case isMap(t): - valT := t.Elem() - m := reflect.MakeMap(t) - for postfix := range p.FilterStripPrefix(key + ".").m { - pp := strings.SplitN(postfix, ".", 2) - mk, mv := pp[0], reflect.New(valT) - if err := dec(p, key+"."+mk, nil, nil, mv); err != nil { - return err - } - m.SetMapIndex(reflect.ValueOf(mk), mv.Elem()) - } - v.Set(m) - - default: - return fmt.Errorf("unsupported type %s", t) - } - return nil -} - -// split splits a string on sep, trims whitespace of elements -// and omits empty elements -func split(s string, sep string) []string { - var a []string - for _, v := range strings.Split(s, sep) { - if v = strings.TrimSpace(v); v != "" { - a = append(a, v) - } - } - return a -} - -// parseTag parses a "key,k=v,k=v,..." -func parseTag(tag string) (key string, opts map[string]string) { - opts = map[string]string{} - for i, s := range strings.Split(tag, ",") { - if i == 0 { - key = s - continue - } - - pp := strings.SplitN(s, "=", 2) - if len(pp) == 1 { - opts[pp[0]] = "" - } else { - opts[pp[0]] = pp[1] - } - } - return key, opts -} - -func isArray(t reflect.Type) bool { return t.Kind() == reflect.Array || t.Kind() == reflect.Slice } -func isBool(t reflect.Type) bool { return t.Kind() == reflect.Bool } -func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) } -func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } -func isPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr } -func isString(t reflect.Type) bool { return t.Kind() == reflect.String } -func isStruct(t reflect.Type) bool { return t.Kind() == reflect.Struct } -func isTime(t reflect.Type) bool { return t == reflect.TypeOf(time.Time{}) } -func isFloat(t reflect.Type) bool { - return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64 -} -func isInt(t reflect.Type) bool { - return t.Kind() == reflect.Int || t.Kind() == reflect.Int8 || t.Kind() == reflect.Int16 || t.Kind() == reflect.Int32 || t.Kind() == reflect.Int64 -} -func isUint(t reflect.Type) bool { - return t.Kind() == reflect.Uint || t.Kind() == reflect.Uint8 || t.Kind() == reflect.Uint16 || t.Kind() == reflect.Uint32 || t.Kind() == reflect.Uint64 -} diff --git a/vendor/github.com/magiconair/properties/doc.go b/vendor/github.com/magiconair/properties/doc.go deleted file mode 100644 index 7c79793159..0000000000 --- a/vendor/github.com/magiconair/properties/doc.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package properties provides functions for reading and writing -// ISO-8859-1 and UTF-8 encoded .properties files and has -// support for recursive property expansion. -// -// Java properties files are ISO-8859-1 encoded and use Unicode -// literals for characters outside the ISO character set. Unicode -// literals can be used in UTF-8 encoded properties files but -// aren't necessary. -// -// To load a single properties file use MustLoadFile(): -// -// p := properties.MustLoadFile(filename, properties.UTF8) -// -// To load multiple properties files use MustLoadFiles() -// which loads the files in the given order and merges the -// result. Missing properties files can be ignored if the -// 'ignoreMissing' flag is set to true. -// -// Filenames can contain environment variables which are expanded -// before loading. -// -// f1 := "/etc/myapp/myapp.conf" -// f2 := "/home/${USER}/myapp.conf" -// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) -// -// All of the different key/value delimiters ' ', ':' and '=' are -// supported as well as the comment characters '!' and '#' and -// multi-line values. -// -// ! this is a comment -// # and so is this -// -// # the following expressions are equal -// key value -// key=value -// key:value -// key = value -// key : value -// key = val\ -// ue -// -// Properties stores all comments preceding a key and provides -// GetComments() and SetComments() methods to retrieve and -// update them. The convenience functions GetComment() and -// SetComment() allow access to the last comment. The -// WriteComment() method writes properties files including -// the comments and with the keys in the original order. -// This can be used for sanitizing properties files. -// -// Property expansion is recursive and circular references -// and malformed expressions are not allowed and cause an -// error. Expansion of environment variables is supported. -// -// # standard property -// key = value -// -// # property expansion: key2 = value -// key2 = ${key} -// -// # recursive expansion: key3 = value -// key3 = ${key2} -// -// # circular reference (error) -// key = ${key} -// -// # malformed expression (error) -// key = ${ke -// -// # refers to the users' home dir -// home = ${HOME} -// -// # local key takes precedence over env var: u = foo -// USER = foo -// u = ${USER} -// -// The default property expansion format is ${key} but can be -// changed by setting different pre- and postfix values on the -// Properties object. -// -// p := properties.NewProperties() -// p.Prefix = "#[" -// p.Postfix = "]#" -// -// Properties provides convenience functions for getting typed -// values with default values if the key does not exist or the -// type conversion failed. -// -// # Returns true if the value is either "1", "on", "yes" or "true" -// # Returns false for every other value and the default value if -// # the key does not exist. -// v = p.GetBool("key", false) -// -// # Returns the value if the key exists and the format conversion -// # was successful. Otherwise, the default value is returned. -// v = p.GetInt64("key", 999) -// v = p.GetUint64("key", 999) -// v = p.GetFloat64("key", 123.0) -// v = p.GetString("key", "def") -// v = p.GetDuration("key", 999) -// -// As an alternative properties may be applied with the standard -// library's flag implementation at any time. -// -// # Standard configuration -// v = flag.Int("key", 999, "help message") -// flag.Parse() -// -// # Merge p into the flag set -// p.MustFlag(flag.CommandLine) -// -// Properties provides several MustXXX() convenience functions -// which will terminate the app if an error occurs. The behavior -// of the failure is configurable and the default is to call -// log.Fatal(err). To have the MustXXX() functions panic instead -// of logging the error set a different ErrorHandler before -// you use the Properties package. -// -// properties.ErrorHandler = properties.PanicHandler -// -// # Will panic instead of logging an error -// p := properties.MustLoadFile("config.properties") -// -// You can also provide your own ErrorHandler function. The only requirement -// is that the error handler function must exit after handling the error. -// -// properties.ErrorHandler = func(err error) { -// fmt.Println(err) -// os.Exit(1) -// } -// -// # Will write to stdout and then exit -// p := properties.MustLoadFile("config.properties") -// -// Properties can also be loaded into a struct via the `Decode` -// method, e.g. -// -// type S struct { -// A string `properties:"a,default=foo"` -// D time.Duration `properties:"timeout,default=5s"` -// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` -// } -// -// See `Decode()` method for the full documentation. -// -// The following documents provide a description of the properties -// file format. -// -// http://en.wikipedia.org/wiki/.properties -// -// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 -package properties diff --git a/vendor/github.com/magiconair/properties/integrate.go b/vendor/github.com/magiconair/properties/integrate.go deleted file mode 100644 index 35d0ae97b3..0000000000 --- a/vendor/github.com/magiconair/properties/integrate.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import "flag" - -// MustFlag sets flags that are skipped by dst.Parse when p contains -// the respective key for flag.Flag.Name. -// -// It's use is recommended with command line arguments as in: -// -// flag.Parse() -// p.MustFlag(flag.CommandLine) -func (p *Properties) MustFlag(dst *flag.FlagSet) { - m := make(map[string]*flag.Flag) - dst.VisitAll(func(f *flag.Flag) { - m[f.Name] = f - }) - dst.Visit(func(f *flag.Flag) { - delete(m, f.Name) // overridden - }) - - for name, f := range m { - v, ok := p.Get(name) - if !ok { - continue - } - - if err := f.Value.Set(v); err != nil { - ErrorHandler(err) - } - } -} diff --git a/vendor/github.com/magiconair/properties/lex.go b/vendor/github.com/magiconair/properties/lex.go deleted file mode 100644 index 3d15a1f6ed..0000000000 --- a/vendor/github.com/magiconair/properties/lex.go +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Parts of the lexer are from the template/text/parser package -// For these parts the following applies: -// -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file of the go 1.2 -// distribution. - -package properties - -import ( - "fmt" - "strconv" - "strings" - "unicode/utf8" -) - -// item represents a token or text string returned from the scanner. -type item struct { - typ itemType // The type of this item. - pos int // The starting position, in bytes, of this item in the input string. - val string // The value of this item. -} - -func (i item) String() string { - switch { - case i.typ == itemEOF: - return "EOF" - case i.typ == itemError: - return i.val - case len(i.val) > 10: - return fmt.Sprintf("%.10q...", i.val) - } - return fmt.Sprintf("%q", i.val) -} - -// itemType identifies the type of lex items. -type itemType int - -const ( - itemError itemType = iota // error occurred; value is text of error - itemEOF - itemKey // a key - itemValue // a value - itemComment // a comment -) - -// defines a constant for EOF -const eof = -1 - -// permitted whitespace characters space, FF and TAB -const whitespace = " \f\t" - -// stateFn represents the state of the scanner as a function that returns the next state. -type stateFn func(*lexer) stateFn - -// lexer holds the state of the scanner. -type lexer struct { - input string // the string being scanned - state stateFn // the next lexing function to enter - pos int // current position in the input - start int // start position of this item - width int // width of last rune read from input - lastPos int // position of most recent item returned by nextItem - runes []rune // scanned runes for this item - items chan item // channel of scanned items -} - -// next returns the next rune in the input. -func (l *lexer) next() rune { - if l.pos >= len(l.input) { - l.width = 0 - return eof - } - r, w := utf8.DecodeRuneInString(l.input[l.pos:]) - l.width = w - l.pos += l.width - return r -} - -// peek returns but does not consume the next rune in the input. -func (l *lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// backup steps back one rune. Can only be called once per call of next. -func (l *lexer) backup() { - l.pos -= l.width -} - -// emit passes an item back to the client. -func (l *lexer) emit(t itemType) { - i := item{t, l.start, string(l.runes)} - l.items <- i - l.start = l.pos - l.runes = l.runes[:0] -} - -// ignore skips over the pending input before this point. -func (l *lexer) ignore() { - l.start = l.pos -} - -// appends the rune to the current value -func (l *lexer) appendRune(r rune) { - l.runes = append(l.runes, r) -} - -// accept consumes the next rune if it's from the valid set. -func (l *lexer) accept(valid string) bool { - if strings.ContainsRune(valid, l.next()) { - return true - } - l.backup() - return false -} - -// acceptRun consumes a run of runes from the valid set. -func (l *lexer) acceptRun(valid string) { - for strings.ContainsRune(valid, l.next()) { - } - l.backup() -} - -// lineNumber reports which line we're on, based on the position of -// the previous item returned by nextItem. Doing it this way -// means we don't have to worry about peek double counting. -func (l *lexer) lineNumber() int { - return 1 + strings.Count(l.input[:l.lastPos], "\n") -} - -// errorf returns an error token and terminates the scan by passing -// back a nil pointer that will be the next state, terminating l.nextItem. -func (l *lexer) errorf(format string, args ...interface{}) stateFn { - l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} - return nil -} - -// nextItem returns the next item from the input. -func (l *lexer) nextItem() item { - i := <-l.items - l.lastPos = i.pos - return i -} - -// lex creates a new scanner for the input string. -func lex(input string) *lexer { - l := &lexer{ - input: input, - items: make(chan item), - runes: make([]rune, 0, 32), - } - go l.run() - return l -} - -// run runs the state machine for the lexer. -func (l *lexer) run() { - for l.state = lexBeforeKey(l); l.state != nil; { - l.state = l.state(l) - } -} - -// state functions - -// lexBeforeKey scans until a key begins. -func lexBeforeKey(l *lexer) stateFn { - switch r := l.next(); { - case isEOF(r): - l.emit(itemEOF) - return nil - - case isEOL(r): - l.ignore() - return lexBeforeKey - - case isComment(r): - return lexComment - - case isWhitespace(r): - l.ignore() - return lexBeforeKey - - default: - l.backup() - return lexKey - } -} - -// lexComment scans a comment line. The comment character has already been scanned. -func lexComment(l *lexer) stateFn { - l.acceptRun(whitespace) - l.ignore() - for { - switch r := l.next(); { - case isEOF(r): - l.ignore() - l.emit(itemEOF) - return nil - case isEOL(r): - l.emit(itemComment) - return lexBeforeKey - default: - l.appendRune(r) - } - } -} - -// lexKey scans the key up to a delimiter -func lexKey(l *lexer) stateFn { - var r rune - -Loop: - for { - switch r = l.next(); { - - case isEscape(r): - err := l.scanEscapeSequence() - if err != nil { - return l.errorf(err.Error()) - } - - case isEndOfKey(r): - l.backup() - break Loop - - case isEOF(r): - break Loop - - default: - l.appendRune(r) - } - } - - if len(l.runes) > 0 { - l.emit(itemKey) - } - - if isEOF(r) { - l.emit(itemEOF) - return nil - } - - return lexBeforeValue -} - -// lexBeforeValue scans the delimiter between key and value. -// Leading and trailing whitespace is ignored. -// We expect to be just after the key. -func lexBeforeValue(l *lexer) stateFn { - l.acceptRun(whitespace) - l.accept(":=") - l.acceptRun(whitespace) - l.ignore() - return lexValue -} - -// lexValue scans text until the end of the line. We expect to be just after the delimiter. -func lexValue(l *lexer) stateFn { - for { - switch r := l.next(); { - case isEscape(r): - if isEOL(l.peek()) { - l.next() - l.acceptRun(whitespace) - } else { - err := l.scanEscapeSequence() - if err != nil { - return l.errorf(err.Error()) - } - } - - case isEOL(r): - l.emit(itemValue) - l.ignore() - return lexBeforeKey - - case isEOF(r): - l.emit(itemValue) - l.emit(itemEOF) - return nil - - default: - l.appendRune(r) - } - } -} - -// scanEscapeSequence scans either one of the escaped characters -// or a unicode literal. We expect to be after the escape character. -func (l *lexer) scanEscapeSequence() error { - switch r := l.next(); { - - case isEscapedCharacter(r): - l.appendRune(decodeEscapedCharacter(r)) - return nil - - case atUnicodeLiteral(r): - return l.scanUnicodeLiteral() - - case isEOF(r): - return fmt.Errorf("premature EOF") - - // silently drop the escape character and append the rune as is - default: - l.appendRune(r) - return nil - } -} - -// scans a unicode literal in the form \uXXXX. We expect to be after the \u. -func (l *lexer) scanUnicodeLiteral() error { - // scan the digits - d := make([]rune, 4) - for i := 0; i < 4; i++ { - d[i] = l.next() - if d[i] == eof || !strings.ContainsRune("0123456789abcdefABCDEF", d[i]) { - return fmt.Errorf("invalid unicode literal") - } - } - - // decode the digits into a rune - r, err := strconv.ParseInt(string(d), 16, 0) - if err != nil { - return err - } - - l.appendRune(rune(r)) - return nil -} - -// decodeEscapedCharacter returns the unescaped rune. We expect to be after the escape character. -func decodeEscapedCharacter(r rune) rune { - switch r { - case 'f': - return '\f' - case 'n': - return '\n' - case 'r': - return '\r' - case 't': - return '\t' - default: - return r - } -} - -// atUnicodeLiteral reports whether we are at a unicode literal. -// The escape character has already been consumed. -func atUnicodeLiteral(r rune) bool { - return r == 'u' -} - -// isComment reports whether we are at the start of a comment. -func isComment(r rune) bool { - return r == '#' || r == '!' -} - -// isEndOfKey reports whether the rune terminates the current key. -func isEndOfKey(r rune) bool { - return strings.ContainsRune(" \f\t\r\n:=", r) -} - -// isEOF reports whether we are at EOF. -func isEOF(r rune) bool { - return r == eof -} - -// isEOL reports whether we are at a new line character. -func isEOL(r rune) bool { - return r == '\n' || r == '\r' -} - -// isEscape reports whether the rune is the escape character which -// prefixes unicode literals and other escaped characters. -func isEscape(r rune) bool { - return r == '\\' -} - -// isEscapedCharacter reports whether we are at one of the characters that need escaping. -// The escape character has already been consumed. -func isEscapedCharacter(r rune) bool { - return strings.ContainsRune(" :=fnrt", r) -} - -// isWhitespace reports whether the rune is a whitespace character. -func isWhitespace(r rune) bool { - return strings.ContainsRune(whitespace, r) -} diff --git a/vendor/github.com/magiconair/properties/load.go b/vendor/github.com/magiconair/properties/load.go deleted file mode 100644 index 635368dc8a..0000000000 --- a/vendor/github.com/magiconair/properties/load.go +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "io/ioutil" - "net/http" - "os" - "strings" -) - -// Encoding specifies encoding of the input data. -type Encoding uint - -const ( - // utf8Default is a private placeholder for the zero value of Encoding to - // ensure that it has the correct meaning. UTF8 is the default encoding but - // was assigned a non-zero value which cannot be changed without breaking - // existing code. Clients should continue to use the public constants. - utf8Default Encoding = iota - - // UTF8 interprets the input data as UTF-8. - UTF8 - - // ISO_8859_1 interprets the input data as ISO-8859-1. - ISO_8859_1 -) - -type Loader struct { - // Encoding determines how the data from files and byte buffers - // is interpreted. For URLs the Content-Type header is used - // to determine the encoding of the data. - Encoding Encoding - - // DisableExpansion configures the property expansion of the - // returned property object. When set to true, the property values - // will not be expanded and the Property object will not be checked - // for invalid expansion expressions. - DisableExpansion bool - - // IgnoreMissing configures whether missing files or URLs which return - // 404 are reported as errors. When set to true, missing files and 404 - // status codes are not reported as errors. - IgnoreMissing bool -} - -// Load reads a buffer into a Properties struct. -func (l *Loader) LoadBytes(buf []byte) (*Properties, error) { - return l.loadBytes(buf, l.Encoding) -} - -// LoadAll reads the content of multiple URLs or files in the given order into -// a Properties struct. If IgnoreMissing is true then a 404 status code or -// missing file will not be reported as error. Encoding sets the encoding for -// files. For the URLs see LoadURL for the Content-Type header and the -// encoding. -func (l *Loader) LoadAll(names []string) (*Properties, error) { - all := NewProperties() - for _, name := range names { - n, err := expandName(name) - if err != nil { - return nil, err - } - - var p *Properties - switch { - case strings.HasPrefix(n, "http://"): - p, err = l.LoadURL(n) - case strings.HasPrefix(n, "https://"): - p, err = l.LoadURL(n) - default: - p, err = l.LoadFile(n) - } - if err != nil { - return nil, err - } - all.Merge(p) - } - - all.DisableExpansion = l.DisableExpansion - if all.DisableExpansion { - return all, nil - } - return all, all.check() -} - -// LoadFile reads a file into a Properties struct. -// If IgnoreMissing is true then a missing file will not be -// reported as error. -func (l *Loader) LoadFile(filename string) (*Properties, error) { - data, err := ioutil.ReadFile(filename) - if err != nil { - if l.IgnoreMissing && os.IsNotExist(err) { - LogPrintf("properties: %s not found. skipping", filename) - return NewProperties(), nil - } - return nil, err - } - return l.loadBytes(data, l.Encoding) -} - -// LoadURL reads the content of the URL into a Properties struct. -// -// The encoding is determined via the Content-Type header which -// should be set to 'text/plain'. If the 'charset' parameter is -// missing, 'iso-8859-1' or 'latin1' the encoding is set to -// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the -// encoding is set to UTF-8. A missing content type header is -// interpreted as 'text/plain; charset=utf-8'. -func (l *Loader) LoadURL(url string) (*Properties, error) { - resp, err := http.Get(url) - if err != nil { - return nil, fmt.Errorf("properties: error fetching %q. %s", url, err) - } - defer resp.Body.Close() - - if resp.StatusCode == 404 && l.IgnoreMissing { - LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode) - return NewProperties(), nil - } - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("properties: %s error reading response. %s", url, err) - } - - ct := resp.Header.Get("Content-Type") - ct = strings.Join(strings.Fields(ct), "") - var enc Encoding - switch strings.ToLower(ct) { - case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1": - enc = ISO_8859_1 - case "", "text/plain;charset=utf-8": - enc = UTF8 - default: - return nil, fmt.Errorf("properties: invalid content type %s", ct) - } - - return l.loadBytes(body, enc) -} - -func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) { - p, err := parse(convert(buf, enc)) - if err != nil { - return nil, err - } - p.DisableExpansion = l.DisableExpansion - if p.DisableExpansion { - return p, nil - } - return p, p.check() -} - -// Load reads a buffer into a Properties struct. -func Load(buf []byte, enc Encoding) (*Properties, error) { - l := &Loader{Encoding: enc} - return l.LoadBytes(buf) -} - -// LoadString reads an UTF8 string into a properties struct. -func LoadString(s string) (*Properties, error) { - l := &Loader{Encoding: UTF8} - return l.LoadBytes([]byte(s)) -} - -// LoadMap creates a new Properties struct from a string map. -func LoadMap(m map[string]string) *Properties { - p := NewProperties() - for k, v := range m { - p.Set(k, v) - } - return p -} - -// LoadFile reads a file into a Properties struct. -func LoadFile(filename string, enc Encoding) (*Properties, error) { - l := &Loader{Encoding: enc} - return l.LoadAll([]string{filename}) -} - -// LoadFiles reads multiple files in the given order into -// a Properties struct. If 'ignoreMissing' is true then -// non-existent files will not be reported as error. -func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} - return l.LoadAll(filenames) -} - -// LoadURL reads the content of the URL into a Properties struct. -// See Loader#LoadURL for details. -func LoadURL(url string) (*Properties, error) { - l := &Loader{Encoding: UTF8} - return l.LoadAll([]string{url}) -} - -// LoadURLs reads the content of multiple URLs in the given order into a -// Properties struct. If IgnoreMissing is true then a 404 status code will -// not be reported as error. See Loader#LoadURL for the Content-Type header -// and the encoding. -func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing} - return l.LoadAll(urls) -} - -// LoadAll reads the content of multiple URLs or files in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will -// not be reported as error. Encoding sets the encoding for files. For the URLs please see -// LoadURL for the Content-Type header and the encoding. -func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} - return l.LoadAll(names) -} - -// MustLoadString reads an UTF8 string into a Properties struct and -// panics on error. -func MustLoadString(s string) *Properties { - return must(LoadString(s)) -} - -// MustLoadFile reads a file into a Properties struct and -// panics on error. -func MustLoadFile(filename string, enc Encoding) *Properties { - return must(LoadFile(filename, enc)) -} - -// MustLoadFiles reads multiple files in the given order into -// a Properties struct and panics on error. If 'ignoreMissing' -// is true then non-existent files will not be reported as error. -func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties { - return must(LoadFiles(filenames, enc, ignoreMissing)) -} - -// MustLoadURL reads the content of a URL into a Properties struct and -// panics on error. -func MustLoadURL(url string) *Properties { - return must(LoadURL(url)) -} - -// MustLoadURLs reads the content of multiple URLs in the given order into a -// Properties struct and panics on error. If 'ignoreMissing' is true then a 404 -// status code will not be reported as error. -func MustLoadURLs(urls []string, ignoreMissing bool) *Properties { - return must(LoadURLs(urls, ignoreMissing)) -} - -// MustLoadAll reads the content of multiple URLs or files in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will -// not be reported as error. Encoding sets the encoding for files. For the URLs please see -// LoadURL for the Content-Type header and the encoding. It panics on error. -func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties { - return must(LoadAll(names, enc, ignoreMissing)) -} - -func must(p *Properties, err error) *Properties { - if err != nil { - ErrorHandler(err) - } - return p -} - -// expandName expands ${ENV_VAR} expressions in a name. -// If the environment variable does not exist then it will be replaced -// with an empty string. Malformed expressions like "${ENV_VAR" will -// be reported as error. -func expandName(name string) (string, error) { - return expand(name, []string{}, "${", "}", make(map[string]string)) -} - -// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string. -// For ISO-8859-1 we can convert each byte straight into a rune since the -// first 256 unicode code points cover ISO-8859-1. -func convert(buf []byte, enc Encoding) string { - switch enc { - case utf8Default, UTF8: - return string(buf) - case ISO_8859_1: - runes := make([]rune, len(buf)) - for i, b := range buf { - runes[i] = rune(b) - } - return string(runes) - default: - ErrorHandler(fmt.Errorf("unsupported encoding %v", enc)) - } - panic("ErrorHandler should exit") -} diff --git a/vendor/github.com/magiconair/properties/parser.go b/vendor/github.com/magiconair/properties/parser.go deleted file mode 100644 index fccfd39f6b..0000000000 --- a/vendor/github.com/magiconair/properties/parser.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "runtime" -) - -type parser struct { - lex *lexer -} - -func parse(input string) (properties *Properties, err error) { - p := &parser{lex: lex(input)} - defer p.recover(&err) - - properties = NewProperties() - key := "" - comments := []string{} - - for { - token := p.expectOneOf(itemComment, itemKey, itemEOF) - switch token.typ { - case itemEOF: - goto done - case itemComment: - comments = append(comments, token.val) - continue - case itemKey: - key = token.val - if _, ok := properties.m[key]; !ok { - properties.k = append(properties.k, key) - } - } - - token = p.expectOneOf(itemValue, itemEOF) - if len(comments) > 0 { - properties.c[key] = comments - comments = []string{} - } - switch token.typ { - case itemEOF: - properties.m[key] = "" - goto done - case itemValue: - properties.m[key] = token.val - } - } - -done: - return properties, nil -} - -func (p *parser) errorf(format string, args ...interface{}) { - format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format) - panic(fmt.Errorf(format, args...)) -} - -func (p *parser) expectOneOf(expected ...itemType) (token item) { - token = p.lex.nextItem() - for _, v := range expected { - if token.typ == v { - return token - } - } - p.unexpected(token) - panic("unexpected token") -} - -func (p *parser) unexpected(token item) { - p.errorf(token.String()) -} - -// recover is the handler that turns panics into returns from the top level of Parse. -func (p *parser) recover(errp *error) { - e := recover() - if e != nil { - if _, ok := e.(runtime.Error); ok { - panic(e) - } - *errp = e.(error) - } -} diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go deleted file mode 100644 index fb2f7b4048..0000000000 --- a/vendor/github.com/magiconair/properties/properties.go +++ /dev/null @@ -1,848 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -// BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer. -// BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used. - -import ( - "bytes" - "fmt" - "io" - "log" - "os" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -const maxExpansionDepth = 64 - -// ErrorHandlerFunc defines the type of function which handles failures -// of the MustXXX() functions. An error handler function must exit -// the application after handling the error. -type ErrorHandlerFunc func(error) - -// ErrorHandler is the function which handles failures of the MustXXX() -// functions. The default is LogFatalHandler. -var ErrorHandler ErrorHandlerFunc = LogFatalHandler - -// LogHandlerFunc defines the function prototype for logging errors. -type LogHandlerFunc func(fmt string, args ...interface{}) - -// LogPrintf defines a log handler which uses log.Printf. -var LogPrintf LogHandlerFunc = log.Printf - -// LogFatalHandler handles the error by logging a fatal error and exiting. -func LogFatalHandler(err error) { - log.Fatal(err) -} - -// PanicHandler handles the error by panicking. -func PanicHandler(err error) { - panic(err) -} - -// ----------------------------------------------------------------------------- - -// A Properties contains the key/value pairs from the properties input. -// All values are stored in unexpanded form and are expanded at runtime -type Properties struct { - // Pre-/Postfix for property expansion. - Prefix string - Postfix string - - // DisableExpansion controls the expansion of properties on Get() - // and the check for circular references on Set(). When set to - // true Properties behaves like a simple key/value store and does - // not check for circular references on Get() or on Set(). - DisableExpansion bool - - // Stores the key/value pairs - m map[string]string - - // Stores the comments per key. - c map[string][]string - - // Stores the keys in order of appearance. - k []string - - // WriteSeparator specifies the separator of key and value while writing the properties. - WriteSeparator string -} - -// NewProperties creates a new Properties struct with the default -// configuration for "${key}" expressions. -func NewProperties() *Properties { - return &Properties{ - Prefix: "${", - Postfix: "}", - m: map[string]string{}, - c: map[string][]string{}, - k: []string{}, - } -} - -// Load reads a buffer into the given Properties struct. -func (p *Properties) Load(buf []byte, enc Encoding) error { - l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion} - newProperties, err := l.LoadBytes(buf) - if err != nil { - return err - } - p.Merge(newProperties) - return nil -} - -// Get returns the expanded value for the given key if exists. -// Otherwise, ok is false. -func (p *Properties) Get(key string) (value string, ok bool) { - v, ok := p.m[key] - if p.DisableExpansion { - return v, ok - } - if !ok { - return "", false - } - - expanded, err := p.expand(key, v) - - // we guarantee that the expanded value is free of - // circular references and malformed expressions - // so we panic if we still get an error here. - if err != nil { - ErrorHandler(err) - } - - return expanded, true -} - -// MustGet returns the expanded value for the given key if exists. -// Otherwise, it panics. -func (p *Properties) MustGet(key string) string { - if v, ok := p.Get(key); ok { - return v - } - ErrorHandler(invalidKeyError(key)) - panic("ErrorHandler should exit") -} - -// ---------------------------------------------------------------------------- - -// ClearComments removes the comments for all keys. -func (p *Properties) ClearComments() { - p.c = map[string][]string{} -} - -// ---------------------------------------------------------------------------- - -// GetComment returns the last comment before the given key or an empty string. -func (p *Properties) GetComment(key string) string { - comments, ok := p.c[key] - if !ok || len(comments) == 0 { - return "" - } - return comments[len(comments)-1] -} - -// ---------------------------------------------------------------------------- - -// GetComments returns all comments that appeared before the given key or nil. -func (p *Properties) GetComments(key string) []string { - if comments, ok := p.c[key]; ok { - return comments - } - return nil -} - -// ---------------------------------------------------------------------------- - -// SetComment sets the comment for the key. -func (p *Properties) SetComment(key, comment string) { - p.c[key] = []string{comment} -} - -// ---------------------------------------------------------------------------- - -// SetComments sets the comments for the key. If the comments are nil then -// all comments for this key are deleted. -func (p *Properties) SetComments(key string, comments []string) { - if comments == nil { - delete(p.c, key) - return - } - p.c[key] = comments -} - -// ---------------------------------------------------------------------------- - -// GetBool checks if the expanded value is one of '1', 'yes', -// 'true' or 'on' if the key exists. The comparison is case-insensitive. -// If the key does not exist the default value is returned. -func (p *Properties) GetBool(key string, def bool) bool { - v, err := p.getBool(key) - if err != nil { - return def - } - return v -} - -// MustGetBool checks if the expanded value is one of '1', 'yes', -// 'true' or 'on' if the key exists. The comparison is case-insensitive. -// If the key does not exist the function panics. -func (p *Properties) MustGetBool(key string) bool { - v, err := p.getBool(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getBool(key string) (value bool, err error) { - if v, ok := p.Get(key); ok { - return boolVal(v), nil - } - return false, invalidKeyError(key) -} - -func boolVal(v string) bool { - v = strings.ToLower(v) - return v == "1" || v == "true" || v == "yes" || v == "on" -} - -// ---------------------------------------------------------------------------- - -// GetDuration parses the expanded value as an time.Duration (in ns) if the -// key exists. If key does not exist or the value cannot be parsed the default -// value is returned. In almost all cases you want to use GetParsedDuration(). -func (p *Properties) GetDuration(key string, def time.Duration) time.Duration { - v, err := p.getInt64(key) - if err != nil { - return def - } - return time.Duration(v) -} - -// MustGetDuration parses the expanded value as an time.Duration (in ns) if -// the key exists. If key does not exist or the value cannot be parsed the -// function panics. In almost all cases you want to use MustGetParsedDuration(). -func (p *Properties) MustGetDuration(key string) time.Duration { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return time.Duration(v) -} - -// ---------------------------------------------------------------------------- - -// GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration { - s, ok := p.Get(key) - if !ok { - return def - } - v, err := time.ParseDuration(s) - if err != nil { - return def - } - return v -} - -// MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetParsedDuration(key string) time.Duration { - s, ok := p.Get(key) - if !ok { - ErrorHandler(invalidKeyError(key)) - } - v, err := time.ParseDuration(s) - if err != nil { - ErrorHandler(err) - } - return v -} - -// ---------------------------------------------------------------------------- - -// GetFloat64 parses the expanded value as a float64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetFloat64(key string, def float64) float64 { - v, err := p.getFloat64(key) - if err != nil { - return def - } - return v -} - -// MustGetFloat64 parses the expanded value as a float64 if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetFloat64(key string) float64 { - v, err := p.getFloat64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getFloat64(key string) (value float64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseFloat(v, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetInt parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. If the value does not fit into an int the -// function panics with an out of range error. -func (p *Properties) GetInt(key string, def int) int { - v, err := p.getInt64(key) - if err != nil { - return def - } - return intRangeCheck(key, v) -} - -// MustGetInt parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -// If the value does not fit into an int the function panics with -// an out of range error. -func (p *Properties) MustGetInt(key string) int { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return intRangeCheck(key, v) -} - -// ---------------------------------------------------------------------------- - -// GetInt64 parses the expanded value as an int64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetInt64(key string, def int64) int64 { - v, err := p.getInt64(key) - if err != nil { - return def - } - return v -} - -// MustGetInt64 parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetInt64(key string) int64 { - v, err := p.getInt64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getInt64(key string) (value int64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseInt(v, 10, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetUint parses the expanded value as an uint if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. If the value does not fit into an int the -// function panics with an out of range error. -func (p *Properties) GetUint(key string, def uint) uint { - v, err := p.getUint64(key) - if err != nil { - return def - } - return uintRangeCheck(key, v) -} - -// MustGetUint parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -// If the value does not fit into an int the function panics with -// an out of range error. -func (p *Properties) MustGetUint(key string) uint { - v, err := p.getUint64(key) - if err != nil { - ErrorHandler(err) - } - return uintRangeCheck(key, v) -} - -// ---------------------------------------------------------------------------- - -// GetUint64 parses the expanded value as an uint64 if the key exists. -// If key does not exist or the value cannot be parsed the default -// value is returned. -func (p *Properties) GetUint64(key string, def uint64) uint64 { - v, err := p.getUint64(key) - if err != nil { - return def - } - return v -} - -// MustGetUint64 parses the expanded value as an int if the key exists. -// If key does not exist or the value cannot be parsed the function panics. -func (p *Properties) MustGetUint64(key string) uint64 { - v, err := p.getUint64(key) - if err != nil { - ErrorHandler(err) - } - return v -} - -func (p *Properties) getUint64(key string) (value uint64, err error) { - if v, ok := p.Get(key); ok { - value, err = strconv.ParseUint(v, 10, 64) - if err != nil { - return 0, err - } - return value, nil - } - return 0, invalidKeyError(key) -} - -// ---------------------------------------------------------------------------- - -// GetString returns the expanded value for the given key if exists or -// the default value otherwise. -func (p *Properties) GetString(key, def string) string { - if v, ok := p.Get(key); ok { - return v - } - return def -} - -// MustGetString returns the expanded value for the given key if exists or -// panics otherwise. -func (p *Properties) MustGetString(key string) string { - if v, ok := p.Get(key); ok { - return v - } - ErrorHandler(invalidKeyError(key)) - panic("ErrorHandler should exit") -} - -// ---------------------------------------------------------------------------- - -// Filter returns a new properties object which contains all properties -// for which the key matches the pattern. -func (p *Properties) Filter(pattern string) (*Properties, error) { - re, err := regexp.Compile(pattern) - if err != nil { - return nil, err - } - - return p.FilterRegexp(re), nil -} - -// FilterRegexp returns a new properties object which contains all properties -// for which the key matches the regular expression. -func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties { - pp := NewProperties() - for _, k := range p.k { - if re.MatchString(k) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) - pp.Set(k, p.m[k]) - } - } - return pp -} - -// FilterPrefix returns a new properties object with a subset of all keys -// with the given prefix. -func (p *Properties) FilterPrefix(prefix string) *Properties { - pp := NewProperties() - for _, k := range p.k { - if strings.HasPrefix(k, prefix) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) - pp.Set(k, p.m[k]) - } - } - return pp -} - -// FilterStripPrefix returns a new properties object with a subset of all keys -// with the given prefix and the prefix removed from the keys. -func (p *Properties) FilterStripPrefix(prefix string) *Properties { - pp := NewProperties() - n := len(prefix) - for _, k := range p.k { - if len(k) > len(prefix) && strings.HasPrefix(k, prefix) { - // TODO(fs): we are ignoring the error which flags a circular reference. - // TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference - // TODO(fs): this function should probably return an error but the signature is fixed - pp.Set(k[n:], p.m[k]) - } - } - return pp -} - -// Len returns the number of keys. -func (p *Properties) Len() int { - return len(p.m) -} - -// Keys returns all keys in the same order as in the input. -func (p *Properties) Keys() []string { - keys := make([]string, len(p.k)) - copy(keys, p.k) - return keys -} - -// Set sets the property key to the corresponding value. -// If a value for key existed before then ok is true and prev -// contains the previous value. If the value contains a -// circular reference or a malformed expression then -// an error is returned. -// An empty key is silently ignored. -func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { - if key == "" { - return "", false, nil - } - - // if expansion is disabled we allow circular references - if p.DisableExpansion { - prev, ok = p.Get(key) - p.m[key] = value - if !ok { - p.k = append(p.k, key) - } - return prev, ok, nil - } - - // to check for a circular reference we temporarily need - // to set the new value. If there is an error then revert - // to the previous state. Only if all tests are successful - // then we add the key to the p.k list. - prev, ok = p.Get(key) - p.m[key] = value - - // now check for a circular reference - _, err = p.expand(key, value) - if err != nil { - - // revert to the previous state - if ok { - p.m[key] = prev - } else { - delete(p.m, key) - } - - return "", false, err - } - - if !ok { - p.k = append(p.k, key) - } - - return prev, ok, nil -} - -// SetValue sets property key to the default string value -// as defined by fmt.Sprintf("%v"). -func (p *Properties) SetValue(key string, value interface{}) error { - _, _, err := p.Set(key, fmt.Sprintf("%v", value)) - return err -} - -// MustSet sets the property key to the corresponding value. -// If a value for key existed before then ok is true and prev -// contains the previous value. An empty key is silently ignored. -func (p *Properties) MustSet(key, value string) (prev string, ok bool) { - prev, ok, err := p.Set(key, value) - if err != nil { - ErrorHandler(err) - } - return prev, ok -} - -// String returns a string of all expanded 'key = value' pairs. -func (p *Properties) String() string { - var s string - for _, key := range p.k { - value, _ := p.Get(key) - s = fmt.Sprintf("%s%s = %s\n", s, key, value) - } - return s -} - -// Sort sorts the properties keys in alphabetical order. -// This is helpfully before writing the properties. -func (p *Properties) Sort() { - sort.Strings(p.k) -} - -// Write writes all unexpanded 'key = value' pairs to the given writer. -// Write returns the number of bytes written and any write error encountered. -func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) { - return p.WriteComment(w, "", enc) -} - -// WriteComment writes all unexpanced 'key = value' pairs to the given writer. -// If prefix is not empty then comments are written with a blank line and the -// given prefix. The prefix should be either "# " or "! " to be compatible with -// the properties file format. Otherwise, the properties parser will not be -// able to read the file back in. It returns the number of bytes written and -// any write error encountered. -func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) { - var x int - - for _, key := range p.k { - value := p.m[key] - - if prefix != "" { - if comments, ok := p.c[key]; ok { - // don't print comments if they are all empty - allEmpty := true - for _, c := range comments { - if c != "" { - allEmpty = false - break - } - } - - if !allEmpty { - // add a blank line between entries but not at the top - if len(comments) > 0 && n > 0 { - x, err = fmt.Fprintln(w) - if err != nil { - return - } - n += x - } - - for _, c := range comments { - x, err = fmt.Fprintf(w, "%s%s\n", prefix, c) - if err != nil { - return - } - n += x - } - } - } - } - sep := " = " - if p.WriteSeparator != "" { - sep = p.WriteSeparator - } - x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc)) - if err != nil { - return - } - n += x - } - return -} - -// Map returns a copy of the properties as a map. -func (p *Properties) Map() map[string]string { - m := make(map[string]string) - for k, v := range p.m { - m[k] = v - } - return m -} - -// FilterFunc returns a copy of the properties which includes the values which passed all filters. -func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties { - pp := NewProperties() -outer: - for k, v := range p.m { - for _, f := range filters { - if !f(k, v) { - continue outer - } - pp.Set(k, v) - } - } - return pp -} - -// ---------------------------------------------------------------------------- - -// Delete removes the key and its comments. -func (p *Properties) Delete(key string) { - delete(p.m, key) - delete(p.c, key) - newKeys := []string{} - for _, k := range p.k { - if k != key { - newKeys = append(newKeys, k) - } - } - p.k = newKeys -} - -// Merge merges properties, comments and keys from other *Properties into p -func (p *Properties) Merge(other *Properties) { - for _, k := range other.k { - if _, ok := p.m[k]; !ok { - p.k = append(p.k, k) - } - } - for k, v := range other.m { - p.m[k] = v - } - for k, v := range other.c { - p.c[k] = v - } -} - -// ---------------------------------------------------------------------------- - -// check expands all values and returns an error if a circular reference or -// a malformed expression was found. -func (p *Properties) check() error { - for key, value := range p.m { - if _, err := p.expand(key, value); err != nil { - return err - } - } - return nil -} - -func (p *Properties) expand(key, input string) (string, error) { - // no pre/postfix -> nothing to expand - if p.Prefix == "" && p.Postfix == "" { - return input, nil - } - - return expand(input, []string{key}, p.Prefix, p.Postfix, p.m) -} - -// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values. -// The function keeps track of the keys that were already expanded and stops if it -// detects a circular reference or a malformed expression of the form '(prefix)key'. -func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) { - if len(keys) > maxExpansionDepth { - return "", fmt.Errorf("expansion too deep") - } - - for { - start := strings.Index(s, prefix) - if start == -1 { - return s, nil - } - - keyStart := start + len(prefix) - keyLen := strings.Index(s[keyStart:], postfix) - if keyLen == -1 { - return "", fmt.Errorf("malformed expression") - } - - end := keyStart + keyLen + len(postfix) - 1 - key := s[keyStart : keyStart+keyLen] - - // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) - - for _, k := range keys { - if key == k { - var b bytes.Buffer - b.WriteString("circular reference in:\n") - for _, k1 := range keys { - fmt.Fprintf(&b, "%s=%s\n", k1, values[k1]) - } - return "", fmt.Errorf(b.String()) - } - } - - val, ok := values[key] - if !ok { - val = os.Getenv(key) - } - new_val, err := expand(val, append(keys, key), prefix, postfix, values) - if err != nil { - return "", err - } - s = s[:start] + new_val + s[end+1:] - } -} - -// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters. -func encode(s string, special string, enc Encoding) string { - switch enc { - case UTF8: - return encodeUtf8(s, special) - case ISO_8859_1: - return encodeIso(s, special) - default: - panic(fmt.Sprintf("unsupported encoding %v", enc)) - } -} - -func encodeUtf8(s string, special string) string { - v := "" - for pos := 0; pos < len(s); { - r, w := utf8.DecodeRuneInString(s[pos:]) - pos += w - v += escape(r, special) - } - return v -} - -func encodeIso(s string, special string) string { - var r rune - var w int - var v string - for pos := 0; pos < len(s); { - switch r, w = utf8.DecodeRuneInString(s[pos:]); { - case r < 1<<8: // single byte rune -> escape special chars only - v += escape(r, special) - case r < 1<<16: // two byte rune -> unicode literal - v += fmt.Sprintf("\\u%04x", r) - default: // more than two bytes per rune -> can't encode - v += "?" - } - pos += w - } - return v -} - -func escape(r rune, special string) string { - switch r { - case '\f': - return "\\f" - case '\n': - return "\\n" - case '\r': - return "\\r" - case '\t': - return "\\t" - case '\\': - return "\\\\" - default: - if strings.ContainsRune(special, r) { - return "\\" + string(r) - } - return string(r) - } -} - -func invalidKeyError(key string) error { - return fmt.Errorf("unknown property: %s", key) -} diff --git a/vendor/github.com/magiconair/properties/rangecheck.go b/vendor/github.com/magiconair/properties/rangecheck.go deleted file mode 100644 index dbd60b36e7..0000000000 --- a/vendor/github.com/magiconair/properties/rangecheck.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013-2022 Frank Schroeder. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package properties - -import ( - "fmt" - "math" -) - -// make this a var to overwrite it in a test -var is32Bit = ^uint(0) == math.MaxUint32 - -// intRangeCheck checks if the value fits into the int type and -// panics if it does not. -func intRangeCheck(key string, v int64) int { - if is32Bit && (v < math.MinInt32 || v > math.MaxInt32) { - panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) - } - return int(v) -} - -// uintRangeCheck checks if the value fits into the uint type and -// panics if it does not. -func uintRangeCheck(key string, v uint64) uint { - if is32Bit && v > math.MaxUint32 { - panic(fmt.Sprintf("Value %d for key %s out of range", v, key)) - } - return uint(v) -} diff --git a/vendor/github.com/mailru/easyjson/jlexer/bytestostr.go b/vendor/github.com/mailru/easyjson/jlexer/bytestostr.go index ff7b27c5b2..e68108f868 100644 --- a/vendor/github.com/mailru/easyjson/jlexer/bytestostr.go +++ b/vendor/github.com/mailru/easyjson/jlexer/bytestostr.go @@ -8,7 +8,6 @@ package jlexer import ( - "reflect" "unsafe" ) @@ -18,7 +17,5 @@ import ( // chunk may be either blocked from being freed by GC because of a single string or the buffer.Data // may be garbage-collected even when the string exists. func bytesToStr(data []byte) string { - h := (*reflect.SliceHeader)(unsafe.Pointer(&data)) - shdr := reflect.StringHeader{Data: h.Data, Len: h.Len} - return *(*string)(unsafe.Pointer(&shdr)) + return *(*string)(unsafe.Pointer(&data)) } diff --git a/vendor/github.com/mailru/easyjson/jlexer/lexer.go b/vendor/github.com/mailru/easyjson/jlexer/lexer.go index b5f5e26132..a27705b12b 100644 --- a/vendor/github.com/mailru/easyjson/jlexer/lexer.go +++ b/vendor/github.com/mailru/easyjson/jlexer/lexer.go @@ -19,21 +19,21 @@ import ( "github.com/josharian/intern" ) -// tokenKind determines type of a token. -type tokenKind byte +// TokenKind determines type of a token. +type TokenKind byte const ( - tokenUndef tokenKind = iota // No token. - tokenDelim // Delimiter: one of '{', '}', '[' or ']'. - tokenString // A string literal, e.g. "abc\u1234" - tokenNumber // Number literal, e.g. 1.5e5 - tokenBool // Boolean literal: true or false. - tokenNull // null keyword. + TokenUndef TokenKind = iota // No token. + TokenDelim // Delimiter: one of '{', '}', '[' or ']'. + TokenString // A string literal, e.g. "abc\u1234" + TokenNumber // Number literal, e.g. 1.5e5 + TokenBool // Boolean literal: true or false. + TokenNull // null keyword. ) // token describes a single token: type, position in the input and value. type token struct { - kind tokenKind // Type of a token. + kind TokenKind // Type of a token. boolValue bool // Value if a boolean literal token. byteValueCloned bool // true if byteValue was allocated and does not refer to original json body @@ -47,7 +47,7 @@ type Lexer struct { start int // Start of the current token. pos int // Current unscanned position in the input stream. - token token // Last scanned token, if token.kind != tokenUndef. + token token // Last scanned token, if token.kind != TokenUndef. firstElement bool // Whether current element is the first in array or an object. wantSep byte // A comma or a colon character, which need to occur before a token. @@ -59,7 +59,7 @@ type Lexer struct { // FetchToken scans the input for the next token. func (r *Lexer) FetchToken() { - r.token.kind = tokenUndef + r.token.kind = TokenUndef r.start = r.pos // Check if r.Data has r.pos element @@ -90,7 +90,7 @@ func (r *Lexer) FetchToken() { r.errSyntax() } - r.token.kind = tokenString + r.token.kind = TokenString r.fetchString() return @@ -99,7 +99,7 @@ func (r *Lexer) FetchToken() { r.errSyntax() } r.firstElement = true - r.token.kind = tokenDelim + r.token.kind = TokenDelim r.token.delimValue = r.Data[r.pos] r.pos++ return @@ -109,7 +109,7 @@ func (r *Lexer) FetchToken() { r.errSyntax() } r.wantSep = 0 - r.token.kind = tokenDelim + r.token.kind = TokenDelim r.token.delimValue = r.Data[r.pos] r.pos++ return @@ -118,7 +118,7 @@ func (r *Lexer) FetchToken() { if r.wantSep != 0 { r.errSyntax() } - r.token.kind = tokenNumber + r.token.kind = TokenNumber r.fetchNumber() return @@ -127,7 +127,7 @@ func (r *Lexer) FetchToken() { r.errSyntax() } - r.token.kind = tokenNull + r.token.kind = TokenNull r.fetchNull() return @@ -136,7 +136,7 @@ func (r *Lexer) FetchToken() { r.errSyntax() } - r.token.kind = tokenBool + r.token.kind = TokenBool r.token.boolValue = true r.fetchTrue() return @@ -146,7 +146,7 @@ func (r *Lexer) FetchToken() { r.errSyntax() } - r.token.kind = tokenBool + r.token.kind = TokenBool r.token.boolValue = false r.fetchFalse() return @@ -391,7 +391,7 @@ func (r *Lexer) fetchString() { // scanToken scans the next token if no token is currently available in the lexer. func (r *Lexer) scanToken() { - if r.token.kind != tokenUndef || r.fatalError != nil { + if r.token.kind != TokenUndef || r.fatalError != nil { return } @@ -400,7 +400,7 @@ func (r *Lexer) scanToken() { // consume resets the current token to allow scanning the next one. func (r *Lexer) consume() { - r.token.kind = tokenUndef + r.token.kind = TokenUndef r.token.byteValueCloned = false r.token.delimValue = 0 } @@ -443,10 +443,10 @@ func (r *Lexer) errInvalidToken(expected string) { switch expected { case "[": r.token.delimValue = ']' - r.token.kind = tokenDelim + r.token.kind = TokenDelim case "{": r.token.delimValue = '}' - r.token.kind = tokenDelim + r.token.kind = TokenDelim } r.addNonfatalError(&LexerError{ Reason: fmt.Sprintf("expected %s", expected), @@ -475,7 +475,7 @@ func (r *Lexer) GetPos() int { // Delim consumes a token and verifies that it is the given delimiter. func (r *Lexer) Delim(c byte) { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } @@ -489,7 +489,7 @@ func (r *Lexer) Delim(c byte) { // IsDelim returns true if there was no scanning error and next token is the given delimiter. func (r *Lexer) IsDelim(c byte) bool { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } return !r.Ok() || r.token.delimValue == c @@ -497,10 +497,10 @@ func (r *Lexer) IsDelim(c byte) bool { // Null verifies that the next token is null and consumes it. func (r *Lexer) Null() { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - if !r.Ok() || r.token.kind != tokenNull { + if !r.Ok() || r.token.kind != TokenNull { r.errInvalidToken("null") } r.consume() @@ -508,15 +508,15 @@ func (r *Lexer) Null() { // IsNull returns true if the next token is a null keyword. func (r *Lexer) IsNull() bool { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - return r.Ok() && r.token.kind == tokenNull + return r.Ok() && r.token.kind == TokenNull } // Skip skips a single token. func (r *Lexer) Skip() { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } r.consume() @@ -621,10 +621,10 @@ func (r *Lexer) Consumed() { } func (r *Lexer) unsafeString(skipUnescape bool) (string, []byte) { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - if !r.Ok() || r.token.kind != tokenString { + if !r.Ok() || r.token.kind != TokenString { r.errInvalidToken("string") return "", nil } @@ -664,10 +664,10 @@ func (r *Lexer) UnsafeFieldName(skipUnescape bool) string { // String reads a string literal. func (r *Lexer) String() string { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - if !r.Ok() || r.token.kind != tokenString { + if !r.Ok() || r.token.kind != TokenString { r.errInvalidToken("string") return "" } @@ -687,10 +687,10 @@ func (r *Lexer) String() string { // StringIntern reads a string literal, and performs string interning on it. func (r *Lexer) StringIntern() string { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - if !r.Ok() || r.token.kind != tokenString { + if !r.Ok() || r.token.kind != TokenString { r.errInvalidToken("string") return "" } @@ -705,10 +705,10 @@ func (r *Lexer) StringIntern() string { // Bytes reads a string literal and base64 decodes it into a byte slice. func (r *Lexer) Bytes() []byte { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - if !r.Ok() || r.token.kind != tokenString { + if !r.Ok() || r.token.kind != TokenString { r.errInvalidToken("string") return nil } @@ -731,10 +731,10 @@ func (r *Lexer) Bytes() []byte { // Bool reads a true or false boolean keyword. func (r *Lexer) Bool() bool { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - if !r.Ok() || r.token.kind != tokenBool { + if !r.Ok() || r.token.kind != TokenBool { r.errInvalidToken("bool") return false } @@ -744,10 +744,10 @@ func (r *Lexer) Bool() bool { } func (r *Lexer) number() string { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } - if !r.Ok() || r.token.kind != tokenNumber { + if !r.Ok() || r.token.kind != TokenNumber { r.errInvalidToken("number") return "" } @@ -1151,7 +1151,7 @@ func (r *Lexer) GetNonFatalErrors() []*LexerError { // JsonNumber fetches and json.Number from 'encoding/json' package. // Both int, float or string, contains them are valid values func (r *Lexer) JsonNumber() json.Number { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } if !r.Ok() { @@ -1160,11 +1160,11 @@ func (r *Lexer) JsonNumber() json.Number { } switch r.token.kind { - case tokenString: + case TokenString: return json.Number(r.String()) - case tokenNumber: + case TokenNumber: return json.Number(r.Raw()) - case tokenNull: + case TokenNull: r.Null() return json.Number("") default: @@ -1175,7 +1175,7 @@ func (r *Lexer) JsonNumber() json.Number { // Interface fetches an interface{} analogous to the 'encoding/json' package. func (r *Lexer) Interface() interface{} { - if r.token.kind == tokenUndef && r.Ok() { + if r.token.kind == TokenUndef && r.Ok() { r.FetchToken() } @@ -1183,13 +1183,13 @@ func (r *Lexer) Interface() interface{} { return nil } switch r.token.kind { - case tokenString: + case TokenString: return r.String() - case tokenNumber: + case TokenNumber: return r.Float64() - case tokenBool: + case TokenBool: return r.Bool() - case tokenNull: + case TokenNull: r.Null() return nil } @@ -1242,3 +1242,16 @@ func (r *Lexer) WantColon() { r.wantSep = ':' r.firstElement = false } + +// CurrentToken returns current token kind if there were no errors and TokenUndef otherwise +func (r *Lexer) CurrentToken() TokenKind { + if r.token.kind == TokenUndef && r.Ok() { + r.FetchToken() + } + + if !r.Ok() { + return TokenUndef + } + + return r.token.kind +} diff --git a/vendor/github.com/mailru/easyjson/jwriter/writer.go b/vendor/github.com/mailru/easyjson/jwriter/writer.go index 2c5b20105b..34b0ade468 100644 --- a/vendor/github.com/mailru/easyjson/jwriter/writer.go +++ b/vendor/github.com/mailru/easyjson/jwriter/writer.go @@ -67,6 +67,18 @@ func (w *Writer) RawString(s string) { w.Buffer.AppendString(s) } +// RawBytesString appends string from bytes to the buffer. +func (w *Writer) RawBytesString(data []byte, err error) { + switch { + case w.Error != nil: + return + case err != nil: + w.Error = err + default: + w.String(string(data)) + } +} + // Raw appends raw binary data to the buffer or sets the error if it is given. Useful for // calling with results of MarshalJSON-like functions. func (w *Writer) Raw(data []byte, err error) { diff --git a/vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go b/vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go index f16af09d6e..17211f1249 100644 --- a/vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go +++ b/vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go @@ -1094,7 +1094,7 @@ func (c *CapSoftwareVersion) DecodeFromBytes(data []byte) error { return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilitySoftwareVersion bytes allowed") } softwareVersionLen := uint8(data[0]) - if len(data[1:]) < int(softwareVersionLen) || softwareVersionLen > 64 { + if len(data[1:]) < int(softwareVersionLen) || softwareVersionLen > 64 || softwareVersionLen == 0 { return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "invalid length of software version capablity") } c.SoftwareVersionLen = softwareVersionLen @@ -12708,6 +12708,10 @@ func parseGenericTransitiveExperimentalExtended(data []byte) (ExtendedCommunityI dscp := data[7] return NewTrafficRemarkExtended(dscp), nil case EC_SUBTYPE_FLOWSPEC_REDIRECT_IP6: + if len(data) < 20 { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all extended community bytes for IPv6 FlowSpec are available") + } + ipv6 := net.IP(data[2:18]).String() localAdmin := binary.BigEndian.Uint16(data[18:20]) return NewRedirectIPv6AddressSpecificExtended(ipv6, localAdmin), nil diff --git a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml index 1d8b69e65e..ec52857a3e 100644 --- a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml +++ b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml @@ -1,3 +1,4 @@ +version: 2 before: hooks: - go mod tidy diff --git a/vendor/github.com/pelletier/go-toml/v2/README.md b/vendor/github.com/pelletier/go-toml/v2/README.md index d964b25fe1..0755e55642 100644 --- a/vendor/github.com/pelletier/go-toml/v2/README.md +++ b/vendor/github.com/pelletier/go-toml/v2/README.md @@ -565,7 +565,7 @@ complete solutions exist out there. ## Versioning -Expect for parts explicitely marked otherwise, go-toml follows [Semantic +Expect for parts explicitly marked otherwise, go-toml follows [Semantic Versioning](https://semver.org). The supported version of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of this document. The last two major versions of Go are supported (see [Go Release diff --git a/vendor/github.com/pelletier/go-toml/v2/marshaler.go b/vendor/github.com/pelletier/go-toml/v2/marshaler.go index 7f4e20c128..161acd9343 100644 --- a/vendor/github.com/pelletier/go-toml/v2/marshaler.go +++ b/vendor/github.com/pelletier/go-toml/v2/marshaler.go @@ -8,7 +8,7 @@ import ( "io" "math" "reflect" - "sort" + "slices" "strconv" "strings" "time" @@ -280,7 +280,7 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e } hasTextMarshaler := v.Type().Implements(textMarshalerType) - if hasTextMarshaler || (v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) { + if hasTextMarshaler || (v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) { if !hasTextMarshaler { v = v.Addr() } @@ -631,6 +631,18 @@ func (enc *Encoder) keyToString(k reflect.Value) (string, error) { return "", fmt.Errorf("toml: error marshalling key %v from text: %w", k, err) } return string(keyB), nil + + case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64: + return strconv.FormatInt(k.Int(), 10), nil + + case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64: + return strconv.FormatUint(k.Uint(), 10), nil + + case keyType.Kind() == reflect.Float32: + return strconv.FormatFloat(k.Float(), 'f', -1, 32), nil + + case keyType.Kind() == reflect.Float64: + return strconv.FormatFloat(k.Float(), 'f', -1, 64), nil } return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind()) } @@ -668,8 +680,8 @@ func (enc *Encoder) encodeMap(b []byte, ctx encoderCtx, v reflect.Value) ([]byte } func sortEntriesByKey(e []entry) { - sort.Slice(e, func(i, j int) bool { - return e[i].Key < e[j].Key + slices.SortFunc(e, func(a, b entry) int { + return strings.Compare(a.Key, b.Key) }) } @@ -732,7 +744,7 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) { if fieldType.Anonymous { if fieldType.Type.Kind() == reflect.Struct { walkStruct(ctx, t, f) - } else if fieldType.Type.Kind() == reflect.Pointer && !f.IsNil() && f.Elem().Kind() == reflect.Struct { + } else if fieldType.Type.Kind() == reflect.Ptr && !f.IsNil() && f.Elem().Kind() == reflect.Struct { walkStruct(ctx, t, f.Elem()) } continue @@ -951,7 +963,7 @@ func willConvertToTable(ctx encoderCtx, v reflect.Value) bool { if !v.IsValid() { return false } - if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) { + if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) { return false } diff --git a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go index 98231bae65..c3df8bee1c 100644 --- a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go +++ b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math" "reflect" + "strconv" "strings" "sync/atomic" "time" @@ -21,10 +21,8 @@ import ( // // It is a shortcut for Decoder.Decode() with the default options. func Unmarshal(data []byte, v interface{}) error { - p := unstable.Parser{} - p.Reset(data) - d := decoder{p: &p} - + d := decoder{} + d.p.Reset(data) return d.FromParser(v) } @@ -117,27 +115,25 @@ func (d *Decoder) EnableUnmarshalerInterface() *Decoder { // Inline Table -> same as Table // Array of Tables -> same as Array and Table func (d *Decoder) Decode(v interface{}) error { - b, err := ioutil.ReadAll(d.r) + b, err := io.ReadAll(d.r) if err != nil { return fmt.Errorf("toml: %w", err) } - p := unstable.Parser{} - p.Reset(b) dec := decoder{ - p: &p, strict: strict{ Enabled: d.strict, }, unmarshalerInterface: d.unmarshalerInterface, } + dec.p.Reset(b) return dec.FromParser(v) } type decoder struct { // Which parser instance in use for this decoding session. - p *unstable.Parser + p unstable.Parser // Flag indicating that the current expression is stashed. // If set to true, calling nextExpr will not actually pull a new expression @@ -1078,12 +1074,39 @@ func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value, } return mk, nil - case reflect.PtrTo(keyType).Implements(textUnmarshalerType): + case reflect.PointerTo(keyType).Implements(textUnmarshalerType): mk := reflect.New(keyType) if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err) } return mk.Elem(), nil + + case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64: + key, err := strconv.ParseInt(string(data), 10, 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from integer: %w", stringType, err) + } + return reflect.ValueOf(key).Convert(keyType), nil + case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64: + key, err := strconv.ParseUint(string(data), 10, 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from unsigned integer: %w", stringType, err) + } + return reflect.ValueOf(key).Convert(keyType), nil + + case keyType.Kind() == reflect.Float32: + key, err := strconv.ParseFloat(string(data), 32) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err) + } + return reflect.ValueOf(float32(key)), nil + + case keyType.Kind() == reflect.Float64: + key, err := strconv.ParseFloat(string(data), 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err) + } + return reflect.ValueOf(float64(key)), nil } return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go index 68ffe3c248..ad347113c0 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/desc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/desc.go @@ -189,12 +189,15 @@ func (d *Desc) String() string { fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()), ) } - vlStrings := make([]string, 0, len(d.variableLabels.names)) - for _, vl := range d.variableLabels.names { - if fn, ok := d.variableLabels.labelConstraints[vl]; ok && fn != nil { - vlStrings = append(vlStrings, fmt.Sprintf("c(%s)", vl)) - } else { - vlStrings = append(vlStrings, vl) + vlStrings := []string{} + if d.variableLabels != nil { + vlStrings = make([]string, 0, len(d.variableLabels.names)) + for _, vl := range d.variableLabels.names { + if fn, ok := d.variableLabels.labelConstraints[vl]; ok && fn != nil { + vlStrings = append(vlStrings, fmt.Sprintf("c(%s)", vl)) + } else { + vlStrings = append(vlStrings, vl) + } } } return fmt.Sprintf( diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go index 5117464172..6b8684731c 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go @@ -288,7 +288,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { } func attachOriginalName(desc, origName string) string { - return fmt.Sprintf("%s Sourced from %s", desc, origName) + return fmt.Sprintf("%s Sourced from %s.", desc, origName) } // Describe returns all descriptions of the collector. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index 519db348a7..c453b754a7 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go @@ -14,6 +14,7 @@ package prometheus import ( + "errors" "fmt" "math" "runtime" @@ -28,6 +29,11 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" ) +const ( + nativeHistogramSchemaMaximum = 8 + nativeHistogramSchemaMinimum = -4 +) + // nativeHistogramBounds for the frac of observed values. Only relevant for // schema > 0. The position in the slice is the schema. (0 is never used, just // here for convenience of using the schema directly as the index.) @@ -330,11 +336,11 @@ func ExponentialBuckets(start, factor float64, count int) []float64 { // used for the Buckets field of HistogramOpts. // // The function panics if 'count' is 0 or negative, if 'min' is 0 or negative. -func ExponentialBucketsRange(min, max float64, count int) []float64 { +func ExponentialBucketsRange(minBucket, maxBucket float64, count int) []float64 { if count < 1 { panic("ExponentialBucketsRange count needs a positive count") } - if min <= 0 { + if minBucket <= 0 { panic("ExponentialBucketsRange min needs to be greater than 0") } @@ -342,12 +348,12 @@ func ExponentialBucketsRange(min, max float64, count int) []float64 { // max = min*growthFactor^(bucketCount-1) // We know max/min and highest bucket. Solve for growthFactor. - growthFactor := math.Pow(max/min, 1.0/float64(count-1)) + growthFactor := math.Pow(maxBucket/minBucket, 1.0/float64(count-1)) // Now that we know growthFactor, solve for each bucket. buckets := make([]float64, count) for i := 1; i <= count; i++ { - buckets[i-1] = min * math.Pow(growthFactor, float64(i-1)) + buckets[i-1] = minBucket * math.Pow(growthFactor, float64(i-1)) } return buckets } @@ -858,15 +864,35 @@ func (h *histogram) Write(out *dto.Metric) error { // findBucket returns the index of the bucket for the provided value, or // len(h.upperBounds) for the +Inf bucket. func (h *histogram) findBucket(v float64) int { - // TODO(beorn7): For small numbers of buckets (<30), a linear search is - // slightly faster than the binary search. If we really care, we could - // switch from one search strategy to the other depending on the number - // of buckets. - // - // Microbenchmarks (BenchmarkHistogramNoLabels): - // 11 buckets: 38.3 ns/op linear - binary 48.7 ns/op - // 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op - // 300 buckets: 154 ns/op linear - binary 61.6 ns/op + n := len(h.upperBounds) + if n == 0 { + return 0 + } + + // Early exit: if v is less than or equal to the first upper bound, return 0 + if v <= h.upperBounds[0] { + return 0 + } + + // Early exit: if v is greater than the last upper bound, return len(h.upperBounds) + if v > h.upperBounds[n-1] { + return n + } + + // For small arrays, use simple linear search + // "magic number" 35 is result of tests on couple different (AWS and baremetal) servers + // see more details here: https://github.com/prometheus/client_golang/pull/1662 + if n < 35 { + for i, bound := range h.upperBounds { + if v <= bound { + return i + } + } + // If v is greater than all upper bounds, return len(h.upperBounds) + return n + } + + // For larger arrays, use stdlib's binary search return sort.SearchFloat64s(h.upperBounds, v) } @@ -1440,9 +1466,9 @@ func pickSchema(bucketFactor float64) int32 { floor := math.Floor(math.Log2(math.Log2(bucketFactor))) switch { case floor <= -8: - return 8 + return nativeHistogramSchemaMaximum case floor >= 4: - return -4 + return nativeHistogramSchemaMinimum default: return -int32(floor) } @@ -1835,3 +1861,196 @@ func (n *nativeExemplars) addExemplar(e *dto.Exemplar) { n.exemplars = append(n.exemplars[:nIdx], append([]*dto.Exemplar{e}, append(n.exemplars[nIdx:rIdx], n.exemplars[rIdx+1:]...)...)...) } } + +type constNativeHistogram struct { + desc *Desc + dto.Histogram + labelPairs []*dto.LabelPair +} + +func validateCount(sum float64, count uint64, negativeBuckets, positiveBuckets map[int]int64, zeroBucket uint64) error { + var bucketPopulationSum int64 + for _, v := range positiveBuckets { + bucketPopulationSum += v + } + for _, v := range negativeBuckets { + bucketPopulationSum += v + } + bucketPopulationSum += int64(zeroBucket) + + // If the sum of observations is NaN, the number of observations must be greater or equal to the sum of all bucket counts. + // Otherwise, the number of observations must be equal to the sum of all bucket counts . + + if math.IsNaN(sum) && bucketPopulationSum > int64(count) || + !math.IsNaN(sum) && bucketPopulationSum != int64(count) { + return errors.New("the sum of all bucket populations exceeds the count of observations") + } + return nil +} + +// NewConstNativeHistogram returns a metric representing a Prometheus native histogram with +// fixed values for the count, sum, and positive/negative/zero bucket counts. As those parameters +// cannot be changed, the returned value does not implement the Histogram +// interface (but only the Metric interface). Users of this package will not +// have much use for it in regular operations. However, when implementing custom +// OpenTelemetry Collectors, it is useful as a throw-away metric that is generated on the fly +// to send it to Prometheus in the Collect method. +// +// zeroBucket counts all (positive and negative) +// observations in the zero bucket (with an absolute value less or equal +// the current threshold). +// positiveBuckets and negativeBuckets are separate maps for negative and positive +// observations. The map's value is an int64, counting observations in +// that bucket. The map's key is the +// index of the bucket according to the used +// Schema. Index 0 is for an upper bound of 1 in positive buckets and for a lower bound of -1 in negative buckets. +// NewConstNativeHistogram returns an error if +// - the length of labelValues is not consistent with the variable labels in Desc or if Desc is invalid. +// - the schema passed is not between 8 and -4 +// - the sum of counts in all buckets including the zero bucket does not equal the count if sum is not NaN (or exceeds the count if sum is NaN) +// +// See https://opentelemetry.io/docs/specs/otel/compatibility/prometheus_and_openmetrics/#exponential-histograms for more details about the conversion from OTel to Prometheus. +func NewConstNativeHistogram( + desc *Desc, + count uint64, + sum float64, + positiveBuckets, negativeBuckets map[int]int64, + zeroBucket uint64, + schema int32, + zeroThreshold float64, + createdTimestamp time.Time, + labelValues ...string, +) (Metric, error) { + if desc.err != nil { + return nil, desc.err + } + if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil { + return nil, err + } + if schema > nativeHistogramSchemaMaximum || schema < nativeHistogramSchemaMinimum { + return nil, errors.New("invalid native histogram schema") + } + if err := validateCount(sum, count, negativeBuckets, positiveBuckets, zeroBucket); err != nil { + return nil, err + } + + NegativeSpan, NegativeDelta := makeBucketsFromMap(negativeBuckets) + PositiveSpan, PositiveDelta := makeBucketsFromMap(positiveBuckets) + ret := &constNativeHistogram{ + desc: desc, + Histogram: dto.Histogram{ + CreatedTimestamp: timestamppb.New(createdTimestamp), + Schema: &schema, + ZeroThreshold: &zeroThreshold, + SampleCount: &count, + SampleSum: &sum, + + NegativeSpan: NegativeSpan, + NegativeDelta: NegativeDelta, + + PositiveSpan: PositiveSpan, + PositiveDelta: PositiveDelta, + + ZeroCount: proto.Uint64(zeroBucket), + }, + labelPairs: MakeLabelPairs(desc, labelValues), + } + if *ret.ZeroThreshold == 0 && *ret.ZeroCount == 0 && len(ret.PositiveSpan) == 0 && len(ret.NegativeSpan) == 0 { + ret.PositiveSpan = []*dto.BucketSpan{{ + Offset: proto.Int32(0), + Length: proto.Uint32(0), + }} + } + return ret, nil +} + +// MustNewConstNativeHistogram is a version of NewConstNativeHistogram that panics where +// NewConstNativeHistogram would have returned an error. +func MustNewConstNativeHistogram( + desc *Desc, + count uint64, + sum float64, + positiveBuckets, negativeBuckets map[int]int64, + zeroBucket uint64, + nativeHistogramSchema int32, + nativeHistogramZeroThreshold float64, + createdTimestamp time.Time, + labelValues ...string, +) Metric { + nativehistogram, err := NewConstNativeHistogram(desc, + count, + sum, + positiveBuckets, + negativeBuckets, + zeroBucket, + nativeHistogramSchema, + nativeHistogramZeroThreshold, + createdTimestamp, + labelValues...) + if err != nil { + panic(err) + } + return nativehistogram +} + +func (h *constNativeHistogram) Desc() *Desc { + return h.desc +} + +func (h *constNativeHistogram) Write(out *dto.Metric) error { + out.Histogram = &h.Histogram + out.Label = h.labelPairs + return nil +} + +func makeBucketsFromMap(buckets map[int]int64) ([]*dto.BucketSpan, []int64) { + if len(buckets) == 0 { + return nil, nil + } + var ii []int + for k := range buckets { + ii = append(ii, k) + } + sort.Ints(ii) + + var ( + spans []*dto.BucketSpan + deltas []int64 + prevCount int64 + nextI int + ) + + appendDelta := func(count int64) { + *spans[len(spans)-1].Length++ + deltas = append(deltas, count-prevCount) + prevCount = count + } + + for n, i := range ii { + count := buckets[i] + // Multiple spans with only small gaps in between are probably + // encoded more efficiently as one larger span with a few empty + // buckets. Needs some research to find the sweet spot. For now, + // we assume that gaps of one or two buckets should not create + // a new span. + iDelta := int32(i - nextI) + if n == 0 || iDelta > 2 { + // We have to create a new span, either because we are + // at the very beginning, or because we have found a gap + // of more than two buckets. + spans = append(spans, &dto.BucketSpan{ + Offset: proto.Int32(iDelta), + Length: proto.Uint32(0), + }) + } else { + // We have found a small gap (or no gap at all). + // Insert empty buckets as needed. + for j := int32(0); j < iDelta; j++ { + appendDelta(0) + } + } + appendDelta(count) + nextI = i + 1 + } + return spans, deltas +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go index a595a20362..8b016355ad 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go @@ -22,17 +22,18 @@ import ( "bytes" "fmt" "io" + "strconv" "strings" ) -func min(a, b int) int { +func minInt(a, b int) int { if a < b { return a } return b } -func max(a, b int) int { +func maxInt(a, b int) int { if a > b { return a } @@ -427,12 +428,12 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { if codes[0].Tag == 'e' { c := codes[0] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + codes[0] = OpCode{c.Tag, maxInt(i1, i2-n), i2, maxInt(j1, j2-n), j2} } if codes[len(codes)-1].Tag == 'e' { c := codes[len(codes)-1] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + codes[len(codes)-1] = OpCode{c.Tag, i1, minInt(i2, i1+n), j1, minInt(j2, j1+n)} } nn := n + n groups := [][]OpCode{} @@ -443,12 +444,12 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { // there is a large range with no changes. if c.Tag == 'e' && i2-i1 > nn { group = append(group, OpCode{ - c.Tag, i1, min(i2, i1+n), - j1, min(j2, j1+n), + c.Tag, i1, minInt(i2, i1+n), + j1, minInt(j2, j1+n), }) groups = append(groups, group) group = []OpCode{} - i1, j1 = max(i1, i2-n), max(j1, j2-n) + i1, j1 = maxInt(i1, i2-n), maxInt(j1, j2-n) } group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) } @@ -515,7 +516,7 @@ func (m *SequenceMatcher) QuickRatio() float64 { // is faster to compute than either .Ratio() or .QuickRatio(). func (m *SequenceMatcher) RealQuickRatio() float64 { la, lb := len(m.a), len(m.b) - return calculateRatio(min(la, lb), la+lb) + return calculateRatio(minInt(la, lb), la+lb) } // Convert range to the "ed" format @@ -524,7 +525,7 @@ func formatRangeUnified(start, stop int) string { beginning := start + 1 // lines start numbering with one length := stop - start if length == 1 { - return fmt.Sprintf("%d", beginning) + return strconv.Itoa(beginning) } if length == 0 { beginning-- // empty ranges begin at line just before the range diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go index 97d17d6cb6..f7f97ef926 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go @@ -66,7 +66,8 @@ func RuntimeMetricsToProm(d *metrics.Description) (string, string, string, bool) name += "_total" } - valid := model.IsValidMetricName(model.LabelValue(namespace + "_" + subsystem + "_" + name)) + // Our current conversion moves to legacy naming, so use legacy validation. + valid := model.IsValidLegacyMetricName(namespace + "_" + subsystem + "_" + name) switch d.Kind { case metrics.KindUint64: case metrics.KindFloat64: diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go index 9d9b81ab44..592eec3e24 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go @@ -108,15 +108,23 @@ func BuildFQName(namespace, subsystem, name string) string { if name == "" { return "" } - switch { - case namespace != "" && subsystem != "": - return strings.Join([]string{namespace, subsystem, name}, "_") - case namespace != "": - return strings.Join([]string{namespace, name}, "_") - case subsystem != "": - return strings.Join([]string{subsystem, name}, "_") + + sb := strings.Builder{} + sb.Grow(len(namespace) + len(subsystem) + len(name) + 2) + + if namespace != "" { + sb.WriteString(namespace) + sb.WriteString("_") } - return name + + if subsystem != "" { + sb.WriteString(subsystem) + sb.WriteString("_") + } + + sb.WriteString(name) + + return sb.String() } type invalidMetric struct { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go index 62a4e7ad9a..e7bce8b58e 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go @@ -23,6 +23,7 @@ import ( type processCollector struct { collectFn func(chan<- Metric) + describeFn func(chan<- *Desc) pidFn func() (int, error) reportErrors bool cpuTotal *Desc @@ -122,26 +123,23 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector { // Set up process metric collection if supported by the runtime. if canCollectProcess() { c.collectFn = c.processCollect + c.describeFn = c.describe } else { - c.collectFn = func(ch chan<- Metric) { - c.reportError(ch, nil, errors.New("process metrics not supported on this platform")) - } + c.collectFn = c.errorCollectFn + c.describeFn = c.errorDescribeFn } return c } -// Describe returns all descriptions of the collector. -func (c *processCollector) Describe(ch chan<- *Desc) { - ch <- c.cpuTotal - ch <- c.openFDs - ch <- c.maxFDs - ch <- c.vsize - ch <- c.maxVsize - ch <- c.rss - ch <- c.startTime - ch <- c.inBytes - ch <- c.outBytes +func (c *processCollector) errorCollectFn(ch chan<- Metric) { + c.reportError(ch, nil, errors.New("process metrics not supported on this platform")) +} + +func (c *processCollector) errorDescribeFn(ch chan<- *Desc) { + if c.reportErrors { + ch <- NewInvalidDesc(errors.New("process metrics not supported on this platform")) + } } // Collect returns the current state of all metrics of the collector. @@ -149,6 +147,11 @@ func (c *processCollector) Collect(ch chan<- Metric) { c.collectFn(ch) } +// Describe returns all descriptions of the collector. +func (c *processCollector) Describe(ch chan<- *Desc) { + c.describeFn(ch) +} + func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) { if !c.reportErrors { return diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go new file mode 100644 index 0000000000..0a61b98461 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go @@ -0,0 +1,130 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build darwin && !ios + +package prometheus + +import ( + "errors" + "fmt" + "os" + "syscall" + "time" + + "golang.org/x/sys/unix" +) + +// notImplementedErr is returned by stub functions that replace cgo functions, when cgo +// isn't available. +var notImplementedErr = errors.New("not implemented") + +type memoryInfo struct { + vsize uint64 // Virtual memory size in bytes + rss uint64 // Resident memory size in bytes +} + +func canCollectProcess() bool { + return true +} + +func getSoftLimit(which int) (uint64, error) { + rlimit := syscall.Rlimit{} + + if err := syscall.Getrlimit(which, &rlimit); err != nil { + return 0, err + } + + return rlimit.Cur, nil +} + +func getOpenFileCount() (float64, error) { + // Alternately, the undocumented proc_pidinfo(PROC_PIDLISTFDS) can be used to + // return a list of open fds, but that requires a way to call C APIs. The + // benefits, however, include fewer system calls and not failing when at the + // open file soft limit. + + if dir, err := os.Open("/dev/fd"); err != nil { + return 0.0, err + } else { + defer dir.Close() + + // Avoid ReadDir(), as it calls stat(2) on each descriptor. Not only is + // that info not used, but KQUEUE descriptors fail stat(2), which causes + // the whole method to fail. + if names, err := dir.Readdirnames(0); err != nil { + return 0.0, err + } else { + // Subtract 1 to ignore the open /dev/fd descriptor above. + return float64(len(names) - 1), nil + } + } +} + +func (c *processCollector) processCollect(ch chan<- Metric) { + if procs, err := unix.SysctlKinfoProcSlice("kern.proc.pid", os.Getpid()); err == nil { + if len(procs) == 1 { + startTime := float64(procs[0].Proc.P_starttime.Nano() / 1e9) + ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime) + } else { + err = fmt.Errorf("sysctl() returned %d proc structs (expected 1)", len(procs)) + c.reportError(ch, c.startTime, err) + } + } else { + c.reportError(ch, c.startTime, err) + } + + // The proc structure returned by kern.proc.pid above has an Rusage member, + // but it is not filled in, so it needs to be fetched by getrusage(2). For + // that call, the UTime, STime, and Maxrss members are filled out, but not + // Ixrss, Idrss, or Isrss for the memory usage. Memory stats will require + // access to the C API to call task_info(TASK_BASIC_INFO). + rusage := unix.Rusage{} + + if err := unix.Getrusage(syscall.RUSAGE_SELF, &rusage); err == nil { + cpuTime := time.Duration(rusage.Stime.Nano() + rusage.Utime.Nano()).Seconds() + ch <- MustNewConstMetric(c.cpuTotal, CounterValue, cpuTime) + } else { + c.reportError(ch, c.cpuTotal, err) + } + + if memInfo, err := getMemory(); err == nil { + ch <- MustNewConstMetric(c.rss, GaugeValue, float64(memInfo.rss)) + ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(memInfo.vsize)) + } else if !errors.Is(err, notImplementedErr) { + // Don't report an error when support is not compiled in. + c.reportError(ch, c.rss, err) + c.reportError(ch, c.vsize, err) + } + + if fds, err := getOpenFileCount(); err == nil { + ch <- MustNewConstMetric(c.openFDs, GaugeValue, fds) + } else { + c.reportError(ch, c.openFDs, err) + } + + if openFiles, err := getSoftLimit(syscall.RLIMIT_NOFILE); err == nil { + ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(openFiles)) + } else { + c.reportError(ch, c.maxFDs, err) + } + + if addressSpace, err := getSoftLimit(syscall.RLIMIT_AS); err == nil { + ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(addressSpace)) + } else { + c.reportError(ch, c.maxVsize, err) + } + + // TODO: socket(PF_SYSTEM) to fetch "com.apple.network.statistics" might + // be able to get the per-process network send/receive counts. +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.c b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.c new file mode 100644 index 0000000000..d00a24315d --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.c @@ -0,0 +1,84 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build darwin && !ios && cgo + +#include +#include +#include + +// The compiler warns that mach/shared_memory_server.h is deprecated, and to use +// mach/shared_region.h instead. But that doesn't define +// SHARED_DATA_REGION_SIZE or SHARED_TEXT_REGION_SIZE, so redefine them here and +// avoid a warning message when running tests. +#define GLOBAL_SHARED_TEXT_SEGMENT 0x90000000U +#define SHARED_DATA_REGION_SIZE 0x10000000 +#define SHARED_TEXT_REGION_SIZE 0x10000000 + + +int get_memory_info(unsigned long long *rss, unsigned long long *vsize) +{ + // This is lightly adapted from how ps(1) obtains its memory info. + // https://github.com/apple-oss-distributions/adv_cmds/blob/8744084ea0ff41ca4bb96b0f9c22407d0e48e9b7/ps/tasks.c#L109 + + kern_return_t error; + task_t task = MACH_PORT_NULL; + mach_task_basic_info_data_t info; + mach_msg_type_number_t info_count = MACH_TASK_BASIC_INFO_COUNT; + + error = task_info( + mach_task_self(), + MACH_TASK_BASIC_INFO, + (task_info_t) &info, + &info_count ); + + if( error != KERN_SUCCESS ) + { + return error; + } + + *rss = info.resident_size; + *vsize = info.virtual_size; + + { + vm_region_basic_info_data_64_t b_info; + mach_vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT; + mach_vm_size_t size; + mach_port_t object_name; + + /* + * try to determine if this task has the split libraries + * mapped in... if so, adjust its virtual size down by + * the 2 segments that are used for split libraries + */ + info_count = VM_REGION_BASIC_INFO_COUNT_64; + + error = mach_vm_region( + mach_task_self(), + &address, + &size, + VM_REGION_BASIC_INFO_64, + (vm_region_info_t) &b_info, + &info_count, + &object_name); + + if (error == KERN_SUCCESS) { + if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) && + *vsize > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE)) { + *vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE); + } + } + } + + return 0; +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.go new file mode 100644 index 0000000000..9ac53f9992 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.go @@ -0,0 +1,51 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build darwin && !ios && cgo + +package prometheus + +/* +int get_memory_info(unsigned long long *rss, unsigned long long *vs); +*/ +import "C" +import "fmt" + +func getMemory() (*memoryInfo, error) { + var rss, vsize C.ulonglong + + if err := C.get_memory_info(&rss, &vsize); err != 0 { + return nil, fmt.Errorf("task_info() failed with 0x%x", int(err)) + } + + return &memoryInfo{vsize: uint64(vsize), rss: uint64(rss)}, nil +} + +// describe returns all descriptions of the collector for Darwin. +// Ensure that this list of descriptors is kept in sync with the metrics collected +// in the processCollect method. Any changes to the metrics in processCollect +// (such as adding or removing metrics) should be reflected in this list of descriptors. +func (c *processCollector) describe(ch chan<- *Desc) { + ch <- c.cpuTotal + ch <- c.openFDs + ch <- c.maxFDs + ch <- c.maxVsize + ch <- c.startTime + ch <- c.rss + ch <- c.vsize + + /* the process could be collected but not implemented yet + ch <- c.inBytes + ch <- c.outBytes + */ +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go new file mode 100644 index 0000000000..8ddb0995d6 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go @@ -0,0 +1,39 @@ +// Copyright 2024 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build darwin && !ios && !cgo + +package prometheus + +func getMemory() (*memoryInfo, error) { + return nil, notImplementedErr +} + +// describe returns all descriptions of the collector for Darwin. +// Ensure that this list of descriptors is kept in sync with the metrics collected +// in the processCollect method. Any changes to the metrics in processCollect +// (such as adding or removing metrics) should be reflected in this list of descriptors. +func (c *processCollector) describe(ch chan<- *Desc) { + ch <- c.cpuTotal + ch <- c.openFDs + ch <- c.maxFDs + ch <- c.maxVsize + ch <- c.startTime + + /* the process could be collected but not implemented yet + ch <- c.rss + ch <- c.vsize + ch <- c.inBytes + ch <- c.outBytes + */ +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_not_supported.go similarity index 56% rename from vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go rename to vendor/github.com/prometheus/client_golang/prometheus/process_collector_not_supported.go index b1e363d6cf..7732b7f376 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_not_supported.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright 2023 The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build js -// +build js +//go:build wasip1 || js || ios +// +build wasip1 js ios package prometheus @@ -21,6 +21,13 @@ func canCollectProcess() bool { } func (c *processCollector) processCollect(ch chan<- Metric) { - // noop on this platform - return + c.errorCollectFn(ch) +} + +// describe returns all descriptions of the collector for wasip1 and js. +// Ensure that this list of descriptors is kept in sync with the metrics collected +// in the processCollect method. Any changes to the metrics in processCollect +// (such as adding or removing metrics) should be reflected in this list of descriptors. +func (c *processCollector) describe(ch chan<- *Desc) { + c.errorDescribeFn(ch) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go similarity index 77% rename from vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go rename to vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go index 14d56d2d06..9f4b130bef 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !windows && !js && !wasip1 -// +build !windows,!js,!wasip1 +//go:build !windows && !js && !wasip1 && !darwin +// +build !windows,!js,!wasip1,!darwin package prometheus @@ -78,3 +78,19 @@ func (c *processCollector) processCollect(ch chan<- Metric) { c.reportError(ch, nil, err) } } + +// describe returns all descriptions of the collector for others than windows, js, wasip1 and darwin. +// Ensure that this list of descriptors is kept in sync with the metrics collected +// in the processCollect method. Any changes to the metrics in processCollect +// (such as adding or removing metrics) should be reflected in this list of descriptors. +func (c *processCollector) describe(ch chan<- *Desc) { + ch <- c.cpuTotal + ch <- c.openFDs + ch <- c.maxFDs + ch <- c.vsize + ch <- c.maxVsize + ch <- c.rss + ch <- c.startTime + ch <- c.inBytes + ch <- c.outBytes +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go deleted file mode 100644 index d8d9a6d7a2..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2023 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build wasip1 -// +build wasip1 - -package prometheus - -func canCollectProcess() bool { - return false -} - -func (*processCollector) processCollect(chan<- Metric) { - // noop on this platform - return -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go index f973398df2..fa474289ef 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go @@ -79,14 +79,10 @@ func getProcessHandleCount(handle windows.Handle) (uint32, error) { } func (c *processCollector) processCollect(ch chan<- Metric) { - h, err := windows.GetCurrentProcess() - if err != nil { - c.reportError(ch, nil, err) - return - } + h := windows.CurrentProcess() var startTime, exitTime, kernelTime, userTime windows.Filetime - err = windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime) + err := windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime) if err != nil { c.reportError(ch, nil, err) return @@ -111,6 +107,19 @@ func (c *processCollector) processCollect(ch chan<- Metric) { ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(16*1024*1024)) // Windows has a hard-coded max limit, not per-process. } +// describe returns all descriptions of the collector for windows. +// Ensure that this list of descriptors is kept in sync with the metrics collected +// in the processCollect method. Any changes to the metrics in processCollect +// (such as adding or removing metrics) should be reflected in this list of descriptors. +func (c *processCollector) describe(ch chan<- *Desc) { + ch <- c.cpuTotal + ch <- c.openFDs + ch <- c.maxFDs + ch <- c.vsize + ch <- c.rss + ch <- c.startTime +} + func fileTimeToSeconds(ft windows.Filetime) float64 { return float64(uint64(ft.HighDateTime)<<32+uint64(ft.LowDateTime)) / 1e7 } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index e598e66e68..28eed26727 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -207,7 +207,13 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO if encodingHeader != string(Identity) { rsp.Header().Set(contentEncodingHeader, encodingHeader) } - enc := expfmt.NewEncoder(w, contentType) + + var enc expfmt.Encoder + if opts.EnableOpenMetricsTextCreatedSamples { + enc = expfmt.NewEncoder(w, contentType, expfmt.WithCreatedLines()) + } else { + enc = expfmt.NewEncoder(w, contentType) + } // handleError handles the error according to opts.ErrorHandling // and returns true if we have to abort after the handling. @@ -408,6 +414,21 @@ type HandlerOpts struct { // (which changes the identity of the resulting series on the Prometheus // server). EnableOpenMetrics bool + // EnableOpenMetricsTextCreatedSamples specifies if this handler should add, extra, synthetic + // Created Timestamps for counters, histograms and summaries, which for the current + // version of OpenMetrics are defined as extra series with the same name and "_created" + // suffix. See also the OpenMetrics specification for more details + // https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#counter-1 + // + // Created timestamps are used to improve the accuracy of reset detection, + // but the way it's designed in OpenMetrics 1.0 it also dramatically increases cardinality + // if the scraper does not handle those metrics correctly (converting to created timestamp + // instead of leaving those series as-is). New OpenMetrics versions might improve + // this situation. + // + // Prometheus introduced the feature flag 'created-timestamp-zero-ingestion' + // in version 2.50.0 to handle this situation. + EnableOpenMetricsTextCreatedSamples bool // ProcessStartTime allows setting process start timevalue that will be exposed // with "Process-Start-Time-Unix" response header along with the metrics // payload. This allow callers to have efficient transformations to cumulative diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index 1ab0e47965..ac5203c6fa 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go @@ -243,6 +243,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { s := &summary{ desc: desc, + now: opts.now, objectives: opts.Objectives, sortedObjectives: make([]float64, 0, len(opts.Objectives)), @@ -280,6 +281,8 @@ type summary struct { desc *Desc + now func() time.Time + objectives map[float64]float64 sortedObjectives []float64 @@ -307,7 +310,7 @@ func (s *summary) Observe(v float64) { s.bufMtx.Lock() defer s.bufMtx.Unlock() - now := time.Now() + now := s.now() if now.After(s.hotBufExpTime) { s.asyncFlush(now) } @@ -326,7 +329,7 @@ func (s *summary) Write(out *dto.Metric) error { s.bufMtx.Lock() s.mtx.Lock() // Swap bufs even if hotBuf is empty to set new hotBufExpTime. - s.swapBufs(time.Now()) + s.swapBufs(s.now()) s.bufMtx.Unlock() s.flushColdBuf() diff --git a/vendor/github.com/prometheus/common/model/alert.go b/vendor/github.com/prometheus/common/model/alert.go index bd3a39e3e1..460f554f29 100644 --- a/vendor/github.com/prometheus/common/model/alert.go +++ b/vendor/github.com/prometheus/common/model/alert.go @@ -65,7 +65,7 @@ func (a *Alert) Resolved() bool { return a.ResolvedAt(time.Now()) } -// ResolvedAt returns true off the activity interval ended before +// ResolvedAt returns true iff the activity interval ended before // the given timestamp. func (a *Alert) ResolvedAt(ts time.Time) bool { if a.EndsAt.IsZero() { diff --git a/vendor/github.com/prometheus/common/model/labels.go b/vendor/github.com/prometheus/common/model/labels.go index 73b7aa3e60..f4a387605f 100644 --- a/vendor/github.com/prometheus/common/model/labels.go +++ b/vendor/github.com/prometheus/common/model/labels.go @@ -22,7 +22,7 @@ import ( ) const ( - // AlertNameLabel is the name of the label containing the an alert's name. + // AlertNameLabel is the name of the label containing the alert's name. AlertNameLabel = "alertname" // ExportedLabelPrefix is the prefix to prepend to the label names present in diff --git a/vendor/github.com/prometheus/common/model/metric.go b/vendor/github.com/prometheus/common/model/metric.go index 5766107cf9..a6b01755bd 100644 --- a/vendor/github.com/prometheus/common/model/metric.go +++ b/vendor/github.com/prometheus/common/model/metric.go @@ -27,13 +27,25 @@ import ( ) var ( - // NameValidationScheme determines the method of name validation to be used by - // all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 - // mode in isolation from other components that don't support UTF-8 may result - // in bugs or other undefined behavior. This value can be set to - // LegacyValidation during startup if a binary is not UTF-8-aware binaries. To - // avoid need for locking, this value should be set once, ideally in an - // init(), before multiple goroutines are started. + // NameValidationScheme determines the global default method of the name + // validation to be used by all calls to IsValidMetricName() and LabelName + // IsValid(). + // + // Deprecated: This variable should not be used and might be removed in the + // far future. If you wish to stick to the legacy name validation use + // `IsValidLegacyMetricName()` and `LabelName.IsValidLegacy()` methods + // instead. This variable is here as an escape hatch for emergency cases, + // given the recent change from `LegacyValidation` to `UTF8Validation`, e.g., + // to delay UTF-8 migrations in time or aid in debugging unforeseen results of + // the change. In such a case, a temporary assignment to `LegacyValidation` + // value in the `init()` function in your main.go or so, could be considered. + // + // Historically we opted for a global variable for feature gating different + // validation schemes in operations that were not otherwise easily adjustable + // (e.g. Labels yaml unmarshaling). That could have been a mistake, a separate + // Labels structure or package might have been a better choice. Given the + // change was made and many upgraded the common already, we live this as-is + // with this warning and learning for the future. NameValidationScheme = UTF8Validation // NameEscapingScheme defines the default way that names will be escaped when @@ -50,7 +62,7 @@ var ( type ValidationScheme int const ( - // LegacyValidation is a setting that requirets that metric and label names + // LegacyValidation is a setting that requires that all metric and label names // conform to the original Prometheus character requirements described by // MetricNameRE and LabelNameRE. LegacyValidation ValidationScheme = iota diff --git a/vendor/github.com/prometheus/procfs/.golangci.yml b/vendor/github.com/prometheus/procfs/.golangci.yml index 126df9e67a..b43e09f683 100644 --- a/vendor/github.com/prometheus/procfs/.golangci.yml +++ b/vendor/github.com/prometheus/procfs/.golangci.yml @@ -2,7 +2,10 @@ linters: enable: - errcheck + - forbidigo - godot + - gofmt + - goimports - gosimple - govet - ineffassign @@ -12,11 +15,17 @@ linters: - testifylint - unused -linter-settings: +linters-settings: + forbidigo: + forbid: + - p: ^fmt\.Print.*$ + msg: Do not commit print statements. godot: capital: true exclude: # Ignore "See: URL" - 'See:' + goimports: + local-prefixes: github.com/prometheus/procfs misspell: locale: US diff --git a/vendor/github.com/prometheus/procfs/Makefile.common b/vendor/github.com/prometheus/procfs/Makefile.common index 1617292350..cbb5d86382 100644 --- a/vendor/github.com/prometheus/procfs/Makefile.common +++ b/vendor/github.com/prometheus/procfs/Makefile.common @@ -61,7 +61,7 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_ SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.59.0 +GOLANGCI_LINT_VERSION ?= v1.60.2 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) @@ -275,3 +275,9 @@ $(1)_precheck: exit 1; \ fi endef + +govulncheck: install-govulncheck + govulncheck ./... + +install-govulncheck: + command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/vendor/github.com/prometheus/procfs/README.md b/vendor/github.com/prometheus/procfs/README.md index 1224816c2a..0718239cf1 100644 --- a/vendor/github.com/prometheus/procfs/README.md +++ b/vendor/github.com/prometheus/procfs/README.md @@ -47,15 +47,15 @@ However, most of the API includes unit tests which can be run with `make test`. The procfs library includes a set of test fixtures which include many example files from the `/proc` and `/sys` filesystems. These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file which is extracted automatically during testing. To add/update the test fixtures, first -ensure the `fixtures` directory is up to date by removing the existing directory and then -extracting the ttar file using `make fixtures/.unpacked` or just `make test`. +ensure the `testdata/fixtures` directory is up to date by removing the existing directory and then +extracting the ttar file using `make testdata/fixtures/.unpacked` or just `make test`. ```bash rm -rf testdata/fixtures make test ``` -Next, make the required changes to the extracted files in the `fixtures` directory. When +Next, make the required changes to the extracted files in the `testdata/fixtures` directory. When the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file based on the updated `fixtures` directory. And finally, verify the changes using `git diff testdata/fixtures.ttar`. diff --git a/vendor/github.com/prometheus/procfs/arp.go b/vendor/github.com/prometheus/procfs/arp.go index cdcc8a7ccc..2e53344151 100644 --- a/vendor/github.com/prometheus/procfs/arp.go +++ b/vendor/github.com/prometheus/procfs/arp.go @@ -23,9 +23,9 @@ import ( // Learned from include/uapi/linux/if_arp.h. const ( - // completed entry (ha valid). + // Completed entry (ha valid). ATFComplete = 0x02 - // permanent entry. + // Permanent entry. ATFPermanent = 0x04 // Publish entry. ATFPublish = 0x08 diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go index 4980c875bf..9bdaccc7c8 100644 --- a/vendor/github.com/prometheus/procfs/fs.go +++ b/vendor/github.com/prometheus/procfs/fs.go @@ -24,8 +24,14 @@ type FS struct { isReal bool } -// DefaultMountPoint is the common mount point of the proc filesystem. -const DefaultMountPoint = fs.DefaultProcMountPoint +const ( + // DefaultMountPoint is the common mount point of the proc filesystem. + DefaultMountPoint = fs.DefaultProcMountPoint + + // SectorSize represents the size of a sector in bytes. + // It is specific to Linux block I/O operations. + SectorSize = 512 +) // NewDefaultFS returns a new proc FS mounted under the default proc mountPoint. // It will error if the mount point directory can't be read or is a file. diff --git a/vendor/github.com/prometheus/procfs/fs_statfs_notype.go b/vendor/github.com/prometheus/procfs/fs_statfs_notype.go index 134767d69a..1b5bdbdf84 100644 --- a/vendor/github.com/prometheus/procfs/fs_statfs_notype.go +++ b/vendor/github.com/prometheus/procfs/fs_statfs_notype.go @@ -17,7 +17,7 @@ package procfs // isRealProc returns true on architectures that don't have a Type argument -// in their Statfs_t struct -func isRealProc(mountPoint string) (bool, error) { +// in their Statfs_t struct. +func isRealProc(_ string) (bool, error) { return true, nil } diff --git a/vendor/github.com/prometheus/procfs/fscache.go b/vendor/github.com/prometheus/procfs/fscache.go index cf2e3eaa03..7db8633077 100644 --- a/vendor/github.com/prometheus/procfs/fscache.go +++ b/vendor/github.com/prometheus/procfs/fscache.go @@ -162,7 +162,7 @@ type Fscacheinfo struct { ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64 // Number of release reqs ignored due to in-progress store ReleaseRequestsIgnoredDueToInProgressStore uint64 - // Number of page stores cancelled due to release req + // Number of page stores canceled due to release req PageStoresCancelledByReleaseRequests uint64 VmscanWaiting uint64 // Number of times async ops added to pending queues @@ -171,11 +171,11 @@ type Fscacheinfo struct { OpsRunning uint64 // Number of times async ops queued for processing OpsEnqueued uint64 - // Number of async ops cancelled + // Number of async ops canceled OpsCancelled uint64 // Number of async ops rejected due to object lookup/create failure OpsRejected uint64 - // Number of async ops initialised + // Number of async ops initialized OpsInitialised uint64 // Number of async ops queued for deferred release OpsDeferred uint64 diff --git a/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/vendor/github.com/prometheus/procfs/internal/fs/fs.go index 3c18c7610e..3a43e83915 100644 --- a/vendor/github.com/prometheus/procfs/internal/fs/fs.go +++ b/vendor/github.com/prometheus/procfs/internal/fs/fs.go @@ -28,6 +28,9 @@ const ( // DefaultConfigfsMountPoint is the common mount point of the configfs. DefaultConfigfsMountPoint = "/sys/kernel/config" + + // DefaultSelinuxMountPoint is the common mount point of the selinuxfs. + DefaultSelinuxMountPoint = "/sys/fs/selinux" ) // FS represents a pseudo-filesystem, normally /proc or /sys, which provides an diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go index 14272dc788..5a7d2df06a 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/parse.go +++ b/vendor/github.com/prometheus/procfs/internal/util/parse.go @@ -14,6 +14,7 @@ package util import ( + "errors" "os" "strconv" "strings" @@ -110,3 +111,16 @@ func ParseBool(b string) *bool { } return &truth } + +// ReadHexFromFile reads a file and attempts to parse a uint64 from a hexadecimal format 0xXX. +func ReadHexFromFile(path string) (uint64, error) { + data, err := os.ReadFile(path) + if err != nil { + return 0, err + } + hexString := strings.TrimSpace(string(data)) + if !strings.HasPrefix(hexString, "0x") { + return 0, errors.New("invalid format: hex string does not start with '0x'") + } + return strconv.ParseUint(hexString[2:], 16, 64) +} diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go index 75a3b6c810..b6c8d1a570 100644 --- a/vendor/github.com/prometheus/procfs/mountstats.go +++ b/vendor/github.com/prometheus/procfs/mountstats.go @@ -45,11 +45,11 @@ const ( fieldTransport11TCPLen = 13 fieldTransport11UDPLen = 10 - // kernel version >= 4.14 MaxLen + // Kernel version >= 4.14 MaxLen // See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393 fieldTransport11RDMAMaxLen = 28 - // kernel version <= 4.2 MinLen + // Kernel version <= 4.2 MinLen // See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331 fieldTransport11RDMAMinLen = 20 ) diff --git a/vendor/github.com/prometheus/procfs/net_dev_snmp6.go b/vendor/github.com/prometheus/procfs/net_dev_snmp6.go new file mode 100644 index 0000000000..f50b38e352 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/net_dev_snmp6.go @@ -0,0 +1,96 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "errors" + "io" + "os" + "strconv" + "strings" +) + +// NetDevSNMP6 is parsed from files in /proc/net/dev_snmp6/ or /proc//net/dev_snmp6/. +// The outer map's keys are interface names and the inner map's keys are stat names. +// +// If you'd like a total across all interfaces, please use the Snmp6() method of the Proc type. +type NetDevSNMP6 map[string]map[string]uint64 + +// Returns kernel/system statistics read from interface files within the /proc/net/dev_snmp6/ +// directory. +func (fs FS) NetDevSNMP6() (NetDevSNMP6, error) { + return newNetDevSNMP6(fs.proc.Path("net/dev_snmp6")) +} + +// Returns kernel/system statistics read from interface files within the /proc//net/dev_snmp6/ +// directory. +func (p Proc) NetDevSNMP6() (NetDevSNMP6, error) { + return newNetDevSNMP6(p.path("net/dev_snmp6")) +} + +// newNetDevSNMP6 creates a new NetDevSNMP6 from the contents of the given directory. +func newNetDevSNMP6(dir string) (NetDevSNMP6, error) { + netDevSNMP6 := make(NetDevSNMP6) + + // The net/dev_snmp6 folders contain one file per interface + ifaceFiles, err := os.ReadDir(dir) + if err != nil { + // On systems with IPv6 disabled, this directory won't exist. + // Do nothing. + if errors.Is(err, os.ErrNotExist) { + return netDevSNMP6, err + } + return netDevSNMP6, err + } + + for _, iFaceFile := range ifaceFiles { + f, err := os.Open(dir + "/" + iFaceFile.Name()) + if err != nil { + return netDevSNMP6, err + } + defer f.Close() + + netDevSNMP6[iFaceFile.Name()], err = parseNetDevSNMP6Stats(f) + if err != nil { + return netDevSNMP6, err + } + } + + return netDevSNMP6, nil +} + +func parseNetDevSNMP6Stats(r io.Reader) (map[string]uint64, error) { + m := make(map[string]uint64) + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + stat := strings.Fields(scanner.Text()) + if len(stat) < 2 { + continue + } + key, val := stat[0], stat[1] + + // Expect stat name to contain "6" or be "ifIndex" + if strings.Contains(key, "6") || key == "ifIndex" { + v, err := strconv.ParseUint(val, 10, 64) + if err != nil { + return m, err + } + + m[key] = v + } + } + return m, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/net_ip_socket.go b/vendor/github.com/prometheus/procfs/net_ip_socket.go index b70f1fc7a4..19e3378f72 100644 --- a/vendor/github.com/prometheus/procfs/net_ip_socket.go +++ b/vendor/github.com/prometheus/procfs/net_ip_socket.go @@ -25,7 +25,7 @@ import ( ) const ( - // readLimit is used by io.LimitReader while reading the content of the + // Maximum size limit used by io.LimitReader while reading the content of the // /proc/net/udp{,6} files. The number of lines inside such a file is dynamic // as each line represents a single used socket. // In theory, the number of available sockets is 65535 (2^16 - 1) per IP. @@ -50,12 +50,12 @@ type ( // UsedSockets shows the total number of parsed lines representing the // number of used sockets. UsedSockets uint64 - // Drops shows the total number of dropped packets of all UPD sockets. + // Drops shows the total number of dropped packets of all UDP sockets. Drops *uint64 } - // netIPSocketLine represents the fields parsed from a single line - // in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped. + // A single line parser for fields from /proc/net/{t,u}dp{,6}. + // Fields which are not used by IPSocket are skipped. // Drops is non-nil for udp{,6}, but nil for tcp{,6}. // For the proc file format details, see https://linux.die.net/man/5/proc. netIPSocketLine struct { diff --git a/vendor/github.com/prometheus/procfs/net_tcp.go b/vendor/github.com/prometheus/procfs/net_tcp.go index 5277629557..0396d72015 100644 --- a/vendor/github.com/prometheus/procfs/net_tcp.go +++ b/vendor/github.com/prometheus/procfs/net_tcp.go @@ -25,24 +25,28 @@ type ( // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead. func (fs FS) NetTCP() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp")) } // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp6. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead. func (fs FS) NetTCP6() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp6")) } // NetTCPSummary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead. func (fs FS) NetTCPSummary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp")) } // NetTCP6Summary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp6. +// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead. func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp6")) } diff --git a/vendor/github.com/prometheus/procfs/net_unix.go b/vendor/github.com/prometheus/procfs/net_unix.go index d868cebdaa..d7e0cacb4c 100644 --- a/vendor/github.com/prometheus/procfs/net_unix.go +++ b/vendor/github.com/prometheus/procfs/net_unix.go @@ -121,12 +121,12 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) { return &nu, nil } -func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) { +func (u *NetUNIX) parseLine(line string, hasInode bool, minFields int) (*NetUNIXLine, error) { fields := strings.Fields(line) l := len(fields) - if l < min { - return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l) + if l < minFields { + return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, minFields, l) } // Field offsets are as follows: @@ -172,7 +172,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, } // Path field is optional. - if l > min { + if l > minFields { // Path occurs at either index 6 or 7 depending on whether inode is // already present. pathIdx := 7 diff --git a/vendor/github.com/prometheus/procfs/proc_cgroup.go b/vendor/github.com/prometheus/procfs/proc_cgroup.go index daeed7f571..4a64347c03 100644 --- a/vendor/github.com/prometheus/procfs/proc_cgroup.go +++ b/vendor/github.com/prometheus/procfs/proc_cgroup.go @@ -24,7 +24,7 @@ import ( ) // Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a -// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource +// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. The v1 has one hierarchy per available resource // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in // this hierarchy' (where==what path on the specific cgroupfs). By prefixing this path with the mount point of diff --git a/vendor/github.com/prometheus/procfs/proc_io.go b/vendor/github.com/prometheus/procfs/proc_io.go index 776f349717..d15b66ddb6 100644 --- a/vendor/github.com/prometheus/procfs/proc_io.go +++ b/vendor/github.com/prometheus/procfs/proc_io.go @@ -50,7 +50,7 @@ func (p Proc) IO() (ProcIO, error) { ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + "read_bytes: %d\nwrite_bytes: %d\n" + - "cancelled_write_bytes: %d\n" + "cancelled_write_bytes: %d\n" //nolint:misspell _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) diff --git a/vendor/github.com/prometheus/procfs/proc_smaps.go b/vendor/github.com/prometheus/procfs/proc_smaps.go index 09060e8208..9a297afcf8 100644 --- a/vendor/github.com/prometheus/procfs/proc_smaps.go +++ b/vendor/github.com/prometheus/procfs/proc_smaps.go @@ -19,7 +19,6 @@ package procfs import ( "bufio" "errors" - "fmt" "os" "regexp" "strconv" @@ -29,7 +28,7 @@ import ( ) var ( - // match the header line before each mapped zone in `/proc/pid/smaps`. + // Match the header line before each mapped zone in `/proc/pid/smaps`. procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`) ) @@ -117,7 +116,6 @@ func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) { func (s *ProcSMapsRollup) parseLine(line string) error { kv := strings.SplitN(line, ":", 2) if len(kv) != 2 { - fmt.Println(line) return errors.New("invalid net/dev line, missing colon") } diff --git a/vendor/github.com/prometheus/procfs/proc_status.go b/vendor/github.com/prometheus/procfs/proc_status.go index a055197c63..dd8aa56885 100644 --- a/vendor/github.com/prometheus/procfs/proc_status.go +++ b/vendor/github.com/prometheus/procfs/proc_status.go @@ -146,7 +146,11 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt } } case "NSpid": - s.NSpids = calcNSPidsList(vString) + nspids, err := calcNSPidsList(vString) + if err != nil { + return err + } + s.NSpids = nspids case "VmPeak": s.VmPeak = vUintBytes case "VmSize": @@ -222,17 +226,17 @@ func calcCpusAllowedList(cpuString string) []uint64 { return g } -func calcNSPidsList(nspidsString string) []uint64 { - s := strings.Split(nspidsString, " ") +func calcNSPidsList(nspidsString string) ([]uint64, error) { + s := strings.Split(nspidsString, "\t") var nspids []uint64 for _, nspid := range s { - nspid, _ := strconv.ParseUint(nspid, 10, 64) - if nspid == 0 { - continue + nspid, err := strconv.ParseUint(nspid, 10, 64) + if err != nil { + return nil, err } nspids = append(nspids, nspid) } - return nspids + return nspids, nil } diff --git a/vendor/github.com/sagikazarmark/locafero/finder.go b/vendor/github.com/sagikazarmark/locafero/finder.go index 754c8b260e..ef8d547122 100644 --- a/vendor/github.com/sagikazarmark/locafero/finder.go +++ b/vendor/github.com/sagikazarmark/locafero/finder.go @@ -27,7 +27,7 @@ type Finder struct { // It provides the capability to search for entries with depth, // meaning it can target deeper locations within the directory structure. // - // It also supports glob syntax (as defined by [filepat.Match]), offering greater flexibility in search patterns. + // It also supports glob syntax (as defined by [filepath.Match]), offering greater flexibility in search patterns. // // Examples: // - config.yaml @@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { // pool.Go(func() ([]string, error) { // // If the name contains any glob character, perform a glob match - // if strings.ContainsAny(searchName, "*?[]\\^") { + // if strings.ContainsAny(searchName, globMatch) { // return globWalkSearch(fsys, searchPath, searchName, f.Type) // } // @@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) { // If the name contains any glob character, perform a glob match - if strings.ContainsAny(item.name, "*?[]\\^") { + if strings.ContainsAny(item.name, globMatch) { return globWalkSearch(fsys, item.path, item.name, f.Type) } diff --git a/vendor/github.com/sagikazarmark/locafero/flake.lock b/vendor/github.com/sagikazarmark/locafero/flake.lock index 46d28f805a..df2a8cceca 100644 --- a/vendor/github.com/sagikazarmark/locafero/flake.lock +++ b/vendor/github.com/sagikazarmark/locafero/flake.lock @@ -1,22 +1,84 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, "devenv": { "inputs": { - "flake-compat": "flake-compat", + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1725907707, + "narHash": "sha256-s3pbtzZmVPHzc86WQjK7MGZMNvvw6hWnFMljEkllAfM=", + "owner": "cachix", + "repo": "devenv", + "rev": "2bbbbc468fc02257265a79652a8350651cca495a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] }, "locked": { - "lastModified": 1694097209, - "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=", + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", "owner": "cachix", "repo": "devenv", - "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", "type": "github" }, "original": { "owner": "cachix", + "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -37,16 +99,32 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1693611461, - "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", + "lastModified": 1725234343, + "narHash": "sha256-+ebgonl3NbiKD2UD0x4BszCZQ6sTfL4xioaM49o5B3Y=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", + "rev": "567b938d64d4b4112ee253b9274472dc3a346eb6", "type": "github" }, "original": { @@ -60,11 +138,29 @@ "systems": "systems" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -82,11 +178,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", "type": "github" }, "original": { @@ -95,53 +191,90 @@ "type": "github" } }, - "lowdown-src": { - "flake": false, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", "type": "github" } }, - "nix": { + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { "inputs": { - "lowdown-src": "lowdown-src", + "flake-compat": [ + "devenv", + "flake-compat" + ], "nixpkgs": [ "devenv", "nixpkgs" ], - "nixpkgs-regression": "nixpkgs-regression" + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", "owner": "domenkozar", "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "relaxed-flakes", + "ref": "devenv-2.21", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", "type": "github" }, "original": { @@ -153,23 +286,33 @@ }, "nixpkgs-lib": { "locked": { - "dir": "lib", - "lastModified": 1693471703, - "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", + "lastModified": 1725233747, + "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "dir": "lib", "owner": "NixOS", - "ref": "nixos-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs-regression_2": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -187,27 +330,43 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1694343207, - "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=", + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1725910328, + "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "78058d810644f5ed276804ce7ea9e82d92bee293", + "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4", "type": "github" }, "original": { @@ -217,13 +376,38 @@ "type": "github" } }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "devenv", "flake-compat" ], - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "gitignore": "gitignore", "nixpkgs": [ "devenv", @@ -232,11 +416,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1688056373, - "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", "type": "github" }, "original": { @@ -249,7 +433,7 @@ "inputs": { "devenv": "devenv", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" } }, "systems": { @@ -266,6 +450,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/vendor/github.com/sagikazarmark/locafero/flake.nix b/vendor/github.com/sagikazarmark/locafero/flake.nix index 209ecf2860..312f1ec8cf 100644 --- a/vendor/github.com/sagikazarmark/locafero/flake.nix +++ b/vendor/github.com/sagikazarmark/locafero/flake.nix @@ -20,6 +20,7 @@ default = { languages = { go.enable = true; + go.package = pkgs.lib.mkDefault pkgs.go_1_23; }; packages = with pkgs; [ @@ -34,11 +35,27 @@ ci = devenv.shells.default; - ci_1_20 = { + ci_1_21 = { imports = [ devenv.shells.ci ]; languages = { - go.package = pkgs.go_1_20; + go.package = pkgs.go_1_21; + }; + }; + + ci_1_22 = { + imports = [ devenv.shells.ci ]; + + languages = { + go.package = pkgs.go_1_22; + }; + }; + + ci_1_23 = { + imports = [ devenv.shells.ci ]; + + languages = { + go.package = pkgs.go_1_23; }; }; }; diff --git a/vendor/github.com/sagikazarmark/locafero/glob.go b/vendor/github.com/sagikazarmark/locafero/glob.go new file mode 100644 index 0000000000..00f833e99c --- /dev/null +++ b/vendor/github.com/sagikazarmark/locafero/glob.go @@ -0,0 +1,5 @@ +//go:build !windows + +package locafero + +const globMatch = "*?[]\\^" diff --git a/vendor/github.com/sagikazarmark/locafero/glob_windows.go b/vendor/github.com/sagikazarmark/locafero/glob_windows.go new file mode 100644 index 0000000000..7aec2b247d --- /dev/null +++ b/vendor/github.com/sagikazarmark/locafero/glob_windows.go @@ -0,0 +1,8 @@ +//go:build windows + +package locafero + +// See [filepath.Match]: +// +// On Windows, escaping is disabled. Instead, '\\' is treated as path separator. +const globMatch = "*?[]^" diff --git a/vendor/github.com/sagikazarmark/slog-shim/.gitignore b/vendor/github.com/sagikazarmark/slog-shim/.gitignore deleted file mode 100644 index dc6d8b5875..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/.devenv/ -/.direnv/ -/.task/ -/build/ diff --git a/vendor/github.com/sagikazarmark/slog-shim/LICENSE b/vendor/github.com/sagikazarmark/slog-shim/LICENSE deleted file mode 100644 index 6a66aea5ea..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/sagikazarmark/slog-shim/README.md b/vendor/github.com/sagikazarmark/slog-shim/README.md deleted file mode 100644 index 1f5be85e10..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# [slog](https://pkg.go.dev/log/slog) shim - -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sagikazarmark/slog-shim/ci.yaml?style=flat-square)](https://github.com/sagikazarmark/slog-shim/actions/workflows/ci.yaml) -[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/sagikazarmark/slog-shim) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square) -[![built with nix](https://img.shields.io/badge/builtwith-nix-7d81f7?style=flat-square)](https://builtwithnix.org) - -Go 1.21 introduced a [new structured logging package](https://golang.org/doc/go1.21#slog), `log/slog`, to the standard library. -Although it's been eagerly anticipated by many, widespread adoption isn't expected to occur immediately, -especially since updating to Go 1.21 is a decision that most libraries won't make overnight. - -Before this package was added to the standard library, there was an _experimental_ version available at [golang.org/x/exp/slog](https://pkg.go.dev/golang.org/x/exp/slog). -While it's generally advised against using experimental packages in production, -this one served as a sort of backport package for the last few years, -incorporating new features before they were added to the standard library (like `slices`, `maps` or `errors`). - -This package serves as a bridge, helping libraries integrate slog in a backward-compatible way without having to immediately update their Go version requirement to 1.21. On Go 1.21 (and above), it acts as a drop-in replacement for `log/slog`, while below 1.21 it falls back to `golang.org/x/exp/slog`. - -**How does it achieve backwards compatibility?** - -Although there's no consensus on whether dropping support for older Go versions is considered backward compatible, a majority seems to believe it is. -(I don't have scientific proof for this, but it's based on conversations with various individuals across different channels.) - -This package adheres to that interpretation of backward compatibility. On Go 1.21, the shim uses type aliases to offer the same API as `slog/log`. -Once a library upgrades its version requirement to Go 1.21, it should be able to discard this shim and use `log/slog` directly. - -For older Go versions, the library might become unstable after removing the shim. -However, since those older versions are no longer supported, the promise of backward compatibility remains intact. - -## Installation - -```shell -go get github.com/sagikazarmark/slog-shim -``` - -## Usage - -Import this package into your library and use it in your public API: - -```go -package mylib - -import slog "github.com/sagikazarmark/slog-shim" - -func New(logger *slog.Logger) MyLib { - // ... -} -``` - -When using the library, clients can either use `log/slog` (when on Go 1.21) or `golang.org/x/exp/slog` (below Go 1.21): - -```go -package main - -import "log/slog" - -// OR - -import "golang.org/x/exp/slog" - -mylib.New(slog.Default()) -``` - -**Make sure consumers are aware that your API behaves differently on different Go versions.** - -Once you bump your Go version requirement to Go 1.21, you can drop the shim entirely from your code: - -```diff -package mylib - -- import slog "github.com/sagikazarmark/slog-shim" -+ import "log/slog" - -func New(logger *slog.Logger) MyLib { - // ... -} -``` - -## License - -The project is licensed under a [BSD-style license](LICENSE). diff --git a/vendor/github.com/sagikazarmark/slog-shim/attr.go b/vendor/github.com/sagikazarmark/slog-shim/attr.go deleted file mode 100644 index 89608bf3a7..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/attr.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// An Attr is a key-value pair. -type Attr = slog.Attr - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return slog.String(key, value) -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return slog.Int64(key, value) -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return slog.Int(key, value) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return slog.Uint64(key, v) -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return slog.Float64(key, v) -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return slog.Bool(key, v) -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return slog.Time(key, v) -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return slog.Duration(key, v) -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return slog.Group(key, args...) -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return slog.Any(key, value) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/attr_120.go b/vendor/github.com/sagikazarmark/slog-shim/attr_120.go deleted file mode 100644 index b664813331..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/attr_120.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// An Attr is a key-value pair. -type Attr = slog.Attr - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return slog.String(key, value) -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return slog.Int64(key, value) -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return slog.Int(key, value) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return slog.Uint64(key, v) -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return slog.Float64(key, v) -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return slog.Bool(key, v) -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return slog.Time(key, v) -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return slog.Duration(key, v) -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return slog.Group(key, args...) -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return slog.Any(key, value) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/flake.lock b/vendor/github.com/sagikazarmark/slog-shim/flake.lock deleted file mode 100644 index 7e8898e9e3..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/flake.lock +++ /dev/null @@ -1,273 +0,0 @@ -{ - "nodes": { - "devenv": { - "inputs": { - "flake-compat": "flake-compat", - "nix": "nix", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1694097209, - "narHash": "sha256-gQmBjjxeSyySjbh0yQVBKApo2KWIFqqbRUvG+Fa+QpM=", - "owner": "cachix", - "repo": "devenv", - "rev": "7a8e6a91510efe89d8dcb8e43233f93e86f6b189", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1693611461, - "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "devenv", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "lowdown-src": { - "flake": false, - "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", - "type": "github" - }, - "original": { - "owner": "kristapsdz", - "repo": "lowdown", - "type": "github" - } - }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-regression": "nixpkgs-regression" - }, - "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", - "owner": "domenkozar", - "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", - "type": "github" - }, - "original": { - "owner": "domenkozar", - "ref": "relaxed-flakes", - "repo": "nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-lib": { - "locked": { - "dir": "lib", - "lastModified": 1693471703, - "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", - "type": "github" - }, - "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-regression": { - "locked": { - "lastModified": 1643052045, - "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", - "type": "github" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-23.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1694345580, - "narHash": "sha256-BbG0NUxQTz1dN/Y87yPWZc/0Kp/coJ0vM3+7sNa5kUM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "f002de6834fdde9c864f33c1ec51da7df19cd832", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "master", - "repo": "nixpkgs", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "flake-utils": "flake-utils", - "gitignore": "gitignore", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1688056373, - "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "root": { - "inputs": { - "devenv": "devenv", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/handler.go b/vendor/github.com/sagikazarmark/slog-shim/handler.go deleted file mode 100644 index f55556ae18..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/handler.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler = slog.Handler - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions = slog.HandlerOptions - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = slog.TimeKey - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = slog.LevelKey - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = slog.MessageKey - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = slog.SourceKey -) diff --git a/vendor/github.com/sagikazarmark/slog-shim/handler_120.go b/vendor/github.com/sagikazarmark/slog-shim/handler_120.go deleted file mode 100644 index 670057573f..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/handler_120.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "golang.org/x/exp/slog" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler = slog.Handler - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions = slog.HandlerOptions - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = slog.TimeKey - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = slog.LevelKey - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = slog.MessageKey - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = slog.SourceKey -) diff --git a/vendor/github.com/sagikazarmark/slog-shim/json_handler.go b/vendor/github.com/sagikazarmark/slog-shim/json_handler.go deleted file mode 100644 index 7c22bd81e4..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/json_handler.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "io" - "log/slog" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler = slog.JSONHandler - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - return slog.NewJSONHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go b/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go deleted file mode 100644 index 7b14f10ba9..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/json_handler_120.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "io" - - "golang.org/x/exp/slog" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler = slog.JSONHandler - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - return slog.NewJSONHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/level.go b/vendor/github.com/sagikazarmark/slog-shim/level.go deleted file mode 100644 index 07288cf891..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/level.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level = slog.Level - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = slog.LevelDebug - LevelInfo Level = slog.LevelInfo - LevelWarn Level = slog.LevelWarn - LevelError Level = slog.LevelError -) - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar = slog.LevelVar - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler = slog.Leveler diff --git a/vendor/github.com/sagikazarmark/slog-shim/level_120.go b/vendor/github.com/sagikazarmark/slog-shim/level_120.go deleted file mode 100644 index d3feb94203..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/level_120.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "golang.org/x/exp/slog" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level = slog.Level - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = slog.LevelDebug - LevelInfo Level = slog.LevelInfo - LevelWarn Level = slog.LevelWarn - LevelError Level = slog.LevelError -) - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar = slog.LevelVar - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler = slog.Leveler diff --git a/vendor/github.com/sagikazarmark/slog-shim/logger.go b/vendor/github.com/sagikazarmark/slog-shim/logger.go deleted file mode 100644 index e80036bec5..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/logger.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "context" - "log" - "log/slog" -) - -// Default returns the default Logger. -func Default() *Logger { return slog.Default() } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - slog.SetDefault(l) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger = slog.Logger - -// New creates a new Logger with the given non-nil Handler. -func New(h Handler) *Logger { - return slog.New(h) -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return slog.With(args...) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return slog.NewLogLogger(h, level) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - slog.Debug(msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - slog.DebugContext(ctx, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - slog.Info(msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - slog.InfoContext(ctx, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - slog.Warn(msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - slog.WarnContext(ctx, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - slog.Error(msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - slog.ErrorContext(ctx, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - slog.Log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - slog.LogAttrs(ctx, level, msg, attrs...) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/logger_120.go b/vendor/github.com/sagikazarmark/slog-shim/logger_120.go deleted file mode 100644 index 97ebdd5e1c..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/logger_120.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "context" - "log" - - "golang.org/x/exp/slog" -) - -// Default returns the default Logger. -func Default() *Logger { return slog.Default() } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - slog.SetDefault(l) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger = slog.Logger - -// New creates a new Logger with the given non-nil Handler. -func New(h Handler) *Logger { - return slog.New(h) -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return slog.With(args...) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return slog.NewLogLogger(h, level) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - slog.Debug(msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - slog.DebugContext(ctx, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - slog.Info(msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - slog.InfoContext(ctx, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - slog.Warn(msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - slog.WarnContext(ctx, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - slog.Error(msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - slog.ErrorContext(ctx, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - slog.Log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - slog.LogAttrs(ctx, level, msg, attrs...) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/record.go b/vendor/github.com/sagikazarmark/slog-shim/record.go deleted file mode 100644 index 85ad1f7842..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/record.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Call [NewRecord] to create a new Record. -// Use [Record.Clone] to create a copy with no shared state. -type Record = slog.Record - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return slog.NewRecord(t, level, msg, pc) -} - -// Source describes the location of a line of source code. -type Source = slog.Source diff --git a/vendor/github.com/sagikazarmark/slog-shim/record_120.go b/vendor/github.com/sagikazarmark/slog-shim/record_120.go deleted file mode 100644 index c2eaf4e796..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/record_120.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Call [NewRecord] to create a new Record. -// Use [Record.Clone] to create a copy with no shared state. -type Record = slog.Record - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return slog.NewRecord(t, level, msg, pc) -} - -// Source describes the location of a line of source code. -type Source = slog.Source diff --git a/vendor/github.com/sagikazarmark/slog-shim/text_handler.go b/vendor/github.com/sagikazarmark/slog-shim/text_handler.go deleted file mode 100644 index 45f6cfcba5..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/text_handler.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "io" - "log/slog" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler = slog.TextHandler - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - return slog.NewTextHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go b/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go deleted file mode 100644 index a69d63ccea..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/text_handler_120.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "io" - - "golang.org/x/exp/slog" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler = slog.TextHandler - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - return slog.NewTextHandler(w, opts) -} diff --git a/vendor/github.com/sagikazarmark/slog-shim/value.go b/vendor/github.com/sagikazarmark/slog-shim/value.go deleted file mode 100644 index 61173eb946..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/value.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 - -package slog - -import ( - "log/slog" - "time" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value = slog.Value - -// Kind is the kind of a Value. -type Kind = slog.Kind - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. -const ( - KindAny = slog.KindAny - KindBool = slog.KindBool - KindDuration = slog.KindDuration - KindFloat64 = slog.KindFloat64 - KindInt64 = slog.KindInt64 - KindString = slog.KindString - KindTime = slog.KindTime - KindUint64 = slog.KindUint64 - KindGroup = slog.KindGroup - KindLogValuer = slog.KindLogValuer -) - -//////////////// Constructors - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return slog.StringValue(value) -} - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return slog.IntValue(v) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return slog.Int64Value(v) -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return slog.Uint64Value(v) -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return slog.Float64Value(v) -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - return slog.BoolValue(v) -} - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - return slog.TimeValue(v) -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return slog.DurationValue(v) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return slog.GroupValue(as...) -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - return slog.AnyValue(v) -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer = slog.LogValuer diff --git a/vendor/github.com/sagikazarmark/slog-shim/value_120.go b/vendor/github.com/sagikazarmark/slog-shim/value_120.go deleted file mode 100644 index 0f9f871eee..0000000000 --- a/vendor/github.com/sagikazarmark/slog-shim/value_120.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.21 - -package slog - -import ( - "time" - - "golang.org/x/exp/slog" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value = slog.Value - -// Kind is the kind of a Value. -type Kind = slog.Kind - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. -const ( - KindAny = slog.KindAny - KindBool = slog.KindBool - KindDuration = slog.KindDuration - KindFloat64 = slog.KindFloat64 - KindInt64 = slog.KindInt64 - KindString = slog.KindString - KindTime = slog.KindTime - KindUint64 = slog.KindUint64 - KindGroup = slog.KindGroup - KindLogValuer = slog.KindLogValuer -) - -//////////////// Constructors - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return slog.StringValue(value) -} - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return slog.IntValue(v) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return slog.Int64Value(v) -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return slog.Uint64Value(v) -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return slog.Float64Value(v) -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - return slog.BoolValue(v) -} - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - return slog.TimeValue(v) -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return slog.DurationValue(v) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return slog.GroupValue(as...) -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - return slog.AnyValue(v) -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer = slog.LogValuer diff --git a/vendor/github.com/spf13/afero/README.md b/vendor/github.com/spf13/afero/README.md index 619af574f3..86f1545543 100644 --- a/vendor/github.com/spf13/afero/README.md +++ b/vendor/github.com/spf13/afero/README.md @@ -2,7 +2,11 @@ A FileSystem Abstraction System for Go -[![Test](https://github.com/spf13/afero/actions/workflows/test.yml/badge.svg)](https://github.com/spf13/afero/actions/workflows/test.yml) [![GoDoc](https://godoc.org/github.com/spf13/afero?status.svg)](https://godoc.org/github.com/spf13/afero) [![Join the chat at https://gitter.im/spf13/afero](https://badges.gitter.im/Dev%20Chat.svg)](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/afero/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/afero/actions?query=workflow%3ACI) +[![Join the chat at https://gitter.im/spf13/afero](https://badges.gitter.im/Dev%20Chat.svg)](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/afero?style=flat-square)](https://goreportcard.com/report/github.com/spf13/afero) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.23-61CFDD.svg?style=flat-square) +[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/afero)](https://pkg.go.dev/mod/github.com/spf13/afero) # Overview @@ -427,6 +431,39 @@ See the [Releases Page](https://github.com/spf13/afero/releases). 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request +## Releasing + +As of version 1.14.0, Afero moved implementations with third-party libraries to +their own submodules. + +Releasing a new version now requires a few steps: + +``` +VERSION=X.Y.Z +git tag -a v$VERSION -m "Release $VERSION" +git push origin v$VERSION + +cd gcsfs +go get github.com/spf13/afero@v$VERSION +go mod tidy +git commit -am "Update afero to v$VERSION" +git tag -a gcsfs/v$VERSION -m "Release gcsfs $VERSION" +git push origin gcsfs/v$VERSION +cd .. + +cd sftpfs +go get github.com/spf13/afero@v$VERSION +go mod tidy +git commit -am "Update afero to v$VERSION" +git tag -a sftpfs/v$VERSION -m "Release sftpfs $VERSION" +git push origin sftpfs/v$VERSION +cd .. + +git push +``` + +TODO: move these instructions to a Makefile or something + ## Contributors Names in no particular order: diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 6444f4b7f6..71757151c3 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -1,4 +1,5 @@ -![cobra logo](assets/CobraMain.png) + +![cobra logo](https://github.com/user-attachments/assets/cbc3adf8-0dff-46e9-a88d-5e2d971c169e) Cobra is a library for creating powerful modern CLI applications. @@ -105,7 +106,7 @@ go install github.com/spf13/cobra-cli@latest For complete details on using the Cobra-CLI generator, please read [The Cobra Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) -For complete details on using the Cobra library, please read the [The Cobra User Guide](site/content/user_guide.md). +For complete details on using the Cobra library, please read [The Cobra User Guide](site/content/user_guide.md). # License diff --git a/vendor/github.com/spf13/cobra/active_help.go b/vendor/github.com/spf13/cobra/active_help.go index 25c30e3ccc..b3e2dadfed 100644 --- a/vendor/github.com/spf13/cobra/active_help.go +++ b/vendor/github.com/spf13/cobra/active_help.go @@ -35,7 +35,7 @@ const ( // This function can be called multiple times before and/or after completions are added to // the array. Each time this function is called with the same array, the new // ActiveHelp line will be shown below the previous ones when completion is triggered. -func AppendActiveHelp(compArray []string, activeHelpStr string) []string { +func AppendActiveHelp(compArray []Completion, activeHelpStr string) []Completion { return append(compArray, fmt.Sprintf("%s%s", activeHelpMarker, activeHelpStr)) } diff --git a/vendor/github.com/spf13/cobra/bash_completionsV2.go b/vendor/github.com/spf13/cobra/bash_completionsV2.go index 1cce5c329c..d2397aa366 100644 --- a/vendor/github.com/spf13/cobra/bash_completionsV2.go +++ b/vendor/github.com/spf13/cobra/bash_completionsV2.go @@ -146,7 +146,7 @@ __%[1]s_process_completion_results() { if (((directive & shellCompDirectiveFilterFileExt) != 0)); then # File extension filtering - local fullFilter filter filteringCmd + local fullFilter="" filter filteringCmd # Do not use quotes around the $completions variable or else newline # characters will be kept. @@ -177,20 +177,71 @@ __%[1]s_process_completion_results() { __%[1]s_handle_special_char "$cur" = # Print the activeHelp statements before we finish + __%[1]s_handle_activeHelp +} + +__%[1]s_handle_activeHelp() { + # Print the activeHelp statements if ((${#activeHelp[*]} != 0)); then - printf "\n"; - printf "%%s\n" "${activeHelp[@]}" - printf "\n" - - # The prompt format is only available from bash 4.4. - # We test if it is available before using it. - if (x=${PS1@P}) 2> /dev/null; then - printf "%%s" "${PS1@P}${COMP_LINE[@]}" - else - # Can't print the prompt. Just print the - # text the user had typed, it is workable enough. - printf "%%s" "${COMP_LINE[@]}" + if [ -z $COMP_TYPE ]; then + # Bash v3 does not set the COMP_TYPE variable. + printf "\n"; + printf "%%s\n" "${activeHelp[@]}" + printf "\n" + __%[1]s_reprint_commandLine + return fi + + # Only print ActiveHelp on the second TAB press + if [ $COMP_TYPE -eq 63 ]; then + printf "\n" + printf "%%s\n" "${activeHelp[@]}" + + if ((${#COMPREPLY[*]} == 0)); then + # When there are no completion choices from the program, file completion + # may kick in if the program has not disabled it; in such a case, we want + # to know if any files will match what the user typed, so that we know if + # there will be completions presented, so that we know how to handle ActiveHelp. + # To find out, we actually trigger the file completion ourselves; + # the call to _filedir will fill COMPREPLY if files match. + if (((directive & shellCompDirectiveNoFileComp) == 0)); then + __%[1]s_debug "Listing files" + _filedir + fi + fi + + if ((${#COMPREPLY[*]} != 0)); then + # If there are completion choices to be shown, print a delimiter. + # Re-printing the command-line will automatically be done + # by the shell when it prints the completion choices. + printf -- "--" + else + # When there are no completion choices at all, we need + # to re-print the command-line since the shell will + # not be doing it itself. + __%[1]s_reprint_commandLine + fi + elif [ $COMP_TYPE -eq 37 ] || [ $COMP_TYPE -eq 42 ]; then + # For completion type: menu-complete/menu-complete-backward and insert-completions + # the completions are immediately inserted into the command-line, so we first + # print the activeHelp message and reprint the command-line since the shell won't. + printf "\n" + printf "%%s\n" "${activeHelp[@]}" + + __%[1]s_reprint_commandLine + fi + fi +} + +__%[1]s_reprint_commandLine() { + # The prompt format is only available from bash 4.4. + # We test if it is available before using it. + if (x=${PS1@P}) 2> /dev/null; then + printf "%%s" "${PS1@P}${COMP_LINE[@]}" + else + # Can't print the prompt. Just print the + # text the user had typed, it is workable enough. + printf "%%s" "${COMP_LINE[@]}" fi } @@ -201,6 +252,8 @@ __%[1]s_extract_activeHelp() { local endIndex=${#activeHelpMarker} while IFS='' read -r comp; do + [[ -z $comp ]] && continue + if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then comp=${comp:endIndex} __%[1]s_debug "ActiveHelp found: $comp" @@ -223,16 +276,21 @@ __%[1]s_handle_completion_types() { # If the user requested inserting one completion at a time, or all # completions at once on the command-line we must remove the descriptions. # https://github.com/spf13/cobra/issues/1508 - local tab=$'\t' comp - while IFS='' read -r comp; do - [[ -z $comp ]] && continue - # Strip any description - comp=${comp%%%%$tab*} - # Only consider the completions that match - if [[ $comp == "$cur"* ]]; then - COMPREPLY+=("$comp") - fi - done < <(printf "%%s\n" "${completions[@]}") + + # If there are no completions, we don't need to do anything + (( ${#completions[@]} == 0 )) && return 0 + + local tab=$'\t' + + # Strip any description and escape the completion to handled special characters + IFS=$'\n' read -ra completions -d '' < <(printf "%%q\n" "${completions[@]%%%%$tab*}") + + # Only consider the completions that match + IFS=$'\n' read -ra COMPREPLY -d '' < <(IFS=$'\n'; compgen -W "${completions[*]}" -- "${cur}") + + # compgen looses the escaping so we need to escape all completions again since they will + # all be inserted on the command-line. + IFS=$'\n' read -ra COMPREPLY -d '' < <(printf "%%q\n" "${COMPREPLY[@]}") ;; *) @@ -243,11 +301,25 @@ __%[1]s_handle_completion_types() { } __%[1]s_handle_standard_completion_case() { - local tab=$'\t' comp + local tab=$'\t' + + # If there are no completions, we don't need to do anything + (( ${#completions[@]} == 0 )) && return 0 # Short circuit to optimize if we don't have descriptions if [[ "${completions[*]}" != *$tab* ]]; then - IFS=$'\n' read -ra COMPREPLY -d '' < <(compgen -W "${completions[*]}" -- "$cur") + # First, escape the completions to handle special characters + IFS=$'\n' read -ra completions -d '' < <(printf "%%q\n" "${completions[@]}") + # Only consider the completions that match what the user typed + IFS=$'\n' read -ra COMPREPLY -d '' < <(IFS=$'\n'; compgen -W "${completions[*]}" -- "${cur}") + + # compgen looses the escaping so, if there is only a single completion, we need to + # escape it again because it will be inserted on the command-line. If there are multiple + # completions, we don't want to escape them because they will be printed in a list + # and we don't want to show escape characters in that list. + if (( ${#COMPREPLY[@]} == 1 )); then + COMPREPLY[0]=$(printf "%%q" "${COMPREPLY[0]}") + fi return 0 fi @@ -256,23 +328,39 @@ __%[1]s_handle_standard_completion_case() { # Look for the longest completion so that we can format things nicely while IFS='' read -r compline; do [[ -z $compline ]] && continue - # Strip any description before checking the length - comp=${compline%%%%$tab*} + + # Before checking if the completion matches what the user typed, + # we need to strip any description and escape the completion to handle special + # characters because those escape characters are part of what the user typed. + # Don't call "printf" in a sub-shell because it will be much slower + # since we are in a loop. + printf -v comp "%%q" "${compline%%%%$tab*}" &>/dev/null || comp=$(printf "%%q" "${compline%%%%$tab*}") + # Only consider the completions that match [[ $comp == "$cur"* ]] || continue + + # The completions matches. Add it to the list of full completions including + # its description. We don't escape the completion because it may get printed + # in a list if there are more than one and we don't want show escape characters + # in that list. COMPREPLY+=("$compline") + + # Strip any description before checking the length, and again, don't escape + # the completion because this length is only used when printing the completions + # in a list and we don't want show escape characters in that list. + comp=${compline%%%%$tab*} if ((${#comp}>longest)); then longest=${#comp} fi done < <(printf "%%s\n" "${completions[@]}") - # If there is a single completion left, remove the description text + # If there is a single completion left, remove the description text and escape any special characters if ((${#COMPREPLY[*]} == 1)); then __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}" - comp="${COMPREPLY[0]%%%%$tab*}" - __%[1]s_debug "Removed description from single completion, which is now: ${comp}" - COMPREPLY[0]=$comp - else # Format the descriptions + COMPREPLY[0]=$(printf "%%q" "${COMPREPLY[0]%%%%$tab*}") + __%[1]s_debug "Removed description from single completion, which is now: ${COMPREPLY[0]}" + else + # Format the descriptions __%[1]s_format_comp_descriptions $longest fi } diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index e0b0947b04..d9cd2414e2 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -176,12 +176,16 @@ func rpad(s string, padding int) string { return fmt.Sprintf(formattedString, s) } -// tmpl executes the given template text on data, writing the result to w. -func tmpl(w io.Writer, text string, data interface{}) error { - t := template.New("top") - t.Funcs(templateFuncs) - template.Must(t.Parse(text)) - return t.Execute(w, data) +func tmpl(text string) *tmplFunc { + return &tmplFunc{ + tmpl: text, + fn: func(w io.Writer, data interface{}) error { + t := template.New("top") + t.Funcs(templateFuncs) + template.Must(t.Parse(text)) + return t.Execute(w, data) + }, + } } // ld compares two strings and returns the levenshtein distance between them. diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 54748fc67e..dbb2c298ba 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -33,6 +33,9 @@ import ( const ( FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" CommandDisplayNameAnnotation = "cobra_annotation_command_display_name" + + helpFlagName = "help" + helpCommandName = "help" ) // FParseErrWhitelist configures Flag parse errors to be ignored @@ -80,11 +83,11 @@ type Command struct { Example string // ValidArgs is list of all valid non-flag arguments that are accepted in shell completions - ValidArgs []string + ValidArgs []Completion // ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion. // It is a dynamic version of using ValidArgs. // Only one of ValidArgs and ValidArgsFunction can be used for a command. - ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + ValidArgsFunction CompletionFunc // Expected arguments Args PositionalArgs @@ -168,12 +171,12 @@ type Command struct { // usageFunc is usage func defined by user. usageFunc func(*Command) error // usageTemplate is usage template defined by user. - usageTemplate string + usageTemplate *tmplFunc // flagErrorFunc is func defined by user and it's called when the parsing of // flags returns an error. flagErrorFunc func(*Command, error) error // helpTemplate is help template defined by user. - helpTemplate string + helpTemplate *tmplFunc // helpFunc is help func defined by user. helpFunc func(*Command, []string) // helpCommand is command with usage 'help'. If it's not defined by user, @@ -186,7 +189,7 @@ type Command struct { completionCommandGroupID string // versionTemplate is the version template defined by user. - versionTemplate string + versionTemplate *tmplFunc // errPrefix is the error message prefix defined by user. errPrefix string @@ -281,6 +284,7 @@ func (c *Command) SetArgs(a []string) { // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. +// // Deprecated: Use SetOut and/or SetErr instead func (c *Command) SetOutput(output io.Writer) { c.outWriter = output @@ -312,7 +316,11 @@ func (c *Command) SetUsageFunc(f func(*Command) error) { // SetUsageTemplate sets usage template. Can be defined by Application. func (c *Command) SetUsageTemplate(s string) { - c.usageTemplate = s + if s == "" { + c.usageTemplate = nil + return + } + c.usageTemplate = tmpl(s) } // SetFlagErrorFunc sets a function to generate an error when flag parsing @@ -348,12 +356,20 @@ func (c *Command) SetCompletionCommandGroupID(groupID string) { // SetHelpTemplate sets help template to be used. Application can use it to set custom template. func (c *Command) SetHelpTemplate(s string) { - c.helpTemplate = s + if s == "" { + c.helpTemplate = nil + return + } + c.helpTemplate = tmpl(s) } // SetVersionTemplate sets version template to be used. Application can use it to set custom template. func (c *Command) SetVersionTemplate(s string) { - c.versionTemplate = s + if s == "" { + c.versionTemplate = nil + return + } + c.versionTemplate = tmpl(s) } // SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. @@ -434,7 +450,8 @@ func (c *Command) UsageFunc() (f func(*Command) error) { } return func(c *Command) error { c.mergePersistentFlags() - err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c) + fn := c.getUsageTemplateFunc() + err := fn(c.OutOrStderr(), c) if err != nil { c.PrintErrln(err) } @@ -442,6 +459,19 @@ func (c *Command) UsageFunc() (f func(*Command) error) { } } +// getUsageTemplateFunc returns the usage template function for the command +// going up the command tree if necessary. +func (c *Command) getUsageTemplateFunc() func(w io.Writer, data interface{}) error { + if c.usageTemplate != nil { + return c.usageTemplate.fn + } + + if c.HasParent() { + return c.parent.getUsageTemplateFunc() + } + return defaultUsageFunc +} + // Usage puts out the usage for the command. // Used when a user provides invalid input. // Can be defined by user by overriding UsageFunc. @@ -460,15 +490,30 @@ func (c *Command) HelpFunc() func(*Command, []string) { } return func(c *Command, a []string) { c.mergePersistentFlags() + fn := c.getHelpTemplateFunc() // The help should be sent to stdout // See https://github.com/spf13/cobra/issues/1002 - err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) + err := fn(c.OutOrStdout(), c) if err != nil { c.PrintErrln(err) } } } +// getHelpTemplateFunc returns the help template function for the command +// going up the command tree if necessary. +func (c *Command) getHelpTemplateFunc() func(w io.Writer, data interface{}) error { + if c.helpTemplate != nil { + return c.helpTemplate.fn + } + + if c.HasParent() { + return c.parent.getHelpTemplateFunc() + } + + return defaultHelpFunc +} + // Help puts out the help for the command. // Used when a user calls help [command]. // Can be defined by user by overriding HelpFunc. @@ -543,71 +588,55 @@ func (c *Command) NamePadding() int { } // UsageTemplate returns usage template for the command. +// This function is kept for backwards-compatibility reasons. func (c *Command) UsageTemplate() string { - if c.usageTemplate != "" { - return c.usageTemplate + if c.usageTemplate != nil { + return c.usageTemplate.tmpl } if c.HasParent() { return c.parent.UsageTemplate() } - return `Usage:{{if .Runnable}} - {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} - {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} - -Aliases: - {{.NameAndAliases}}{{end}}{{if .HasExample}} - -Examples: -{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}} - -Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}} - -{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}} - -Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} - -Flags: -{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} - -Global Flags: -{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} - -Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} - {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} - -Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} -` + return defaultUsageTemplate } // HelpTemplate return help template for the command. +// This function is kept for backwards-compatibility reasons. func (c *Command) HelpTemplate() string { - if c.helpTemplate != "" { - return c.helpTemplate + if c.helpTemplate != nil { + return c.helpTemplate.tmpl } if c.HasParent() { return c.parent.HelpTemplate() } - return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} - -{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` + return defaultHelpTemplate } // VersionTemplate return version template for the command. +// This function is kept for backwards-compatibility reasons. func (c *Command) VersionTemplate() string { - if c.versionTemplate != "" { - return c.versionTemplate + if c.versionTemplate != nil { + return c.versionTemplate.tmpl } if c.HasParent() { return c.parent.VersionTemplate() } - return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}} -` + return defaultVersionTemplate +} + +// getVersionTemplateFunc returns the version template function for the command +// going up the command tree if necessary. +func (c *Command) getVersionTemplateFunc() func(w io.Writer, data interface{}) error { + if c.versionTemplate != nil { + return c.versionTemplate.fn + } + + if c.HasParent() { + return c.parent.getVersionTemplateFunc() + } + return defaultVersionFunc } // ErrPrefix return error message prefix for the command @@ -894,7 +923,7 @@ func (c *Command) execute(a []string) (err error) { // If help is called, regardless of other flags, return we want help. // Also say we need help if the command isn't runnable. - helpVal, err := c.Flags().GetBool("help") + helpVal, err := c.Flags().GetBool(helpFlagName) if err != nil { // should be impossible to get here as we always declare a help // flag in InitDefaultHelpFlag() @@ -914,7 +943,8 @@ func (c *Command) execute(a []string) (err error) { return err } if versionVal { - err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c) + fn := c.getVersionTemplateFunc() + err := fn(c.OutOrStdout(), c) if err != nil { c.Println(err) } @@ -1068,12 +1098,6 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // initialize help at the last point to allow for user overriding c.InitDefaultHelpCmd() - // initialize completion at the last point to allow for user overriding - c.InitDefaultCompletionCmd() - - // Now that all commands have been created, let's make sure all groups - // are properly created also - c.checkCommandGroups() args := c.args @@ -1082,9 +1106,16 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { args = os.Args[1:] } - // initialize the hidden command to be used for shell completion + // initialize the __complete command to be used for shell completion c.initCompleteCmd(args) + // initialize the default completion command + c.InitDefaultCompletionCmd(args...) + + // Now that all commands have been created, let's make sure all groups + // are properly created also + c.checkCommandGroups() + var flags []string if c.TraverseChildren { cmd, flags, err = c.Traverse(args) @@ -1187,16 +1218,16 @@ func (c *Command) checkCommandGroups() { // If c already has help flag, it will do nothing. func (c *Command) InitDefaultHelpFlag() { c.mergePersistentFlags() - if c.Flags().Lookup("help") == nil { + if c.Flags().Lookup(helpFlagName) == nil { usage := "help for " - name := c.displayName() + name := c.DisplayName() if name == "" { usage += "this command" } else { usage += name } - c.Flags().BoolP("help", "h", false, usage) - _ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"}) + c.Flags().BoolP(helpFlagName, "h", false, usage) + _ = c.Flags().SetAnnotation(helpFlagName, FlagSetByCobraAnnotation, []string{"true"}) } } @@ -1215,7 +1246,7 @@ func (c *Command) InitDefaultVersionFlag() { if c.Name() == "" { usage += "this command" } else { - usage += c.Name() + usage += c.DisplayName() } if c.Flags().ShorthandLookup("v") == nil { c.Flags().BoolP("version", "v", false, usage) @@ -1239,9 +1270,9 @@ func (c *Command) InitDefaultHelpCmd() { Use: "help [command]", Short: "Help about any command", Long: `Help provides help for any command in the application. -Simply type ` + c.displayName() + ` help [path to command] for full details.`, - ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) { - var completions []string +Simply type ` + c.DisplayName() + ` help [path to command] for full details.`, + ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) { + var completions []Completion cmd, _, e := c.Root().Find(args) if e != nil { return nil, ShellCompDirectiveNoFileComp @@ -1253,7 +1284,7 @@ Simply type ` + c.displayName() + ` help [path to command] for full details.`, for _, subCmd := range cmd.Commands() { if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand { if strings.HasPrefix(subCmd.Name(), toComplete) { - completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short)) + completions = append(completions, CompletionWithDesc(subCmd.Name(), subCmd.Short)) } } } @@ -1430,10 +1461,12 @@ func (c *Command) CommandPath() string { if c.HasParent() { return c.Parent().CommandPath() + " " + c.Name() } - return c.displayName() + return c.DisplayName() } -func (c *Command) displayName() string { +// DisplayName returns the name to display in help text. Returns command Name() +// If CommandDisplayNameAnnoation is not set +func (c *Command) DisplayName() string { if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok { return displayName } @@ -1443,7 +1476,7 @@ func (c *Command) displayName() string { // UseLine puts out the full usage for a given command (including parents). func (c *Command) UseLine() string { var useline string - use := strings.Replace(c.Use, c.Name(), c.displayName(), 1) + use := strings.Replace(c.Use, c.Name(), c.DisplayName(), 1) if c.HasParent() { useline = c.parent.CommandPath() + " " + use } else { @@ -1649,7 +1682,7 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f // to this command (local and persistent declared here and by all parents). func (c *Command) Flags() *flag.FlagSet { if c.flags == nil { - c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1664,7 +1697,7 @@ func (c *Command) Flags() *flag.FlagSet { func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { persistentFlags := c.PersistentFlags() - out := flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + out := flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) c.LocalFlags().VisitAll(func(f *flag.Flag) { if persistentFlags.Lookup(f.Name) == nil { out.AddFlag(f) @@ -1679,7 +1712,7 @@ func (c *Command) LocalFlags() *flag.FlagSet { c.mergePersistentFlags() if c.lflags == nil { - c.lflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.lflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1707,7 +1740,7 @@ func (c *Command) InheritedFlags() *flag.FlagSet { c.mergePersistentFlags() if c.iflags == nil { - c.iflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.iflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1736,7 +1769,7 @@ func (c *Command) NonInheritedFlags() *flag.FlagSet { // PersistentFlags returns the persistent FlagSet specifically set in the current command. func (c *Command) PersistentFlags() *flag.FlagSet { if c.pflags == nil { - c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1749,9 +1782,9 @@ func (c *Command) PersistentFlags() *flag.FlagSet { func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() - c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) c.flags.SetOutput(c.flagErrorBuf) - c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) c.pflags.SetOutput(c.flagErrorBuf) c.lflags = nil @@ -1868,7 +1901,7 @@ func (c *Command) mergePersistentFlags() { // If c.parentsPflags == nil, it makes new. func (c *Command) updateParentsPflags() { if c.parentsPflags == nil { - c.parentsPflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.parentsPflags = flag.NewFlagSet(c.DisplayName(), flag.ContinueOnError) c.parentsPflags.SetOutput(c.flagErrorBuf) c.parentsPflags.SortFlags = false } @@ -1894,3 +1927,141 @@ func commandNameMatches(s string, t string) bool { return s == t } + +// tmplFunc holds a template and a function that will execute said template. +type tmplFunc struct { + tmpl string + fn func(io.Writer, interface{}) error +} + +var defaultUsageTemplate = `Usage:{{if .Runnable}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} + +Aliases: + {{.NameAndAliases}}{{end}}{{if .HasExample}} + +Examples: +{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}} + +Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}} + +{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}} + +Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} + +Flags: +{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} + +Global Flags: +{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} + +Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} + +Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} +` + +// defaultUsageFunc is equivalent to executing defaultUsageTemplate. The two should be changed in sync. +func defaultUsageFunc(w io.Writer, in interface{}) error { + c := in.(*Command) + fmt.Fprint(w, "Usage:") + if c.Runnable() { + fmt.Fprintf(w, "\n %s", c.UseLine()) + } + if c.HasAvailableSubCommands() { + fmt.Fprintf(w, "\n %s [command]", c.CommandPath()) + } + if len(c.Aliases) > 0 { + fmt.Fprintf(w, "\n\nAliases:\n") + fmt.Fprintf(w, " %s", c.NameAndAliases()) + } + if c.HasExample() { + fmt.Fprintf(w, "\n\nExamples:\n") + fmt.Fprintf(w, "%s", c.Example) + } + if c.HasAvailableSubCommands() { + cmds := c.Commands() + if len(c.Groups()) == 0 { + fmt.Fprintf(w, "\n\nAvailable Commands:") + for _, subcmd := range cmds { + if subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName { + fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short) + } + } + } else { + for _, group := range c.Groups() { + fmt.Fprintf(w, "\n\n%s", group.Title) + for _, subcmd := range cmds { + if subcmd.GroupID == group.ID && (subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName) { + fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short) + } + } + } + if !c.AllChildCommandsHaveGroup() { + fmt.Fprintf(w, "\n\nAdditional Commands:") + for _, subcmd := range cmds { + if subcmd.GroupID == "" && (subcmd.IsAvailableCommand() || subcmd.Name() == helpCommandName) { + fmt.Fprintf(w, "\n %s %s", rpad(subcmd.Name(), subcmd.NamePadding()), subcmd.Short) + } + } + } + } + } + if c.HasAvailableLocalFlags() { + fmt.Fprintf(w, "\n\nFlags:\n") + fmt.Fprint(w, trimRightSpace(c.LocalFlags().FlagUsages())) + } + if c.HasAvailableInheritedFlags() { + fmt.Fprintf(w, "\n\nGlobal Flags:\n") + fmt.Fprint(w, trimRightSpace(c.InheritedFlags().FlagUsages())) + } + if c.HasHelpSubCommands() { + fmt.Fprintf(w, "\n\nAdditional help topcis:") + for _, subcmd := range c.Commands() { + if subcmd.IsAdditionalHelpTopicCommand() { + fmt.Fprintf(w, "\n %s %s", rpad(subcmd.CommandPath(), subcmd.CommandPathPadding()), subcmd.Short) + } + } + } + if c.HasAvailableSubCommands() { + fmt.Fprintf(w, "\n\nUse \"%s [command] --help\" for more information about a command.", c.CommandPath()) + } + fmt.Fprintln(w) + return nil +} + +var defaultHelpTemplate = `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} + +{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` + +// defaultHelpFunc is equivalent to executing defaultHelpTemplate. The two should be changed in sync. +func defaultHelpFunc(w io.Writer, in interface{}) error { + c := in.(*Command) + usage := c.Long + if usage == "" { + usage = c.Short + } + usage = trimRightSpace(usage) + if usage != "" { + fmt.Fprintln(w, usage) + fmt.Fprintln(w) + } + if c.Runnable() || c.HasSubCommands() { + fmt.Fprint(w, c.UsageString()) + } + return nil +} + +var defaultVersionTemplate = `{{with .DisplayName}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}} +` + +// defaultVersionFunc is equivalent to executing defaultVersionTemplate. The two should be changed in sync. +func defaultVersionFunc(w io.Writer, in interface{}) error { + c := in.(*Command) + _, err := fmt.Fprintf(w, "%s version %s\n", c.DisplayName(), c.Version) + return err +} diff --git a/vendor/github.com/spf13/cobra/completions.go b/vendor/github.com/spf13/cobra/completions.go index c0c08b0572..a1752f7631 100644 --- a/vendor/github.com/spf13/cobra/completions.go +++ b/vendor/github.com/spf13/cobra/completions.go @@ -35,7 +35,7 @@ const ( ) // Global map of flag completion functions. Make sure to use flagCompletionMutex before you try to read and write from it. -var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){} +var flagCompletionFunctions = map[*pflag.Flag]CompletionFunc{} // lock for reading and writing from flagCompletionFunctions var flagCompletionMutex = &sync.RWMutex{} @@ -117,22 +117,50 @@ type CompletionOptions struct { HiddenDefaultCmd bool } +// Completion is a string that can be used for completions +// +// two formats are supported: +// - the completion choice +// - the completion choice with a textual description (separated by a TAB). +// +// [CompletionWithDesc] can be used to create a completion string with a textual description. +// +// Note: Go type alias is used to provide a more descriptive name in the documentation, but any string can be used. +type Completion = string + +// CompletionFunc is a function that provides completion results. +type CompletionFunc = func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) + +// CompletionWithDesc returns a [Completion] with a description by using the TAB delimited format. +func CompletionWithDesc(choice string, description string) Completion { + return choice + "\t" + description +} + // NoFileCompletions can be used to disable file completion for commands that should // not trigger file completions. -func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { +// +// This method satisfies [CompletionFunc]. +// It can be used with [Command.RegisterFlagCompletionFunc] and for [Command.ValidArgsFunction]. +func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) { return nil, ShellCompDirectiveNoFileComp } // FixedCompletions can be used to create a completion function which always // returns the same results. -func FixedCompletions(choices []string, directive ShellCompDirective) func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { - return func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { +// +// This method returns a function that satisfies [CompletionFunc] +// It can be used with [Command.RegisterFlagCompletionFunc] and for [Command.ValidArgsFunction]. +func FixedCompletions(choices []Completion, directive ShellCompDirective) CompletionFunc { + return func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) { return choices, directive } } // RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag. -func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)) error { +// +// You can use pre-defined completion functions such as [FixedCompletions] or [NoFileCompletions], +// or you can define your own. +func (c *Command) RegisterFlagCompletionFunc(flagName string, f CompletionFunc) error { flag := c.Flag(flagName) if flag == nil { return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName) @@ -148,7 +176,7 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman } // GetFlagCompletionFunc returns the completion function for the given flag of the command, if available. -func (c *Command) GetFlagCompletionFunc(flagName string) (func(*Command, []string, string) ([]string, ShellCompDirective), bool) { +func (c *Command) GetFlagCompletionFunc(flagName string) (CompletionFunc, bool) { flag := c.Flag(flagName) if flag == nil { return nil, false @@ -270,7 +298,15 @@ func (c *Command) initCompleteCmd(args []string) { } } -func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) { +// SliceValue is a reduced version of [pflag.SliceValue]. It is used to detect +// flags that accept multiple values and therefore can provide completion +// multiple times. +type SliceValue interface { + // GetSlice returns the flag value list as an array of strings. + GetSlice() []string +} + +func (c *Command) getCompletions(args []string) (*Command, []Completion, ShellCompDirective, error) { // The last argument, which is not completely typed by the user, // should not be part of the list of arguments toComplete := args[len(args)-1] @@ -298,7 +334,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi } if err != nil { // Unable to find the real command. E.g., someInvalidCmd - return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs) + return c, []Completion{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs) } finalCmd.ctx = c.ctx @@ -328,7 +364,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi // Parse the flags early so we can check if required flags are set if err = finalCmd.ParseFlags(finalArgs); err != nil { - return finalCmd, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error()) + return finalCmd, []Completion{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error()) } realArgCount := finalCmd.Flags().NArg() @@ -340,14 +376,14 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi if flagErr != nil { // If error type is flagCompError and we don't want flagCompletion we should ignore the error if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) { - return finalCmd, []string{}, ShellCompDirectiveDefault, flagErr + return finalCmd, []Completion{}, ShellCompDirectiveDefault, flagErr } } // Look for the --help or --version flags. If they are present, // there should be no further completions. if helpOrVersionFlagPresent(finalCmd) { - return finalCmd, []string{}, ShellCompDirectiveNoFileComp, nil + return finalCmd, []Completion{}, ShellCompDirectiveNoFileComp, nil } // We only remove the flags from the arguments if DisableFlagParsing is not set. @@ -376,11 +412,11 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi return finalCmd, subDir, ShellCompDirectiveFilterDirs, nil } // Directory completion - return finalCmd, []string{}, ShellCompDirectiveFilterDirs, nil + return finalCmd, []Completion{}, ShellCompDirectiveFilterDirs, nil } } - var completions []string + var completions []Completion var directive ShellCompDirective // Enforce flag groups before doing flag completions @@ -399,10 +435,14 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi // If we have not found any required flags, only then can we show regular flags if len(completions) == 0 { doCompleteFlags := func(flag *pflag.Flag) { - if !flag.Changed || + _, acceptsMultiple := flag.Value.(SliceValue) + acceptsMultiple = acceptsMultiple || strings.Contains(flag.Value.Type(), "Slice") || - strings.Contains(flag.Value.Type(), "Array") { - // If the flag is not already present, or if it can be specified multiple times (Array or Slice) + strings.Contains(flag.Value.Type(), "Array") || + strings.HasPrefix(flag.Value.Type(), "stringTo") + + if !flag.Changed || acceptsMultiple { + // If the flag is not already present, or if it can be specified multiple times (Array, Slice, or stringTo) // we suggest it as a completion completions = append(completions, getFlagNameCompletions(flag, toComplete)...) } @@ -462,7 +502,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi for _, subCmd := range finalCmd.Commands() { if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand { if strings.HasPrefix(subCmd.Name(), toComplete) { - completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short)) + completions = append(completions, CompletionWithDesc(subCmd.Name(), subCmd.Short)) } directive = ShellCompDirectiveNoFileComp } @@ -507,7 +547,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi } // Find the completion function for the flag or command - var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + var completionFn CompletionFunc if flag != nil && flagCompletion { flagCompletionMutex.RLock() completionFn = flagCompletionFunctions[flag] @@ -518,7 +558,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi if completionFn != nil { // Go custom completion defined for this flag or command. // Call the registered completion function to get the completions. - var comps []string + var comps []Completion comps, directive = completionFn(finalCmd, finalArgs, toComplete) completions = append(completions, comps...) } @@ -531,23 +571,23 @@ func helpOrVersionFlagPresent(cmd *Command) bool { len(versionFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && versionFlag.Changed { return true } - if helpFlag := cmd.Flags().Lookup("help"); helpFlag != nil && + if helpFlag := cmd.Flags().Lookup(helpFlagName); helpFlag != nil && len(helpFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && helpFlag.Changed { return true } return false } -func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string { +func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []Completion { if nonCompletableFlag(flag) { - return []string{} + return []Completion{} } - var completions []string + var completions []Completion flagName := "--" + flag.Name if strings.HasPrefix(flagName, toComplete) { // Flag without the = - completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage)) + completions = append(completions, CompletionWithDesc(flagName, flag.Usage)) // Why suggest both long forms: --flag and --flag= ? // This forces the user to *always* have to type either an = or a space after the flag name. @@ -559,20 +599,20 @@ func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string { // if len(flag.NoOptDefVal) == 0 { // // Flag requires a value, so it can be suffixed with = // flagName += "=" - // completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage)) + // completions = append(completions, CompletionWithDesc(flagName, flag.Usage)) // } } flagName = "-" + flag.Shorthand if len(flag.Shorthand) > 0 && strings.HasPrefix(flagName, toComplete) { - completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage)) + completions = append(completions, CompletionWithDesc(flagName, flag.Usage)) } return completions } -func completeRequireFlags(finalCmd *Command, toComplete string) []string { - var completions []string +func completeRequireFlags(finalCmd *Command, toComplete string) []Completion { + var completions []Completion doCompleteRequiredFlags := func(flag *pflag.Flag) { if _, present := flag.Annotations[BashCompOneRequiredFlag]; present { @@ -687,8 +727,8 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p // 1- the feature has been explicitly disabled by the program, // 2- c has no subcommands (to avoid creating one), // 3- c already has a 'completion' command provided by the program. -func (c *Command) InitDefaultCompletionCmd() { - if c.CompletionOptions.DisableDefaultCmd || !c.HasSubCommands() { +func (c *Command) InitDefaultCompletionCmd(args ...string) { + if c.CompletionOptions.DisableDefaultCmd { return } @@ -701,6 +741,16 @@ func (c *Command) InitDefaultCompletionCmd() { haveNoDescFlag := !c.CompletionOptions.DisableNoDescFlag && !c.CompletionOptions.DisableDescriptions + // Special case to know if there are sub-commands or not. + hasSubCommands := false + for _, cmd := range c.commands { + if cmd.Name() != ShellCompRequestCmd && cmd.Name() != helpCommandName { + // We found a real sub-command (not 'help' or '__complete') + hasSubCommands = true + break + } + } + completionCmd := &Command{ Use: compCmdName, Short: "Generate the autocompletion script for the specified shell", @@ -714,6 +764,22 @@ See each sub-command's help for details on how to use the generated script. } c.AddCommand(completionCmd) + if !hasSubCommands { + // If the 'completion' command will be the only sub-command, + // we only create it if it is actually being called. + // This avoids breaking programs that would suddenly find themselves with + // a subcommand, which would prevent them from accepting arguments. + // We also create the 'completion' command if the user is triggering + // shell completion for it (prog __complete completion '') + subCmd, cmdArgs, err := c.Find(args) + if err != nil || subCmd.Name() != compCmdName && + !(subCmd.Name() == ShellCompRequestCmd && len(cmdArgs) > 1 && cmdArgs[0] == compCmdName) { + // The completion command is not being called or being completed so we remove it. + c.RemoveCommand(completionCmd) + return + } + } + out := c.OutOrStdout() noDesc := c.CompletionOptions.DisableDescriptions shortDesc := "Generate the autocompletion script for %s" diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go index a830b7bcad..746dcb92e3 100644 --- a/vendor/github.com/spf13/cobra/powershell_completions.go +++ b/vendor/github.com/spf13/cobra/powershell_completions.go @@ -162,7 +162,10 @@ filter __%[1]s_escapeStringWithSpecialChars { if (-Not $Description) { $Description = " " } - @{Name="$Name";Description="$Description"} + New-Object -TypeName PSCustomObject -Property @{ + Name = "$Name" + Description = "$Description" + } } @@ -240,7 +243,12 @@ filter __%[1]s_escapeStringWithSpecialChars { __%[1]s_debug "Only one completion left" # insert space after value - [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + $CompletionText = $($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space + if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){ + [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + } else { + $CompletionText + } } else { # Add the proper number of spaces to align the descriptions @@ -255,7 +263,12 @@ filter __%[1]s_escapeStringWithSpecialChars { $Description = " ($($comp.Description))" } - [System.Management.Automation.CompletionResult]::new("$($comp.Name)$Description", "$($comp.Name)$Description", 'ParameterValue', "$($comp.Description)") + $CompletionText = "$($comp.Name)$Description" + if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){ + [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)$Description", 'ParameterValue', "$($comp.Description)") + } else { + $CompletionText + } } } @@ -264,7 +277,13 @@ filter __%[1]s_escapeStringWithSpecialChars { # insert space after value # MenuComplete will automatically show the ToolTip of # the highlighted value at the bottom of the suggestions. - [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + + $CompletionText = $($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space + if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){ + [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + } else { + $CompletionText + } } # TabCompleteNext and in case we get something unknown @@ -272,7 +291,13 @@ filter __%[1]s_escapeStringWithSpecialChars { # Like MenuComplete but we don't want to add a space here because # the user need to press space anyway to get the completion. # Description will not be shown because that's not possible with TabCompleteNext - [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + + $CompletionText = $($comp.Name | __%[1]s_escapeStringWithSpecialChars) + if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage"){ + [System.Management.Automation.CompletionResult]::new($CompletionText, "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + } else { + $CompletionText + } } } diff --git a/vendor/github.com/spf13/viper/.golangci.yaml b/vendor/github.com/spf13/viper/.golangci.yaml index 1faeae42c7..474f41633c 100644 --- a/vendor/github.com/spf13/viper/.golangci.yaml +++ b/vendor/github.com/spf13/viper/.golangci.yaml @@ -17,8 +17,6 @@ linters-settings: disabled-checks: - importShadow - unnamedResult - golint: - min-confidence: 0 goimports: local-prefixes: github.com/spf13/viper @@ -30,7 +28,6 @@ linters: - dupl - durationcheck - exhaustive - - exportloopref - gci - gocritic - godot diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md index 3fc7d84f16..769a5d900d 100644 --- a/vendor/github.com/spf13/viper/README.md +++ b/vendor/github.com/spf13/viper/README.md @@ -3,7 +3,8 @@ > > **Thank you!** -![Viper](.github/logo.png?raw=true) +![viper logo](https://github.com/user-attachments/assets/acae9193-2974-41f3-808d-2d433f5ada5e) + [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration) [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go) @@ -11,7 +12,7 @@ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI) [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper) -![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.21-61CFDD.svg?style=flat-square) [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper) **Go configuration with fangs!** @@ -802,7 +803,7 @@ if err != nil { } ``` -Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. +Viper uses [github.com/go-viper/mapstructure](https://github.com/go-viper/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. ### Decoding custom formats @@ -836,13 +837,15 @@ func yamlStringSettings() string { ## Viper or Vipers? -Viper comes ready to use out of the box. There is no configuration or -initialization needed to begin using Viper. Since most applications will want -to use a single central repository for their configuration, the viper package -provides this. It is similar to a singleton. +Viper comes with a global instance (singleton) out of the box. + +Although it makes setting up configuration easy, +using it is generally discouraged as it makes testing harder and can lead to unexpected behavior. + +The best practice is to initialize a Viper instance and pass that around when necessary. -In all of the examples above, they demonstrate using viper in its singleton -style approach. +The global instance _MAY_ be deprecated in the future. +See [#1855](https://github.com/spf13/viper/issues/1855) for more details. ### Working with multiple vipers diff --git a/vendor/github.com/spf13/viper/UPDATES.md b/vendor/github.com/spf13/viper/UPDATES.md new file mode 100644 index 0000000000..ccf413ed7e --- /dev/null +++ b/vendor/github.com/spf13/viper/UPDATES.md @@ -0,0 +1,126 @@ +# Update Log + +**This document details any major updates required to use new features or improvements in Viper.** + +## v1.20.x + +### New file searching API + +Viper now includes a new file searching API that allows users to customize how Viper looks for config files. + +Viper accepts a custom [`Finder`](https://pkg.go.dev/github.com/spf13/viper#Finder) interface implementation: + +```go +// Finder looks for files and directories in an [afero.Fs] filesystem. +type Finder interface { + Find(fsys afero.Fs) ([]string, error) +} +``` + +It is supposed to return a list of paths to config files. + +The default implementation uses [github.com/sagikazarmark/locafero](https://github.com/sagikazarmark/locafero) under the hood. + +You can supply your own implementation using `WithFinder`: + +```go +v := viper.NewWithOptions( + viper.WithFinder(&MyFinder{}), +) +``` + +For more information, check out the [Finder examples](https://pkg.go.dev/github.com/spf13/viper#Finder) +and the [documentation](https://pkg.go.dev/github.com/sagikazarmark/locafero) for the locafero package. + +### New encoding API + +Viper now allows customizing the encoding layer by providing an API for encoding and decoding configuration data: + +```go +// Encoder encodes Viper's internal data structures into a byte representation. +// It's primarily used for encoding a map[string]any into a file format. +type Encoder interface { + Encode(v map[string]any) ([]byte, error) +} + +// Decoder decodes the contents of a byte slice into Viper's internal data structures. +// It's primarily used for decoding contents of a file into a map[string]any. +type Decoder interface { + Decode(b []byte, v map[string]any) error +} + +// Codec combines [Encoder] and [Decoder] interfaces. +type Codec interface { + Encoder + Decoder +} +``` + +By default, Viper includes the following codecs: + +- JSON +- TOML +- YAML +- Dotenv + +The rest of the codecs are moved to [github.com/go-viper/encoding](https://github.com/go-viper/encoding) + +Customizing the encoding layer is possible by providing a custom registry of codecs: + +- [Encoder](https://pkg.go.dev/github.com/spf13/viper#Encoder) -> [EncoderRegistry](https://pkg.go.dev/github.com/spf13/viper#EncoderRegistry) +- [Decoder](https://pkg.go.dev/github.com/spf13/viper#Decoder) -> [DecoderRegistry](https://pkg.go.dev/github.com/spf13/viper#DecoderRegistry) +- [Codec](https://pkg.go.dev/github.com/spf13/viper#Codec) -> [CodecRegistry](https://pkg.go.dev/github.com/spf13/viper#CodecRegistry) + +You can supply the registry of codecs to Viper using the appropriate `With*Registry` function: + +```go +codecRegistry := viper.NewCodecRegistry() + +codecRegistry.RegisterCodec("myformat", &MyCodec{}) + +v := viper.NewWithOptions( + viper.WithCodecRegistry(codecRegistry), +) +``` + +### BREAKING: HCL, Java properties, INI removed from core + +In order to reduce third-party dependencies, Viper dropped support for the following formats from the core: + +- HCL +- Java properties +- INI + +You can still use these formats though by importing them from [github.com/go-viper/encoding](https://github.com/go-viper/encoding): + +```go +import ( + "github.com/go-viper/encoding/hcl" + "github.com/go-viper/encoding/javaproperties" + "github.com/go-viper/encoding/ini" +) + +codecRegistry := viper.NewCodecRegistry() + +{ + codec := hcl.Codec{} + + codecRegistry.RegisterCodec("hcl", codec) + codecRegistry.RegisterCodec("tfvars", codec) + +} + +{ + codec := &javaproperties.Codec{} + + codecRegistry.RegisterCodec("properties", codec) + codecRegistry.RegisterCodec("props", codec) + codecRegistry.RegisterCodec("prop", codec) +} + +codecRegistry.RegisterCodec("ini", ini.Codec{}) + +v := viper.NewWithOptions( + viper.WithCodecRegistry(codecRegistry), +) +``` diff --git a/vendor/github.com/spf13/viper/encoding.go b/vendor/github.com/spf13/viper/encoding.go new file mode 100644 index 0000000000..a7da55860e --- /dev/null +++ b/vendor/github.com/spf13/viper/encoding.go @@ -0,0 +1,181 @@ +package viper + +import ( + "errors" + "strings" + "sync" + + "github.com/spf13/viper/internal/encoding/dotenv" + "github.com/spf13/viper/internal/encoding/json" + "github.com/spf13/viper/internal/encoding/toml" + "github.com/spf13/viper/internal/encoding/yaml" +) + +// Encoder encodes Viper's internal data structures into a byte representation. +// It's primarily used for encoding a map[string]any into a file format. +type Encoder interface { + Encode(v map[string]any) ([]byte, error) +} + +// Decoder decodes the contents of a byte slice into Viper's internal data structures. +// It's primarily used for decoding contents of a file into a map[string]any. +type Decoder interface { + Decode(b []byte, v map[string]any) error +} + +// Codec combines [Encoder] and [Decoder] interfaces. +type Codec interface { + Encoder + Decoder +} + +// TODO: consider adding specific errors for not found scenarios + +// EncoderRegistry returns an [Encoder] for a given format. +// +// Format is case-insensitive. +// +// [EncoderRegistry] returns an error if no [Encoder] is registered for the format. +type EncoderRegistry interface { + Encoder(format string) (Encoder, error) +} + +// DecoderRegistry returns an [Decoder] for a given format. +// +// Format is case-insensitive. +// +// [DecoderRegistry] returns an error if no [Decoder] is registered for the format. +type DecoderRegistry interface { + Decoder(format string) (Decoder, error) +} + +// [CodecRegistry] combines [EncoderRegistry] and [DecoderRegistry] interfaces. +type CodecRegistry interface { + EncoderRegistry + DecoderRegistry +} + +// WithEncoderRegistry sets a custom [EncoderRegistry]. +func WithEncoderRegistry(r EncoderRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.encoderRegistry = r + }) +} + +// WithDecoderRegistry sets a custom [DecoderRegistry]. +func WithDecoderRegistry(r DecoderRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.decoderRegistry = r + }) +} + +// WithCodecRegistry sets a custom [EncoderRegistry] and [DecoderRegistry]. +func WithCodecRegistry(r CodecRegistry) Option { + return optionFunc(func(v *Viper) { + if r == nil { + return + } + + v.encoderRegistry = r + v.decoderRegistry = r + }) +} + +// DefaultCodecRegistry is a simple implementation of [CodecRegistry] that allows registering custom [Codec]s. +type DefaultCodecRegistry struct { + codecs map[string]Codec + + mu sync.RWMutex + once sync.Once +} + +// NewCodecRegistry returns a new [CodecRegistry], ready to accept custom [Codec]s. +func NewCodecRegistry() *DefaultCodecRegistry { + r := &DefaultCodecRegistry{} + + r.init() + + return r +} + +func (r *DefaultCodecRegistry) init() { + r.once.Do(func() { + r.codecs = map[string]Codec{} + }) +} + +// RegisterCodec registers a custom [Codec]. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) RegisterCodec(format string, codec Codec) error { + r.init() + + r.mu.Lock() + defer r.mu.Unlock() + + r.codecs[strings.ToLower(format)] = codec + + return nil +} + +// Encoder implements the [EncoderRegistry] interface. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) Encoder(format string) (Encoder, error) { + encoder, ok := r.codec(format) + if !ok { + return nil, errors.New("encoder not found for this format") + } + + return encoder, nil +} + +// Decoder implements the [DecoderRegistry] interface. +// +// Format is case-insensitive. +func (r *DefaultCodecRegistry) Decoder(format string) (Decoder, error) { + decoder, ok := r.codec(format) + if !ok { + return nil, errors.New("decoder not found for this format") + } + + return decoder, nil +} + +func (r *DefaultCodecRegistry) codec(format string) (Codec, bool) { + r.mu.Lock() + defer r.mu.Unlock() + + format = strings.ToLower(format) + + if r.codecs != nil { + codec, ok := r.codecs[format] + if ok { + return codec, true + } + } + + switch format { + case "yaml", "yml": + return yaml.Codec{}, true + + case "json": + return json.Codec{}, true + + case "toml": + return toml.Codec{}, true + + case "dotenv", "env": + return &dotenv.Codec{}, true + } + + return nil, false +} diff --git a/vendor/github.com/spf13/viper/experimental.go b/vendor/github.com/spf13/viper/experimental.go new file mode 100644 index 0000000000..6e19e8a100 --- /dev/null +++ b/vendor/github.com/spf13/viper/experimental.go @@ -0,0 +1,8 @@ +package viper + +// ExperimentalBindStruct tells Viper to use the new bind struct feature. +func ExperimentalBindStruct() Option { + return optionFunc(func(v *Viper) { + v.experimentalBindStruct = true + }) +} diff --git a/vendor/github.com/spf13/viper/file.go b/vendor/github.com/spf13/viper/file.go index a54fe5a7a8..50a40581d0 100644 --- a/vendor/github.com/spf13/viper/file.go +++ b/vendor/github.com/spf13/viper/file.go @@ -1,5 +1,3 @@ -//go:build !finder - package viper import ( @@ -7,12 +5,62 @@ import ( "os" "path/filepath" + "github.com/sagikazarmark/locafero" "github.com/spf13/afero" ) +// ExperimentalFinder tells Viper to use the new Finder interface for finding configuration files. +func ExperimentalFinder() Option { + return optionFunc(func(v *Viper) { + v.experimentalFinder = true + }) +} + +// Search for a config file. +func (v *Viper) findConfigFile() (string, error) { + finder := v.finder + + if finder == nil && v.experimentalFinder { + var names []string + + if v.configType != "" { + names = locafero.NameWithOptionalExtensions(v.configName, SupportedExts...) + } else { + names = locafero.NameWithExtensions(v.configName, SupportedExts...) + } + + finder = locafero.Finder{ + Paths: v.configPaths, + Names: names, + Type: locafero.FileTypeFile, + } + } + + if finder != nil { + return v.findConfigFileWithFinder(finder) + } + + return v.findConfigFileOld() +} + +func (v *Viper) findConfigFileWithFinder(finder Finder) (string, error) { + results, err := finder.Find(v.fs) + if err != nil { + return "", err + } + + if len(results) == 0 { + return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} + } + + // We call clean on the final result to ensure that the path is in its canonical form. + // This is mostly for consistent path handling and to make sure tests pass. + return results[0], nil +} + // Search all configPaths for any config file. // Returns the first path that exists (and is a config file). -func (v *Viper) findConfigFile() (string, error) { +func (v *Viper) findConfigFileOld() (string, error) { v.logger.Info("searching for config in paths", "paths", v.configPaths) for _, cp := range v.configPaths { diff --git a/vendor/github.com/spf13/viper/file_finder.go b/vendor/github.com/spf13/viper/file_finder.go deleted file mode 100644 index d96a1bd223..0000000000 --- a/vendor/github.com/spf13/viper/file_finder.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build finder - -package viper - -import ( - "fmt" - - "github.com/sagikazarmark/locafero" -) - -// Search all configPaths for any config file. -// Returns the first path that exists (and is a config file). -func (v *Viper) findConfigFile() (string, error) { - var names []string - - if v.configType != "" { - names = locafero.NameWithOptionalExtensions(v.configName, SupportedExts...) - } else { - names = locafero.NameWithExtensions(v.configName, SupportedExts...) - } - - finder := locafero.Finder{ - Paths: v.configPaths, - Names: names, - Type: locafero.FileTypeFile, - } - - results, err := finder.Find(v.fs) - if err != nil { - return "", err - } - - if len(results) == 0 { - return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} - } - - return results[0], nil -} diff --git a/vendor/github.com/spf13/viper/finder.go b/vendor/github.com/spf13/viper/finder.go new file mode 100644 index 0000000000..9b203ea69a --- /dev/null +++ b/vendor/github.com/spf13/viper/finder.go @@ -0,0 +1,55 @@ +package viper + +import ( + "errors" + + "github.com/spf13/afero" +) + +// WithFinder sets a custom [Finder]. +func WithFinder(f Finder) Option { + return optionFunc(func(v *Viper) { + if f == nil { + return + } + + v.finder = f + }) +} + +// Finder looks for files and directories in an [afero.Fs] filesystem. +type Finder interface { + Find(fsys afero.Fs) ([]string, error) +} + +// Finders combines multiple finders into one. +func Finders(finders ...Finder) Finder { + return &combinedFinder{finders: finders} +} + +// combinedFinder is a Finder that combines multiple finders. +type combinedFinder struct { + finders []Finder +} + +// Find implements the [Finder] interface. +func (c *combinedFinder) Find(fsys afero.Fs) ([]string, error) { + var results []string + var errs []error + + for _, finder := range c.finders { + if finder == nil { + continue + } + + r, err := finder.Find(fsys) + if err != nil { + errs = append(errs, err) + continue + } + + results = append(results, r...) + } + + return results, errors.Join(errs...) +} diff --git a/vendor/github.com/spf13/viper/flake.lock b/vendor/github.com/spf13/viper/flake.lock index 3840614fa2..d76dfbddd1 100644 --- a/vendor/github.com/spf13/viper/flake.lock +++ b/vendor/github.com/spf13/viper/flake.lock @@ -1,22 +1,84 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, "devenv": { "inputs": { - "flake-compat": "flake-compat", + "cachix": "cachix", + "flake-compat": "flake-compat_2", + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1724763216, + "narHash": "sha256-oW2bwCrJpIzibCNK6zfIDaIQw765yMAuMSG2gyZfGv0=", + "owner": "cachix", + "repo": "devenv", + "rev": "1e4ef61205b9aa20fe04bf1c468b6a316281c4f1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] }, "locked": { - "lastModified": 1707817777, - "narHash": "sha256-vHyIs1OULQ3/91wD6xOiuayfI71JXALGA5KLnDKAcy0=", + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", "owner": "cachix", "repo": "devenv", - "rev": "5a30b9e5ac7c6167e61b1f4193d5130bb9f8defa", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", "type": "github" }, "original": { "owner": "cachix", + "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -37,16 +99,32 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1706830856, - "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=", + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", "type": "github" }, "original": { @@ -60,11 +138,29 @@ "systems": "systems" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -82,11 +178,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", "type": "github" }, "original": { @@ -95,53 +191,90 @@ "type": "github" } }, - "lowdown-src": { - "flake": false, + "nix": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", "type": "github" } }, - "nix": { + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { "inputs": { - "lowdown-src": "lowdown-src", + "flake-compat": [ + "devenv", + "flake-compat" + ], "nixpkgs": [ "devenv", "nixpkgs" ], - "nixpkgs-regression": "nixpkgs-regression" + "nixpkgs-regression": "nixpkgs-regression_2" }, "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", "owner": "domenkozar", "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "relaxed-flakes", + "ref": "devenv-2.21", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", "type": "github" }, "original": { @@ -153,23 +286,33 @@ }, "nixpkgs-lib": { "locked": { - "dir": "lib", - "lastModified": 1706550542, - "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=", + "lastModified": 1722555339, + "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "dir": "lib", "owner": "NixOS", - "ref": "nixos-unstable", "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" } }, - "nixpkgs-regression": { + "nixpkgs-regression_2": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -187,27 +330,43 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "lastModified": 1710695816, + "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "614b4613980a522ba49f0d194531beddbb7220d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1707939175, - "narHash": "sha256-D1xan0lgxbmXDyzVqXTiSYHLmAMrMRdD+alKzEO/p3w=", + "lastModified": 1713361204, + "narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1724748588, + "narHash": "sha256-NlpGA4+AIf1dKNq76ps90rxowlFXUsV9x7vK/mN37JM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f7e8132daca31b1e3859ac0fb49741754375ac3d", + "rev": "a6292e34000dc93d43bccf78338770c1c5ec8a99", "type": "github" }, "original": { @@ -217,13 +376,38 @@ "type": "github" } }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "devenv", "flake-compat" ], - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "gitignore": "gitignore", "nixpkgs": [ "devenv", @@ -232,11 +416,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1704725188, - "narHash": "sha256-qq8NbkhRZF1vVYQFt1s8Mbgo8knj+83+QlL5LBnYGpI=", + "lastModified": 1713775815, + "narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "ea96f0c05924341c551a797aaba8126334c505d2", + "rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4", "type": "github" }, "original": { @@ -249,7 +433,7 @@ "inputs": { "devenv": "devenv", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" } }, "systems": { @@ -266,6 +450,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/vendor/github.com/spf13/viper/flake.nix b/vendor/github.com/spf13/viper/flake.nix index 0230668cff..52ad7d5814 100644 --- a/vendor/github.com/spf13/viper/flake.nix +++ b/vendor/github.com/spf13/viper/flake.nix @@ -20,7 +20,7 @@ default = { languages = { go.enable = true; - go.package = pkgs.go_1_22; + go.package = pkgs.go_1_23; }; pre-commit.hooks = { diff --git a/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/vendor/github.com/spf13/viper/internal/encoding/decoder.go deleted file mode 100644 index 8a7b1dbc91..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/decoder.go +++ /dev/null @@ -1,61 +0,0 @@ -package encoding - -import ( - "sync" -) - -// Decoder decodes the contents of b into v. -// It's primarily used for decoding contents of a file into a map[string]any. -type Decoder interface { - Decode(b []byte, v map[string]any) error -} - -const ( - // ErrDecoderNotFound is returned when there is no decoder registered for a format. - ErrDecoderNotFound = encodingError("decoder not found for this format") - - // ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format. - ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format") -) - -// DecoderRegistry can choose an appropriate Decoder based on the provided format. -type DecoderRegistry struct { - decoders map[string]Decoder - - mu sync.RWMutex -} - -// NewDecoderRegistry returns a new, initialized DecoderRegistry. -func NewDecoderRegistry() *DecoderRegistry { - return &DecoderRegistry{ - decoders: make(map[string]Decoder), - } -} - -// RegisterDecoder registers a Decoder for a format. -// Registering a Decoder for an already existing format is not supported. -func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error { - e.mu.Lock() - defer e.mu.Unlock() - - if _, ok := e.decoders[format]; ok { - return ErrDecoderFormatAlreadyRegistered - } - - e.decoders[format] = enc - - return nil -} - -// Decode calls the underlying Decoder based on the format. -func (e *DecoderRegistry) Decode(format string, b []byte, v map[string]any) error { - e.mu.RLock() - decoder, ok := e.decoders[format] - e.mu.RUnlock() - - if !ok { - return ErrDecoderNotFound - } - - return decoder.Decode(b, v) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/vendor/github.com/spf13/viper/internal/encoding/encoder.go deleted file mode 100644 index 659585962c..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/encoder.go +++ /dev/null @@ -1,60 +0,0 @@ -package encoding - -import ( - "sync" -) - -// Encoder encodes the contents of v into a byte representation. -// It's primarily used for encoding a map[string]any into a file format. -type Encoder interface { - Encode(v map[string]any) ([]byte, error) -} - -const ( - // ErrEncoderNotFound is returned when there is no encoder registered for a format. - ErrEncoderNotFound = encodingError("encoder not found for this format") - - // ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format. - ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format") -) - -// EncoderRegistry can choose an appropriate Encoder based on the provided format. -type EncoderRegistry struct { - encoders map[string]Encoder - - mu sync.RWMutex -} - -// NewEncoderRegistry returns a new, initialized EncoderRegistry. -func NewEncoderRegistry() *EncoderRegistry { - return &EncoderRegistry{ - encoders: make(map[string]Encoder), - } -} - -// RegisterEncoder registers an Encoder for a format. -// Registering a Encoder for an already existing format is not supported. -func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error { - e.mu.Lock() - defer e.mu.Unlock() - - if _, ok := e.encoders[format]; ok { - return ErrEncoderFormatAlreadyRegistered - } - - e.encoders[format] = enc - - return nil -} - -func (e *EncoderRegistry) Encode(format string, v map[string]any) ([]byte, error) { - e.mu.RLock() - encoder, ok := e.encoders[format] - e.mu.RUnlock() - - if !ok { - return nil, ErrEncoderNotFound - } - - return encoder.Encode(v) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/error.go b/vendor/github.com/spf13/viper/internal/encoding/error.go deleted file mode 100644 index e4cde02d7b..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/error.go +++ /dev/null @@ -1,7 +0,0 @@ -package encoding - -type encodingError string - -func (e encodingError) Error() string { - return string(e) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go deleted file mode 100644 index d7fa8a1b7a..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go +++ /dev/null @@ -1,40 +0,0 @@ -package hcl - -import ( - "bytes" - "encoding/json" - - "github.com/hashicorp/hcl" - "github.com/hashicorp/hcl/hcl/printer" -) - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding. -// TODO: add printer config to the codec? -type Codec struct{} - -func (Codec) Encode(v map[string]any) ([]byte, error) { - b, err := json.Marshal(v) - if err != nil { - return nil, err - } - - // TODO: use printer.Format? Is the trailing newline an issue? - - ast, err := hcl.Parse(string(b)) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - - err = printer.Fprint(&buf, ast.Node) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (Codec) Decode(b []byte, v map[string]any) error { - return hcl.Unmarshal(b, &v) -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go b/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go deleted file mode 100644 index d91cf59d2b..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/ini/codec.go +++ /dev/null @@ -1,99 +0,0 @@ -package ini - -import ( - "bytes" - "sort" - "strings" - - "github.com/spf13/cast" - "gopkg.in/ini.v1" -) - -// LoadOptions contains all customized options used for load data source(s). -// This type is added here for convenience: this way consumers can import a single package called "ini". -type LoadOptions = ini.LoadOptions - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for INI encoding. -type Codec struct { - KeyDelimiter string - LoadOptions LoadOptions -} - -func (c Codec) Encode(v map[string]any) ([]byte, error) { - cfg := ini.Empty() - ini.PrettyFormat = false - - flattened := map[string]any{} - - flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) - - keys := make([]string, 0, len(flattened)) - - for key := range flattened { - keys = append(keys, key) - } - - sort.Strings(keys) - - for _, key := range keys { - sectionName, keyName := "", key - - lastSep := strings.LastIndex(key, ".") - if lastSep != -1 { - sectionName = key[:(lastSep)] - keyName = key[(lastSep + 1):] - } - - // TODO: is this a good idea? - if sectionName == "default" { - sectionName = "" - } - - cfg.Section(sectionName).Key(keyName).SetValue(cast.ToString(flattened[key])) - } - - var buf bytes.Buffer - - _, err := cfg.WriteTo(&buf) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (c Codec) Decode(b []byte, v map[string]any) error { - cfg := ini.Empty(c.LoadOptions) - - err := cfg.Append(b) - if err != nil { - return err - } - - sections := cfg.Sections() - - for i := 0; i < len(sections); i++ { - section := sections[i] - keys := section.Keys() - - for j := 0; j < len(keys); j++ { - key := keys[j] - value := cfg.Section(section.Name()).Key(key.Name()).String() - - deepestMap := deepSearch(v, strings.Split(section.Name(), c.keyDelimiter())) - - // set innermost value - deepestMap[key.Name()] = value - } - } - - return nil -} - -func (c Codec) keyDelimiter() string { - if c.KeyDelimiter == "" { - return "." - } - - return c.KeyDelimiter -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go b/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go deleted file mode 100644 index 490ab594ec..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/ini/map_utils.go +++ /dev/null @@ -1,74 +0,0 @@ -package ini - -import ( - "strings" - - "github.com/spf13/cast" -) - -// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED -// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE -// deepSearch scans deep maps, following the key indexes listed in the -// sequence "path". -// The last value is expected to be another map, and is returned. -// -// In case intermediate keys do not exist, or map to a non-map value, -// a new map is created and inserted, and the search continues from there: -// the initial map "m" may be modified! -func deepSearch(m map[string]any, path []string) map[string]any { - for _, k := range path { - m2, ok := m[k] - if !ok { - // intermediate key does not exist - // => create it and continue from there - m3 := make(map[string]any) - m[k] = m3 - m = m3 - continue - } - m3, ok := m2.(map[string]any) - if !ok { - // intermediate key is a value - // => replace with a new map - m3 = make(map[string]any) - m[k] = m3 - } - // continue search from here - m = m3 - } - return m -} - -// flattenAndMergeMap recursively flattens the given map into a new map -// Code is based on the function with the same name in the main package. -// TODO: move it to a common place. -func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { - if shadow != nil && prefix != "" && shadow[prefix] != nil { - // prefix is shadowed => nothing more to flatten - return shadow - } - if shadow == nil { - shadow = make(map[string]any) - } - - var m2 map[string]any - if prefix != "" { - prefix += delimiter - } - for k, val := range m { - fullKey := prefix + k - switch val := val.(type) { - case map[string]any: - m2 = val - case map[any]any: - m2 = cast.ToStringMap(val) - default: - // immediate value - shadow[strings.ToLower(fullKey)] = val - continue - } - // recursively merge to shadow map - shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter) - } - return shadow -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go b/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go deleted file mode 100644 index e92e5172c1..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/codec.go +++ /dev/null @@ -1,86 +0,0 @@ -package javaproperties - -import ( - "bytes" - "sort" - "strings" - - "github.com/magiconair/properties" - "github.com/spf13/cast" -) - -// Codec implements the encoding.Encoder and encoding.Decoder interfaces for Java properties encoding. -type Codec struct { - KeyDelimiter string - - // Store read properties on the object so that we can write back in order with comments. - // This will only be used if the configuration read is a properties file. - // TODO: drop this feature in v2 - // TODO: make use of the global properties object optional - Properties *properties.Properties -} - -func (c *Codec) Encode(v map[string]any) ([]byte, error) { - if c.Properties == nil { - c.Properties = properties.NewProperties() - } - - flattened := map[string]any{} - - flattened = flattenAndMergeMap(flattened, v, "", c.keyDelimiter()) - - keys := make([]string, 0, len(flattened)) - - for key := range flattened { - keys = append(keys, key) - } - - sort.Strings(keys) - - for _, key := range keys { - _, _, err := c.Properties.Set(key, cast.ToString(flattened[key])) - if err != nil { - return nil, err - } - } - - var buf bytes.Buffer - - _, err := c.Properties.WriteComment(&buf, "#", properties.UTF8) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (c *Codec) Decode(b []byte, v map[string]any) error { - var err error - c.Properties, err = properties.Load(b, properties.UTF8) - if err != nil { - return err - } - - for _, key := range c.Properties.Keys() { - // ignore existence check: we know it's there - value, _ := c.Properties.Get(key) - - // recursively build nested maps - path := strings.Split(key, c.keyDelimiter()) - lastKey := strings.ToLower(path[len(path)-1]) - deepestMap := deepSearch(v, path[0:len(path)-1]) - - // set innermost value - deepestMap[lastKey] = value - } - - return nil -} - -func (c Codec) keyDelimiter() string { - if c.KeyDelimiter == "" { - return "." - } - - return c.KeyDelimiter -} diff --git a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go b/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go deleted file mode 100644 index 6e1aff2236..0000000000 --- a/vendor/github.com/spf13/viper/internal/encoding/javaproperties/map_utils.go +++ /dev/null @@ -1,74 +0,0 @@ -package javaproperties - -import ( - "strings" - - "github.com/spf13/cast" -) - -// THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED -// AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE -// deepSearch scans deep maps, following the key indexes listed in the -// sequence "path". -// The last value is expected to be another map, and is returned. -// -// In case intermediate keys do not exist, or map to a non-map value, -// a new map is created and inserted, and the search continues from there: -// the initial map "m" may be modified! -func deepSearch(m map[string]any, path []string) map[string]any { - for _, k := range path { - m2, ok := m[k] - if !ok { - // intermediate key does not exist - // => create it and continue from there - m3 := make(map[string]any) - m[k] = m3 - m = m3 - continue - } - m3, ok := m2.(map[string]any) - if !ok { - // intermediate key is a value - // => replace with a new map - m3 = make(map[string]any) - m[k] = m3 - } - // continue search from here - m = m3 - } - return m -} - -// flattenAndMergeMap recursively flattens the given map into a new map -// Code is based on the function with the same name in the main package. -// TODO: move it to a common place. -func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { - if shadow != nil && prefix != "" && shadow[prefix] != nil { - // prefix is shadowed => nothing more to flatten - return shadow - } - if shadow == nil { - shadow = make(map[string]any) - } - - var m2 map[string]any - if prefix != "" { - prefix += delimiter - } - for k, val := range m { - fullKey := prefix + k - switch val := val.(type) { - case map[string]any: - m2 = val - case map[any]any: - m2 = cast.ToStringMap(val) - default: - // immediate value - shadow[strings.ToLower(fullKey)] = val - continue - } - // recursively merge to shadow map - shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter) - } - return shadow -} diff --git a/vendor/github.com/spf13/viper/internal/features/finder.go b/vendor/github.com/spf13/viper/internal/features/finder.go new file mode 100644 index 0000000000..983ea3a9d7 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/features/finder.go @@ -0,0 +1,5 @@ +//go:build viper_finder + +package features + +const Finder = true diff --git a/vendor/github.com/spf13/viper/internal/features/finder_default.go b/vendor/github.com/spf13/viper/internal/features/finder_default.go new file mode 100644 index 0000000000..89bcb06ee1 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/features/finder_default.go @@ -0,0 +1,5 @@ +//go:build !viper_finder + +package features + +const Finder = false diff --git a/vendor/github.com/spf13/viper/logger.go b/vendor/github.com/spf13/viper/logger.go index 8938053b31..828042f29a 100644 --- a/vendor/github.com/spf13/viper/logger.go +++ b/vendor/github.com/spf13/viper/logger.go @@ -2,46 +2,9 @@ package viper import ( "context" - - slog "github.com/sagikazarmark/slog-shim" + "log/slog" ) -// Logger is a unified interface for various logging use cases and practices, including: -// - leveled logging -// - structured logging -// -// Deprecated: use `log/slog` instead. -type Logger interface { - // Trace logs a Trace event. - // - // Even more fine-grained information than Debug events. - // Loggers not supporting this level should fall back to Debug. - Trace(msg string, keyvals ...any) - - // Debug logs a Debug event. - // - // A verbose series of information events. - // They are useful when debugging the system. - Debug(msg string, keyvals ...any) - - // Info logs an Info event. - // - // General information about what's happening inside the system. - Info(msg string, keyvals ...any) - - // Warn logs a Warn(ing) event. - // - // Non-critical events that should be looked at. - Warn(msg string, keyvals ...any) - - // Error logs an Error event. - // - // Critical events that require immediate attention. - // Loggers commonly provide Fatal and Panic levels above Error level, - // but exiting and panicking is out of scope for a logging library. - Error(msg string, keyvals ...any) -} - // WithLogger sets a custom logger. func WithLogger(l *slog.Logger) Option { return optionFunc(func(v *Viper) { diff --git a/vendor/github.com/spf13/viper/remote.go b/vendor/github.com/spf13/viper/remote.go new file mode 100644 index 0000000000..bdde7de267 --- /dev/null +++ b/vendor/github.com/spf13/viper/remote.go @@ -0,0 +1,256 @@ +package viper + +import ( + "bytes" + "fmt" + "io" + "reflect" + "slices" +) + +// SupportedRemoteProviders are universally supported remote providers. +var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} + +func resetRemote() { + SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} +} + +type remoteConfigFactory interface { + Get(rp RemoteProvider) (io.Reader, error) + Watch(rp RemoteProvider) (io.Reader, error) + WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) +} + +type RemoteResponse struct { + Value []byte + Error error +} + +// RemoteConfig is optional, see the remote package. +var RemoteConfig remoteConfigFactory + +// UnsupportedRemoteProviderError denotes encountering an unsupported remote +// provider. Currently only etcd and Consul are supported. +type UnsupportedRemoteProviderError string + +// Error returns the formatted remote provider error. +func (str UnsupportedRemoteProviderError) Error() string { + return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) +} + +// RemoteConfigError denotes encountering an error while trying to +// pull the configuration from the remote provider. +type RemoteConfigError string + +// Error returns the formatted remote provider error. +func (rce RemoteConfigError) Error() string { + return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) +} + +type defaultRemoteProvider struct { + provider string + endpoint string + path string + secretKeyring string +} + +func (rp defaultRemoteProvider) Provider() string { + return rp.provider +} + +func (rp defaultRemoteProvider) Endpoint() string { + return rp.endpoint +} + +func (rp defaultRemoteProvider) Path() string { + return rp.path +} + +func (rp defaultRemoteProvider) SecretKeyring() string { + return rp.secretKeyring +} + +// RemoteProvider stores the configuration necessary +// to connect to a remote key/value store. +// Optional secretKeyring to unencrypt encrypted values +// can be provided. +type RemoteProvider interface { + Provider() string + Endpoint() string + Path() string + SecretKeyring() string +} + +// AddRemoteProvider adds a remote configuration source. +// Remote Providers are searched in the order they are added. +// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. +// endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp". +func AddRemoteProvider(provider, endpoint, path string) error { + return v.AddRemoteProvider(provider, endpoint, path) +} + +func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { + if !slices.Contains(SupportedRemoteProviders, provider) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) + + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +// AddSecureRemoteProvider adds a remote configuration source. +// Secure Remote Providers are searched in the order they are added. +// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. +// endpoint is the url. etcd requires http://ip:port consul requires ip:port +// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg +// path is the path in the k/v store to retrieve configuration +// To retrieve a config file called myapp.json from /configs/myapp.json +// you should set path to /configs and set config name (SetConfigName()) to +// "myapp". +// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt. +func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) +} + +func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { + if !slices.Contains(SupportedRemoteProviders, provider) { + return UnsupportedRemoteProviderError(provider) + } + if provider != "" && endpoint != "" { + v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) + + rp := &defaultRemoteProvider{ + endpoint: endpoint, + provider: provider, + path: path, + secretKeyring: secretkeyring, + } + if !v.providerPathExists(rp) { + v.remoteProviders = append(v.remoteProviders, rp) + } + } + return nil +} + +func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { + for _, y := range v.remoteProviders { + if reflect.DeepEqual(y, p) { + return true + } + } + return false +} + +// ReadRemoteConfig attempts to get configuration from a remote source +// and read it in the remote configuration registry. +func ReadRemoteConfig() error { return v.ReadRemoteConfig() } + +func (v *Viper) ReadRemoteConfig() error { + return v.getKeyValueConfig() +} + +func WatchRemoteConfig() error { return v.WatchRemoteConfig() } +func (v *Viper) WatchRemoteConfig() error { + return v.watchKeyValueConfig() +} + +func (v *Viper) WatchRemoteConfigOnChannel() error { + return v.watchKeyValueConfigOnChannel() +} + +// Retrieve the first found remote configuration. +func (v *Viper) getKeyValueConfig() error { + if RemoteConfig == nil { + return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") + } + + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + val, err := v.getRemoteConfig(rp) + if err != nil { + v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) + + continue + } + + v.kvstore = val + + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) { + reader, err := RemoteConfig.Get(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfigOnChannel() error { + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + respc, _ := RemoteConfig.WatchChannel(rp) + // Todo: Add quit channel + go func(rc <-chan *RemoteResponse) { + for { + b := <-rc + reader := bytes.NewReader(b.Value) + v.unmarshalReader(reader, v.kvstore) + } + }(respc) + return nil + } + return RemoteConfigError("No Files Found") +} + +// Retrieve the first found remote configuration. +func (v *Viper) watchKeyValueConfig() error { + if len(v.remoteProviders) == 0 { + return RemoteConfigError("No Remote Providers") + } + + for _, rp := range v.remoteProviders { + val, err := v.watchRemoteConfig(rp) + if err != nil { + v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error()) + + continue + } + v.kvstore = val + return nil + } + return RemoteConfigError("No Files Found") +} + +func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) { + reader, err := RemoteConfig.Watch(provider) + if err != nil { + return nil, err + } + err = v.unmarshalReader(reader, v.kvstore) + return v.kvstore, err +} diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go index 117c6ac312..2a08074bc7 100644 --- a/vendor/github.com/spf13/viper/util.go +++ b/vendor/github.com/spf13/viper/util.go @@ -12,13 +12,13 @@ package viper import ( "fmt" + "log/slog" "os" "path/filepath" "runtime" "strings" "unicode" - slog "github.com/sagikazarmark/slog-shim" "github.com/spf13/cast" ) @@ -128,15 +128,6 @@ func absPathify(logger *slog.Logger, inPath string) string { return "" } -func stringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } - } - return false -} - func userHomeDir() string { if runtime.GOOS == "windows" { home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go index da68d9944c..f900e58b1a 100644 --- a/vendor/github.com/spf13/viper/viper.go +++ b/vendor/github.com/spf13/viper/viper.go @@ -25,29 +25,22 @@ import ( "errors" "fmt" "io" + "log/slog" "os" "path/filepath" "reflect" + "slices" "strconv" "strings" "sync" "time" "github.com/fsnotify/fsnotify" - "github.com/mitchellh/mapstructure" - slog "github.com/sagikazarmark/slog-shim" + "github.com/go-viper/mapstructure/v2" "github.com/spf13/afero" "github.com/spf13/cast" "github.com/spf13/pflag" - "github.com/spf13/viper/internal/encoding" - "github.com/spf13/viper/internal/encoding/dotenv" - "github.com/spf13/viper/internal/encoding/hcl" - "github.com/spf13/viper/internal/encoding/ini" - "github.com/spf13/viper/internal/encoding/javaproperties" - "github.com/spf13/viper/internal/encoding/json" - "github.com/spf13/viper/internal/encoding/toml" - "github.com/spf13/viper/internal/encoding/yaml" "github.com/spf13/viper/internal/features" ) @@ -63,24 +56,10 @@ func (e ConfigMarshalError) Error() string { var v *Viper -type RemoteResponse struct { - Value []byte - Error error -} - func init() { v = New() } -type remoteConfigFactory interface { - Get(rp RemoteProvider) (io.Reader, error) - Watch(rp RemoteProvider) (io.Reader, error) - WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) -} - -// RemoteConfig is optional, see the remote package. -var RemoteConfig remoteConfigFactory - // UnsupportedConfigError denotes encountering an unsupported // configuration filetype. type UnsupportedConfigError string @@ -90,24 +69,6 @@ func (str UnsupportedConfigError) Error() string { return fmt.Sprintf("Unsupported Config Type %q", string(str)) } -// UnsupportedRemoteProviderError denotes encountering an unsupported remote -// provider. Currently only etcd and Consul are supported. -type UnsupportedRemoteProviderError string - -// Error returns the formatted remote provider error. -func (str UnsupportedRemoteProviderError) Error() string { - return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) -} - -// RemoteConfigError denotes encountering an error while trying to -// pull the configuration from the remote provider. -type RemoteConfigError string - -// Error returns the formatted remote provider error. -func (rce RemoteConfigError) Error() string { - return fmt.Sprintf("Remote Configurations Error: %s", string(rce)) -} - // ConfigFileNotFoundError denotes failing to find configuration file. type ConfigFileNotFoundError struct { name, locations string @@ -190,6 +151,8 @@ type Viper struct { // The filesystem to read config from. fs afero.Fs + finder Finder + // A set of remote providers to search for the configuration remoteProviders []*defaultRemoteProvider @@ -200,9 +163,6 @@ type Viper struct { configPermissions os.FileMode envPrefix string - // Specific commands for ini parsing - iniLoadOptions ini.LoadOptions - automaticEnvApplied bool envKeyReplacer StringReplacer allowEmptyEnv bool @@ -221,9 +181,13 @@ type Viper struct { logger *slog.Logger - // TODO: should probably be protected with a mutex - encoderRegistry *encoding.EncoderRegistry - decoderRegistry *encoding.DecoderRegistry + encoderRegistry EncoderRegistry + decoderRegistry DecoderRegistry + + decodeHook mapstructure.DecodeHookFunc + + experimentalFinder bool + experimentalBindStruct bool } // New returns an initialized Viper instance. @@ -244,7 +208,13 @@ func New() *Viper { v.typeByDefValue = false v.logger = slog.New(&discardHandler{}) - v.resetEncoding() + codecRegistry := NewCodecRegistry() + + v.encoderRegistry = codecRegistry + v.decoderRegistry = codecRegistry + + v.experimentalFinder = features.Finder + v.experimentalBindStruct = features.BindStruct return v } @@ -280,10 +250,25 @@ type StringReplacer interface { // EnvKeyReplacer sets a replacer used for mapping environment variables to internal keys. func EnvKeyReplacer(r StringReplacer) Option { return optionFunc(func(v *Viper) { + if r == nil { + return + } + v.envKeyReplacer = r }) } +// WithDecodeHook sets a default decode hook for mapstructure. +func WithDecodeHook(h mapstructure.DecodeHookFunc) Option { + return optionFunc(func(v *Viper) { + if h == nil { + return + } + + v.decodeHook = h + }) +} + // NewWithOptions creates a new Viper instance. func NewWithOptions(opts ...Option) *Viper { v := New() @@ -292,138 +277,32 @@ func NewWithOptions(opts ...Option) *Viper { opt.apply(v) } - v.resetEncoding() - return v } +// SetOptions sets the options on the global Viper instance. +// +// Be careful when using this function: subsequent calls may override options you set. +// It's always better to use a local Viper instance. +func SetOptions(opts ...Option) { + for _, opt := range opts { + opt.apply(v) + } +} + // Reset is intended for testing, will reset all to default settings. // In the public interface for the viper package so applications // can use it in their testing as well. func Reset() { v = New() SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} - SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} -} - -// TODO: make this lazy initialization instead. -func (v *Viper) resetEncoding() { - encoderRegistry := encoding.NewEncoderRegistry() - decoderRegistry := encoding.NewDecoderRegistry() - - { - codec := yaml.Codec{} - - encoderRegistry.RegisterEncoder("yaml", codec) - decoderRegistry.RegisterDecoder("yaml", codec) - - encoderRegistry.RegisterEncoder("yml", codec) - decoderRegistry.RegisterDecoder("yml", codec) - } - - { - codec := json.Codec{} - - encoderRegistry.RegisterEncoder("json", codec) - decoderRegistry.RegisterDecoder("json", codec) - } - - { - codec := toml.Codec{} - - encoderRegistry.RegisterEncoder("toml", codec) - decoderRegistry.RegisterDecoder("toml", codec) - } - - { - codec := hcl.Codec{} - - encoderRegistry.RegisterEncoder("hcl", codec) - decoderRegistry.RegisterDecoder("hcl", codec) - - encoderRegistry.RegisterEncoder("tfvars", codec) - decoderRegistry.RegisterDecoder("tfvars", codec) - } - - { - codec := ini.Codec{ - KeyDelimiter: v.keyDelim, - LoadOptions: v.iniLoadOptions, - } - - encoderRegistry.RegisterEncoder("ini", codec) - decoderRegistry.RegisterDecoder("ini", codec) - } - - { - codec := &javaproperties.Codec{ - KeyDelimiter: v.keyDelim, - } - - encoderRegistry.RegisterEncoder("properties", codec) - decoderRegistry.RegisterDecoder("properties", codec) - - encoderRegistry.RegisterEncoder("props", codec) - decoderRegistry.RegisterDecoder("props", codec) - - encoderRegistry.RegisterEncoder("prop", codec) - decoderRegistry.RegisterDecoder("prop", codec) - } - - { - codec := &dotenv.Codec{} - - encoderRegistry.RegisterEncoder("dotenv", codec) - decoderRegistry.RegisterDecoder("dotenv", codec) - - encoderRegistry.RegisterEncoder("env", codec) - decoderRegistry.RegisterDecoder("env", codec) - } - v.encoderRegistry = encoderRegistry - v.decoderRegistry = decoderRegistry -} - -type defaultRemoteProvider struct { - provider string - endpoint string - path string - secretKeyring string -} - -func (rp defaultRemoteProvider) Provider() string { - return rp.provider -} - -func (rp defaultRemoteProvider) Endpoint() string { - return rp.endpoint -} - -func (rp defaultRemoteProvider) Path() string { - return rp.path -} - -func (rp defaultRemoteProvider) SecretKeyring() string { - return rp.secretKeyring -} - -// RemoteProvider stores the configuration necessary -// to connect to a remote key/value store. -// Optional secretKeyring to unencrypt encrypted values -// can be provided. -type RemoteProvider interface { - Provider() string - Endpoint() string - Path() string - SecretKeyring() string + resetRemote() } // SupportedExts are universally supported extensions. var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} -// SupportedRemoteProviders are universally supported remote providers. -var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"} - // OnConfigChange sets the event handler that is called when a config file changes. func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } @@ -574,90 +453,20 @@ func (v *Viper) ConfigFileUsed() string { return v.configFile } func AddConfigPath(in string) { v.AddConfigPath(in) } func (v *Viper) AddConfigPath(in string) { + if v.finder != nil { + v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "AddConfigPath")) + } + if in != "" { absin := absPathify(v.logger, in) v.logger.Info("adding path to search paths", "path", absin) - if !stringInSlice(absin, v.configPaths) { + if !slices.Contains(v.configPaths, absin) { v.configPaths = append(v.configPaths, absin) } } } -// AddRemoteProvider adds a remote configuration source. -// Remote Providers are searched in the order they are added. -// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. -// endpoint is the url. etcd requires http://ip:port, consul requires ip:port, nats requires nats://ip:port -// path is the path in the k/v store to retrieve configuration -// To retrieve a config file called myapp.json from /configs/myapp.json -// you should set path to /configs and set config name (SetConfigName()) to -// "myapp". -func AddRemoteProvider(provider, endpoint, path string) error { - return v.AddRemoteProvider(provider, endpoint, path) -} - -func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { - return UnsupportedRemoteProviderError(provider) - } - if provider != "" && endpoint != "" { - v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) - - rp := &defaultRemoteProvider{ - endpoint: endpoint, - provider: provider, - path: path, - } - if !v.providerPathExists(rp) { - v.remoteProviders = append(v.remoteProviders, rp) - } - } - return nil -} - -// AddSecureRemoteProvider adds a remote configuration source. -// Secure Remote Providers are searched in the order they are added. -// provider is a string value: "etcd", "etcd3", "consul", "firestore" or "nats" are currently supported. -// endpoint is the url. etcd requires http://ip:port consul requires ip:port -// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg -// path is the path in the k/v store to retrieve configuration -// To retrieve a config file called myapp.json from /configs/myapp.json -// you should set path to /configs and set config name (SetConfigName()) to -// "myapp". -// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt. -func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { - return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring) -} - -func (v *Viper) AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error { - if !stringInSlice(provider, SupportedRemoteProviders) { - return UnsupportedRemoteProviderError(provider) - } - if provider != "" && endpoint != "" { - v.logger.Info("adding remote provider", "provider", provider, "endpoint", endpoint) - - rp := &defaultRemoteProvider{ - endpoint: endpoint, - provider: provider, - path: path, - secretKeyring: secretkeyring, - } - if !v.providerPathExists(rp) { - v.remoteProviders = append(v.remoteProviders, rp) - } - } - return nil -} - -func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool { - for _, y := range v.remoteProviders { - if reflect.DeepEqual(y, p) { - return true - } - } - return false -} - // searchMap recursively searches for a value for path in source map. // Returns nil if not found. // Note: This assumes that the path entries and map keys are lower cased. @@ -965,6 +774,7 @@ func (v *Viper) Sub(key string) *Viper { subv.automaticEnvApplied = v.automaticEnvApplied subv.envPrefix = v.envPrefix subv.envKeyReplacer = v.envKeyReplacer + subv.keyDelim = v.keyDelim subv.config = cast.ToStringMap(data) return subv } @@ -1006,6 +816,13 @@ func (v *Viper) GetInt64(key string) int64 { return cast.ToInt64(v.Get(key)) } +// GetUint8 returns the value associated with the key as an unsigned integer. +func GetUint8(key string) uint8 { return v.GetUint8(key) } + +func (v *Viper) GetUint8(key string) uint8 { + return cast.ToUint8(v.Get(key)) +} + // GetUint returns the value associated with the key as an unsigned integer. func GetUint(key string) uint { return v.GetUint(key) } @@ -1105,7 +922,7 @@ func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) error { - return decode(v.Get(key), defaultDecoderConfig(rawVal, opts...)) + return decode(v.Get(key), v.defaultDecoderConfig(rawVal, opts...)) } // Unmarshal unmarshals the config into a Struct. Make sure that the tags @@ -1117,7 +934,7 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error { func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error { keys := v.AllKeys() - if features.BindStruct { + if v.experimentalBindStruct { // TODO: make this optional? structKeys, err := v.decodeStructKeys(rawVal, opts...) if err != nil { @@ -1128,13 +945,13 @@ func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error { } // TODO: struct keys should be enough? - return decode(v.getSettings(keys), defaultDecoderConfig(rawVal, opts...)) + return decode(v.getSettings(keys), v.defaultDecoderConfig(rawVal, opts...)) } func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) { var structKeyMap map[string]any - err := decode(input, defaultDecoderConfig(&structKeyMap, opts...)) + err := decode(input, v.defaultDecoderConfig(&structKeyMap, opts...)) if err != nil { return nil, err } @@ -1151,22 +968,54 @@ func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]stri // defaultDecoderConfig returns default mapstructure.DecoderConfig with support // of time.Duration values & string slices. -func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { +func (v *Viper) defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig { + decodeHook := v.decodeHook + if decodeHook == nil { + decodeHook = mapstructure.ComposeDecodeHookFunc( + mapstructure.StringToTimeDurationHookFunc(), + // mapstructure.StringToSliceHookFunc(","), + stringToWeakSliceHookFunc(","), + ) + } + c := &mapstructure.DecoderConfig{ Metadata: nil, - Result: output, WeaklyTypedInput: true, - DecodeHook: mapstructure.ComposeDecodeHookFunc( - mapstructure.StringToTimeDurationHookFunc(), - mapstructure.StringToSliceHookFunc(","), - ), + DecodeHook: decodeHook, } + for _, opt := range opts { opt(c) } + + // Do not allow overwriting the output + c.Result = output + return c } +// As of mapstructure v2.0.0 StringToSliceHookFunc checks if the return type is a string slice. +// This function removes that check. +// TODO: implement a function that checks if the value can be converted to the return type and use it instead. +func stringToWeakSliceHookFunc(sep string) mapstructure.DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}, + ) (interface{}, error) { + if f.Kind() != reflect.String || t.Kind() != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + // decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality. func decode(input any, config *mapstructure.DecoderConfig) error { decoder, err := mapstructure.NewDecoder(config) @@ -1183,12 +1032,12 @@ func UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { - config := defaultDecoderConfig(rawVal, opts...) + config := v.defaultDecoderConfig(rawVal, opts...) config.ErrorUnused = true keys := v.AllKeys() - if features.BindStruct { + if v.experimentalBindStruct { // TODO: make this optional? structKeys, err := v.decodeStructKeys(rawVal, opts...) if err != nil { @@ -1638,7 +1487,7 @@ func (v *Viper) ReadInConfig() error { return err } - if !stringInSlice(v.getConfigType(), SupportedExts) { + if !slices.Contains(SupportedExts, v.getConfigType()) { return UnsupportedConfigError(v.getConfigType()) } @@ -1669,7 +1518,7 @@ func (v *Viper) MergeInConfig() error { return err } - if !stringInSlice(v.getConfigType(), SupportedExts) { + if !slices.Contains(SupportedExts, v.getConfigType()) { return UnsupportedConfigError(v.getConfigType()) } @@ -1686,6 +1535,10 @@ func (v *Viper) MergeInConfig() error { func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } func (v *Viper) ReadConfig(in io.Reader) error { + if v.configType == "" { + return errors.New("cannot decode configuration: config type is not set") + } + v.config = make(map[string]any) return v.unmarshalReader(in, v.config) } @@ -1694,6 +1547,10 @@ func (v *Viper) ReadConfig(in io.Reader) error { func MergeConfig(in io.Reader) error { return v.MergeConfig(in) } func (v *Viper) MergeConfig(in io.Reader) error { + if v.configType == "" { + return errors.New("cannot decode configuration: config type is not set") + } + cfg := make(map[string]any) if err := v.unmarshalReader(in, cfg); err != nil { return err @@ -1742,6 +1599,19 @@ func (v *Viper) WriteConfigAs(filename string) error { return v.writeConfig(filename, true) } +// WriteConfigTo writes current configuration to an [io.Writer]. +func WriteConfigTo(w io.Writer) error { return v.WriteConfigTo(w) } + +func (v *Viper) WriteConfigTo(w io.Writer) error { + format := strings.ToLower(v.getConfigType()) + + if !slices.Contains(SupportedExts, format) { + return UnsupportedConfigError(format) + } + + return v.marshalWriter(w, format) +} + // SafeWriteConfigAs writes current configuration to a given filename if it does not exist. func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) } @@ -1768,7 +1638,7 @@ func (v *Viper) writeConfig(filename string, force bool) error { return fmt.Errorf("config type could not be determined for %s", filename) } - if !stringInSlice(configType, SupportedExts) { + if !slices.Contains(SupportedExts, configType) { return UnsupportedConfigError(configType) } if v.config == nil { @@ -1795,12 +1665,20 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error { buf := new(bytes.Buffer) buf.ReadFrom(in) - switch format := strings.ToLower(v.getConfigType()); format { - case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "properties", "props", "prop", "dotenv", "env": - err := v.decoderRegistry.Decode(format, buf.Bytes(), c) - if err != nil { - return ConfigParseError{err} - } + format := strings.ToLower(v.getConfigType()) + + if !slices.Contains(SupportedExts, format) { + return UnsupportedConfigError(format) + } + + decoder, err := v.decoderRegistry.Decoder(format) + if err != nil { + return ConfigParseError{err} + } + + err = decoder.Decode(buf.Bytes(), c) + if err != nil { + return ConfigParseError{err} } insensitiviseMap(c) @@ -1808,20 +1686,24 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error { } // Marshal a map into Writer. -func (v *Viper) marshalWriter(f afero.File, configType string) error { +func (v *Viper) marshalWriter(w io.Writer, configType string) error { c := v.AllSettings() - switch configType { - case "yaml", "yml", "json", "toml", "hcl", "tfvars", "ini", "prop", "props", "properties", "dotenv", "env": - b, err := v.encoderRegistry.Encode(configType, c) - if err != nil { - return ConfigMarshalError{err} - } - _, err = f.WriteString(string(b)) - if err != nil { - return ConfigMarshalError{err} - } + encoder, err := v.encoderRegistry.Encoder(configType) + if err != nil { + return ConfigMarshalError{err} } + + b, err := encoder.Encode(c) + if err != nil { + return ConfigMarshalError{err} + } + + _, err = w.Write(b) + if err != nil { + return ConfigMarshalError{err} + } + return nil } @@ -1953,106 +1835,6 @@ func mergeMaps(src, tgt map[string]any, itgt map[any]any) { } } -// ReadRemoteConfig attempts to get configuration from a remote source -// and read it in the remote configuration registry. -func ReadRemoteConfig() error { return v.ReadRemoteConfig() } - -func (v *Viper) ReadRemoteConfig() error { - return v.getKeyValueConfig() -} - -func WatchRemoteConfig() error { return v.WatchRemoteConfig() } -func (v *Viper) WatchRemoteConfig() error { - return v.watchKeyValueConfig() -} - -func (v *Viper) WatchRemoteConfigOnChannel() error { - return v.watchKeyValueConfigOnChannel() -} - -// Retrieve the first found remote configuration. -func (v *Viper) getKeyValueConfig() error { - if RemoteConfig == nil { - return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") - } - - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - val, err := v.getRemoteConfig(rp) - if err != nil { - v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) - - continue - } - - v.kvstore = val - - return nil - } - return RemoteConfigError("No Files Found") -} - -func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]any, error) { - reader, err := RemoteConfig.Get(provider) - if err != nil { - return nil, err - } - err = v.unmarshalReader(reader, v.kvstore) - return v.kvstore, err -} - -// Retrieve the first found remote configuration. -func (v *Viper) watchKeyValueConfigOnChannel() error { - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - respc, _ := RemoteConfig.WatchChannel(rp) - // Todo: Add quit channel - go func(rc <-chan *RemoteResponse) { - for { - b := <-rc - reader := bytes.NewReader(b.Value) - v.unmarshalReader(reader, v.kvstore) - } - }(respc) - return nil - } - return RemoteConfigError("No Files Found") -} - -// Retrieve the first found remote configuration. -func (v *Viper) watchKeyValueConfig() error { - if len(v.remoteProviders) == 0 { - return RemoteConfigError("No Remote Providers") - } - - for _, rp := range v.remoteProviders { - val, err := v.watchRemoteConfig(rp) - if err != nil { - v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error()) - - continue - } - v.kvstore = val - return nil - } - return RemoteConfigError("No Files Found") -} - -func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, error) { - reader, err := RemoteConfig.Watch(provider) - if err != nil { - return nil, err - } - err = v.unmarshalReader(reader, v.kvstore) - return v.kvstore, err -} - // AllKeys returns all keys holding a value, regardless of where they are set. // Nested keys are returned with a v.keyDelim separator. func AllKeys() []string { return v.AllKeys() } @@ -2174,6 +1956,10 @@ func (v *Viper) SetFs(fs afero.Fs) { func SetConfigName(in string) { v.SetConfigName(in) } func (v *Viper) SetConfigName(in string) { + if v.finder != nil { + v.logger.Warn("ineffective call to function: custom finder takes precedence", slog.String("function", "SetConfigName")) + } + if in != "" { v.configName = in v.configFile = "" @@ -2197,13 +1983,6 @@ func (v *Viper) SetConfigPermissions(perm os.FileMode) { v.configPermissions = perm.Perm() } -// IniLoadOptions sets the load options for ini parsing. -func IniLoadOptions(in ini.LoadOptions) Option { - return optionFunc(func(v *Viper) { - v.iniLoadOptions = in - }) -} - func (v *Viper) getConfigType() string { if v.configType != "" { return v.configType diff --git a/vendor/go.etcd.io/etcd/api/v3/version/version.go b/vendor/go.etcd.io/etcd/api/v3/version/version.go index 15c99a2c28..e614915822 100644 --- a/vendor/go.etcd.io/etcd/api/v3/version/version.go +++ b/vendor/go.etcd.io/etcd/api/v3/version/version.go @@ -26,7 +26,7 @@ import ( var ( // MinClusterVersion is the min cluster version this etcd binary is compatible with. MinClusterVersion = "3.0.0" - Version = "3.5.18" + Version = "3.5.19" APIVersion = "unknown" // Git SHA Value will be set during build diff --git a/vendor/go.opentelemetry.io/otel/.gitignore b/vendor/go.opentelemetry.io/otel/.gitignore index ae8577ef36..749e8e881b 100644 --- a/vendor/go.opentelemetry.io/otel/.gitignore +++ b/vendor/go.opentelemetry.io/otel/.gitignore @@ -1,6 +1,7 @@ .DS_Store Thumbs.db +.cache/ .tools/ venv/ .idea/ diff --git a/vendor/go.opentelemetry.io/otel/.golangci.yml b/vendor/go.opentelemetry.io/otel/.golangci.yml index ce3f40b609..c58e48ab0c 100644 --- a/vendor/go.opentelemetry.io/otel/.golangci.yml +++ b/vendor/go.opentelemetry.io/otel/.golangci.yml @@ -25,13 +25,13 @@ linters: - perfsprint - revive - staticcheck - - tenv - testifylint - typecheck - unconvert - unused - unparam - usestdlibvars + - usetesting issues: # Maximum issues count per one linter. @@ -175,132 +175,60 @@ linters-settings: # This means that linting errors with less than 0.8 confidence will be ignored. # Default: 0.8 confidence: 0.01 + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md rules: - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#blank-imports - name: blank-imports - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr - name: bool-literal-in-expr - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#constant-logical-expr - name: constant-logical-expr - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-as-argument - # TODO (#3372) re-enable linter when it is compatible. https://github.com/golangci/golangci-lint/issues/3280 - name: context-as-argument disabled: true arguments: - allowTypesBefore: "*testing.T" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-keys-type + - allowTypesBefore: "*testing.T" - name: context-keys-type - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#deep-exit - name: deep-exit - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#defer - name: defer - disabled: false arguments: - ["call-chain", "loop"] - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#dot-imports - name: dot-imports - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#duplicated-imports - name: duplicated-imports - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#early-return - name: early-return - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block + arguments: + - "preserveScope" - name: empty-block - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-lines - name: empty-lines - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming - name: error-naming - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-return - name: error-return - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-strings - name: error-strings - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#errorf - name: errorf - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#exported - name: exported - disabled: false arguments: - "sayRepetitiveInsteadOfStutters" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#flag-parameter - name: flag-parameter - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#identical-branches - name: identical-branches - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#if-return - name: if-return - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#increment-decrement + - name: import-shadowing - name: increment-decrement - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#indent-error-flow - name: indent-error-flow - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-shadowing - - name: import-shadowing - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#package-comments + arguments: + - "preserveScope" - name: package-comments - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range - name: range - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-in-closure - name: range-val-in-closure - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-address - name: range-val-address - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redefines-builtin-id - name: redefines-builtin-id - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-format - name: string-format - disabled: false arguments: - - panic - '/^[^\n]*$/' - must not contain line breaks - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#struct-tag - name: struct-tag - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#superfluous-else - name: superfluous-else - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-equal - - name: time-equal - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-naming - - name: var-naming - disabled: false arguments: - - ["ID"] # AllowList - - ["Otel", "Aws", "Gcp"] # DenyList - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-declaration - - name: var-declaration - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unconditional-recursion + - "preserveScope" + - name: time-equal - name: unconditional-recursion - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return - name: unexported-return - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unhandled-error - name: unhandled-error - disabled: false arguments: - "fmt.Fprint" - "fmt.Fprintf" @@ -308,15 +236,14 @@ linters-settings: - "fmt.Print" - "fmt.Printf" - "fmt.Println" - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unnecessary-stmt - name: unnecessary-stmt - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break - name: useless-break - disabled: false - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#waitgroup-by-value + - name: var-declaration + - name: var-naming + arguments: + - ["ID"] # AllowList + - ["Otel", "Aws", "Gcp"] # DenyList - name: waitgroup-by-value - disabled: false testifylint: enable-all: true disable: diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md index 599d59cd13..c076db2823 100644 --- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md +++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md @@ -11,6 +11,46 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm +## [1.35.0/0.57.0/0.11.0] 2025-03-05 + +This release is the last to support [Go 1.22]. +The next release will require at least [Go 1.23]. + +### Added + +- Add `ValueFromAttribute` and `KeyValueFromAttribute` in `go.opentelemetry.io/otel/log`. (#6180) +- Add `EventName` and `SetEventName` to `Record` in `go.opentelemetry.io/otel/log`. (#6187) +- Add `EventName` to `RecordFactory` in `go.opentelemetry.io/otel/log/logtest`. (#6187) +- `AssertRecordEqual` in `go.opentelemetry.io/otel/log/logtest` checks `Record.EventName`. (#6187) +- Add `EventName` and `SetEventName` to `Record` in `go.opentelemetry.io/otel/sdk/log`. (#6193) +- Add `EventName` to `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest`. (#6193) +- Emit `Record.EventName` field in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#6211) +- Emit `Record.EventName` field in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#6211) +- Emit `Record.EventName` field in `go.opentelemetry.io/otel/exporters/stdout/stdoutlog` (#6210) +- The `go.opentelemetry.io/otel/semconv/v1.28.0` package. + The package contains semantic conventions from the `v1.28.0` version of the OpenTelemetry Semantic Conventions. + See the [migration documentation](./semconv/v1.28.0/MIGRATION.md) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/v1.27.0`(#6236) +- The `go.opentelemetry.io/otel/semconv/v1.30.0` package. + The package contains semantic conventions from the `v1.30.0` version of the OpenTelemetry Semantic Conventions. + See the [migration documentation](./semconv/v1.30.0/MIGRATION.md) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/v1.28.0`(#6240) +- Document the pitfalls of using `Resource` as a comparable type. + `Resource.Equal` and `Resource.Equivalent` should be used instead. (#6272) +- Support [Go 1.24]. (#6304) +- Add `FilterProcessor` and `EnabledParameters` in `go.opentelemetry.io/otel/sdk/log`. + It replaces `go.opentelemetry.io/otel/sdk/log/internal/x.FilterProcessor`. + Compared to previous version it additionally gives the possibility to filter by resource and instrumentation scope. (#6317) + +### Changed + +- Update `github.com/prometheus/common` to `v0.62.0`, which changes the `NameValidationScheme` to `NoEscaping`. + This allows metrics names to keep original delimiters (e.g. `.`), rather than replacing with underscores. + This is controlled by the `Content-Type` header, or can be reverted by setting `NameValidationScheme` to `LegacyValidation` in `github.com/prometheus/common/model`. (#6198) + +### Fixes + +- Eliminate goroutine leak for the processor returned by `NewSimpleSpanProcessor` in `go.opentelemetry.io/otel/sdk/trace` when `Shutdown` is called and the passed `ctx` is canceled and `SpanExporter.Shutdown` has not returned. (#6368) +- Eliminate goroutine leak for the processor returned by `NewBatchSpanProcessor` in `go.opentelemetry.io/otel/sdk/trace` when `ForceFlush` is called and the passed `ctx` is canceled and `SpanExporter.Export` has not returned. (#6369) + ## [1.34.0/0.56.0/0.10.0] 2025-01-17 ### Changed @@ -3197,7 +3237,8 @@ It contains api and sdk for trace and meter. - CircleCI build CI manifest files. - CODEOWNERS file to track owners of this project. -[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.34.0...HEAD +[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.35.0...HEAD +[1.35.0/0.57.0/0.11.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.35.0 [1.34.0/0.56.0/0.10.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.34.0 [1.33.0/0.55.0/0.9.0/0.0.12]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.33.0 [1.32.0/0.54.0/0.8.0/0.0.11]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.32.0 @@ -3288,6 +3329,7 @@ It contains api and sdk for trace and meter. +[Go 1.24]: https://go.dev/doc/go1.24 [Go 1.23]: https://go.dev/doc/go1.23 [Go 1.22]: https://go.dev/doc/go1.22 [Go 1.21]: https://go.dev/doc/go1.21 diff --git a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md index 22a2e9dbd4..7b8af585aa 100644 --- a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md +++ b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md @@ -181,6 +181,18 @@ patterns in the spec. For a deeper discussion, see [this](https://github.com/open-telemetry/opentelemetry-specification/issues/165). +## Tests + +Each functionality should be covered by tests. + +Performance-critical functionality should also be covered by benchmarks. + +- Pull requests adding a performance-critical functionality +should have `go test -bench` output in their description. +- Pull requests changing a performance-critical functionality +should have [`benchstat`](https://pkg.go.dev/golang.org/x/perf/cmd/benchstat) +output in their description. + ## Documentation Each (non-internal, non-test) package must be documented using diff --git a/vendor/go.opentelemetry.io/otel/Makefile b/vendor/go.opentelemetry.io/otel/Makefile index a7f6d8cc68..226410d742 100644 --- a/vendor/go.opentelemetry.io/otel/Makefile +++ b/vendor/go.opentelemetry.io/otel/Makefile @@ -11,6 +11,10 @@ ALL_COVERAGE_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} GO = go TIMEOUT = 60 +# User to run as in docker images. +DOCKER_USER=$(shell id -u):$(shell id -g) +DEPENDENCIES_DOCKERFILE=./dependencies.Dockerfile + .DEFAULT_GOAL := precommit .PHONY: precommit ci @@ -81,20 +85,20 @@ PIP := $(PYTOOLS)/pip WORKDIR := /workdir # The python image to use for the virtual environment. -PYTHONIMAGE := python:3.11.3-slim-bullseye +PYTHONIMAGE := $(shell awk '$$4=="python" {print $$2}' $(DEPENDENCIES_DOCKERFILE)) # Run the python image with the current directory mounted. -DOCKERPY := docker run --rm -v "$(CURDIR):$(WORKDIR)" -w $(WORKDIR) $(PYTHONIMAGE) +DOCKERPY := docker run --rm -u $(DOCKER_USER) -v "$(CURDIR):$(WORKDIR)" -w $(WORKDIR) $(PYTHONIMAGE) # Create a virtual environment for Python tools. $(PYTOOLS): # The `--upgrade` flag is needed to ensure that the virtual environment is # created with the latest pip version. - @$(DOCKERPY) bash -c "python3 -m venv $(VENVDIR) && $(PIP) install --upgrade pip" + @$(DOCKERPY) bash -c "python3 -m venv $(VENVDIR) && $(PIP) install --upgrade --cache-dir=$(WORKDIR)/.cache/pip pip" # Install python packages into the virtual environment. $(PYTOOLS)/%: $(PYTOOLS) - @$(DOCKERPY) $(PIP) install -r requirements.txt + @$(DOCKERPY) $(PIP) install --cache-dir=$(WORKDIR)/.cache/pip -r requirements.txt CODESPELL = $(PYTOOLS)/codespell $(CODESPELL): PACKAGE=codespell @@ -119,7 +123,7 @@ vanity-import-fix: $(PORTO) # Generate go.work file for local development. .PHONY: go-work go-work: $(CROSSLINK) - $(CROSSLINK) work --root=$(shell pwd) + $(CROSSLINK) work --root=$(shell pwd) --go=1.22.7 # Build @@ -265,13 +269,30 @@ check-clean-work-tree: exit 1; \ fi +# The weaver docker image to use for semconv-generate. +WEAVER_IMAGE := $(shell awk '$$4=="weaver" {print $$2}' $(DEPENDENCIES_DOCKERFILE)) + SEMCONVPKG ?= "semconv/" .PHONY: semconv-generate -semconv-generate: $(SEMCONVGEN) $(SEMCONVKIT) +semconv-generate: $(SEMCONVKIT) [ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry semantic-conventions tag"; exit 1 ) - [ "$(OTEL_SEMCONV_REPO)" ] || ( echo "OTEL_SEMCONV_REPO unset: missing path to opentelemetry semantic-conventions repo"; exit 1 ) - $(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -z "$(SEMCONVPKG)/capitalizations.txt" -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" - $(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=metric -f metric.go -t "$(SEMCONVPKG)/metric_template.j2" -s "$(TAG)" + # Ensure the target directory for source code is available. + mkdir -p $(PWD)/$(SEMCONVPKG)/${TAG} + # Note: We mount a home directory for downloading/storing the semconv repository. + # Weaver will automatically clean the cache when finished, but the directories will remain. + mkdir -p ~/.weaver + docker run --rm \ + -u $(DOCKER_USER) \ + --env HOME=/tmp/weaver \ + --mount 'type=bind,source=$(PWD)/semconv,target=/home/weaver/templates/registry/go,readonly' \ + --mount 'type=bind,source=$(PWD)/semconv/${TAG},target=/home/weaver/target' \ + --mount 'type=bind,source=$(HOME)/.weaver,target=/tmp/weaver/.weaver' \ + $(WEAVER_IMAGE) registry generate \ + --registry=https://github.com/open-telemetry/semantic-conventions/archive/refs/tags/$(TAG).zip[model] \ + --templates=/home/weaver/templates \ + --param tag=$(TAG) \ + go \ + /home/weaver/target $(SEMCONVKIT) -output "$(SEMCONVPKG)/$(TAG)" -tag "$(TAG)" .PHONY: gorelease diff --git a/vendor/go.opentelemetry.io/otel/README.md b/vendor/go.opentelemetry.io/otel/README.md index d9a1920762..8421cd7e59 100644 --- a/vendor/go.opentelemetry.io/otel/README.md +++ b/vendor/go.opentelemetry.io/otel/README.md @@ -4,6 +4,8 @@ [![codecov.io](https://codecov.io/gh/open-telemetry/opentelemetry-go/coverage.svg?branch=main)](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main) [![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel)](https://pkg.go.dev/go.opentelemetry.io/otel) [![Go Report Card](https://goreportcard.com/badge/go.opentelemetry.io/otel)](https://goreportcard.com/report/go.opentelemetry.io/otel) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/open-telemetry/opentelemetry-go/badge)](https://scorecard.dev/viewer/?uri=github.com/open-telemetry/opentelemetry-go) +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9996/badge)](https://www.bestpractices.dev/projects/9996) [![Slack](https://img.shields.io/badge/slack-@cncf/otel--go-brightgreen.svg?logo=slack)](https://cloud-native.slack.com/archives/C01NPAXACKT) OpenTelemetry-Go is the [Go](https://golang.org/) implementation of [OpenTelemetry](https://opentelemetry.io/). @@ -49,18 +51,25 @@ Currently, this project supports the following environments. | OS | Go Version | Architecture | |----------|------------|--------------| +| Ubuntu | 1.24 | amd64 | | Ubuntu | 1.23 | amd64 | | Ubuntu | 1.22 | amd64 | +| Ubuntu | 1.24 | 386 | | Ubuntu | 1.23 | 386 | | Ubuntu | 1.22 | 386 | -| Linux | 1.23 | arm64 | -| Linux | 1.22 | arm64 | +| Ubuntu | 1.24 | arm64 | +| Ubuntu | 1.23 | arm64 | +| Ubuntu | 1.22 | arm64 | +| macOS 13 | 1.24 | amd64 | | macOS 13 | 1.23 | amd64 | | macOS 13 | 1.22 | amd64 | +| macOS | 1.24 | arm64 | | macOS | 1.23 | arm64 | | macOS | 1.22 | arm64 | +| Windows | 1.24 | amd64 | | Windows | 1.23 | amd64 | | Windows | 1.22 | amd64 | +| Windows | 1.24 | 386 | | Windows | 1.23 | 386 | | Windows | 1.22 | 386 | diff --git a/vendor/go.opentelemetry.io/otel/RELEASING.md b/vendor/go.opentelemetry.io/otel/RELEASING.md index 4ebef4f9dd..1e13ae54f7 100644 --- a/vendor/go.opentelemetry.io/otel/RELEASING.md +++ b/vendor/go.opentelemetry.io/otel/RELEASING.md @@ -5,17 +5,14 @@ New versions of the [OpenTelemetry Semantic Conventions] mean new versions of the `semconv` package need to be generated. The `semconv-generate` make target is used for this. -1. Checkout a local copy of the [OpenTelemetry Semantic Conventions] to the desired release tag. -2. Pull the latest `otel/semconvgen` image: `docker pull otel/semconvgen:latest` -3. Run the `make semconv-generate ...` target from this repository. +1. Set the `TAG` environment variable to the semantic convention tag you want to generate. +2. Run the `make semconv-generate ...` target from this repository. For example, ```sh -export TAG="v1.21.0" # Change to the release version you are generating. -export OTEL_SEMCONV_REPO="/absolute/path/to/opentelemetry/semantic-conventions" -docker pull otel/semconvgen:latest -make semconv-generate # Uses the exported TAG and OTEL_SEMCONV_REPO. +export TAG="v1.30.0" # Change to the release version you are generating. +make semconv-generate # Uses the exported TAG. ``` This should create a new sub-package of [`semconv`](./semconv). diff --git a/vendor/go.opentelemetry.io/otel/dependencies.Dockerfile b/vendor/go.opentelemetry.io/otel/dependencies.Dockerfile new file mode 100644 index 0000000000..e4c4a753c8 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/dependencies.Dockerfile @@ -0,0 +1,3 @@ +# This is a renovate-friendly source of Docker images. +FROM python:3.13.2-slim-bullseye@sha256:31b581c8218e1f3c58672481b3b7dba8e898852866b408c6a984c22832523935 AS python +FROM otel/weaver:v0.13.2@sha256:ae7346b992e477f629ea327e0979e8a416a97f7956ab1f7e95ac1f44edf1a893 AS weaver diff --git a/vendor/go.opentelemetry.io/otel/renovate.json b/vendor/go.opentelemetry.io/otel/renovate.json index 4f80c898a1..a6fa353f95 100644 --- a/vendor/go.opentelemetry.io/otel/renovate.json +++ b/vendor/go.opentelemetry.io/otel/renovate.json @@ -1,7 +1,7 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:recommended" + "config:best-practices" ], "ignorePaths": [], "labels": ["Skip Changelog", "dependencies"], @@ -14,6 +14,10 @@ "matchDepTypes": ["indirect"], "enabled": true }, + { + "matchPackageNames": ["go.opentelemetry.io/build-tools/**"], + "groupName": "build-tools" + }, { "matchPackageNames": ["google.golang.org/genproto/googleapis/**"], "groupName": "googleapis" diff --git a/vendor/go.opentelemetry.io/otel/requirements.txt b/vendor/go.opentelemetry.io/otel/requirements.txt index ab09daf9d5..1bb55fb1cc 100644 --- a/vendor/go.opentelemetry.io/otel/requirements.txt +++ b/vendor/go.opentelemetry.io/otel/requirements.txt @@ -1 +1 @@ -codespell==2.3.0 +codespell==2.4.1 diff --git a/vendor/go.opentelemetry.io/otel/trace/auto.go b/vendor/go.opentelemetry.io/otel/trace/auto.go new file mode 100644 index 0000000000..7e2910025a --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/auto.go @@ -0,0 +1,661 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package trace // import "go.opentelemetry.io/otel/trace" + +import ( + "context" + "encoding/json" + "fmt" + "math" + "os" + "reflect" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + "unicode/utf8" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + "go.opentelemetry.io/otel/trace/embedded" + "go.opentelemetry.io/otel/trace/internal/telemetry" +) + +// newAutoTracerProvider returns an auto-instrumentable [trace.TracerProvider]. +// If an [go.opentelemetry.io/auto.Instrumentation] is configured to instrument +// the process using the returned TracerProvider, all of the telemetry it +// produces will be processed and handled by that Instrumentation. By default, +// if no Instrumentation instruments the TracerProvider it will not generate +// any trace telemetry. +func newAutoTracerProvider() TracerProvider { return tracerProviderInstance } + +var tracerProviderInstance = new(autoTracerProvider) + +type autoTracerProvider struct{ embedded.TracerProvider } + +var _ TracerProvider = autoTracerProvider{} + +func (p autoTracerProvider) Tracer(name string, opts ...TracerOption) Tracer { + cfg := NewTracerConfig(opts...) + return autoTracer{ + name: name, + version: cfg.InstrumentationVersion(), + schemaURL: cfg.SchemaURL(), + } +} + +type autoTracer struct { + embedded.Tracer + + name, schemaURL, version string +} + +var _ Tracer = autoTracer{} + +func (t autoTracer) Start(ctx context.Context, name string, opts ...SpanStartOption) (context.Context, Span) { + var psc SpanContext + sampled := true + span := new(autoSpan) + + // Ask eBPF for sampling decision and span context info. + t.start(ctx, span, &psc, &sampled, &span.spanContext) + + span.sampled.Store(sampled) + + ctx = ContextWithSpan(ctx, span) + + if sampled { + // Only build traces if sampled. + cfg := NewSpanStartConfig(opts...) + span.traces, span.span = t.traces(name, cfg, span.spanContext, psc) + } + + return ctx, span +} + +// Expected to be implemented in eBPF. +// +//go:noinline +func (t *autoTracer) start( + ctx context.Context, + spanPtr *autoSpan, + psc *SpanContext, + sampled *bool, + sc *SpanContext, +) { + start(ctx, spanPtr, psc, sampled, sc) +} + +// start is used for testing. +var start = func(context.Context, *autoSpan, *SpanContext, *bool, *SpanContext) {} + +func (t autoTracer) traces(name string, cfg SpanConfig, sc, psc SpanContext) (*telemetry.Traces, *telemetry.Span) { + span := &telemetry.Span{ + TraceID: telemetry.TraceID(sc.TraceID()), + SpanID: telemetry.SpanID(sc.SpanID()), + Flags: uint32(sc.TraceFlags()), + TraceState: sc.TraceState().String(), + ParentSpanID: telemetry.SpanID(psc.SpanID()), + Name: name, + Kind: spanKind(cfg.SpanKind()), + } + + span.Attrs, span.DroppedAttrs = convCappedAttrs(maxSpan.Attrs, cfg.Attributes()) + + links := cfg.Links() + if limit := maxSpan.Links; limit == 0 { + n := int64(len(links)) + if n > 0 { + span.DroppedLinks = uint32(min(n, math.MaxUint32)) // nolint: gosec // Bounds checked. + } + } else { + if limit > 0 { + n := int64(max(len(links)-limit, 0)) + span.DroppedLinks = uint32(min(n, math.MaxUint32)) // nolint: gosec // Bounds checked. + links = links[n:] + } + span.Links = convLinks(links) + } + + if t := cfg.Timestamp(); !t.IsZero() { + span.StartTime = cfg.Timestamp() + } else { + span.StartTime = time.Now() + } + + return &telemetry.Traces{ + ResourceSpans: []*telemetry.ResourceSpans{ + { + ScopeSpans: []*telemetry.ScopeSpans{ + { + Scope: &telemetry.Scope{ + Name: t.name, + Version: t.version, + }, + Spans: []*telemetry.Span{span}, + SchemaURL: t.schemaURL, + }, + }, + }, + }, + }, span +} + +func spanKind(kind SpanKind) telemetry.SpanKind { + switch kind { + case SpanKindInternal: + return telemetry.SpanKindInternal + case SpanKindServer: + return telemetry.SpanKindServer + case SpanKindClient: + return telemetry.SpanKindClient + case SpanKindProducer: + return telemetry.SpanKindProducer + case SpanKindConsumer: + return telemetry.SpanKindConsumer + } + return telemetry.SpanKind(0) // undefined. +} + +type autoSpan struct { + embedded.Span + + spanContext SpanContext + sampled atomic.Bool + + mu sync.Mutex + traces *telemetry.Traces + span *telemetry.Span +} + +func (s *autoSpan) SpanContext() SpanContext { + if s == nil { + return SpanContext{} + } + // s.spanContext is immutable, do not acquire lock s.mu. + return s.spanContext +} + +func (s *autoSpan) IsRecording() bool { + if s == nil { + return false + } + + return s.sampled.Load() +} + +func (s *autoSpan) SetStatus(c codes.Code, msg string) { + if s == nil || !s.sampled.Load() { + return + } + + s.mu.Lock() + defer s.mu.Unlock() + + if s.span.Status == nil { + s.span.Status = new(telemetry.Status) + } + + s.span.Status.Message = msg + + switch c { + case codes.Unset: + s.span.Status.Code = telemetry.StatusCodeUnset + case codes.Error: + s.span.Status.Code = telemetry.StatusCodeError + case codes.Ok: + s.span.Status.Code = telemetry.StatusCodeOK + } +} + +func (s *autoSpan) SetAttributes(attrs ...attribute.KeyValue) { + if s == nil || !s.sampled.Load() { + return + } + + s.mu.Lock() + defer s.mu.Unlock() + + limit := maxSpan.Attrs + if limit == 0 { + // No attributes allowed. + n := int64(len(attrs)) + if n > 0 { + s.span.DroppedAttrs += uint32(min(n, math.MaxUint32)) // nolint: gosec // Bounds checked. + } + return + } + + m := make(map[string]int) + for i, a := range s.span.Attrs { + m[a.Key] = i + } + + for _, a := range attrs { + val := convAttrValue(a.Value) + if val.Empty() { + s.span.DroppedAttrs++ + continue + } + + if idx, ok := m[string(a.Key)]; ok { + s.span.Attrs[idx] = telemetry.Attr{ + Key: string(a.Key), + Value: val, + } + } else if limit < 0 || len(s.span.Attrs) < limit { + s.span.Attrs = append(s.span.Attrs, telemetry.Attr{ + Key: string(a.Key), + Value: val, + }) + m[string(a.Key)] = len(s.span.Attrs) - 1 + } else { + s.span.DroppedAttrs++ + } + } +} + +// convCappedAttrs converts up to limit attrs into a []telemetry.Attr. The +// number of dropped attributes is also returned. +func convCappedAttrs(limit int, attrs []attribute.KeyValue) ([]telemetry.Attr, uint32) { + n := len(attrs) + if limit == 0 { + var out uint32 + if n > 0 { + out = uint32(min(int64(n), math.MaxUint32)) // nolint: gosec // Bounds checked. + } + return nil, out + } + + if limit < 0 { + // Unlimited. + return convAttrs(attrs), 0 + } + + if n < 0 { + n = 0 + } + + limit = min(n, limit) + return convAttrs(attrs[:limit]), uint32(n - limit) // nolint: gosec // Bounds checked. +} + +func convAttrs(attrs []attribute.KeyValue) []telemetry.Attr { + if len(attrs) == 0 { + // Avoid allocations if not necessary. + return nil + } + + out := make([]telemetry.Attr, 0, len(attrs)) + for _, attr := range attrs { + key := string(attr.Key) + val := convAttrValue(attr.Value) + if val.Empty() { + continue + } + out = append(out, telemetry.Attr{Key: key, Value: val}) + } + return out +} + +func convAttrValue(value attribute.Value) telemetry.Value { + switch value.Type() { + case attribute.BOOL: + return telemetry.BoolValue(value.AsBool()) + case attribute.INT64: + return telemetry.Int64Value(value.AsInt64()) + case attribute.FLOAT64: + return telemetry.Float64Value(value.AsFloat64()) + case attribute.STRING: + v := truncate(maxSpan.AttrValueLen, value.AsString()) + return telemetry.StringValue(v) + case attribute.BOOLSLICE: + slice := value.AsBoolSlice() + out := make([]telemetry.Value, 0, len(slice)) + for _, v := range slice { + out = append(out, telemetry.BoolValue(v)) + } + return telemetry.SliceValue(out...) + case attribute.INT64SLICE: + slice := value.AsInt64Slice() + out := make([]telemetry.Value, 0, len(slice)) + for _, v := range slice { + out = append(out, telemetry.Int64Value(v)) + } + return telemetry.SliceValue(out...) + case attribute.FLOAT64SLICE: + slice := value.AsFloat64Slice() + out := make([]telemetry.Value, 0, len(slice)) + for _, v := range slice { + out = append(out, telemetry.Float64Value(v)) + } + return telemetry.SliceValue(out...) + case attribute.STRINGSLICE: + slice := value.AsStringSlice() + out := make([]telemetry.Value, 0, len(slice)) + for _, v := range slice { + v = truncate(maxSpan.AttrValueLen, v) + out = append(out, telemetry.StringValue(v)) + } + return telemetry.SliceValue(out...) + } + return telemetry.Value{} +} + +// truncate returns a truncated version of s such that it contains less than +// the limit number of characters. Truncation is applied by returning the limit +// number of valid characters contained in s. +// +// If limit is negative, it returns the original string. +// +// UTF-8 is supported. When truncating, all invalid characters are dropped +// before applying truncation. +// +// If s already contains less than the limit number of bytes, it is returned +// unchanged. No invalid characters are removed. +func truncate(limit int, s string) string { + // This prioritize performance in the following order based on the most + // common expected use-cases. + // + // - Short values less than the default limit (128). + // - Strings with valid encodings that exceed the limit. + // - No limit. + // - Strings with invalid encodings that exceed the limit. + if limit < 0 || len(s) <= limit { + return s + } + + // Optimistically, assume all valid UTF-8. + var b strings.Builder + count := 0 + for i, c := range s { + if c != utf8.RuneError { + count++ + if count > limit { + return s[:i] + } + continue + } + + _, size := utf8.DecodeRuneInString(s[i:]) + if size == 1 { + // Invalid encoding. + b.Grow(len(s) - 1) + _, _ = b.WriteString(s[:i]) + s = s[i:] + break + } + } + + // Fast-path, no invalid input. + if b.Cap() == 0 { + return s + } + + // Truncate while validating UTF-8. + for i := 0; i < len(s) && count < limit; { + c := s[i] + if c < utf8.RuneSelf { + // Optimization for single byte runes (common case). + _ = b.WriteByte(c) + i++ + count++ + continue + } + + _, size := utf8.DecodeRuneInString(s[i:]) + if size == 1 { + // We checked for all 1-byte runes above, this is a RuneError. + i++ + continue + } + + _, _ = b.WriteString(s[i : i+size]) + i += size + count++ + } + + return b.String() +} + +func (s *autoSpan) End(opts ...SpanEndOption) { + if s == nil || !s.sampled.Swap(false) { + return + } + + // s.end exists so the lock (s.mu) is not held while s.ended is called. + s.ended(s.end(opts)) +} + +func (s *autoSpan) end(opts []SpanEndOption) []byte { + s.mu.Lock() + defer s.mu.Unlock() + + cfg := NewSpanEndConfig(opts...) + if t := cfg.Timestamp(); !t.IsZero() { + s.span.EndTime = cfg.Timestamp() + } else { + s.span.EndTime = time.Now() + } + + b, _ := json.Marshal(s.traces) // TODO: do not ignore this error. + return b +} + +// Expected to be implemented in eBPF. +// +//go:noinline +func (*autoSpan) ended(buf []byte) { ended(buf) } + +// ended is used for testing. +var ended = func([]byte) {} + +func (s *autoSpan) RecordError(err error, opts ...EventOption) { + if s == nil || err == nil || !s.sampled.Load() { + return + } + + cfg := NewEventConfig(opts...) + + attrs := cfg.Attributes() + attrs = append(attrs, + semconv.ExceptionType(typeStr(err)), + semconv.ExceptionMessage(err.Error()), + ) + if cfg.StackTrace() { + buf := make([]byte, 2048) + n := runtime.Stack(buf, false) + attrs = append(attrs, semconv.ExceptionStacktrace(string(buf[0:n]))) + } + + s.mu.Lock() + defer s.mu.Unlock() + + s.addEvent(semconv.ExceptionEventName, cfg.Timestamp(), attrs) +} + +func typeStr(i any) string { + t := reflect.TypeOf(i) + if t.PkgPath() == "" && t.Name() == "" { + // Likely a builtin type. + return t.String() + } + return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()) +} + +func (s *autoSpan) AddEvent(name string, opts ...EventOption) { + if s == nil || !s.sampled.Load() { + return + } + + cfg := NewEventConfig(opts...) + + s.mu.Lock() + defer s.mu.Unlock() + + s.addEvent(name, cfg.Timestamp(), cfg.Attributes()) +} + +// addEvent adds an event with name and attrs at tStamp to the span. The span +// lock (s.mu) needs to be held by the caller. +func (s *autoSpan) addEvent(name string, tStamp time.Time, attrs []attribute.KeyValue) { + limit := maxSpan.Events + + if limit == 0 { + s.span.DroppedEvents++ + return + } + + if limit > 0 && len(s.span.Events) == limit { + // Drop head while avoiding allocation of more capacity. + copy(s.span.Events[:limit-1], s.span.Events[1:]) + s.span.Events = s.span.Events[:limit-1] + s.span.DroppedEvents++ + } + + e := &telemetry.SpanEvent{Time: tStamp, Name: name} + e.Attrs, e.DroppedAttrs = convCappedAttrs(maxSpan.EventAttrs, attrs) + + s.span.Events = append(s.span.Events, e) +} + +func (s *autoSpan) AddLink(link Link) { + if s == nil || !s.sampled.Load() { + return + } + + l := maxSpan.Links + + s.mu.Lock() + defer s.mu.Unlock() + + if l == 0 { + s.span.DroppedLinks++ + return + } + + if l > 0 && len(s.span.Links) == l { + // Drop head while avoiding allocation of more capacity. + copy(s.span.Links[:l-1], s.span.Links[1:]) + s.span.Links = s.span.Links[:l-1] + s.span.DroppedLinks++ + } + + s.span.Links = append(s.span.Links, convLink(link)) +} + +func convLinks(links []Link) []*telemetry.SpanLink { + out := make([]*telemetry.SpanLink, 0, len(links)) + for _, link := range links { + out = append(out, convLink(link)) + } + return out +} + +func convLink(link Link) *telemetry.SpanLink { + l := &telemetry.SpanLink{ + TraceID: telemetry.TraceID(link.SpanContext.TraceID()), + SpanID: telemetry.SpanID(link.SpanContext.SpanID()), + TraceState: link.SpanContext.TraceState().String(), + Flags: uint32(link.SpanContext.TraceFlags()), + } + l.Attrs, l.DroppedAttrs = convCappedAttrs(maxSpan.LinkAttrs, link.Attributes) + + return l +} + +func (s *autoSpan) SetName(name string) { + if s == nil || !s.sampled.Load() { + return + } + + s.mu.Lock() + defer s.mu.Unlock() + + s.span.Name = name +} + +func (*autoSpan) TracerProvider() TracerProvider { return newAutoTracerProvider() } + +// maxSpan are the span limits resolved during startup. +var maxSpan = newSpanLimits() + +type spanLimits struct { + // Attrs is the number of allowed attributes for a span. + // + // This is resolved from the environment variable value for the + // OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT key if it exists. Otherwise, the + // environment variable value for OTEL_ATTRIBUTE_COUNT_LIMIT, or 128 if + // that is not set, is used. + Attrs int + // AttrValueLen is the maximum attribute value length allowed for a span. + // + // This is resolved from the environment variable value for the + // OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT key if it exists. Otherwise, the + // environment variable value for OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, or -1 + // if that is not set, is used. + AttrValueLen int + // Events is the number of allowed events for a span. + // + // This is resolved from the environment variable value for the + // OTEL_SPAN_EVENT_COUNT_LIMIT key, or 128 is used if that is not set. + Events int + // EventAttrs is the number of allowed attributes for a span event. + // + // The is resolved from the environment variable value for the + // OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT key, or 128 is used if that is not set. + EventAttrs int + // Links is the number of allowed Links for a span. + // + // This is resolved from the environment variable value for the + // OTEL_SPAN_LINK_COUNT_LIMIT, or 128 is used if that is not set. + Links int + // LinkAttrs is the number of allowed attributes for a span link. + // + // This is resolved from the environment variable value for the + // OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, or 128 is used if that is not set. + LinkAttrs int +} + +func newSpanLimits() spanLimits { + return spanLimits{ + Attrs: firstEnv( + 128, + "OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", + "OTEL_ATTRIBUTE_COUNT_LIMIT", + ), + AttrValueLen: firstEnv( + -1, // Unlimited. + "OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", + "OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", + ), + Events: firstEnv(128, "OTEL_SPAN_EVENT_COUNT_LIMIT"), + EventAttrs: firstEnv(128, "OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT"), + Links: firstEnv(128, "OTEL_SPAN_LINK_COUNT_LIMIT"), + LinkAttrs: firstEnv(128, "OTEL_LINK_ATTRIBUTE_COUNT_LIMIT"), + } +} + +// firstEnv returns the parsed integer value of the first matching environment +// variable from keys. The defaultVal is returned if the value is not an +// integer or no match is found. +func firstEnv(defaultVal int, keys ...string) int { + for _, key := range keys { + strV := os.Getenv(key) + if strV == "" { + continue + } + + v, err := strconv.Atoi(strV) + if err == nil { + return v + } + // Ignore invalid environment variable. + } + + return defaultVal +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/attr.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/attr.go new file mode 100644 index 0000000000..f663547b4e --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/attr.go @@ -0,0 +1,58 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +// Attr is a key-value pair. +type Attr struct { + Key string `json:"key,omitempty"` + Value Value `json:"value,omitempty"` +} + +// String returns an Attr for a string value. +func String(key, value string) Attr { + return Attr{key, StringValue(value)} +} + +// Int64 returns an Attr for an int64 value. +func Int64(key string, value int64) Attr { + return Attr{key, Int64Value(value)} +} + +// Int returns an Attr for an int value. +func Int(key string, value int) Attr { + return Int64(key, int64(value)) +} + +// Float64 returns an Attr for a float64 value. +func Float64(key string, value float64) Attr { + return Attr{key, Float64Value(value)} +} + +// Bool returns an Attr for a bool value. +func Bool(key string, value bool) Attr { + return Attr{key, BoolValue(value)} +} + +// Bytes returns an Attr for a []byte value. +// The passed slice must not be changed after it is passed. +func Bytes(key string, value []byte) Attr { + return Attr{key, BytesValue(value)} +} + +// Slice returns an Attr for a []Value value. +// The passed slice must not be changed after it is passed. +func Slice(key string, value ...Value) Attr { + return Attr{key, SliceValue(value...)} +} + +// Map returns an Attr for a map value. +// The passed slice must not be changed after it is passed. +func Map(key string, value ...Attr) Attr { + return Attr{key, MapValue(value...)} +} + +// Equal returns if a is equal to b. +func (a Attr) Equal(b Attr) bool { + return a.Key == b.Key && a.Value.Equal(b.Value) +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/doc.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/doc.go new file mode 100644 index 0000000000..5debe90bbb --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/doc.go @@ -0,0 +1,8 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +/* +Package telemetry provides a lightweight representations of OpenTelemetry +telemetry that is compatible with the OTLP JSON protobuf encoding. +*/ +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/id.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/id.go new file mode 100644 index 0000000000..7b1ae3c4ea --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/id.go @@ -0,0 +1,103 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +import ( + "encoding/hex" + "errors" + "fmt" +) + +const ( + traceIDSize = 16 + spanIDSize = 8 +) + +// TraceID is a custom data type that is used for all trace IDs. +type TraceID [traceIDSize]byte + +// String returns the hex string representation form of a TraceID. +func (tid TraceID) String() string { + return hex.EncodeToString(tid[:]) +} + +// IsEmpty returns false if id contains at least one non-zero byte. +func (tid TraceID) IsEmpty() bool { + return tid == [traceIDSize]byte{} +} + +// MarshalJSON converts the trace ID into a hex string enclosed in quotes. +func (tid TraceID) MarshalJSON() ([]byte, error) { + if tid.IsEmpty() { + return []byte(`""`), nil + } + return marshalJSON(tid[:]) +} + +// UnmarshalJSON inflates the trace ID from hex string, possibly enclosed in +// quotes. +func (tid *TraceID) UnmarshalJSON(data []byte) error { + *tid = [traceIDSize]byte{} + return unmarshalJSON(tid[:], data) +} + +// SpanID is a custom data type that is used for all span IDs. +type SpanID [spanIDSize]byte + +// String returns the hex string representation form of a SpanID. +func (sid SpanID) String() string { + return hex.EncodeToString(sid[:]) +} + +// IsEmpty returns true if the span ID contains at least one non-zero byte. +func (sid SpanID) IsEmpty() bool { + return sid == [spanIDSize]byte{} +} + +// MarshalJSON converts span ID into a hex string enclosed in quotes. +func (sid SpanID) MarshalJSON() ([]byte, error) { + if sid.IsEmpty() { + return []byte(`""`), nil + } + return marshalJSON(sid[:]) +} + +// UnmarshalJSON decodes span ID from hex string, possibly enclosed in quotes. +func (sid *SpanID) UnmarshalJSON(data []byte) error { + *sid = [spanIDSize]byte{} + return unmarshalJSON(sid[:], data) +} + +// marshalJSON converts id into a hex string enclosed in quotes. +func marshalJSON(id []byte) ([]byte, error) { + // Plus 2 quote chars at the start and end. + hexLen := hex.EncodedLen(len(id)) + 2 + + b := make([]byte, hexLen) + hex.Encode(b[1:hexLen-1], id) + b[0], b[hexLen-1] = '"', '"' + + return b, nil +} + +// unmarshalJSON inflates trace id from hex string, possibly enclosed in quotes. +func unmarshalJSON(dst []byte, src []byte) error { + if l := len(src); l >= 2 && src[0] == '"' && src[l-1] == '"' { + src = src[1 : l-1] + } + nLen := len(src) + if nLen == 0 { + return nil + } + + if len(dst) != hex.DecodedLen(nLen) { + return errors.New("invalid length for ID") + } + + _, err := hex.Decode(dst, src) + if err != nil { + return fmt.Errorf("cannot unmarshal ID from string '%s': %w", string(src), err) + } + return nil +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/number.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/number.go new file mode 100644 index 0000000000..f5e3a8cec9 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/number.go @@ -0,0 +1,67 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +import ( + "encoding/json" + "strconv" +) + +// protoInt64 represents the protobuf encoding of integers which can be either +// strings or integers. +type protoInt64 int64 + +// Int64 returns the protoInt64 as an int64. +func (i *protoInt64) Int64() int64 { return int64(*i) } + +// UnmarshalJSON decodes both strings and integers. +func (i *protoInt64) UnmarshalJSON(data []byte) error { + if data[0] == '"' { + var str string + if err := json.Unmarshal(data, &str); err != nil { + return err + } + parsedInt, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return err + } + *i = protoInt64(parsedInt) + } else { + var parsedInt int64 + if err := json.Unmarshal(data, &parsedInt); err != nil { + return err + } + *i = protoInt64(parsedInt) + } + return nil +} + +// protoUint64 represents the protobuf encoding of integers which can be either +// strings or integers. +type protoUint64 uint64 + +// Int64 returns the protoUint64 as a uint64. +func (i *protoUint64) Uint64() uint64 { return uint64(*i) } + +// UnmarshalJSON decodes both strings and integers. +func (i *protoUint64) UnmarshalJSON(data []byte) error { + if data[0] == '"' { + var str string + if err := json.Unmarshal(data, &str); err != nil { + return err + } + parsedUint, err := strconv.ParseUint(str, 10, 64) + if err != nil { + return err + } + *i = protoUint64(parsedUint) + } else { + var parsedUint uint64 + if err := json.Unmarshal(data, &parsedUint); err != nil { + return err + } + *i = protoUint64(parsedUint) + } + return nil +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/resource.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/resource.go new file mode 100644 index 0000000000..1798a702d4 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/resource.go @@ -0,0 +1,66 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" +) + +// Resource information. +type Resource struct { + // Attrs are the set of attributes that describe the resource. Attribute + // keys MUST be unique (it is not allowed to have more than one attribute + // with the same key). + Attrs []Attr `json:"attributes,omitempty"` + // DroppedAttrs is the number of dropped attributes. If the value + // is 0, then no attributes were dropped. + DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"` +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into r. +func (r *Resource) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid Resource type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid Resource field: %#v", keyIface) + } + + switch key { + case "attributes": + err = decoder.Decode(&r.Attrs) + case "droppedAttributesCount", "dropped_attributes_count": + err = decoder.Decode(&r.DroppedAttrs) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/scope.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/scope.go new file mode 100644 index 0000000000..c2b4c635b7 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/scope.go @@ -0,0 +1,67 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" +) + +// Scope is the identifying values of the instrumentation scope. +type Scope struct { + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` + Attrs []Attr `json:"attributes,omitempty"` + DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"` +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into r. +func (s *Scope) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid Scope type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid Scope field: %#v", keyIface) + } + + switch key { + case "name": + err = decoder.Decode(&s.Name) + case "version": + err = decoder.Decode(&s.Version) + case "attributes": + err = decoder.Decode(&s.Attrs) + case "droppedAttributesCount", "dropped_attributes_count": + err = decoder.Decode(&s.DroppedAttrs) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go new file mode 100644 index 0000000000..3c5e1cdb1b --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go @@ -0,0 +1,460 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "math" + "time" +) + +// A Span represents a single operation performed by a single component of the +// system. +type Span struct { + // A unique identifier for a trace. All spans from the same trace share + // the same `trace_id`. The ID is a 16-byte array. An ID with all zeroes OR + // of length other than 16 bytes is considered invalid (empty string in OTLP/JSON + // is zero-length and thus is also invalid). + // + // This field is required. + TraceID TraceID `json:"traceId,omitempty"` + // A unique identifier for a span within a trace, assigned when the span + // is created. The ID is an 8-byte array. An ID with all zeroes OR of length + // other than 8 bytes is considered invalid (empty string in OTLP/JSON + // is zero-length and thus is also invalid). + // + // This field is required. + SpanID SpanID `json:"spanId,omitempty"` + // trace_state conveys information about request position in multiple distributed tracing graphs. + // It is a trace_state in w3c-trace-context format: https://www.w3.org/TR/trace-context/#tracestate-header + // See also https://github.com/w3c/distributed-tracing for more details about this field. + TraceState string `json:"traceState,omitempty"` + // The `span_id` of this span's parent span. If this is a root span, then this + // field must be empty. The ID is an 8-byte array. + ParentSpanID SpanID `json:"parentSpanId,omitempty"` + // Flags, a bit field. + // + // Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace + // Context specification. To read the 8-bit W3C trace flag, use + // `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + // + // Bits 8 and 9 represent the 3 states of whether a span's parent + // is remote. The states are (unknown, is not remote, is remote). + // To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`. + // To read whether the span is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`. + // + // When creating span messages, if the message is logically forwarded from another source + // with an equivalent flags fields (i.e., usually another OTLP span message), the field SHOULD + // be copied as-is. If creating from a source that does not have an equivalent flags field + // (such as a runtime representation of an OpenTelemetry span), the high 22 bits MUST + // be set to zero. + // Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be zero. + // + // [Optional]. + Flags uint32 `json:"flags,omitempty"` + // A description of the span's operation. + // + // For example, the name can be a qualified method name or a file name + // and a line number where the operation is called. A best practice is to use + // the same display name at the same call point in an application. + // This makes it easier to correlate spans in different traces. + // + // This field is semantically required to be set to non-empty string. + // Empty value is equivalent to an unknown span name. + // + // This field is required. + Name string `json:"name"` + // Distinguishes between spans generated in a particular context. For example, + // two spans with the same name may be distinguished using `CLIENT` (caller) + // and `SERVER` (callee) to identify queueing latency associated with the span. + Kind SpanKind `json:"kind,omitempty"` + // start_time_unix_nano is the start time of the span. On the client side, this is the time + // kept by the local machine where the span execution starts. On the server side, this + // is the time when the server's application handler starts running. + // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. + // + // This field is semantically required and it is expected that end_time >= start_time. + StartTime time.Time `json:"startTimeUnixNano,omitempty"` + // end_time_unix_nano is the end time of the span. On the client side, this is the time + // kept by the local machine where the span execution ends. On the server side, this + // is the time when the server application handler stops running. + // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. + // + // This field is semantically required and it is expected that end_time >= start_time. + EndTime time.Time `json:"endTimeUnixNano,omitempty"` + // attributes is a collection of key/value pairs. Note, global attributes + // like server name can be set using the resource API. Examples of attributes: + // + // "/http/user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" + // "/http/server_latency": 300 + // "example.com/myattribute": true + // "example.com/score": 10.239 + // + // The OpenTelemetry API specification further restricts the allowed value types: + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/common/README.md#attribute + // Attribute keys MUST be unique (it is not allowed to have more than one + // attribute with the same key). + Attrs []Attr `json:"attributes,omitempty"` + // dropped_attributes_count is the number of attributes that were discarded. Attributes + // can be discarded because their keys are too long or because there are too many + // attributes. If this value is 0, then no attributes were dropped. + DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"` + // events is a collection of Event items. + Events []*SpanEvent `json:"events,omitempty"` + // dropped_events_count is the number of dropped events. If the value is 0, then no + // events were dropped. + DroppedEvents uint32 `json:"droppedEventsCount,omitempty"` + // links is a collection of Links, which are references from this span to a span + // in the same or different trace. + Links []*SpanLink `json:"links,omitempty"` + // dropped_links_count is the number of dropped links after the maximum size was + // enforced. If this value is 0, then no links were dropped. + DroppedLinks uint32 `json:"droppedLinksCount,omitempty"` + // An optional final status for this span. Semantically when Status isn't set, it means + // span's status code is unset, i.e. assume STATUS_CODE_UNSET (code = 0). + Status *Status `json:"status,omitempty"` +} + +// MarshalJSON encodes s into OTLP formatted JSON. +func (s Span) MarshalJSON() ([]byte, error) { + startT := s.StartTime.UnixNano() + if s.StartTime.IsZero() || startT < 0 { + startT = 0 + } + + endT := s.EndTime.UnixNano() + if s.EndTime.IsZero() || endT < 0 { + endT = 0 + } + + // Override non-empty default SpanID marshal and omitempty. + var parentSpanId string + if !s.ParentSpanID.IsEmpty() { + b := make([]byte, hex.EncodedLen(spanIDSize)) + hex.Encode(b, s.ParentSpanID[:]) + parentSpanId = string(b) + } + + type Alias Span + return json.Marshal(struct { + Alias + ParentSpanID string `json:"parentSpanId,omitempty"` + StartTime uint64 `json:"startTimeUnixNano,omitempty"` + EndTime uint64 `json:"endTimeUnixNano,omitempty"` + }{ + Alias: Alias(s), + ParentSpanID: parentSpanId, + StartTime: uint64(startT), // nolint:gosec // >0 checked above. + EndTime: uint64(endT), // nolint:gosec // >0 checked above. + }) +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into s. +func (s *Span) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid Span type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid Span field: %#v", keyIface) + } + + switch key { + case "traceId", "trace_id": + err = decoder.Decode(&s.TraceID) + case "spanId", "span_id": + err = decoder.Decode(&s.SpanID) + case "traceState", "trace_state": + err = decoder.Decode(&s.TraceState) + case "parentSpanId", "parent_span_id": + err = decoder.Decode(&s.ParentSpanID) + case "flags": + err = decoder.Decode(&s.Flags) + case "name": + err = decoder.Decode(&s.Name) + case "kind": + err = decoder.Decode(&s.Kind) + case "startTimeUnixNano", "start_time_unix_nano": + var val protoUint64 + err = decoder.Decode(&val) + v := int64(min(val.Uint64(), math.MaxInt64)) // nolint: gosec // Overflow checked. + s.StartTime = time.Unix(0, v) + case "endTimeUnixNano", "end_time_unix_nano": + var val protoUint64 + err = decoder.Decode(&val) + v := int64(min(val.Uint64(), math.MaxInt64)) // nolint: gosec // Overflow checked. + s.EndTime = time.Unix(0, v) + case "attributes": + err = decoder.Decode(&s.Attrs) + case "droppedAttributesCount", "dropped_attributes_count": + err = decoder.Decode(&s.DroppedAttrs) + case "events": + err = decoder.Decode(&s.Events) + case "droppedEventsCount", "dropped_events_count": + err = decoder.Decode(&s.DroppedEvents) + case "links": + err = decoder.Decode(&s.Links) + case "droppedLinksCount", "dropped_links_count": + err = decoder.Decode(&s.DroppedLinks) + case "status": + err = decoder.Decode(&s.Status) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} + +// SpanFlags represents constants used to interpret the +// Span.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: +// +// (span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK) +// +// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. +// +// Note that Span flags were introduced in version 1.1 of the +// OpenTelemetry protocol. Older Span producers do not set this +// field, consequently consumers should not rely on the absence of a +// particular flag bit to indicate the presence of a particular feature. +type SpanFlags int32 + +const ( + // Bits 0-7 are used for trace flags. + SpanFlagsTraceFlagsMask SpanFlags = 255 + // Bits 8 and 9 are used to indicate that the parent span or link span is remote. + // Bit 8 (`HAS_IS_REMOTE`) indicates whether the value is known. + // Bit 9 (`IS_REMOTE`) indicates whether the span or link is remote. + SpanFlagsContextHasIsRemoteMask SpanFlags = 256 + // SpanFlagsContextHasIsRemoteMask indicates the Span is remote. + SpanFlagsContextIsRemoteMask SpanFlags = 512 +) + +// SpanKind is the type of span. Can be used to specify additional relationships between spans +// in addition to a parent/child relationship. +type SpanKind int32 + +const ( + // Indicates that the span represents an internal operation within an application, + // as opposed to an operation happening at the boundaries. Default value. + SpanKindInternal SpanKind = 1 + // Indicates that the span covers server-side handling of an RPC or other + // remote network request. + SpanKindServer SpanKind = 2 + // Indicates that the span describes a request to some remote service. + SpanKindClient SpanKind = 3 + // Indicates that the span describes a producer sending a message to a broker. + // Unlike CLIENT and SERVER, there is often no direct critical path latency relationship + // between producer and consumer spans. A PRODUCER span ends when the message was accepted + // by the broker while the logical processing of the message might span a much longer time. + SpanKindProducer SpanKind = 4 + // Indicates that the span describes consumer receiving a message from a broker. + // Like the PRODUCER kind, there is often no direct critical path latency relationship + // between producer and consumer spans. + SpanKindConsumer SpanKind = 5 +) + +// Event is a time-stamped annotation of the span, consisting of user-supplied +// text description and key-value pairs. +type SpanEvent struct { + // time_unix_nano is the time the event occurred. + Time time.Time `json:"timeUnixNano,omitempty"` + // name of the event. + // This field is semantically required to be set to non-empty string. + Name string `json:"name,omitempty"` + // attributes is a collection of attribute key/value pairs on the event. + // Attribute keys MUST be unique (it is not allowed to have more than one + // attribute with the same key). + Attrs []Attr `json:"attributes,omitempty"` + // dropped_attributes_count is the number of dropped attributes. If the value is 0, + // then no attributes were dropped. + DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"` +} + +// MarshalJSON encodes e into OTLP formatted JSON. +func (e SpanEvent) MarshalJSON() ([]byte, error) { + t := e.Time.UnixNano() + if e.Time.IsZero() || t < 0 { + t = 0 + } + + type Alias SpanEvent + return json.Marshal(struct { + Alias + Time uint64 `json:"timeUnixNano,omitempty"` + }{ + Alias: Alias(e), + Time: uint64(t), // nolint: gosec // >0 checked above + }) +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into se. +func (se *SpanEvent) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid SpanEvent type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid SpanEvent field: %#v", keyIface) + } + + switch key { + case "timeUnixNano", "time_unix_nano": + var val protoUint64 + err = decoder.Decode(&val) + v := int64(min(val.Uint64(), math.MaxInt64)) // nolint: gosec // Overflow checked. + se.Time = time.Unix(0, v) + case "name": + err = decoder.Decode(&se.Name) + case "attributes": + err = decoder.Decode(&se.Attrs) + case "droppedAttributesCount", "dropped_attributes_count": + err = decoder.Decode(&se.DroppedAttrs) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} + +// A pointer from the current span to another span in the same trace or in a +// different trace. For example, this can be used in batching operations, +// where a single batch handler processes multiple requests from different +// traces or when the handler receives a request from a different project. +type SpanLink struct { + // A unique identifier of a trace that this linked span is part of. The ID is a + // 16-byte array. + TraceID TraceID `json:"traceId,omitempty"` + // A unique identifier for the linked span. The ID is an 8-byte array. + SpanID SpanID `json:"spanId,omitempty"` + // The trace_state associated with the link. + TraceState string `json:"traceState,omitempty"` + // attributes is a collection of attribute key/value pairs on the link. + // Attribute keys MUST be unique (it is not allowed to have more than one + // attribute with the same key). + Attrs []Attr `json:"attributes,omitempty"` + // dropped_attributes_count is the number of dropped attributes. If the value is 0, + // then no attributes were dropped. + DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"` + // Flags, a bit field. + // + // Bits 0-7 (8 least significant bits) are the trace flags as defined in W3C Trace + // Context specification. To read the 8-bit W3C trace flag, use + // `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + // + // Bits 8 and 9 represent the 3 states of whether the link is remote. + // The states are (unknown, is not remote, is remote). + // To read whether the value is known, use `(flags & SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK) != 0`. + // To read whether the link is remote, use `(flags & SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK) != 0`. + // + // Readers MUST NOT assume that bits 10-31 (22 most significant bits) will be zero. + // When creating new spans, bits 10-31 (most-significant 22-bits) MUST be zero. + // + // [Optional]. + Flags uint32 `json:"flags,omitempty"` +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into sl. +func (sl *SpanLink) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid SpanLink type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid SpanLink field: %#v", keyIface) + } + + switch key { + case "traceId", "trace_id": + err = decoder.Decode(&sl.TraceID) + case "spanId", "span_id": + err = decoder.Decode(&sl.SpanID) + case "traceState", "trace_state": + err = decoder.Decode(&sl.TraceState) + case "attributes": + err = decoder.Decode(&sl.Attrs) + case "droppedAttributesCount", "dropped_attributes_count": + err = decoder.Decode(&sl.DroppedAttrs) + case "flags": + err = decoder.Decode(&sl.Flags) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go new file mode 100644 index 0000000000..1d013a8fa8 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +// For the semantics of status codes see +// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#set-status +type StatusCode int32 + +const ( + // The default status. + StatusCodeUnset StatusCode = 0 + // The Span has been validated by an Application developer or Operator to + // have completed successfully. + StatusCodeOK StatusCode = 1 + // The Span contains an error. + StatusCodeError StatusCode = 2 +) + +var statusCodeStrings = []string{ + "Unset", + "OK", + "Error", +} + +func (s StatusCode) String() string { + if s >= 0 && int(s) < len(statusCodeStrings) { + return statusCodeStrings[s] + } + return "" +} + +// The Status type defines a logical error model that is suitable for different +// programming environments, including REST APIs and RPC APIs. +type Status struct { + // A developer-facing human readable error message. + Message string `json:"message,omitempty"` + // The status code. + Code StatusCode `json:"code,omitempty"` +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go new file mode 100644 index 0000000000..b039407081 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go @@ -0,0 +1,189 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" +) + +// Traces represents the traces data that can be stored in a persistent storage, +// OR can be embedded by other protocols that transfer OTLP traces data but do +// not implement the OTLP protocol. +// +// The main difference between this message and collector protocol is that +// in this message there will not be any "control" or "metadata" specific to +// OTLP protocol. +// +// When new fields are added into this message, the OTLP request MUST be updated +// as well. +type Traces struct { + // An array of ResourceSpans. + // For data coming from a single resource this array will typically contain + // one element. Intermediary nodes that receive data from multiple origins + // typically batch the data before forwarding further and in that case this + // array will contain multiple elements. + ResourceSpans []*ResourceSpans `json:"resourceSpans,omitempty"` +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into td. +func (td *Traces) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid TracesData type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid TracesData field: %#v", keyIface) + } + + switch key { + case "resourceSpans", "resource_spans": + err = decoder.Decode(&td.ResourceSpans) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} + +// A collection of ScopeSpans from a Resource. +type ResourceSpans struct { + // The resource for the spans in this message. + // If this field is not set then no resource info is known. + Resource Resource `json:"resource"` + // A list of ScopeSpans that originate from a resource. + ScopeSpans []*ScopeSpans `json:"scopeSpans,omitempty"` + // This schema_url applies to the data in the "resource" field. It does not apply + // to the data in the "scope_spans" field which have their own schema_url field. + SchemaURL string `json:"schemaUrl,omitempty"` +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into rs. +func (rs *ResourceSpans) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid ResourceSpans type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid ResourceSpans field: %#v", keyIface) + } + + switch key { + case "resource": + err = decoder.Decode(&rs.Resource) + case "scopeSpans", "scope_spans": + err = decoder.Decode(&rs.ScopeSpans) + case "schemaUrl", "schema_url": + err = decoder.Decode(&rs.SchemaURL) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} + +// A collection of Spans produced by an InstrumentationScope. +type ScopeSpans struct { + // The instrumentation scope information for the spans in this message. + // Semantically when InstrumentationScope isn't set, it is equivalent with + // an empty instrumentation scope name (unknown). + Scope *Scope `json:"scope"` + // A list of Spans that originate from an instrumentation scope. + Spans []*Span `json:"spans,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the span data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url + // This schema_url applies to all spans and span events in the "spans" field. + SchemaURL string `json:"schemaUrl,omitempty"` +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into ss. +func (ss *ScopeSpans) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid ScopeSpans type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid ScopeSpans field: %#v", keyIface) + } + + switch key { + case "scope": + err = decoder.Decode(&ss.Scope) + case "spans": + err = decoder.Decode(&ss.Spans) + case "schemaUrl", "schema_url": + err = decoder.Decode(&ss.SchemaURL) + default: + // Skip unknown. + } + + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go new file mode 100644 index 0000000000..7251492da0 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go @@ -0,0 +1,453 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package telemetry // import "go.opentelemetry.io/otel/trace/internal/telemetry" + +import ( + "bytes" + "cmp" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "math" + "slices" + "strconv" + "unsafe" +) + +// A Value represents a structured value. +// A zero value is valid and represents an empty value. +type Value struct { + // Ensure forward compatibility by explicitly making this not comparable. + noCmp [0]func() //nolint: unused // This is indeed used. + + // num holds the value for Int64, Float64, and Bool. It holds the length + // for String, Bytes, Slice, Map. + num uint64 + // any holds either the KindBool, KindInt64, KindFloat64, stringptr, + // bytesptr, sliceptr, or mapptr. If KindBool, KindInt64, or KindFloat64 + // then the value of Value is in num as described above. Otherwise, it + // contains the value wrapped in the appropriate type. + any any +} + +type ( + // sliceptr represents a value in Value.any for KindString Values. + stringptr *byte + // bytesptr represents a value in Value.any for KindBytes Values. + bytesptr *byte + // sliceptr represents a value in Value.any for KindSlice Values. + sliceptr *Value + // mapptr represents a value in Value.any for KindMap Values. + mapptr *Attr +) + +// ValueKind is the kind of a [Value]. +type ValueKind int + +// ValueKind values. +const ( + ValueKindEmpty ValueKind = iota + ValueKindBool + ValueKindFloat64 + ValueKindInt64 + ValueKindString + ValueKindBytes + ValueKindSlice + ValueKindMap +) + +var valueKindStrings = []string{ + "Empty", + "Bool", + "Float64", + "Int64", + "String", + "Bytes", + "Slice", + "Map", +} + +func (k ValueKind) String() string { + if k >= 0 && int(k) < len(valueKindStrings) { + return valueKindStrings[k] + } + return "" +} + +// StringValue returns a new [Value] for a string. +func StringValue(v string) Value { + return Value{ + num: uint64(len(v)), + any: stringptr(unsafe.StringData(v)), + } +} + +// IntValue returns a [Value] for an int. +func IntValue(v int) Value { return Int64Value(int64(v)) } + +// Int64Value returns a [Value] for an int64. +func Int64Value(v int64) Value { + return Value{ + num: uint64(v), // nolint: gosec // Store raw bytes. + any: ValueKindInt64, + } +} + +// Float64Value returns a [Value] for a float64. +func Float64Value(v float64) Value { + return Value{num: math.Float64bits(v), any: ValueKindFloat64} +} + +// BoolValue returns a [Value] for a bool. +func BoolValue(v bool) Value { //nolint:revive // Not a control flag. + var n uint64 + if v { + n = 1 + } + return Value{num: n, any: ValueKindBool} +} + +// BytesValue returns a [Value] for a byte slice. The passed slice must not be +// changed after it is passed. +func BytesValue(v []byte) Value { + return Value{ + num: uint64(len(v)), + any: bytesptr(unsafe.SliceData(v)), + } +} + +// SliceValue returns a [Value] for a slice of [Value]. The passed slice must +// not be changed after it is passed. +func SliceValue(vs ...Value) Value { + return Value{ + num: uint64(len(vs)), + any: sliceptr(unsafe.SliceData(vs)), + } +} + +// MapValue returns a new [Value] for a slice of key-value pairs. The passed +// slice must not be changed after it is passed. +func MapValue(kvs ...Attr) Value { + return Value{ + num: uint64(len(kvs)), + any: mapptr(unsafe.SliceData(kvs)), + } +} + +// AsString returns the value held by v as a string. +func (v Value) AsString() string { + if sp, ok := v.any.(stringptr); ok { + return unsafe.String(sp, v.num) + } + // TODO: error handle + return "" +} + +// asString returns the value held by v as a string. It will panic if the Value +// is not KindString. +func (v Value) asString() string { + return unsafe.String(v.any.(stringptr), v.num) +} + +// AsInt64 returns the value held by v as an int64. +func (v Value) AsInt64() int64 { + if v.Kind() != ValueKindInt64 { + // TODO: error handle + return 0 + } + return v.asInt64() +} + +// asInt64 returns the value held by v as an int64. If v is not of KindInt64, +// this will return garbage. +func (v Value) asInt64() int64 { + // Assumes v.num was a valid int64 (overflow not checked). + return int64(v.num) // nolint: gosec +} + +// AsBool returns the value held by v as a bool. +func (v Value) AsBool() bool { + if v.Kind() != ValueKindBool { + // TODO: error handle + return false + } + return v.asBool() +} + +// asBool returns the value held by v as a bool. If v is not of KindBool, this +// will return garbage. +func (v Value) asBool() bool { return v.num == 1 } + +// AsFloat64 returns the value held by v as a float64. +func (v Value) AsFloat64() float64 { + if v.Kind() != ValueKindFloat64 { + // TODO: error handle + return 0 + } + return v.asFloat64() +} + +// asFloat64 returns the value held by v as a float64. If v is not of +// KindFloat64, this will return garbage. +func (v Value) asFloat64() float64 { return math.Float64frombits(v.num) } + +// AsBytes returns the value held by v as a []byte. +func (v Value) AsBytes() []byte { + if sp, ok := v.any.(bytesptr); ok { + return unsafe.Slice((*byte)(sp), v.num) + } + // TODO: error handle + return nil +} + +// asBytes returns the value held by v as a []byte. It will panic if the Value +// is not KindBytes. +func (v Value) asBytes() []byte { + return unsafe.Slice((*byte)(v.any.(bytesptr)), v.num) +} + +// AsSlice returns the value held by v as a []Value. +func (v Value) AsSlice() []Value { + if sp, ok := v.any.(sliceptr); ok { + return unsafe.Slice((*Value)(sp), v.num) + } + // TODO: error handle + return nil +} + +// asSlice returns the value held by v as a []Value. It will panic if the Value +// is not KindSlice. +func (v Value) asSlice() []Value { + return unsafe.Slice((*Value)(v.any.(sliceptr)), v.num) +} + +// AsMap returns the value held by v as a []Attr. +func (v Value) AsMap() []Attr { + if sp, ok := v.any.(mapptr); ok { + return unsafe.Slice((*Attr)(sp), v.num) + } + // TODO: error handle + return nil +} + +// asMap returns the value held by v as a []Attr. It will panic if the +// Value is not KindMap. +func (v Value) asMap() []Attr { + return unsafe.Slice((*Attr)(v.any.(mapptr)), v.num) +} + +// Kind returns the Kind of v. +func (v Value) Kind() ValueKind { + switch x := v.any.(type) { + case ValueKind: + return x + case stringptr: + return ValueKindString + case bytesptr: + return ValueKindBytes + case sliceptr: + return ValueKindSlice + case mapptr: + return ValueKindMap + default: + return ValueKindEmpty + } +} + +// Empty returns if v does not hold any value. +func (v Value) Empty() bool { return v.Kind() == ValueKindEmpty } + +// Equal returns if v is equal to w. +func (v Value) Equal(w Value) bool { + k1 := v.Kind() + k2 := w.Kind() + if k1 != k2 { + return false + } + switch k1 { + case ValueKindInt64, ValueKindBool: + return v.num == w.num + case ValueKindString: + return v.asString() == w.asString() + case ValueKindFloat64: + return v.asFloat64() == w.asFloat64() + case ValueKindSlice: + return slices.EqualFunc(v.asSlice(), w.asSlice(), Value.Equal) + case ValueKindMap: + sv := sortMap(v.asMap()) + sw := sortMap(w.asMap()) + return slices.EqualFunc(sv, sw, Attr.Equal) + case ValueKindBytes: + return bytes.Equal(v.asBytes(), w.asBytes()) + case ValueKindEmpty: + return true + default: + // TODO: error handle + return false + } +} + +func sortMap(m []Attr) []Attr { + sm := make([]Attr, len(m)) + copy(sm, m) + slices.SortFunc(sm, func(a, b Attr) int { + return cmp.Compare(a.Key, b.Key) + }) + + return sm +} + +// String returns Value's value as a string, formatted like [fmt.Sprint]. +// +// The returned string is meant for debugging; +// the string representation is not stable. +func (v Value) String() string { + switch v.Kind() { + case ValueKindString: + return v.asString() + case ValueKindInt64: + // Assumes v.num was a valid int64 (overflow not checked). + return strconv.FormatInt(int64(v.num), 10) // nolint: gosec + case ValueKindFloat64: + return strconv.FormatFloat(v.asFloat64(), 'g', -1, 64) + case ValueKindBool: + return strconv.FormatBool(v.asBool()) + case ValueKindBytes: + return fmt.Sprint(v.asBytes()) + case ValueKindMap: + return fmt.Sprint(v.asMap()) + case ValueKindSlice: + return fmt.Sprint(v.asSlice()) + case ValueKindEmpty: + return "" + default: + // Try to handle this as gracefully as possible. + // + // Don't panic here. The goal here is to have developers find this + // first if a slog.Kind is is not handled. It is + // preferable to have user's open issue asking why their attributes + // have a "unhandled: " prefix than say that their code is panicking. + return fmt.Sprintf("", v.Kind()) + } +} + +// MarshalJSON encodes v into OTLP formatted JSON. +func (v *Value) MarshalJSON() ([]byte, error) { + switch v.Kind() { + case ValueKindString: + return json.Marshal(struct { + Value string `json:"stringValue"` + }{v.asString()}) + case ValueKindInt64: + return json.Marshal(struct { + Value string `json:"intValue"` + }{strconv.FormatInt(int64(v.num), 10)}) // nolint: gosec // From raw bytes. + case ValueKindFloat64: + return json.Marshal(struct { + Value float64 `json:"doubleValue"` + }{v.asFloat64()}) + case ValueKindBool: + return json.Marshal(struct { + Value bool `json:"boolValue"` + }{v.asBool()}) + case ValueKindBytes: + return json.Marshal(struct { + Value []byte `json:"bytesValue"` + }{v.asBytes()}) + case ValueKindMap: + return json.Marshal(struct { + Value struct { + Values []Attr `json:"values"` + } `json:"kvlistValue"` + }{struct { + Values []Attr `json:"values"` + }{v.asMap()}}) + case ValueKindSlice: + return json.Marshal(struct { + Value struct { + Values []Value `json:"values"` + } `json:"arrayValue"` + }{struct { + Values []Value `json:"values"` + }{v.asSlice()}}) + case ValueKindEmpty: + return nil, nil + default: + return nil, fmt.Errorf("unknown Value kind: %s", v.Kind().String()) + } +} + +// UnmarshalJSON decodes the OTLP formatted JSON contained in data into v. +func (v *Value) UnmarshalJSON(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + + t, err := decoder.Token() + if err != nil { + return err + } + if t != json.Delim('{') { + return errors.New("invalid Value type") + } + + for decoder.More() { + keyIface, err := decoder.Token() + if err != nil { + if errors.Is(err, io.EOF) { + // Empty. + return nil + } + return err + } + + key, ok := keyIface.(string) + if !ok { + return fmt.Errorf("invalid Value key: %#v", keyIface) + } + + switch key { + case "stringValue", "string_value": + var val string + err = decoder.Decode(&val) + *v = StringValue(val) + case "boolValue", "bool_value": + var val bool + err = decoder.Decode(&val) + *v = BoolValue(val) + case "intValue", "int_value": + var val protoInt64 + err = decoder.Decode(&val) + *v = Int64Value(val.Int64()) + case "doubleValue", "double_value": + var val float64 + err = decoder.Decode(&val) + *v = Float64Value(val) + case "bytesValue", "bytes_value": + var val64 string + if err := decoder.Decode(&val64); err != nil { + return err + } + var val []byte + val, err = base64.StdEncoding.DecodeString(val64) + *v = BytesValue(val) + case "arrayValue", "array_value": + var val struct{ Values []Value } + err = decoder.Decode(&val) + *v = SliceValue(val.Values...) + case "kvlistValue", "kvlist_value": + var val struct{ Values []Attr } + err = decoder.Decode(&val) + *v = MapValue(val.Values...) + default: + // Skip unknown. + continue + } + // Use first valid. Ignore the rest. + return err + } + + // Only unknown fields. Return nil without unmarshaling any value. + return nil +} diff --git a/vendor/go.opentelemetry.io/otel/trace/noop.go b/vendor/go.opentelemetry.io/otel/trace/noop.go index ca20e9997a..c8b1ae5d67 100644 --- a/vendor/go.opentelemetry.io/otel/trace/noop.go +++ b/vendor/go.opentelemetry.io/otel/trace/noop.go @@ -82,4 +82,22 @@ func (noopSpan) AddLink(Link) {} func (noopSpan) SetName(string) {} // TracerProvider returns a no-op TracerProvider. -func (noopSpan) TracerProvider() TracerProvider { return noopTracerProvider{} } +func (s noopSpan) TracerProvider() TracerProvider { + return s.tracerProvider(autoInstEnabled) +} + +// autoInstEnabled defines if the auto-instrumentation SDK is enabled. +// +// The auto-instrumentation is expected to overwrite this value to true when it +// attaches to the process. +var autoInstEnabled = new(bool) + +// tracerProvider return a noopTracerProvider if autoEnabled is false, +// otherwise it will return a TracerProvider from the sdk package used in +// auto-instrumentation. +func (noopSpan) tracerProvider(autoEnabled *bool) TracerProvider { + if *autoEnabled { + return newAutoTracerProvider() + } + return noopTracerProvider{} +} diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go index eb22002d82..d5fa71f674 100644 --- a/vendor/go.opentelemetry.io/otel/version.go +++ b/vendor/go.opentelemetry.io/otel/version.go @@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel" // Version is the current release version of OpenTelemetry in use. func Version() string { - return "1.34.0" + return "1.35.0" } diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml index ce4fe59b0e..2b4cb4b418 100644 --- a/vendor/go.opentelemetry.io/otel/versions.yaml +++ b/vendor/go.opentelemetry.io/otel/versions.yaml @@ -3,7 +3,7 @@ module-sets: stable-v1: - version: v1.34.0 + version: v1.35.0 modules: - go.opentelemetry.io/otel - go.opentelemetry.io/otel/bridge/opencensus @@ -23,11 +23,11 @@ module-sets: - go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/trace experimental-metrics: - version: v0.56.0 + version: v0.57.0 modules: - go.opentelemetry.io/otel/exporters/prometheus experimental-logs: - version: v0.10.0 + version: v0.11.0 modules: - go.opentelemetry.io/otel/log - go.opentelemetry.io/otel/sdk/log @@ -40,3 +40,4 @@ module-sets: - go.opentelemetry.io/otel/schema excluded-modules: - go.opentelemetry.io/otel/internal/tools + - go.opentelemetry.io/otel/trace/internal/telemetry/test diff --git a/vendor/golang.org/x/exp/LICENSE b/vendor/golang.org/x/exp/LICENSE deleted file mode 100644 index 2a7cf70da6..0000000000 --- a/vendor/golang.org/x/exp/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/exp/PATENTS b/vendor/golang.org/x/exp/PATENTS deleted file mode 100644 index 733099041f..0000000000 --- a/vendor/golang.org/x/exp/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/exp/constraints/constraints.go b/vendor/golang.org/x/exp/constraints/constraints.go deleted file mode 100644 index 2c033dff47..0000000000 --- a/vendor/golang.org/x/exp/constraints/constraints.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package constraints defines a set of useful constraints to be used -// with type parameters. -package constraints - -// Signed is a constraint that permits any signed integer type. -// If future releases of Go add new predeclared signed integer types, -// this constraint will be modified to include them. -type Signed interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 -} - -// Unsigned is a constraint that permits any unsigned integer type. -// If future releases of Go add new predeclared unsigned integer types, -// this constraint will be modified to include them. -type Unsigned interface { - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr -} - -// Integer is a constraint that permits any integer type. -// If future releases of Go add new predeclared integer types, -// this constraint will be modified to include them. -type Integer interface { - Signed | Unsigned -} - -// Float is a constraint that permits any floating-point type. -// If future releases of Go add new predeclared floating-point types, -// this constraint will be modified to include them. -type Float interface { - ~float32 | ~float64 -} - -// Complex is a constraint that permits any complex numeric type. -// If future releases of Go add new predeclared complex numeric types, -// this constraint will be modified to include them. -type Complex interface { - ~complex64 | ~complex128 -} - -// Ordered is a constraint that permits any ordered type: any type -// that supports the operators < <= >= >. -// If future releases of Go add new ordered types, -// this constraint will be modified to include them. -type Ordered interface { - Integer | Float | ~string -} diff --git a/vendor/golang.org/x/exp/slices/cmp.go b/vendor/golang.org/x/exp/slices/cmp.go deleted file mode 100644 index fbf1934a06..0000000000 --- a/vendor/golang.org/x/exp/slices/cmp.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// min is a version of the predeclared function from the Go 1.21 release. -func min[T constraints.Ordered](a, b T) T { - if a < b || isNaN(a) { - return a - } - return b -} - -// max is a version of the predeclared function from the Go 1.21 release. -func max[T constraints.Ordered](a, b T) T { - if a > b || isNaN(a) { - return a - } - return b -} - -// cmpLess is a copy of cmp.Less from the Go 1.21 release. -func cmpLess[T constraints.Ordered](x, y T) bool { - return (isNaN(x) && !isNaN(y)) || x < y -} - -// cmpCompare is a copy of cmp.Compare from the Go 1.21 release. -func cmpCompare[T constraints.Ordered](x, y T) int { - xNaN := isNaN(x) - yNaN := isNaN(y) - if xNaN && yNaN { - return 0 - } - if xNaN || x < y { - return -1 - } - if yNaN || x > y { - return +1 - } - return 0 -} diff --git a/vendor/golang.org/x/exp/slices/slices.go b/vendor/golang.org/x/exp/slices/slices.go deleted file mode 100644 index 46ceac3439..0000000000 --- a/vendor/golang.org/x/exp/slices/slices.go +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package slices defines various functions useful with slices of any type. -package slices - -import ( - "unsafe" - - "golang.org/x/exp/constraints" -) - -// Equal reports whether two slices are equal: the same length and all -// elements equal. If the lengths are different, Equal returns false. -// Otherwise, the elements are compared in increasing index order, and the -// comparison stops at the first unequal pair. -// Floating point NaNs are not considered equal. -func Equal[S ~[]E, E comparable](s1, s2 S) bool { - if len(s1) != len(s2) { - return false - } - for i := range s1 { - if s1[i] != s2[i] { - return false - } - } - return true -} - -// EqualFunc reports whether two slices are equal using an equality -// function on each pair of elements. If the lengths are different, -// EqualFunc returns false. Otherwise, the elements are compared in -// increasing index order, and the comparison stops at the first index -// for which eq returns false. -func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool { - if len(s1) != len(s2) { - return false - } - for i, v1 := range s1 { - v2 := s2[i] - if !eq(v1, v2) { - return false - } - } - return true -} - -// Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair -// of elements. The elements are compared sequentially, starting at index 0, -// until one element is not equal to the other. -// The result of comparing the first non-matching elements is returned. -// If both slices are equal until one of them ends, the shorter slice is -// considered less than the longer one. -// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. -func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmpCompare(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 -} - -// CompareFunc is like [Compare] but uses a custom comparison function on each -// pair of elements. -// The result is the first non-zero result of cmp; if cmp always -// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2), -// and +1 if len(s1) > len(s2). -func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmp(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 -} - -// Index returns the index of the first occurrence of v in s, -// or -1 if not present. -func Index[S ~[]E, E comparable](s S, v E) int { - for i := range s { - if v == s[i] { - return i - } - } - return -1 -} - -// IndexFunc returns the first index i satisfying f(s[i]), -// or -1 if none do. -func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int { - for i := range s { - if f(s[i]) { - return i - } - } - return -1 -} - -// Contains reports whether v is present in s. -func Contains[S ~[]E, E comparable](s S, v E) bool { - return Index(s, v) >= 0 -} - -// ContainsFunc reports whether at least one -// element e of s satisfies f(e). -func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool { - return IndexFunc(s, f) >= 0 -} - -// Insert inserts the values v... into s at index i, -// returning the modified slice. -// The elements at s[i:] are shifted up to make room. -// In the returned slice r, r[i] == v[0], -// and r[i+len(v)] == value originally at r[i]. -// Insert panics if i is out of range. -// This function is O(len(s) + len(v)). -func Insert[S ~[]E, E any](s S, i int, v ...E) S { - m := len(v) - if m == 0 { - return s - } - n := len(s) - if i == n { - return append(s, v...) - } - if n+m > cap(s) { - // Use append rather than make so that we bump the size of - // the slice up to the next storage class. - // This is what Grow does but we don't call Grow because - // that might copy the values twice. - s2 := append(s[:i], make(S, n+m-i)...) - copy(s2[i:], v) - copy(s2[i+m:], s[i:]) - return s2 - } - s = s[:n+m] - - // before: - // s: aaaaaaaabbbbccccccccdddd - // ^ ^ ^ ^ - // i i+m n n+m - // after: - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // - // a are the values that don't move in s. - // v are the values copied in from v. - // b and c are the values from s that are shifted up in index. - // d are the values that get overwritten, never to be seen again. - - if !overlaps(v, s[i+m:]) { - // Easy case - v does not overlap either the c or d regions. - // (It might be in some of a or b, or elsewhere entirely.) - // The data we copy up doesn't write to v at all, so just do it. - - copy(s[i+m:], s[i:]) - - // Now we have - // s: aaaaaaaabbbbbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // Note the b values are duplicated. - - copy(s[i:], v) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s - } - - // The hard case - v overlaps c or d. We can't just shift up - // the data because we'd move or clobber the values we're trying - // to insert. - // So instead, write v on top of d, then rotate. - copy(s[n:], v) - - // Now we have - // s: aaaaaaaabbbbccccccccvvvv - // ^ ^ ^ ^ - // i i+m n n+m - - rotateRight(s[i:], m) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s -} - -// clearSlice sets all elements up to the length of s to the zero value of E. -// We may use the builtin clear func instead, and remove clearSlice, when upgrading -// to Go 1.21+. -func clearSlice[S ~[]E, E any](s S) { - var zero E - for i := range s { - s[i] = zero - } -} - -// Delete removes the elements s[i:j] from s, returning the modified slice. -// Delete panics if j > len(s) or s[i:j] is not a valid slice of s. -// Delete is O(len(s)-i), so if many items must be deleted, it is better to -// make a single call deleting them all together than to delete one at a time. -// Delete zeroes the elements s[len(s)-(j-i):len(s)]. -func Delete[S ~[]E, E any](s S, i, j int) S { - _ = s[i:j:len(s)] // bounds check - - if i == j { - return s - } - - oldlen := len(s) - s = append(s[:i], s[j:]...) - clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC - return s -} - -// DeleteFunc removes any elements from s for which del returns true, -// returning the modified slice. -// DeleteFunc zeroes the elements between the new length and the original length. -func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { - i := IndexFunc(s, del) - if i == -1 { - return s - } - // Don't start copying elements until we find one to delete. - for j := i + 1; j < len(s); j++ { - if v := s[j]; !del(v) { - s[i] = v - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// Replace replaces the elements s[i:j] by the given v, and returns the -// modified slice. Replace panics if s[i:j] is not a valid slice of s. -// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length. -func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { - _ = s[i:j] // verify that i:j is a valid subslice - - if i == j { - return Insert(s, i, v...) - } - if j == len(s) { - return append(s[:i], v...) - } - - tot := len(s[:i]) + len(v) + len(s[j:]) - if tot > cap(s) { - // Too big to fit, allocate and copy over. - s2 := append(s[:i], make(S, tot-i)...) // See Insert - copy(s2[i:], v) - copy(s2[i+len(v):], s[j:]) - return s2 - } - - r := s[:tot] - - if i+len(v) <= j { - // Easy, as v fits in the deleted portion. - copy(r[i:], v) - if i+len(v) != j { - copy(r[i+len(v):], s[j:]) - } - clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC - return r - } - - // We are expanding (v is bigger than j-i). - // The situation is something like this: - // (example has i=4,j=8,len(s)=16,len(v)=6) - // s: aaaaxxxxbbbbbbbbyy - // ^ ^ ^ ^ - // i j len(s) tot - // a: prefix of s - // x: deleted range - // b: more of s - // y: area to expand into - - if !overlaps(r[i+len(v):], v) { - // Easy, as v is not clobbered by the first copy. - copy(r[i+len(v):], s[j:]) - copy(r[i:], v) - return r - } - - // This is a situation where we don't have a single place to which - // we can copy v. Parts of it need to go to two different places. - // We want to copy the prefix of v into y and the suffix into x, then - // rotate |y| spots to the right. - // - // v[2:] v[:2] - // | | - // s: aaaavvvvbbbbbbbbvv - // ^ ^ ^ ^ - // i j len(s) tot - // - // If either of those two destinations don't alias v, then we're good. - y := len(v) - (j - i) // length of y portion - - if !overlaps(r[i:j], v) { - copy(r[i:j], v[y:]) - copy(r[len(s):], v[:y]) - rotateRight(r[i:], y) - return r - } - if !overlaps(r[len(s):], v) { - copy(r[len(s):], v[:y]) - copy(r[i:j], v[y:]) - rotateRight(r[i:], y) - return r - } - - // Now we know that v overlaps both x and y. - // That means that the entirety of b is *inside* v. - // So we don't need to preserve b at all; instead we - // can copy v first, then copy the b part of v out of - // v to the right destination. - k := startIdx(v, s[j:]) - copy(r[i:], v) - copy(r[i+len(v):], r[i+k:]) - return r -} - -// Clone returns a copy of the slice. -// The elements are copied using assignment, so this is a shallow clone. -func Clone[S ~[]E, E any](s S) S { - // Preserve nil in case it matters. - if s == nil { - return nil - } - return append(S([]E{}), s...) -} - -// Compact replaces consecutive runs of equal elements with a single copy. -// This is like the uniq command found on Unix. -// Compact modifies the contents of the slice s and returns the modified slice, -// which may have a smaller length. -// Compact zeroes the elements between the new length and the original length. -func Compact[S ~[]E, E comparable](s S) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if s[k] != s[k-1] { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// CompactFunc is like [Compact] but uses an equality function to compare elements. -// For runs of elements that compare equal, CompactFunc keeps the first one. -// CompactFunc zeroes the elements between the new length and the original length. -func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if !eq(s[k], s[k-1]) { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// Grow increases the slice's capacity, if necessary, to guarantee space for -// another n elements. After Grow(n), at least n elements can be appended -// to the slice without another allocation. If n is negative or too large to -// allocate the memory, Grow panics. -func Grow[S ~[]E, E any](s S, n int) S { - if n < 0 { - panic("cannot be negative") - } - if n -= cap(s) - len(s); n > 0 { - // TODO(https://go.dev/issue/53888): Make using []E instead of S - // to workaround a compiler bug where the runtime.growslice optimization - // does not take effect. Revert when the compiler is fixed. - s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)] - } - return s -} - -// Clip removes unused capacity from the slice, returning s[:len(s):len(s)]. -func Clip[S ~[]E, E any](s S) S { - return s[:len(s):len(s)] -} - -// Rotation algorithm explanation: -// -// rotate left by 2 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join first parts -// 89234567 01 -// recursively rotate first left part by 2 -// 23456789 01 -// join at the end -// 2345678901 -// -// rotate left by 8 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join last parts -// 89 23456701 -// recursively rotate second part left by 6 -// 89 01234567 -// join at the end -// 8901234567 - -// TODO: There are other rotate algorithms. -// This algorithm has the desirable property that it moves each element exactly twice. -// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes. -// The follow-cycles algorithm can be 1-write but it is not very cache friendly. - -// rotateLeft rotates b left by n spaces. -// s_final[i] = s_orig[i+r], wrapping around. -func rotateLeft[E any](s []E, r int) { - for r != 0 && r != len(s) { - if r*2 <= len(s) { - swap(s[:r], s[len(s)-r:]) - s = s[:len(s)-r] - } else { - swap(s[:len(s)-r], s[r:]) - s, r = s[len(s)-r:], r*2-len(s) - } - } -} -func rotateRight[E any](s []E, r int) { - rotateLeft(s, len(s)-r) -} - -// swap swaps the contents of x and y. x and y must be equal length and disjoint. -func swap[E any](x, y []E) { - for i := 0; i < len(x); i++ { - x[i], y[i] = y[i], x[i] - } -} - -// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap. -func overlaps[E any](a, b []E) bool { - if len(a) == 0 || len(b) == 0 { - return false - } - elemSize := unsafe.Sizeof(a[0]) - if elemSize == 0 { - return false - } - // TODO: use a runtime/unsafe facility once one becomes available. See issue 12445. - // Also see crypto/internal/alias/alias.go:AnyOverlap - return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) && - uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1) -} - -// startIdx returns the index in haystack where the needle starts. -// prerequisite: the needle must be aliased entirely inside the haystack. -func startIdx[E any](haystack, needle []E) int { - p := &needle[0] - for i := range haystack { - if p == &haystack[i] { - return i - } - } - // TODO: what if the overlap is by a non-integral number of Es? - panic("needle not found") -} - -// Reverse reverses the elements of the slice in place. -func Reverse[S ~[]E, E any](s S) { - for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { - s[i], s[j] = s[j], s[i] - } -} diff --git a/vendor/golang.org/x/exp/slices/sort.go b/vendor/golang.org/x/exp/slices/sort.go deleted file mode 100644 index f58bbc7ba4..0000000000 --- a/vendor/golang.org/x/exp/slices/sort.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp - -package slices - -import ( - "math/bits" - - "golang.org/x/exp/constraints" -) - -// Sort sorts a slice of any ordered type in ascending order. -// When sorting floating-point numbers, NaNs are ordered before other values. -func Sort[S ~[]E, E constraints.Ordered](x S) { - n := len(x) - pdqsortOrdered(x, 0, n, bits.Len(uint(n))) -} - -// SortFunc sorts the slice x in ascending order as determined by the cmp -// function. This sort is not guaranteed to be stable. -// cmp(a, b) should return a negative number when a < b, a positive number when -// a > b and zero when a == b or when a is not comparable to b in the sense -// of the formal definition of Strict Weak Ordering. -// -// SortFunc requires that cmp is a strict weak ordering. -// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. -// To indicate 'uncomparable', return 0 from the function. -func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - n := len(x) - pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp) -} - -// SortStableFunc sorts the slice x while keeping the original order of equal -// elements, using cmp to compare elements in the same way as [SortFunc]. -func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - stableCmpFunc(x, len(x), cmp) -} - -// IsSorted reports whether x is sorted in ascending order. -func IsSorted[S ~[]E, E constraints.Ordered](x S) bool { - for i := len(x) - 1; i > 0; i-- { - if cmpLess(x[i], x[i-1]) { - return false - } - } - return true -} - -// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the -// comparison function as defined by [SortFunc]. -func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool { - for i := len(x) - 1; i > 0; i-- { - if cmp(x[i], x[i-1]) < 0 { - return false - } - } - return true -} - -// Min returns the minimal value in x. It panics if x is empty. -// For floating-point numbers, Min propagates NaNs (any NaN value in x -// forces the output to be NaN). -func Min[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Min: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = min(m, x[i]) - } - return m -} - -// MinFunc returns the minimal value in x, using cmp to compare elements. -// It panics if x is empty. If there is more than one minimal element -// according to the cmp function, MinFunc returns the first one. -func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MinFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) < 0 { - m = x[i] - } - } - return m -} - -// Max returns the maximal value in x. It panics if x is empty. -// For floating-point E, Max propagates NaNs (any NaN value in x -// forces the output to be NaN). -func Max[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Max: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = max(m, x[i]) - } - return m -} - -// MaxFunc returns the maximal value in x, using cmp to compare elements. -// It panics if x is empty. If there is more than one maximal element -// according to the cmp function, MaxFunc returns the first one. -func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MaxFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) > 0 { - m = x[i] - } - } - return m -} - -// BinarySearch searches for target in a sorted slice and returns the position -// where target is found, or the position where target would appear in the -// sort order; it also returns a bool saying whether the target is really found -// in the slice. The slice must be sorted in increasing order. -func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) { - // Inlining is faster than calling BinarySearchFunc with a lambda. - n := len(x) - // Define x[-1] < target and x[n] >= target. - // Invariant: x[i-1] < target, x[j] >= target. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i ≤ h < j - if cmpLess(x[h], target) { - i = h + 1 // preserves x[i-1] < target - } else { - j = h // preserves x[j] >= target - } - } - // i == j, x[i-1] < target, and x[j] (= x[i]) >= target => answer is i. - return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target))) -} - -// BinarySearchFunc works like [BinarySearch], but uses a custom comparison -// function. The slice must be sorted in increasing order, where "increasing" -// is defined by cmp. cmp should return 0 if the slice element matches -// the target, a negative number if the slice element precedes the target, -// or a positive number if the slice element follows the target. -// cmp must implement the same ordering as the slice, such that if -// cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice. -func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) { - n := len(x) - // Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 . - // Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i ≤ h < j - if cmp(x[h], target) < 0 { - i = h + 1 // preserves cmp(x[i - 1], target) < 0 - } else { - j = h // preserves cmp(x[j], target) >= 0 - } - } - // i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0 => answer is i. - return i, i < n && cmp(x[i], target) == 0 -} - -type sortedHint int // hint for pdqsort when choosing the pivot - -const ( - unknownHint sortedHint = iota - increasingHint - decreasingHint -) - -// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf -type xorshift uint64 - -func (r *xorshift) Next() uint64 { - *r ^= *r << 13 - *r ^= *r >> 17 - *r ^= *r << 5 - return uint64(*r) -} - -func nextPowerOfTwo(length int) uint { - return 1 << bits.Len(uint(length)) -} - -// isNaN reports whether x is a NaN without requiring the math package. -// This will always return false if T is not floating-point. -func isNaN[T constraints.Ordered](x T) bool { - return x != x -} diff --git a/vendor/golang.org/x/exp/slices/zsortanyfunc.go b/vendor/golang.org/x/exp/slices/zsortanyfunc.go deleted file mode 100644 index 06f2c7a248..0000000000 --- a/vendor/golang.org/x/exp/slices/zsortanyfunc.go +++ /dev/null @@ -1,479 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -// insertionSortCmpFunc sorts data[a:b] using insertion sort. -func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownCmpFunc implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) { - child++ - } - if !(cmp(data[first+root], data[first+child]) < 0) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownCmpFunc(data, i, hi, first, cmp) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownCmpFunc(data, lo, i, first, cmp) - } -} - -// pdqsortCmpFunc sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortCmpFunc(data, a, b, cmp) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortCmpFunc(data, a, b, cmp) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsCmpFunc(data, a, b, cmp) - limit-- - } - - pivot, hint := choosePivotCmpFunc(data, a, b, cmp) - if hint == decreasingHint { - reverseRangeCmpFunc(data, a, b, cmp) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortCmpFunc(data, a, b, cmp) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) { - mid := partitionEqualCmpFunc(data, a, b, pivot, cmp) - a = mid - continue - } - - mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortCmpFunc(data, a, mid, limit, cmp) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortCmpFunc(data, mid+1, b, limit, cmp) - b = mid - } - } -} - -// partitionCmpFunc does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !(cmp(data[a], data[i]) < 0) { - i++ - } - for i <= j && (cmp(data[a], data[j]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !(cmp(data[i], data[i-1]) < 0) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotCmpFunc chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentCmpFunc(data, i, &swaps, cmp) - j = medianAdjacentCmpFunc(data, j, &swaps, cmp) - k = medianAdjacentCmpFunc(data, k, &swaps, cmp) - } - // Find the median among i, j, k and stores it into j. - j = medianCmpFunc(data, i, j, k, &swaps, cmp) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) { - if cmp(data[b], data[a]) < 0 { - *swaps++ - return b, a - } - return a, b -} - -// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int { - a, b = order2CmpFunc(data, a, b, swaps, cmp) - b, c = order2CmpFunc(data, b, c, swaps, cmp) - a, b = order2CmpFunc(data, a, b, swaps, cmp) - return b -} - -// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int { - return medianCmpFunc(data, a-1, a, a+1, swaps, cmp) -} - -func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortCmpFunc(data, a, b, cmp) - a = b - b += blockSize - } - insertionSortCmpFunc(data, a, n, cmp) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeCmpFunc(data, a, a+blockSize, b, cmp) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeCmpFunc(data, a, m, n, cmp) - } - blockSize *= 2 - } -} - -// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmp(data[h], data[a]) < 0 { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !(cmp(data[m], data[h]) < 0) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !(cmp(data[p-c], data[c]) < 0) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateCmpFunc(data, start, m, end, cmp) - } - if a < start && start < mid { - symMergeCmpFunc(data, a, start, mid, cmp) - } - if mid < end && end < b { - symMergeCmpFunc(data, mid, end, b, cmp) - } -} - -// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeCmpFunc(data, m-i, m, j, cmp) - i -= j - } else { - swapRangeCmpFunc(data, m-i, m+j-i, i, cmp) - j -= i - } - } - // i == j - swapRangeCmpFunc(data, m-i, m, i, cmp) -} diff --git a/vendor/golang.org/x/exp/slices/zsortordered.go b/vendor/golang.org/x/exp/slices/zsortordered.go deleted file mode 100644 index 99b47c3986..0000000000 --- a/vendor/golang.org/x/exp/slices/zsortordered.go +++ /dev/null @@ -1,481 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// insertionSortOrdered sorts data[a:b] using insertion sort. -func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && cmpLess(data[j], data[j-1]); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownOrdered implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) { - child++ - } - if !cmpLess(data[first+root], data[first+child]) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownOrdered(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownOrdered(data, lo, i, first) - } -} - -// pdqsortOrdered sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortOrdered(data, a, b) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortOrdered(data, a, b) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsOrdered(data, a, b) - limit-- - } - - pivot, hint := choosePivotOrdered(data, a, b) - if hint == decreasingHint { - reverseRangeOrdered(data, a, b) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortOrdered(data, a, b) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !cmpLess(data[a-1], data[pivot]) { - mid := partitionEqualOrdered(data, a, b, pivot) - a = mid - continue - } - - mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortOrdered(data, a, mid, limit) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortOrdered(data, mid+1, b, limit) - b = mid - } - } -} - -// partitionOrdered does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !cmpLess(data[a], data[i]) { - i++ - } - for i <= j && cmpLess(data[a], data[j]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !cmpLess(data[i], data[i-1]) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsOrdered scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotOrdered chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,∞): uses the Tukey ninther method. -func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentOrdered(data, i, &swaps) - j = medianAdjacentOrdered(data, j, &swaps) - k = medianAdjacentOrdered(data, k, &swaps) - } - // Find the median among i, j, k and stores it into j. - j = medianOrdered(data, i, j, k, &swaps) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { - if cmpLess(data[b], data[a]) { - *swaps++ - return b, a - } - return a, b -} - -// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { - a, b = order2Ordered(data, a, b, swaps) - b, c = order2Ordered(data, b, c, swaps) - a, b = order2Ordered(data, a, b, swaps) - return b -} - -// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { - return medianOrdered(data, a-1, a, a+1, swaps) -} - -func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableOrdered[E constraints.Ordered](data []E, n int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortOrdered(data, a, b) - a = b - b += blockSize - } - insertionSortOrdered(data, a, n) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeOrdered(data, a, a+blockSize, b) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeOrdered(data, a, m, n) - } - blockSize *= 2 - } -} - -// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmpLess(data[h], data[a]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !cmpLess(data[m], data[h]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !cmpLess(data[p-c], data[c]) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateOrdered(data, start, m, end) - } - if a < start && start < mid { - symMergeOrdered(data, a, start, mid) - } - if mid < end && end < b { - symMergeOrdered(data, mid, end, b) - } -} - -// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeOrdered(data, m-i, m, j) - i -= j - } else { - swapRangeOrdered(data, m-i, m+j-i, i) - j -= i - } - } - // i == j - swapRangeOrdered(data, m-i, m, i) -} diff --git a/vendor/golang.org/x/exp/slog/attr.go b/vendor/golang.org/x/exp/slog/attr.go deleted file mode 100644 index a180d0e1d3..0000000000 --- a/vendor/golang.org/x/exp/slog/attr.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "time" -) - -// An Attr is a key-value pair. -type Attr struct { - Key string - Value Value -} - -// String returns an Attr for a string value. -func String(key, value string) Attr { - return Attr{key, StringValue(value)} -} - -// Int64 returns an Attr for an int64. -func Int64(key string, value int64) Attr { - return Attr{key, Int64Value(value)} -} - -// Int converts an int to an int64 and returns -// an Attr with that value. -func Int(key string, value int) Attr { - return Int64(key, int64(value)) -} - -// Uint64 returns an Attr for a uint64. -func Uint64(key string, v uint64) Attr { - return Attr{key, Uint64Value(v)} -} - -// Float64 returns an Attr for a floating-point number. -func Float64(key string, v float64) Attr { - return Attr{key, Float64Value(v)} -} - -// Bool returns an Attr for a bool. -func Bool(key string, v bool) Attr { - return Attr{key, BoolValue(v)} -} - -// Time returns an Attr for a time.Time. -// It discards the monotonic portion. -func Time(key string, v time.Time) Attr { - return Attr{key, TimeValue(v)} -} - -// Duration returns an Attr for a time.Duration. -func Duration(key string, v time.Duration) Attr { - return Attr{key, DurationValue(v)} -} - -// Group returns an Attr for a Group Value. -// The first argument is the key; the remaining arguments -// are converted to Attrs as in [Logger.Log]. -// -// Use Group to collect several key-value pairs under a single -// key on a log line, or as the result of LogValue -// in order to log a single value as multiple Attrs. -func Group(key string, args ...any) Attr { - return Attr{key, GroupValue(argsToAttrSlice(args)...)} -} - -func argsToAttrSlice(args []any) []Attr { - var ( - attr Attr - attrs []Attr - ) - for len(args) > 0 { - attr, args = argsToAttr(args) - attrs = append(attrs, attr) - } - return attrs -} - -// Any returns an Attr for the supplied value. -// See [Value.AnyValue] for how values are treated. -func Any(key string, value any) Attr { - return Attr{key, AnyValue(value)} -} - -// Equal reports whether a and b have equal keys and values. -func (a Attr) Equal(b Attr) bool { - return a.Key == b.Key && a.Value.Equal(b.Value) -} - -func (a Attr) String() string { - return fmt.Sprintf("%s=%s", a.Key, a.Value) -} - -// isEmpty reports whether a has an empty key and a nil value. -// That can be written as Attr{} or Any("", nil). -func (a Attr) isEmpty() bool { - return a.Key == "" && a.Value.num == 0 && a.Value.any == nil -} diff --git a/vendor/golang.org/x/exp/slog/doc.go b/vendor/golang.org/x/exp/slog/doc.go deleted file mode 100644 index 4beaf86748..0000000000 --- a/vendor/golang.org/x/exp/slog/doc.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package slog provides structured logging, -in which log records include a message, -a severity level, and various other attributes -expressed as key-value pairs. - -It defines a type, [Logger], -which provides several methods (such as [Logger.Info] and [Logger.Error]) -for reporting events of interest. - -Each Logger is associated with a [Handler]. -A Logger output method creates a [Record] from the method arguments -and passes it to the Handler, which decides how to handle it. -There is a default Logger accessible through top-level functions -(such as [Info] and [Error]) that call the corresponding Logger methods. - -A log record consists of a time, a level, a message, and a set of key-value -pairs, where the keys are strings and the values may be of any type. -As an example, - - slog.Info("hello", "count", 3) - -creates a record containing the time of the call, -a level of Info, the message "hello", and a single -pair with key "count" and value 3. - -The [Info] top-level function calls the [Logger.Info] method on the default Logger. -In addition to [Logger.Info], there are methods for Debug, Warn and Error levels. -Besides these convenience methods for common levels, -there is also a [Logger.Log] method which takes the level as an argument. -Each of these methods has a corresponding top-level function that uses the -default logger. - -The default handler formats the log record's message, time, level, and attributes -as a string and passes it to the [log] package. - - 2022/11/08 15:28:26 INFO hello count=3 - -For more control over the output format, create a logger with a different handler. -This statement uses [New] to create a new logger with a TextHandler -that writes structured records in text form to standard error: - - logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) - -[TextHandler] output is a sequence of key=value pairs, easily and unambiguously -parsed by machine. This statement: - - logger.Info("hello", "count", 3) - -produces this output: - - time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3 - -The package also provides [JSONHandler], whose output is line-delimited JSON: - - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - logger.Info("hello", "count", 3) - -produces this output: - - {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3} - -Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions]. -There are options for setting the minimum level (see Levels, below), -displaying the source file and line of the log call, and -modifying attributes before they are logged. - -Setting a logger as the default with - - slog.SetDefault(logger) - -will cause the top-level functions like [Info] to use it. -[SetDefault] also updates the default logger used by the [log] package, -so that existing applications that use [log.Printf] and related functions -will send log records to the logger's handler without needing to be rewritten. - -Some attributes are common to many log calls. -For example, you may wish to include the URL or trace identifier of a server request -with all log events arising from the request. -Rather than repeat the attribute with every log call, you can use [Logger.With] -to construct a new Logger containing the attributes: - - logger2 := logger.With("url", r.URL) - -The arguments to With are the same key-value pairs used in [Logger.Info]. -The result is a new Logger with the same handler as the original, but additional -attributes that will appear in the output of every call. - -# Levels - -A [Level] is an integer representing the importance or severity of a log event. -The higher the level, the more severe the event. -This package defines constants for the most common levels, -but any int can be used as a level. - -In an application, you may wish to log messages only at a certain level or greater. -One common configuration is to log messages at Info or higher levels, -suppressing debug logging until it is needed. -The built-in handlers can be configured with the minimum level to output by -setting [HandlerOptions.Level]. -The program's `main` function typically does this. -The default value is LevelInfo. - -Setting the [HandlerOptions.Level] field to a [Level] value -fixes the handler's minimum level throughout its lifetime. -Setting it to a [LevelVar] allows the level to be varied dynamically. -A LevelVar holds a Level and is safe to read or write from multiple -goroutines. -To vary the level dynamically for an entire program, first initialize -a global LevelVar: - - var programLevel = new(slog.LevelVar) // Info by default - -Then use the LevelVar to construct a handler, and make it the default: - - h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) - slog.SetDefault(slog.New(h)) - -Now the program can change its logging level with a single statement: - - programLevel.Set(slog.LevelDebug) - -# Groups - -Attributes can be collected into groups. -A group has a name that is used to qualify the names of its attributes. -How this qualification is displayed depends on the handler. -[TextHandler] separates the group and attribute names with a dot. -[JSONHandler] treats each group as a separate JSON object, with the group name as the key. - -Use [Group] to create a Group attribute from a name and a list of key-value pairs: - - slog.Group("request", - "method", r.Method, - "url", r.URL) - -TextHandler would display this group as - - request.method=GET request.url=http://example.com - -JSONHandler would display it as - - "request":{"method":"GET","url":"http://example.com"} - -Use [Logger.WithGroup] to qualify all of a Logger's output -with a group name. Calling WithGroup on a Logger results in a -new Logger with the same Handler as the original, but with all -its attributes qualified by the group name. - -This can help prevent duplicate attribute keys in large systems, -where subsystems might use the same keys. -Pass each subsystem a different Logger with its own group name so that -potential duplicates are qualified: - - logger := slog.Default().With("id", systemID) - parserLogger := logger.WithGroup("parser") - parseInput(input, parserLogger) - -When parseInput logs with parserLogger, its keys will be qualified with "parser", -so even if it uses the common key "id", the log line will have distinct keys. - -# Contexts - -Some handlers may wish to include information from the [context.Context] that is -available at the call site. One example of such information -is the identifier for the current span when tracing is enabled. - -The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first -argument, as do their corresponding top-level functions. - -Although the convenience methods on Logger (Info and so on) and the -corresponding top-level functions do not take a context, the alternatives ending -in "Context" do. For example, - - slog.InfoContext(ctx, "message") - -It is recommended to pass a context to an output method if one is available. - -# Attrs and Values - -An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as -alternating keys and values. The statement - - slog.Info("hello", slog.Int("count", 3)) - -behaves the same as - - slog.Info("hello", "count", 3) - -There are convenience constructors for [Attr] such as [Int], [String], and [Bool] -for common types, as well as the function [Any] for constructing Attrs of any -type. - -The value part of an Attr is a type called [Value]. -Like an [any], a Value can hold any Go value, -but it can represent typical values, including all numbers and strings, -without an allocation. - -For the most efficient log output, use [Logger.LogAttrs]. -It is similar to [Logger.Log] but accepts only Attrs, not alternating -keys and values; this allows it, too, to avoid allocation. - -The call - - logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3)) - -is the most efficient way to achieve the same output as - - slog.Info("hello", "count", 3) - -# Customizing a type's logging behavior - -If a type implements the [LogValuer] interface, the [Value] returned from its LogValue -method is used for logging. You can use this to control how values of the type -appear in logs. For example, you can redact secret information like passwords, -or gather a struct's fields in a Group. See the examples under [LogValuer] for -details. - -A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve] -method handles these cases carefully, avoiding infinite loops and unbounded recursion. -Handler authors and others may wish to use Value.Resolve instead of calling LogValue directly. - -# Wrapping output methods - -The logger functions use reflection over the call stack to find the file name -and line number of the logging call within the application. This can produce -incorrect source information for functions that wrap slog. For instance, if you -define this function in file mylog.go: - - func Infof(format string, args ...any) { - slog.Default().Info(fmt.Sprintf(format, args...)) - } - -and you call it like this in main.go: - - Infof(slog.Default(), "hello, %s", "world") - -then slog will report the source file as mylog.go, not main.go. - -A correct implementation of Infof will obtain the source location -(pc) and pass it to NewRecord. -The Infof function in the package-level example called "wrapping" -demonstrates how to do this. - -# Working with Records - -Sometimes a Handler will need to modify a Record -before passing it on to another Handler or backend. -A Record contains a mixture of simple public fields (e.g. Time, Level, Message) -and hidden fields that refer to state (such as attributes) indirectly. This -means that modifying a simple copy of a Record (e.g. by calling -[Record.Add] or [Record.AddAttrs] to add attributes) -may have unexpected effects on the original. -Before modifying a Record, use [Clone] to -create a copy that shares no state with the original, -or create a new Record with [NewRecord] -and build up its Attrs by traversing the old ones with [Record.Attrs]. - -# Performance considerations - -If profiling your application demonstrates that logging is taking significant time, -the following suggestions may help. - -If many log lines have a common attribute, use [Logger.With] to create a Logger with -that attribute. The built-in handlers will format that attribute only once, at the -call to [Logger.With]. The [Handler] interface is designed to allow that optimization, -and a well-written Handler should take advantage of it. - -The arguments to a log call are always evaluated, even if the log event is discarded. -If possible, defer computation so that it happens only if the value is actually logged. -For example, consider the call - - slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily - -The URL.String method will be called even if the logger discards Info-level events. -Instead, pass the URL directly: - - slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed - -The built-in [TextHandler] will call its String method, but only -if the log event is enabled. -Avoiding the call to String also preserves the structure of the underlying value. -For example [JSONHandler] emits the components of the parsed URL as a JSON object. -If you want to avoid eagerly paying the cost of the String call -without causing the handler to potentially inspect the structure of the value, -wrap the value in a fmt.Stringer implementation that hides its Marshal methods. - -You can also use the [LogValuer] interface to avoid unnecessary work in disabled log -calls. Say you need to log some expensive value: - - slog.Debug("frobbing", "value", computeExpensiveValue(arg)) - -Even if this line is disabled, computeExpensiveValue will be called. -To avoid that, define a type implementing LogValuer: - - type expensive struct { arg int } - - func (e expensive) LogValue() slog.Value { - return slog.AnyValue(computeExpensiveValue(e.arg)) - } - -Then use a value of that type in log calls: - - slog.Debug("frobbing", "value", expensive{arg}) - -Now computeExpensiveValue will only be called when the line is enabled. - -The built-in handlers acquire a lock before calling [io.Writer.Write] -to ensure that each record is written in one piece. User-defined -handlers are responsible for their own locking. -*/ -package slog diff --git a/vendor/golang.org/x/exp/slog/handler.go b/vendor/golang.org/x/exp/slog/handler.go deleted file mode 100644 index bd635cb818..0000000000 --- a/vendor/golang.org/x/exp/slog/handler.go +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "fmt" - "io" - "reflect" - "strconv" - "sync" - "time" - - "golang.org/x/exp/slices" - "golang.org/x/exp/slog/internal/buffer" -) - -// A Handler handles log records produced by a Logger.. -// -// A typical handler may print log records to standard error, -// or write them to a file or database, or perhaps augment them -// with additional attributes and pass them on to another handler. -// -// Any of the Handler's methods may be called concurrently with itself -// or with other methods. It is the responsibility of the Handler to -// manage this concurrency. -// -// Users of the slog package should not invoke Handler methods directly. -// They should use the methods of [Logger] instead. -type Handler interface { - // Enabled reports whether the handler handles records at the given level. - // The handler ignores records whose level is lower. - // It is called early, before any arguments are processed, - // to save effort if the log event should be discarded. - // If called from a Logger method, the first argument is the context - // passed to that method, or context.Background() if nil was passed - // or the method does not take a context. - // The context is passed so Enabled can use its values - // to make a decision. - Enabled(context.Context, Level) bool - - // Handle handles the Record. - // It will only be called when Enabled returns true. - // The Context argument is as for Enabled. - // It is present solely to provide Handlers access to the context's values. - // Canceling the context should not affect record processing. - // (Among other things, log messages may be necessary to debug a - // cancellation-related problem.) - // - // Handle methods that produce output should observe the following rules: - // - If r.Time is the zero time, ignore the time. - // - If r.PC is zero, ignore it. - // - Attr's values should be resolved. - // - If an Attr's key and value are both the zero value, ignore the Attr. - // This can be tested with attr.Equal(Attr{}). - // - If a group's key is empty, inline the group's Attrs. - // - If a group has no Attrs (even if it has a non-empty key), - // ignore it. - Handle(context.Context, Record) error - - // WithAttrs returns a new Handler whose attributes consist of - // both the receiver's attributes and the arguments. - // The Handler owns the slice: it may retain, modify or discard it. - WithAttrs(attrs []Attr) Handler - - // WithGroup returns a new Handler with the given group appended to - // the receiver's existing groups. - // The keys of all subsequent attributes, whether added by With or in a - // Record, should be qualified by the sequence of group names. - // - // How this qualification happens is up to the Handler, so long as - // this Handler's attribute keys differ from those of another Handler - // with a different sequence of group names. - // - // A Handler should treat WithGroup as starting a Group of Attrs that ends - // at the end of the log event. That is, - // - // logger.WithGroup("s").LogAttrs(level, msg, slog.Int("a", 1), slog.Int("b", 2)) - // - // should behave like - // - // logger.LogAttrs(level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2))) - // - // If the name is empty, WithGroup returns the receiver. - WithGroup(name string) Handler -} - -type defaultHandler struct { - ch *commonHandler - // log.Output, except for testing - output func(calldepth int, message string) error -} - -func newDefaultHandler(output func(int, string) error) *defaultHandler { - return &defaultHandler{ - ch: &commonHandler{json: false}, - output: output, - } -} - -func (*defaultHandler) Enabled(_ context.Context, l Level) bool { - return l >= LevelInfo -} - -// Collect the level, attributes and message in a string and -// write it with the default log.Logger. -// Let the log.Logger handle time and file/line. -func (h *defaultHandler) Handle(ctx context.Context, r Record) error { - buf := buffer.New() - buf.WriteString(r.Level.String()) - buf.WriteByte(' ') - buf.WriteString(r.Message) - state := h.ch.newHandleState(buf, true, " ", nil) - defer state.free() - state.appendNonBuiltIns(r) - - // skip [h.output, defaultHandler.Handle, handlerWriter.Write, log.Output] - return h.output(4, buf.String()) -} - -func (h *defaultHandler) WithAttrs(as []Attr) Handler { - return &defaultHandler{h.ch.withAttrs(as), h.output} -} - -func (h *defaultHandler) WithGroup(name string) Handler { - return &defaultHandler{h.ch.withGroup(name), h.output} -} - -// HandlerOptions are options for a TextHandler or JSONHandler. -// A zero HandlerOptions consists entirely of default values. -type HandlerOptions struct { - // AddSource causes the handler to compute the source code position - // of the log statement and add a SourceKey attribute to the output. - AddSource bool - - // Level reports the minimum record level that will be logged. - // The handler discards records with lower levels. - // If Level is nil, the handler assumes LevelInfo. - // The handler calls Level.Level for each record processed; - // to adjust the minimum level dynamically, use a LevelVar. - Level Leveler - - // ReplaceAttr is called to rewrite each non-group attribute before it is logged. - // The attribute's value has been resolved (see [Value.Resolve]). - // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded. - // - // The built-in attributes with keys "time", "level", "source", and "msg" - // are passed to this function, except that time is omitted - // if zero, and source is omitted if AddSource is false. - // - // The first argument is a list of currently open groups that contain the - // Attr. It must not be retained or modified. ReplaceAttr is never called - // for Group attributes, only their contents. For example, the attribute - // list - // - // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) - // - // results in consecutive calls to ReplaceAttr with the following arguments: - // - // nil, Int("a", 1) - // []string{"g"}, Int("b", 2) - // nil, Int("c", 3) - // - // ReplaceAttr can be used to change the default keys of the built-in - // attributes, convert types (for example, to replace a `time.Time` with the - // integer seconds since the Unix epoch), sanitize personal information, or - // remove attributes from the output. - ReplaceAttr func(groups []string, a Attr) Attr -} - -// Keys for "built-in" attributes. -const ( - // TimeKey is the key used by the built-in handlers for the time - // when the log method is called. The associated Value is a [time.Time]. - TimeKey = "time" - // LevelKey is the key used by the built-in handlers for the level - // of the log call. The associated value is a [Level]. - LevelKey = "level" - // MessageKey is the key used by the built-in handlers for the - // message of the log call. The associated value is a string. - MessageKey = "msg" - // SourceKey is the key used by the built-in handlers for the source file - // and line of the log call. The associated value is a string. - SourceKey = "source" -) - -type commonHandler struct { - json bool // true => output JSON; false => output text - opts HandlerOptions - preformattedAttrs []byte - groupPrefix string // for text: prefix of groups opened in preformatting - groups []string // all groups started from WithGroup - nOpenGroups int // the number of groups opened in preformattedAttrs - mu sync.Mutex - w io.Writer -} - -func (h *commonHandler) clone() *commonHandler { - // We can't use assignment because we can't copy the mutex. - return &commonHandler{ - json: h.json, - opts: h.opts, - preformattedAttrs: slices.Clip(h.preformattedAttrs), - groupPrefix: h.groupPrefix, - groups: slices.Clip(h.groups), - nOpenGroups: h.nOpenGroups, - w: h.w, - } -} - -// enabled reports whether l is greater than or equal to the -// minimum level. -func (h *commonHandler) enabled(l Level) bool { - minLevel := LevelInfo - if h.opts.Level != nil { - minLevel = h.opts.Level.Level() - } - return l >= minLevel -} - -func (h *commonHandler) withAttrs(as []Attr) *commonHandler { - h2 := h.clone() - // Pre-format the attributes as an optimization. - prefix := buffer.New() - defer prefix.Free() - prefix.WriteString(h.groupPrefix) - state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "", prefix) - defer state.free() - if len(h2.preformattedAttrs) > 0 { - state.sep = h.attrSep() - } - state.openGroups() - for _, a := range as { - state.appendAttr(a) - } - // Remember the new prefix for later keys. - h2.groupPrefix = state.prefix.String() - // Remember how many opened groups are in preformattedAttrs, - // so we don't open them again when we handle a Record. - h2.nOpenGroups = len(h2.groups) - return h2 -} - -func (h *commonHandler) withGroup(name string) *commonHandler { - if name == "" { - return h - } - h2 := h.clone() - h2.groups = append(h2.groups, name) - return h2 -} - -func (h *commonHandler) handle(r Record) error { - state := h.newHandleState(buffer.New(), true, "", nil) - defer state.free() - if h.json { - state.buf.WriteByte('{') - } - // Built-in attributes. They are not in a group. - stateGroups := state.groups - state.groups = nil // So ReplaceAttrs sees no groups instead of the pre groups. - rep := h.opts.ReplaceAttr - // time - if !r.Time.IsZero() { - key := TimeKey - val := r.Time.Round(0) // strip monotonic to match Attr behavior - if rep == nil { - state.appendKey(key) - state.appendTime(val) - } else { - state.appendAttr(Time(key, val)) - } - } - // level - key := LevelKey - val := r.Level - if rep == nil { - state.appendKey(key) - state.appendString(val.String()) - } else { - state.appendAttr(Any(key, val)) - } - // source - if h.opts.AddSource { - state.appendAttr(Any(SourceKey, r.source())) - } - key = MessageKey - msg := r.Message - if rep == nil { - state.appendKey(key) - state.appendString(msg) - } else { - state.appendAttr(String(key, msg)) - } - state.groups = stateGroups // Restore groups passed to ReplaceAttrs. - state.appendNonBuiltIns(r) - state.buf.WriteByte('\n') - - h.mu.Lock() - defer h.mu.Unlock() - _, err := h.w.Write(*state.buf) - return err -} - -func (s *handleState) appendNonBuiltIns(r Record) { - // preformatted Attrs - if len(s.h.preformattedAttrs) > 0 { - s.buf.WriteString(s.sep) - s.buf.Write(s.h.preformattedAttrs) - s.sep = s.h.attrSep() - } - // Attrs in Record -- unlike the built-in ones, they are in groups started - // from WithGroup. - s.prefix = buffer.New() - defer s.prefix.Free() - s.prefix.WriteString(s.h.groupPrefix) - s.openGroups() - r.Attrs(func(a Attr) bool { - s.appendAttr(a) - return true - }) - if s.h.json { - // Close all open groups. - for range s.h.groups { - s.buf.WriteByte('}') - } - // Close the top-level object. - s.buf.WriteByte('}') - } -} - -// attrSep returns the separator between attributes. -func (h *commonHandler) attrSep() string { - if h.json { - return "," - } - return " " -} - -// handleState holds state for a single call to commonHandler.handle. -// The initial value of sep determines whether to emit a separator -// before the next key, after which it stays true. -type handleState struct { - h *commonHandler - buf *buffer.Buffer - freeBuf bool // should buf be freed? - sep string // separator to write before next key - prefix *buffer.Buffer // for text: key prefix - groups *[]string // pool-allocated slice of active groups, for ReplaceAttr -} - -var groupPool = sync.Pool{New: func() any { - s := make([]string, 0, 10) - return &s -}} - -func (h *commonHandler) newHandleState(buf *buffer.Buffer, freeBuf bool, sep string, prefix *buffer.Buffer) handleState { - s := handleState{ - h: h, - buf: buf, - freeBuf: freeBuf, - sep: sep, - prefix: prefix, - } - if h.opts.ReplaceAttr != nil { - s.groups = groupPool.Get().(*[]string) - *s.groups = append(*s.groups, h.groups[:h.nOpenGroups]...) - } - return s -} - -func (s *handleState) free() { - if s.freeBuf { - s.buf.Free() - } - if gs := s.groups; gs != nil { - *gs = (*gs)[:0] - groupPool.Put(gs) - } -} - -func (s *handleState) openGroups() { - for _, n := range s.h.groups[s.h.nOpenGroups:] { - s.openGroup(n) - } -} - -// Separator for group names and keys. -const keyComponentSep = '.' - -// openGroup starts a new group of attributes -// with the given name. -func (s *handleState) openGroup(name string) { - if s.h.json { - s.appendKey(name) - s.buf.WriteByte('{') - s.sep = "" - } else { - s.prefix.WriteString(name) - s.prefix.WriteByte(keyComponentSep) - } - // Collect group names for ReplaceAttr. - if s.groups != nil { - *s.groups = append(*s.groups, name) - } -} - -// closeGroup ends the group with the given name. -func (s *handleState) closeGroup(name string) { - if s.h.json { - s.buf.WriteByte('}') - } else { - (*s.prefix) = (*s.prefix)[:len(*s.prefix)-len(name)-1 /* for keyComponentSep */] - } - s.sep = s.h.attrSep() - if s.groups != nil { - *s.groups = (*s.groups)[:len(*s.groups)-1] - } -} - -// appendAttr appends the Attr's key and value using app. -// It handles replacement and checking for an empty key. -// after replacement). -func (s *handleState) appendAttr(a Attr) { - if rep := s.h.opts.ReplaceAttr; rep != nil && a.Value.Kind() != KindGroup { - var gs []string - if s.groups != nil { - gs = *s.groups - } - // Resolve before calling ReplaceAttr, so the user doesn't have to. - a.Value = a.Value.Resolve() - a = rep(gs, a) - } - a.Value = a.Value.Resolve() - // Elide empty Attrs. - if a.isEmpty() { - return - } - // Special case: Source. - if v := a.Value; v.Kind() == KindAny { - if src, ok := v.Any().(*Source); ok { - if s.h.json { - a.Value = src.group() - } else { - a.Value = StringValue(fmt.Sprintf("%s:%d", src.File, src.Line)) - } - } - } - if a.Value.Kind() == KindGroup { - attrs := a.Value.Group() - // Output only non-empty groups. - if len(attrs) > 0 { - // Inline a group with an empty key. - if a.Key != "" { - s.openGroup(a.Key) - } - for _, aa := range attrs { - s.appendAttr(aa) - } - if a.Key != "" { - s.closeGroup(a.Key) - } - } - } else { - s.appendKey(a.Key) - s.appendValue(a.Value) - } -} - -func (s *handleState) appendError(err error) { - s.appendString(fmt.Sprintf("!ERROR:%v", err)) -} - -func (s *handleState) appendKey(key string) { - s.buf.WriteString(s.sep) - if s.prefix != nil { - // TODO: optimize by avoiding allocation. - s.appendString(string(*s.prefix) + key) - } else { - s.appendString(key) - } - if s.h.json { - s.buf.WriteByte(':') - } else { - s.buf.WriteByte('=') - } - s.sep = s.h.attrSep() -} - -func (s *handleState) appendString(str string) { - if s.h.json { - s.buf.WriteByte('"') - *s.buf = appendEscapedJSONString(*s.buf, str) - s.buf.WriteByte('"') - } else { - // text - if needsQuoting(str) { - *s.buf = strconv.AppendQuote(*s.buf, str) - } else { - s.buf.WriteString(str) - } - } -} - -func (s *handleState) appendValue(v Value) { - defer func() { - if r := recover(); r != nil { - // If it panics with a nil pointer, the most likely cases are - // an encoding.TextMarshaler or error fails to guard against nil, - // in which case "" seems to be the feasible choice. - // - // Adapted from the code in fmt/print.go. - if v := reflect.ValueOf(v.any); v.Kind() == reflect.Pointer && v.IsNil() { - s.appendString("") - return - } - - // Otherwise just print the original panic message. - s.appendString(fmt.Sprintf("!PANIC: %v", r)) - } - }() - - var err error - if s.h.json { - err = appendJSONValue(s, v) - } else { - err = appendTextValue(s, v) - } - if err != nil { - s.appendError(err) - } -} - -func (s *handleState) appendTime(t time.Time) { - if s.h.json { - appendJSONTime(s, t) - } else { - writeTimeRFC3339Millis(s.buf, t) - } -} - -// This takes half the time of Time.AppendFormat. -func writeTimeRFC3339Millis(buf *buffer.Buffer, t time.Time) { - year, month, day := t.Date() - buf.WritePosIntWidth(year, 4) - buf.WriteByte('-') - buf.WritePosIntWidth(int(month), 2) - buf.WriteByte('-') - buf.WritePosIntWidth(day, 2) - buf.WriteByte('T') - hour, min, sec := t.Clock() - buf.WritePosIntWidth(hour, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(min, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(sec, 2) - ns := t.Nanosecond() - buf.WriteByte('.') - buf.WritePosIntWidth(ns/1e6, 3) - _, offsetSeconds := t.Zone() - if offsetSeconds == 0 { - buf.WriteByte('Z') - } else { - offsetMinutes := offsetSeconds / 60 - if offsetMinutes < 0 { - buf.WriteByte('-') - offsetMinutes = -offsetMinutes - } else { - buf.WriteByte('+') - } - buf.WritePosIntWidth(offsetMinutes/60, 2) - buf.WriteByte(':') - buf.WritePosIntWidth(offsetMinutes%60, 2) - } -} diff --git a/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go b/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go deleted file mode 100644 index 7786c166e0..0000000000 --- a/vendor/golang.org/x/exp/slog/internal/buffer/buffer.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package buffer provides a pool-allocated byte buffer. -package buffer - -import ( - "sync" -) - -// Buffer adapted from go/src/fmt/print.go -type Buffer []byte - -// Having an initial size gives a dramatic speedup. -var bufPool = sync.Pool{ - New: func() any { - b := make([]byte, 0, 1024) - return (*Buffer)(&b) - }, -} - -func New() *Buffer { - return bufPool.Get().(*Buffer) -} - -func (b *Buffer) Free() { - // To reduce peak allocation, return only smaller buffers to the pool. - const maxBufferSize = 16 << 10 - if cap(*b) <= maxBufferSize { - *b = (*b)[:0] - bufPool.Put(b) - } -} - -func (b *Buffer) Reset() { - *b = (*b)[:0] -} - -func (b *Buffer) Write(p []byte) (int, error) { - *b = append(*b, p...) - return len(p), nil -} - -func (b *Buffer) WriteString(s string) { - *b = append(*b, s...) -} - -func (b *Buffer) WriteByte(c byte) { - *b = append(*b, c) -} - -func (b *Buffer) WritePosInt(i int) { - b.WritePosIntWidth(i, 0) -} - -// WritePosIntWidth writes non-negative integer i to the buffer, padded on the left -// by zeroes to the given width. Use a width of 0 to omit padding. -func (b *Buffer) WritePosIntWidth(i, width int) { - // Cheap integer to fixed-width decimal ASCII. - // Copied from log/log.go. - - if i < 0 { - panic("negative int") - } - - // Assemble decimal in reverse order. - var bb [20]byte - bp := len(bb) - 1 - for i >= 10 || width > 1 { - width-- - q := i / 10 - bb[bp] = byte('0' + i - q*10) - bp-- - i = q - } - // i < 10 - bb[bp] = byte('0' + i) - b.Write(bb[bp:]) -} - -func (b *Buffer) String() string { - return string(*b) -} diff --git a/vendor/golang.org/x/exp/slog/internal/ignorepc.go b/vendor/golang.org/x/exp/slog/internal/ignorepc.go deleted file mode 100644 index d1256426ff..0000000000 --- a/vendor/golang.org/x/exp/slog/internal/ignorepc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -// If IgnorePC is true, do not invoke runtime.Callers to get the pc. -// This is solely for benchmarking the slowdown from runtime.Callers. -var IgnorePC = false diff --git a/vendor/golang.org/x/exp/slog/json_handler.go b/vendor/golang.org/x/exp/slog/json_handler.go deleted file mode 100644 index 157ada8692..0000000000 --- a/vendor/golang.org/x/exp/slog/json_handler.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "strconv" - "time" - "unicode/utf8" - - "golang.org/x/exp/slog/internal/buffer" -) - -// JSONHandler is a Handler that writes Records to an io.Writer as -// line-delimited JSON objects. -type JSONHandler struct { - *commonHandler -} - -// NewJSONHandler creates a JSONHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &JSONHandler{ - &commonHandler{ - json: true, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *JSONHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new JSONHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *JSONHandler) WithAttrs(attrs []Attr) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *JSONHandler) WithGroup(name string) Handler { - return &JSONHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a JSON object on a single line. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output as with json.Marshal. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" -// and the value is output as "FILE:LINE". -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// Values are formatted as with an [encoding/json.Encoder] with SetEscapeHTML(false), -// with two exceptions. -// -// First, an Attr whose Value is of type error is formatted as a string, by -// calling its Error method. Only errors in Attrs receive this special treatment, -// not errors embedded in structs, slices, maps or other data structures that -// are processed by the encoding/json package. -// -// Second, an encoding failure does not cause Handle to return an error. -// Instead, the error message is formatted as a string. -// -// Each call to Handle results in a single serialized call to io.Writer.Write. -func (h *JSONHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -// Adapted from time.Time.MarshalJSON to avoid allocation. -func appendJSONTime(s *handleState, t time.Time) { - if y := t.Year(); y < 0 || y >= 10000 { - // RFC 3339 is clear that years are 4 digits exactly. - // See golang.org/issue/4556#c15 for more discussion. - s.appendError(errors.New("time.Time year outside of range [0,9999]")) - } - s.buf.WriteByte('"') - *s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano) - s.buf.WriteByte('"') -} - -func appendJSONValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindInt64: - *s.buf = strconv.AppendInt(*s.buf, v.Int64(), 10) - case KindUint64: - *s.buf = strconv.AppendUint(*s.buf, v.Uint64(), 10) - case KindFloat64: - // json.Marshal is funny about floats; it doesn't - // always match strconv.AppendFloat. So just call it. - // That's expensive, but floats are rare. - if err := appendJSONMarshal(s.buf, v.Float64()); err != nil { - return err - } - case KindBool: - *s.buf = strconv.AppendBool(*s.buf, v.Bool()) - case KindDuration: - // Do what json.Marshal does. - *s.buf = strconv.AppendInt(*s.buf, int64(v.Duration()), 10) - case KindTime: - s.appendTime(v.Time()) - case KindAny: - a := v.Any() - _, jm := a.(json.Marshaler) - if err, ok := a.(error); ok && !jm { - s.appendString(err.Error()) - } else { - return appendJSONMarshal(s.buf, a) - } - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } - return nil -} - -func appendJSONMarshal(buf *buffer.Buffer, v any) error { - // Use a json.Encoder to avoid escaping HTML. - var bb bytes.Buffer - enc := json.NewEncoder(&bb) - enc.SetEscapeHTML(false) - if err := enc.Encode(v); err != nil { - return err - } - bs := bb.Bytes() - buf.Write(bs[:len(bs)-1]) // remove final newline - return nil -} - -// appendEscapedJSONString escapes s for JSON and appends it to buf. -// It does not surround the string in quotation marks. -// -// Modified from encoding/json/encode.go:encodeState.string, -// with escapeHTML set to false. -func appendEscapedJSONString(buf []byte, s string) []byte { - char := func(b byte) { buf = append(buf, b) } - str := func(s string) { buf = append(buf, s...) } - - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if safeSet[b] { - i++ - continue - } - if start < i { - str(s[start:i]) - } - char('\\') - switch b { - case '\\', '"': - char(b) - case '\n': - char('n') - case '\r': - char('r') - case '\t': - char('t') - default: - // This encodes bytes < 0x20 except for \t, \n and \r. - str(`u00`) - char(hex[b>>4]) - char(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - str(s[start:i]) - } - str(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - str(s[start:i]) - } - str(`\u202`) - char(hex[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - str(s[start:]) - } - return buf -} - -var hex = "0123456789abcdef" - -// Copied from encoding/json/tables.go. -// -// safeSet holds the value true if the ASCII character with the given array -// position can be represented inside a JSON string without any further -// escaping. -// -// All values are true except for the ASCII control characters (0-31), the -// double quote ("), and the backslash character ("\"). -var safeSet = [utf8.RuneSelf]bool{ - ' ': true, - '!': true, - '"': false, - '#': true, - '$': true, - '%': true, - '&': true, - '\'': true, - '(': true, - ')': true, - '*': true, - '+': true, - ',': true, - '-': true, - '.': true, - '/': true, - '0': true, - '1': true, - '2': true, - '3': true, - '4': true, - '5': true, - '6': true, - '7': true, - '8': true, - '9': true, - ':': true, - ';': true, - '<': true, - '=': true, - '>': true, - '?': true, - '@': true, - 'A': true, - 'B': true, - 'C': true, - 'D': true, - 'E': true, - 'F': true, - 'G': true, - 'H': true, - 'I': true, - 'J': true, - 'K': true, - 'L': true, - 'M': true, - 'N': true, - 'O': true, - 'P': true, - 'Q': true, - 'R': true, - 'S': true, - 'T': true, - 'U': true, - 'V': true, - 'W': true, - 'X': true, - 'Y': true, - 'Z': true, - '[': true, - '\\': false, - ']': true, - '^': true, - '_': true, - '`': true, - 'a': true, - 'b': true, - 'c': true, - 'd': true, - 'e': true, - 'f': true, - 'g': true, - 'h': true, - 'i': true, - 'j': true, - 'k': true, - 'l': true, - 'm': true, - 'n': true, - 'o': true, - 'p': true, - 'q': true, - 'r': true, - 's': true, - 't': true, - 'u': true, - 'v': true, - 'w': true, - 'x': true, - 'y': true, - 'z': true, - '{': true, - '|': true, - '}': true, - '~': true, - '\u007f': true, -} diff --git a/vendor/golang.org/x/exp/slog/level.go b/vendor/golang.org/x/exp/slog/level.go deleted file mode 100644 index b2365f0aa5..0000000000 --- a/vendor/golang.org/x/exp/slog/level.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "errors" - "fmt" - "strconv" - "strings" - "sync/atomic" -) - -// A Level is the importance or severity of a log event. -// The higher the level, the more important or severe the event. -type Level int - -// Level numbers are inherently arbitrary, -// but we picked them to satisfy three constraints. -// Any system can map them to another numbering scheme if it wishes. -// -// First, we wanted the default level to be Info, Since Levels are ints, Info is -// the default value for int, zero. -// - -// Second, we wanted to make it easy to use levels to specify logger verbosity. -// Since a larger level means a more severe event, a logger that accepts events -// with smaller (or more negative) level means a more verbose logger. Logger -// verbosity is thus the negation of event severity, and the default verbosity -// of 0 accepts all events at least as severe as INFO. -// -// Third, we wanted some room between levels to accommodate schemes with named -// levels between ours. For example, Google Cloud Logging defines a Notice level -// between Info and Warn. Since there are only a few of these intermediate -// levels, the gap between the numbers need not be large. Our gap of 4 matches -// OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the -// DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog -// Level range. OpenTelemetry also has the names TRACE and FATAL, which slog -// does not. But those OpenTelemetry levels can still be represented as slog -// Levels by using the appropriate integers. -// -// Names for common levels. -const ( - LevelDebug Level = -4 - LevelInfo Level = 0 - LevelWarn Level = 4 - LevelError Level = 8 -) - -// String returns a name for the level. -// If the level has a name, then that name -// in uppercase is returned. -// If the level is between named values, then -// an integer is appended to the uppercased name. -// Examples: -// -// LevelWarn.String() => "WARN" -// (LevelInfo+2).String() => "INFO+2" -func (l Level) String() string { - str := func(base string, val Level) string { - if val == 0 { - return base - } - return fmt.Sprintf("%s%+d", base, val) - } - - switch { - case l < LevelInfo: - return str("DEBUG", l-LevelDebug) - case l < LevelWarn: - return str("INFO", l-LevelInfo) - case l < LevelError: - return str("WARN", l-LevelWarn) - default: - return str("ERROR", l-LevelError) - } -} - -// MarshalJSON implements [encoding/json.Marshaler] -// by quoting the output of [Level.String]. -func (l Level) MarshalJSON() ([]byte, error) { - // AppendQuote is sufficient for JSON-encoding all Level strings. - // They don't contain any runes that would produce invalid JSON - // when escaped. - return strconv.AppendQuote(nil, l.String()), nil -} - -// UnmarshalJSON implements [encoding/json.Unmarshaler] -// It accepts any string produced by [Level.MarshalJSON], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalJSON(data []byte) error { - s, err := strconv.Unquote(string(data)) - if err != nil { - return err - } - return l.parse(s) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.String]. -func (l Level) MarshalText() ([]byte, error) { - return []byte(l.String()), nil -} - -// UnmarshalText implements [encoding.TextUnmarshaler]. -// It accepts any string produced by [Level.MarshalText], -// ignoring case. -// It also accepts numeric offsets that would result in a different string on -// output. For example, "Error-8" would marshal as "INFO". -func (l *Level) UnmarshalText(data []byte) error { - return l.parse(string(data)) -} - -func (l *Level) parse(s string) (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("slog: level string %q: %w", s, err) - } - }() - - name := s - offset := 0 - if i := strings.IndexAny(s, "+-"); i >= 0 { - name = s[:i] - offset, err = strconv.Atoi(s[i:]) - if err != nil { - return err - } - } - switch strings.ToUpper(name) { - case "DEBUG": - *l = LevelDebug - case "INFO": - *l = LevelInfo - case "WARN": - *l = LevelWarn - case "ERROR": - *l = LevelError - default: - return errors.New("unknown name") - } - *l += Level(offset) - return nil -} - -// Level returns the receiver. -// It implements Leveler. -func (l Level) Level() Level { return l } - -// A LevelVar is a Level variable, to allow a Handler level to change -// dynamically. -// It implements Leveler as well as a Set method, -// and it is safe for use by multiple goroutines. -// The zero LevelVar corresponds to LevelInfo. -type LevelVar struct { - val atomic.Int64 -} - -// Level returns v's level. -func (v *LevelVar) Level() Level { - return Level(int(v.val.Load())) -} - -// Set sets v's level to l. -func (v *LevelVar) Set(l Level) { - v.val.Store(int64(l)) -} - -func (v *LevelVar) String() string { - return fmt.Sprintf("LevelVar(%s)", v.Level()) -} - -// MarshalText implements [encoding.TextMarshaler] -// by calling [Level.MarshalText]. -func (v *LevelVar) MarshalText() ([]byte, error) { - return v.Level().MarshalText() -} - -// UnmarshalText implements [encoding.TextUnmarshaler] -// by calling [Level.UnmarshalText]. -func (v *LevelVar) UnmarshalText(data []byte) error { - var l Level - if err := l.UnmarshalText(data); err != nil { - return err - } - v.Set(l) - return nil -} - -// A Leveler provides a Level value. -// -// As Level itself implements Leveler, clients typically supply -// a Level value wherever a Leveler is needed, such as in HandlerOptions. -// Clients who need to vary the level dynamically can provide a more complex -// Leveler implementation such as *LevelVar. -type Leveler interface { - Level() Level -} diff --git a/vendor/golang.org/x/exp/slog/logger.go b/vendor/golang.org/x/exp/slog/logger.go deleted file mode 100644 index e87ec9936c..0000000000 --- a/vendor/golang.org/x/exp/slog/logger.go +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "log" - "runtime" - "sync/atomic" - "time" - - "golang.org/x/exp/slog/internal" -) - -var defaultLogger atomic.Value - -func init() { - defaultLogger.Store(New(newDefaultHandler(log.Output))) -} - -// Default returns the default Logger. -func Default() *Logger { return defaultLogger.Load().(*Logger) } - -// SetDefault makes l the default Logger. -// After this call, output from the log package's default Logger -// (as with [log.Print], etc.) will be logged at LevelInfo using l's Handler. -func SetDefault(l *Logger) { - defaultLogger.Store(l) - // If the default's handler is a defaultHandler, then don't use a handleWriter, - // or we'll deadlock as they both try to acquire the log default mutex. - // The defaultHandler will use whatever the log default writer is currently - // set to, which is correct. - // This can occur with SetDefault(Default()). - // See TestSetDefault. - if _, ok := l.Handler().(*defaultHandler); !ok { - capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0 - log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC}) - log.SetFlags(0) // we want just the log message, no time or location - } -} - -// handlerWriter is an io.Writer that calls a Handler. -// It is used to link the default log.Logger to the default slog.Logger. -type handlerWriter struct { - h Handler - level Level - capturePC bool -} - -func (w *handlerWriter) Write(buf []byte) (int, error) { - if !w.h.Enabled(context.Background(), w.level) { - return 0, nil - } - var pc uintptr - if !internal.IgnorePC && w.capturePC { - // skip [runtime.Callers, w.Write, Logger.Output, log.Print] - var pcs [1]uintptr - runtime.Callers(4, pcs[:]) - pc = pcs[0] - } - - // Remove final newline. - origLen := len(buf) // Report that the entire buf was written. - if len(buf) > 0 && buf[len(buf)-1] == '\n' { - buf = buf[:len(buf)-1] - } - r := NewRecord(time.Now(), w.level, string(buf), pc) - return origLen, w.h.Handle(context.Background(), r) -} - -// A Logger records structured information about each call to its -// Log, Debug, Info, Warn, and Error methods. -// For each call, it creates a Record and passes it to a Handler. -// -// To create a new Logger, call [New] or a Logger method -// that begins "With". -type Logger struct { - handler Handler // for structured logging -} - -func (l *Logger) clone() *Logger { - c := *l - return &c -} - -// Handler returns l's Handler. -func (l *Logger) Handler() Handler { return l.handler } - -// With returns a new Logger that includes the given arguments, converted to -// Attrs as in [Logger.Log]. -// The Attrs will be added to each output from the Logger. -// The new Logger shares the old Logger's context. -// The new Logger's handler is the result of calling WithAttrs on the receiver's -// handler. -func (l *Logger) With(args ...any) *Logger { - c := l.clone() - c.handler = l.handler.WithAttrs(argsToAttrSlice(args)) - return c -} - -// WithGroup returns a new Logger that starts a group. The keys of all -// attributes added to the Logger will be qualified by the given name. -// (How that qualification happens depends on the [Handler.WithGroup] -// method of the Logger's Handler.) -// The new Logger shares the old Logger's context. -// -// The new Logger's handler is the result of calling WithGroup on the receiver's -// handler. -func (l *Logger) WithGroup(name string) *Logger { - c := l.clone() - c.handler = l.handler.WithGroup(name) - return c - -} - -// New creates a new Logger with the given non-nil Handler and a nil context. -func New(h Handler) *Logger { - if h == nil { - panic("nil Handler") - } - return &Logger{handler: h} -} - -// With calls Logger.With on the default logger. -func With(args ...any) *Logger { - return Default().With(args...) -} - -// Enabled reports whether l emits log records at the given context and level. -func (l *Logger) Enabled(ctx context.Context, level Level) bool { - if ctx == nil { - ctx = context.Background() - } - return l.Handler().Enabled(ctx, level) -} - -// NewLogLogger returns a new log.Logger such that each call to its Output method -// dispatches a Record to the specified handler. The logger acts as a bridge from -// the older log API to newer structured logging handlers. -func NewLogLogger(h Handler, level Level) *log.Logger { - return log.New(&handlerWriter{h, level, true}, "", 0) -} - -// Log emits a log record with the current time and the given level and message. -// The Record's Attrs consist of the Logger's attributes followed by -// the Attrs specified by args. -// -// The attribute arguments are processed as follows: -// - If an argument is an Attr, it is used as is. -// - If an argument is a string and this is not the last argument, -// the following argument is treated as the value and the two are combined -// into an Attr. -// - Otherwise, the argument is treated as a value with key "!BADKEY". -func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) { - l.log(ctx, level, msg, args...) -} - -// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. -func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - l.logAttrs(ctx, level, msg, attrs...) -} - -// Debug logs at LevelDebug. -func (l *Logger) Debug(msg string, args ...any) { - l.log(nil, LevelDebug, msg, args...) -} - -// DebugContext logs at LevelDebug with the given context. -func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// DebugCtx logs at LevelDebug with the given context. -// Deprecated: Use Logger.DebugContext. -func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelDebug, msg, args...) -} - -// Info logs at LevelInfo. -func (l *Logger) Info(msg string, args ...any) { - l.log(nil, LevelInfo, msg, args...) -} - -// InfoContext logs at LevelInfo with the given context. -func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// InfoCtx logs at LevelInfo with the given context. -// Deprecated: Use Logger.InfoContext. -func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelInfo, msg, args...) -} - -// Warn logs at LevelWarn. -func (l *Logger) Warn(msg string, args ...any) { - l.log(nil, LevelWarn, msg, args...) -} - -// WarnContext logs at LevelWarn with the given context. -func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// WarnCtx logs at LevelWarn with the given context. -// Deprecated: Use Logger.WarnContext. -func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelWarn, msg, args...) -} - -// Error logs at LevelError. -func (l *Logger) Error(msg string, args ...any) { - l.log(nil, LevelError, msg, args...) -} - -// ErrorContext logs at LevelError with the given context. -func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// ErrorCtx logs at LevelError with the given context. -// Deprecated: Use Logger.ErrorContext. -func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) { - l.log(ctx, LevelError, msg, args...) -} - -// log is the low-level logging method for methods that take ...any. -// It must always be called directly by an exported logging method -// or function, because it uses a fixed call depth to obtain the pc. -func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.Add(args...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// logAttrs is like [Logger.log], but for methods that take ...Attr. -func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - if !l.Enabled(ctx, level) { - return - } - var pc uintptr - if !internal.IgnorePC { - var pcs [1]uintptr - // skip [runtime.Callers, this function, this function's caller] - runtime.Callers(3, pcs[:]) - pc = pcs[0] - } - r := NewRecord(time.Now(), level, msg, pc) - r.AddAttrs(attrs...) - if ctx == nil { - ctx = context.Background() - } - _ = l.Handler().Handle(ctx, r) -} - -// Debug calls Logger.Debug on the default logger. -func Debug(msg string, args ...any) { - Default().log(nil, LevelDebug, msg, args...) -} - -// DebugContext calls Logger.DebugContext on the default logger. -func DebugContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// Info calls Logger.Info on the default logger. -func Info(msg string, args ...any) { - Default().log(nil, LevelInfo, msg, args...) -} - -// InfoContext calls Logger.InfoContext on the default logger. -func InfoContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// Warn calls Logger.Warn on the default logger. -func Warn(msg string, args ...any) { - Default().log(nil, LevelWarn, msg, args...) -} - -// WarnContext calls Logger.WarnContext on the default logger. -func WarnContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// Error calls Logger.Error on the default logger. -func Error(msg string, args ...any) { - Default().log(nil, LevelError, msg, args...) -} - -// ErrorContext calls Logger.ErrorContext on the default logger. -func ErrorContext(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// DebugCtx calls Logger.DebugContext on the default logger. -// Deprecated: call DebugContext. -func DebugCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelDebug, msg, args...) -} - -// InfoCtx calls Logger.InfoContext on the default logger. -// Deprecated: call InfoContext. -func InfoCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelInfo, msg, args...) -} - -// WarnCtx calls Logger.WarnContext on the default logger. -// Deprecated: call WarnContext. -func WarnCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelWarn, msg, args...) -} - -// ErrorCtx calls Logger.ErrorContext on the default logger. -// Deprecated: call ErrorContext. -func ErrorCtx(ctx context.Context, msg string, args ...any) { - Default().log(ctx, LevelError, msg, args...) -} - -// Log calls Logger.Log on the default logger. -func Log(ctx context.Context, level Level, msg string, args ...any) { - Default().log(ctx, level, msg, args...) -} - -// LogAttrs calls Logger.LogAttrs on the default logger. -func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) { - Default().logAttrs(ctx, level, msg, attrs...) -} diff --git a/vendor/golang.org/x/exp/slog/noplog.bench b/vendor/golang.org/x/exp/slog/noplog.bench deleted file mode 100644 index ed9296ff61..0000000000 --- a/vendor/golang.org/x/exp/slog/noplog.bench +++ /dev/null @@ -1,36 +0,0 @@ -goos: linux -goarch: amd64 -pkg: golang.org/x/exp/slog -cpu: Intel(R) Xeon(R) CPU @ 2.20GHz -BenchmarkNopLog/attrs-8 1000000 1090 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1097 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1078 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1095 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-8 1000000 1096 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4007268 308.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4016138 299.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 4020529 305.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3977829 303.4 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/attrs-parallel-8 3225438 318.5 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1179256 994.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1002 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1216710 993.2 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1013 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/keys-values-8 1000000 1016 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 989066 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 994116 1163 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 1000000 1152 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 991675 1165 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-8 965268 1166 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955503 303.3 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3861188 307.8 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3967752 303.9 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3955203 302.7 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/WithContext-parallel-8 3948278 301.1 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 940622 1247 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 936381 1257 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 959730 1266 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 943473 1290 ns/op 0 B/op 0 allocs/op -BenchmarkNopLog/Ctx-8 919414 1259 ns/op 0 B/op 0 allocs/op -PASS -ok golang.org/x/exp/slog 40.566s diff --git a/vendor/golang.org/x/exp/slog/record.go b/vendor/golang.org/x/exp/slog/record.go deleted file mode 100644 index 38b3440f77..0000000000 --- a/vendor/golang.org/x/exp/slog/record.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "runtime" - "time" - - "golang.org/x/exp/slices" -) - -const nAttrsInline = 5 - -// A Record holds information about a log event. -// Copies of a Record share state. -// Do not modify a Record after handing out a copy to it. -// Use [Record.Clone] to create a copy with no shared state. -type Record struct { - // The time at which the output method (Log, Info, etc.) was called. - Time time.Time - - // The log message. - Message string - - // The level of the event. - Level Level - - // The program counter at the time the record was constructed, as determined - // by runtime.Callers. If zero, no program counter is available. - // - // The only valid use for this value is as an argument to - // [runtime.CallersFrames]. In particular, it must not be passed to - // [runtime.FuncForPC]. - PC uintptr - - // Allocation optimization: an inline array sized to hold - // the majority of log calls (based on examination of open-source - // code). It holds the start of the list of Attrs. - front [nAttrsInline]Attr - - // The number of Attrs in front. - nFront int - - // The list of Attrs except for those in front. - // Invariants: - // - len(back) > 0 iff nFront == len(front) - // - Unused array elements are zero. Used to detect mistakes. - back []Attr -} - -// NewRecord creates a Record from the given arguments. -// Use [Record.AddAttrs] to add attributes to the Record. -// -// NewRecord is intended for logging APIs that want to support a [Handler] as -// a backend. -func NewRecord(t time.Time, level Level, msg string, pc uintptr) Record { - return Record{ - Time: t, - Message: msg, - Level: level, - PC: pc, - } -} - -// Clone returns a copy of the record with no shared state. -// The original record and the clone can both be modified -// without interfering with each other. -func (r Record) Clone() Record { - r.back = slices.Clip(r.back) // prevent append from mutating shared array - return r -} - -// NumAttrs returns the number of attributes in the Record. -func (r Record) NumAttrs() int { - return r.nFront + len(r.back) -} - -// Attrs calls f on each Attr in the Record. -// Iteration stops if f returns false. -func (r Record) Attrs(f func(Attr) bool) { - for i := 0; i < r.nFront; i++ { - if !f(r.front[i]) { - return - } - } - for _, a := range r.back { - if !f(a) { - return - } - } -} - -// AddAttrs appends the given Attrs to the Record's list of Attrs. -func (r *Record) AddAttrs(attrs ...Attr) { - n := copy(r.front[r.nFront:], attrs) - r.nFront += n - // Check if a copy was modified by slicing past the end - // and seeing if the Attr there is non-zero. - if cap(r.back) > len(r.back) { - end := r.back[:len(r.back)+1][len(r.back)] - if !end.isEmpty() { - panic("copies of a slog.Record were both modified") - } - } - r.back = append(r.back, attrs[n:]...) -} - -// Add converts the args to Attrs as described in [Logger.Log], -// then appends the Attrs to the Record's list of Attrs. -func (r *Record) Add(args ...any) { - var a Attr - for len(args) > 0 { - a, args = argsToAttr(args) - if r.nFront < len(r.front) { - r.front[r.nFront] = a - r.nFront++ - } else { - if r.back == nil { - r.back = make([]Attr, 0, countAttrs(args)) - } - r.back = append(r.back, a) - } - } - -} - -// countAttrs returns the number of Attrs that would be created from args. -func countAttrs(args []any) int { - n := 0 - for i := 0; i < len(args); i++ { - n++ - if _, ok := args[i].(string); ok { - i++ - } - } - return n -} - -const badKey = "!BADKEY" - -// argsToAttr turns a prefix of the nonempty args slice into an Attr -// and returns the unconsumed portion of the slice. -// If args[0] is an Attr, it returns it. -// If args[0] is a string, it treats the first two elements as -// a key-value pair. -// Otherwise, it treats args[0] as a value with a missing key. -func argsToAttr(args []any) (Attr, []any) { - switch x := args[0].(type) { - case string: - if len(args) == 1 { - return String(badKey, x), nil - } - return Any(x, args[1]), args[2:] - - case Attr: - return x, args[1:] - - default: - return Any(badKey, x), args[1:] - } -} - -// Source describes the location of a line of source code. -type Source struct { - // Function is the package path-qualified function name containing the - // source line. If non-empty, this string uniquely identifies a single - // function in the program. This may be the empty string if not known. - Function string `json:"function"` - // File and Line are the file name and line number (1-based) of the source - // line. These may be the empty string and zero, respectively, if not known. - File string `json:"file"` - Line int `json:"line"` -} - -// attrs returns the non-zero fields of s as a slice of attrs. -// It is similar to a LogValue method, but we don't want Source -// to implement LogValuer because it would be resolved before -// the ReplaceAttr function was called. -func (s *Source) group() Value { - var as []Attr - if s.Function != "" { - as = append(as, String("function", s.Function)) - } - if s.File != "" { - as = append(as, String("file", s.File)) - } - if s.Line != 0 { - as = append(as, Int("line", s.Line)) - } - return GroupValue(as...) -} - -// source returns a Source for the log event. -// If the Record was created without the necessary information, -// or if the location is unavailable, it returns a non-nil *Source -// with zero fields. -func (r Record) source() *Source { - fs := runtime.CallersFrames([]uintptr{r.PC}) - f, _ := fs.Next() - return &Source{ - Function: f.Function, - File: f.File, - Line: f.Line, - } -} diff --git a/vendor/golang.org/x/exp/slog/text_handler.go b/vendor/golang.org/x/exp/slog/text_handler.go deleted file mode 100644 index 75b66b716f..0000000000 --- a/vendor/golang.org/x/exp/slog/text_handler.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "context" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "unicode" - "unicode/utf8" -) - -// TextHandler is a Handler that writes Records to an io.Writer as a -// sequence of key=value pairs separated by spaces and followed by a newline. -type TextHandler struct { - *commonHandler -} - -// NewTextHandler creates a TextHandler that writes to w, -// using the given options. -// If opts is nil, the default options are used. -func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler { - if opts == nil { - opts = &HandlerOptions{} - } - return &TextHandler{ - &commonHandler{ - json: false, - w: w, - opts: *opts, - }, - } -} - -// Enabled reports whether the handler handles records at the given level. -// The handler ignores records whose level is lower. -func (h *TextHandler) Enabled(_ context.Context, level Level) bool { - return h.commonHandler.enabled(level) -} - -// WithAttrs returns a new TextHandler whose attributes consists -// of h's attributes followed by attrs. -func (h *TextHandler) WithAttrs(attrs []Attr) Handler { - return &TextHandler{commonHandler: h.commonHandler.withAttrs(attrs)} -} - -func (h *TextHandler) WithGroup(name string) Handler { - return &TextHandler{commonHandler: h.commonHandler.withGroup(name)} -} - -// Handle formats its argument Record as a single line of space-separated -// key=value items. -// -// If the Record's time is zero, the time is omitted. -// Otherwise, the key is "time" -// and the value is output in RFC3339 format with millisecond precision. -// -// If the Record's level is zero, the level is omitted. -// Otherwise, the key is "level" -// and the value of [Level.String] is output. -// -// If the AddSource option is set and source information is available, -// the key is "source" and the value is output as FILE:LINE. -// -// The message's key is "msg". -// -// To modify these or other attributes, or remove them from the output, use -// [HandlerOptions.ReplaceAttr]. -// -// If a value implements [encoding.TextMarshaler], the result of MarshalText is -// written. Otherwise, the result of fmt.Sprint is written. -// -// Keys and values are quoted with [strconv.Quote] if they contain Unicode space -// characters, non-printing characters, '"' or '='. -// -// Keys inside groups consist of components (keys or group names) separated by -// dots. No further escaping is performed. -// Thus there is no way to determine from the key "a.b.c" whether there -// are two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c", -// or single group "a" and a key "b.c". -// If it is necessary to reconstruct the group structure of a key -// even in the presence of dots inside components, use -// [HandlerOptions.ReplaceAttr] to encode that information in the key. -// -// Each call to Handle results in a single serialized call to -// io.Writer.Write. -func (h *TextHandler) Handle(_ context.Context, r Record) error { - return h.commonHandler.handle(r) -} - -func appendTextValue(s *handleState, v Value) error { - switch v.Kind() { - case KindString: - s.appendString(v.str()) - case KindTime: - s.appendTime(v.time()) - case KindAny: - if tm, ok := v.any.(encoding.TextMarshaler); ok { - data, err := tm.MarshalText() - if err != nil { - return err - } - // TODO: avoid the conversion to string. - s.appendString(string(data)) - return nil - } - if bs, ok := byteSlice(v.any); ok { - // As of Go 1.19, this only allocates for strings longer than 32 bytes. - s.buf.WriteString(strconv.Quote(string(bs))) - return nil - } - s.appendString(fmt.Sprintf("%+v", v.Any())) - default: - *s.buf = v.append(*s.buf) - } - return nil -} - -// byteSlice returns its argument as a []byte if the argument's -// underlying type is []byte, along with a second return value of true. -// Otherwise it returns nil, false. -func byteSlice(a any) ([]byte, bool) { - if bs, ok := a.([]byte); ok { - return bs, true - } - // Like Printf's %s, we allow both the slice type and the byte element type to be named. - t := reflect.TypeOf(a) - if t != nil && t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { - return reflect.ValueOf(a).Bytes(), true - } - return nil, false -} - -func needsQuoting(s string) bool { - if len(s) == 0 { - return true - } - for i := 0; i < len(s); { - b := s[i] - if b < utf8.RuneSelf { - // Quote anything except a backslash that would need quoting in a - // JSON string, as well as space and '=' - if b != '\\' && (b == ' ' || b == '=' || !safeSet[b]) { - return true - } - i++ - continue - } - r, size := utf8.DecodeRuneInString(s[i:]) - if r == utf8.RuneError || unicode.IsSpace(r) || !unicode.IsPrint(r) { - return true - } - i += size - } - return false -} diff --git a/vendor/golang.org/x/exp/slog/value.go b/vendor/golang.org/x/exp/slog/value.go deleted file mode 100644 index 3550c46fc0..0000000000 --- a/vendor/golang.org/x/exp/slog/value.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slog - -import ( - "fmt" - "math" - "runtime" - "strconv" - "strings" - "time" - "unsafe" - - "golang.org/x/exp/slices" -) - -// A Value can represent any Go value, but unlike type any, -// it can represent most small values without an allocation. -// The zero Value corresponds to nil. -type Value struct { - _ [0]func() // disallow == - // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration, - // the string length for KindString, and nanoseconds since the epoch for KindTime. - num uint64 - // If any is of type Kind, then the value is in num as described above. - // If any is of type *time.Location, then the Kind is Time and time.Time value - // can be constructed from the Unix nanos in num and the location (monotonic time - // is not preserved). - // If any is of type stringptr, then the Kind is String and the string value - // consists of the length in num and the pointer in any. - // Otherwise, the Kind is Any and any is the value. - // (This implies that Attrs cannot store values of type Kind, *time.Location - // or stringptr.) - any any -} - -// Kind is the kind of a Value. -type Kind int - -// The following list is sorted alphabetically, but it's also important that -// KindAny is 0 so that a zero Value represents nil. - -const ( - KindAny Kind = iota - KindBool - KindDuration - KindFloat64 - KindInt64 - KindString - KindTime - KindUint64 - KindGroup - KindLogValuer -) - -var kindStrings = []string{ - "Any", - "Bool", - "Duration", - "Float64", - "Int64", - "String", - "Time", - "Uint64", - "Group", - "LogValuer", -} - -func (k Kind) String() string { - if k >= 0 && int(k) < len(kindStrings) { - return kindStrings[k] - } - return "" -} - -// Unexported version of Kind, just so we can store Kinds in Values. -// (No user-provided value has this type.) -type kind Kind - -// Kind returns v's Kind. -func (v Value) Kind() Kind { - switch x := v.any.(type) { - case Kind: - return x - case stringptr: - return KindString - case timeLocation: - return KindTime - case groupptr: - return KindGroup - case LogValuer: - return KindLogValuer - case kind: // a kind is just a wrapper for a Kind - return KindAny - default: - return KindAny - } -} - -//////////////// Constructors - -// IntValue returns a Value for an int. -func IntValue(v int) Value { - return Int64Value(int64(v)) -} - -// Int64Value returns a Value for an int64. -func Int64Value(v int64) Value { - return Value{num: uint64(v), any: KindInt64} -} - -// Uint64Value returns a Value for a uint64. -func Uint64Value(v uint64) Value { - return Value{num: v, any: KindUint64} -} - -// Float64Value returns a Value for a floating-point number. -func Float64Value(v float64) Value { - return Value{num: math.Float64bits(v), any: KindFloat64} -} - -// BoolValue returns a Value for a bool. -func BoolValue(v bool) Value { - u := uint64(0) - if v { - u = 1 - } - return Value{num: u, any: KindBool} -} - -// Unexported version of *time.Location, just so we can store *time.Locations in -// Values. (No user-provided value has this type.) -type timeLocation *time.Location - -// TimeValue returns a Value for a time.Time. -// It discards the monotonic portion. -func TimeValue(v time.Time) Value { - if v.IsZero() { - // UnixNano on the zero time is undefined, so represent the zero time - // with a nil *time.Location instead. time.Time.Location method never - // returns nil, so a Value with any == timeLocation(nil) cannot be - // mistaken for any other Value, time.Time or otherwise. - return Value{any: timeLocation(nil)} - } - return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())} -} - -// DurationValue returns a Value for a time.Duration. -func DurationValue(v time.Duration) Value { - return Value{num: uint64(v.Nanoseconds()), any: KindDuration} -} - -// AnyValue returns a Value for the supplied value. -// -// If the supplied value is of type Value, it is returned -// unmodified. -// -// Given a value of one of Go's predeclared string, bool, or -// (non-complex) numeric types, AnyValue returns a Value of kind -// String, Bool, Uint64, Int64, or Float64. The width of the -// original numeric type is not preserved. -// -// Given a time.Time or time.Duration value, AnyValue returns a Value of kind -// KindTime or KindDuration. The monotonic time is not preserved. -// -// For nil, or values of all other types, including named types whose -// underlying type is numeric, AnyValue returns a value of kind KindAny. -func AnyValue(v any) Value { - switch v := v.(type) { - case string: - return StringValue(v) - case int: - return Int64Value(int64(v)) - case uint: - return Uint64Value(uint64(v)) - case int64: - return Int64Value(v) - case uint64: - return Uint64Value(v) - case bool: - return BoolValue(v) - case time.Duration: - return DurationValue(v) - case time.Time: - return TimeValue(v) - case uint8: - return Uint64Value(uint64(v)) - case uint16: - return Uint64Value(uint64(v)) - case uint32: - return Uint64Value(uint64(v)) - case uintptr: - return Uint64Value(uint64(v)) - case int8: - return Int64Value(int64(v)) - case int16: - return Int64Value(int64(v)) - case int32: - return Int64Value(int64(v)) - case float64: - return Float64Value(v) - case float32: - return Float64Value(float64(v)) - case []Attr: - return GroupValue(v...) - case Kind: - return Value{any: kind(v)} - case Value: - return v - default: - return Value{any: v} - } -} - -//////////////// Accessors - -// Any returns v's value as an any. -func (v Value) Any() any { - switch v.Kind() { - case KindAny: - if k, ok := v.any.(kind); ok { - return Kind(k) - } - return v.any - case KindLogValuer: - return v.any - case KindGroup: - return v.group() - case KindInt64: - return int64(v.num) - case KindUint64: - return v.num - case KindFloat64: - return v.float() - case KindString: - return v.str() - case KindBool: - return v.bool() - case KindDuration: - return v.duration() - case KindTime: - return v.time() - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// Int64 returns v's value as an int64. It panics -// if v is not a signed integer. -func (v Value) Int64() int64 { - if g, w := v.Kind(), KindInt64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return int64(v.num) -} - -// Uint64 returns v's value as a uint64. It panics -// if v is not an unsigned integer. -func (v Value) Uint64() uint64 { - if g, w := v.Kind(), KindUint64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.num -} - -// Bool returns v's value as a bool. It panics -// if v is not a bool. -func (v Value) Bool() bool { - if g, w := v.Kind(), KindBool; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.bool() -} - -func (v Value) bool() bool { - return v.num == 1 -} - -// Duration returns v's value as a time.Duration. It panics -// if v is not a time.Duration. -func (v Value) Duration() time.Duration { - if g, w := v.Kind(), KindDuration; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.duration() -} - -func (v Value) duration() time.Duration { - return time.Duration(int64(v.num)) -} - -// Float64 returns v's value as a float64. It panics -// if v is not a float64. -func (v Value) Float64() float64 { - if g, w := v.Kind(), KindFloat64; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - - return v.float() -} - -func (v Value) float() float64 { - return math.Float64frombits(v.num) -} - -// Time returns v's value as a time.Time. It panics -// if v is not a time.Time. -func (v Value) Time() time.Time { - if g, w := v.Kind(), KindTime; g != w { - panic(fmt.Sprintf("Value kind is %s, not %s", g, w)) - } - return v.time() -} - -func (v Value) time() time.Time { - loc := v.any.(timeLocation) - if loc == nil { - return time.Time{} - } - return time.Unix(0, int64(v.num)).In(loc) -} - -// LogValuer returns v's value as a LogValuer. It panics -// if v is not a LogValuer. -func (v Value) LogValuer() LogValuer { - return v.any.(LogValuer) -} - -// Group returns v's value as a []Attr. -// It panics if v's Kind is not KindGroup. -func (v Value) Group() []Attr { - if sp, ok := v.any.(groupptr); ok { - return unsafe.Slice((*Attr)(sp), v.num) - } - panic("Group: bad kind") -} - -func (v Value) group() []Attr { - return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num) -} - -//////////////// Other - -// Equal reports whether v and w represent the same Go value. -func (v Value) Equal(w Value) bool { - k1 := v.Kind() - k2 := w.Kind() - if k1 != k2 { - return false - } - switch k1 { - case KindInt64, KindUint64, KindBool, KindDuration: - return v.num == w.num - case KindString: - return v.str() == w.str() - case KindFloat64: - return v.float() == w.float() - case KindTime: - return v.time().Equal(w.time()) - case KindAny, KindLogValuer: - return v.any == w.any // may panic if non-comparable - case KindGroup: - return slices.EqualFunc(v.group(), w.group(), Attr.Equal) - default: - panic(fmt.Sprintf("bad kind: %s", k1)) - } -} - -// append appends a text representation of v to dst. -// v is formatted as with fmt.Sprint. -func (v Value) append(dst []byte) []byte { - switch v.Kind() { - case KindString: - return append(dst, v.str()...) - case KindInt64: - return strconv.AppendInt(dst, int64(v.num), 10) - case KindUint64: - return strconv.AppendUint(dst, v.num, 10) - case KindFloat64: - return strconv.AppendFloat(dst, v.float(), 'g', -1, 64) - case KindBool: - return strconv.AppendBool(dst, v.bool()) - case KindDuration: - return append(dst, v.duration().String()...) - case KindTime: - return append(dst, v.time().String()...) - case KindGroup: - return fmt.Append(dst, v.group()) - case KindAny, KindLogValuer: - return fmt.Append(dst, v.any) - default: - panic(fmt.Sprintf("bad kind: %s", v.Kind())) - } -} - -// A LogValuer is any Go value that can convert itself into a Value for logging. -// -// This mechanism may be used to defer expensive operations until they are -// needed, or to expand a single value into a sequence of components. -type LogValuer interface { - LogValue() Value -} - -const maxLogValues = 100 - -// Resolve repeatedly calls LogValue on v while it implements LogValuer, -// and returns the result. -// If v resolves to a group, the group's attributes' values are not recursively -// resolved. -// If the number of LogValue calls exceeds a threshold, a Value containing an -// error is returned. -// Resolve's return value is guaranteed not to be of Kind KindLogValuer. -func (v Value) Resolve() (rv Value) { - orig := v - defer func() { - if r := recover(); r != nil { - rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5))) - } - }() - - for i := 0; i < maxLogValues; i++ { - if v.Kind() != KindLogValuer { - return v - } - v = v.LogValuer().LogValue() - } - err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any()) - return AnyValue(err) -} - -func stack(skip, nFrames int) string { - pcs := make([]uintptr, nFrames+1) - n := runtime.Callers(skip+1, pcs) - if n == 0 { - return "(no stack)" - } - frames := runtime.CallersFrames(pcs[:n]) - var b strings.Builder - i := 0 - for { - frame, more := frames.Next() - fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line) - if !more { - break - } - i++ - if i >= nFrames { - fmt.Fprintf(&b, "(rest of stack elided)\n") - break - } - } - return b.String() -} diff --git a/vendor/golang.org/x/exp/slog/value_119.go b/vendor/golang.org/x/exp/slog/value_119.go deleted file mode 100644 index 29b0d73292..0000000000 --- a/vendor/golang.org/x/exp/slog/value_119.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.19 && !go1.20 - -package slog - -import ( - "reflect" - "unsafe" -) - -type ( - stringptr unsafe.Pointer // used in Value.any when the Value is a string - groupptr unsafe.Pointer // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&value)) - return Value{num: uint64(hdr.Len), any: stringptr(hdr.Data)} -} - -func (v Value) str() string { - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(v.any.(stringptr)) - hdr.Len = int(v.num) - return s -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - // Inlining this code makes a huge difference. - var s string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - hdr.Data = uintptr(sp) - hdr.Len = int(v.num) - return s - } - return string(v.append(nil)) -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&as)) - return Value{num: uint64(hdr.Len), any: groupptr(hdr.Data)} -} diff --git a/vendor/golang.org/x/exp/slog/value_120.go b/vendor/golang.org/x/exp/slog/value_120.go deleted file mode 100644 index f7d4c09325..0000000000 --- a/vendor/golang.org/x/exp/slog/value_120.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package slog - -import "unsafe" - -type ( - stringptr *byte // used in Value.any when the Value is a string - groupptr *Attr // used in Value.any when the Value is a []Attr -) - -// StringValue returns a new Value for a string. -func StringValue(value string) Value { - return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))} -} - -// GroupValue returns a new Value for a list of Attrs. -// The caller must not subsequently mutate the argument slice. -func GroupValue(as ...Attr) Value { - return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))} -} - -// String returns Value's value as a string, formatted like fmt.Sprint. Unlike -// the methods Int64, Float64, and so on, which panic if v is of the -// wrong kind, String never panics. -func (v Value) String() string { - if sp, ok := v.any.(stringptr); ok { - return unsafe.String(sp, v.num) - } - return string(v.append(nil)) -} - -func (v Value) str() string { - return unsafe.String(v.any.(stringptr), v.num) -} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go index 37dc0cfdb5..e0df203cea 100644 --- a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go +++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package ctxhttp provides helper functions for performing context-aware HTTP requests. -package ctxhttp // import "golang.org/x/net/context/ctxhttp" +package ctxhttp import ( "context" diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index 7434b87843..b640deb0e0 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -2233,25 +2233,25 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *http.Request, error) { sc.serveG.check() - rp := requestParam{ - method: f.PseudoValue("method"), - scheme: f.PseudoValue("scheme"), - authority: f.PseudoValue("authority"), - path: f.PseudoValue("path"), - protocol: f.PseudoValue("protocol"), + rp := httpcommon.ServerRequestParam{ + Method: f.PseudoValue("method"), + Scheme: f.PseudoValue("scheme"), + Authority: f.PseudoValue("authority"), + Path: f.PseudoValue("path"), + Protocol: f.PseudoValue("protocol"), } // extended connect is disabled, so we should not see :protocol - if disableExtendedConnectProtocol && rp.protocol != "" { + if disableExtendedConnectProtocol && rp.Protocol != "" { return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol)) } - isConnect := rp.method == "CONNECT" + isConnect := rp.Method == "CONNECT" if isConnect { - if rp.protocol == "" && (rp.path != "" || rp.scheme != "" || rp.authority == "") { + if rp.Protocol == "" && (rp.Path != "" || rp.Scheme != "" || rp.Authority == "") { return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol)) } - } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") { + } else if rp.Method == "" || rp.Path == "" || (rp.Scheme != "https" && rp.Scheme != "http") { // See 8.1.2.6 Malformed Requests and Responses: // // Malformed requests or responses that are detected @@ -2265,15 +2265,16 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol)) } - rp.header = make(http.Header) + header := make(http.Header) + rp.Header = header for _, hf := range f.RegularFields() { - rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value) + header.Add(sc.canonicalHeader(hf.Name), hf.Value) } - if rp.authority == "" { - rp.authority = rp.header.Get("Host") + if rp.Authority == "" { + rp.Authority = header.Get("Host") } - if rp.protocol != "" { - rp.header.Set(":protocol", rp.protocol) + if rp.Protocol != "" { + header.Set(":protocol", rp.Protocol) } rw, req, err := sc.newWriterAndRequestNoBody(st, rp) @@ -2282,7 +2283,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res } bodyOpen := !f.StreamEnded() if bodyOpen { - if vv, ok := rp.header["Content-Length"]; ok { + if vv, ok := rp.Header["Content-Length"]; ok { if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil { req.ContentLength = int64(cl) } else { @@ -2298,84 +2299,38 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res return rw, req, nil } -type requestParam struct { - method string - scheme, authority, path string - protocol string - header http.Header -} - -func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*responseWriter, *http.Request, error) { +func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp httpcommon.ServerRequestParam) (*responseWriter, *http.Request, error) { sc.serveG.check() var tlsState *tls.ConnectionState // nil if not scheme https - if rp.scheme == "https" { + if rp.Scheme == "https" { tlsState = sc.tlsState } - needsContinue := httpguts.HeaderValuesContainsToken(rp.header["Expect"], "100-continue") - if needsContinue { - rp.header.Del("Expect") - } - // Merge Cookie headers into one "; "-delimited value. - if cookies := rp.header["Cookie"]; len(cookies) > 1 { - rp.header.Set("Cookie", strings.Join(cookies, "; ")) - } - - // Setup Trailers - var trailer http.Header - for _, v := range rp.header["Trailer"] { - for _, key := range strings.Split(v, ",") { - key = http.CanonicalHeaderKey(textproto.TrimString(key)) - switch key { - case "Transfer-Encoding", "Trailer", "Content-Length": - // Bogus. (copy of http1 rules) - // Ignore. - default: - if trailer == nil { - trailer = make(http.Header) - } - trailer[key] = nil - } - } - } - delete(rp.header, "Trailer") - - var url_ *url.URL - var requestURI string - if rp.method == "CONNECT" && rp.protocol == "" { - url_ = &url.URL{Host: rp.authority} - requestURI = rp.authority // mimic HTTP/1 server behavior - } else { - var err error - url_, err = url.ParseRequestURI(rp.path) - if err != nil { - return nil, nil, sc.countError("bad_path", streamError(st.id, ErrCodeProtocol)) - } - requestURI = rp.path + res := httpcommon.NewServerRequest(rp) + if res.InvalidReason != "" { + return nil, nil, sc.countError(res.InvalidReason, streamError(st.id, ErrCodeProtocol)) } body := &requestBody{ conn: sc, stream: st, - needsContinue: needsContinue, + needsContinue: res.NeedsContinue, } - req := &http.Request{ - Method: rp.method, - URL: url_, + req := (&http.Request{ + Method: rp.Method, + URL: res.URL, RemoteAddr: sc.remoteAddrStr, - Header: rp.header, - RequestURI: requestURI, + Header: rp.Header, + RequestURI: res.RequestURI, Proto: "HTTP/2.0", ProtoMajor: 2, ProtoMinor: 0, TLS: tlsState, - Host: rp.authority, + Host: rp.Authority, Body: body, - Trailer: trailer, - } - req = req.WithContext(st.ctx) - + Trailer: res.Trailer, + }).WithContext(st.ctx) rw := sc.newResponseWriter(st, req) return rw, req, nil } @@ -3270,12 +3225,12 @@ func (sc *serverConn) startPush(msg *startPushRequest) { // we start in "half closed (remote)" for simplicity. // See further comments at the definition of stateHalfClosedRemote. promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote) - rw, req, err := sc.newWriterAndRequestNoBody(promised, requestParam{ - method: msg.method, - scheme: msg.url.Scheme, - authority: msg.url.Host, - path: msg.url.RequestURI(), - header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE + rw, req, err := sc.newWriterAndRequestNoBody(promised, httpcommon.ServerRequestParam{ + Method: msg.method, + Scheme: msg.url.Scheme, + Authority: msg.url.Host, + Path: msg.url.RequestURI(), + Header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE }) if err != nil { // Should not happen, since we've already validated msg.url. diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index f2c166b615..f26356b9cd 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -1286,6 +1286,19 @@ func (cc *ClientConn) responseHeaderTimeout() time.Duration { return 0 } +// actualContentLength returns a sanitized version of +// req.ContentLength, where 0 actually means zero (not unknown) and -1 +// means unknown. +func actualContentLength(req *http.Request) int64 { + if req.Body == nil || req.Body == http.NoBody { + return 0 + } + if req.ContentLength != 0 { + return req.ContentLength + } + return -1 +} + func (cc *ClientConn) decrStreamReservations() { cc.mu.Lock() defer cc.mu.Unlock() @@ -1310,7 +1323,7 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) reqCancel: req.Cancel, isHead: req.Method == "HEAD", reqBody: req.Body, - reqBodyContentLength: httpcommon.ActualContentLength(req), + reqBodyContentLength: actualContentLength(req), trace: httptrace.ContextClientTrace(ctx), peerClosed: make(chan struct{}), abort: make(chan struct{}), @@ -1318,7 +1331,7 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) donec: make(chan struct{}), } - cs.requestedGzip = httpcommon.IsRequestGzip(req, cc.t.disableCompression()) + cs.requestedGzip = httpcommon.IsRequestGzip(req.Method, req.Header, cc.t.disableCompression()) go cs.doRequest(req, streamf) @@ -1349,7 +1362,7 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) } res.Request = req res.TLS = cc.tlsState - if res.Body == noBody && httpcommon.ActualContentLength(req) == 0 { + if res.Body == noBody && actualContentLength(req) == 0 { // If there isn't a request or response body still being // written, then wait for the stream to be closed before // RoundTrip returns. @@ -1596,12 +1609,7 @@ func (cs *clientStream) encodeAndWriteHeaders(req *http.Request) error { // sent by writeRequestBody below, along with any Trailers, // again in form HEADERS{1}, CONTINUATION{0,}) cc.hbuf.Reset() - res, err := httpcommon.EncodeHeaders(httpcommon.EncodeHeadersParam{ - Request: req, - AddGzipHeader: cs.requestedGzip, - PeerMaxHeaderListSize: cc.peerMaxHeaderListSize, - DefaultUserAgent: defaultUserAgent, - }, func(name, value string) { + res, err := encodeRequestHeaders(req, cs.requestedGzip, cc.peerMaxHeaderListSize, func(name, value string) { cc.writeHeader(name, value) }) if err != nil { @@ -1617,6 +1625,22 @@ func (cs *clientStream) encodeAndWriteHeaders(req *http.Request) error { return err } +func encodeRequestHeaders(req *http.Request, addGzipHeader bool, peerMaxHeaderListSize uint64, headerf func(name, value string)) (httpcommon.EncodeHeadersResult, error) { + return httpcommon.EncodeHeaders(req.Context(), httpcommon.EncodeHeadersParam{ + Request: httpcommon.Request{ + Header: req.Header, + Trailer: req.Trailer, + URL: req.URL, + Host: req.Host, + Method: req.Method, + ActualContentLength: actualContentLength(req), + }, + AddGzipHeader: addGzipHeader, + PeerMaxHeaderListSize: peerMaxHeaderListSize, + DefaultUserAgent: defaultUserAgent, + }, headerf) +} + // cleanupWriteRequest performs post-request tasks. // // If err (the result of writeRequest) is non-nil and the stream is not closed, @@ -2186,6 +2210,13 @@ func (rl *clientConnReadLoop) cleanup() { } cc.cond.Broadcast() cc.mu.Unlock() + + if !cc.seenSettings { + // If we have a pending request that wants extended CONNECT, + // let it continue and fail with the connection error. + cc.extendedConnectAllowed = true + close(cc.seenSettingsChan) + } } // countReadFrameError calls Transport.CountError with a string @@ -2278,9 +2309,6 @@ func (rl *clientConnReadLoop) run() error { if VerboseLogs { cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err) } - if !cc.seenSettings { - close(cc.seenSettingsChan) - } return err } } diff --git a/vendor/golang.org/x/net/internal/httpcommon/headermap.go b/vendor/golang.org/x/net/internal/httpcommon/headermap.go index ad3fbacd60..92483d8e41 100644 --- a/vendor/golang.org/x/net/internal/httpcommon/headermap.go +++ b/vendor/golang.org/x/net/internal/httpcommon/headermap.go @@ -5,7 +5,7 @@ package httpcommon import ( - "net/http" + "net/textproto" "sync" ) @@ -82,7 +82,7 @@ func buildCommonHeaderMaps() { commonLowerHeader = make(map[string]string, len(common)) commonCanonHeader = make(map[string]string, len(common)) for _, v := range common { - chk := http.CanonicalHeaderKey(v) + chk := textproto.CanonicalMIMEHeaderKey(v) commonLowerHeader[chk] = v commonCanonHeader[v] = chk } @@ -104,7 +104,7 @@ func CanonicalHeader(v string) string { if s, ok := commonCanonHeader[v]; ok { return s } - return http.CanonicalHeaderKey(v) + return textproto.CanonicalMIMEHeaderKey(v) } // CachedCanonicalHeader returns the canonical form of a well-known header name. diff --git a/vendor/golang.org/x/net/internal/httpcommon/request.go b/vendor/golang.org/x/net/internal/httpcommon/request.go index 3439147738..4b70553179 100644 --- a/vendor/golang.org/x/net/internal/httpcommon/request.go +++ b/vendor/golang.org/x/net/internal/httpcommon/request.go @@ -5,10 +5,12 @@ package httpcommon import ( + "context" "errors" "fmt" - "net/http" "net/http/httptrace" + "net/textproto" + "net/url" "sort" "strconv" "strings" @@ -21,9 +23,21 @@ var ( ErrRequestHeaderListSize = errors.New("request header list larger than peer's advertised limit") ) +// Request is a subset of http.Request. +// It'd be simpler to pass an *http.Request, of course, but we can't depend on net/http +// without creating a dependency cycle. +type Request struct { + URL *url.URL + Method string + Host string + Header map[string][]string + Trailer map[string][]string + ActualContentLength int64 // 0 means 0, -1 means unknown +} + // EncodeHeadersParam is parameters to EncodeHeaders. type EncodeHeadersParam struct { - Request *http.Request + Request Request // AddGzipHeader indicates that an "accept-encoding: gzip" header should be // added to the request. @@ -47,11 +61,11 @@ type EncodeHeadersResult struct { // It validates a request and calls headerf with each pseudo-header and header // for the request. // The headerf function is called with the validated, canonicalized header name. -func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) (res EncodeHeadersResult, _ error) { +func EncodeHeaders(ctx context.Context, param EncodeHeadersParam, headerf func(name, value string)) (res EncodeHeadersResult, _ error) { req := param.Request // Check for invalid connection-level headers. - if err := checkConnHeaders(req); err != nil { + if err := checkConnHeaders(req.Header); err != nil { return res, err } @@ -73,7 +87,10 @@ func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) ( // isNormalConnect is true if this is a non-extended CONNECT request. isNormalConnect := false - protocol := req.Header.Get(":protocol") + var protocol string + if vv := req.Header[":protocol"]; len(vv) > 0 { + protocol = vv[0] + } if req.Method == "CONNECT" && protocol == "" { isNormalConnect = true } else if protocol != "" && req.Method != "CONNECT" { @@ -107,9 +124,7 @@ func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) ( return res, fmt.Errorf("invalid HTTP trailer %s", err) } - contentLength := ActualContentLength(req) - - trailers, err := commaSeparatedTrailers(req) + trailers, err := commaSeparatedTrailers(req.Trailer) if err != nil { return res, err } @@ -123,7 +138,7 @@ func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) ( f(":authority", host) m := req.Method if m == "" { - m = http.MethodGet + m = "GET" } f(":method", m) if !isNormalConnect { @@ -198,8 +213,8 @@ func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) ( f(k, v) } } - if shouldSendReqContentLength(req.Method, contentLength) { - f("content-length", strconv.FormatInt(contentLength, 10)) + if shouldSendReqContentLength(req.Method, req.ActualContentLength) { + f("content-length", strconv.FormatInt(req.ActualContentLength, 10)) } if param.AddGzipHeader { f("accept-encoding", "gzip") @@ -225,7 +240,7 @@ func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) ( } } - trace := httptrace.ContextClientTrace(req.Context()) + trace := httptrace.ContextClientTrace(ctx) // Header list size is ok. Write the headers. enumerateHeaders(func(name, value string) { @@ -243,19 +258,19 @@ func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) ( } }) - res.HasBody = contentLength != 0 + res.HasBody = req.ActualContentLength != 0 res.HasTrailers = trailers != "" return res, nil } // IsRequestGzip reports whether we should add an Accept-Encoding: gzip header // for a request. -func IsRequestGzip(req *http.Request, disableCompression bool) bool { +func IsRequestGzip(method string, header map[string][]string, disableCompression bool) bool { // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? if !disableCompression && - req.Header.Get("Accept-Encoding") == "" && - req.Header.Get("Range") == "" && - req.Method != "HEAD" { + len(header["Accept-Encoding"]) == 0 && + len(header["Range"]) == 0 && + method != "HEAD" { // Request gzip only, not deflate. Deflate is ambiguous and // not as universally supported anyway. // See: https://zlib.net/zlib_faq.html#faq39 @@ -280,22 +295,22 @@ func IsRequestGzip(req *http.Request, disableCompression bool) bool { // // Certain headers are special-cased as okay but not transmitted later. // For example, we allow "Transfer-Encoding: chunked", but drop the header when encoding. -func checkConnHeaders(req *http.Request) error { - if v := req.Header.Get("Upgrade"); v != "" { - return fmt.Errorf("invalid Upgrade request header: %q", req.Header["Upgrade"]) +func checkConnHeaders(h map[string][]string) error { + if vv := h["Upgrade"]; len(vv) > 0 && (vv[0] != "" && vv[0] != "chunked") { + return fmt.Errorf("invalid Upgrade request header: %q", vv) } - if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") { + if vv := h["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") { return fmt.Errorf("invalid Transfer-Encoding request header: %q", vv) } - if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !asciiEqualFold(vv[0], "close") && !asciiEqualFold(vv[0], "keep-alive")) { + if vv := h["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !asciiEqualFold(vv[0], "close") && !asciiEqualFold(vv[0], "keep-alive")) { return fmt.Errorf("invalid Connection request header: %q", vv) } return nil } -func commaSeparatedTrailers(req *http.Request) (string, error) { - keys := make([]string, 0, len(req.Trailer)) - for k := range req.Trailer { +func commaSeparatedTrailers(trailer map[string][]string) (string, error) { + keys := make([]string, 0, len(trailer)) + for k := range trailer { k = CanonicalHeader(k) switch k { case "Transfer-Encoding", "Trailer", "Content-Length": @@ -310,19 +325,6 @@ func commaSeparatedTrailers(req *http.Request) (string, error) { return "", nil } -// ActualContentLength returns a sanitized version of -// req.ContentLength, where 0 actually means zero (not unknown) and -1 -// means unknown. -func ActualContentLength(req *http.Request) int64 { - if req.Body == nil || req.Body == http.NoBody { - return 0 - } - if req.ContentLength != 0 { - return req.ContentLength - } - return -1 -} - // validPseudoPath reports whether v is a valid :path pseudo-header // value. It must be either: // @@ -340,7 +342,7 @@ func validPseudoPath(v string) bool { return (len(v) > 0 && v[0] == '/') || v == "*" } -func validateHeaders(hdrs http.Header) string { +func validateHeaders(hdrs map[string][]string) string { for k, vv := range hdrs { if !httpguts.ValidHeaderFieldName(k) && k != ":protocol" { return fmt.Sprintf("name %q", k) @@ -377,3 +379,89 @@ func shouldSendReqContentLength(method string, contentLength int64) bool { return false } } + +// ServerRequestParam is parameters to NewServerRequest. +type ServerRequestParam struct { + Method string + Scheme, Authority, Path string + Protocol string + Header map[string][]string +} + +// ServerRequestResult is the result of NewServerRequest. +type ServerRequestResult struct { + // Various http.Request fields. + URL *url.URL + RequestURI string + Trailer map[string][]string + + NeedsContinue bool // client provided an "Expect: 100-continue" header + + // If the request should be rejected, this is a short string suitable for passing + // to the http2 package's CountError function. + // It might be a bit odd to return errors this way rather than returing an error, + // but this ensures we don't forget to include a CountError reason. + InvalidReason string +} + +func NewServerRequest(rp ServerRequestParam) ServerRequestResult { + needsContinue := httpguts.HeaderValuesContainsToken(rp.Header["Expect"], "100-continue") + if needsContinue { + delete(rp.Header, "Expect") + } + // Merge Cookie headers into one "; "-delimited value. + if cookies := rp.Header["Cookie"]; len(cookies) > 1 { + rp.Header["Cookie"] = []string{strings.Join(cookies, "; ")} + } + + // Setup Trailers + var trailer map[string][]string + for _, v := range rp.Header["Trailer"] { + for _, key := range strings.Split(v, ",") { + key = textproto.CanonicalMIMEHeaderKey(textproto.TrimString(key)) + switch key { + case "Transfer-Encoding", "Trailer", "Content-Length": + // Bogus. (copy of http1 rules) + // Ignore. + default: + if trailer == nil { + trailer = make(map[string][]string) + } + trailer[key] = nil + } + } + } + delete(rp.Header, "Trailer") + + // "':authority' MUST NOT include the deprecated userinfo subcomponent + // for "http" or "https" schemed URIs." + // https://www.rfc-editor.org/rfc/rfc9113.html#section-8.3.1-2.3.8 + if strings.IndexByte(rp.Authority, '@') != -1 && (rp.Scheme == "http" || rp.Scheme == "https") { + return ServerRequestResult{ + InvalidReason: "userinfo_in_authority", + } + } + + var url_ *url.URL + var requestURI string + if rp.Method == "CONNECT" && rp.Protocol == "" { + url_ = &url.URL{Host: rp.Authority} + requestURI = rp.Authority // mimic HTTP/1 server behavior + } else { + var err error + url_, err = url.ParseRequestURI(rp.Path) + if err != nil { + return ServerRequestResult{ + InvalidReason: "bad_path", + } + } + requestURI = rp.Path + } + + return ServerRequestResult{ + URL: url_, + NeedsContinue: needsContinue, + RequestURI: requestURI, + Trailer: trailer, + } +} diff --git a/vendor/golang.org/x/net/proxy/per_host.go b/vendor/golang.org/x/net/proxy/per_host.go index d7d4b8b6e3..32bdf435ec 100644 --- a/vendor/golang.org/x/net/proxy/per_host.go +++ b/vendor/golang.org/x/net/proxy/per_host.go @@ -7,6 +7,7 @@ package proxy import ( "context" "net" + "net/netip" "strings" ) @@ -57,7 +58,8 @@ func (p *PerHost) DialContext(ctx context.Context, network, addr string) (c net. } func (p *PerHost) dialerForRequest(host string) Dialer { - if ip := net.ParseIP(host); ip != nil { + if nip, err := netip.ParseAddr(host); err == nil { + ip := net.IP(nip.AsSlice()) for _, net := range p.bypassNetworks { if net.Contains(ip) { return p.bypass @@ -108,8 +110,8 @@ func (p *PerHost) AddFromString(s string) { } continue } - if ip := net.ParseIP(host); ip != nil { - p.AddIP(ip) + if nip, err := netip.ParseAddr(host); err == nil { + p.AddIP(net.IP(nip.AsSlice())) continue } if strings.HasPrefix(host, "*.") { diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 74f052aa9f..eacdd7fd93 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -288,7 +288,7 @@ func (tf *tokenRefresher) Token() (*Token, error) { if tf.refreshToken != tk.RefreshToken { tf.refreshToken = tk.RefreshToken } - return tk, err + return tk, nil } // reuseTokenSource is a TokenSource that holds a single token in memory @@ -356,11 +356,15 @@ func NewClient(ctx context.Context, src TokenSource) *http.Client { if src == nil { return internal.ContextClient(ctx) } + cc := internal.ContextClient(ctx) return &http.Client{ Transport: &Transport{ - Base: internal.ContextClient(ctx).Transport, + Base: cc.Transport, Source: ReuseTokenSource(nil, src), }, + CheckRedirect: cc.CheckRedirect, + Jar: cc.Jar, + Timeout: cc.Timeout, } } diff --git a/vendor/golang.org/x/oauth2/pkce.go b/vendor/golang.org/x/oauth2/pkce.go index 50593b6dfe..6a95da975c 100644 --- a/vendor/golang.org/x/oauth2/pkce.go +++ b/vendor/golang.org/x/oauth2/pkce.go @@ -21,7 +21,7 @@ const ( // // A fresh verifier should be generated for each authorization. // S256ChallengeOption(verifier) should then be passed to Config.AuthCodeURL -// (or Config.DeviceAccess) and VerifierOption(verifier) to Config.Exchange +// (or Config.DeviceAuth) and VerifierOption(verifier) to Config.Exchange // (or Config.DeviceAccessToken). func GenerateVerifier() string { // "RECOMMENDED that the output of a suitable random number generator be @@ -51,7 +51,7 @@ func S256ChallengeFromVerifier(verifier string) string { } // S256ChallengeOption derives a PKCE code challenge derived from verifier with -// method S256. It should be passed to Config.AuthCodeURL or Config.DeviceAccess +// method S256. It should be passed to Config.AuthCodeURL or Config.DeviceAuth // only. func S256ChallengeOption(verifier string) AuthCodeOption { return challengeOption{ diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go index b8322598ae..a4ea5d14f1 100644 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -46,7 +46,7 @@ func (g *Group) done() { // returns a non-nil error or the first time Wait returns, whichever occurs // first. func WithContext(ctx context.Context) (*Group, context.Context) { - ctx, cancel := withCancelCause(ctx) + ctx, cancel := context.WithCancelCause(ctx) return &Group{cancel: cancel}, ctx } diff --git a/vendor/golang.org/x/sync/errgroup/go120.go b/vendor/golang.org/x/sync/errgroup/go120.go deleted file mode 100644 index f93c740b63..0000000000 --- a/vendor/golang.org/x/sync/errgroup/go120.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - return context.WithCancelCause(parent) -} diff --git a/vendor/golang.org/x/sync/errgroup/pre_go120.go b/vendor/golang.org/x/sync/errgroup/pre_go120.go deleted file mode 100644 index 88ce33434e..0000000000 --- a/vendor/golang.org/x/sync/errgroup/pre_go120.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - ctx, cancel := context.WithCancel(parent) - return ctx, func(error) { cancel() } -} diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go index ec5f0cdd0c..794b2e32bf 100644 --- a/vendor/golang.org/x/time/rate/rate.go +++ b/vendor/golang.org/x/time/rate/rate.go @@ -85,7 +85,7 @@ func (lim *Limiter) Burst() int { // TokensAt returns the number of tokens available at time t. func (lim *Limiter) TokensAt(t time.Time) float64 { lim.mu.Lock() - _, tokens := lim.advance(t) // does not mutate lim + tokens := lim.advance(t) // does not mutate lim lim.mu.Unlock() return tokens } @@ -186,7 +186,7 @@ func (r *Reservation) CancelAt(t time.Time) { return } // advance time to now - t, tokens := r.lim.advance(t) + tokens := r.lim.advance(t) // calculate new number of tokens tokens += restoreTokens if burst := float64(r.lim.burst); tokens > burst { @@ -307,7 +307,7 @@ func (lim *Limiter) SetLimitAt(t time.Time, newLimit Limit) { lim.mu.Lock() defer lim.mu.Unlock() - t, tokens := lim.advance(t) + tokens := lim.advance(t) lim.last = t lim.tokens = tokens @@ -324,7 +324,7 @@ func (lim *Limiter) SetBurstAt(t time.Time, newBurst int) { lim.mu.Lock() defer lim.mu.Unlock() - t, tokens := lim.advance(t) + tokens := lim.advance(t) lim.last = t lim.tokens = tokens @@ -347,7 +347,7 @@ func (lim *Limiter) reserveN(t time.Time, n int, maxFutureReserve time.Duration) } } - t, tokens := lim.advance(t) + tokens := lim.advance(t) // Calculate the remaining number of tokens resulting from the request. tokens -= float64(n) @@ -380,10 +380,11 @@ func (lim *Limiter) reserveN(t time.Time, n int, maxFutureReserve time.Duration) return r } -// advance calculates and returns an updated state for lim resulting from the passage of time. +// advance calculates and returns an updated number of tokens for lim +// resulting from the passage of time. // lim is not changed. // advance requires that lim.mu is held. -func (lim *Limiter) advance(t time.Time) (newT time.Time, newTokens float64) { +func (lim *Limiter) advance(t time.Time) (newTokens float64) { last := lim.last if t.Before(last) { last = t @@ -396,7 +397,7 @@ func (lim *Limiter) advance(t time.Time) (newT time.Time, newTokens float64) { if burst := float64(lim.burst); tokens > burst { tokens = burst } - return t, tokens + return tokens } // durationFromTokens is a unit conversion function from the number of tokens to the duration diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go index 8b462f3dfe..0b789e2c5e 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go index db7806cb99..f840481726 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go index 08505ba3fe..5d583b8660 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go index a462e7d013..53e9dd1e99 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go index c93b4f5248..d30fcee4ce 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go index a1c543a948..175974a869 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go index 2b54db3045..b8c4aa71f2 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/checked.pb.go b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/checked.pb.go index 9f81dbcd86..af9c44d93e 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/checked.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/checked.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/eval.pb.go b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/eval.pb.go index 0a2ffb5955..4b4f15477f 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/eval.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/eval.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/explain.pb.go b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/explain.pb.go index 57aaa2c9f5..ef27e878b9 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/explain.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/explain.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/syntax.pb.go b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/syntax.pb.go index c90c6015d2..7b973217ed 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/syntax.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/syntax.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/value.pb.go b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/value.pb.go index 0a5ca6a1b9..4ba3c7b2a8 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/value.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/expr/v1alpha1/value.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go b/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go index 498020e33c..a69c1d4734 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go index 6ad1b1c1df..06a3f71063 100644 --- a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go index 382ad69411..c9b343c715 100644 --- a/vendor/google.golang.org/grpc/balancer/balancer.go +++ b/vendor/google.golang.org/grpc/balancer/balancer.go @@ -129,6 +129,13 @@ type State struct { // brand new implementation of this interface. For the situations like // testing, the new implementation should embed this interface. This allows // gRPC to add new methods to this interface. +// +// NOTICE: This interface is intended to be implemented by gRPC, or intercepted +// by custom load balancing polices. Users should not need their own complete +// implementation of this interface -- they should always delegate to a +// ClientConn passed to Builder.Build() by embedding it in their +// implementations. An embedded ClientConn must never be nil, or runtime panics +// will occur. type ClientConn interface { // NewSubConn is called by balancer to create a new SubConn. // It doesn't block and wait for the connections to be established. @@ -167,6 +174,17 @@ type ClientConn interface { // // Deprecated: Use the Target field in the BuildOptions instead. Target() string + + // MetricsRecorder provides the metrics recorder that balancers can use to + // record metrics. Balancer implementations which do not register metrics on + // metrics registry and record on them can ignore this method. The returned + // MetricsRecorder is guaranteed to never be nil. + MetricsRecorder() estats.MetricsRecorder + + // EnforceClientConnEmbedding is included to force implementers to embed + // another implementation of this interface, allowing gRPC to add methods + // without breaking users. + internal.EnforceClientConnEmbedding } // BuildOptions contains additional information for Build. @@ -198,10 +216,6 @@ type BuildOptions struct { // same resolver.Target as passed to the resolver. See the documentation for // the resolver.Target type for details about what it contains. Target resolver.Target - // MetricsRecorder is the metrics recorder that balancers can use to record - // metrics. Balancer implementations which do not register metrics on - // metrics registry and record on them can ignore this field. - MetricsRecorder estats.MetricsRecorder } // Builder creates a balancer. diff --git a/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go b/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go new file mode 100644 index 0000000000..421c4fecc9 --- /dev/null +++ b/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go @@ -0,0 +1,358 @@ +/* + * + * Copyright 2024 gRPC 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 endpointsharding implements a load balancing policy that manages +// homogeneous child policies each owning a single endpoint. +// +// # Experimental +// +// Notice: This package is EXPERIMENTAL and may be changed or removed in a +// later release. +package endpointsharding + +import ( + "errors" + rand "math/rand/v2" + "sync" + "sync/atomic" + + "google.golang.org/grpc/balancer" + "google.golang.org/grpc/balancer/base" + "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/resolver" +) + +// ChildState is the balancer state of a child along with the endpoint which +// identifies the child balancer. +type ChildState struct { + Endpoint resolver.Endpoint + State balancer.State + + // Balancer exposes only the ExitIdler interface of the child LB policy. + // Other methods of the child policy are called only by endpointsharding. + Balancer balancer.ExitIdler +} + +// Options are the options to configure the behaviour of the +// endpointsharding balancer. +type Options struct { + // DisableAutoReconnect allows the balancer to keep child balancer in the + // IDLE state until they are explicitly triggered to exit using the + // ChildState obtained from the endpointsharding picker. When set to false, + // the endpointsharding balancer will automatically call ExitIdle on child + // connections that report IDLE. + DisableAutoReconnect bool +} + +// ChildBuilderFunc creates a new balancer with the ClientConn. It has the same +// type as the balancer.Builder.Build method. +type ChildBuilderFunc func(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer + +// NewBalancer returns a load balancing policy that manages homogeneous child +// policies each owning a single endpoint. The endpointsharding balancer +// forwards the LoadBalancingConfig in ClientConn state updates to its children. +func NewBalancer(cc balancer.ClientConn, opts balancer.BuildOptions, childBuilder ChildBuilderFunc, esOpts Options) balancer.Balancer { + es := &endpointSharding{ + cc: cc, + bOpts: opts, + esOpts: esOpts, + childBuilder: childBuilder, + } + es.children.Store(resolver.NewEndpointMap()) + return es +} + +// endpointSharding is a balancer that wraps child balancers. It creates a child +// balancer with child config for every unique Endpoint received. It updates the +// child states on any update from parent or child. +type endpointSharding struct { + cc balancer.ClientConn + bOpts balancer.BuildOptions + esOpts Options + childBuilder ChildBuilderFunc + + // childMu synchronizes calls to any single child. It must be held for all + // calls into a child. To avoid deadlocks, do not acquire childMu while + // holding mu. + childMu sync.Mutex + children atomic.Pointer[resolver.EndpointMap] // endpoint -> *balancerWrapper + + // inhibitChildUpdates is set during UpdateClientConnState/ResolverError + // calls (calls to children will each produce an update, only want one + // update). + inhibitChildUpdates atomic.Bool + + // mu synchronizes access to the state stored in balancerWrappers in the + // children field. mu must not be held during calls into a child since + // synchronous calls back from the child may require taking mu, causing a + // deadlock. To avoid deadlocks, do not acquire childMu while holding mu. + mu sync.Mutex +} + +// UpdateClientConnState creates a child for new endpoints and deletes children +// for endpoints that are no longer present. It also updates all the children, +// and sends a single synchronous update of the childrens' aggregated state at +// the end of the UpdateClientConnState operation. If any endpoint has no +// addresses it will ignore that endpoint. Otherwise, returns first error found +// from a child, but fully processes the new update. +func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState) error { + es.childMu.Lock() + defer es.childMu.Unlock() + + es.inhibitChildUpdates.Store(true) + defer func() { + es.inhibitChildUpdates.Store(false) + es.updateState() + }() + var ret error + + children := es.children.Load() + newChildren := resolver.NewEndpointMap() + + // Update/Create new children. + for _, endpoint := range state.ResolverState.Endpoints { + if _, ok := newChildren.Get(endpoint); ok { + // Endpoint child was already created, continue to avoid duplicate + // update. + continue + } + var childBalancer *balancerWrapper + if val, ok := children.Get(endpoint); ok { + childBalancer = val.(*balancerWrapper) + // Endpoint attributes may have changed, update the stored endpoint. + es.mu.Lock() + childBalancer.childState.Endpoint = endpoint + es.mu.Unlock() + } else { + childBalancer = &balancerWrapper{ + childState: ChildState{Endpoint: endpoint}, + ClientConn: es.cc, + es: es, + } + childBalancer.childState.Balancer = childBalancer + childBalancer.child = es.childBuilder(childBalancer, es.bOpts) + } + newChildren.Set(endpoint, childBalancer) + if err := childBalancer.updateClientConnStateLocked(balancer.ClientConnState{ + BalancerConfig: state.BalancerConfig, + ResolverState: resolver.State{ + Endpoints: []resolver.Endpoint{endpoint}, + Attributes: state.ResolverState.Attributes, + }, + }); err != nil && ret == nil { + // Return first error found, and always commit full processing of + // updating children. If desired to process more specific errors + // across all endpoints, caller should make these specific + // validations, this is a current limitation for simplicity sake. + ret = err + } + } + // Delete old children that are no longer present. + for _, e := range children.Keys() { + child, _ := children.Get(e) + if _, ok := newChildren.Get(e); !ok { + child.(*balancerWrapper).closeLocked() + } + } + es.children.Store(newChildren) + if newChildren.Len() == 0 { + return balancer.ErrBadResolverState + } + return ret +} + +// ResolverError forwards the resolver error to all of the endpointSharding's +// children and sends a single synchronous update of the childStates at the end +// of the ResolverError operation. +func (es *endpointSharding) ResolverError(err error) { + es.childMu.Lock() + defer es.childMu.Unlock() + es.inhibitChildUpdates.Store(true) + defer func() { + es.inhibitChildUpdates.Store(false) + es.updateState() + }() + children := es.children.Load() + for _, child := range children.Values() { + child.(*balancerWrapper).resolverErrorLocked(err) + } +} + +func (es *endpointSharding) UpdateSubConnState(balancer.SubConn, balancer.SubConnState) { + // UpdateSubConnState is deprecated. +} + +func (es *endpointSharding) Close() { + es.childMu.Lock() + defer es.childMu.Unlock() + children := es.children.Load() + for _, child := range children.Values() { + child.(*balancerWrapper).closeLocked() + } +} + +// updateState updates this component's state. It sends the aggregated state, +// and a picker with round robin behavior with all the child states present if +// needed. +func (es *endpointSharding) updateState() { + if es.inhibitChildUpdates.Load() { + return + } + var readyPickers, connectingPickers, idlePickers, transientFailurePickers []balancer.Picker + + es.mu.Lock() + defer es.mu.Unlock() + + children := es.children.Load() + childStates := make([]ChildState, 0, children.Len()) + + for _, child := range children.Values() { + bw := child.(*balancerWrapper) + childState := bw.childState + childStates = append(childStates, childState) + childPicker := childState.State.Picker + switch childState.State.ConnectivityState { + case connectivity.Ready: + readyPickers = append(readyPickers, childPicker) + case connectivity.Connecting: + connectingPickers = append(connectingPickers, childPicker) + case connectivity.Idle: + idlePickers = append(idlePickers, childPicker) + case connectivity.TransientFailure: + transientFailurePickers = append(transientFailurePickers, childPicker) + // connectivity.Shutdown shouldn't appear. + } + } + + // Construct the round robin picker based off the aggregated state. Whatever + // the aggregated state, use the pickers present that are currently in that + // state only. + var aggState connectivity.State + var pickers []balancer.Picker + if len(readyPickers) >= 1 { + aggState = connectivity.Ready + pickers = readyPickers + } else if len(connectingPickers) >= 1 { + aggState = connectivity.Connecting + pickers = connectingPickers + } else if len(idlePickers) >= 1 { + aggState = connectivity.Idle + pickers = idlePickers + } else if len(transientFailurePickers) >= 1 { + aggState = connectivity.TransientFailure + pickers = transientFailurePickers + } else { + aggState = connectivity.TransientFailure + pickers = []balancer.Picker{base.NewErrPicker(errors.New("no children to pick from"))} + } // No children (resolver error before valid update). + p := &pickerWithChildStates{ + pickers: pickers, + childStates: childStates, + next: uint32(rand.IntN(len(pickers))), + } + es.cc.UpdateState(balancer.State{ + ConnectivityState: aggState, + Picker: p, + }) +} + +// pickerWithChildStates delegates to the pickers it holds in a round robin +// fashion. It also contains the childStates of all the endpointSharding's +// children. +type pickerWithChildStates struct { + pickers []balancer.Picker + childStates []ChildState + next uint32 +} + +func (p *pickerWithChildStates) Pick(info balancer.PickInfo) (balancer.PickResult, error) { + nextIndex := atomic.AddUint32(&p.next, 1) + picker := p.pickers[nextIndex%uint32(len(p.pickers))] + return picker.Pick(info) +} + +// ChildStatesFromPicker returns the state of all the children managed by the +// endpoint sharding balancer that created this picker. +func ChildStatesFromPicker(picker balancer.Picker) []ChildState { + p, ok := picker.(*pickerWithChildStates) + if !ok { + return nil + } + return p.childStates +} + +// balancerWrapper is a wrapper of a balancer. It ID's a child balancer by +// endpoint, and persists recent child balancer state. +type balancerWrapper struct { + // The following fields are initialized at build time and read-only after + // that and therefore do not need to be guarded by a mutex. + + // child contains the wrapped balancer. Access its methods only through + // methods on balancerWrapper to ensure proper synchronization + child balancer.Balancer + balancer.ClientConn // embed to intercept UpdateState, doesn't deal with SubConns + + es *endpointSharding + + // Access to the following fields is guarded by es.mu. + + childState ChildState + isClosed bool +} + +func (bw *balancerWrapper) UpdateState(state balancer.State) { + bw.es.mu.Lock() + bw.childState.State = state + bw.es.mu.Unlock() + if state.ConnectivityState == connectivity.Idle && !bw.es.esOpts.DisableAutoReconnect { + bw.ExitIdle() + } + bw.es.updateState() +} + +// ExitIdle pings an IDLE child balancer to exit idle in a new goroutine to +// avoid deadlocks due to synchronous balancer state updates. +func (bw *balancerWrapper) ExitIdle() { + if ei, ok := bw.child.(balancer.ExitIdler); ok { + go func() { + bw.es.childMu.Lock() + if !bw.isClosed { + ei.ExitIdle() + } + bw.es.childMu.Unlock() + }() + } +} + +// updateClientConnStateLocked delivers the ClientConnState to the child +// balancer. Callers must hold the child mutex of the parent endpointsharding +// balancer. +func (bw *balancerWrapper) updateClientConnStateLocked(ccs balancer.ClientConnState) error { + return bw.child.UpdateClientConnState(ccs) +} + +// closeLocked closes the child balancer. Callers must hold the child mutext of +// the parent endpointsharding balancer. +func (bw *balancerWrapper) closeLocked() { + bw.child.Close() + bw.isClosed = true +} + +func (bw *balancerWrapper) resolverErrorLocked(err error) { + bw.child.ResolverError(err) +} diff --git a/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go index 76fa5fea95..113181e6b3 100644 --- a/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go +++ b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go @@ -120,7 +120,7 @@ func (pickfirstBuilder) Build(cc balancer.ClientConn, bo balancer.BuildOptions) b := &pickfirstBalancer{ cc: cc, target: bo.Target.String(), - metricsRecorder: bo.MetricsRecorder, // ClientConn will always create a Metrics Recorder. + metricsRecorder: cc.MetricsRecorder(), subConns: resolver.NewAddressMap(), state: connectivity.Connecting, diff --git a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go index 80a42d2251..35da5d1ec9 100644 --- a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go +++ b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go @@ -22,12 +22,13 @@ package roundrobin import ( - rand "math/rand/v2" - "sync/atomic" + "fmt" "google.golang.org/grpc/balancer" - "google.golang.org/grpc/balancer/base" + "google.golang.org/grpc/balancer/endpointsharding" + "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/grpclog" + internalgrpclog "google.golang.org/grpc/internal/grpclog" ) // Name is the name of round_robin balancer. @@ -35,47 +36,44 @@ const Name = "round_robin" var logger = grpclog.Component("roundrobin") -// newBuilder creates a new roundrobin balancer builder. -func newBuilder() balancer.Builder { - return base.NewBalancerBuilder(Name, &rrPickerBuilder{}, base.Config{HealthCheck: true}) -} - func init() { - balancer.Register(newBuilder()) + balancer.Register(builder{}) } -type rrPickerBuilder struct{} +type builder struct{} -func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker { - logger.Infof("roundrobinPicker: Build called with info: %v", info) - if len(info.ReadySCs) == 0 { - return base.NewErrPicker(balancer.ErrNoSubConnAvailable) - } - scs := make([]balancer.SubConn, 0, len(info.ReadySCs)) - for sc := range info.ReadySCs { - scs = append(scs, sc) - } - return &rrPicker{ - subConns: scs, - // Start at a random index, as the same RR balancer rebuilds a new - // picker when SubConn states change, and we don't want to apply excess - // load to the first server in the list. - next: uint32(rand.IntN(len(scs))), +func (bb builder) Name() string { + return Name +} + +func (bb builder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer { + childBuilder := balancer.Get(pickfirstleaf.Name).Build + bal := &rrBalancer{ + cc: cc, + Balancer: endpointsharding.NewBalancer(cc, opts, childBuilder, endpointsharding.Options{}), } + bal.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[%p] ", bal)) + bal.logger.Infof("Created") + return bal } -type rrPicker struct { - // subConns is the snapshot of the roundrobin balancer when this picker was - // created. The slice is immutable. Each Get() will do a round robin - // selection from it and return the selected SubConn. - subConns []balancer.SubConn - next uint32 +type rrBalancer struct { + balancer.Balancer + cc balancer.ClientConn + logger *internalgrpclog.PrefixLogger } -func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) { - subConnsLen := uint32(len(p.subConns)) - nextIndex := atomic.AddUint32(&p.next, 1) +func (b *rrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error { + return b.Balancer.UpdateClientConnState(balancer.ClientConnState{ + // Enable the health listener in pickfirst children for client side health + // checks and outlier detection, if configured. + ResolverState: pickfirstleaf.EnableHealthListener(ccs.ResolverState), + }) +} - sc := p.subConns[nextIndex%subConnsLen] - return balancer.PickResult{SubConn: sc}, nil +func (b *rrBalancer) ExitIdle() { + // Should always be ok, as child is endpoint sharding. + if ei, ok := b.Balancer.(balancer.ExitIdler); ok { + ei.ExitIdle() + } } diff --git a/vendor/google.golang.org/grpc/balancer/subconn.go b/vendor/google.golang.org/grpc/balancer/subconn.go index ea27c4fa76..9ee44d4af0 100644 --- a/vendor/google.golang.org/grpc/balancer/subconn.go +++ b/vendor/google.golang.org/grpc/balancer/subconn.go @@ -44,7 +44,7 @@ import ( // should only use a single address. // // NOTICE: This interface is intended to be implemented by gRPC, or intercepted -// by custom load balancing poilices. Users should not need their own complete +// by custom load balancing polices. Users should not need their own complete // implementation of this interface -- they should always delegate to a SubConn // returned by ClientConn.NewSubConn() by embedding it in their implementations. // An embedded SubConn must never be nil, or runtime panics will occur. diff --git a/vendor/google.golang.org/grpc/balancer_wrapper.go b/vendor/google.golang.org/grpc/balancer_wrapper.go index c2688376ae..948a21ef68 100644 --- a/vendor/google.golang.org/grpc/balancer_wrapper.go +++ b/vendor/google.golang.org/grpc/balancer_wrapper.go @@ -26,6 +26,7 @@ import ( "google.golang.org/grpc/balancer" "google.golang.org/grpc/codes" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/balancer/gracefulswitch" "google.golang.org/grpc/internal/channelz" @@ -59,6 +60,7 @@ var ( // It uses the gracefulswitch.Balancer internally to ensure that balancer // switches happen in a graceful manner. type ccBalancerWrapper struct { + internal.EnforceClientConnEmbedding // The following fields are initialized when the wrapper is created and are // read-only afterwards, and therefore can be accessed without a mutex. cc *ClientConn @@ -92,7 +94,6 @@ func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper { CustomUserAgent: cc.dopts.copts.UserAgent, ChannelzParent: cc.channelz, Target: cc.parsedTarget, - MetricsRecorder: cc.metricsRecorderList, }, serializer: grpcsync.NewCallbackSerializer(ctx), serializerCancel: cancel, @@ -101,6 +102,10 @@ func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper { return ccb } +func (ccb *ccBalancerWrapper) MetricsRecorder() stats.MetricsRecorder { + return ccb.cc.metricsRecorderList +} + // updateClientConnState is invoked by grpc to push a ClientConnState update to // the underlying balancer. This is always executed from the serializer, so // it is safe to call into the balancer here. @@ -415,7 +420,7 @@ func (acbw *acBalancerWrapper) GetOrBuildProducer(pb balancer.ProducerBuilder) ( } acbw.producersMu.Unlock() } - return pData.producer, grpcsync.OnceFunc(unref) + return pData.producer, sync.OnceFunc(unref) } func (acbw *acBalancerWrapper) closeProducers() { diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go index 21dd72969a..b2f8fc7f43 100644 --- a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go +++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.2 +// protoc-gen-go v1.36.4 // protoc v5.27.1 // source: grpc/binlog/v1/binarylog.proto @@ -31,6 +31,7 @@ import ( timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -233,10 +234,7 @@ func (Address_Type) EnumDescriptor() ([]byte, []int) { // Log entry we store in binary logs type GrpcLogEntry struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The timestamp of the binary log message Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Uniquely identifies a call. The value must not be 0 in order to disambiguate @@ -255,7 +253,7 @@ type GrpcLogEntry struct { // The logger uses one of the following fields to record the payload, // according to the type of the log entry. // - // Types that are assignable to Payload: + // Types that are valid to be assigned to Payload: // // *GrpcLogEntry_ClientHeader // *GrpcLogEntry_ServerHeader @@ -269,7 +267,9 @@ type GrpcLogEntry struct { // EVENT_TYPE_SERVER_HEADER normally or EVENT_TYPE_SERVER_TRAILER in // the case of trailers-only. On server side, peer is always // logged on EVENT_TYPE_CLIENT_HEADER. - Peer *Address `protobuf:"bytes,11,opt,name=peer,proto3" json:"peer,omitempty"` + Peer *Address `protobuf:"bytes,11,opt,name=peer,proto3" json:"peer,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GrpcLogEntry) Reset() { @@ -337,37 +337,45 @@ func (x *GrpcLogEntry) GetLogger() GrpcLogEntry_Logger { return GrpcLogEntry_LOGGER_UNKNOWN } -func (m *GrpcLogEntry) GetPayload() isGrpcLogEntry_Payload { - if m != nil { - return m.Payload +func (x *GrpcLogEntry) GetPayload() isGrpcLogEntry_Payload { + if x != nil { + return x.Payload } return nil } func (x *GrpcLogEntry) GetClientHeader() *ClientHeader { - if x, ok := x.GetPayload().(*GrpcLogEntry_ClientHeader); ok { - return x.ClientHeader + if x != nil { + if x, ok := x.Payload.(*GrpcLogEntry_ClientHeader); ok { + return x.ClientHeader + } } return nil } func (x *GrpcLogEntry) GetServerHeader() *ServerHeader { - if x, ok := x.GetPayload().(*GrpcLogEntry_ServerHeader); ok { - return x.ServerHeader + if x != nil { + if x, ok := x.Payload.(*GrpcLogEntry_ServerHeader); ok { + return x.ServerHeader + } } return nil } func (x *GrpcLogEntry) GetMessage() *Message { - if x, ok := x.GetPayload().(*GrpcLogEntry_Message); ok { - return x.Message + if x != nil { + if x, ok := x.Payload.(*GrpcLogEntry_Message); ok { + return x.Message + } } return nil } func (x *GrpcLogEntry) GetTrailer() *Trailer { - if x, ok := x.GetPayload().(*GrpcLogEntry_Trailer); ok { - return x.Trailer + if x != nil { + if x, ok := x.Payload.(*GrpcLogEntry_Trailer); ok { + return x.Trailer + } } return nil } @@ -416,10 +424,7 @@ func (*GrpcLogEntry_Message) isGrpcLogEntry_Payload() {} func (*GrpcLogEntry_Trailer) isGrpcLogEntry_Payload() {} type ClientHeader struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // This contains only the metadata from the application. Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` // The name of the RPC method, which looks something like: @@ -433,7 +438,9 @@ type ClientHeader struct { // or : . Authority string `protobuf:"bytes,3,opt,name=authority,proto3" json:"authority,omitempty"` // the RPC timeout - Timeout *durationpb.Duration `protobuf:"bytes,4,opt,name=timeout,proto3" json:"timeout,omitempty"` + Timeout *durationpb.Duration `protobuf:"bytes,4,opt,name=timeout,proto3" json:"timeout,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ClientHeader) Reset() { @@ -495,12 +502,11 @@ func (x *ClientHeader) GetTimeout() *durationpb.Duration { } type ServerHeader struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // This contains only the metadata from the application. - Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ServerHeader) Reset() { @@ -541,10 +547,7 @@ func (x *ServerHeader) GetMetadata() *Metadata { } type Trailer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // This contains only the metadata from the application. Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` // The gRPC status code. @@ -555,6 +558,8 @@ type Trailer struct { // The value of the 'grpc-status-details-bin' metadata key. If // present, this is always an encoded 'google.rpc.Status' message. StatusDetails []byte `protobuf:"bytes,4,opt,name=status_details,json=statusDetails,proto3" json:"status_details,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Trailer) Reset() { @@ -617,15 +622,14 @@ func (x *Trailer) GetStatusDetails() []byte { // Message payload, used by CLIENT_MESSAGE and SERVER_MESSAGE type Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Length of the message. It may not be the same as the length of the // data field, as the logging payload can be truncated or omitted. Length uint32 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"` // May be truncated or omitted. - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Message) Reset() { @@ -694,11 +698,10 @@ func (x *Message) GetData() []byte { // header is just a normal metadata key. // The pair will not count towards the size limit. type Metadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Entry []*MetadataEntry `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"` unknownFields protoimpl.UnknownFields - - Entry []*MetadataEntry `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Metadata) Reset() { @@ -740,12 +743,11 @@ func (x *Metadata) GetEntry() []*MetadataEntry { // A metadata key value pair type MetadataEntry struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + sizeCache protoimpl.SizeCache } func (x *MetadataEntry) Reset() { @@ -794,14 +796,13 @@ func (x *MetadataEntry) GetValue() []byte { // Address information type Address struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type Address_Type `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.binarylog.v1.Address_Type" json:"type,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Type Address_Type `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.binarylog.v1.Address_Type" json:"type,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` // only for TYPE_IPV4 and TYPE_IPV6 - IpPort uint32 `protobuf:"varint,3,opt,name=ip_port,json=ipPort,proto3" json:"ip_port,omitempty"` + IpPort uint32 `protobuf:"varint,3,opt,name=ip_port,json=ipPort,proto3" json:"ip_port,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Address) Reset() { @@ -857,7 +858,7 @@ func (x *Address) GetIpPort() uint32 { var File_grpc_binlog_v1_binarylog_proto protoreflect.FileDescriptor -var file_grpc_binlog_v1_binarylog_proto_rawDesc = []byte{ +var file_grpc_binlog_v1_binarylog_proto_rawDesc = string([]byte{ 0x0a, 0x1e, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x6c, 0x6f, 0x67, @@ -983,16 +984,16 @@ var file_grpc_binlog_v1_binarylog_proto_rawDesc = []byte{ 0x69, 0x6e, 0x61, 0x72, 0x79, 0x6c, 0x6f, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x6c, 0x6f, 0x67, 0x5f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +}) var ( file_grpc_binlog_v1_binarylog_proto_rawDescOnce sync.Once - file_grpc_binlog_v1_binarylog_proto_rawDescData = file_grpc_binlog_v1_binarylog_proto_rawDesc + file_grpc_binlog_v1_binarylog_proto_rawDescData []byte ) func file_grpc_binlog_v1_binarylog_proto_rawDescGZIP() []byte { file_grpc_binlog_v1_binarylog_proto_rawDescOnce.Do(func() { - file_grpc_binlog_v1_binarylog_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_binlog_v1_binarylog_proto_rawDescData) + file_grpc_binlog_v1_binarylog_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_grpc_binlog_v1_binarylog_proto_rawDesc), len(file_grpc_binlog_v1_binarylog_proto_rawDesc))) }) return file_grpc_binlog_v1_binarylog_proto_rawDescData } @@ -1051,7 +1052,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_grpc_binlog_v1_binarylog_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_grpc_binlog_v1_binarylog_proto_rawDesc), len(file_grpc_binlog_v1_binarylog_proto_rawDesc)), NumEnums: 3, NumMessages: 8, NumExtensions: 0, @@ -1063,7 +1064,6 @@ func file_grpc_binlog_v1_binarylog_proto_init() { MessageInfos: file_grpc_binlog_v1_binarylog_proto_msgTypes, }.Build() File_grpc_binlog_v1_binarylog_proto = out.File - file_grpc_binlog_v1_binarylog_proto_rawDesc = nil file_grpc_binlog_v1_binarylog_proto_goTypes = nil file_grpc_binlog_v1_binarylog_proto_depIdxs = nil } diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index 4f57b55434..a319ef9794 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -118,12 +118,26 @@ func (dcs *defaultConfigSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*ires // NewClient creates a new gRPC "channel" for the target URI provided. No I/O // is performed. Use of the ClientConn for RPCs will automatically cause it to -// connect. Connect may be used to manually create a connection, but for most -// users this is unnecessary. +// connect. The Connect method may be called to manually create a connection, +// but for most users this should be unnecessary. // // The target name syntax is defined in -// https://github.com/grpc/grpc/blob/master/doc/naming.md. e.g. to use dns -// resolver, a "dns:///" prefix should be applied to the target. +// https://github.com/grpc/grpc/blob/master/doc/naming.md. E.g. to use the dns +// name resolver, a "dns:///" prefix may be applied to the target. The default +// name resolver will be used if no scheme is detected, or if the parsed scheme +// is not a registered name resolver. The default resolver is "dns" but can be +// overridden using the resolver package's SetDefaultScheme. +// +// Examples: +// +// - "foo.googleapis.com:8080" +// - "dns:///foo.googleapis.com:8080" +// - "dns:///foo.googleapis.com" +// - "dns:///10.0.0.213:8080" +// - "dns:///%5B2001:db8:85a3:8d3:1319:8a2e:370:7348%5D:443" +// - "dns://8.8.8.8/foo.googleapis.com:8080" +// - "dns://8.8.8.8/foo.googleapis.com" +// - "zookeeper://zk.example.com:9900/example_service" // // The DialOptions returned by WithBlock, WithTimeout, // WithReturnConnectionError, and FailOnNonTempDialError are ignored by this @@ -181,7 +195,7 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error) } cc.dopts.defaultServiceConfig, _ = scpr.Config.(*ServiceConfig) } - cc.mkp = cc.dopts.copts.KeepaliveParams + cc.keepaliveParams = cc.dopts.copts.KeepaliveParams if err = cc.initAuthority(); err != nil { return nil, err @@ -225,7 +239,12 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) { func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) { // At the end of this method, we kick the channel out of idle, rather than // waiting for the first rpc. - opts = append([]DialOption{withDefaultScheme("passthrough")}, opts...) + // + // WithLocalDNSResolution dial option in `grpc.Dial` ensures that it + // preserves behavior: when default scheme passthrough is used, skip + // hostname resolution, when "dns" is used for resolution, perform + // resolution on the client. + opts = append([]DialOption{withDefaultScheme("passthrough"), WithLocalDNSResolution()}, opts...) cc, err := NewClient(target, opts...) if err != nil { return nil, err @@ -618,7 +637,7 @@ type ClientConn struct { balancerWrapper *ccBalancerWrapper // Always recreated whenever entering idle to simplify Close. sc *ServiceConfig // Latest service config received from the resolver. conns map[*addrConn]struct{} // Set to nil on close. - mkp keepalive.ClientParameters // May be updated upon receipt of a GoAway. + keepaliveParams keepalive.ClientParameters // May be updated upon receipt of a GoAway. // firstResolveEvent is used to track whether the name resolver sent us at // least one update. RPCs block on this event. May be accessed without mu // if we know we cannot be asked to enter idle mode while accessing it (e.g. @@ -867,7 +886,13 @@ func (cc *ClientConn) Target() string { return cc.target } -// CanonicalTarget returns the canonical target string of the ClientConn. +// CanonicalTarget returns the canonical target string used when creating cc. +// +// This always has the form "://[authority]/". For example: +// +// - "dns:///example.com:42" +// - "dns://8.8.8.8/example.com:42" +// - "unix:///path/to/socket" func (cc *ClientConn) CanonicalTarget() string { return cc.parsedTarget.String() } @@ -1210,8 +1235,8 @@ func (ac *addrConn) adjustParams(r transport.GoAwayReason) { case transport.GoAwayTooManyPings: v := 2 * ac.dopts.copts.KeepaliveParams.Time ac.cc.mu.Lock() - if v > ac.cc.mkp.Time { - ac.cc.mkp.Time = v + if v > ac.cc.keepaliveParams.Time { + ac.cc.keepaliveParams.Time = v } ac.cc.mu.Unlock() } @@ -1307,7 +1332,7 @@ func (ac *addrConn) tryAllAddrs(ctx context.Context, addrs []resolver.Address, c ac.mu.Lock() ac.cc.mu.RLock() - ac.dopts.copts.KeepaliveParams = ac.cc.mkp + ac.dopts.copts.KeepaliveParams = ac.cc.keepaliveParams ac.cc.mu.RUnlock() copts := ac.dopts.copts diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go index f3a045296a..405a2ffeb3 100644 --- a/vendor/google.golang.org/grpc/dialoptions.go +++ b/vendor/google.golang.org/grpc/dialoptions.go @@ -73,7 +73,7 @@ type dialOptions struct { chainUnaryInts []UnaryClientInterceptor chainStreamInts []StreamClientInterceptor - cp Compressor + compressorV0 Compressor dc Decompressor bs internalbackoff.Strategy block bool @@ -94,6 +94,8 @@ type dialOptions struct { idleTimeout time.Duration defaultScheme string maxCallAttempts int + enableLocalDNSResolution bool // Specifies if target hostnames should be resolved when proxying is enabled. + useProxy bool // Specifies if a server should be connected via proxy. } // DialOption configures how we set up the connection. @@ -256,7 +258,7 @@ func WithCodec(c Codec) DialOption { // Deprecated: use UseCompressor instead. Will be supported throughout 1.x. func WithCompressor(cp Compressor) DialOption { return newFuncDialOption(func(o *dialOptions) { - o.cp = cp + o.compressorV0 = cp }) } @@ -377,7 +379,22 @@ func WithInsecure() DialOption { // later release. func WithNoProxy() DialOption { return newFuncDialOption(func(o *dialOptions) { - o.copts.UseProxy = false + o.useProxy = false + }) +} + +// WithLocalDNSResolution forces local DNS name resolution even when a proxy is +// specified in the environment. By default, the server name is provided +// directly to the proxy as part of the CONNECT handshake. This is ignored if +// WithNoProxy is used. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func WithLocalDNSResolution() DialOption { + return newFuncDialOption(func(o *dialOptions) { + o.enableLocalDNSResolution = true }) } @@ -667,14 +684,15 @@ func defaultDialOptions() dialOptions { copts: transport.ConnectOptions{ ReadBufferSize: defaultReadBufSize, WriteBufferSize: defaultWriteBufSize, - UseProxy: true, UserAgent: grpcUA, BufferPool: mem.DefaultBufferPool(), }, - bs: internalbackoff.DefaultExponential, - idleTimeout: 30 * time.Minute, - defaultScheme: "dns", - maxCallAttempts: defaultMaxCallAttempts, + bs: internalbackoff.DefaultExponential, + idleTimeout: 30 * time.Minute, + defaultScheme: "dns", + maxCallAttempts: defaultMaxCallAttempts, + useProxy: true, + enableLocalDNSResolution: false, } } diff --git a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go index 73bb4c4ee9..fbc1ca356a 100644 --- a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go +++ b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go @@ -109,8 +109,9 @@ func (gsb *Balancer) switchTo(builder balancer.Builder) (*balancerWrapper, error return nil, errBalancerClosed } bw := &balancerWrapper{ - builder: builder, - gsb: gsb, + ClientConn: gsb.cc, + builder: builder, + gsb: gsb, lastState: balancer.State{ ConnectivityState: connectivity.Connecting, Picker: base.NewErrPicker(balancer.ErrNoSubConnAvailable), @@ -293,6 +294,7 @@ func (gsb *Balancer) Close() { // State updates from the wrapped balancer can result in invocation of the // graceful switch logic. type balancerWrapper struct { + balancer.ClientConn balancer.Balancer gsb *Balancer builder balancer.Builder @@ -413,7 +415,3 @@ func (bw *balancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver bw.gsb.mu.Unlock() bw.gsb.cc.UpdateAddresses(sc, addrs) } - -func (bw *balancerWrapper) Target() string { - return bw.gsb.cc.Target() -} diff --git a/vendor/google.golang.org/grpc/internal/envconfig/xds.go b/vendor/google.golang.org/grpc/internal/envconfig/xds.go index 9afeb444d4..2eb97f832b 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/xds.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/xds.go @@ -56,7 +56,11 @@ var ( // XDSDualstackEndpointsEnabled is true if gRPC should read the // "additional addresses" in the xDS endpoint resource. - // TODO: https://github.com/grpc/grpc-go/issues/7866 - Control this using - // an env variable when all LB policies handle endpoints. - XDSDualstackEndpointsEnabled = false + XDSDualstackEndpointsEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_DUALSTACK_ENDPOINTS", true) + + // XDSSystemRootCertsEnabled is true when xDS enabled gRPC clients can use + // the system's default root certificates for TLS certificate validation. + // For more details, see: + // https://github.com/grpc/proposal/blob/master/A82-xds-system-root-certs.md. + XDSSystemRootCertsEnabled = boolFromEnv("GRPC_EXPERIMENTAL_XDS_SYSTEM_ROOT_CERTS", false) ) diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/oncefunc.go b/vendor/google.golang.org/grpc/internal/grpcsync/oncefunc.go deleted file mode 100644 index 6635f7bca9..0000000000 --- a/vendor/google.golang.org/grpc/internal/grpcsync/oncefunc.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Copyright 2022 gRPC 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 grpcsync - -import ( - "sync" -) - -// OnceFunc returns a function wrapping f which ensures f is only executed -// once even if the returned function is executed multiple times. -func OnceFunc(f func()) func() { - var once sync.Once - return func() { - once.Do(f) - } -} diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go index c17b98194b..13e1f386b1 100644 --- a/vendor/google.golang.org/grpc/internal/internal.go +++ b/vendor/google.golang.org/grpc/internal/internal.go @@ -64,6 +64,9 @@ var ( // gRPC server. An xDS-enabled server needs to know what type of credentials // is configured on the underlying gRPC server. This is set by server.go. GetServerCredentials any // func (*grpc.Server) credentials.TransportCredentials + // MetricsRecorderForServer returns the MetricsRecorderList derived from a + // server's stats handlers. + MetricsRecorderForServer any // func (*grpc.Server) estats.MetricsRecorder // CanonicalString returns the canonical string of the code defined here: // https://github.com/grpc/grpc/blob/master/doc/statuscodes.md. // @@ -151,6 +154,20 @@ var ( // other features, including the CSDS service. NewXDSResolverWithConfigForTesting any // func([]byte) (resolver.Builder, error) + // NewXDSResolverWithPoolForTesting creates a new xDS resolver builder + // using the provided xDS pool instead of creating a new one using the + // bootstrap configuration specified by the supported environment variables. + // The resolver.Builder is meant to be used in conjunction with the + // grpc.WithResolvers DialOption. The resolver.Builder does not take + // ownership of the provided xDS client and it is the responsibility of the + // caller to close the client when no longer required. + // + // Testing Only + // + // This function should ONLY be used for testing and may not work with some + // other features, including the CSDS service. + NewXDSResolverWithPoolForTesting any // func(*xdsclient.Pool) (resolver.Builder, error) + // NewXDSResolverWithClientForTesting creates a new xDS resolver builder // using the provided xDS client instead of creating a new one using the // bootstrap configuration specified by the supported environment variables. @@ -277,3 +294,9 @@ const RLSLoadBalancingPolicyName = "rls_experimental" type EnforceSubConnEmbedding interface { enforceSubConnEmbedding() } + +// EnforceClientConnEmbedding is used to enforce proper ClientConn implementation +// embedding. +type EnforceClientConnEmbedding interface { + enforceClientConnEmbedding() +} diff --git a/vendor/google.golang.org/grpc/internal/proxyattributes/proxyattributes.go b/vendor/google.golang.org/grpc/internal/proxyattributes/proxyattributes.go new file mode 100644 index 0000000000..1f61f1a49d --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/proxyattributes/proxyattributes.go @@ -0,0 +1,54 @@ +/* + * + * Copyright 2024 gRPC 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 proxyattributes contains functions for getting and setting proxy +// attributes like the CONNECT address and user info. +package proxyattributes + +import ( + "net/url" + + "google.golang.org/grpc/resolver" +) + +type keyType string + +const proxyOptionsKey = keyType("grpc.resolver.delegatingresolver.proxyOptions") + +// Options holds the proxy connection details needed during the CONNECT +// handshake. +type Options struct { + User *url.Userinfo + ConnectAddr string +} + +// Set returns a copy of addr with opts set in its attributes. +func Set(addr resolver.Address, opts Options) resolver.Address { + addr.Attributes = addr.Attributes.WithValue(proxyOptionsKey, opts) + return addr +} + +// Get returns the Options for the proxy [resolver.Address] and a boolean +// value representing if the attribute is present or not. The returned data +// should not be mutated. +func Get(addr resolver.Address) (Options, bool) { + if a := addr.Attributes.Value(proxyOptionsKey); a != nil { + return a.(Options), true + } + return Options{}, false +} diff --git a/vendor/google.golang.org/grpc/internal/resolver/delegatingresolver/delegatingresolver.go b/vendor/google.golang.org/grpc/internal/resolver/delegatingresolver/delegatingresolver.go new file mode 100644 index 0000000000..a6c6470133 --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/resolver/delegatingresolver/delegatingresolver.go @@ -0,0 +1,329 @@ +/* + * + * Copyright 2024 gRPC 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 delegatingresolver implements a resolver capable of resolving both +// target URIs and proxy addresses. +package delegatingresolver + +import ( + "fmt" + "net/http" + "net/url" + "sync" + + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/internal/proxyattributes" + "google.golang.org/grpc/resolver" + "google.golang.org/grpc/serviceconfig" +) + +var ( + logger = grpclog.Component("delegating-resolver") + // HTTPSProxyFromEnvironment will be overwritten in the tests + HTTPSProxyFromEnvironment = http.ProxyFromEnvironment +) + +// delegatingResolver manages both target URI and proxy address resolution by +// delegating these tasks to separate child resolvers. Essentially, it acts as +// a intermediary between the gRPC ClientConn and the child resolvers. +// +// It implements the [resolver.Resolver] interface. +type delegatingResolver struct { + target resolver.Target // parsed target URI to be resolved + cc resolver.ClientConn // gRPC ClientConn + targetResolver resolver.Resolver // resolver for the target URI, based on its scheme + proxyResolver resolver.Resolver // resolver for the proxy URI; nil if no proxy is configured + proxyURL *url.URL // proxy URL, derived from proxy environment and target + + mu sync.Mutex // protects all the fields below + targetResolverState *resolver.State // state of the target resolver + proxyAddrs []resolver.Address // resolved proxy addresses; empty if no proxy is configured +} + +// nopResolver is a resolver that does nothing. +type nopResolver struct{} + +func (nopResolver) ResolveNow(resolver.ResolveNowOptions) {} + +func (nopResolver) Close() {} + +// proxyURLForTarget determines the proxy URL for the given address based on +// the environment. It can return the following: +// - nil URL, nil error: No proxy is configured or the address is excluded +// using the `NO_PROXY` environment variable or if req.URL.Host is +// "localhost" (with or without // a port number) +// - nil URL, non-nil error: An error occurred while retrieving the proxy URL. +// - non-nil URL, nil error: A proxy is configured, and the proxy URL was +// retrieved successfully without any errors. +func proxyURLForTarget(address string) (*url.URL, error) { + req := &http.Request{URL: &url.URL{ + Scheme: "https", + Host: address, + }} + return HTTPSProxyFromEnvironment(req) +} + +// New creates a new delegating resolver that can create up to two child +// resolvers: +// - one to resolve the proxy address specified using the supported +// environment variables. This uses the registered resolver for the "dns" +// scheme. +// - one to resolve the target URI using the resolver specified by the scheme +// in the target URI or specified by the user using the WithResolvers dial +// option. As a special case, if the target URI's scheme is "dns" and a +// proxy is specified using the supported environment variables, the target +// URI's path portion is used as the resolved address unless target +// resolution is enabled using the dial option. +func New(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions, targetResolverBuilder resolver.Builder, targetResolutionEnabled bool) (resolver.Resolver, error) { + r := &delegatingResolver{ + target: target, + cc: cc, + } + + var err error + r.proxyURL, err = proxyURLForTarget(target.Endpoint()) + if err != nil { + return nil, fmt.Errorf("delegating_resolver: failed to determine proxy URL for target %s: %v", target, err) + } + + // proxy is not configured or proxy address excluded using `NO_PROXY` env + // var, so only target resolver is used. + if r.proxyURL == nil { + return targetResolverBuilder.Build(target, cc, opts) + } + + if logger.V(2) { + logger.Infof("Proxy URL detected : %s", r.proxyURL) + } + + // When the scheme is 'dns' and target resolution on client is not enabled, + // resolution should be handled by the proxy, not the client. Therefore, we + // bypass the target resolver and store the unresolved target address. + if target.URL.Scheme == "dns" && !targetResolutionEnabled { + state := resolver.State{ + Addresses: []resolver.Address{{Addr: target.Endpoint()}}, + Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: target.Endpoint()}}}}, + } + r.targetResolverState = &state + } else { + wcc := &wrappingClientConn{ + stateListener: r.updateTargetResolverState, + parent: r, + } + if r.targetResolver, err = targetResolverBuilder.Build(target, wcc, opts); err != nil { + return nil, fmt.Errorf("delegating_resolver: unable to build the resolver for target %s: %v", target, err) + } + } + + if r.proxyResolver, err = r.proxyURIResolver(opts); err != nil { + return nil, fmt.Errorf("delegating_resolver: failed to build resolver for proxy URL %q: %v", r.proxyURL, err) + } + + if r.targetResolver == nil { + r.targetResolver = nopResolver{} + } + if r.proxyResolver == nil { + r.proxyResolver = nopResolver{} + } + return r, nil +} + +// proxyURIResolver creates a resolver for resolving proxy URIs using the +// "dns" scheme. It adjusts the proxyURL to conform to the "dns:///" format and +// builds a resolver with a wrappingClientConn to capture resolved addresses. +func (r *delegatingResolver) proxyURIResolver(opts resolver.BuildOptions) (resolver.Resolver, error) { + proxyBuilder := resolver.Get("dns") + if proxyBuilder == nil { + panic("delegating_resolver: resolver for proxy not found for scheme dns") + } + url := *r.proxyURL + url.Scheme = "dns" + url.Path = "/" + r.proxyURL.Host + url.Host = "" // Clear the Host field to conform to the "dns:///" format + + proxyTarget := resolver.Target{URL: url} + wcc := &wrappingClientConn{ + stateListener: r.updateProxyResolverState, + parent: r, + } + return proxyBuilder.Build(proxyTarget, wcc, opts) +} + +func (r *delegatingResolver) ResolveNow(o resolver.ResolveNowOptions) { + r.targetResolver.ResolveNow(o) + r.proxyResolver.ResolveNow(o) +} + +func (r *delegatingResolver) Close() { + r.targetResolver.Close() + r.targetResolver = nil + + r.proxyResolver.Close() + r.proxyResolver = nil +} + +// updateClientConnStateLocked creates a list of combined addresses by +// pairing each proxy address with every target address. For each pair, it +// generates a new [resolver.Address] using the proxy address, and adding the +// target address as the attribute along with user info. It returns nil if +// either resolver has not sent update even once and returns the error from +// ClientConn update once both resolvers have sent update atleast once. +func (r *delegatingResolver) updateClientConnStateLocked() error { + if r.targetResolverState == nil || r.proxyAddrs == nil { + return nil + } + + curState := *r.targetResolverState + // If multiple resolved proxy addresses are present, we send only the + // unresolved proxy host and let net.Dial handle the proxy host name + // resolution when creating the transport. Sending all resolved addresses + // would increase the number of addresses passed to the ClientConn and + // subsequently to load balancing (LB) policies like Round Robin, leading + // to additional TCP connections. However, if there's only one resolved + // proxy address, we send it directly, as it doesn't affect the address + // count returned by the target resolver and the address count sent to the + // ClientConn. + var proxyAddr resolver.Address + if len(r.proxyAddrs) == 1 { + proxyAddr = r.proxyAddrs[0] + } else { + proxyAddr = resolver.Address{Addr: r.proxyURL.Host} + } + var addresses []resolver.Address + for _, targetAddr := range (*r.targetResolverState).Addresses { + addresses = append(addresses, proxyattributes.Set(proxyAddr, proxyattributes.Options{ + User: r.proxyURL.User, + ConnectAddr: targetAddr.Addr, + })) + } + + // Create a list of combined endpoints by pairing all proxy endpoints + // with every target endpoint. Each time, it constructs a new + // [resolver.Endpoint] using the all addresses from all the proxy endpoint + // and the target addresses from one endpoint. The target address and user + // information from the proxy URL are added as attributes to the proxy + // address.The resulting list of addresses is then grouped into endpoints, + // covering all combinations of proxy and target endpoints. + var endpoints []resolver.Endpoint + for _, endpt := range (*r.targetResolverState).Endpoints { + var addrs []resolver.Address + for _, proxyAddr := range r.proxyAddrs { + for _, targetAddr := range endpt.Addresses { + addrs = append(addrs, proxyattributes.Set(proxyAddr, proxyattributes.Options{ + User: r.proxyURL.User, + ConnectAddr: targetAddr.Addr, + })) + } + } + endpoints = append(endpoints, resolver.Endpoint{Addresses: addrs}) + } + // Use the targetResolverState for its service config and attributes + // contents. The state update is only sent after both the target and proxy + // resolvers have sent their updates, and curState has been updated with + // the combined addresses. + curState.Addresses = addresses + curState.Endpoints = endpoints + return r.cc.UpdateState(curState) +} + +// updateProxyResolverState updates the proxy resolver state by storing proxy +// addresses and endpoints, marking the resolver as ready, and triggering a +// state update if both proxy and target resolvers are ready. If the ClientConn +// returns a non-nil error, it calls `ResolveNow()` on the target resolver. It +// is a StateListener function of wrappingClientConn passed to the proxy resolver. +func (r *delegatingResolver) updateProxyResolverState(state resolver.State) error { + r.mu.Lock() + defer r.mu.Unlock() + if logger.V(2) { + logger.Infof("Addresses received from proxy resolver: %s", state.Addresses) + } + if len(state.Endpoints) > 0 { + // We expect exactly one address per endpoint because the proxy + // resolver uses "dns" resolution. + r.proxyAddrs = make([]resolver.Address, 0, len(state.Endpoints)) + for _, endpoint := range state.Endpoints { + r.proxyAddrs = append(r.proxyAddrs, endpoint.Addresses...) + } + } else if state.Addresses != nil { + r.proxyAddrs = state.Addresses + } else { + r.proxyAddrs = []resolver.Address{} // ensure proxyAddrs is non-nil to indicate an update has been received + } + err := r.updateClientConnStateLocked() + // Another possible approach was to block until updates are received from + // both resolvers. But this is not used because calling `New()` triggers + // `Build()` for the first resolver, which calls `UpdateState()`. And the + // second resolver hasn't sent an update yet, so it would cause `New()` to + // block indefinitely. + if err != nil { + r.targetResolver.ResolveNow(resolver.ResolveNowOptions{}) + } + return err +} + +// updateTargetResolverState updates the target resolver state by storing target +// addresses, endpoints, and service config, marking the resolver as ready, and +// triggering a state update if both resolvers are ready. If the ClientConn +// returns a non-nil error, it calls `ResolveNow()` on the proxy resolver. It +// is a StateListener function of wrappingClientConn passed to the target resolver. +func (r *delegatingResolver) updateTargetResolverState(state resolver.State) error { + r.mu.Lock() + defer r.mu.Unlock() + + if logger.V(2) { + logger.Infof("Addresses received from target resolver: %v", state.Addresses) + } + r.targetResolverState = &state + err := r.updateClientConnStateLocked() + if err != nil { + r.proxyResolver.ResolveNow(resolver.ResolveNowOptions{}) + } + return nil +} + +// wrappingClientConn serves as an intermediary between the parent ClientConn +// and the child resolvers created here. It implements the resolver.ClientConn +// interface and is passed in that capacity to the child resolvers. +type wrappingClientConn struct { + // Callback to deliver resolver state updates + stateListener func(state resolver.State) error + parent *delegatingResolver +} + +// UpdateState receives resolver state updates and forwards them to the +// appropriate listener function (either for the proxy or target resolver). +func (wcc *wrappingClientConn) UpdateState(state resolver.State) error { + return wcc.stateListener(state) +} + +// ReportError intercepts errors from the child resolvers and passes them to ClientConn. +func (wcc *wrappingClientConn) ReportError(err error) { + wcc.parent.cc.ReportError(err) +} + +// NewAddress intercepts the new resolved address from the child resolvers and +// passes them to ClientConn. +func (wcc *wrappingClientConn) NewAddress(addrs []resolver.Address) { + wcc.UpdateState(resolver.State{Addresses: addrs}) +} + +// ParseServiceConfig parses the provided service config and returns an +// object that provides the parsed config. +func (wcc *wrappingClientConn) ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult { + return wcc.parent.cc.ParseServiceConfig(serviceConfigJSON) +} diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go index f323ab7f45..513dbb93d5 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -43,6 +43,7 @@ import ( "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcutil" imetadata "google.golang.org/grpc/internal/metadata" + "google.golang.org/grpc/internal/proxyattributes" istatus "google.golang.org/grpc/internal/status" isyscall "google.golang.org/grpc/internal/syscall" "google.golang.org/grpc/internal/transport/networktype" @@ -153,7 +154,7 @@ type http2Client struct { logger *grpclog.PrefixLogger } -func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr resolver.Address, useProxy bool, grpcUA string) (net.Conn, error) { +func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr resolver.Address, grpcUA string) (net.Conn, error) { address := addr.Addr networkType, ok := networktype.Get(addr) if fn != nil { @@ -177,8 +178,8 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error if !ok { networkType, address = parseDialTarget(address) } - if networkType == "tcp" && useProxy { - return proxyDial(ctx, address, grpcUA) + if opts, present := proxyattributes.Get(addr); present { + return proxyDial(ctx, addr, grpcUA, opts) } return internal.NetDialerWithTCPKeepalive().DialContext(ctx, networkType, address) } @@ -217,7 +218,7 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts // address specific arbitrary data to reach custom dialers and credential handshakers. connectCtx = icredentials.NewClientHandshakeInfoContext(connectCtx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes}) - conn, err := dial(connectCtx, opts.Dialer, addr, opts.UseProxy, opts.UserAgent) + conn, err := dial(connectCtx, opts.Dialer, addr, opts.UserAgent) if err != nil { if opts.FailOnNonTempDialError { return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err) diff --git a/vendor/google.golang.org/grpc/internal/transport/proxy.go b/vendor/google.golang.org/grpc/internal/transport/proxy.go index 54b2244365..d773845955 100644 --- a/vendor/google.golang.org/grpc/internal/transport/proxy.go +++ b/vendor/google.golang.org/grpc/internal/transport/proxy.go @@ -30,34 +30,16 @@ import ( "net/url" "google.golang.org/grpc/internal" + "google.golang.org/grpc/internal/proxyattributes" + "google.golang.org/grpc/resolver" ) const proxyAuthHeaderKey = "Proxy-Authorization" -var ( - // The following variable will be overwritten in the tests. - httpProxyFromEnvironment = http.ProxyFromEnvironment -) - -func mapAddress(address string) (*url.URL, error) { - req := &http.Request{ - URL: &url.URL{ - Scheme: "https", - Host: address, - }, - } - url, err := httpProxyFromEnvironment(req) - if err != nil { - return nil, err - } - return url, nil -} - // To read a response from a net.Conn, http.ReadResponse() takes a bufio.Reader. -// It's possible that this reader reads more than what's need for the response and stores -// those bytes in the buffer. -// bufConn wraps the original net.Conn and the bufio.Reader to make sure we don't lose the -// bytes in the buffer. +// It's possible that this reader reads more than what's need for the response +// and stores those bytes in the buffer. bufConn wraps the original net.Conn +// and the bufio.Reader to make sure we don't lose the bytes in the buffer. type bufConn struct { net.Conn r io.Reader @@ -72,7 +54,7 @@ func basicAuth(username, password string) string { return base64.StdEncoding.EncodeToString([]byte(auth)) } -func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr string, proxyURL *url.URL, grpcUA string) (_ net.Conn, err error) { +func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, grpcUA string, opts proxyattributes.Options) (_ net.Conn, err error) { defer func() { if err != nil { conn.Close() @@ -81,15 +63,14 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr stri req := &http.Request{ Method: http.MethodConnect, - URL: &url.URL{Host: backendAddr}, + URL: &url.URL{Host: opts.ConnectAddr}, Header: map[string][]string{"User-Agent": {grpcUA}}, } - if t := proxyURL.User; t != nil { - u := t.Username() - p, _ := t.Password() + if user := opts.User; user != nil { + u := user.Username() + p, _ := user.Password() req.Header.Add(proxyAuthHeaderKey, "Basic "+basicAuth(u, p)) } - if err := sendHTTPRequest(ctx, req, conn); err != nil { return nil, fmt.Errorf("failed to write the HTTP request: %v", err) } @@ -117,28 +98,13 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr stri return conn, nil } -// proxyDial dials, connecting to a proxy first if necessary. Checks if a proxy -// is necessary, dials, does the HTTP CONNECT handshake, and returns the -// connection. -func proxyDial(ctx context.Context, addr string, grpcUA string) (net.Conn, error) { - newAddr := addr - proxyURL, err := mapAddress(addr) - if err != nil { - return nil, err - } - if proxyURL != nil { - newAddr = proxyURL.Host - } - - conn, err := internal.NetDialerWithTCPKeepalive().DialContext(ctx, "tcp", newAddr) +// proxyDial establishes a TCP connection to the specified address and performs an HTTP CONNECT handshake. +func proxyDial(ctx context.Context, addr resolver.Address, grpcUA string, opts proxyattributes.Options) (net.Conn, error) { + conn, err := internal.NetDialerWithTCPKeepalive().DialContext(ctx, "tcp", addr.Addr) if err != nil { return nil, err } - if proxyURL == nil { - // proxy is disabled if proxyURL is nil. - return conn, err - } - return doHTTPConnectHandshake(ctx, conn, addr, proxyURL, grpcUA) + return doHTTPConnectHandshake(ctx, conn, grpcUA, opts) } func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error { diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index 2859b87755..af4a4aeab1 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -502,8 +502,6 @@ type ConnectOptions struct { ChannelzParent *channelz.SubChannel // MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received. MaxHeaderListSize *uint32 - // UseProxy specifies if a proxy should be used. - UseProxy bool // The mem.BufferPool to use when reading/writing to the wire. BufferPool mem.BufferPool } diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go index bdaa2130e4..a2d2a798d4 100644 --- a/vendor/google.golang.org/grpc/picker_wrapper.go +++ b/vendor/google.golang.org/grpc/picker_wrapper.go @@ -123,7 +123,7 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. if lastPickErr != nil { errStr = "latest balancer error: " + lastPickErr.Error() } else { - errStr = fmt.Sprintf("received context error while waiting for new LB policy update: %s", ctx.Err().Error()) + errStr = fmt.Sprintf("%v while waiting for connections to become ready", ctx.Err()) } switch ctx.Err() { case context.DeadlineExceeded: diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go index 8eb1cf3bcf..b84ef26d46 100644 --- a/vendor/google.golang.org/grpc/resolver/resolver.go +++ b/vendor/google.golang.org/grpc/resolver/resolver.go @@ -30,6 +30,7 @@ import ( "google.golang.org/grpc/attributes" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/internal" "google.golang.org/grpc/serviceconfig" ) @@ -175,6 +176,8 @@ type BuildOptions struct { // Authority is the effective authority of the clientconn for which the // resolver is built. Authority string + // MetricsRecorder is the metrics recorder to do recording. + MetricsRecorder stats.MetricsRecorder } // An Endpoint is one network endpoint, or server, which may have multiple diff --git a/vendor/google.golang.org/grpc/resolver_wrapper.go b/vendor/google.golang.org/grpc/resolver_wrapper.go index 23bb3fb258..945e24ff83 100644 --- a/vendor/google.golang.org/grpc/resolver_wrapper.go +++ b/vendor/google.golang.org/grpc/resolver_wrapper.go @@ -26,6 +26,7 @@ import ( "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/pretty" + "google.golang.org/grpc/internal/resolver/delegatingresolver" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" ) @@ -76,9 +77,19 @@ func (ccr *ccResolverWrapper) start() error { CredsBundle: ccr.cc.dopts.copts.CredsBundle, Dialer: ccr.cc.dopts.copts.Dialer, Authority: ccr.cc.authority, + MetricsRecorder: ccr.cc.metricsRecorderList, } var err error - ccr.resolver, err = ccr.cc.resolverBuilder.Build(ccr.cc.parsedTarget, ccr, opts) + // The delegating resolver is used unless: + // - A custom dialer is provided via WithContextDialer dialoption or + // - Proxy usage is disabled through WithNoProxy dialoption. + // In these cases, the resolver is built based on the scheme of target, + // using the appropriate resolver builder. + if ccr.cc.dopts.copts.Dialer != nil || !ccr.cc.dopts.useProxy { + ccr.resolver, err = ccr.cc.resolverBuilder.Build(ccr.cc.parsedTarget, ccr, opts) + } else { + ccr.resolver, err = delegatingresolver.New(ccr.cc.parsedTarget, ccr, opts, ccr.cc.resolverBuilder, ccr.cc.dopts.enableLocalDNSResolution) + } errCh <- err }) return <-errCh diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go index 9fac2b08b4..a8ddb0af52 100644 --- a/vendor/google.golang.org/grpc/rpc_util.go +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -151,7 +151,7 @@ func (d *gzipDecompressor) Type() string { // callInfo contains all related configuration and information about an RPC. type callInfo struct { - compressorType string + compressorName string failFast bool maxReceiveMessageSize *int maxSendMessageSize *int @@ -222,7 +222,7 @@ type HeaderCallOption struct { func (o HeaderCallOption) before(*callInfo) error { return nil } func (o HeaderCallOption) after(_ *callInfo, attempt *csAttempt) { - *o.HeaderAddr, _ = attempt.s.Header() + *o.HeaderAddr, _ = attempt.transportStream.Header() } // Trailer returns a CallOptions that retrieves the trailer metadata @@ -244,7 +244,7 @@ type TrailerCallOption struct { func (o TrailerCallOption) before(*callInfo) error { return nil } func (o TrailerCallOption) after(_ *callInfo, attempt *csAttempt) { - *o.TrailerAddr = attempt.s.Trailer() + *o.TrailerAddr = attempt.transportStream.Trailer() } // Peer returns a CallOption that retrieves peer information for a unary RPC. @@ -266,7 +266,7 @@ type PeerCallOption struct { func (o PeerCallOption) before(*callInfo) error { return nil } func (o PeerCallOption) after(_ *callInfo, attempt *csAttempt) { - if x, ok := peer.FromContext(attempt.s.Context()); ok { + if x, ok := peer.FromContext(attempt.transportStream.Context()); ok { *o.PeerAddr = *x } } @@ -435,7 +435,7 @@ type CompressorCallOption struct { } func (o CompressorCallOption) before(c *callInfo) error { - c.compressorType = o.CompressorType + c.compressorName = o.CompressorType return nil } func (o CompressorCallOption) after(*callInfo, *csAttempt) {} @@ -692,9 +692,9 @@ func encode(c baseCodec, msg any) (mem.BufferSlice, error) { if err != nil { return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error()) } - if uint(b.Len()) > math.MaxUint32 { + if bufSize := uint(b.Len()); bufSize > math.MaxUint32 { b.Free() - return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b)) + return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", bufSize) } return b, nil } @@ -828,30 +828,13 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM return nil, st.Err() } - var size int if pf.isCompressed() { defer compressed.Free() - // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor, // use this decompressor as the default. - if dc != nil { - var uncompressedBuf []byte - uncompressedBuf, err = dc.Do(compressed.Reader()) - if err == nil { - out = mem.BufferSlice{mem.SliceBuffer(uncompressedBuf)} - } - size = len(uncompressedBuf) - } else { - out, size, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) - } + out, err = decompress(compressor, compressed, dc, maxReceiveMessageSize, p.bufferPool) if err != nil { - return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) - } - if size > maxReceiveMessageSize { - out.Free() - // TODO: Revisit the error code. Currently keep it consistent with java - // implementation. - return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) + return nil, err } } else { out = compressed @@ -866,20 +849,46 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM return out, nil } -// Using compressor, decompress d, returning data and size. -// Optionally, if data will be over maxReceiveMessageSize, just return the size. -func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, int, error) { - dcReader, err := compressor.Decompress(d.Reader()) - if err != nil { - return nil, 0, err +// decompress processes the given data by decompressing it using either a custom decompressor or a standard compressor. +// If a custom decompressor is provided, it takes precedence. The function validates that the decompressed data +// does not exceed the specified maximum size and returns an error if this limit is exceeded. +// On success, it returns the decompressed data. Otherwise, it returns an error if decompression fails or the data exceeds the size limit. +func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { + if dc != nil { + uncompressed, err := dc.Do(d.Reader()) + if err != nil { + return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) + } + if len(uncompressed) > maxReceiveMessageSize { + return nil, status.Errorf(codes.ResourceExhausted, "grpc: message after decompression larger than max (%d vs. %d)", len(uncompressed), maxReceiveMessageSize) + } + return mem.BufferSlice{mem.SliceBuffer(uncompressed)}, nil } + if compressor != nil { + dcReader, err := compressor.Decompress(d.Reader()) + if err != nil { + return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the message: %v", err) + } - out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1), pool) - if err != nil { - out.Free() - return nil, 0, err + out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)), pool) + if err != nil { + out.Free() + return nil, status.Errorf(codes.Internal, "grpc: failed to read decompressed data: %v", err) + } + + if out.Len() == maxReceiveMessageSize && !atEOF(dcReader) { + out.Free() + return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) + } + return out, nil } - return out, out.Len(), nil + return nil, status.Errorf(codes.Internal, "grpc: no decompressor available for compressed payload") +} + +// atEOF reads data from r and returns true if zero bytes could be read and r.Read returns EOF. +func atEOF(dcReader io.Reader) bool { + n, err := dcReader.Read(make([]byte, 1)) + return n == 0 && err == io.EOF } type recvCompressor interface { diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index 9d5b2884d1..976e70ae06 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -37,12 +37,14 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding/proto" + estats "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/binarylog" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcutil" + istats "google.golang.org/grpc/internal/stats" "google.golang.org/grpc/internal/transport" "google.golang.org/grpc/keepalive" "google.golang.org/grpc/mem" @@ -82,6 +84,9 @@ func init() { internal.BinaryLogger = binaryLogger internal.JoinServerOptions = newJoinServerOption internal.BufferPool = bufferPool + internal.MetricsRecorderForServer = func(srv *Server) estats.MetricsRecorder { + return istats.NewMetricsRecorderList(srv.opts.statsHandlers) + } } var statusOK = status.New(codes.OK, "") @@ -643,7 +648,7 @@ func (s *Server) serverWorker() { // connections to reduce the time spent overall on runtime.morestack. func (s *Server) initServerWorkers() { s.serverWorkerChannel = make(chan func()) - s.serverWorkerChannelClose = grpcsync.OnceFunc(func() { + s.serverWorkerChannelClose = sync.OnceFunc(func() { close(s.serverWorkerChannel) }) for i := uint32(0); i < s.opts.numServerWorkers; i++ { @@ -1645,10 +1650,10 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv // If dc is set and matches the stream's compression, use it. Otherwise, try // to find a matching registered compressor for decomp. if rc := stream.RecvCompress(); s.opts.dc != nil && s.opts.dc.Type() == rc { - ss.dc = s.opts.dc + ss.decompressorV0 = s.opts.dc } else if rc != "" && rc != encoding.Identity { - ss.decomp = encoding.GetCompressor(rc) - if ss.decomp == nil { + ss.decompressorV1 = encoding.GetCompressor(rc) + if ss.decompressorV1 == nil { st := status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", rc) ss.s.WriteStatus(st) return st.Err() @@ -1660,12 +1665,12 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv // // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686. if s.opts.cp != nil { - ss.cp = s.opts.cp + ss.compressorV0 = s.opts.cp ss.sendCompressorName = s.opts.cp.Type() } else if rc := stream.RecvCompress(); rc != "" && rc != encoding.Identity { // Legacy compressor not specified; attempt to respond with same encoding. - ss.comp = encoding.GetCompressor(rc) - if ss.comp != nil { + ss.compressorV1 = encoding.GetCompressor(rc) + if ss.compressorV1 != nil { ss.sendCompressorName = rc } } @@ -1676,7 +1681,7 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv } } - ss.ctx = newContextWithRPCInfo(ss.ctx, false, ss.codec, ss.cp, ss.comp) + ss.ctx = newContextWithRPCInfo(ss.ctx, false, ss.codec, ss.compressorV0, ss.compressorV1) if trInfo != nil { trInfo.tr.LazyLog(&trInfo.firstLine, false) @@ -1930,7 +1935,7 @@ func (s *Server) stop(graceful bool) { s.conns = nil if s.opts.numServerWorkers > 0 { - // Closing the channel (only once, via grpcsync.OnceFunc) after all the + // Closing the channel (only once, via sync.OnceFunc) after all the // connections have been closed above ensures that there are no // goroutines executing the callback passed to st.HandleStreams (where // the channel is written to). diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go index 54adbbced7..12163150ba 100644 --- a/vendor/google.golang.org/grpc/stream.go +++ b/vendor/google.golang.org/grpc/stream.go @@ -258,9 +258,9 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth } func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, mc serviceconfig.MethodConfig, onCommit, doneFunc func(), opts ...CallOption) (_ iresolver.ClientStream, err error) { - c := defaultCallInfo() + callInfo := defaultCallInfo() if mc.WaitForReady != nil { - c.failFast = !*mc.WaitForReady + callInfo.failFast = !*mc.WaitForReady } // Possible context leak: @@ -281,20 +281,20 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client }() for _, o := range opts { - if err := o.before(c); err != nil { + if err := o.before(callInfo); err != nil { return nil, toRPCErr(err) } } - c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize) - c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize) - if err := setCallInfoCodec(c); err != nil { + callInfo.maxSendMessageSize = getMaxSize(mc.MaxReqSize, callInfo.maxSendMessageSize, defaultClientMaxSendMessageSize) + callInfo.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, callInfo.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize) + if err := setCallInfoCodec(callInfo); err != nil { return nil, err } callHdr := &transport.CallHdr{ Host: cc.authority, Method: method, - ContentSubtype: c.contentSubtype, + ContentSubtype: callInfo.contentSubtype, DoneFunc: doneFunc, } @@ -302,22 +302,22 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client // set. In that case, also find the compressor from the encoding package. // Otherwise, use the compressor configured by the WithCompressor DialOption, // if set. - var cp Compressor - var comp encoding.Compressor - if ct := c.compressorType; ct != "" { + var compressorV0 Compressor + var compressorV1 encoding.Compressor + if ct := callInfo.compressorName; ct != "" { callHdr.SendCompress = ct if ct != encoding.Identity { - comp = encoding.GetCompressor(ct) - if comp == nil { + compressorV1 = encoding.GetCompressor(ct) + if compressorV1 == nil { return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct) } } - } else if cc.dopts.cp != nil { - callHdr.SendCompress = cc.dopts.cp.Type() - cp = cc.dopts.cp + } else if cc.dopts.compressorV0 != nil { + callHdr.SendCompress = cc.dopts.compressorV0.Type() + compressorV0 = cc.dopts.compressorV0 } - if c.creds != nil { - callHdr.Creds = c.creds + if callInfo.creds != nil { + callHdr.Creds = callInfo.creds } cs := &clientStream{ @@ -325,12 +325,12 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client ctx: ctx, methodConfig: &mc, opts: opts, - callInfo: c, + callInfo: callInfo, cc: cc, desc: desc, - codec: c.codec, - cp: cp, - comp: comp, + codec: callInfo.codec, + compressorV0: compressorV0, + compressorV1: compressorV1, cancel: cancel, firstAttempt: true, onCommit: onCommit, @@ -412,7 +412,7 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error) return nil, ErrClientConnClosing } - ctx := newContextWithRPCInfo(cs.ctx, cs.callInfo.failFast, cs.callInfo.codec, cs.cp, cs.comp) + ctx := newContextWithRPCInfo(cs.ctx, cs.callInfo.failFast, cs.callInfo.codec, cs.compressorV0, cs.compressorV1) method := cs.callHdr.Method var beginTime time.Time shs := cs.cc.dopts.copts.StatsHandlers @@ -454,12 +454,12 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error) } return &csAttempt{ - ctx: ctx, - beginTime: beginTime, - cs: cs, - dc: cs.cc.dopts.dc, - statsHandlers: shs, - trInfo: trInfo, + ctx: ctx, + beginTime: beginTime, + cs: cs, + decompressorV0: cs.cc.dopts.dc, + statsHandlers: shs, + trInfo: trInfo, }, nil } @@ -467,7 +467,7 @@ func (a *csAttempt) getTransport() error { cs := a.cs var err error - a.t, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method) + a.transport, a.pickResult, err = cs.cc.getTransport(a.ctx, cs.callInfo.failFast, cs.callHdr.Method) if err != nil { if de, ok := err.(dropError); ok { err = de.error @@ -476,7 +476,7 @@ func (a *csAttempt) getTransport() error { return err } if a.trInfo != nil { - a.trInfo.firstLine.SetRemoteAddr(a.t.RemoteAddr()) + a.trInfo.firstLine.SetRemoteAddr(a.transport.RemoteAddr()) } return nil } @@ -503,7 +503,7 @@ func (a *csAttempt) newStream() error { a.ctx = metadata.NewOutgoingContext(a.ctx, md) } - s, err := a.t.NewStream(a.ctx, cs.callHdr) + s, err := a.transport.NewStream(a.ctx, cs.callHdr) if err != nil { nse, ok := err.(*transport.NewStreamError) if !ok { @@ -518,9 +518,9 @@ func (a *csAttempt) newStream() error { // Unwrap and convert error. return toRPCErr(nse.Err) } - a.s = s + a.transportStream = s a.ctx = s.Context() - a.p = &parser{r: s, bufferPool: a.cs.cc.dopts.copts.BufferPool} + a.parser = &parser{r: s, bufferPool: a.cs.cc.dopts.copts.BufferPool} return nil } @@ -532,9 +532,9 @@ type clientStream struct { cc *ClientConn desc *StreamDesc - codec baseCodec - cp Compressor - comp encoding.Compressor + codec baseCodec + compressorV0 Compressor + compressorV1 encoding.Compressor cancel context.CancelFunc // cancels all attempts @@ -583,17 +583,17 @@ type replayOp struct { // csAttempt implements a single transport stream attempt within a // clientStream. type csAttempt struct { - ctx context.Context - cs *clientStream - t transport.ClientTransport - s *transport.ClientStream - p *parser - pickResult balancer.PickResult - - finished bool - dc Decompressor - decomp encoding.Compressor - decompSet bool + ctx context.Context + cs *clientStream + transport transport.ClientTransport + transportStream *transport.ClientStream + parser *parser + pickResult balancer.PickResult + + finished bool + decompressorV0 Decompressor + decompressorV1 encoding.Compressor + decompressorSet bool mu sync.Mutex // guards trInfo.tr // trInfo may be nil (if EnableTracing is false). @@ -639,14 +639,14 @@ func (a *csAttempt) shouldRetry(err error) (bool, error) { // RPC is finished or committed or was dropped by the picker; cannot retry. return false, err } - if a.s == nil && a.allowTransparentRetry { + if a.transportStream == nil && a.allowTransparentRetry { return true, nil } // Wait for the trailers. unprocessed := false - if a.s != nil { - <-a.s.Done() - unprocessed = a.s.Unprocessed() + if a.transportStream != nil { + <-a.transportStream.Done() + unprocessed = a.transportStream.Unprocessed() } if cs.firstAttempt && unprocessed { // First attempt, stream unprocessed: transparently retry. @@ -658,14 +658,14 @@ func (a *csAttempt) shouldRetry(err error) (bool, error) { pushback := 0 hasPushback := false - if a.s != nil { - if !a.s.TrailersOnly() { + if a.transportStream != nil { + if !a.transportStream.TrailersOnly() { return false, err } // TODO(retry): Move down if the spec changes to not check server pushback // before considering this a failure for throttling. - sps := a.s.Trailer()["grpc-retry-pushback-ms"] + sps := a.transportStream.Trailer()["grpc-retry-pushback-ms"] if len(sps) == 1 { var e error if pushback, e = strconv.Atoi(sps[0]); e != nil || pushback < 0 { @@ -682,8 +682,8 @@ func (a *csAttempt) shouldRetry(err error) (bool, error) { } var code codes.Code - if a.s != nil { - code = a.s.Status().Code() + if a.transportStream != nil { + code = a.transportStream.Status().Code() } else { code = status.Code(err) } @@ -756,8 +756,8 @@ func (cs *clientStream) Context() context.Context { cs.commitAttempt() // No need to lock before using attempt, since we know it is committed and // cannot change. - if cs.attempt.s != nil { - return cs.attempt.s.Context() + if cs.attempt.transportStream != nil { + return cs.attempt.transportStream.Context() } return cs.ctx } @@ -794,9 +794,9 @@ func (cs *clientStream) withRetry(op func(a *csAttempt) error, onSuccess func()) continue } if err == io.EOF { - <-a.s.Done() + <-a.transportStream.Done() } - if err == nil || (err == io.EOF && a.s.Status().Code() == codes.OK) { + if err == nil || (err == io.EOF && a.transportStream.Status().Code() == codes.OK) { onSuccess() cs.mu.Unlock() return err @@ -812,7 +812,7 @@ func (cs *clientStream) Header() (metadata.MD, error) { var m metadata.MD err := cs.withRetry(func(a *csAttempt) error { var err error - m, err = a.s.Header() + m, err = a.transportStream.Header() return toRPCErr(err) }, cs.commitAttemptLocked) @@ -856,10 +856,10 @@ func (cs *clientStream) Trailer() metadata.MD { // directions -- it will prevent races and should not meaningfully impact // performance. cs.commitAttempt() - if cs.attempt.s == nil { + if cs.attempt.transportStream == nil { return nil } - return cs.attempt.s.Trailer() + return cs.attempt.transportStream.Trailer() } func (cs *clientStream) replayBufferLocked(attempt *csAttempt) error { @@ -904,7 +904,7 @@ func (cs *clientStream) SendMsg(m any) (err error) { } // load hdr, payload, data - hdr, data, payload, pf, err := prepareMsg(m, cs.codec, cs.cp, cs.comp, cs.cc.dopts.copts.BufferPool) + hdr, data, payload, pf, err := prepareMsg(m, cs.codec, cs.compressorV0, cs.compressorV1, cs.cc.dopts.copts.BufferPool) if err != nil { return err } @@ -992,7 +992,7 @@ func (cs *clientStream) CloseSend() error { } cs.sentLast = true op := func(a *csAttempt) error { - a.s.Write(nil, nil, &transport.WriteOptions{Last: true}) + a.transportStream.Write(nil, nil, &transport.WriteOptions{Last: true}) // Always return nil; io.EOF is the only error that might make sense // instead, but there is no need to signal the client to call RecvMsg // as the only use left for the stream after CloseSend is to call @@ -1030,7 +1030,7 @@ func (cs *clientStream) finish(err error) { if cs.attempt != nil { cs.attempt.finish(err) // after functions all rely upon having a stream. - if cs.attempt.s != nil { + if cs.attempt.transportStream != nil { for _, o := range cs.opts { o.after(cs.callInfo, cs.attempt) } @@ -1084,7 +1084,7 @@ func (a *csAttempt) sendMsg(m any, hdr []byte, payld mem.BufferSlice, dataLength } a.mu.Unlock() } - if err := a.s.Write(hdr, payld, &transport.WriteOptions{Last: !cs.desc.ClientStreams}); err != nil { + if err := a.transportStream.Write(hdr, payld, &transport.WriteOptions{Last: !cs.desc.ClientStreams}); err != nil { if !cs.desc.ClientStreams { // For non-client-streaming RPCs, we return nil instead of EOF on error // because the generated code requires it. finish is not called; RecvMsg() @@ -1108,25 +1108,25 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { defer payInfo.free() } - if !a.decompSet { + if !a.decompressorSet { // Block until we receive headers containing received message encoding. - if ct := a.s.RecvCompress(); ct != "" && ct != encoding.Identity { - if a.dc == nil || a.dc.Type() != ct { + if ct := a.transportStream.RecvCompress(); ct != "" && ct != encoding.Identity { + if a.decompressorV0 == nil || a.decompressorV0.Type() != ct { // No configured decompressor, or it does not match the incoming // message encoding; attempt to find a registered compressor that does. - a.dc = nil - a.decomp = encoding.GetCompressor(ct) + a.decompressorV0 = nil + a.decompressorV1 = encoding.GetCompressor(ct) } } else { // No compression is used; disable our decompressor. - a.dc = nil + a.decompressorV0 = nil } // Only initialize this state once per stream. - a.decompSet = true + a.decompressorSet = true } - if err := recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, payInfo, a.decomp, false); err != nil { + if err := recv(a.parser, cs.codec, a.transportStream, a.decompressorV0, m, *cs.callInfo.maxReceiveMessageSize, payInfo, a.decompressorV1, false); err != nil { if err == io.EOF { - if statusErr := a.s.Status().Err(); statusErr != nil { + if statusErr := a.transportStream.Status().Err(); statusErr != nil { return statusErr } return io.EOF // indicates successful end of stream. @@ -1157,8 +1157,8 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { } // Special handling for non-server-stream rpcs. // This recv expects EOF or errors, so we don't collect inPayload. - if err := recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, nil, a.decomp, false); err == io.EOF { - return a.s.Status().Err() // non-server streaming Recv returns nil on success + if err := recv(a.parser, cs.codec, a.transportStream, a.decompressorV0, m, *cs.callInfo.maxReceiveMessageSize, nil, a.decompressorV1, false); err == io.EOF { + return a.transportStream.Status().Err() // non-server streaming Recv returns nil on success } else if err != nil { return toRPCErr(err) } @@ -1177,20 +1177,20 @@ func (a *csAttempt) finish(err error) { err = nil } var tr metadata.MD - if a.s != nil { - a.s.Close(err) - tr = a.s.Trailer() + if a.transportStream != nil { + a.transportStream.Close(err) + tr = a.transportStream.Trailer() } if a.pickResult.Done != nil { br := false - if a.s != nil { - br = a.s.BytesReceived() + if a.transportStream != nil { + br = a.transportStream.BytesReceived() } a.pickResult.Done(balancer.DoneInfo{ Err: err, Trailer: tr, - BytesSent: a.s != nil, + BytesSent: a.transportStream != nil, BytesReceived: br, ServerLoad: balancerload.Parse(tr), }) @@ -1272,7 +1272,7 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin // if set. var cp Compressor var comp encoding.Compressor - if ct := c.compressorType; ct != "" { + if ct := c.compressorName; ct != "" { callHdr.SendCompress = ct if ct != encoding.Identity { comp = encoding.GetCompressor(ct) @@ -1280,9 +1280,9 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct) } } - } else if ac.cc.dopts.cp != nil { - callHdr.SendCompress = ac.cc.dopts.cp.Type() - cp = ac.cc.dopts.cp + } else if ac.cc.dopts.compressorV0 != nil { + callHdr.SendCompress = ac.cc.dopts.compressorV0.Type() + cp = ac.cc.dopts.compressorV0 } if c.creds != nil { callHdr.Creds = c.creds @@ -1290,26 +1290,26 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin // Use a special addrConnStream to avoid retry. as := &addrConnStream{ - callHdr: callHdr, - ac: ac, - ctx: ctx, - cancel: cancel, - opts: opts, - callInfo: c, - desc: desc, - codec: c.codec, - cp: cp, - comp: comp, - t: t, - } - - s, err := as.t.NewStream(as.ctx, as.callHdr) + callHdr: callHdr, + ac: ac, + ctx: ctx, + cancel: cancel, + opts: opts, + callInfo: c, + desc: desc, + codec: c.codec, + sendCompressorV0: cp, + sendCompressorV1: comp, + transport: t, + } + + s, err := as.transport.NewStream(as.ctx, as.callHdr) if err != nil { err = toRPCErr(err) return nil, err } - as.s = s - as.p = &parser{r: s, bufferPool: ac.dopts.copts.BufferPool} + as.transportStream = s + as.parser = &parser{r: s, bufferPool: ac.dopts.copts.BufferPool} ac.incrCallsStarted() if desc != unaryStreamDesc { // Listen on stream context to cleanup when the stream context is @@ -1335,29 +1335,31 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin } type addrConnStream struct { - s *transport.ClientStream - ac *addrConn - callHdr *transport.CallHdr - cancel context.CancelFunc - opts []CallOption - callInfo *callInfo - t transport.ClientTransport - ctx context.Context - sentLast bool - desc *StreamDesc - codec baseCodec - cp Compressor - comp encoding.Compressor - decompSet bool - dc Decompressor - decomp encoding.Compressor - p *parser - mu sync.Mutex - finished bool + transportStream *transport.ClientStream + ac *addrConn + callHdr *transport.CallHdr + cancel context.CancelFunc + opts []CallOption + callInfo *callInfo + transport transport.ClientTransport + ctx context.Context + sentLast bool + desc *StreamDesc + codec baseCodec + sendCompressorV0 Compressor + sendCompressorV1 encoding.Compressor + decompressorSet bool + decompressorV0 Decompressor + decompressorV1 encoding.Compressor + parser *parser + + // mu guards finished and is held for the entire finish method. + mu sync.Mutex + finished bool } func (as *addrConnStream) Header() (metadata.MD, error) { - m, err := as.s.Header() + m, err := as.transportStream.Header() if err != nil { as.finish(toRPCErr(err)) } @@ -1365,7 +1367,7 @@ func (as *addrConnStream) Header() (metadata.MD, error) { } func (as *addrConnStream) Trailer() metadata.MD { - return as.s.Trailer() + return as.transportStream.Trailer() } func (as *addrConnStream) CloseSend() error { @@ -1375,7 +1377,7 @@ func (as *addrConnStream) CloseSend() error { } as.sentLast = true - as.s.Write(nil, nil, &transport.WriteOptions{Last: true}) + as.transportStream.Write(nil, nil, &transport.WriteOptions{Last: true}) // Always return nil; io.EOF is the only error that might make sense // instead, but there is no need to signal the client to call RecvMsg // as the only use left for the stream after CloseSend is to call @@ -1384,7 +1386,7 @@ func (as *addrConnStream) CloseSend() error { } func (as *addrConnStream) Context() context.Context { - return as.s.Context() + return as.transportStream.Context() } func (as *addrConnStream) SendMsg(m any) (err error) { @@ -1406,7 +1408,7 @@ func (as *addrConnStream) SendMsg(m any) (err error) { } // load hdr, payload, data - hdr, data, payload, pf, err := prepareMsg(m, as.codec, as.cp, as.comp, as.ac.dopts.copts.BufferPool) + hdr, data, payload, pf, err := prepareMsg(m, as.codec, as.sendCompressorV0, as.sendCompressorV1, as.ac.dopts.copts.BufferPool) if err != nil { return err } @@ -1425,7 +1427,7 @@ func (as *addrConnStream) SendMsg(m any) (err error) { return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", payload.Len(), *as.callInfo.maxSendMessageSize) } - if err := as.s.Write(hdr, payload, &transport.WriteOptions{Last: !as.desc.ClientStreams}); err != nil { + if err := as.transportStream.Write(hdr, payload, &transport.WriteOptions{Last: !as.desc.ClientStreams}); err != nil { if !as.desc.ClientStreams { // For non-client-streaming RPCs, we return nil instead of EOF on error // because the generated code requires it. finish is not called; RecvMsg() @@ -1446,25 +1448,25 @@ func (as *addrConnStream) RecvMsg(m any) (err error) { } }() - if !as.decompSet { + if !as.decompressorSet { // Block until we receive headers containing received message encoding. - if ct := as.s.RecvCompress(); ct != "" && ct != encoding.Identity { - if as.dc == nil || as.dc.Type() != ct { + if ct := as.transportStream.RecvCompress(); ct != "" && ct != encoding.Identity { + if as.decompressorV0 == nil || as.decompressorV0.Type() != ct { // No configured decompressor, or it does not match the incoming // message encoding; attempt to find a registered compressor that does. - as.dc = nil - as.decomp = encoding.GetCompressor(ct) + as.decompressorV0 = nil + as.decompressorV1 = encoding.GetCompressor(ct) } } else { // No compression is used; disable our decompressor. - as.dc = nil + as.decompressorV0 = nil } // Only initialize this state once per stream. - as.decompSet = true + as.decompressorSet = true } - if err := recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp, false); err != nil { + if err := recv(as.parser, as.codec, as.transportStream, as.decompressorV0, m, *as.callInfo.maxReceiveMessageSize, nil, as.decompressorV1, false); err != nil { if err == io.EOF { - if statusErr := as.s.Status().Err(); statusErr != nil { + if statusErr := as.transportStream.Status().Err(); statusErr != nil { return statusErr } return io.EOF // indicates successful end of stream. @@ -1479,8 +1481,8 @@ func (as *addrConnStream) RecvMsg(m any) (err error) { // Special handling for non-server-stream rpcs. // This recv expects EOF or errors, so we don't collect inPayload. - if err := recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp, false); err == io.EOF { - return as.s.Status().Err() // non-server streaming Recv returns nil on success + if err := recv(as.parser, as.codec, as.transportStream, as.decompressorV0, m, *as.callInfo.maxReceiveMessageSize, nil, as.decompressorV1, false); err == io.EOF { + return as.transportStream.Status().Err() // non-server streaming Recv returns nil on success } else if err != nil { return toRPCErr(err) } @@ -1498,8 +1500,8 @@ func (as *addrConnStream) finish(err error) { // Ending a stream with EOF indicates a success. err = nil } - if as.s != nil { - as.s.Close(err) + if as.transportStream != nil { + as.transportStream.Close(err) } if err != nil { @@ -1570,10 +1572,10 @@ type serverStream struct { p *parser codec baseCodec - cp Compressor - dc Decompressor - comp encoding.Compressor - decomp encoding.Compressor + compressorV0 Compressor + compressorV1 encoding.Compressor + decompressorV0 Decompressor + decompressorV1 encoding.Compressor sendCompressorName string @@ -1669,12 +1671,12 @@ func (ss *serverStream) SendMsg(m any) (err error) { // Server handler could have set new compressor by calling SetSendCompressor. // In case it is set, we need to use it for compressing outbound message. if sendCompressorsName := ss.s.SendCompress(); sendCompressorsName != ss.sendCompressorName { - ss.comp = encoding.GetCompressor(sendCompressorsName) + ss.compressorV1 = encoding.GetCompressor(sendCompressorsName) ss.sendCompressorName = sendCompressorsName } // load hdr, payload, data - hdr, data, payload, pf, err := prepareMsg(m, ss.codec, ss.cp, ss.comp, ss.p.bufferPool) + hdr, data, payload, pf, err := prepareMsg(m, ss.codec, ss.compressorV0, ss.compressorV1, ss.p.bufferPool) if err != nil { return err } @@ -1755,7 +1757,7 @@ func (ss *serverStream) RecvMsg(m any) (err error) { payInfo = &payloadInfo{} defer payInfo.free() } - if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, payInfo, ss.decomp, true); err != nil { + if err := recv(ss.p, ss.codec, ss.s, ss.decompressorV0, m, ss.maxReceiveMessageSize, payInfo, ss.decompressorV1, true); err != nil { if err == io.EOF { if len(ss.binlogs) != 0 { chc := &binarylog.ClientHalfClose{} diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 0e03fa4d4f..783c41f78c 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.70.0" +const Version = "1.71.0" diff --git a/vendor/gopkg.in/ini.v1/.editorconfig b/vendor/gopkg.in/ini.v1/.editorconfig deleted file mode 100644 index 4a2d9180f9..0000000000 --- a/vendor/gopkg.in/ini.v1/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -# http://editorconfig.org - -root = true - -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -[*_test.go] -trim_trailing_whitespace = false diff --git a/vendor/gopkg.in/ini.v1/.gitignore b/vendor/gopkg.in/ini.v1/.gitignore deleted file mode 100644 index 588388bda2..0000000000 --- a/vendor/gopkg.in/ini.v1/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -testdata/conf_out.ini -ini.sublime-project -ini.sublime-workspace -testdata/conf_reflect.ini -.idea -/.vscode -.DS_Store diff --git a/vendor/gopkg.in/ini.v1/.golangci.yml b/vendor/gopkg.in/ini.v1/.golangci.yml deleted file mode 100644 index 631e369254..0000000000 --- a/vendor/gopkg.in/ini.v1/.golangci.yml +++ /dev/null @@ -1,27 +0,0 @@ -linters-settings: - staticcheck: - checks: [ - "all", - "-SA1019" # There are valid use cases of strings.Title - ] - nakedret: - max-func-lines: 0 # Disallow any unnamed return statement - -linters: - enable: - - deadcode - - errcheck - - gosimple - - govet - - ineffassign - - staticcheck - - structcheck - - typecheck - - unused - - varcheck - - nakedret - - gofmt - - rowserrcheck - - unconvert - - goimports - - unparam diff --git a/vendor/gopkg.in/ini.v1/LICENSE b/vendor/gopkg.in/ini.v1/LICENSE deleted file mode 100644 index d361bbcdf5..0000000000 --- a/vendor/gopkg.in/ini.v1/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. - - Copyright 2014 Unknwon - - 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/gopkg.in/ini.v1/Makefile b/vendor/gopkg.in/ini.v1/Makefile deleted file mode 100644 index f3b0dae2d2..0000000000 --- a/vendor/gopkg.in/ini.v1/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PHONY: build test bench vet coverage - -build: vet bench - -test: - go test -v -cover -race - -bench: - go test -v -cover -test.bench=. -test.benchmem - -vet: - go vet - -coverage: - go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out diff --git a/vendor/gopkg.in/ini.v1/README.md b/vendor/gopkg.in/ini.v1/README.md deleted file mode 100644 index 30606d9700..0000000000 --- a/vendor/gopkg.in/ini.v1/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# INI - -[![GitHub Workflow Status](https://img.shields.io/github/checks-status/go-ini/ini/main?logo=github&style=for-the-badge)](https://github.com/go-ini/ini/actions?query=branch%3Amain) -[![codecov](https://img.shields.io/codecov/c/github/go-ini/ini/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-ini/ini) -[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/github.com/go-ini/ini?tab=doc) -[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-ini/ini) - -![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200) - -Package ini provides INI file read and write functionality in Go. - -## Features - -- Load from multiple data sources(file, `[]byte`, `io.Reader` and `io.ReadCloser`) with overwrites. -- Read with recursion values. -- Read with parent-child sections. -- Read with auto-increment key names. -- Read with multiple-line values. -- Read with tons of helper methods. -- Read and convert values to Go types. -- Read and **WRITE** comments of sections and keys. -- Manipulate sections, keys and comments with ease. -- Keep sections and keys in order as you parse and save. - -## Installation - -The minimum requirement of Go is **1.13**. - -```sh -$ go get gopkg.in/ini.v1 -``` - -Please add `-u` flag to update in the future. - -## Getting Help - -- [Getting Started](https://ini.unknwon.io/docs/intro/getting_started) -- [API Documentation](https://gowalker.org/gopkg.in/ini.v1) -- 中国大陆镜像:https://ini.unknwon.cn - -## License - -This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. diff --git a/vendor/gopkg.in/ini.v1/codecov.yml b/vendor/gopkg.in/ini.v1/codecov.yml deleted file mode 100644 index e02ec84bc0..0000000000 --- a/vendor/gopkg.in/ini.v1/codecov.yml +++ /dev/null @@ -1,16 +0,0 @@ -coverage: - range: "60...95" - status: - project: - default: - threshold: 1% - informational: true - patch: - defualt: - only_pulls: true - informational: true - -comment: - layout: 'diff' - -github_checks: false diff --git a/vendor/gopkg.in/ini.v1/data_source.go b/vendor/gopkg.in/ini.v1/data_source.go deleted file mode 100644 index c3a541f1d1..0000000000 --- a/vendor/gopkg.in/ini.v1/data_source.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019 Unknwon -// -// 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 ini - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "os" -) - -var ( - _ dataSource = (*sourceFile)(nil) - _ dataSource = (*sourceData)(nil) - _ dataSource = (*sourceReadCloser)(nil) -) - -// dataSource is an interface that returns object which can be read and closed. -type dataSource interface { - ReadCloser() (io.ReadCloser, error) -} - -// sourceFile represents an object that contains content on the local file system. -type sourceFile struct { - name string -} - -func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) { - return os.Open(s.name) -} - -// sourceData represents an object that contains content in memory. -type sourceData struct { - data []byte -} - -func (s *sourceData) ReadCloser() (io.ReadCloser, error) { - return ioutil.NopCloser(bytes.NewReader(s.data)), nil -} - -// sourceReadCloser represents an input stream with Close method. -type sourceReadCloser struct { - reader io.ReadCloser -} - -func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) { - return s.reader, nil -} - -func parseDataSource(source interface{}) (dataSource, error) { - switch s := source.(type) { - case string: - return sourceFile{s}, nil - case []byte: - return &sourceData{s}, nil - case io.ReadCloser: - return &sourceReadCloser{s}, nil - case io.Reader: - return &sourceReadCloser{ioutil.NopCloser(s)}, nil - default: - return nil, fmt.Errorf("error parsing data source: unknown type %q", s) - } -} diff --git a/vendor/gopkg.in/ini.v1/deprecated.go b/vendor/gopkg.in/ini.v1/deprecated.go deleted file mode 100644 index 48b8e66d6d..0000000000 --- a/vendor/gopkg.in/ini.v1/deprecated.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 Unknwon -// -// 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 ini - -var ( - // Deprecated: Use "DefaultSection" instead. - DEFAULT_SECTION = DefaultSection - // Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE. - AllCapsUnderscore = SnackCase -) diff --git a/vendor/gopkg.in/ini.v1/error.go b/vendor/gopkg.in/ini.v1/error.go deleted file mode 100644 index f66bc94b8b..0000000000 --- a/vendor/gopkg.in/ini.v1/error.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2016 Unknwon -// -// 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 ini - -import ( - "fmt" -) - -// ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one. -type ErrDelimiterNotFound struct { - Line string -} - -// IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound. -func IsErrDelimiterNotFound(err error) bool { - _, ok := err.(ErrDelimiterNotFound) - return ok -} - -func (err ErrDelimiterNotFound) Error() string { - return fmt.Sprintf("key-value delimiter not found: %s", err.Line) -} - -// ErrEmptyKeyName indicates the error type of no key name is found which there should be one. -type ErrEmptyKeyName struct { - Line string -} - -// IsErrEmptyKeyName returns true if the given error is an instance of ErrEmptyKeyName. -func IsErrEmptyKeyName(err error) bool { - _, ok := err.(ErrEmptyKeyName) - return ok -} - -func (err ErrEmptyKeyName) Error() string { - return fmt.Sprintf("empty key name: %s", err.Line) -} diff --git a/vendor/gopkg.in/ini.v1/file.go b/vendor/gopkg.in/ini.v1/file.go deleted file mode 100644 index f8b22408be..0000000000 --- a/vendor/gopkg.in/ini.v1/file.go +++ /dev/null @@ -1,541 +0,0 @@ -// Copyright 2017 Unknwon -// -// 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 ini - -import ( - "bytes" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "strings" - "sync" -) - -// File represents a combination of one or more INI files in memory. -type File struct { - options LoadOptions - dataSources []dataSource - - // Should make things safe, but sometimes doesn't matter. - BlockMode bool - lock sync.RWMutex - - // To keep data in order. - sectionList []string - // To keep track of the index of a section with same name. - // This meta list is only used with non-unique section names are allowed. - sectionIndexes []int - - // Actual data is stored here. - sections map[string][]*Section - - NameMapper - ValueMapper -} - -// newFile initializes File object with given data sources. -func newFile(dataSources []dataSource, opts LoadOptions) *File { - if len(opts.KeyValueDelimiters) == 0 { - opts.KeyValueDelimiters = "=:" - } - if len(opts.KeyValueDelimiterOnWrite) == 0 { - opts.KeyValueDelimiterOnWrite = "=" - } - if len(opts.ChildSectionDelimiter) == 0 { - opts.ChildSectionDelimiter = "." - } - - return &File{ - BlockMode: true, - dataSources: dataSources, - sections: make(map[string][]*Section), - options: opts, - } -} - -// Empty returns an empty file object. -func Empty(opts ...LoadOptions) *File { - var opt LoadOptions - if len(opts) > 0 { - opt = opts[0] - } - - // Ignore error here, we are sure our data is good. - f, _ := LoadSources(opt, []byte("")) - return f -} - -// NewSection creates a new section. -func (f *File) NewSection(name string) (*Section, error) { - if len(name) == 0 { - return nil, errors.New("empty section name") - } - - if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection { - name = strings.ToLower(name) - } - - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) { - return f.sections[name][0], nil - } - - f.sectionList = append(f.sectionList, name) - - // NOTE: Append to indexes must happen before appending to sections, - // otherwise index will have off-by-one problem. - f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name])) - - sec := newSection(f, name) - f.sections[name] = append(f.sections[name], sec) - - return sec, nil -} - -// NewRawSection creates a new section with an unparseable body. -func (f *File) NewRawSection(name, body string) (*Section, error) { - section, err := f.NewSection(name) - if err != nil { - return nil, err - } - - section.isRawSection = true - section.rawBody = body - return section, nil -} - -// NewSections creates a list of sections. -func (f *File) NewSections(names ...string) (err error) { - for _, name := range names { - if _, err = f.NewSection(name); err != nil { - return err - } - } - return nil -} - -// GetSection returns section by given name. -func (f *File) GetSection(name string) (*Section, error) { - secs, err := f.SectionsByName(name) - if err != nil { - return nil, err - } - - return secs[0], err -} - -// HasSection returns true if the file contains a section with given name. -func (f *File) HasSection(name string) bool { - section, _ := f.GetSection(name) - return section != nil -} - -// SectionsByName returns all sections with given name. -func (f *File) SectionsByName(name string) ([]*Section, error) { - if len(name) == 0 { - name = DefaultSection - } - if f.options.Insensitive || f.options.InsensitiveSections { - name = strings.ToLower(name) - } - - if f.BlockMode { - f.lock.RLock() - defer f.lock.RUnlock() - } - - secs := f.sections[name] - if len(secs) == 0 { - return nil, fmt.Errorf("section %q does not exist", name) - } - - return secs, nil -} - -// Section assumes named section exists and returns a zero-value when not. -func (f *File) Section(name string) *Section { - sec, err := f.GetSection(name) - if err != nil { - if name == "" { - name = DefaultSection - } - sec, _ = f.NewSection(name) - return sec - } - return sec -} - -// SectionWithIndex assumes named section exists and returns a new section when not. -func (f *File) SectionWithIndex(name string, index int) *Section { - secs, err := f.SectionsByName(name) - if err != nil || len(secs) <= index { - // NOTE: It's OK here because the only possible error is empty section name, - // but if it's empty, this piece of code won't be executed. - newSec, _ := f.NewSection(name) - return newSec - } - - return secs[index] -} - -// Sections returns a list of Section stored in the current instance. -func (f *File) Sections() []*Section { - if f.BlockMode { - f.lock.RLock() - defer f.lock.RUnlock() - } - - sections := make([]*Section, len(f.sectionList)) - for i, name := range f.sectionList { - sections[i] = f.sections[name][f.sectionIndexes[i]] - } - return sections -} - -// ChildSections returns a list of child sections of given section name. -func (f *File) ChildSections(name string) []*Section { - return f.Section(name).ChildSections() -} - -// SectionStrings returns list of section names. -func (f *File) SectionStrings() []string { - list := make([]string, len(f.sectionList)) - copy(list, f.sectionList) - return list -} - -// DeleteSection deletes a section or all sections with given name. -func (f *File) DeleteSection(name string) { - secs, err := f.SectionsByName(name) - if err != nil { - return - } - - for i := 0; i < len(secs); i++ { - // For non-unique sections, it is always needed to remove the first one so - // in the next iteration, the subsequent section continue having index 0. - // Ignoring the error as index 0 never returns an error. - _ = f.DeleteSectionWithIndex(name, 0) - } -} - -// DeleteSectionWithIndex deletes a section with given name and index. -func (f *File) DeleteSectionWithIndex(name string, index int) error { - if !f.options.AllowNonUniqueSections && index != 0 { - return fmt.Errorf("delete section with non-zero index is only allowed when non-unique sections is enabled") - } - - if len(name) == 0 { - name = DefaultSection - } - if f.options.Insensitive || f.options.InsensitiveSections { - name = strings.ToLower(name) - } - - if f.BlockMode { - f.lock.Lock() - defer f.lock.Unlock() - } - - // Count occurrences of the sections - occurrences := 0 - - sectionListCopy := make([]string, len(f.sectionList)) - copy(sectionListCopy, f.sectionList) - - for i, s := range sectionListCopy { - if s != name { - continue - } - - if occurrences == index { - if len(f.sections[name]) <= 1 { - delete(f.sections, name) // The last one in the map - } else { - f.sections[name] = append(f.sections[name][:index], f.sections[name][index+1:]...) - } - - // Fix section lists - f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...) - f.sectionIndexes = append(f.sectionIndexes[:i], f.sectionIndexes[i+1:]...) - - } else if occurrences > index { - // Fix the indices of all following sections with this name. - f.sectionIndexes[i-1]-- - } - - occurrences++ - } - - return nil -} - -func (f *File) reload(s dataSource) error { - r, err := s.ReadCloser() - if err != nil { - return err - } - defer r.Close() - - return f.parse(r) -} - -// Reload reloads and parses all data sources. -func (f *File) Reload() (err error) { - for _, s := range f.dataSources { - if err = f.reload(s); err != nil { - // In loose mode, we create an empty default section for nonexistent files. - if os.IsNotExist(err) && f.options.Loose { - _ = f.parse(bytes.NewBuffer(nil)) - continue - } - return err - } - if f.options.ShortCircuit { - return nil - } - } - return nil -} - -// Append appends one or more data sources and reloads automatically. -func (f *File) Append(source interface{}, others ...interface{}) error { - ds, err := parseDataSource(source) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - for _, s := range others { - ds, err = parseDataSource(s) - if err != nil { - return err - } - f.dataSources = append(f.dataSources, ds) - } - return f.Reload() -} - -func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) { - equalSign := DefaultFormatLeft + f.options.KeyValueDelimiterOnWrite + DefaultFormatRight - - if PrettyFormat || PrettyEqual { - equalSign = fmt.Sprintf(" %s ", f.options.KeyValueDelimiterOnWrite) - } - - // Use buffer to make sure target is safe until finish encoding. - buf := bytes.NewBuffer(nil) - lastSectionIdx := len(f.sectionList) - 1 - for i, sname := range f.sectionList { - sec := f.SectionWithIndex(sname, f.sectionIndexes[i]) - if len(sec.Comment) > 0 { - // Support multiline comments - lines := strings.Split(sec.Comment, LineBreak) - for i := range lines { - if lines[i][0] != '#' && lines[i][0] != ';' { - lines[i] = "; " + lines[i] - } else { - lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:]) - } - - if _, err := buf.WriteString(lines[i] + LineBreak); err != nil { - return nil, err - } - } - } - - if i > 0 || DefaultHeader || (i == 0 && strings.ToUpper(sec.name) != DefaultSection) { - if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil { - return nil, err - } - } else { - // Write nothing if default section is empty - if len(sec.keyList) == 0 { - continue - } - } - - isLastSection := i == lastSectionIdx - if sec.isRawSection { - if _, err := buf.WriteString(sec.rawBody); err != nil { - return nil, err - } - - if PrettySection && !isLastSection { - // Put a line between sections - if _, err := buf.WriteString(LineBreak); err != nil { - return nil, err - } - } - continue - } - - // Count and generate alignment length and buffer spaces using the - // longest key. Keys may be modified if they contain certain characters so - // we need to take that into account in our calculation. - alignLength := 0 - if PrettyFormat { - for _, kname := range sec.keyList { - keyLength := len(kname) - // First case will surround key by ` and second by """ - if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) { - keyLength += 2 - } else if strings.Contains(kname, "`") { - keyLength += 6 - } - - if keyLength > alignLength { - alignLength = keyLength - } - } - } - alignSpaces := bytes.Repeat([]byte(" "), alignLength) - - KeyList: - for _, kname := range sec.keyList { - key := sec.Key(kname) - if len(key.Comment) > 0 { - if len(indent) > 0 && sname != DefaultSection { - buf.WriteString(indent) - } - - // Support multiline comments - lines := strings.Split(key.Comment, LineBreak) - for i := range lines { - if lines[i][0] != '#' && lines[i][0] != ';' { - lines[i] = "; " + strings.TrimSpace(lines[i]) - } else { - lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:]) - } - - if _, err := buf.WriteString(lines[i] + LineBreak); err != nil { - return nil, err - } - } - } - - if len(indent) > 0 && sname != DefaultSection { - buf.WriteString(indent) - } - - switch { - case key.isAutoIncrement: - kname = "-" - case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters): - kname = "`" + kname + "`" - case strings.Contains(kname, "`"): - kname = `"""` + kname + `"""` - } - - writeKeyValue := func(val string) (bool, error) { - if _, err := buf.WriteString(kname); err != nil { - return false, err - } - - if key.isBooleanType { - buf.WriteString(LineBreak) - return true, nil - } - - // Write out alignment spaces before "=" sign - if PrettyFormat { - buf.Write(alignSpaces[:alignLength-len(kname)]) - } - - // In case key value contains "\n", "`", "\"", "#" or ";" - if strings.ContainsAny(val, "\n`") { - val = `"""` + val + `"""` - } else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") { - val = "`" + val + "`" - } else if len(strings.TrimSpace(val)) != len(val) { - val = `"` + val + `"` - } - if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil { - return false, err - } - return false, nil - } - - shadows := key.ValueWithShadows() - if len(shadows) == 0 { - if _, err := writeKeyValue(""); err != nil { - return nil, err - } - } - - for _, val := range shadows { - exitLoop, err := writeKeyValue(val) - if err != nil { - return nil, err - } else if exitLoop { - continue KeyList - } - } - - for _, val := range key.nestedValues { - if _, err := buf.WriteString(indent + " " + val + LineBreak); err != nil { - return nil, err - } - } - } - - if PrettySection && !isLastSection { - // Put a line between sections - if _, err := buf.WriteString(LineBreak); err != nil { - return nil, err - } - } - } - - return buf, nil -} - -// WriteToIndent writes content into io.Writer with given indention. -// If PrettyFormat has been set to be true, -// it will align "=" sign with spaces under each section. -func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) { - buf, err := f.writeToBuffer(indent) - if err != nil { - return 0, err - } - return buf.WriteTo(w) -} - -// WriteTo writes file content into io.Writer. -func (f *File) WriteTo(w io.Writer) (int64, error) { - return f.WriteToIndent(w, "") -} - -// SaveToIndent writes content to file system with given value indention. -func (f *File) SaveToIndent(filename, indent string) error { - // Note: Because we are truncating with os.Create, - // so it's safer to save to a temporary file location and rename after done. - buf, err := f.writeToBuffer(indent) - if err != nil { - return err - } - - return ioutil.WriteFile(filename, buf.Bytes(), 0666) -} - -// SaveTo writes content to file system. -func (f *File) SaveTo(filename string) error { - return f.SaveToIndent(filename, "") -} diff --git a/vendor/gopkg.in/ini.v1/helper.go b/vendor/gopkg.in/ini.v1/helper.go deleted file mode 100644 index f9d80a682a..0000000000 --- a/vendor/gopkg.in/ini.v1/helper.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 Unknwon -// -// 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 ini - -func inSlice(str string, s []string) bool { - for _, v := range s { - if str == v { - return true - } - } - return false -} diff --git a/vendor/gopkg.in/ini.v1/ini.go b/vendor/gopkg.in/ini.v1/ini.go deleted file mode 100644 index 99e7f86511..0000000000 --- a/vendor/gopkg.in/ini.v1/ini.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2014 Unknwon -// -// 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 ini provides INI file read and write functionality in Go. -package ini - -import ( - "os" - "regexp" - "runtime" - "strings" -) - -const ( - // Maximum allowed depth when recursively substituing variable names. - depthValues = 99 -) - -var ( - // DefaultSection is the name of default section. You can use this var or the string literal. - // In most of cases, an empty string is all you need to access the section. - DefaultSection = "DEFAULT" - - // LineBreak is the delimiter to determine or compose a new line. - // This variable will be changed to "\r\n" automatically on Windows at package init time. - LineBreak = "\n" - - // Variable regexp pattern: %(variable)s - varPattern = regexp.MustCompile(`%\(([^)]+)\)s`) - - // DefaultHeader explicitly writes default section header. - DefaultHeader = false - - // PrettySection indicates whether to put a line between sections. - PrettySection = true - // PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output - // or reduce all possible spaces for compact format. - PrettyFormat = true - // PrettyEqual places spaces around "=" sign even when PrettyFormat is false. - PrettyEqual = false - // DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled. - DefaultFormatLeft = "" - // DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled. - DefaultFormatRight = "" -) - -var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test") - -func init() { - if runtime.GOOS == "windows" && !inTest { - LineBreak = "\r\n" - } -} - -// LoadOptions contains all customized options used for load data source(s). -type LoadOptions struct { - // Loose indicates whether the parser should ignore nonexistent files or return error. - Loose bool - // Insensitive indicates whether the parser forces all section and key names to lowercase. - Insensitive bool - // InsensitiveSections indicates whether the parser forces all section to lowercase. - InsensitiveSections bool - // InsensitiveKeys indicates whether the parser forces all key names to lowercase. - InsensitiveKeys bool - // IgnoreContinuation indicates whether to ignore continuation lines while parsing. - IgnoreContinuation bool - // IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value. - IgnoreInlineComment bool - // SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs. - SkipUnrecognizableLines bool - // ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source. - ShortCircuit bool - // AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing. - // This type of keys are mostly used in my.cnf. - AllowBooleanKeys bool - // AllowShadows indicates whether to keep track of keys with same name under same section. - AllowShadows bool - // AllowNestedValues indicates whether to allow AWS-like nested values. - // Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values - AllowNestedValues bool - // AllowPythonMultilineValues indicates whether to allow Python-like multi-line values. - // Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure - // Relevant quote: Values can also span multiple lines, as long as they are indented deeper - // than the first line of the value. - AllowPythonMultilineValues bool - // SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value. - // Docs: https://docs.python.org/2/library/configparser.html - // Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names. - // In the latter case, they need to be preceded by a whitespace character to be recognized as a comment. - SpaceBeforeInlineComment bool - // UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format - // when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value" - UnescapeValueDoubleQuotes bool - // UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format - // when value is NOT surrounded by any quotes. - // Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all. - UnescapeValueCommentSymbols bool - // UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise - // conform to key/value pairs. Specify the names of those blocks here. - UnparseableSections []string - // KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:". - KeyValueDelimiters string - // KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=". - KeyValueDelimiterOnWrite string - // ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".". - ChildSectionDelimiter string - // PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes). - PreserveSurroundedQuote bool - // DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values). - DebugFunc DebugFunc - // ReaderBufferSize is the buffer size of the reader in bytes. - ReaderBufferSize int - // AllowNonUniqueSections indicates whether to allow sections with the same name multiple times. - AllowNonUniqueSections bool - // AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated. - AllowDuplicateShadowValues bool -} - -// DebugFunc is the type of function called to log parse events. -type DebugFunc func(message string) - -// LoadSources allows caller to apply customized options for loading from data source(s). -func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) { - sources := make([]dataSource, len(others)+1) - sources[0], err = parseDataSource(source) - if err != nil { - return nil, err - } - for i := range others { - sources[i+1], err = parseDataSource(others[i]) - if err != nil { - return nil, err - } - } - f := newFile(sources, opts) - if err = f.Reload(); err != nil { - return nil, err - } - return f, nil -} - -// Load loads and parses from INI data sources. -// Arguments can be mixed of file name with string type, or raw data in []byte. -// It will return error if list contains nonexistent files. -func Load(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{}, source, others...) -} - -// LooseLoad has exactly same functionality as Load function -// except it ignores nonexistent files instead of returning error. -func LooseLoad(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{Loose: true}, source, others...) -} - -// InsensitiveLoad has exactly same functionality as Load function -// except it forces all section and key names to be lowercased. -func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{Insensitive: true}, source, others...) -} - -// ShadowLoad has exactly same functionality as Load function -// except it allows have shadow keys. -func ShadowLoad(source interface{}, others ...interface{}) (*File, error) { - return LoadSources(LoadOptions{AllowShadows: true}, source, others...) -} diff --git a/vendor/gopkg.in/ini.v1/key.go b/vendor/gopkg.in/ini.v1/key.go deleted file mode 100644 index a19d9f38ef..0000000000 --- a/vendor/gopkg.in/ini.v1/key.go +++ /dev/null @@ -1,837 +0,0 @@ -// Copyright 2014 Unknwon -// -// 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 ini - -import ( - "bytes" - "errors" - "fmt" - "strconv" - "strings" - "time" -) - -// Key represents a key under a section. -type Key struct { - s *Section - Comment string - name string - value string - isAutoIncrement bool - isBooleanType bool - - isShadow bool - shadows []*Key - - nestedValues []string -} - -// newKey simply return a key object with given values. -func newKey(s *Section, name, val string) *Key { - return &Key{ - s: s, - name: name, - value: val, - } -} - -func (k *Key) addShadow(val string) error { - if k.isShadow { - return errors.New("cannot add shadow to another shadow key") - } else if k.isAutoIncrement || k.isBooleanType { - return errors.New("cannot add shadow to auto-increment or boolean key") - } - - if !k.s.f.options.AllowDuplicateShadowValues { - // Deduplicate shadows based on their values. - if k.value == val { - return nil - } - for i := range k.shadows { - if k.shadows[i].value == val { - return nil - } - } - } - - shadow := newKey(k.s, k.name, val) - shadow.isShadow = true - k.shadows = append(k.shadows, shadow) - return nil -} - -// AddShadow adds a new shadow key to itself. -func (k *Key) AddShadow(val string) error { - if !k.s.f.options.AllowShadows { - return errors.New("shadow key is not allowed") - } - return k.addShadow(val) -} - -func (k *Key) addNestedValue(val string) error { - if k.isAutoIncrement || k.isBooleanType { - return errors.New("cannot add nested value to auto-increment or boolean key") - } - - k.nestedValues = append(k.nestedValues, val) - return nil -} - -// AddNestedValue adds a nested value to the key. -func (k *Key) AddNestedValue(val string) error { - if !k.s.f.options.AllowNestedValues { - return errors.New("nested value is not allowed") - } - return k.addNestedValue(val) -} - -// ValueMapper represents a mapping function for values, e.g. os.ExpandEnv -type ValueMapper func(string) string - -// Name returns name of key. -func (k *Key) Name() string { - return k.name -} - -// Value returns raw value of key for performance purpose. -func (k *Key) Value() string { - return k.value -} - -// ValueWithShadows returns raw values of key and its shadows if any. Shadow -// keys with empty values are ignored from the returned list. -func (k *Key) ValueWithShadows() []string { - if len(k.shadows) == 0 { - if k.value == "" { - return []string{} - } - return []string{k.value} - } - - vals := make([]string, 0, len(k.shadows)+1) - if k.value != "" { - vals = append(vals, k.value) - } - for _, s := range k.shadows { - if s.value != "" { - vals = append(vals, s.value) - } - } - return vals -} - -// NestedValues returns nested values stored in the key. -// It is possible returned value is nil if no nested values stored in the key. -func (k *Key) NestedValues() []string { - return k.nestedValues -} - -// transformValue takes a raw value and transforms to its final string. -func (k *Key) transformValue(val string) string { - if k.s.f.ValueMapper != nil { - val = k.s.f.ValueMapper(val) - } - - // Fail-fast if no indicate char found for recursive value - if !strings.Contains(val, "%") { - return val - } - for i := 0; i < depthValues; i++ { - vr := varPattern.FindString(val) - if len(vr) == 0 { - break - } - - // Take off leading '%(' and trailing ')s'. - noption := vr[2 : len(vr)-2] - - // Search in the same section. - // If not found or found the key itself, then search again in default section. - nk, err := k.s.GetKey(noption) - if err != nil || k == nk { - nk, _ = k.s.f.Section("").GetKey(noption) - if nk == nil { - // Stop when no results found in the default section, - // and returns the value as-is. - break - } - } - - // Substitute by new value and take off leading '%(' and trailing ')s'. - val = strings.Replace(val, vr, nk.value, -1) - } - return val -} - -// String returns string representation of value. -func (k *Key) String() string { - return k.transformValue(k.value) -} - -// Validate accepts a validate function which can -// return modifed result as key value. -func (k *Key) Validate(fn func(string) string) string { - return fn(k.String()) -} - -// parseBool returns the boolean value represented by the string. -// -// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On, -// 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off. -// Any other value returns an error. -func parseBool(str string) (value bool, err error) { - switch str { - case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On": - return true, nil - case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off": - return false, nil - } - return false, fmt.Errorf("parsing \"%s\": invalid syntax", str) -} - -// Bool returns bool type value. -func (k *Key) Bool() (bool, error) { - return parseBool(k.String()) -} - -// Float64 returns float64 type value. -func (k *Key) Float64() (float64, error) { - return strconv.ParseFloat(k.String(), 64) -} - -// Int returns int type value. -func (k *Key) Int() (int, error) { - v, err := strconv.ParseInt(k.String(), 0, 64) - return int(v), err -} - -// Int64 returns int64 type value. -func (k *Key) Int64() (int64, error) { - return strconv.ParseInt(k.String(), 0, 64) -} - -// Uint returns uint type valued. -func (k *Key) Uint() (uint, error) { - u, e := strconv.ParseUint(k.String(), 0, 64) - return uint(u), e -} - -// Uint64 returns uint64 type value. -func (k *Key) Uint64() (uint64, error) { - return strconv.ParseUint(k.String(), 0, 64) -} - -// Duration returns time.Duration type value. -func (k *Key) Duration() (time.Duration, error) { - return time.ParseDuration(k.String()) -} - -// TimeFormat parses with given format and returns time.Time type value. -func (k *Key) TimeFormat(format string) (time.Time, error) { - return time.Parse(format, k.String()) -} - -// Time parses with RFC3339 format and returns time.Time type value. -func (k *Key) Time() (time.Time, error) { - return k.TimeFormat(time.RFC3339) -} - -// MustString returns default value if key value is empty. -func (k *Key) MustString(defaultVal string) string { - val := k.String() - if len(val) == 0 { - k.value = defaultVal - return defaultVal - } - return val -} - -// MustBool always returns value without error, -// it returns false if error occurs. -func (k *Key) MustBool(defaultVal ...bool) bool { - val, err := k.Bool() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatBool(defaultVal[0]) - return defaultVal[0] - } - return val -} - -// MustFloat64 always returns value without error, -// it returns 0.0 if error occurs. -func (k *Key) MustFloat64(defaultVal ...float64) float64 { - val, err := k.Float64() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64) - return defaultVal[0] - } - return val -} - -// MustInt always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt(defaultVal ...int) int { - val, err := k.Int() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatInt(int64(defaultVal[0]), 10) - return defaultVal[0] - } - return val -} - -// MustInt64 always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustInt64(defaultVal ...int64) int64 { - val, err := k.Int64() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatInt(defaultVal[0], 10) - return defaultVal[0] - } - return val -} - -// MustUint always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustUint(defaultVal ...uint) uint { - val, err := k.Uint() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatUint(uint64(defaultVal[0]), 10) - return defaultVal[0] - } - return val -} - -// MustUint64 always returns value without error, -// it returns 0 if error occurs. -func (k *Key) MustUint64(defaultVal ...uint64) uint64 { - val, err := k.Uint64() - if len(defaultVal) > 0 && err != nil { - k.value = strconv.FormatUint(defaultVal[0], 10) - return defaultVal[0] - } - return val -} - -// MustDuration always returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration { - val, err := k.Duration() - if len(defaultVal) > 0 && err != nil { - k.value = defaultVal[0].String() - return defaultVal[0] - } - return val -} - -// MustTimeFormat always parses with given format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time { - val, err := k.TimeFormat(format) - if len(defaultVal) > 0 && err != nil { - k.value = defaultVal[0].Format(format) - return defaultVal[0] - } - return val -} - -// MustTime always parses with RFC3339 format and returns value without error, -// it returns zero value if error occurs. -func (k *Key) MustTime(defaultVal ...time.Time) time.Time { - return k.MustTimeFormat(time.RFC3339, defaultVal...) -} - -// In always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) In(defaultVal string, candidates []string) string { - val := k.String() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InFloat64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { - val := k.MustFloat64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt(defaultVal int, candidates []int) int { - val := k.MustInt() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InInt64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { - val := k.MustInt64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InUint always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InUint(defaultVal uint, candidates []uint) uint { - val := k.MustUint() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InUint64 always returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 { - val := k.MustUint64() - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTimeFormat always parses with given format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time { - val := k.MustTimeFormat(format) - for _, cand := range candidates { - if val == cand { - return val - } - } - return defaultVal -} - -// InTime always parses with RFC3339 format and returns value without error, -// it returns default value if error occurs or doesn't fit into candidates. -func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time { - return k.InTimeFormat(time.RFC3339, defaultVal, candidates) -} - -// RangeFloat64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 { - val := k.MustFloat64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt(defaultVal, min, max int) int { - val := k.MustInt() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeInt64 checks if value is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeInt64(defaultVal, min, max int64) int64 { - val := k.MustInt64() - if val < min || val > max { - return defaultVal - } - return val -} - -// RangeTimeFormat checks if value with given format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time { - val := k.MustTimeFormat(format) - if val.Unix() < min.Unix() || val.Unix() > max.Unix() { - return defaultVal - } - return val -} - -// RangeTime checks if value with RFC3339 format is in given range inclusively, -// and returns default value if it's not. -func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time { - return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max) -} - -// Strings returns list of string divided by given delimiter. -func (k *Key) Strings(delim string) []string { - str := k.String() - if len(str) == 0 { - return []string{} - } - - runes := []rune(str) - vals := make([]string, 0, 2) - var buf bytes.Buffer - escape := false - idx := 0 - for { - if escape { - escape = false - if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) { - buf.WriteRune('\\') - } - buf.WriteRune(runes[idx]) - } else { - if runes[idx] == '\\' { - escape = true - } else if strings.HasPrefix(string(runes[idx:]), delim) { - idx += len(delim) - 1 - vals = append(vals, strings.TrimSpace(buf.String())) - buf.Reset() - } else { - buf.WriteRune(runes[idx]) - } - } - idx++ - if idx == len(runes) { - break - } - } - - if buf.Len() > 0 { - vals = append(vals, strings.TrimSpace(buf.String())) - } - - return vals -} - -// StringsWithShadows returns list of string divided by given delimiter. -// Shadows will also be appended if any. -func (k *Key) StringsWithShadows(delim string) []string { - vals := k.ValueWithShadows() - results := make([]string, 0, len(vals)*2) - for i := range vals { - if len(vals) == 0 { - continue - } - - results = append(results, strings.Split(vals[i], delim)...) - } - - for i := range results { - results[i] = k.transformValue(strings.TrimSpace(results[i])) - } - return results -} - -// Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Float64s(delim string) []float64 { - vals, _ := k.parseFloat64s(k.Strings(delim), true, false) - return vals -} - -// Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Ints(delim string) []int { - vals, _ := k.parseInts(k.Strings(delim), true, false) - return vals -} - -// Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Int64s(delim string) []int64 { - vals, _ := k.parseInt64s(k.Strings(delim), true, false) - return vals -} - -// Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Uints(delim string) []uint { - vals, _ := k.parseUints(k.Strings(delim), true, false) - return vals -} - -// Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Uint64s(delim string) []uint64 { - vals, _ := k.parseUint64s(k.Strings(delim), true, false) - return vals -} - -// Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value. -func (k *Key) Bools(delim string) []bool { - vals, _ := k.parseBools(k.Strings(delim), true, false) - return vals -} - -// TimesFormat parses with given format and returns list of time.Time divided by given delimiter. -// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC). -func (k *Key) TimesFormat(format, delim string) []time.Time { - vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false) - return vals -} - -// Times parses with RFC3339 format and returns list of time.Time divided by given delimiter. -// Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC). -func (k *Key) Times(delim string) []time.Time { - return k.TimesFormat(time.RFC3339, delim) -} - -// ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then -// it will not be included to result list. -func (k *Key) ValidFloat64s(delim string) []float64 { - vals, _ := k.parseFloat64s(k.Strings(delim), false, false) - return vals -} - -// ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will -// not be included to result list. -func (k *Key) ValidInts(delim string) []int { - vals, _ := k.parseInts(k.Strings(delim), false, false) - return vals -} - -// ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer, -// then it will not be included to result list. -func (k *Key) ValidInt64s(delim string) []int64 { - vals, _ := k.parseInt64s(k.Strings(delim), false, false) - return vals -} - -// ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer, -// then it will not be included to result list. -func (k *Key) ValidUints(delim string) []uint { - vals, _ := k.parseUints(k.Strings(delim), false, false) - return vals -} - -// ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned -// integer, then it will not be included to result list. -func (k *Key) ValidUint64s(delim string) []uint64 { - vals, _ := k.parseUint64s(k.Strings(delim), false, false) - return vals -} - -// ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned -// integer, then it will not be included to result list. -func (k *Key) ValidBools(delim string) []bool { - vals, _ := k.parseBools(k.Strings(delim), false, false) - return vals -} - -// ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter. -func (k *Key) ValidTimesFormat(format, delim string) []time.Time { - vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false) - return vals -} - -// ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter. -func (k *Key) ValidTimes(delim string) []time.Time { - return k.ValidTimesFormat(time.RFC3339, delim) -} - -// StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input. -func (k *Key) StrictFloat64s(delim string) ([]float64, error) { - return k.parseFloat64s(k.Strings(delim), false, true) -} - -// StrictInts returns list of int divided by given delimiter or error on first invalid input. -func (k *Key) StrictInts(delim string) ([]int, error) { - return k.parseInts(k.Strings(delim), false, true) -} - -// StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input. -func (k *Key) StrictInt64s(delim string) ([]int64, error) { - return k.parseInt64s(k.Strings(delim), false, true) -} - -// StrictUints returns list of uint divided by given delimiter or error on first invalid input. -func (k *Key) StrictUints(delim string) ([]uint, error) { - return k.parseUints(k.Strings(delim), false, true) -} - -// StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input. -func (k *Key) StrictUint64s(delim string) ([]uint64, error) { - return k.parseUint64s(k.Strings(delim), false, true) -} - -// StrictBools returns list of bool divided by given delimiter or error on first invalid input. -func (k *Key) StrictBools(delim string) ([]bool, error) { - return k.parseBools(k.Strings(delim), false, true) -} - -// StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter -// or error on first invalid input. -func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) { - return k.parseTimesFormat(format, k.Strings(delim), false, true) -} - -// StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter -// or error on first invalid input. -func (k *Key) StrictTimes(delim string) ([]time.Time, error) { - return k.StrictTimesFormat(time.RFC3339, delim) -} - -// parseBools transforms strings to bools. -func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) { - vals := make([]bool, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := parseBool(str) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(bool)) - } - } - return vals, err -} - -// parseFloat64s transforms strings to float64s. -func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) { - vals := make([]float64, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseFloat(str, 64) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(float64)) - } - } - return vals, err -} - -// parseInts transforms strings to ints. -func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) { - vals := make([]int, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseInt(str, 0, 64) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, int(val.(int64))) - } - } - return vals, err -} - -// parseInt64s transforms strings to int64s. -func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) { - vals := make([]int64, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseInt(str, 0, 64) - return val, err - } - - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(int64)) - } - } - return vals, err -} - -// parseUints transforms strings to uints. -func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) { - vals := make([]uint, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseUint(str, 0, 64) - return val, err - } - - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, uint(val.(uint64))) - } - } - return vals, err -} - -// parseUint64s transforms strings to uint64s. -func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) { - vals := make([]uint64, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := strconv.ParseUint(str, 0, 64) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(uint64)) - } - } - return vals, err -} - -type Parser func(str string) (interface{}, error) - -// parseTimesFormat transforms strings to times in given format. -func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) { - vals := make([]time.Time, 0, len(strs)) - parser := func(str string) (interface{}, error) { - val, err := time.Parse(format, str) - return val, err - } - rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) - if err == nil { - for _, val := range rawVals { - vals = append(vals, val.(time.Time)) - } - } - return vals, err -} - -// doParse transforms strings to different types -func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) { - vals := make([]interface{}, 0, len(strs)) - for _, str := range strs { - val, err := parser(str) - if err != nil && returnOnInvalid { - return nil, err - } - if err == nil || addInvalid { - vals = append(vals, val) - } - } - return vals, nil -} - -// SetValue changes key value. -func (k *Key) SetValue(v string) { - if k.s.f.BlockMode { - k.s.f.lock.Lock() - defer k.s.f.lock.Unlock() - } - - k.value = v - k.s.keysHash[k.name] = v -} diff --git a/vendor/gopkg.in/ini.v1/parser.go b/vendor/gopkg.in/ini.v1/parser.go deleted file mode 100644 index 44fc526c2c..0000000000 --- a/vendor/gopkg.in/ini.v1/parser.go +++ /dev/null @@ -1,520 +0,0 @@ -// Copyright 2015 Unknwon -// -// 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 ini - -import ( - "bufio" - "bytes" - "fmt" - "io" - "regexp" - "strconv" - "strings" - "unicode" -) - -const minReaderBufferSize = 4096 - -var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`) - -type parserOptions struct { - IgnoreContinuation bool - IgnoreInlineComment bool - AllowPythonMultilineValues bool - SpaceBeforeInlineComment bool - UnescapeValueDoubleQuotes bool - UnescapeValueCommentSymbols bool - PreserveSurroundedQuote bool - DebugFunc DebugFunc - ReaderBufferSize int -} - -type parser struct { - buf *bufio.Reader - options parserOptions - - isEOF bool - count int - comment *bytes.Buffer -} - -func (p *parser) debug(format string, args ...interface{}) { - if p.options.DebugFunc != nil { - p.options.DebugFunc(fmt.Sprintf(format, args...)) - } -} - -func newParser(r io.Reader, opts parserOptions) *parser { - size := opts.ReaderBufferSize - if size < minReaderBufferSize { - size = minReaderBufferSize - } - - return &parser{ - buf: bufio.NewReaderSize(r, size), - options: opts, - count: 1, - comment: &bytes.Buffer{}, - } -} - -// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format. -// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding -func (p *parser) BOM() error { - mask, err := p.buf.Peek(2) - if err != nil && err != io.EOF { - return err - } else if len(mask) < 2 { - return nil - } - - switch { - case mask[0] == 254 && mask[1] == 255: - fallthrough - case mask[0] == 255 && mask[1] == 254: - _, err = p.buf.Read(mask) - if err != nil { - return err - } - case mask[0] == 239 && mask[1] == 187: - mask, err := p.buf.Peek(3) - if err != nil && err != io.EOF { - return err - } else if len(mask) < 3 { - return nil - } - if mask[2] == 191 { - _, err = p.buf.Read(mask) - if err != nil { - return err - } - } - } - return nil -} - -func (p *parser) readUntil(delim byte) ([]byte, error) { - data, err := p.buf.ReadBytes(delim) - if err != nil { - if err == io.EOF { - p.isEOF = true - } else { - return nil, err - } - } - return data, nil -} - -func cleanComment(in []byte) ([]byte, bool) { - i := bytes.IndexAny(in, "#;") - if i == -1 { - return nil, false - } - return in[i:], true -} - -func readKeyName(delimiters string, in []byte) (string, int, error) { - line := string(in) - - // Check if key name surrounded by quotes. - var keyQuote string - if line[0] == '"' { - if len(line) > 6 && line[0:3] == `"""` { - keyQuote = `"""` - } else { - keyQuote = `"` - } - } else if line[0] == '`' { - keyQuote = "`" - } - - // Get out key name - var endIdx int - if len(keyQuote) > 0 { - startIdx := len(keyQuote) - // FIXME: fail case -> """"""name"""=value - pos := strings.Index(line[startIdx:], keyQuote) - if pos == -1 { - return "", -1, fmt.Errorf("missing closing key quote: %s", line) - } - pos += startIdx - - // Find key-value delimiter - i := strings.IndexAny(line[pos+startIdx:], delimiters) - if i < 0 { - return "", -1, ErrDelimiterNotFound{line} - } - endIdx = pos + i - return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil - } - - endIdx = strings.IndexAny(line, delimiters) - if endIdx < 0 { - return "", -1, ErrDelimiterNotFound{line} - } - if endIdx == 0 { - return "", -1, ErrEmptyKeyName{line} - } - - return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil -} - -func (p *parser) readMultilines(line, val, valQuote string) (string, error) { - for { - data, err := p.readUntil('\n') - if err != nil { - return "", err - } - next := string(data) - - pos := strings.LastIndex(next, valQuote) - if pos > -1 { - val += next[:pos] - - comment, has := cleanComment([]byte(next[pos:])) - if has { - p.comment.Write(bytes.TrimSpace(comment)) - } - break - } - val += next - if p.isEOF { - return "", fmt.Errorf("missing closing key quote from %q to %q", line, next) - } - } - return val, nil -} - -func (p *parser) readContinuationLines(val string) (string, error) { - for { - data, err := p.readUntil('\n') - if err != nil { - return "", err - } - next := strings.TrimSpace(string(data)) - - if len(next) == 0 { - break - } - val += next - if val[len(val)-1] != '\\' { - break - } - val = val[:len(val)-1] - } - return val, nil -} - -// hasSurroundedQuote check if and only if the first and last characters -// are quotes \" or \'. -// It returns false if any other parts also contain same kind of quotes. -func hasSurroundedQuote(in string, quote byte) bool { - return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote && - strings.IndexByte(in[1:], quote) == len(in)-2 -} - -func (p *parser) readValue(in []byte, bufferSize int) (string, error) { - - line := strings.TrimLeftFunc(string(in), unicode.IsSpace) - if len(line) == 0 { - if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' { - return p.readPythonMultilines(line, bufferSize) - } - return "", nil - } - - var valQuote string - if len(line) > 3 && line[0:3] == `"""` { - valQuote = `"""` - } else if line[0] == '`' { - valQuote = "`" - } else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' { - valQuote = `"` - } - - if len(valQuote) > 0 { - startIdx := len(valQuote) - pos := strings.LastIndex(line[startIdx:], valQuote) - // Check for multi-line value - if pos == -1 { - return p.readMultilines(line, line[startIdx:], valQuote) - } - - if p.options.UnescapeValueDoubleQuotes && valQuote == `"` { - return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil - } - return line[startIdx : pos+startIdx], nil - } - - lastChar := line[len(line)-1] - // Won't be able to reach here if value only contains whitespace - line = strings.TrimSpace(line) - trimmedLastChar := line[len(line)-1] - - // Check continuation lines when desired - if !p.options.IgnoreContinuation && trimmedLastChar == '\\' { - return p.readContinuationLines(line[:len(line)-1]) - } - - // Check if ignore inline comment - if !p.options.IgnoreInlineComment { - var i int - if p.options.SpaceBeforeInlineComment { - i = strings.Index(line, " #") - if i == -1 { - i = strings.Index(line, " ;") - } - - } else { - i = strings.IndexAny(line, "#;") - } - - if i > -1 { - p.comment.WriteString(line[i:]) - line = strings.TrimSpace(line[:i]) - } - - } - - // Trim single and double quotes - if (hasSurroundedQuote(line, '\'') || - hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote { - line = line[1 : len(line)-1] - } else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols { - line = strings.ReplaceAll(line, `\;`, ";") - line = strings.ReplaceAll(line, `\#`, "#") - } else if p.options.AllowPythonMultilineValues && lastChar == '\n' { - return p.readPythonMultilines(line, bufferSize) - } - - return line, nil -} - -func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) { - parserBufferPeekResult, _ := p.buf.Peek(bufferSize) - peekBuffer := bytes.NewBuffer(parserBufferPeekResult) - - for { - peekData, peekErr := peekBuffer.ReadBytes('\n') - if peekErr != nil && peekErr != io.EOF { - p.debug("readPythonMultilines: failed to peek with error: %v", peekErr) - return "", peekErr - } - - p.debug("readPythonMultilines: parsing %q", string(peekData)) - - peekMatches := pythonMultiline.FindStringSubmatch(string(peekData)) - p.debug("readPythonMultilines: matched %d parts", len(peekMatches)) - for n, v := range peekMatches { - p.debug(" %d: %q", n, v) - } - - // Return if not a Python multiline value. - if len(peekMatches) != 3 { - p.debug("readPythonMultilines: end of value, got: %q", line) - return line, nil - } - - // Advance the parser reader (buffer) in-sync with the peek buffer. - _, err := p.buf.Discard(len(peekData)) - if err != nil { - p.debug("readPythonMultilines: failed to skip to the end, returning error") - return "", err - } - - line += "\n" + peekMatches[0] - } -} - -// parse parses data through an io.Reader. -func (f *File) parse(reader io.Reader) (err error) { - p := newParser(reader, parserOptions{ - IgnoreContinuation: f.options.IgnoreContinuation, - IgnoreInlineComment: f.options.IgnoreInlineComment, - AllowPythonMultilineValues: f.options.AllowPythonMultilineValues, - SpaceBeforeInlineComment: f.options.SpaceBeforeInlineComment, - UnescapeValueDoubleQuotes: f.options.UnescapeValueDoubleQuotes, - UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols, - PreserveSurroundedQuote: f.options.PreserveSurroundedQuote, - DebugFunc: f.options.DebugFunc, - ReaderBufferSize: f.options.ReaderBufferSize, - }) - if err = p.BOM(); err != nil { - return fmt.Errorf("BOM: %v", err) - } - - // Ignore error because default section name is never empty string. - name := DefaultSection - if f.options.Insensitive || f.options.InsensitiveSections { - name = strings.ToLower(DefaultSection) - } - section, _ := f.NewSection(name) - - // This "last" is not strictly equivalent to "previous one" if current key is not the first nested key - var isLastValueEmpty bool - var lastRegularKey *Key - - var line []byte - var inUnparseableSection bool - - // NOTE: Iterate and increase `currentPeekSize` until - // the size of the parser buffer is found. - // TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`. - parserBufferSize := 0 - // NOTE: Peek 4kb at a time. - currentPeekSize := minReaderBufferSize - - if f.options.AllowPythonMultilineValues { - for { - peekBytes, _ := p.buf.Peek(currentPeekSize) - peekBytesLength := len(peekBytes) - - if parserBufferSize >= peekBytesLength { - break - } - - currentPeekSize *= 2 - parserBufferSize = peekBytesLength - } - } - - for !p.isEOF { - line, err = p.readUntil('\n') - if err != nil { - return err - } - - if f.options.AllowNestedValues && - isLastValueEmpty && len(line) > 0 { - if line[0] == ' ' || line[0] == '\t' { - err = lastRegularKey.addNestedValue(string(bytes.TrimSpace(line))) - if err != nil { - return err - } - continue - } - } - - line = bytes.TrimLeftFunc(line, unicode.IsSpace) - if len(line) == 0 { - continue - } - - // Comments - if line[0] == '#' || line[0] == ';' { - // Note: we do not care ending line break, - // it is needed for adding second line, - // so just clean it once at the end when set to value. - p.comment.Write(line) - continue - } - - // Section - if line[0] == '[' { - // Read to the next ']' (TODO: support quoted strings) - closeIdx := bytes.LastIndexByte(line, ']') - if closeIdx == -1 { - return fmt.Errorf("unclosed section: %s", line) - } - - name := string(line[1:closeIdx]) - section, err = f.NewSection(name) - if err != nil { - return err - } - - comment, has := cleanComment(line[closeIdx+1:]) - if has { - p.comment.Write(comment) - } - - section.Comment = strings.TrimSpace(p.comment.String()) - - // Reset auto-counter and comments - p.comment.Reset() - p.count = 1 - // Nested values can't span sections - isLastValueEmpty = false - - inUnparseableSection = false - for i := range f.options.UnparseableSections { - if f.options.UnparseableSections[i] == name || - ((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) { - inUnparseableSection = true - continue - } - } - continue - } - - if inUnparseableSection { - section.isRawSection = true - section.rawBody += string(line) - continue - } - - kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line) - if err != nil { - switch { - // Treat as boolean key when desired, and whole line is key name. - case IsErrDelimiterNotFound(err): - switch { - case f.options.AllowBooleanKeys: - kname, err := p.readValue(line, parserBufferSize) - if err != nil { - return err - } - key, err := section.NewBooleanKey(kname) - if err != nil { - return err - } - key.Comment = strings.TrimSpace(p.comment.String()) - p.comment.Reset() - continue - - case f.options.SkipUnrecognizableLines: - continue - } - case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines: - continue - } - return err - } - - // Auto increment. - isAutoIncr := false - if kname == "-" { - isAutoIncr = true - kname = "#" + strconv.Itoa(p.count) - p.count++ - } - - value, err := p.readValue(line[offset:], parserBufferSize) - if err != nil { - return err - } - isLastValueEmpty = len(value) == 0 - - key, err := section.NewKey(kname, value) - if err != nil { - return err - } - key.isAutoIncrement = isAutoIncr - key.Comment = strings.TrimSpace(p.comment.String()) - p.comment.Reset() - lastRegularKey = key - } - return nil -} diff --git a/vendor/gopkg.in/ini.v1/section.go b/vendor/gopkg.in/ini.v1/section.go deleted file mode 100644 index a3615d820b..0000000000 --- a/vendor/gopkg.in/ini.v1/section.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2014 Unknwon -// -// 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 ini - -import ( - "errors" - "fmt" - "strings" -) - -// Section represents a config section. -type Section struct { - f *File - Comment string - name string - keys map[string]*Key - keyList []string - keysHash map[string]string - - isRawSection bool - rawBody string -} - -func newSection(f *File, name string) *Section { - return &Section{ - f: f, - name: name, - keys: make(map[string]*Key), - keyList: make([]string, 0, 10), - keysHash: make(map[string]string), - } -} - -// Name returns name of Section. -func (s *Section) Name() string { - return s.name -} - -// Body returns rawBody of Section if the section was marked as unparseable. -// It still follows the other rules of the INI format surrounding leading/trailing whitespace. -func (s *Section) Body() string { - return strings.TrimSpace(s.rawBody) -} - -// SetBody updates body content only if section is raw. -func (s *Section) SetBody(body string) { - if !s.isRawSection { - return - } - s.rawBody = body -} - -// NewKey creates a new key to given section. -func (s *Section) NewKey(name, val string) (*Key, error) { - if len(name) == 0 { - return nil, errors.New("error creating new key: empty key name") - } else if s.f.options.Insensitive || s.f.options.InsensitiveKeys { - name = strings.ToLower(name) - } - - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - if inSlice(name, s.keyList) { - if s.f.options.AllowShadows { - if err := s.keys[name].addShadow(val); err != nil { - return nil, err - } - } else { - s.keys[name].value = val - s.keysHash[name] = val - } - return s.keys[name], nil - } - - s.keyList = append(s.keyList, name) - s.keys[name] = newKey(s, name, val) - s.keysHash[name] = val - return s.keys[name], nil -} - -// NewBooleanKey creates a new boolean type key to given section. -func (s *Section) NewBooleanKey(name string) (*Key, error) { - key, err := s.NewKey(name, "true") - if err != nil { - return nil, err - } - - key.isBooleanType = true - return key, nil -} - -// GetKey returns key in section by given name. -func (s *Section) GetKey(name string) (*Key, error) { - if s.f.BlockMode { - s.f.lock.RLock() - } - if s.f.options.Insensitive || s.f.options.InsensitiveKeys { - name = strings.ToLower(name) - } - key := s.keys[name] - if s.f.BlockMode { - s.f.lock.RUnlock() - } - - if key == nil { - // Check if it is a child-section. - sname := s.name - for { - if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 { - sname = sname[:i] - sec, err := s.f.GetSection(sname) - if err != nil { - continue - } - return sec.GetKey(name) - } - break - } - return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name) - } - return key, nil -} - -// HasKey returns true if section contains a key with given name. -func (s *Section) HasKey(name string) bool { - key, _ := s.GetKey(name) - return key != nil -} - -// Deprecated: Use "HasKey" instead. -func (s *Section) Haskey(name string) bool { - return s.HasKey(name) -} - -// HasValue returns true if section contains given raw value. -func (s *Section) HasValue(value string) bool { - if s.f.BlockMode { - s.f.lock.RLock() - defer s.f.lock.RUnlock() - } - - for _, k := range s.keys { - if value == k.value { - return true - } - } - return false -} - -// Key assumes named Key exists in section and returns a zero-value when not. -func (s *Section) Key(name string) *Key { - key, err := s.GetKey(name) - if err != nil { - // It's OK here because the only possible error is empty key name, - // but if it's empty, this piece of code won't be executed. - key, _ = s.NewKey(name, "") - return key - } - return key -} - -// Keys returns list of keys of section. -func (s *Section) Keys() []*Key { - keys := make([]*Key, len(s.keyList)) - for i := range s.keyList { - keys[i] = s.Key(s.keyList[i]) - } - return keys -} - -// ParentKeys returns list of keys of parent section. -func (s *Section) ParentKeys() []*Key { - var parentKeys []*Key - sname := s.name - for { - if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 { - sname = sname[:i] - sec, err := s.f.GetSection(sname) - if err != nil { - continue - } - parentKeys = append(parentKeys, sec.Keys()...) - } else { - break - } - - } - return parentKeys -} - -// KeyStrings returns list of key names of section. -func (s *Section) KeyStrings() []string { - list := make([]string, len(s.keyList)) - copy(list, s.keyList) - return list -} - -// KeysHash returns keys hash consisting of names and values. -func (s *Section) KeysHash() map[string]string { - if s.f.BlockMode { - s.f.lock.RLock() - defer s.f.lock.RUnlock() - } - - hash := make(map[string]string, len(s.keysHash)) - for key, value := range s.keysHash { - hash[key] = value - } - return hash -} - -// DeleteKey deletes a key from section. -func (s *Section) DeleteKey(name string) { - if s.f.BlockMode { - s.f.lock.Lock() - defer s.f.lock.Unlock() - } - - for i, k := range s.keyList { - if k == name { - s.keyList = append(s.keyList[:i], s.keyList[i+1:]...) - delete(s.keys, name) - delete(s.keysHash, name) - return - } - } -} - -// ChildSections returns a list of child sections of current section. -// For example, "[parent.child1]" and "[parent.child12]" are child sections -// of section "[parent]". -func (s *Section) ChildSections() []*Section { - prefix := s.name + s.f.options.ChildSectionDelimiter - children := make([]*Section, 0, 3) - for _, name := range s.f.sectionList { - if strings.HasPrefix(name, prefix) { - children = append(children, s.f.sections[name]...) - } - } - return children -} diff --git a/vendor/gopkg.in/ini.v1/struct.go b/vendor/gopkg.in/ini.v1/struct.go deleted file mode 100644 index a486b2fe0f..0000000000 --- a/vendor/gopkg.in/ini.v1/struct.go +++ /dev/null @@ -1,747 +0,0 @@ -// Copyright 2014 Unknwon -// -// 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 ini - -import ( - "bytes" - "errors" - "fmt" - "reflect" - "strings" - "time" - "unicode" -) - -// NameMapper represents a ini tag name mapper. -type NameMapper func(string) string - -// Built-in name getters. -var ( - // SnackCase converts to format SNACK_CASE. - SnackCase NameMapper = func(raw string) string { - newstr := make([]rune, 0, len(raw)) - for i, chr := range raw { - if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { - if i > 0 { - newstr = append(newstr, '_') - } - } - newstr = append(newstr, unicode.ToUpper(chr)) - } - return string(newstr) - } - // TitleUnderscore converts to format title_underscore. - TitleUnderscore NameMapper = func(raw string) string { - newstr := make([]rune, 0, len(raw)) - for i, chr := range raw { - if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { - if i > 0 { - newstr = append(newstr, '_') - } - chr -= 'A' - 'a' - } - newstr = append(newstr, chr) - } - return string(newstr) - } -) - -func (s *Section) parseFieldName(raw, actual string) string { - if len(actual) > 0 { - return actual - } - if s.f.NameMapper != nil { - return s.f.NameMapper(raw) - } - return raw -} - -func parseDelim(actual string) string { - if len(actual) > 0 { - return actual - } - return "," -} - -var reflectTime = reflect.TypeOf(time.Now()).Kind() - -// setSliceWithProperType sets proper values to slice based on its type. -func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error { - var strs []string - if allowShadow { - strs = key.StringsWithShadows(delim) - } else { - strs = key.Strings(delim) - } - - numVals := len(strs) - if numVals == 0 { - return nil - } - - var vals interface{} - var err error - - sliceOf := field.Type().Elem().Kind() - switch sliceOf { - case reflect.String: - vals = strs - case reflect.Int: - vals, err = key.parseInts(strs, true, false) - case reflect.Int64: - vals, err = key.parseInt64s(strs, true, false) - case reflect.Uint: - vals, err = key.parseUints(strs, true, false) - case reflect.Uint64: - vals, err = key.parseUint64s(strs, true, false) - case reflect.Float64: - vals, err = key.parseFloat64s(strs, true, false) - case reflect.Bool: - vals, err = key.parseBools(strs, true, false) - case reflectTime: - vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false) - default: - return fmt.Errorf("unsupported type '[]%s'", sliceOf) - } - if err != nil && isStrict { - return err - } - - slice := reflect.MakeSlice(field.Type(), numVals, numVals) - for i := 0; i < numVals; i++ { - switch sliceOf { - case reflect.String: - slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i])) - case reflect.Int: - slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i])) - case reflect.Int64: - slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i])) - case reflect.Uint: - slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i])) - case reflect.Uint64: - slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i])) - case reflect.Float64: - slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i])) - case reflect.Bool: - slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i])) - case reflectTime: - slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i])) - } - } - field.Set(slice) - return nil -} - -func wrapStrictError(err error, isStrict bool) error { - if isStrict { - return err - } - return nil -} - -// setWithProperType sets proper value to field based on its type, -// but it does not return error for failing parsing, -// because we want to use default value that is already assigned to struct. -func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error { - vt := t - isPtr := t.Kind() == reflect.Ptr - if isPtr { - vt = t.Elem() - } - switch vt.Kind() { - case reflect.String: - stringVal := key.String() - if isPtr { - field.Set(reflect.ValueOf(&stringVal)) - } else if len(stringVal) > 0 { - field.SetString(key.String()) - } - case reflect.Bool: - boolVal, err := key.Bool() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - field.Set(reflect.ValueOf(&boolVal)) - } else { - field.SetBool(boolVal) - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - // ParseDuration will not return err for `0`, so check the type name - if vt.Name() == "Duration" { - durationVal, err := key.Duration() - if err != nil { - if intVal, err := key.Int64(); err == nil { - field.SetInt(intVal) - return nil - } - return wrapStrictError(err, isStrict) - } - if isPtr { - field.Set(reflect.ValueOf(&durationVal)) - } else if int64(durationVal) > 0 { - field.Set(reflect.ValueOf(durationVal)) - } - return nil - } - - intVal, err := key.Int64() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - pv := reflect.New(t.Elem()) - pv.Elem().SetInt(intVal) - field.Set(pv) - } else { - field.SetInt(intVal) - } - // byte is an alias for uint8, so supporting uint8 breaks support for byte - case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: - durationVal, err := key.Duration() - // Skip zero value - if err == nil && uint64(durationVal) > 0 { - if isPtr { - field.Set(reflect.ValueOf(&durationVal)) - } else { - field.Set(reflect.ValueOf(durationVal)) - } - return nil - } - - uintVal, err := key.Uint64() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - pv := reflect.New(t.Elem()) - pv.Elem().SetUint(uintVal) - field.Set(pv) - } else { - field.SetUint(uintVal) - } - - case reflect.Float32, reflect.Float64: - floatVal, err := key.Float64() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - pv := reflect.New(t.Elem()) - pv.Elem().SetFloat(floatVal) - field.Set(pv) - } else { - field.SetFloat(floatVal) - } - case reflectTime: - timeVal, err := key.Time() - if err != nil { - return wrapStrictError(err, isStrict) - } - if isPtr { - field.Set(reflect.ValueOf(&timeVal)) - } else { - field.Set(reflect.ValueOf(timeVal)) - } - case reflect.Slice: - return setSliceWithProperType(key, field, delim, allowShadow, isStrict) - default: - return fmt.Errorf("unsupported type %q", t) - } - return nil -} - -func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) { - opts := strings.SplitN(tag, ",", 5) - rawName = opts[0] - for _, opt := range opts[1:] { - omitEmpty = omitEmpty || (opt == "omitempty") - allowShadow = allowShadow || (opt == "allowshadow") - allowNonUnique = allowNonUnique || (opt == "nonunique") - extends = extends || (opt == "extends") - } - return rawName, omitEmpty, allowShadow, allowNonUnique, extends -} - -// mapToField maps the given value to the matching field of the given section. -// The sectionIndex is the index (if non unique sections are enabled) to which the value should be added. -func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error { - if val.Kind() == reflect.Ptr { - val = val.Elem() - } - typ := val.Type() - - for i := 0; i < typ.NumField(); i++ { - field := val.Field(i) - tpField := typ.Field(i) - - tag := tpField.Tag.Get("ini") - if tag == "-" { - continue - } - - rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag) - fieldName := s.parseFieldName(tpField.Name, rawName) - if len(fieldName) == 0 || !field.CanSet() { - continue - } - - isStruct := tpField.Type.Kind() == reflect.Struct - isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct - isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous - if isAnonymousPtr { - field.Set(reflect.New(tpField.Type.Elem())) - } - - if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) { - if isStructPtr && field.IsNil() { - field.Set(reflect.New(tpField.Type.Elem())) - } - fieldSection := s - if rawName != "" { - sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName - if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) { - fieldSection = secs[sectionIndex] - } - } - if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil { - return fmt.Errorf("map to field %q: %v", fieldName, err) - } - } else if isAnonymousPtr || isStruct || isStructPtr { - if secs, err := s.f.SectionsByName(fieldName); err == nil { - if len(secs) <= sectionIndex { - return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName) - } - // Only set the field to non-nil struct value if we have a section for it. - // Otherwise, we end up with a non-nil struct ptr even though there is no data. - if isStructPtr && field.IsNil() { - field.Set(reflect.New(tpField.Type.Elem())) - } - if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil { - return fmt.Errorf("map to field %q: %v", fieldName, err) - } - continue - } - } - - // Map non-unique sections - if allowNonUnique && tpField.Type.Kind() == reflect.Slice { - newField, err := s.mapToSlice(fieldName, field, isStrict) - if err != nil { - return fmt.Errorf("map to slice %q: %v", fieldName, err) - } - - field.Set(newField) - continue - } - - if key, err := s.GetKey(fieldName); err == nil { - delim := parseDelim(tpField.Tag.Get("delim")) - if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil { - return fmt.Errorf("set field %q: %v", fieldName, err) - } - } - } - return nil -} - -// mapToSlice maps all sections with the same name and returns the new value. -// The type of the Value must be a slice. -func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) { - secs, err := s.f.SectionsByName(secName) - if err != nil { - return reflect.Value{}, err - } - - typ := val.Type().Elem() - for i, sec := range secs { - elem := reflect.New(typ) - if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil { - return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err) - } - - val = reflect.Append(val, elem.Elem()) - } - return val, nil -} - -// mapTo maps a section to object v. -func (s *Section) mapTo(v interface{}, isStrict bool) error { - typ := reflect.TypeOf(v) - val := reflect.ValueOf(v) - if typ.Kind() == reflect.Ptr { - typ = typ.Elem() - val = val.Elem() - } else { - return errors.New("not a pointer to a struct") - } - - if typ.Kind() == reflect.Slice { - newField, err := s.mapToSlice(s.name, val, isStrict) - if err != nil { - return err - } - - val.Set(newField) - return nil - } - - return s.mapToField(val, isStrict, 0, s.name) -} - -// MapTo maps section to given struct. -func (s *Section) MapTo(v interface{}) error { - return s.mapTo(v, false) -} - -// StrictMapTo maps section to given struct in strict mode, -// which returns all possible error including value parsing error. -func (s *Section) StrictMapTo(v interface{}) error { - return s.mapTo(v, true) -} - -// MapTo maps file to given struct. -func (f *File) MapTo(v interface{}) error { - return f.Section("").MapTo(v) -} - -// StrictMapTo maps file to given struct in strict mode, -// which returns all possible error including value parsing error. -func (f *File) StrictMapTo(v interface{}) error { - return f.Section("").StrictMapTo(v) -} - -// MapToWithMapper maps data sources to given struct with name mapper. -func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { - cfg, err := Load(source, others...) - if err != nil { - return err - } - cfg.NameMapper = mapper - return cfg.MapTo(v) -} - -// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode, -// which returns all possible error including value parsing error. -func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { - cfg, err := Load(source, others...) - if err != nil { - return err - } - cfg.NameMapper = mapper - return cfg.StrictMapTo(v) -} - -// MapTo maps data sources to given struct. -func MapTo(v, source interface{}, others ...interface{}) error { - return MapToWithMapper(v, nil, source, others...) -} - -// StrictMapTo maps data sources to given struct in strict mode, -// which returns all possible error including value parsing error. -func StrictMapTo(v, source interface{}, others ...interface{}) error { - return StrictMapToWithMapper(v, nil, source, others...) -} - -// reflectSliceWithProperType does the opposite thing as setSliceWithProperType. -func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error { - slice := field.Slice(0, field.Len()) - if field.Len() == 0 { - return nil - } - sliceOf := field.Type().Elem().Kind() - - if allowShadow { - var keyWithShadows *Key - for i := 0; i < field.Len(); i++ { - var val string - switch sliceOf { - case reflect.String: - val = slice.Index(i).String() - case reflect.Int, reflect.Int64: - val = fmt.Sprint(slice.Index(i).Int()) - case reflect.Uint, reflect.Uint64: - val = fmt.Sprint(slice.Index(i).Uint()) - case reflect.Float64: - val = fmt.Sprint(slice.Index(i).Float()) - case reflect.Bool: - val = fmt.Sprint(slice.Index(i).Bool()) - case reflectTime: - val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339) - default: - return fmt.Errorf("unsupported type '[]%s'", sliceOf) - } - - if i == 0 { - keyWithShadows = newKey(key.s, key.name, val) - } else { - _ = keyWithShadows.AddShadow(val) - } - } - *key = *keyWithShadows - return nil - } - - var buf bytes.Buffer - for i := 0; i < field.Len(); i++ { - switch sliceOf { - case reflect.String: - buf.WriteString(slice.Index(i).String()) - case reflect.Int, reflect.Int64: - buf.WriteString(fmt.Sprint(slice.Index(i).Int())) - case reflect.Uint, reflect.Uint64: - buf.WriteString(fmt.Sprint(slice.Index(i).Uint())) - case reflect.Float64: - buf.WriteString(fmt.Sprint(slice.Index(i).Float())) - case reflect.Bool: - buf.WriteString(fmt.Sprint(slice.Index(i).Bool())) - case reflectTime: - buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339)) - default: - return fmt.Errorf("unsupported type '[]%s'", sliceOf) - } - buf.WriteString(delim) - } - key.SetValue(buf.String()[:buf.Len()-len(delim)]) - return nil -} - -// reflectWithProperType does the opposite thing as setWithProperType. -func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error { - switch t.Kind() { - case reflect.String: - key.SetValue(field.String()) - case reflect.Bool: - key.SetValue(fmt.Sprint(field.Bool())) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - key.SetValue(fmt.Sprint(field.Int())) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - key.SetValue(fmt.Sprint(field.Uint())) - case reflect.Float32, reflect.Float64: - key.SetValue(fmt.Sprint(field.Float())) - case reflectTime: - key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339))) - case reflect.Slice: - return reflectSliceWithProperType(key, field, delim, allowShadow) - case reflect.Ptr: - if !field.IsNil() { - return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow) - } - default: - return fmt.Errorf("unsupported type %q", t) - } - return nil -} - -// CR: copied from encoding/json/encode.go with modifications of time.Time support. -// TODO: add more test coverage. -func isEmptyValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - case reflectTime: - t, ok := v.Interface().(time.Time) - return ok && t.IsZero() - } - return false -} - -// StructReflector is the interface implemented by struct types that can extract themselves into INI objects. -type StructReflector interface { - ReflectINIStruct(*File) error -} - -func (s *Section) reflectFrom(val reflect.Value) error { - if val.Kind() == reflect.Ptr { - val = val.Elem() - } - typ := val.Type() - - for i := 0; i < typ.NumField(); i++ { - if !val.Field(i).CanInterface() { - continue - } - - field := val.Field(i) - tpField := typ.Field(i) - - tag := tpField.Tag.Get("ini") - if tag == "-" { - continue - } - - rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag) - if omitEmpty && isEmptyValue(field) { - continue - } - - if r, ok := field.Interface().(StructReflector); ok { - return r.ReflectINIStruct(s.f) - } - - fieldName := s.parseFieldName(tpField.Name, rawName) - if len(fieldName) == 0 || !field.CanSet() { - continue - } - - if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) { - if err := s.reflectFrom(field); err != nil { - return fmt.Errorf("reflect from field %q: %v", fieldName, err) - } - continue - } - - if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) || - (tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") { - // Note: The only error here is section doesn't exist. - sec, err := s.f.GetSection(fieldName) - if err != nil { - // Note: fieldName can never be empty here, ignore error. - sec, _ = s.f.NewSection(fieldName) - } - - // Add comment from comment tag - if len(sec.Comment) == 0 { - sec.Comment = tpField.Tag.Get("comment") - } - - if err = sec.reflectFrom(field); err != nil { - return fmt.Errorf("reflect from field %q: %v", fieldName, err) - } - continue - } - - if allowNonUnique && tpField.Type.Kind() == reflect.Slice { - slice := field.Slice(0, field.Len()) - if field.Len() == 0 { - return nil - } - sliceOf := field.Type().Elem().Kind() - - for i := 0; i < field.Len(); i++ { - if sliceOf != reflect.Struct && sliceOf != reflect.Ptr { - return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName) - } - - sec, err := s.f.NewSection(fieldName) - if err != nil { - return err - } - - // Add comment from comment tag - if len(sec.Comment) == 0 { - sec.Comment = tpField.Tag.Get("comment") - } - - if err := sec.reflectFrom(slice.Index(i)); err != nil { - return fmt.Errorf("reflect from field %q: %v", fieldName, err) - } - } - continue - } - - // Note: Same reason as section. - key, err := s.GetKey(fieldName) - if err != nil { - key, _ = s.NewKey(fieldName, "") - } - - // Add comment from comment tag - if len(key.Comment) == 0 { - key.Comment = tpField.Tag.Get("comment") - } - - delim := parseDelim(tpField.Tag.Get("delim")) - if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil { - return fmt.Errorf("reflect field %q: %v", fieldName, err) - } - - } - return nil -} - -// ReflectFrom reflects section from given struct. It overwrites existing ones. -func (s *Section) ReflectFrom(v interface{}) error { - typ := reflect.TypeOf(v) - val := reflect.ValueOf(v) - - if s.name != DefaultSection && s.f.options.AllowNonUniqueSections && - (typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) { - // Clear sections to make sure none exists before adding the new ones - s.f.DeleteSection(s.name) - - if typ.Kind() == reflect.Ptr { - sec, err := s.f.NewSection(s.name) - if err != nil { - return err - } - return sec.reflectFrom(val.Elem()) - } - - slice := val.Slice(0, val.Len()) - sliceOf := val.Type().Elem().Kind() - if sliceOf != reflect.Ptr { - return fmt.Errorf("not a slice of pointers") - } - - for i := 0; i < slice.Len(); i++ { - sec, err := s.f.NewSection(s.name) - if err != nil { - return err - } - - err = sec.reflectFrom(slice.Index(i)) - if err != nil { - return fmt.Errorf("reflect from %dth field: %v", i, err) - } - } - - return nil - } - - if typ.Kind() == reflect.Ptr { - val = val.Elem() - } else { - return errors.New("not a pointer to a struct") - } - - return s.reflectFrom(val) -} - -// ReflectFrom reflects file from given struct. -func (f *File) ReflectFrom(v interface{}) error { - return f.Section("").ReflectFrom(v) -} - -// ReflectFromWithMapper reflects data sources from given struct with name mapper. -func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error { - cfg.NameMapper = mapper - return cfg.ReflectFrom(v) -} - -// ReflectFrom reflects data sources from given struct. -func ReflectFrom(cfg *File, v interface{}) error { - return ReflectFromWithMapper(cfg, v, nil) -} diff --git a/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go b/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go index f0272fd6ab..40bce2a68e 100644 --- a/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go +++ b/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go @@ -237,6 +237,9 @@ func coalesceValues(printf printFn, c *chart.Chart, v map[string]interface{}, pr printf("warning: skipped value for %s.%s: Not a table.", subPrefix, key) } } else { + // If the key is a child chart, coalesce tables with Merge set to true + merge := childChartMergeTrue(c, key, merge) + // Because v has higher precedence than nv, dest values override src // values. coalesceTablesFullKey(printf, dest, src, concatPrefix(subPrefix, key), merge) @@ -249,6 +252,15 @@ func coalesceValues(printf printFn, c *chart.Chart, v map[string]interface{}, pr } } +func childChartMergeTrue(chrt *chart.Chart, key string, merge bool) bool { + for _, subchart := range chrt.Dependencies() { + if subchart.Name() == key { + return true + } + } + return merge +} + // CoalesceTables merges a source map into a destination map. // // dest is considered authoritative. diff --git a/vendor/helm.sh/helm/v3/pkg/kube/resource.go b/vendor/helm.sh/helm/v3/pkg/kube/resource.go index d441db8a70..db8e9178e7 100644 --- a/vendor/helm.sh/helm/v3/pkg/kube/resource.go +++ b/vendor/helm.sh/helm/v3/pkg/kube/resource.go @@ -81,5 +81,5 @@ func (r ResourceList) Intersect(rs ResourceList) ResourceList { // isMatchingInfo returns true if infos match on Name and GroupVersionKind. func isMatchingInfo(a, b *resource.Info) bool { - return a.Name == b.Name && a.Namespace == b.Namespace && a.Mapping.GroupVersionKind.Kind == b.Mapping.GroupVersionKind.Kind + return a.Name == b.Name && a.Namespace == b.Namespace && a.Mapping.GroupVersionKind.Kind == b.Mapping.GroupVersionKind.Kind && a.Mapping.GroupVersionKind.Group == b.Mapping.GroupVersionKind.Group } diff --git a/vendor/k8s.io/api/resource/v1alpha3/types.go b/vendor/k8s.io/api/resource/v1alpha3/types.go index fb4d7041db..49d7c86de3 100644 --- a/vendor/k8s.io/api/resource/v1alpha3/types.go +++ b/vendor/k8s.io/api/resource/v1alpha3/types.go @@ -145,6 +145,10 @@ type ResourceSliceSpec struct { Devices []Device `json:"devices" protobuf:"bytes,6,name=devices"` } +// DriverNameMaxLength is the maximum valid length of a driver name in the +// ResourceSliceSpec and other places. It's the same as for CSI driver names. +const DriverNameMaxLength = 63 + // ResourcePool describes the pool that ResourceSlices belong to. type ResourcePool struct { // Name is used to identify the pool. For node-local devices, this diff --git a/vendor/k8s.io/api/resource/v1beta1/types.go b/vendor/k8s.io/api/resource/v1beta1/types.go index ca79c5a664..fbdc35ca86 100644 --- a/vendor/k8s.io/api/resource/v1beta1/types.go +++ b/vendor/k8s.io/api/resource/v1beta1/types.go @@ -144,6 +144,10 @@ type ResourceSliceSpec struct { Devices []Device `json:"devices" protobuf:"bytes,6,name=devices"` } +// DriverNameMaxLength is the maximum valid length of a driver name in the +// ResourceSliceSpec and other places. It's the same as for CSI driver names. +const DriverNameMaxLength = 63 + // ResourcePool describes the pool that ResourceSlices belong to. type ResourcePool struct { // Name is used to identify the pool. For node-local devices, this diff --git a/vendor/modules.txt b/vendor/modules.txt index b2db8f69d5..1d098bb5eb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -52,12 +52,11 @@ github.com/chai2010/gettext-go github.com/chai2010/gettext-go/mo github.com/chai2010/gettext-go/plural github.com/chai2010/gettext-go/po -# github.com/cilium/charts v0.0.0-20250204154402-8a35f8210901 +# github.com/cilium/charts v0.0.0-20250315135936-15c20a953df6 ## explicit; go 1.17 github.com/cilium/charts -# github.com/cilium/cilium v1.18.0-pre.0.0.20250307211928-06901cc99eca +# github.com/cilium/cilium v1.18.0-pre.0.0.20250321220641-9d59c1208ae1 ## explicit; go 1.24.0 -github.com/cilium/cilium github.com/cilium/cilium/api/v1/client github.com/cilium/cilium/api/v1/client/bgp github.com/cilium/cilium/api/v1/client/daemon @@ -104,8 +103,10 @@ github.com/cilium/cilium/cilium-cli/logging github.com/cilium/cilium/cilium-cli/multicast github.com/cilium/cilium/cilium-cli/status github.com/cilium/cilium/cilium-cli/sysdump +github.com/cilium/cilium/cilium-cli/utils/codeowners github.com/cilium/cilium/cilium-cli/utils/features github.com/cilium/cilium/cilium-cli/utils/lock +github.com/cilium/cilium/cilium-cli/utils/log github.com/cilium/cilium/cilium-cli/utils/runner github.com/cilium/cilium/cilium-cli/utils/wait github.com/cilium/cilium/daemon/k8s @@ -151,6 +152,7 @@ github.com/cilium/cilium/pkg/debug github.com/cilium/cilium/pkg/defaults github.com/cilium/cilium/pkg/endpoint/id github.com/cilium/cilium/pkg/endpoint/regeneration +github.com/cilium/cilium/pkg/envoy/policy github.com/cilium/cilium/pkg/envoy/resource github.com/cilium/cilium/pkg/fqdn/dns github.com/cilium/cilium/pkg/fqdn/matchpattern @@ -259,7 +261,7 @@ github.com/cilium/cilium/pkg/u8proto github.com/cilium/cilium/pkg/version github.com/cilium/cilium/pkg/versioncheck github.com/cilium/cilium/pkg/wireguard/types -# github.com/cilium/ebpf v0.17.1 +# github.com/cilium/ebpf v0.17.3 ## explicit; go 1.22 github.com/cilium/ebpf github.com/cilium/ebpf/asm @@ -275,16 +277,17 @@ github.com/cilium/ebpf/internal/testutils/fdtrace github.com/cilium/ebpf/internal/tracefs github.com/cilium/ebpf/internal/unix github.com/cilium/ebpf/link -# github.com/cilium/hive v0.0.0-20250217113459-914947d44393 +# github.com/cilium/hive v0.0.0-20250311080423-b13b66490d76 ## explicit; go 1.21.3 github.com/cilium/hive github.com/cilium/hive/cell +github.com/cilium/hive/hivetest github.com/cilium/hive/internal github.com/cilium/hive/job github.com/cilium/hive/script github.com/cilium/hive/script/internal/diff -# github.com/cilium/proxy v0.0.0-20250214115704-3e4b99dc5d1f -## explicit; go 1.23 +# github.com/cilium/proxy v0.0.0-20250318065604-173988fc0adb +## explicit; go 1.23.0 github.com/cilium/proxy/go/cilium/api github.com/cilium/proxy/go/envoy/admin/v3 github.com/cilium/proxy/go/envoy/annotations @@ -562,7 +565,7 @@ github.com/cilium/proxy/go/envoy/type/tracing/v3 github.com/cilium/proxy/go/envoy/type/v3 github.com/cilium/proxy/go/envoy/watchdog/v3 github.com/cilium/proxy/pkg/policy/api/kafka -# github.com/cilium/statedb v0.3.6 +# github.com/cilium/statedb v0.3.7 ## explicit; go 1.23 github.com/cilium/statedb github.com/cilium/statedb/index @@ -572,8 +575,8 @@ github.com/cilium/statedb/reconciler # github.com/cilium/stream v0.0.0-20241203114243-53c3e5d79744 ## explicit; go 1.21.0 github.com/cilium/stream -# github.com/cilium/workerpool v1.2.0 -## explicit; go 1.15 +# github.com/cilium/workerpool v1.3.0 +## explicit; go 1.22 github.com/cilium/workerpool # github.com/cloudflare/cfssl v1.6.5 ## explicit; go 1.18 @@ -604,7 +607,7 @@ github.com/cncf/xds/go/xds/annotations/v3 github.com/cncf/xds/go/xds/core/v3 github.com/cncf/xds/go/xds/type/matcher/v3 github.com/cncf/xds/go/xds/type/v3 -# github.com/containerd/containerd v1.7.24 +# github.com/containerd/containerd v1.7.27 ## explicit; go 1.21 github.com/containerd/containerd/archive/compression github.com/containerd/containerd/content @@ -665,14 +668,14 @@ github.com/docker/distribution/registry/client/auth/challenge github.com/docker/distribution/registry/client/transport github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache/memory -# github.com/docker/docker v27.5.1+incompatible +# github.com/docker/docker v28.0.1+incompatible ## explicit github.com/docker/docker/api/types/filters github.com/docker/docker/api/types/registry github.com/docker/docker/api/types/versions github.com/docker/docker/errdefs +github.com/docker/docker/internal/lazyregexp github.com/docker/docker/pkg/homedir -github.com/docker/docker/pkg/ioutils github.com/docker/docker/registry # github.com/docker/docker-credential-helpers v0.7.0 ## explicit; go 1.18 @@ -732,7 +735,7 @@ github.com/go-openapi/analysis/internal/flatten/operations github.com/go-openapi/analysis/internal/flatten/replace github.com/go-openapi/analysis/internal/flatten/schutils github.com/go-openapi/analysis/internal/flatten/sortref -# github.com/go-openapi/errors v0.22.0 +# github.com/go-openapi/errors v0.22.1 ## explicit; go 1.20 github.com/go-openapi/errors # github.com/go-openapi/jsonpointer v0.21.0 @@ -762,12 +765,16 @@ github.com/go-openapi/spec # github.com/go-openapi/strfmt v0.23.0 ## explicit; go 1.20 github.com/go-openapi/strfmt -# github.com/go-openapi/swag v0.23.0 +# github.com/go-openapi/swag v0.23.1 ## explicit; go 1.20 github.com/go-openapi/swag # github.com/go-openapi/validate v0.24.0 ## explicit; go 1.20 github.com/go-openapi/validate +# github.com/go-viper/mapstructure/v2 v2.2.1 +## explicit; go 1.18 +github.com/go-viper/mapstructure/v2 +github.com/go-viper/mapstructure/v2/internal/errors # github.com/gobwas/glob v0.2.3 ## explicit github.com/gobwas/glob @@ -814,17 +821,17 @@ github.com/google/gnostic-models/extensions github.com/google/gnostic-models/jsonschema github.com/google/gnostic-models/openapiv2 github.com/google/gnostic-models/openapiv3 -# github.com/google/go-cmp v0.6.0 -## explicit; go 1.13 +# github.com/google/go-cmp v0.7.0 +## explicit; go 1.21 github.com/google/go-cmp/cmp github.com/google/go-cmp/cmp/cmpopts github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/go-github/v68 v68.0.0 -## explicit; go 1.21 -github.com/google/go-github/v68/github +# github.com/google/go-github/v70 v70.0.0 +## explicit; go 1.23.0 +github.com/google/go-github/v70/github # github.com/google/go-querystring v1.1.0 ## explicit; go 1.10 github.com/google/go-querystring/query @@ -868,18 +875,6 @@ github.com/hashicorp/go-hclog # github.com/hashicorp/go-multierror v1.1.1 ## explicit; go 1.13 github.com/hashicorp/go-multierror -# github.com/hashicorp/hcl v1.0.1-vault-5 -## explicit; go 1.15 -github.com/hashicorp/hcl -github.com/hashicorp/hcl/hcl/ast -github.com/hashicorp/hcl/hcl/parser -github.com/hashicorp/hcl/hcl/printer -github.com/hashicorp/hcl/hcl/scanner -github.com/hashicorp/hcl/hcl/strconv -github.com/hashicorp/hcl/hcl/token -github.com/hashicorp/hcl/json/parser -github.com/hashicorp/hcl/json/scanner -github.com/hashicorp/hcl/json/token # github.com/hmarr/codeowners v1.2.1 ## explicit; go 1.18 github.com/hmarr/codeowners @@ -900,8 +895,8 @@ github.com/josharian/intern # github.com/json-iterator/go v1.1.12 ## explicit; go 1.12 github.com/json-iterator/go -# github.com/klauspost/compress v1.17.9 -## explicit; go 1.20 +# github.com/klauspost/compress v1.17.11 +## explicit; go 1.21 github.com/klauspost/compress github.com/klauspost/compress/fse github.com/klauspost/compress/huff0 @@ -926,11 +921,8 @@ github.com/liggitt/tabwriter # github.com/mackerelio/go-osstat v0.2.5 ## explicit; go 1.18 github.com/mackerelio/go-osstat/memory -# github.com/magiconair/properties v1.8.7 -## explicit; go 1.19 -github.com/magiconair/properties -# github.com/mailru/easyjson v0.7.7 -## explicit; go 1.12 +# github.com/mailru/easyjson v0.9.0 +## explicit; go 1.20 github.com/mailru/easyjson/buffer github.com/mailru/easyjson/jlexer github.com/mailru/easyjson/jwriter @@ -996,14 +988,14 @@ github.com/opencontainers/image-spec/specs-go/v1 github.com/opentracing/opentracing-go github.com/opentracing/opentracing-go/ext github.com/opentracing/opentracing-go/log -# github.com/osrg/gobgp/v3 v3.34.0 +# github.com/osrg/gobgp/v3 v3.35.0 ## explicit; go 1.22.7 github.com/osrg/gobgp/v3/pkg/packet/bgp # github.com/pelletier/go-toml v1.9.5 ## explicit; go 1.12 github.com/pelletier/go-toml -# github.com/pelletier/go-toml/v2 v2.2.2 -## explicit; go 1.16 +# github.com/pelletier/go-toml/v2 v2.2.3 +## explicit; go 1.21.0 github.com/pelletier/go-toml/v2 github.com/pelletier/go-toml/v2/internal/characters github.com/pelletier/go-toml/v2/internal/danger @@ -1021,8 +1013,8 @@ github.com/pkg/browser # github.com/pkg/errors v0.9.1 ## explicit github.com/pkg/errors -# github.com/prometheus/client_golang v1.20.5 -## explicit; go 1.20 +# github.com/prometheus/client_golang v1.21.1 +## explicit; go 1.21 github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header github.com/prometheus/client_golang/prometheus @@ -1032,12 +1024,12 @@ github.com/prometheus/client_golang/prometheus/promhttp # github.com/prometheus/client_model v0.6.1 ## explicit; go 1.19 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.62.0 +# github.com/prometheus/common v0.63.0 ## explicit; go 1.21 github.com/prometheus/common/expfmt github.com/prometheus/common/model -# github.com/prometheus/procfs v0.15.1 -## explicit; go 1.20 +# github.com/prometheus/procfs v0.16.0 +## explicit; go 1.21 github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util @@ -1051,12 +1043,9 @@ github.com/rubenv/sql-migrate/sqlparse # github.com/russross/blackfriday/v2 v2.1.0 ## explicit github.com/russross/blackfriday/v2 -# github.com/sagikazarmark/locafero v0.4.0 -## explicit; go 1.20 +# github.com/sagikazarmark/locafero v0.7.0 +## explicit; go 1.21 github.com/sagikazarmark/locafero -# github.com/sagikazarmark/slog-shim v0.1.0 -## explicit; go 1.20 -github.com/sagikazarmark/slog-shim # github.com/sasha-s/go-deadlock v0.3.5 ## explicit github.com/sasha-s/go-deadlock @@ -1073,28 +1062,24 @@ github.com/sourcegraph/conc github.com/sourcegraph/conc/internal/multierror github.com/sourcegraph/conc/iter github.com/sourcegraph/conc/panics -# github.com/spf13/afero v1.12.0 -## explicit; go 1.21 +# github.com/spf13/afero v1.14.0 +## explicit; go 1.23.0 github.com/spf13/afero github.com/spf13/afero/internal/common github.com/spf13/afero/mem # github.com/spf13/cast v1.7.1 ## explicit; go 1.19 github.com/spf13/cast -# github.com/spf13/cobra v1.8.1 +# github.com/spf13/cobra v1.9.1 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/pflag v1.0.6 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/spf13/viper v1.19.0 -## explicit; go 1.20 +# github.com/spf13/viper v1.20.0 +## explicit; go 1.21.0 github.com/spf13/viper -github.com/spf13/viper/internal/encoding github.com/spf13/viper/internal/encoding/dotenv -github.com/spf13/viper/internal/encoding/hcl -github.com/spf13/viper/internal/encoding/ini -github.com/spf13/viper/internal/encoding/javaproperties github.com/spf13/viper/internal/encoding/json github.com/spf13/viper/internal/encoding/toml github.com/spf13/viper/internal/encoding/yaml @@ -1151,22 +1136,22 @@ github.com/zmap/zlint/v3/lints/etsi github.com/zmap/zlint/v3/lints/mozilla github.com/zmap/zlint/v3/lints/rfc github.com/zmap/zlint/v3/util -# go.etcd.io/etcd/api/v3 v3.5.18 -## explicit; go 1.22 +# go.etcd.io/etcd/api/v3 v3.5.19 +## explicit; go 1.23.0 go.etcd.io/etcd/api/v3/authpb go.etcd.io/etcd/api/v3/etcdserverpb go.etcd.io/etcd/api/v3/membershippb go.etcd.io/etcd/api/v3/mvccpb go.etcd.io/etcd/api/v3/v3rpc/rpctypes go.etcd.io/etcd/api/v3/version -# go.etcd.io/etcd/client/pkg/v3 v3.5.18 -## explicit; go 1.22 +# go.etcd.io/etcd/client/pkg/v3 v3.5.19 +## explicit; go 1.23.0 go.etcd.io/etcd/client/pkg/v3/logutil go.etcd.io/etcd/client/pkg/v3/systemd go.etcd.io/etcd/client/pkg/v3/tlsutil go.etcd.io/etcd/client/pkg/v3/types -# go.etcd.io/etcd/client/v3 v3.5.18 -## explicit; go 1.22 +# go.etcd.io/etcd/client/v3 v3.5.19 +## explicit; go 1.23.0 go.etcd.io/etcd/client/v3 go.etcd.io/etcd/client/v3/concurrency go.etcd.io/etcd/client/v3/credentials @@ -1192,7 +1177,7 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil -# go.opentelemetry.io/otel v1.34.0 +# go.opentelemetry.io/otel v1.35.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel go.opentelemetry.io/otel/attribute @@ -1209,15 +1194,16 @@ go.opentelemetry.io/otel/semconv/v1.17.0/httpconv go.opentelemetry.io/otel/semconv/v1.20.0 go.opentelemetry.io/otel/semconv/v1.21.0 go.opentelemetry.io/otel/semconv/v1.26.0 -# go.opentelemetry.io/otel/metric v1.34.0 +# go.opentelemetry.io/otel/metric v1.35.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric/embedded go.opentelemetry.io/otel/metric/noop -# go.opentelemetry.io/otel/trace v1.34.0 +# go.opentelemetry.io/otel/trace v1.35.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded +go.opentelemetry.io/otel/trace/internal/telemetry go.opentelemetry.io/otel/trace/noop # go.opentelemetry.io/proto/otlp v1.5.0 ## explicit; go 1.22.0 @@ -1247,8 +1233,8 @@ go.uber.org/zap/zapgrpc # go4.org/netipx v0.0.0-20231129151722-fdeea329fbba ## explicit; go 1.18 go4.org/netipx -# golang.org/x/crypto v0.33.0 -## explicit; go 1.20 +# golang.org/x/crypto v0.36.0 +## explicit; go 1.23.0 golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/cast5 @@ -1267,15 +1253,8 @@ golang.org/x/crypto/pbkdf2 golang.org/x/crypto/pkcs12 golang.org/x/crypto/pkcs12/internal/rc2 golang.org/x/crypto/scrypt -# golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa -## explicit; go 1.20 -golang.org/x/exp/constraints -golang.org/x/exp/slices -golang.org/x/exp/slog -golang.org/x/exp/slog/internal -golang.org/x/exp/slog/internal/buffer -# golang.org/x/net v0.35.0 -## explicit; go 1.18 +# golang.org/x/net v0.37.0 +## explicit; go 1.23.0 golang.org/x/net/context/ctxhttp golang.org/x/net/html golang.org/x/net/html/atom @@ -1289,26 +1268,26 @@ golang.org/x/net/internal/timeseries golang.org/x/net/proxy golang.org/x/net/trace golang.org/x/net/websocket -# golang.org/x/oauth2 v0.26.0 -## explicit; go 1.18 +# golang.org/x/oauth2 v0.28.0 +## explicit; go 1.23.0 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sync v0.11.0 -## explicit; go 1.18 +# golang.org/x/sync v0.12.0 +## explicit; go 1.23.0 golang.org/x/sync/errgroup golang.org/x/sync/semaphore golang.org/x/sync/singleflight -# golang.org/x/sys v0.30.0 -## explicit; go 1.18 +# golang.org/x/sys v0.31.0 +## explicit; go 1.23.0 golang.org/x/sys/execabs golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.29.0 -## explicit; go 1.18 +# golang.org/x/term v0.30.0 +## explicit; go 1.23.0 golang.org/x/term -# golang.org/x/text v0.22.0 -## explicit; go 1.18 +# golang.org/x/text v0.23.0 +## explicit; go 1.23.0 golang.org/x/text/encoding golang.org/x/text/encoding/internal golang.org/x/text/encoding/internal/identifier @@ -1319,27 +1298,28 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# golang.org/x/time v0.10.0 -## explicit; go 1.18 +# golang.org/x/time v0.11.0 +## explicit; go 1.23.0 golang.org/x/time/rate -# golang.org/x/tools v0.30.0 -## explicit; go 1.22.0 +# golang.org/x/tools v0.31.0 +## explicit; go 1.23.0 golang.org/x/tools/txtar -# google.golang.org/genproto/googleapis/api v0.0.0-20250207221924-e9438ea467c6 -## explicit; go 1.22 +# google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 +## explicit; go 1.23.0 google.golang.org/genproto/googleapis/api google.golang.org/genproto/googleapis/api/annotations google.golang.org/genproto/googleapis/api/expr/v1alpha1 -# google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 -## explicit; go 1.22 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 +## explicit; go 1.23.0 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.70.0 -## explicit; go 1.22 +# google.golang.org/grpc v1.71.0 +## explicit; go 1.22.0 google.golang.org/grpc google.golang.org/grpc/attributes google.golang.org/grpc/backoff google.golang.org/grpc/balancer google.golang.org/grpc/balancer/base +google.golang.org/grpc/balancer/endpointsharding google.golang.org/grpc/balancer/grpclb/state google.golang.org/grpc/balancer/pickfirst google.golang.org/grpc/balancer/pickfirst/internal @@ -1371,7 +1351,9 @@ google.golang.org/grpc/internal/grpcutil google.golang.org/grpc/internal/idle google.golang.org/grpc/internal/metadata google.golang.org/grpc/internal/pretty +google.golang.org/grpc/internal/proxyattributes google.golang.org/grpc/internal/resolver +google.golang.org/grpc/internal/resolver/delegatingresolver google.golang.org/grpc/internal/resolver/dns google.golang.org/grpc/internal/resolver/dns/internal google.golang.org/grpc/internal/resolver/passthrough @@ -1443,13 +1425,10 @@ gopkg.in/evanphx/json-patch.v4 # gopkg.in/inf.v0 v0.9.1 ## explicit gopkg.in/inf.v0 -# gopkg.in/ini.v1 v1.67.0 -## explicit -gopkg.in/ini.v1 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# helm.sh/helm/v3 v3.17.0 +# helm.sh/helm/v3 v3.17.2 ## explicit; go 1.23.0 helm.sh/helm/v3/internal/fileutil helm.sh/helm/v3/internal/resolver @@ -1491,7 +1470,7 @@ helm.sh/helm/v3/pkg/strvals helm.sh/helm/v3/pkg/time helm.sh/helm/v3/pkg/time/ctime helm.sh/helm/v3/pkg/uploader -# k8s.io/api v0.32.2 +# k8s.io/api v0.32.3 ## explicit; go 1.23.0 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 @@ -1552,7 +1531,7 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 k8s.io/api/storagemigration/v1alpha1 -# k8s.io/apiextensions-apiserver v0.32.2 +# k8s.io/apiextensions-apiserver v0.32.3 ## explicit; go 1.23.0 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 @@ -1568,7 +1547,7 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextension k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1/fake k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1 k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake -# k8s.io/apimachinery v0.32.2 +# k8s.io/apimachinery v0.32.3 ## explicit; go 1.23.0 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -1633,16 +1612,16 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/apiserver v0.32.2 +# k8s.io/apiserver v0.32.3 ## explicit; go 1.23.0 k8s.io/apiserver/pkg/endpoints/deprecation -# k8s.io/cli-runtime v0.32.2 +# k8s.io/cli-runtime v0.32.3 ## explicit; go 1.23.0 k8s.io/cli-runtime/pkg/genericclioptions k8s.io/cli-runtime/pkg/genericiooptions k8s.io/cli-runtime/pkg/printers k8s.io/cli-runtime/pkg/resource -# k8s.io/client-go v0.32.2 +# k8s.io/client-go v0.32.3 ## explicit; go 1.23.0 k8s.io/client-go/applyconfigurations k8s.io/client-go/applyconfigurations/admissionregistration/v1 @@ -1870,7 +1849,7 @@ k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/watchlist k8s.io/client-go/util/workqueue -# k8s.io/component-base v0.32.2 +# k8s.io/component-base v0.32.3 ## explicit; go 1.23.0 k8s.io/component-base/version # k8s.io/klog/v2 v2.130.1 @@ -1894,7 +1873,7 @@ k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/util/proto/validation k8s.io/kube-openapi/pkg/validation/spec -# k8s.io/kubectl v0.32.2 +# k8s.io/kubectl v0.32.3 ## explicit; go 1.23.0 k8s.io/kubectl/pkg/cmd/util k8s.io/kubectl/pkg/scheme @@ -1931,7 +1910,7 @@ oras.land/oras-go/pkg/registry/remote/auth oras.land/oras-go/pkg/registry/remote/internal/errutil oras.land/oras-go/pkg/registry/remote/internal/syncutil oras.land/oras-go/pkg/target -# sigs.k8s.io/controller-runtime v0.20.1 +# sigs.k8s.io/controller-runtime v0.20.3 ## explicit; go 1.23.0 sigs.k8s.io/controller-runtime/pkg/client/apiutil # sigs.k8s.io/gateway-api v1.2.1 @@ -2021,7 +2000,7 @@ sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/validation/field sigs.k8s.io/kustomize/kyaml/yaml/merge2 sigs.k8s.io/kustomize/kyaml/yaml/schema sigs.k8s.io/kustomize/kyaml/yaml/walk -# sigs.k8s.io/mcs-api v0.1.1-0.20250129110323-a7986579439f +# sigs.k8s.io/mcs-api v0.1.1-0.20250224121229-6c631f4730d0 ## explicit; go 1.23.0 sigs.k8s.io/mcs-api/pkg/apis/v1alpha1 sigs.k8s.io/mcs-api/pkg/client/clientset/versioned @@ -2029,7 +2008,7 @@ sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/fake sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/scheme sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/typed/apis/v1alpha1 sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/typed/apis/v1alpha1/fake -# sigs.k8s.io/structured-merge-diff/v4 v4.4.2 +# sigs.k8s.io/structured-merge-diff/v4 v4.5.0 ## explicit; go 1.13 sigs.k8s.io/structured-merge-diff/v4/fieldpath sigs.k8s.io/structured-merge-diff/v4/merge diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v4/merge/update.go b/vendor/sigs.k8s.io/structured-merge-diff/v4/merge/update.go index 34ab2d6fb4..455818ff85 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/v4/merge/update.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/v4/merge/update.go @@ -33,6 +33,9 @@ type UpdaterBuilder struct { Converter Converter IgnoreFilter map[fieldpath.APIVersion]fieldpath.Filter + // IgnoredFields provides a set of fields to ignore for each + IgnoredFields map[fieldpath.APIVersion]*fieldpath.Set + // Stop comparing the new object with old object after applying. // This was initially used to avoid spurious etcd update, but // since that's vastly inefficient, we've come-up with a better @@ -46,6 +49,7 @@ func (u *UpdaterBuilder) BuildUpdater() *Updater { return &Updater{ Converter: u.Converter, IgnoreFilter: u.IgnoreFilter, + IgnoredFields: u.IgnoredFields, returnInputOnNoop: u.ReturnInputOnNoop, } } @@ -56,6 +60,9 @@ type Updater struct { // Deprecated: This will eventually become private. Converter Converter + // Deprecated: This will eventually become private. + IgnoredFields map[fieldpath.APIVersion]*fieldpath.Set + // Deprecated: This will eventually become private. IgnoreFilter map[fieldpath.APIVersion]fieldpath.Filter @@ -70,8 +77,19 @@ func (s *Updater) update(oldObject, newObject *typed.TypedValue, version fieldpa return nil, nil, fmt.Errorf("failed to compare objects: %v", err) } - versions := map[fieldpath.APIVersion]*typed.Comparison{ - version: compare.FilterFields(s.IgnoreFilter[version]), + var versions map[fieldpath.APIVersion]*typed.Comparison + + if s.IgnoredFields != nil && s.IgnoreFilter != nil { + return nil, nil, fmt.Errorf("IgnoreFilter and IgnoreFilter may not both be set") + } + if s.IgnoredFields != nil { + versions = map[fieldpath.APIVersion]*typed.Comparison{ + version: compare.ExcludeFields(s.IgnoredFields[version]), + } + } else { + versions = map[fieldpath.APIVersion]*typed.Comparison{ + version: compare.FilterFields(s.IgnoreFilter[version]), + } } for manager, managerSet := range managers { @@ -101,7 +119,12 @@ func (s *Updater) update(oldObject, newObject *typed.TypedValue, version fieldpa if err != nil { return nil, nil, fmt.Errorf("failed to compare objects: %v", err) } - versions[managerSet.APIVersion()] = compare.FilterFields(s.IgnoreFilter[managerSet.APIVersion()]) + + if s.IgnoredFields != nil { + versions[managerSet.APIVersion()] = compare.ExcludeFields(s.IgnoredFields[managerSet.APIVersion()]) + } else { + versions[managerSet.APIVersion()] = compare.FilterFields(s.IgnoreFilter[managerSet.APIVersion()]) + } } conflictSet := managerSet.Set().Intersection(compare.Modified.Union(compare.Added)) @@ -154,7 +177,16 @@ func (s *Updater) Update(liveObject, newObject *typed.TypedValue, version fieldp managers[manager] = fieldpath.NewVersionedSet(fieldpath.NewSet(), version, false) } set := managers[manager].Set().Difference(compare.Removed).Union(compare.Modified).Union(compare.Added) - ignoreFilter := s.IgnoreFilter[version] + + if s.IgnoredFields != nil && s.IgnoreFilter != nil { + return nil, nil, fmt.Errorf("IgnoreFilter and IgnoreFilter may not both be set") + } + var ignoreFilter fieldpath.Filter + if s.IgnoredFields != nil { + ignoreFilter = fieldpath.NewExcludeSetFilter(s.IgnoredFields[version]) + } else { + ignoreFilter = s.IgnoreFilter[version] + } if ignoreFilter != nil { set = ignoreFilter.Filter(set) } @@ -189,7 +221,15 @@ func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fiel return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to get field set: %v", err) } - ignoreFilter := s.IgnoreFilter[version] + if s.IgnoredFields != nil && s.IgnoreFilter != nil { + return nil, nil, fmt.Errorf("IgnoreFilter and IgnoreFilter may not both be set") + } + var ignoreFilter fieldpath.Filter + if s.IgnoredFields != nil { + ignoreFilter = fieldpath.NewExcludeSetFilter(s.IgnoredFields[version]) + } else { + ignoreFilter = s.IgnoreFilter[version] + } if ignoreFilter != nil { set = ignoreFilter.Filter(set) } diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v4/typed/typed.go b/vendor/sigs.k8s.io/structured-merge-diff/v4/typed/typed.go index 9be9028280..7edaa6d489 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/v4/typed/typed.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/v4/typed/typed.go @@ -32,6 +32,21 @@ const ( AllowDuplicates ValidationOptions = iota ) +// extractItemsOptions is the options available when extracting items. +type extractItemsOptions struct { + appendKeyFields bool +} + +type ExtractItemsOption func(*extractItemsOptions) + +// WithAppendKeyFields configures ExtractItems to include key fields. +// It is exported for use in configuring ExtractItems. +func WithAppendKeyFields() ExtractItemsOption { + return func(opts *extractItemsOptions) { + opts.appendKeyFields = true + } +} + // AsTyped accepts a value and a type and returns a TypedValue. 'v' must have // type 'typeName' in the schema. An error is returned if the v doesn't conform // to the schema. @@ -187,7 +202,37 @@ func (tv TypedValue) RemoveItems(items *fieldpath.Set) *TypedValue { } // ExtractItems returns a value with only the provided list or map items extracted from the value. -func (tv TypedValue) ExtractItems(items *fieldpath.Set) *TypedValue { +func (tv TypedValue) ExtractItems(items *fieldpath.Set, opts ...ExtractItemsOption) *TypedValue { + options := &extractItemsOptions{} + for _, opt := range opts { + opt(options) + } + if options.appendKeyFields { + tvPathSet, err := tv.ToFieldSet() + if err == nil { + keyFieldPathSet := fieldpath.NewSet() + items.Iterate(func(path fieldpath.Path) { + if !tvPathSet.Has(path) { + return + } + for i, pe := range path { + if pe.Key == nil { + continue + } + for _, keyField := range *pe.Key { + keyName := keyField.Name + // Create a new slice with the same elements as path[:i+1], but set its capacity to len(path[:i+1]). + // This ensures that appending to keyFieldPath creates a new underlying array, avoiding accidental + // modification of the original slice (path). + keyFieldPath := append(path[:i+1:i+1], fieldpath.PathElement{FieldName: &keyName}) + keyFieldPathSet.Insert(keyFieldPath) + } + } + }) + items = items.Union(keyFieldPathSet) + } + } + tv.value = removeItemsWithSchema(tv.value, items, tv.schema, tv.typeRef, true) return &tv } diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v4/value/scalar.go b/vendor/sigs.k8s.io/structured-merge-diff/v4/value/scalar.go index c78a4c18d1..5824219e51 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/v4/value/scalar.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/v4/value/scalar.go @@ -43,7 +43,7 @@ func IntCompare(lhs, rhs int64) int { func BoolCompare(lhs, rhs bool) int { if lhs == rhs { return 0 - } else if lhs == false { + } else if !lhs { return -1 } return 1