* Increase golangci-lint verbosity

* Revender hive to 9dd47f8bfa1f
This commit is contained in:
Steven Fairchild 2024-02-12 10:13:32 -05:00 коммит произвёл GitHub
Родитель 9eb8db1e4e
Коммит 6bd01cddf4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
83 изменённых файлов: 2471 добавлений и 838 удалений

Просмотреть файл

@ -12,6 +12,9 @@ run:
- "exclude_graphdriver_btrfs"
go: "1.18"
output:
format: github-actions
issues:
max-same-issues: 0
exclude-rules:

22
go.mod
Просмотреть файл

@ -28,7 +28,7 @@ require (
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/go-chi/chi/v5 v5.0.8
github.com/go-logr/logr v1.3.0
github.com/go-logr/logr v1.4.1
github.com/go-test/deep v1.1.0
github.com/gofrs/uuid v4.2.0+incompatible
github.com/golang-jwt/jwt/v4 v4.5.0
@ -59,7 +59,7 @@ require (
github.com/openshift/client-go v0.0.0-20220525160904-9e1acff93e4a
github.com/openshift/cloud-credential-operator v0.0.0-00010101000000-000000000000
github.com/openshift/console-operator v0.0.0-20220407014945-45d37e70e0c2
github.com/openshift/hive/apis v0.0.0-20231116161336-9dd47f8bfa1f
github.com/openshift/hive/apis v0.0.0-20240131003045-5fbe0d158ba9
github.com/openshift/library-go v0.0.0-20220525173854-9b950a41acdc
github.com/openshift/machine-config-operator v0.0.1-0.20230519222939-1abc13efbb0d
github.com/pires/go-proxyproto v0.6.2
@ -74,21 +74,21 @@ require (
github.com/tebeka/selenium v0.9.9
github.com/ugorji/go/codec v1.2.7
github.com/vincent-petithory/dataurl v1.0.0
golang.org/x/crypto v0.18.0
golang.org/x/net v0.20.0
golang.org/x/crypto v0.19.0
golang.org/x/net v0.21.0
golang.org/x/oauth2 v0.10.0
golang.org/x/sync v0.3.0
golang.org/x/text v0.14.0
golang.org/x/tools v0.10.0
k8s.io/api v0.28.3
k8s.io/api v0.29.1
k8s.io/apiextensions-apiserver v0.25.0
k8s.io/apimachinery v0.28.3
k8s.io/apimachinery v0.29.1
k8s.io/cli-runtime v0.25.16
k8s.io/client-go v0.25.16
k8s.io/code-generator v0.25.16
k8s.io/kubectl v0.24.17
k8s.io/kubernetes v1.24.17
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
k8s.io/utils v0.0.0-20240102154912-e7106e64919e
sigs.k8s.io/cluster-api-provider-azure v1.2.1
sigs.k8s.io/controller-runtime v0.13.1
sigs.k8s.io/controller-tools v0.9.0
@ -256,8 +256,8 @@ require (
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.starlark.net v0.0.0-20220328144851-d1966c6b9fcd // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
@ -273,14 +273,14 @@ require (
k8s.io/apiserver v0.25.16 // indirect
k8s.io/component-base v0.25.16 // indirect
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-aggregator v0.24.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kube-storage-version-migrator v0.0.4 // indirect
sigs.k8s.io/kustomize/api v0.12.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

31
go.sum
Просмотреть файл

@ -238,8 +238,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
@ -753,20 +753,20 @@ go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
@ -831,8 +831,8 @@ k8s.io/component-base v0.25.16 h1:ywaMQRJoCCQwWSM6z9jC+RJWBY/CcJDVgnyyIhuNAkQ=
k8s.io/component-base v0.25.16/go.mod h1:ZMFrcDjbpM12U5hvZ8bXgPf9U2Wrp0McSGMhoUkA9Mo=
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 h1:TT1WdmqqXareKxZ/oNXEUSwKlLiHzPMyB0t8BaFeBYI=
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-aggregator v0.25.16 h1:yvWWF2bHyuNQ/dMwgWcbh3MkYl1hwl2A7dMwvMMwMIg=
k8s.io/kube-aggregator v0.25.16/go.mod h1:fmC08uLMNFUQj1pvtCYL0cTjhq+KDC9o31p51aH9dLE=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
@ -841,8 +841,8 @@ k8s.io/kubectl v0.25.16 h1:6TK2I58rj3Og6CZlkc6j2ARICag25ko9ALsr5w/Oe6A=
k8s.io/kubectl v0.25.16/go.mod h1:mmyKlLfVqm6s6zcKNwK8f36Vf5MAmrmudRko9/wibNA=
k8s.io/kubernetes v1.25.16 h1:pdtEdre7aInDvXas+mWzpTiK/7cpcaGRyYB+Bedr2+Q=
k8s.io/kubernetes v1.25.16/go.mod h1:ZrRRMmY0nDNxlnPnJopZRhF2i0tzfB3+DnitJcDe8Vw=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.37/go.mod h1:vfnxT4FXNT8eGvO+xi/DsyC/qHmdujqwrUa1WSspCsk=
sigs.k8s.io/controller-runtime v0.11.2 h1:H5GTxQl0Mc9UjRJhORusqfJCIjBO8UtUxGggCwL1rLA=
sigs.k8s.io/controller-runtime v0.11.2/go.mod h1:P6QCzrEjLaZGqHsfd+os7JQ+WFZhvB8MRFsn4dWF7O4=
@ -856,7 +856,8 @@ sigs.k8s.io/kustomize/api v0.11.2 h1:6YvCJHFDwsLwAX7zNHBxMZi3k7dGIXI8G9l0saYQI0E
sigs.k8s.io/kustomize/api v0.11.2/go.mod h1:GZuhith5YcqxIDe0GnRJNx5xxPTjlwaLTt/e+ChUtJA=
sigs.k8s.io/kustomize/kyaml v0.13.3 h1:tNNQIC+8cc+aXFTVg+RtQAOsjwUdYBZRAgYOVI3RBc4=
sigs.k8s.io/kustomize/kyaml v0.13.3/go.mod h1:/ya3Gk4diiQzlE4mBh7wykyLRFZNvqlbh+JnwQ9Vhrc=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

Просмотреть файл

@ -14,5 +14,5 @@ then
echo "ERROR: golangci-lint could not be found, Go linting aborted. To install it visit https://golangci-lint.run/usage/install/#local-installation"
exit 1
else
golangci-lint run
golangci-lint run --verbose
fi

67
vendor/github.com/go-logr/logr/README.md сгенерированный поставляемый
Просмотреть файл

@ -91,11 +91,12 @@ logr design but also left out some parts and changed others:
| Adding a name to a logger | `WithName` | no API |
| Modify verbosity of log entries in a call chain | `V` | no API |
| Grouping of key/value pairs | not supported | `WithGroup`, `GroupValue` |
| Pass context for extracting additional values | no API | API variants like `InfoCtx` |
The high-level slog API is explicitly meant to be one of many different APIs
that can be layered on top of a shared `slog.Handler`. logr is one such
alternative API, with [interoperability](#slog-interoperability) provided by the [`slogr`](slogr)
package.
alternative API, with [interoperability](#slog-interoperability) provided by
some conversion functions.
### Inspiration
@ -145,24 +146,24 @@ There are implementations for the following logging libraries:
## slog interoperability
Interoperability goes both ways, using the `logr.Logger` API with a `slog.Handler`
and using the `slog.Logger` API with a `logr.LogSink`. [slogr](./slogr) provides `NewLogr` and
`NewSlogHandler` API calls to convert between a `logr.Logger` and a `slog.Handler`.
and using the `slog.Logger` API with a `logr.LogSink`. `FromSlogHandler` and
`ToSlogHandler` convert between a `logr.Logger` and a `slog.Handler`.
As usual, `slog.New` can be used to wrap such a `slog.Handler` in the high-level
slog API. `slogr` itself leaves that to the caller.
slog API.
## Using a `logr.Sink` as backend for slog
### Using a `logr.LogSink` as backend for slog
Ideally, a logr sink implementation should support both logr and slog by
implementing both the normal logr interface(s) and `slogr.SlogSink`. Because
implementing both the normal logr interface(s) and `SlogSink`. Because
of a conflict in the parameters of the common `Enabled` method, it is [not
possible to implement both slog.Handler and logr.Sink in the same
type](https://github.com/golang/go/issues/59110).
If both are supported, log calls can go from the high-level APIs to the backend
without the need to convert parameters. `NewLogr` and `NewSlogHandler` can
without the need to convert parameters. `FromSlogHandler` and `ToSlogHandler` can
convert back and forth without adding additional wrappers, with one exception:
when `Logger.V` was used to adjust the verbosity for a `slog.Handler`, then
`NewSlogHandler` has to use a wrapper which adjusts the verbosity for future
`ToSlogHandler` has to use a wrapper which adjusts the verbosity for future
log calls.
Such an implementation should also support values that implement specific
@ -187,13 +188,13 @@ Not supporting slog has several drawbacks:
These drawbacks are severe enough that applications using a mixture of slog and
logr should switch to a different backend.
## Using a `slog.Handler` as backend for logr
### Using a `slog.Handler` as backend for logr
Using a plain `slog.Handler` without support for logr works better than the
other direction:
- All logr verbosity levels can be mapped 1:1 to their corresponding slog level
by negating them.
- Stack unwinding is done by the `slogr.SlogSink` and the resulting program
- Stack unwinding is done by the `SlogSink` and the resulting program
counter is passed to the `slog.Handler`.
- Names added via `Logger.WithName` are gathered and recorded in an additional
attribute with `logger` as key and the names separated by slash as value.
@ -205,27 +206,39 @@ ideally support both `logr.Marshaler` and `slog.Valuer`. If compatibility
with logr implementations without slog support is not important, then
`slog.Valuer` is sufficient.
## Context support for slog
### Context support for slog
Storing a logger in a `context.Context` is not supported by
slog. `logr.NewContext` and `logr.FromContext` can be used with slog like this
to fill this gap:
slog. `NewContextWithSlogLogger` and `FromContextAsSlogLogger` can be
used to fill this gap. They store and retrieve a `slog.Logger` pointer
under the same context key that is also used by `NewContext` and
`FromContext` for `logr.Logger` value.
func HandlerFromContext(ctx context.Context) slog.Handler {
logger, err := logr.FromContext(ctx)
if err == nil {
return slogr.NewSlogHandler(logger)
}
return slog.Default().Handler()
}
When `NewContextWithSlogLogger` is followed by `FromContext`, the latter will
automatically convert the `slog.Logger` to a
`logr.Logger`. `FromContextAsSlogLogger` does the same for the other direction.
func ContextWithHandler(ctx context.Context, handler slog.Handler) context.Context {
return logr.NewContext(ctx, slogr.NewLogr(handler))
}
With this approach, binaries which use either slog or logr are as efficient as
possible with no unnecessary allocations. This is also why the API stores a
`slog.Logger` pointer: when storing a `slog.Handler`, creating a `slog.Logger`
on retrieval would need to allocate one.
The downside is that storing and retrieving a `slog.Handler` needs more
allocations compared to using a `logr.Logger`. Therefore the recommendation is
to use the `logr.Logger` API in code which uses contextual logging.
The downside is that switching back and forth needs more allocations. Because
logr is the API that is already in use by different packages, in particular
Kubernetes, the recommendation is to use the `logr.Logger` API in code which
uses contextual logging.
An alternative to adding values to a logger and storing that logger in the
context is to store the values in the context and to configure a logging
backend to extract those values when emitting log entries. This only works when
log calls are passed the context, which is not supported by the logr API.
With the slog API, it is possible, but not
required. https://github.com/veqryn/slog-context is a package for slog which
provides additional support code for this approach. It also contains wrappers
for the context functions in logr, so developers who prefer to not use the logr
APIs directly can use those instead and the resulting code will still be
interoperable with logr.
## FAQ

33
vendor/github.com/go-logr/logr/context.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,33 @@
/*
Copyright 2023 The logr 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 logr
// contextKey is how we find Loggers in a context.Context. With Go < 1.21,
// the value is always a Logger value. With Go >= 1.21, the value can be a
// Logger value or a slog.Logger pointer.
type contextKey struct{}
// notFoundError exists to carry an IsNotFound method.
type notFoundError struct{}
func (notFoundError) Error() string {
return "no logr.Logger was present"
}
func (notFoundError) IsNotFound() bool {
return true
}

49
vendor/github.com/go-logr/logr/context_noslog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,49 @@
//go:build !go1.21
// +build !go1.21
/*
Copyright 2019 The logr 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 logr
import (
"context"
)
// FromContext returns a Logger from ctx or an error if no Logger is found.
func FromContext(ctx context.Context) (Logger, error) {
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
return v, nil
}
return Logger{}, notFoundError{}
}
// FromContextOrDiscard returns a Logger from ctx. If no Logger is found, this
// returns a Logger that discards all log messages.
func FromContextOrDiscard(ctx context.Context) Logger {
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
return v
}
return Discard()
}
// NewContext returns a new Context, derived from ctx, which carries the
// provided Logger.
func NewContext(ctx context.Context, logger Logger) context.Context {
return context.WithValue(ctx, contextKey{}, logger)
}

83
vendor/github.com/go-logr/logr/context_slog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,83 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2019 The logr 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 logr
import (
"context"
"fmt"
"log/slog"
)
// FromContext returns a Logger from ctx or an error if no Logger is found.
func FromContext(ctx context.Context) (Logger, error) {
v := ctx.Value(contextKey{})
if v == nil {
return Logger{}, notFoundError{}
}
switch v := v.(type) {
case Logger:
return v, nil
case *slog.Logger:
return FromSlogHandler(v.Handler()), nil
default:
// Not reached.
panic(fmt.Sprintf("unexpected value type for logr context key: %T", v))
}
}
// FromContextAsSlogLogger returns a slog.Logger from ctx or nil if no such Logger is found.
func FromContextAsSlogLogger(ctx context.Context) *slog.Logger {
v := ctx.Value(contextKey{})
if v == nil {
return nil
}
switch v := v.(type) {
case Logger:
return slog.New(ToSlogHandler(v))
case *slog.Logger:
return v
default:
// Not reached.
panic(fmt.Sprintf("unexpected value type for logr context key: %T", v))
}
}
// FromContextOrDiscard returns a Logger from ctx. If no Logger is found, this
// returns a Logger that discards all log messages.
func FromContextOrDiscard(ctx context.Context) Logger {
if logger, err := FromContext(ctx); err == nil {
return logger
}
return Discard()
}
// NewContext returns a new Context, derived from ctx, which carries the
// provided Logger.
func NewContext(ctx context.Context, logger Logger) context.Context {
return context.WithValue(ctx, contextKey{}, logger)
}
// NewContextWithSlogLogger returns a new Context, derived from ctx, which carries the
// provided slog.Logger.
func NewContextWithSlogLogger(ctx context.Context, logger *slog.Logger) context.Context {
return context.WithValue(ctx, contextKey{}, logger)
}

189
vendor/github.com/go-logr/logr/funcr/funcr.go сгенерированный поставляемый
Просмотреть файл

@ -100,6 +100,11 @@ type Options struct {
// details, see docs for Go's time.Layout.
TimestampFormat string
// LogInfoLevel tells funcr what key to use to log the info level.
// If not specified, the info level will be logged as "level".
// If this is set to "", the info level will not be logged at all.
LogInfoLevel *string
// Verbosity tells funcr which V logs to produce. Higher values enable
// more logs. Info logs at or below this level will be written, while logs
// above this level will be discarded.
@ -213,6 +218,10 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
if opts.MaxLogDepth == 0 {
opts.MaxLogDepth = defaultMaxLogDepth
}
if opts.LogInfoLevel == nil {
opts.LogInfoLevel = new(string)
*opts.LogInfoLevel = "level"
}
f := Formatter{
outputFormat: outfmt,
prefix: "",
@ -227,12 +236,15 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
// implementation. It should be constructed with NewFormatter. Some of
// its methods directly implement logr.LogSink.
type Formatter struct {
outputFormat outputFormat
prefix string
values []any
valuesStr string
depth int
opts *Options
outputFormat outputFormat
prefix string
values []any
valuesStr string
parentValuesStr string
depth int
opts *Options
group string // for slog groups
groupDepth int
}
// outputFormat indicates which outputFormat to use.
@ -253,33 +265,62 @@ func (f Formatter) render(builtins, args []any) string {
// Empirically bytes.Buffer is faster than strings.Builder for this.
buf := bytes.NewBuffer(make([]byte, 0, 1024))
if f.outputFormat == outputJSON {
buf.WriteByte('{')
buf.WriteByte('{') // for the whole line
}
vals := builtins
if hook := f.opts.RenderBuiltinsHook; hook != nil {
vals = hook(f.sanitize(vals))
}
f.flatten(buf, vals, false, false) // keys are ours, no need to escape
continuing := len(builtins) > 0
if len(f.valuesStr) > 0 {
if f.parentValuesStr != "" {
if continuing {
if f.outputFormat == outputJSON {
buf.WriteByte(',')
} else {
buf.WriteByte(' ')
}
buf.WriteByte(f.comma())
}
buf.WriteString(f.parentValuesStr)
continuing = true
buf.WriteString(f.valuesStr)
}
groupDepth := f.groupDepth
if f.group != "" {
if f.valuesStr != "" || len(args) != 0 {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys
buf.WriteByte(f.colon())
buf.WriteByte('{') // for the group
continuing = false
} else {
// The group was empty
groupDepth--
}
}
if f.valuesStr != "" {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.valuesStr)
continuing = true
}
vals = args
if hook := f.opts.RenderArgsHook; hook != nil {
vals = hook(f.sanitize(vals))
}
f.flatten(buf, vals, continuing, true) // escape user-provided keys
if f.outputFormat == outputJSON {
buf.WriteByte('}')
for i := 0; i < groupDepth; i++ {
buf.WriteByte('}') // for the groups
}
if f.outputFormat == outputJSON {
buf.WriteByte('}') // for the whole line
}
return buf.String()
}
@ -298,9 +339,16 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc
if len(kvList)%2 != 0 {
kvList = append(kvList, noValue)
}
copied := false
for i := 0; i < len(kvList); i += 2 {
k, ok := kvList[i].(string)
if !ok {
if !copied {
newList := make([]any, len(kvList))
copy(newList, kvList)
kvList = newList
copied = true
}
k = f.nonStringKey(kvList[i])
kvList[i] = k
}
@ -308,7 +356,7 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc
if i > 0 || continuing {
if f.outputFormat == outputJSON {
buf.WriteByte(',')
buf.WriteByte(f.comma())
} else {
// In theory the format could be something we don't understand. In
// practice, we control it, so it won't be.
@ -316,24 +364,35 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc
}
}
if escapeKeys {
buf.WriteString(prettyString(k))
} else {
// this is faster
buf.WriteByte('"')
buf.WriteString(k)
buf.WriteByte('"')
}
if f.outputFormat == outputJSON {
buf.WriteByte(':')
} else {
buf.WriteByte('=')
}
buf.WriteString(f.quoted(k, escapeKeys))
buf.WriteByte(f.colon())
buf.WriteString(f.pretty(v))
}
return kvList
}
func (f Formatter) quoted(str string, escape bool) string {
if escape {
return prettyString(str)
}
// this is faster
return `"` + str + `"`
}
func (f Formatter) comma() byte {
if f.outputFormat == outputJSON {
return ','
}
return ' '
}
func (f Formatter) colon() byte {
if f.outputFormat == outputJSON {
return ':'
}
return '='
}
func (f Formatter) pretty(value any) string {
return f.prettyWithFlags(value, 0, 0)
}
@ -407,12 +466,12 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
}
for i := 0; i < len(v); i += 2 {
if i > 0 {
buf.WriteByte(',')
buf.WriteByte(f.comma())
}
k, _ := v[i].(string) // sanitize() above means no need to check success
// arbitrary keys might need escaping
buf.WriteString(prettyString(k))
buf.WriteByte(':')
buf.WriteByte(f.colon())
buf.WriteString(f.prettyWithFlags(v[i+1], 0, depth+1))
}
if flags&flagRawStruct == 0 {
@ -481,7 +540,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
continue
}
if printComma {
buf.WriteByte(',')
buf.WriteByte(f.comma())
}
printComma = true // if we got here, we are rendering a field
if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" {
@ -492,10 +551,8 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
name = fld.Name
}
// field names can't contain characters which need escaping
buf.WriteByte('"')
buf.WriteString(name)
buf.WriteByte('"')
buf.WriteByte(':')
buf.WriteString(f.quoted(name, false))
buf.WriteByte(f.colon())
buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), 0, depth+1))
}
if flags&flagRawStruct == 0 {
@ -520,7 +577,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
buf.WriteByte('[')
for i := 0; i < v.Len(); i++ {
if i > 0 {
buf.WriteByte(',')
buf.WriteByte(f.comma())
}
e := v.Index(i)
buf.WriteString(f.prettyWithFlags(e.Interface(), 0, depth+1))
@ -534,7 +591,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
i := 0
for it.Next() {
if i > 0 {
buf.WriteByte(',')
buf.WriteByte(f.comma())
}
// If a map key supports TextMarshaler, use it.
keystr := ""
@ -556,7 +613,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
}
}
buf.WriteString(keystr)
buf.WriteByte(':')
buf.WriteByte(f.colon())
buf.WriteString(f.prettyWithFlags(it.Value().Interface(), 0, depth+1))
i++
}
@ -706,6 +763,53 @@ func (f Formatter) sanitize(kvList []any) []any {
return kvList
}
// startGroup opens a new group scope (basically a sub-struct), which locks all
// the current saved values and starts them anew. This is needed to satisfy
// slog.
func (f *Formatter) startGroup(group string) {
// Unnamed groups are just inlined.
if group == "" {
return
}
// Any saved values can no longer be changed.
buf := bytes.NewBuffer(make([]byte, 0, 1024))
continuing := false
if f.parentValuesStr != "" {
buf.WriteString(f.parentValuesStr)
continuing = true
}
if f.group != "" && f.valuesStr != "" {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys
buf.WriteByte(f.colon())
buf.WriteByte('{') // for the group
continuing = false
}
if f.valuesStr != "" {
if continuing {
buf.WriteByte(f.comma())
}
buf.WriteString(f.valuesStr)
}
// NOTE: We don't close the scope here - that's done later, when a log line
// is actually rendered (because we have N scopes to close).
f.parentValuesStr = buf.String()
// Start collecting new values.
f.group = group
f.groupDepth++
f.valuesStr = ""
f.values = nil
}
// Init configures this Formatter from runtime info, such as the call depth
// imposed by logr itself.
// Note that this receiver is a pointer, so depth can be saved.
@ -740,7 +844,10 @@ func (f Formatter) FormatInfo(level int, msg string, kvList []any) (prefix, args
if policy := f.opts.LogCaller; policy == All || policy == Info {
args = append(args, "caller", f.caller())
}
args = append(args, "level", level, "msg", msg)
if key := *f.opts.LogInfoLevel; key != "" {
args = append(args, key, level)
}
args = append(args, "msg", msg)
return prefix, f.render(args, kvList)
}

105
vendor/github.com/go-logr/logr/funcr/slogsink.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,105 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The logr 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 funcr
import (
"context"
"log/slog"
"github.com/go-logr/logr"
)
var _ logr.SlogSink = &fnlogger{}
const extraSlogSinkDepth = 3 // 2 for slog, 1 for SlogSink
func (l fnlogger) Handle(_ context.Context, record slog.Record) error {
kvList := make([]any, 0, 2*record.NumAttrs())
record.Attrs(func(attr slog.Attr) bool {
kvList = attrToKVs(attr, kvList)
return true
})
if record.Level >= slog.LevelError {
l.WithCallDepth(extraSlogSinkDepth).Error(nil, record.Message, kvList...)
} else {
level := l.levelFromSlog(record.Level)
l.WithCallDepth(extraSlogSinkDepth).Info(level, record.Message, kvList...)
}
return nil
}
func (l fnlogger) WithAttrs(attrs []slog.Attr) logr.SlogSink {
kvList := make([]any, 0, 2*len(attrs))
for _, attr := range attrs {
kvList = attrToKVs(attr, kvList)
}
l.AddValues(kvList)
return &l
}
func (l fnlogger) WithGroup(name string) logr.SlogSink {
l.startGroup(name)
return &l
}
// attrToKVs appends a slog.Attr to a logr-style kvList. It handle slog Groups
// and other details of slog.
func attrToKVs(attr slog.Attr, kvList []any) []any {
attrVal := attr.Value.Resolve()
if attrVal.Kind() == slog.KindGroup {
groupVal := attrVal.Group()
grpKVs := make([]any, 0, 2*len(groupVal))
for _, attr := range groupVal {
grpKVs = attrToKVs(attr, grpKVs)
}
if attr.Key == "" {
// slog says we have to inline these
kvList = append(kvList, grpKVs...)
} else {
kvList = append(kvList, attr.Key, PseudoStruct(grpKVs))
}
} else if attr.Key != "" {
kvList = append(kvList, attr.Key, attrVal.Any())
}
return kvList
}
// levelFromSlog adjusts the level by the logger's verbosity and negates it.
// It ensures that the result is >= 0. This is necessary because the result is
// passed to a LogSink and that API did not historically document whether
// levels could be negative or what that meant.
//
// Some example usage:
//
// logrV0 := getMyLogger()
// logrV2 := logrV0.V(2)
// slogV2 := slog.New(logr.ToSlogHandler(logrV2))
// slogV2.Debug("msg") // =~ logrV2.V(4) =~ logrV0.V(6)
// slogV2.Info("msg") // =~ logrV2.V(0) =~ logrV0.V(2)
// slogv2.Warn("msg") // =~ logrV2.V(-4) =~ logrV0.V(0)
func (l fnlogger) levelFromSlog(level slog.Level) int {
result := -level
if result < 0 {
result = 0 // because LogSink doesn't expect negative V levels
}
return int(result)
}

43
vendor/github.com/go-logr/logr/logr.go сгенерированный поставляемый
Просмотреть файл

@ -207,10 +207,6 @@ limitations under the License.
// those.
package logr
import (
"context"
)
// New returns a new Logger instance. This is primarily used by libraries
// implementing LogSink, rather than end users. Passing a nil sink will create
// a Logger which discards all log lines.
@ -410,45 +406,6 @@ func (l Logger) IsZero() bool {
return l.sink == nil
}
// contextKey is how we find Loggers in a context.Context.
type contextKey struct{}
// FromContext returns a Logger from ctx or an error if no Logger is found.
func FromContext(ctx context.Context) (Logger, error) {
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
return v, nil
}
return Logger{}, notFoundError{}
}
// notFoundError exists to carry an IsNotFound method.
type notFoundError struct{}
func (notFoundError) Error() string {
return "no logr.Logger was present"
}
func (notFoundError) IsNotFound() bool {
return true
}
// FromContextOrDiscard returns a Logger from ctx. If no Logger is found, this
// returns a Logger that discards all log messages.
func FromContextOrDiscard(ctx context.Context) Logger {
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
return v
}
return Discard()
}
// NewContext returns a new Context, derived from ctx, which carries the
// provided Logger.
func NewContext(ctx context.Context, logger Logger) context.Context {
return context.WithValue(ctx, contextKey{}, logger)
}
// RuntimeInfo holds information that the logr "core" library knows which
// LogSinks might want to know.
type RuntimeInfo struct {

192
vendor/github.com/go-logr/logr/sloghandler.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,192 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The logr 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 logr
import (
"context"
"log/slog"
)
type slogHandler struct {
// May be nil, in which case all logs get discarded.
sink LogSink
// Non-nil if sink is non-nil and implements SlogSink.
slogSink SlogSink
// groupPrefix collects values from WithGroup calls. It gets added as
// prefix to value keys when handling a log record.
groupPrefix string
// levelBias can be set when constructing the handler to influence the
// slog.Level of log records. A positive levelBias reduces the
// slog.Level value. slog has no API to influence this value after the
// handler got created, so it can only be set indirectly through
// Logger.V.
levelBias slog.Level
}
var _ slog.Handler = &slogHandler{}
// groupSeparator is used to concatenate WithGroup names and attribute keys.
const groupSeparator = "."
// GetLevel is used for black box unit testing.
func (l *slogHandler) GetLevel() slog.Level {
return l.levelBias
}
func (l *slogHandler) Enabled(_ context.Context, level slog.Level) bool {
return l.sink != nil && (level >= slog.LevelError || l.sink.Enabled(l.levelFromSlog(level)))
}
func (l *slogHandler) Handle(ctx context.Context, record slog.Record) error {
if l.slogSink != nil {
// Only adjust verbosity level of log entries < slog.LevelError.
if record.Level < slog.LevelError {
record.Level -= l.levelBias
}
return l.slogSink.Handle(ctx, record)
}
// No need to check for nil sink here because Handle will only be called
// when Enabled returned true.
kvList := make([]any, 0, 2*record.NumAttrs())
record.Attrs(func(attr slog.Attr) bool {
kvList = attrToKVs(attr, l.groupPrefix, kvList)
return true
})
if record.Level >= slog.LevelError {
l.sinkWithCallDepth().Error(nil, record.Message, kvList...)
} else {
level := l.levelFromSlog(record.Level)
l.sinkWithCallDepth().Info(level, record.Message, kvList...)
}
return nil
}
// sinkWithCallDepth adjusts the stack unwinding so that when Error or Info
// are called by Handle, code in slog gets skipped.
//
// This offset currently (Go 1.21.0) works for calls through
// slog.New(ToSlogHandler(...)). There's no guarantee that the call
// chain won't change. Wrapping the handler will also break unwinding. It's
// still better than not adjusting at all....
//
// This cannot be done when constructing the handler because FromSlogHandler needs
// access to the original sink without this adjustment. A second copy would
// work, but then WithAttrs would have to be called for both of them.
func (l *slogHandler) sinkWithCallDepth() LogSink {
if sink, ok := l.sink.(CallDepthLogSink); ok {
return sink.WithCallDepth(2)
}
return l.sink
}
func (l *slogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
if l.sink == nil || len(attrs) == 0 {
return l
}
clone := *l
if l.slogSink != nil {
clone.slogSink = l.slogSink.WithAttrs(attrs)
clone.sink = clone.slogSink
} else {
kvList := make([]any, 0, 2*len(attrs))
for _, attr := range attrs {
kvList = attrToKVs(attr, l.groupPrefix, kvList)
}
clone.sink = l.sink.WithValues(kvList...)
}
return &clone
}
func (l *slogHandler) WithGroup(name string) slog.Handler {
if l.sink == nil {
return l
}
if name == "" {
// slog says to inline empty groups
return l
}
clone := *l
if l.slogSink != nil {
clone.slogSink = l.slogSink.WithGroup(name)
clone.sink = clone.slogSink
} else {
clone.groupPrefix = addPrefix(clone.groupPrefix, name)
}
return &clone
}
// attrToKVs appends a slog.Attr to a logr-style kvList. It handle slog Groups
// and other details of slog.
func attrToKVs(attr slog.Attr, groupPrefix string, kvList []any) []any {
attrVal := attr.Value.Resolve()
if attrVal.Kind() == slog.KindGroup {
groupVal := attrVal.Group()
grpKVs := make([]any, 0, 2*len(groupVal))
prefix := groupPrefix
if attr.Key != "" {
prefix = addPrefix(groupPrefix, attr.Key)
}
for _, attr := range groupVal {
grpKVs = attrToKVs(attr, prefix, grpKVs)
}
kvList = append(kvList, grpKVs...)
} else if attr.Key != "" {
kvList = append(kvList, addPrefix(groupPrefix, attr.Key), attrVal.Any())
}
return kvList
}
func addPrefix(prefix, name string) string {
if prefix == "" {
return name
}
if name == "" {
return prefix
}
return prefix + groupSeparator + name
}
// levelFromSlog adjusts the level by the logger's verbosity and negates it.
// It ensures that the result is >= 0. This is necessary because the result is
// passed to a LogSink and that API did not historically document whether
// levels could be negative or what that meant.
//
// Some example usage:
//
// logrV0 := getMyLogger()
// logrV2 := logrV0.V(2)
// slogV2 := slog.New(logr.ToSlogHandler(logrV2))
// slogV2.Debug("msg") // =~ logrV2.V(4) =~ logrV0.V(6)
// slogV2.Info("msg") // =~ logrV2.V(0) =~ logrV0.V(2)
// slogv2.Warn("msg") // =~ logrV2.V(-4) =~ logrV0.V(0)
func (l *slogHandler) levelFromSlog(level slog.Level) int {
result := -level
result += l.levelBias // in case the original Logger had a V level
if result < 0 {
result = 0 // because LogSink doesn't expect negative V levels
}
return int(result)
}

100
vendor/github.com/go-logr/logr/slogr.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,100 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The logr 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 logr
import (
"context"
"log/slog"
)
// FromSlogHandler returns a Logger which writes to the slog.Handler.
//
// The logr verbosity level is mapped to slog levels such that V(0) becomes
// slog.LevelInfo and V(4) becomes slog.LevelDebug.
func FromSlogHandler(handler slog.Handler) Logger {
if handler, ok := handler.(*slogHandler); ok {
if handler.sink == nil {
return Discard()
}
return New(handler.sink).V(int(handler.levelBias))
}
return New(&slogSink{handler: handler})
}
// ToSlogHandler returns a slog.Handler which writes to the same sink as the Logger.
//
// The returned logger writes all records with level >= slog.LevelError as
// error log entries with LogSink.Error, regardless of the verbosity level of
// the Logger:
//
// logger := <some Logger with 0 as verbosity level>
// slog.New(ToSlogHandler(logger.V(10))).Error(...) -> logSink.Error(...)
//
// The level of all other records gets reduced by the verbosity
// level of the Logger and the result is negated. If it happens
// to be negative, then it gets replaced by zero because a LogSink
// is not expected to handled negative levels:
//
// slog.New(ToSlogHandler(logger)).Debug(...) -> logger.GetSink().Info(level=4, ...)
// slog.New(ToSlogHandler(logger)).Warning(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(ToSlogHandler(logger)).Info(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(ToSlogHandler(logger.V(4))).Info(...) -> logger.GetSink().Info(level=4, ...)
func ToSlogHandler(logger Logger) slog.Handler {
if sink, ok := logger.GetSink().(*slogSink); ok && logger.GetV() == 0 {
return sink.handler
}
handler := &slogHandler{sink: logger.GetSink(), levelBias: slog.Level(logger.GetV())}
if slogSink, ok := handler.sink.(SlogSink); ok {
handler.slogSink = slogSink
}
return handler
}
// SlogSink is an optional interface that a LogSink can implement to support
// logging through the slog.Logger or slog.Handler APIs better. It then should
// also support special slog values like slog.Group. When used as a
// slog.Handler, the advantages are:
//
// - stack unwinding gets avoided in favor of logging the pre-recorded PC,
// as intended by slog
// - proper grouping of key/value pairs via WithGroup
// - verbosity levels > slog.LevelInfo can be recorded
// - less overhead
//
// Both APIs (Logger and slog.Logger/Handler) then are supported equally
// well. Developers can pick whatever API suits them better and/or mix
// packages which use either API in the same binary with a common logging
// implementation.
//
// This interface is necessary because the type implementing the LogSink
// interface cannot also implement the slog.Handler interface due to the
// different prototype of the common Enabled method.
//
// An implementation could support both interfaces in two different types, but then
// additional interfaces would be needed to convert between those types in FromSlogHandler
// and ToSlogHandler.
type SlogSink interface {
LogSink
Handle(ctx context.Context, record slog.Record) error
WithAttrs(attrs []slog.Attr) SlogSink
WithGroup(name string) SlogSink
}

120
vendor/github.com/go-logr/logr/slogsink.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,120 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The logr 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 logr
import (
"context"
"log/slog"
"runtime"
"time"
)
var (
_ LogSink = &slogSink{}
_ CallDepthLogSink = &slogSink{}
_ Underlier = &slogSink{}
)
// Underlier is implemented by the LogSink returned by NewFromLogHandler.
type Underlier interface {
// GetUnderlying returns the Handler used by the LogSink.
GetUnderlying() slog.Handler
}
const (
// nameKey is used to log the `WithName` values as an additional attribute.
nameKey = "logger"
// errKey is used to log the error parameter of Error as an additional attribute.
errKey = "err"
)
type slogSink struct {
callDepth int
name string
handler slog.Handler
}
func (l *slogSink) Init(info RuntimeInfo) {
l.callDepth = info.CallDepth
}
func (l *slogSink) GetUnderlying() slog.Handler {
return l.handler
}
func (l *slogSink) WithCallDepth(depth int) LogSink {
newLogger := *l
newLogger.callDepth += depth
return &newLogger
}
func (l *slogSink) Enabled(level int) bool {
return l.handler.Enabled(context.Background(), slog.Level(-level))
}
func (l *slogSink) Info(level int, msg string, kvList ...interface{}) {
l.log(nil, msg, slog.Level(-level), kvList...)
}
func (l *slogSink) Error(err error, msg string, kvList ...interface{}) {
l.log(err, msg, slog.LevelError, kvList...)
}
func (l *slogSink) log(err error, msg string, level slog.Level, kvList ...interface{}) {
var pcs [1]uintptr
// skip runtime.Callers, this function, Info/Error, and all helper functions above that.
runtime.Callers(3+l.callDepth, pcs[:])
record := slog.NewRecord(time.Now(), level, msg, pcs[0])
if l.name != "" {
record.AddAttrs(slog.String(nameKey, l.name))
}
if err != nil {
record.AddAttrs(slog.Any(errKey, err))
}
record.Add(kvList...)
_ = l.handler.Handle(context.Background(), record)
}
func (l slogSink) WithName(name string) LogSink {
if l.name != "" {
l.name += "/"
}
l.name += name
return &l
}
func (l slogSink) WithValues(kvList ...interface{}) LogSink {
l.handler = l.handler.WithAttrs(kvListToAttrs(kvList...))
return &l
}
func kvListToAttrs(kvList ...interface{}) []slog.Attr {
// We don't need the record itself, only its Add method.
record := slog.NewRecord(time.Time{}, 0, "", 0)
record.Add(kvList...)
attrs := make([]slog.Attr, 0, record.NumAttrs())
record.Attrs(func(attr slog.Attr) bool {
attrs = append(attrs, attr)
return true
})
return attrs
}

12
vendor/golang.org/x/net/html/token.go сгенерированный поставляемый
Просмотреть файл

@ -910,9 +910,6 @@ func (z *Tokenizer) readTagAttrKey() {
return
}
switch c {
case ' ', '\n', '\r', '\t', '\f', '/':
z.pendingAttr[0].end = z.raw.end - 1
return
case '=':
if z.pendingAttr[0].start+1 == z.raw.end {
// WHATWG 13.2.5.32, if we see an equals sign before the attribute name
@ -920,7 +917,9 @@ func (z *Tokenizer) readTagAttrKey() {
continue
}
fallthrough
case '>':
case ' ', '\n', '\r', '\t', '\f', '/', '>':
// WHATWG 13.2.5.33 Attribute name state
// We need to reconsume the char in the after attribute name state to support the / character
z.raw.end--
z.pendingAttr[0].end = z.raw.end
return
@ -939,6 +938,11 @@ func (z *Tokenizer) readTagAttrVal() {
if z.err != nil {
return
}
if c == '/' {
// WHATWG 13.2.5.34 After attribute name state
// U+002F SOLIDUS (/) - Switch to the self-closing start tag state.
return
}
if c != '=' {
z.raw.end--
return

11
vendor/golang.org/x/net/http2/frame.go сгенерированный поставляемый
Просмотреть файл

@ -1510,13 +1510,12 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
}
func (fr *Framer) maxHeaderStringLen() int {
v := fr.maxHeaderListSize()
if uint32(int(v)) == v {
return int(v)
v := int(fr.maxHeaderListSize())
if v < 0 {
// If maxHeaderListSize overflows an int, use no limit (0).
return 0
}
// They had a crazy big number for MaxHeaderBytes anyway,
// so give them unlimited header lengths:
return 0
return v
}
// readMetaFrame returns 0 or more CONTINUATION frames from fr and

2
vendor/golang.org/x/sys/unix/mkerrors.sh сгенерированный поставляемый
Просмотреть файл

@ -584,7 +584,7 @@ ccflags="$@"
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
$2 ~ /^KEYCTL_/ ||
$2 ~ /^PERF_/ ||
$2 ~ /^SECCOMP_MODE_/ ||
$2 ~ /^SECCOMP_/ ||
$2 ~ /^SEEK_/ ||
$2 ~ /^SCHED_/ ||
$2 ~ /^SPLICE_/ ||

36
vendor/golang.org/x/sys/unix/zerrors_linux.go сгенерированный поставляемый
Просмотреть файл

@ -1785,6 +1785,8 @@ const (
LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20
LANDLOCK_ACCESS_FS_TRUNCATE = 0x4000
LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2
LANDLOCK_ACCESS_NET_BIND_TCP = 0x1
LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2
LANDLOCK_CREATE_RULESET_VERSION = 0x1
LINUX_REBOOT_CMD_CAD_OFF = 0x0
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
@ -2465,6 +2467,7 @@ const (
PR_MCE_KILL_GET = 0x22
PR_MCE_KILL_LATE = 0x0
PR_MCE_KILL_SET = 0x1
PR_MDWE_NO_INHERIT = 0x2
PR_MDWE_REFUSE_EXEC_GAIN = 0x1
PR_MPX_DISABLE_MANAGEMENT = 0x2c
PR_MPX_ENABLE_MANAGEMENT = 0x2b
@ -2669,8 +2672,9 @@ const (
RTAX_FEATURES = 0xc
RTAX_FEATURE_ALLFRAG = 0x8
RTAX_FEATURE_ECN = 0x1
RTAX_FEATURE_MASK = 0xf
RTAX_FEATURE_MASK = 0x1f
RTAX_FEATURE_SACK = 0x2
RTAX_FEATURE_TCP_USEC_TS = 0x10
RTAX_FEATURE_TIMESTAMP = 0x4
RTAX_HOPLIMIT = 0xa
RTAX_INITCWND = 0xb
@ -2913,9 +2917,38 @@ const (
SCM_RIGHTS = 0x1
SCM_TIMESTAMP = 0x1d
SC_LOG_FLUSH = 0x100000
SECCOMP_ADDFD_FLAG_SEND = 0x2
SECCOMP_ADDFD_FLAG_SETFD = 0x1
SECCOMP_FILTER_FLAG_LOG = 0x2
SECCOMP_FILTER_FLAG_NEW_LISTENER = 0x8
SECCOMP_FILTER_FLAG_SPEC_ALLOW = 0x4
SECCOMP_FILTER_FLAG_TSYNC = 0x1
SECCOMP_FILTER_FLAG_TSYNC_ESRCH = 0x10
SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV = 0x20
SECCOMP_GET_ACTION_AVAIL = 0x2
SECCOMP_GET_NOTIF_SIZES = 0x3
SECCOMP_IOCTL_NOTIF_RECV = 0xc0502100
SECCOMP_IOCTL_NOTIF_SEND = 0xc0182101
SECCOMP_IOC_MAGIC = '!'
SECCOMP_MODE_DISABLED = 0x0
SECCOMP_MODE_FILTER = 0x2
SECCOMP_MODE_STRICT = 0x1
SECCOMP_RET_ACTION = 0x7fff0000
SECCOMP_RET_ACTION_FULL = 0xffff0000
SECCOMP_RET_ALLOW = 0x7fff0000
SECCOMP_RET_DATA = 0xffff
SECCOMP_RET_ERRNO = 0x50000
SECCOMP_RET_KILL = 0x0
SECCOMP_RET_KILL_PROCESS = 0x80000000
SECCOMP_RET_KILL_THREAD = 0x0
SECCOMP_RET_LOG = 0x7ffc0000
SECCOMP_RET_TRACE = 0x7ff00000
SECCOMP_RET_TRAP = 0x30000
SECCOMP_RET_USER_NOTIF = 0x7fc00000
SECCOMP_SET_MODE_FILTER = 0x1
SECCOMP_SET_MODE_STRICT = 0x0
SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP = 0x1
SECCOMP_USER_NOTIF_FLAG_CONTINUE = 0x1
SECRETMEM_MAGIC = 0x5345434d
SECURITYFS_MAGIC = 0x73636673
SEEK_CUR = 0x1
@ -3075,6 +3108,7 @@ const (
SOL_TIPC = 0x10f
SOL_TLS = 0x11a
SOL_UDP = 0x11
SOL_VSOCK = 0x11f
SOL_X25 = 0x106
SOL_XDP = 0x11b
SOMAXCONN = 0x1000

3
vendor/golang.org/x/sys/unix/zerrors_linux_386.go сгенерированный поставляемый
Просмотреть файл

@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go сгенерированный поставляемый
Просмотреть файл

@ -282,6 +282,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_arm.go сгенерированный поставляемый
Просмотреть файл

@ -288,6 +288,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go сгенерированный поставляемый
Просмотреть файл

@ -278,6 +278,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go сгенерированный поставляемый
Просмотреть файл

@ -275,6 +275,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_mips.go сгенерированный поставляемый
Просмотреть файл

@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

3
vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go сгенерированный поставляемый
Просмотреть файл

@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

3
vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go сгенерированный поставляемый
Просмотреть файл

@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

3
vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go сгенерированный поставляемый
Просмотреть файл

@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307

3
vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go сгенерированный поставляемый
Просмотреть файл

@ -336,6 +336,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go сгенерированный поставляемый
Просмотреть файл

@ -340,6 +340,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go сгенерированный поставляемый
Просмотреть файл

@ -340,6 +340,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go сгенерированный поставляемый
Просмотреть файл

@ -272,6 +272,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go сгенерированный поставляемый
Просмотреть файл

@ -344,6 +344,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905

3
vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go сгенерированный поставляемый
Просмотреть файл

@ -335,6 +335,9 @@ const (
SCM_TIMESTAMPNS = 0x21
SCM_TXTIME = 0x3f
SCM_WIFI_STATUS = 0x25
SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x400000
SFD_NONBLOCK = 0x4000
SF_FP = 0x38

4
vendor/golang.org/x/sys/unix/zsysnum_linux_386.go сгенерированный поставляемый
Просмотреть файл

@ -448,4 +448,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

3
vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go сгенерированный поставляемый
Просмотреть файл

@ -371,4 +371,7 @@ const (
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go сгенерированный поставляемый
Просмотреть файл

@ -412,4 +412,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go сгенерированный поставляемый
Просмотреть файл

@ -315,4 +315,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go сгенерированный поставляемый
Просмотреть файл

@ -309,4 +309,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go сгенерированный поставляемый
Просмотреть файл

@ -432,4 +432,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 4450
SYS_CACHESTAT = 4451
SYS_FCHMODAT2 = 4452
SYS_MAP_SHADOW_STACK = 4453
SYS_FUTEX_WAKE = 4454
SYS_FUTEX_WAIT = 4455
SYS_FUTEX_REQUEUE = 4456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go сгенерированный поставляемый
Просмотреть файл

@ -362,4 +362,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 5450
SYS_CACHESTAT = 5451
SYS_FCHMODAT2 = 5452
SYS_MAP_SHADOW_STACK = 5453
SYS_FUTEX_WAKE = 5454
SYS_FUTEX_WAIT = 5455
SYS_FUTEX_REQUEUE = 5456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go сгенерированный поставляемый
Просмотреть файл

@ -362,4 +362,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 5450
SYS_CACHESTAT = 5451
SYS_FCHMODAT2 = 5452
SYS_MAP_SHADOW_STACK = 5453
SYS_FUTEX_WAKE = 5454
SYS_FUTEX_WAIT = 5455
SYS_FUTEX_REQUEUE = 5456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go сгенерированный поставляемый
Просмотреть файл

@ -432,4 +432,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 4450
SYS_CACHESTAT = 4451
SYS_FCHMODAT2 = 4452
SYS_MAP_SHADOW_STACK = 4453
SYS_FUTEX_WAKE = 4454
SYS_FUTEX_WAIT = 4455
SYS_FUTEX_REQUEUE = 4456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go сгенерированный поставляемый
Просмотреть файл

@ -439,4 +439,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go сгенерированный поставляемый
Просмотреть файл

@ -411,4 +411,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go сгенерированный поставляемый
Просмотреть файл

@ -411,4 +411,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go сгенерированный поставляемый
Просмотреть файл

@ -316,4 +316,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go сгенерированный поставляемый
Просмотреть файл

@ -377,4 +377,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

4
vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go сгенерированный поставляемый
Просмотреть файл

@ -390,4 +390,8 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
)

125
vendor/golang.org/x/sys/unix/ztypes_linux.go сгенерированный поставляемый
Просмотреть файл

@ -174,7 +174,8 @@ type FscryptPolicyV2 struct {
Contents_encryption_mode uint8
Filenames_encryption_mode uint8
Flags uint8
_ [4]uint8
Log2_data_unit_size uint8
_ [3]uint8
Master_key_identifier [16]uint8
}
@ -455,60 +456,63 @@ type Ucred struct {
}
type TCPInfo struct {
State uint8
Ca_state uint8
Retransmits uint8
Probes uint8
Backoff uint8
Options uint8
Rto uint32
Ato uint32
Snd_mss uint32
Rcv_mss uint32
Unacked uint32
Sacked uint32
Lost uint32
Retrans uint32
Fackets uint32
Last_data_sent uint32
Last_ack_sent uint32
Last_data_recv uint32
Last_ack_recv uint32
Pmtu uint32
Rcv_ssthresh uint32
Rtt uint32
Rttvar uint32
Snd_ssthresh uint32
Snd_cwnd uint32
Advmss uint32
Reordering uint32
Rcv_rtt uint32
Rcv_space uint32
Total_retrans uint32
Pacing_rate uint64
Max_pacing_rate uint64
Bytes_acked uint64
Bytes_received uint64
Segs_out uint32
Segs_in uint32
Notsent_bytes uint32
Min_rtt uint32
Data_segs_in uint32
Data_segs_out uint32
Delivery_rate uint64
Busy_time uint64
Rwnd_limited uint64
Sndbuf_limited uint64
Delivered uint32
Delivered_ce uint32
Bytes_sent uint64
Bytes_retrans uint64
Dsack_dups uint32
Reord_seen uint32
Rcv_ooopack uint32
Snd_wnd uint32
Rcv_wnd uint32
Rehash uint32
State uint8
Ca_state uint8
Retransmits uint8
Probes uint8
Backoff uint8
Options uint8
Rto uint32
Ato uint32
Snd_mss uint32
Rcv_mss uint32
Unacked uint32
Sacked uint32
Lost uint32
Retrans uint32
Fackets uint32
Last_data_sent uint32
Last_ack_sent uint32
Last_data_recv uint32
Last_ack_recv uint32
Pmtu uint32
Rcv_ssthresh uint32
Rtt uint32
Rttvar uint32
Snd_ssthresh uint32
Snd_cwnd uint32
Advmss uint32
Reordering uint32
Rcv_rtt uint32
Rcv_space uint32
Total_retrans uint32
Pacing_rate uint64
Max_pacing_rate uint64
Bytes_acked uint64
Bytes_received uint64
Segs_out uint32
Segs_in uint32
Notsent_bytes uint32
Min_rtt uint32
Data_segs_in uint32
Data_segs_out uint32
Delivery_rate uint64
Busy_time uint64
Rwnd_limited uint64
Sndbuf_limited uint64
Delivered uint32
Delivered_ce uint32
Bytes_sent uint64
Bytes_retrans uint64
Dsack_dups uint32
Reord_seen uint32
Rcv_ooopack uint32
Snd_wnd uint32
Rcv_wnd uint32
Rehash uint32
Total_rto uint16
Total_rto_recoveries uint16
Total_rto_time uint32
}
type CanFilter struct {
@ -551,7 +555,7 @@ const (
SizeofIPv6MTUInfo = 0x20
SizeofICMPv6Filter = 0x20
SizeofUcred = 0xc
SizeofTCPInfo = 0xf0
SizeofTCPInfo = 0xf8
SizeofCanFilter = 0x8
SizeofTCPRepairOpt = 0x8
)
@ -3399,7 +3403,7 @@ const (
DEVLINK_PORT_FN_ATTR_STATE = 0x2
DEVLINK_PORT_FN_ATTR_OPSTATE = 0x3
DEVLINK_PORT_FN_ATTR_CAPS = 0x4
DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x4
DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x5
)
type FsverityDigest struct {
@ -4183,7 +4187,8 @@ const (
)
type LandlockRulesetAttr struct {
Access_fs uint64
Access_fs uint64
Access_net uint64
}
type LandlockPathBeneathAttr struct {
@ -5134,7 +5139,7 @@ const (
NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf
NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe
NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf
NL80211_FREQUENCY_ATTR_MAX = 0x1b
NL80211_FREQUENCY_ATTR_MAX = 0x1c
NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6
NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
@ -5547,7 +5552,7 @@ const (
NL80211_REGDOM_TYPE_CUSTOM_WORLD = 0x2
NL80211_REGDOM_TYPE_INTERSECTION = 0x3
NL80211_REGDOM_TYPE_WORLD = 0x1
NL80211_REG_RULE_ATTR_MAX = 0x7
NL80211_REG_RULE_ATTR_MAX = 0x8
NL80211_REKEY_DATA_AKM = 0x4
NL80211_REKEY_DATA_KCK = 0x2
NL80211_REKEY_DATA_KEK = 0x1

17
vendor/golang.org/x/sys/windows/env_windows.go сгенерированный поставляемый
Просмотреть файл

@ -37,14 +37,17 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) {
return nil, err
}
defer DestroyEnvironmentBlock(block)
blockp := unsafe.Pointer(block)
for {
entry := UTF16PtrToString((*uint16)(blockp))
if len(entry) == 0 {
break
size := unsafe.Sizeof(*block)
for *block != 0 {
// find NUL terminator
end := unsafe.Pointer(block)
for *(*uint16)(end) != 0 {
end = unsafe.Add(end, size)
}
env = append(env, entry)
blockp = unsafe.Add(blockp, 2*(len(entry)+1))
entry := unsafe.Slice(block, (uintptr(end)-uintptr(unsafe.Pointer(block)))/size)
env = append(env, UTF16ToString(entry))
block = (*uint16)(unsafe.Add(end, size))
}
return env, nil
}

3
vendor/golang.org/x/sys/windows/syscall_windows.go сгенерированный поставляемый
Просмотреть файл

@ -125,8 +125,7 @@ func UTF16PtrToString(p *uint16) string {
for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ {
ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(*p))
}
return string(utf16.Decode(unsafe.Slice(p, n)))
return UTF16ToString(unsafe.Slice(p, n))
}
func Getpagesize() int { return 4096 }

6
vendor/k8s.io/klog/v2/.golangci.yaml сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
linters:
disable-all: true
enable: # sorted alphabetical
- gofmt
- misspell
- revive

4
vendor/k8s.io/klog/v2/OWNERS сгенерированный поставляемый
Просмотреть файл

@ -1,14 +1,16 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- harshanarayana
- mengjiao-liu
- pohly
approvers:
- dims
- pohly
- thockin
- serathius
emeritus_approvers:
- brancz
- justinsb
- lavalamp
- piosz
- serathius
- tallclair

31
vendor/k8s.io/klog/v2/contextual_slog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2021 The Kubernetes 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 klog
import (
"log/slog"
"github.com/go-logr/logr"
)
// SetSlogLogger reconfigures klog to log through the slog logger. The logger must not be nil.
func SetSlogLogger(logger *slog.Logger) {
SetLoggerWithOptions(logr.FromSlogHandler(logger.Handler()), ContextualLogger(true))
}

12
vendor/k8s.io/klog/v2/internal/buffer/buffer.go сгенерированный поставляемый
Просмотреть файл

@ -30,14 +30,16 @@ import (
var (
// Pid is inserted into log headers. Can be overridden for tests.
Pid = os.Getpid()
// Time, if set, will be used instead of the actual current time.
Time *time.Time
)
// Buffer holds a single byte.Buffer for reuse. The zero value is ready for
// use. It also provides some helper methods for output formatting.
type Buffer struct {
bytes.Buffer
Tmp [64]byte // temporary byte array for creating headers.
next *Buffer
Tmp [64]byte // temporary byte array for creating headers.
}
var buffers = sync.Pool{
@ -122,6 +124,9 @@ func (buf *Buffer) FormatHeader(s severity.Severity, file string, line int, now
// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
// It's worth about 3X. Fprintf is hard.
if Time != nil {
now = *Time
}
_, month, day := now.Date()
hour, minute, second := now.Clock()
// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
@ -157,6 +162,9 @@ func (buf *Buffer) SprintHeader(s severity.Severity, now time.Time) string {
// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
// It's worth about 3X. Fprintf is hard.
if Time != nil {
now = *Time
}
_, month, day := now.Date()
hour, minute, second := now.Clock()
// Lmmdd hh:mm:ss.uuuuuu threadid file:line]

21
vendor/k8s.io/klog/v2/internal/clock/clock.go сгенерированный поставляемый
Просмотреть файл

@ -39,16 +39,6 @@ type Clock interface {
// Sleep sleeps for the provided duration d.
// Consider making the sleep interruptible by using 'select' on a context channel and a timer channel.
Sleep(d time.Duration)
// Tick returns the channel of a new Ticker.
// This method does not allow to free/GC the backing ticker. Use
// NewTicker from WithTicker instead.
Tick(d time.Duration) <-chan time.Time
}
// WithTicker allows for injecting fake or real clocks into code that
// needs to do arbitrary things based on time.
type WithTicker interface {
Clock
// NewTicker returns a new Ticker.
NewTicker(time.Duration) Ticker
}
@ -66,7 +56,7 @@ type WithDelayedExecution interface {
// WithTickerAndDelayedExecution allows for injecting fake or real clocks
// into code that needs Ticker and AfterFunc functionality
type WithTickerAndDelayedExecution interface {
WithTicker
Clock
// AfterFunc executes f in its own goroutine after waiting
// for d duration and returns a Timer whose channel can be
// closed by calling Stop() on the Timer.
@ -79,7 +69,7 @@ type Ticker interface {
Stop()
}
var _ = WithTicker(RealClock{})
var _ Clock = RealClock{}
// RealClock really calls time.Now()
type RealClock struct{}
@ -115,13 +105,6 @@ func (RealClock) AfterFunc(d time.Duration, f func()) Timer {
}
}
// Tick is the same as time.Tick(d)
// This method does not allow to free/GC the backing ticker. Use
// NewTicker instead.
func (RealClock) Tick(d time.Duration) <-chan time.Time {
return time.Tick(d)
}
// NewTicker returns a new Ticker.
func (RealClock) NewTicker(d time.Duration) Ticker {
return &realTicker{

71
vendor/k8s.io/klog/v2/internal/serialize/keyvalues.go сгенерированный поставляемый
Просмотреть файл

@ -172,73 +172,6 @@ func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
Formatter{}.KVListFormat(b, keysAndValues...)
}
// KVFormat serializes one key/value pair into the provided buffer.
// A space gets inserted before the pair.
func (f Formatter) KVFormat(b *bytes.Buffer, k, v interface{}) {
b.WriteByte(' ')
// Keys are assumed to be well-formed according to
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments
// for the sake of performance. Keys with spaces,
// special characters, etc. will break parsing.
if sK, ok := k.(string); ok {
// Avoid one allocation when the key is a string, which
// normally it should be.
b.WriteString(sK)
} else {
b.WriteString(fmt.Sprintf("%s", k))
}
// The type checks are sorted so that more frequently used ones
// come first because that is then faster in the common
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
// than plain strings
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
switch v := v.(type) {
case textWriter:
writeTextWriterValue(b, v)
case fmt.Stringer:
writeStringValue(b, StringerToString(v))
case string:
writeStringValue(b, v)
case error:
writeStringValue(b, ErrorToString(v))
case logr.Marshaler:
value := MarshalerToValue(v)
// A marshaler that returns a string is useful for
// delayed formatting of complex values. We treat this
// case like a normal string. This is useful for
// multi-line support.
//
// We could do this by recursively formatting a value,
// but that comes with the risk of infinite recursion
// if a marshaler returns itself. Instead we call it
// only once and rely on it returning the intended
// value directly.
switch value := value.(type) {
case string:
writeStringValue(b, value)
default:
f.formatAny(b, value)
}
case []byte:
// In https://github.com/kubernetes/klog/pull/237 it was decided
// to format byte slices with "%+q". The advantages of that are:
// - readable output if the bytes happen to be printable
// - non-printable bytes get represented as unicode escape
// sequences (\uxxxx)
//
// The downsides are that we cannot use the faster
// strconv.Quote here and that multi-line output is not
// supported. If developers know that a byte array is
// printable and they want multi-line output, they can
// convert the value to string before logging it.
b.WriteByte('=')
b.WriteString(fmt.Sprintf("%+q", v))
default:
f.formatAny(b, v)
}
}
func KVFormat(b *bytes.Buffer, k, v interface{}) {
Formatter{}.KVFormat(b, k, v)
}
@ -251,6 +184,10 @@ func (f Formatter) formatAny(b *bytes.Buffer, v interface{}) {
b.WriteString(f.AnyToStringHook(v))
return
}
formatAsJSON(b, v)
}
func formatAsJSON(b *bytes.Buffer, v interface{}) {
encoder := json.NewEncoder(b)
l := b.Len()
if err := encoder.Encode(v); err != nil {

97
vendor/k8s.io/klog/v2/internal/serialize/keyvalues_no_slog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,97 @@
//go:build !go1.21
// +build !go1.21
/*
Copyright 2023 The Kubernetes 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 serialize
import (
"bytes"
"fmt"
"github.com/go-logr/logr"
)
// KVFormat serializes one key/value pair into the provided buffer.
// A space gets inserted before the pair.
func (f Formatter) KVFormat(b *bytes.Buffer, k, v interface{}) {
// This is the version without slog support. Must be kept in sync with
// the version in keyvalues_slog.go.
b.WriteByte(' ')
// Keys are assumed to be well-formed according to
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments
// for the sake of performance. Keys with spaces,
// special characters, etc. will break parsing.
if sK, ok := k.(string); ok {
// Avoid one allocation when the key is a string, which
// normally it should be.
b.WriteString(sK)
} else {
b.WriteString(fmt.Sprintf("%s", k))
}
// The type checks are sorted so that more frequently used ones
// come first because that is then faster in the common
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
// than plain strings
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
switch v := v.(type) {
case textWriter:
writeTextWriterValue(b, v)
case fmt.Stringer:
writeStringValue(b, StringerToString(v))
case string:
writeStringValue(b, v)
case error:
writeStringValue(b, ErrorToString(v))
case logr.Marshaler:
value := MarshalerToValue(v)
// A marshaler that returns a string is useful for
// delayed formatting of complex values. We treat this
// case like a normal string. This is useful for
// multi-line support.
//
// We could do this by recursively formatting a value,
// but that comes with the risk of infinite recursion
// if a marshaler returns itself. Instead we call it
// only once and rely on it returning the intended
// value directly.
switch value := value.(type) {
case string:
writeStringValue(b, value)
default:
f.formatAny(b, value)
}
case []byte:
// In https://github.com/kubernetes/klog/pull/237 it was decided
// to format byte slices with "%+q". The advantages of that are:
// - readable output if the bytes happen to be printable
// - non-printable bytes get represented as unicode escape
// sequences (\uxxxx)
//
// The downsides are that we cannot use the faster
// strconv.Quote here and that multi-line output is not
// supported. If developers know that a byte array is
// printable and they want multi-line output, they can
// convert the value to string before logging it.
b.WriteByte('=')
b.WriteString(fmt.Sprintf("%+q", v))
default:
f.formatAny(b, v)
}
}

155
vendor/k8s.io/klog/v2/internal/serialize/keyvalues_slog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,155 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The Kubernetes 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 serialize
import (
"bytes"
"fmt"
"log/slog"
"strconv"
"github.com/go-logr/logr"
)
// KVFormat serializes one key/value pair into the provided buffer.
// A space gets inserted before the pair.
func (f Formatter) KVFormat(b *bytes.Buffer, k, v interface{}) {
// This is the version without slog support. Must be kept in sync with
// the version in keyvalues_slog.go.
b.WriteByte(' ')
// Keys are assumed to be well-formed according to
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments
// for the sake of performance. Keys with spaces,
// special characters, etc. will break parsing.
if sK, ok := k.(string); ok {
// Avoid one allocation when the key is a string, which
// normally it should be.
b.WriteString(sK)
} else {
b.WriteString(fmt.Sprintf("%s", k))
}
// The type checks are sorted so that more frequently used ones
// come first because that is then faster in the common
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
// than plain strings
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
//
// slog.LogValuer does not need to be handled here because the handler will
// already have resolved such special values to the final value for logging.
switch v := v.(type) {
case textWriter:
writeTextWriterValue(b, v)
case slog.Value:
// This must come before fmt.Stringer because slog.Value implements
// fmt.Stringer, but does not produce the output that we want.
b.WriteByte('=')
generateJSON(b, v)
case fmt.Stringer:
writeStringValue(b, StringerToString(v))
case string:
writeStringValue(b, v)
case error:
writeStringValue(b, ErrorToString(v))
case logr.Marshaler:
value := MarshalerToValue(v)
// A marshaler that returns a string is useful for
// delayed formatting of complex values. We treat this
// case like a normal string. This is useful for
// multi-line support.
//
// We could do this by recursively formatting a value,
// but that comes with the risk of infinite recursion
// if a marshaler returns itself. Instead we call it
// only once and rely on it returning the intended
// value directly.
switch value := value.(type) {
case string:
writeStringValue(b, value)
default:
f.formatAny(b, value)
}
case slog.LogValuer:
value := slog.AnyValue(v).Resolve()
if value.Kind() == slog.KindString {
writeStringValue(b, value.String())
} else {
b.WriteByte('=')
generateJSON(b, value)
}
case []byte:
// In https://github.com/kubernetes/klog/pull/237 it was decided
// to format byte slices with "%+q". The advantages of that are:
// - readable output if the bytes happen to be printable
// - non-printable bytes get represented as unicode escape
// sequences (\uxxxx)
//
// The downsides are that we cannot use the faster
// strconv.Quote here and that multi-line output is not
// supported. If developers know that a byte array is
// printable and they want multi-line output, they can
// convert the value to string before logging it.
b.WriteByte('=')
b.WriteString(fmt.Sprintf("%+q", v))
default:
f.formatAny(b, v)
}
}
// generateJSON has the same preference for plain strings as KVFormat.
// In contrast to KVFormat it always produces valid JSON with no line breaks.
func generateJSON(b *bytes.Buffer, v interface{}) {
switch v := v.(type) {
case slog.Value:
switch v.Kind() {
case slog.KindGroup:
// Format as a JSON group. We must not involve f.AnyToStringHook (if there is any),
// because there is no guarantee that it produces valid JSON.
b.WriteByte('{')
for i, attr := range v.Group() {
if i > 0 {
b.WriteByte(',')
}
b.WriteString(strconv.Quote(attr.Key))
b.WriteByte(':')
generateJSON(b, attr.Value)
}
b.WriteByte('}')
case slog.KindLogValuer:
generateJSON(b, v.Resolve())
default:
// Peel off the slog.Value wrapper and format the actual value.
generateJSON(b, v.Any())
}
case fmt.Stringer:
b.WriteString(strconv.Quote(StringerToString(v)))
case logr.Marshaler:
generateJSON(b, MarshalerToValue(v))
case slog.LogValuer:
generateJSON(b, slog.AnyValue(v).Resolve().Any())
case string:
b.WriteString(strconv.Quote(v))
case error:
b.WriteString(strconv.Quote(v.Error()))
default:
formatAsJSON(b, v)
}
}

96
vendor/k8s.io/klog/v2/internal/sloghandler/sloghandler_slog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,96 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The Kubernetes 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 sloghandler
import (
"context"
"log/slog"
"runtime"
"strings"
"time"
"k8s.io/klog/v2/internal/severity"
)
func Handle(_ context.Context, record slog.Record, groups string, printWithInfos func(file string, line int, now time.Time, err error, s severity.Severity, msg string, kvList []interface{})) error {
now := record.Time
if now.IsZero() {
// This format doesn't support printing entries without a time.
now = time.Now()
}
// slog has numeric severity levels, with 0 as default "info", negative for debugging, and
// positive with some pre-defined levels for more important. Those ranges get mapped to
// the corresponding klog levels where possible, with "info" the default that is used
// also for negative debug levels.
level := record.Level
s := severity.InfoLog
switch {
case level >= slog.LevelError:
s = severity.ErrorLog
case level >= slog.LevelWarn:
s = severity.WarningLog
}
var file string
var line int
if record.PC != 0 {
// Same as https://cs.opensource.google/go/x/exp/+/642cacee:slog/record.go;drc=642cacee5cc05231f45555a333d07f1005ffc287;l=70
fs := runtime.CallersFrames([]uintptr{record.PC})
f, _ := fs.Next()
if f.File != "" {
file = f.File
if slash := strings.LastIndex(file, "/"); slash >= 0 {
file = file[slash+1:]
}
line = f.Line
}
} else {
file = "???"
line = 1
}
kvList := make([]interface{}, 0, 2*record.NumAttrs())
record.Attrs(func(attr slog.Attr) bool {
kvList = appendAttr(groups, kvList, attr)
return true
})
printWithInfos(file, line, now, nil, s, record.Message, kvList)
return nil
}
func Attrs2KVList(groups string, attrs []slog.Attr) []interface{} {
kvList := make([]interface{}, 0, 2*len(attrs))
for _, attr := range attrs {
kvList = appendAttr(groups, kvList, attr)
}
return kvList
}
func appendAttr(groups string, kvList []interface{}, attr slog.Attr) []interface{} {
var key string
if groups != "" {
key = groups + "." + attr.Key
} else {
key = attr.Key
}
return append(kvList, key, attr.Value)
}

39
vendor/k8s.io/klog/v2/k8s_references_slog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,39 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2021 The Kubernetes 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 klog
import (
"log/slog"
)
func (ref ObjectRef) LogValue() slog.Value {
if ref.Namespace != "" {
return slog.GroupValue(slog.String("name", ref.Name), slog.String("namespace", ref.Namespace))
}
return slog.GroupValue(slog.String("name", ref.Name))
}
var _ slog.LogValuer = ObjectRef{}
func (ks kobjSlice) LogValue() slog.Value {
return slog.AnyValue(ks.MarshalLog())
}
var _ slog.LogValuer = kobjSlice{}

89
vendor/k8s.io/klog/v2/klog.go сгенерированный поставляемый
Просмотреть файл

@ -14,9 +14,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Package klog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup.
// It provides functions Info, Warning, Error, Fatal, plus formatting variants such as
// Infof. It also provides V-style logging controlled by the -v and -vmodule=file=2 flags.
// Package klog contains the following functionality:
//
// - output routing as defined via command line flags ([InitFlags])
// - log formatting as text, either with a single, unstructured string ([Info], [Infof], etc.)
// or as a structured log entry with message and key/value pairs ([InfoS], etc.)
// - management of a go-logr [Logger] ([SetLogger], [Background], [TODO])
// - helper functions for logging values ([Format]) and managing the state of klog ([CaptureState], [State.Restore])
// - wrappers for [logr] APIs for contextual logging where the wrappers can
// be turned into no-ops ([EnableContextualLogging], [NewContext], [FromContext],
// [LoggerWithValues], [LoggerWithName]); if the ability to turn off
// contextual logging is not needed, then go-logr can also be used directly
// - type aliases for go-logr types to simplify imports in code which uses both (e.g. [Logger])
// - [k8s.io/klog/v2/textlogger]: a logger which uses the same formatting as klog log with
// simpler output routing; beware that it comes with its own command line flags
// and does not use the ones from klog
// - [k8s.io/klog/v2/ktesting]: per-test output in Go unit tests
// - [k8s.io/klog/v2/klogr]: a deprecated, standalone [logr.Logger] on top of the main klog package;
// use [Background] instead if klog output routing is needed, [k8s.io/klog/v2/textlogger] if not
// - [k8s.io/klog/v2/examples]: demos of this functionality
// - [k8s.io/klog/v2/test]: reusable tests for [logr.Logger] implementations
//
// Basic examples:
//
@ -415,7 +432,7 @@ func init() {
logging.stderrThreshold = severityValue{
Severity: severity.ErrorLog, // Default stderrThreshold is ERROR.
}
commandLine.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false)")
commandLine.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=true)")
commandLine.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
commandLine.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
@ -518,9 +535,7 @@ type settings struct {
func (s settings) deepCopy() settings {
// vmodule is a slice and would be shared, so we have copy it.
filter := make([]modulePat, len(s.vmodule.filter))
for i := range s.vmodule.filter {
filter[i] = s.vmodule.filter[i]
}
copy(filter, s.vmodule.filter)
s.vmodule.filter = filter
if s.logger != nil {
@ -657,16 +672,15 @@ func (l *loggingT) header(s severity.Severity, depth int) (*buffer.Buffer, strin
}
}
}
return l.formatHeader(s, file, line), file, line
return l.formatHeader(s, file, line, timeNow()), file, line
}
// formatHeader formats a log header using the provided file name and line number.
func (l *loggingT) formatHeader(s severity.Severity, file string, line int) *buffer.Buffer {
func (l *loggingT) formatHeader(s severity.Severity, file string, line int, now time.Time) *buffer.Buffer {
buf := buffer.GetBuffer()
if l.skipHeaders {
return buf
}
now := timeNow()
buf.FormatHeader(s, file, line, now)
return buf
}
@ -676,6 +690,10 @@ func (l *loggingT) println(s severity.Severity, logger *logWriter, filter LogFil
}
func (l *loggingT) printlnDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
if false {
_ = fmt.Sprintln(args...) // cause vet to treat this function like fmt.Println
}
buf, file, line := l.header(s, depth)
// If a logger is set and doesn't support writing a formatted buffer,
// we clear the generated header as we rely on the backing
@ -696,7 +714,15 @@ func (l *loggingT) print(s severity.Severity, logger *logWriter, filter LogFilte
}
func (l *loggingT) printDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
if false {
_ = fmt.Sprint(args...) // // cause vet to treat this function like fmt.Print
}
buf, file, line := l.header(s, depth)
l.printWithInfos(buf, file, line, s, logger, filter, depth+1, args...)
}
func (l *loggingT) printWithInfos(buf *buffer.Buffer, file string, line int, s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
// If a logger is set and doesn't support writing a formatted buffer,
// we clear the generated header as we rely on the backing
// logger implementation to print headers.
@ -719,6 +745,10 @@ func (l *loggingT) printf(s severity.Severity, logger *logWriter, filter LogFilt
}
func (l *loggingT) printfDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, format string, args ...interface{}) {
if false {
_ = fmt.Sprintf(format, args...) // cause vet to treat this function like fmt.Printf
}
buf, file, line := l.header(s, depth)
// If a logger is set and doesn't support writing a formatted buffer,
// we clear the generated header as we rely on the backing
@ -741,7 +771,7 @@ func (l *loggingT) printfDepth(s severity.Severity, logger *logWriter, filter Lo
// alsoLogToStderr is true, the log message always appears on standard error; it
// will also appear in the log file unless --logtostderr is set.
func (l *loggingT) printWithFileLine(s severity.Severity, logger *logWriter, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
buf := l.formatHeader(s, file, line)
buf := l.formatHeader(s, file, line, timeNow())
// If a logger is set and doesn't support writing a formatted buffer,
// we clear the generated header as we rely on the backing
// logger implementation to print headers.
@ -759,7 +789,7 @@ func (l *loggingT) printWithFileLine(s severity.Severity, logger *logWriter, fil
l.output(s, logger, buf, 2 /* depth */, file, line, alsoToStderr)
}
// if loggr is specified, will call loggr.Error, otherwise output with logging module.
// if logger is specified, will call logger.Error, otherwise output with logging module.
func (l *loggingT) errorS(err error, logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
if filter != nil {
msg, keysAndValues = filter.FilterS(msg, keysAndValues)
@ -771,7 +801,7 @@ func (l *loggingT) errorS(err error, logger *logWriter, filter LogFilter, depth
l.printS(err, severity.ErrorLog, depth+1, msg, keysAndValues...)
}
// if loggr is specified, will call loggr.Info, otherwise output with logging module.
// if logger is specified, will call logger.Info, otherwise output with logging module.
func (l *loggingT) infoS(logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
if filter != nil {
msg, keysAndValues = filter.FilterS(msg, keysAndValues)
@ -783,7 +813,7 @@ func (l *loggingT) infoS(logger *logWriter, filter LogFilter, depth int, msg str
l.printS(nil, severity.InfoLog, depth+1, msg, keysAndValues...)
}
// printS is called from infoS and errorS if loggr is not specified.
// printS is called from infoS and errorS if logger is not specified.
// set log severity by s
func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string, keysAndValues ...interface{}) {
// Only create a new buffer if we don't have one cached.
@ -796,7 +826,7 @@ func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string,
serialize.KVListFormat(&b.Buffer, "err", err)
}
serialize.KVListFormat(&b.Buffer, keysAndValues...)
l.printDepth(s, logging.logger, nil, depth+1, &b.Buffer)
l.printDepth(s, nil, nil, depth+1, &b.Buffer)
// Make the buffer available for reuse.
buffer.PutBuffer(b)
}
@ -873,6 +903,9 @@ func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Bu
if logger.writeKlogBuffer != nil {
logger.writeKlogBuffer(data)
} else {
if len(data) > 0 && data[len(data)-1] == '\n' {
data = data[:len(data)-1]
}
// TODO: set 'severity' and caller information as structured log info
// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
if s == severity.ErrorLog {
@ -897,7 +930,7 @@ func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Bu
l.exit(err)
}
}
l.file[severity.InfoLog].Write(data)
_, _ = l.file[severity.InfoLog].Write(data)
} else {
if l.file[s] == nil {
if err := l.createFiles(s); err != nil {
@ -907,20 +940,20 @@ func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Bu
}
if l.oneOutput {
l.file[s].Write(data)
_, _ = l.file[s].Write(data)
} else {
switch s {
case severity.FatalLog:
l.file[severity.FatalLog].Write(data)
_, _ = l.file[severity.FatalLog].Write(data)
fallthrough
case severity.ErrorLog:
l.file[severity.ErrorLog].Write(data)
_, _ = l.file[severity.ErrorLog].Write(data)
fallthrough
case severity.WarningLog:
l.file[severity.WarningLog].Write(data)
_, _ = l.file[severity.WarningLog].Write(data)
fallthrough
case severity.InfoLog:
l.file[severity.InfoLog].Write(data)
_, _ = l.file[severity.InfoLog].Write(data)
}
}
}
@ -946,7 +979,7 @@ func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Bu
logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
for log := severity.FatalLog; log >= severity.InfoLog; log-- {
if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
f.Write(trace)
_, _ = f.Write(trace)
}
}
l.mu.Unlock()
@ -1102,7 +1135,7 @@ const flushInterval = 5 * time.Second
// flushDaemon periodically flushes the log file buffers.
type flushDaemon struct {
mu sync.Mutex
clock clock.WithTicker
clock clock.Clock
flush func()
stopC chan struct{}
stopDone chan struct{}
@ -1110,7 +1143,7 @@ type flushDaemon struct {
// newFlushDaemon returns a new flushDaemon. If the passed clock is nil, a
// clock.RealClock is used.
func newFlushDaemon(flush func(), tickClock clock.WithTicker) *flushDaemon {
func newFlushDaemon(flush func(), tickClock clock.Clock) *flushDaemon {
if tickClock == nil {
tickClock = clock.RealClock{}
}
@ -1201,8 +1234,8 @@ func (l *loggingT) flushAll() {
for s := severity.FatalLog; s >= severity.InfoLog; s-- {
file := l.file[s]
if file != nil {
file.Flush() // ignore error
file.Sync() // ignore error
_ = file.Flush() // ignore error
_ = file.Sync() // ignore error
}
}
if logging.loggerOptions.flush != nil {
@ -1281,9 +1314,7 @@ func (l *loggingT) setV(pc uintptr) Level {
fn := runtime.FuncForPC(pc)
file, _ := fn.FileLine(pc)
// The file is something like /a/b/c/d.go. We want just the d.
if strings.HasSuffix(file, ".go") {
file = file[:len(file)-3]
}
file = strings.TrimSuffix(file, ".go")
if slash := strings.LastIndex(file, "/"); slash >= 0 {
file = file[slash+1:]
}

4
vendor/k8s.io/klog/v2/klog_file.go сгенерированный поставляемый
Просмотреть файл

@ -109,8 +109,8 @@ func create(tag string, t time.Time, startup bool) (f *os.File, filename string,
f, err := openOrCreate(fname, startup)
if err == nil {
symlink := filepath.Join(dir, link)
os.Remove(symlink) // ignore err
os.Symlink(name, symlink) // ignore err
_ = os.Remove(symlink) // ignore err
_ = os.Symlink(name, symlink) // ignore err
return f, fname, nil
}
lastErr = err

46
vendor/k8s.io/klog/v2/klogr.go сгенерированный поставляемый
Просмотреть файл

@ -22,6 +22,11 @@ import (
"k8s.io/klog/v2/internal/serialize"
)
const (
// nameKey is used to log the `WithName` values as an additional attribute.
nameKey = "logger"
)
// NewKlogr returns a logger that is functionally identical to
// klogr.NewWithOptions(klogr.FormatKlog), i.e. it passes through to klog. The
// difference is that it uses a simpler implementation.
@ -32,10 +37,15 @@ func NewKlogr() Logger {
// klogger is a subset of klogr/klogr.go. It had to be copied to break an
// import cycle (klogr wants to use klog, and klog wants to use klogr).
type klogger struct {
level int
callDepth int
prefix string
values []interface{}
// hasPrefix is true if the first entry in values is the special
// nameKey key/value. Such an entry gets added and later updated in
// WithName.
hasPrefix bool
values []interface{}
groups string
}
func (l *klogger) Init(info logr.RuntimeInfo) {
@ -44,34 +54,40 @@ func (l *klogger) Init(info logr.RuntimeInfo) {
func (l *klogger) Info(level int, msg string, kvList ...interface{}) {
merged := serialize.MergeKVs(l.values, kvList)
if l.prefix != "" {
msg = l.prefix + ": " + msg
}
// Skip this function.
VDepth(l.callDepth+1, Level(level)).InfoSDepth(l.callDepth+1, msg, merged...)
}
func (l *klogger) Enabled(level int) bool {
// Skip this function and logr.Logger.Info where Enabled is called.
return VDepth(l.callDepth+2, Level(level)).Enabled()
return VDepth(l.callDepth+1, Level(level)).Enabled()
}
func (l *klogger) Error(err error, msg string, kvList ...interface{}) {
merged := serialize.MergeKVs(l.values, kvList)
if l.prefix != "" {
msg = l.prefix + ": " + msg
}
ErrorSDepth(l.callDepth+1, err, msg, merged...)
}
// WithName returns a new logr.Logger with the specified name appended. klogr
// uses '/' characters to separate name elements. Callers should not pass '/'
// uses '.' characters to separate name elements. Callers should not pass '.'
// in the provided name string, but this library does not actually enforce that.
func (l klogger) WithName(name string) logr.LogSink {
if len(l.prefix) > 0 {
l.prefix = l.prefix + "/"
if l.hasPrefix {
// Copy slice and modify value. No length checks and type
// assertions are needed because hasPrefix is only true if the
// first two elements exist and are key/value strings.
v := make([]interface{}, 0, len(l.values))
v = append(v, l.values...)
prefix, _ := v[1].(string)
v[1] = prefix + "." + name
l.values = v
} else {
// Preprend new key/value pair.
v := make([]interface{}, 0, 2+len(l.values))
v = append(v, nameKey, name)
v = append(v, l.values...)
l.values = v
l.hasPrefix = true
}
l.prefix += name
return &l
}

96
vendor/k8s.io/klog/v2/klogr_slog.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,96 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The Kubernetes 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 klog
import (
"context"
"log/slog"
"strconv"
"time"
"github.com/go-logr/logr"
"k8s.io/klog/v2/internal/buffer"
"k8s.io/klog/v2/internal/serialize"
"k8s.io/klog/v2/internal/severity"
"k8s.io/klog/v2/internal/sloghandler"
)
func (l *klogger) Handle(ctx context.Context, record slog.Record) error {
if logging.logger != nil {
if slogSink, ok := logging.logger.GetSink().(logr.SlogSink); ok {
// Let that logger do the work.
return slogSink.Handle(ctx, record)
}
}
return sloghandler.Handle(ctx, record, l.groups, slogOutput)
}
// slogOutput corresponds to several different functions in klog.go.
// It goes through some of the same checks and formatting steps before
// it ultimately converges by calling logging.printWithInfos.
func slogOutput(file string, line int, now time.Time, err error, s severity.Severity, msg string, kvList []interface{}) {
// See infoS.
if logging.logger != nil {
// Taking this path happens when klog has a logger installed
// as backend which doesn't support slog. Not good, we have to
// guess about the call depth and drop the actual location.
logger := logging.logger.WithCallDepth(2)
if s > severity.ErrorLog {
logger.Error(err, msg, kvList...)
} else {
logger.Info(msg, kvList...)
}
return
}
// See printS.
b := buffer.GetBuffer()
b.WriteString(strconv.Quote(msg))
if err != nil {
serialize.KVListFormat(&b.Buffer, "err", err)
}
serialize.KVListFormat(&b.Buffer, kvList...)
// See print + header.
buf := logging.formatHeader(s, file, line, now)
logging.printWithInfos(buf, file, line, s, nil, nil, 0, &b.Buffer)
buffer.PutBuffer(b)
}
func (l *klogger) WithAttrs(attrs []slog.Attr) logr.SlogSink {
clone := *l
clone.values = serialize.WithValues(l.values, sloghandler.Attrs2KVList(l.groups, attrs))
return &clone
}
func (l *klogger) WithGroup(name string) logr.SlogSink {
clone := *l
if clone.groups != "" {
clone.groups += "." + name
} else {
clone.groups = name
}
return &clone
}
var _ logr.SlogSink = &klogger{}

34
vendor/k8s.io/klog/v2/safeptr.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,34 @@
//go:build go1.18
// +build go1.18
/*
Copyright 2023 The Kubernetes 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 klog
// SafePtr is a function that takes a pointer of any type (T) as an argument.
// If the provided pointer is not nil, it returns the same pointer. If it is nil, it returns nil instead.
//
// This function is particularly useful to prevent nil pointer dereferencing when:
//
// - The type implements interfaces that are called by the logger, such as `fmt.Stringer`.
// - And these interface implementations do not perform nil checks themselves.
func SafePtr[T any](p *T) any {
if p == nil {
return nil
}
return p
}

8
vendor/k8s.io/utils/integer/integer.go сгенерированный поставляемый
Просмотреть файл

@ -16,6 +16,8 @@ limitations under the License.
package integer
import "math"
// IntMax returns the maximum of the params
func IntMax(a, b int) int {
if b > a {
@ -65,9 +67,7 @@ func Int64Min(a, b int64) int64 {
}
// RoundToInt32 rounds floats into integer numbers.
// Deprecated: use math.Round() and a cast directly.
func RoundToInt32(a float64) int32 {
if a < 0 {
return int32(a - 0.5)
}
return int32(a + 0.5)
return int32(math.Round(a))
}

25
vendor/modules.txt поставляемый
Просмотреть файл

@ -532,7 +532,7 @@ github.com/go-chi/chi/v5/middleware
# github.com/go-errors/errors v1.4.2
## explicit; go 1.14
github.com/go-errors/errors
# github.com/go-logr/logr v1.3.0
# github.com/go-logr/logr v1.4.1
## explicit; go 1.18
github.com/go-logr/logr
github.com/go-logr/logr/funcr
@ -1063,7 +1063,7 @@ github.com/openshift/console-operator/pkg/api
# github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87
## explicit; go 1.12
github.com/openshift/custom-resource-status/conditions/v1
# github.com/openshift/hive/apis v0.0.0-20231116161336-9dd47f8bfa1f => github.com/openshift/hive/apis v0.0.0-20231116161336-9dd47f8bfa1f
# github.com/openshift/hive/apis v0.0.0-20240131003045-5fbe0d158ba9 => github.com/openshift/hive/apis v0.0.0-20231116161336-9dd47f8bfa1f
## explicit; go 1.20
github.com/openshift/hive/apis/hive/v1
github.com/openshift/hive/apis/hive/v1/agent
@ -1317,7 +1317,7 @@ go.starlark.net/resolve
go.starlark.net/starlark
go.starlark.net/starlarkstruct
go.starlark.net/syntax
# golang.org/x/crypto v0.18.0
# golang.org/x/crypto v0.19.0
## explicit; go 1.18
golang.org/x/crypto/blowfish
golang.org/x/crypto/cast5
@ -1352,7 +1352,7 @@ golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile
golang.org/x/mod/module
golang.org/x/mod/semver
# golang.org/x/net v0.20.0
# golang.org/x/net v0.21.0
## explicit; go 1.18
golang.org/x/net/context
golang.org/x/net/html
@ -1374,14 +1374,14 @@ golang.org/x/oauth2/internal
## explicit; go 1.17
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
# golang.org/x/sys v0.16.0
# golang.org/x/sys v0.17.0
## explicit; go 1.18
golang.org/x/sys/cpu
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.16.0
# golang.org/x/term v0.17.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/text v0.14.0
@ -1560,7 +1560,7 @@ gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3
# k8s.io/api v0.28.3 => k8s.io/api v0.25.16
# k8s.io/api v0.29.1 => k8s.io/api v0.25.16
## explicit; go 1.19
k8s.io/api/admission/v1
k8s.io/api/admission/v1beta1
@ -1629,7 +1629,7 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme
k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1
k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1
k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model
# k8s.io/apimachinery v0.28.3 => k8s.io/apimachinery v0.25.16
# k8s.io/apimachinery v0.29.1 => k8s.io/apimachinery v0.25.16
## explicit; go 1.19
k8s.io/apimachinery/pkg/api/equality
k8s.io/apimachinery/pkg/api/errors
@ -2022,14 +2022,15 @@ k8s.io/gengo/generator
k8s.io/gengo/namer
k8s.io/gengo/parser
k8s.io/gengo/types
# k8s.io/klog/v2 v2.100.1
## explicit; go 1.13
# k8s.io/klog/v2 v2.120.1
## explicit; go 1.18
k8s.io/klog/v2
k8s.io/klog/v2/internal/buffer
k8s.io/klog/v2/internal/clock
k8s.io/klog/v2/internal/dbg
k8s.io/klog/v2/internal/serialize
k8s.io/klog/v2/internal/severity
k8s.io/klog/v2/internal/sloghandler
# k8s.io/kube-aggregator v0.24.1 => k8s.io/kube-aggregator v0.25.16
## explicit; go 1.19
k8s.io/kube-aggregator/pkg/apis/apiregistration
@ -2078,7 +2079,7 @@ k8s.io/kubernetes/pkg/apis/rbac/v1
k8s.io/kubernetes/pkg/features
k8s.io/kubernetes/pkg/kubelet/events
k8s.io/kubernetes/pkg/util/parsers
# k8s.io/utils v0.0.0-20230726121419-3b25d923346b
# k8s.io/utils v0.0.0-20240102154912-e7106e64919e
## explicit; go 1.18
k8s.io/utils/buffer
k8s.io/utils/clock
@ -2245,7 +2246,7 @@ sigs.k8s.io/kustomize/kyaml/yaml/merge2
sigs.k8s.io/kustomize/kyaml/yaml/merge3
sigs.k8s.io/kustomize/kyaml/yaml/schema
sigs.k8s.io/kustomize/kyaml/yaml/walk
# sigs.k8s.io/structured-merge-diff/v4 v4.2.3
# sigs.k8s.io/structured-merge-diff/v4 v4.4.1
## explicit; go 1.13
sigs.k8s.io/structured-merge-diff/v4/fieldpath
sigs.k8s.io/structured-merge-diff/v4/schema

45
vendor/sigs.k8s.io/structured-merge-diff/v4/fieldpath/pathelementmap.go сгенерированный поставляемый
Просмотреть файл

@ -28,20 +28,15 @@ import (
// for PathElementSet and SetNodeMap, so we could probably share the
// code.
type PathElementValueMap struct {
members sortedPathElementValues
valueMap PathElementMap
}
func MakePathElementValueMap(size int) PathElementValueMap {
return PathElementValueMap{
members: make(sortedPathElementValues, 0, size),
valueMap: MakePathElementMap(size),
}
}
type pathElementValue struct {
PathElement PathElement
Value value.Value
}
type sortedPathElementValues []pathElementValue
// Implement the sort interface; this would permit bulk creation, which would
@ -53,7 +48,40 @@ func (spev sortedPathElementValues) Less(i, j int) bool {
func (spev sortedPathElementValues) Swap(i, j int) { spev[i], spev[j] = spev[j], spev[i] }
// Insert adds the pathelement and associated value in the map.
// If insert is called twice with the same PathElement, the value is replaced.
func (s *PathElementValueMap) Insert(pe PathElement, v value.Value) {
s.valueMap.Insert(pe, v)
}
// Get retrieves the value associated with the given PathElement from the map.
// (nil, false) is returned if there is no such PathElement.
func (s *PathElementValueMap) Get(pe PathElement) (value.Value, bool) {
v, ok := s.valueMap.Get(pe)
if !ok {
return nil, false
}
return v.(value.Value), true
}
// PathElementValueMap is a map from PathElement to interface{}.
type PathElementMap struct {
members sortedPathElementValues
}
type pathElementValue struct {
PathElement PathElement
Value interface{}
}
func MakePathElementMap(size int) PathElementMap {
return PathElementMap{
members: make(sortedPathElementValues, 0, size),
}
}
// Insert adds the pathelement and associated value in the map.
// If insert is called twice with the same PathElement, the value is replaced.
func (s *PathElementMap) Insert(pe PathElement, v interface{}) {
loc := sort.Search(len(s.members), func(i int) bool {
return !s.members[i].PathElement.Less(pe)
})
@ -62,6 +90,7 @@ func (s *PathElementValueMap) Insert(pe PathElement, v value.Value) {
return
}
if s.members[loc].PathElement.Equals(pe) {
s.members[loc].Value = v
return
}
s.members = append(s.members, pathElementValue{})
@ -71,7 +100,7 @@ func (s *PathElementValueMap) Insert(pe PathElement, v value.Value) {
// Get retrieves the value associated with the given PathElement from the map.
// (nil, false) is returned if there is no such PathElement.
func (s *PathElementValueMap) Get(pe PathElement) (value.Value, bool) {
func (s *PathElementMap) Get(pe PathElement) (interface{}, bool) {
loc := sort.Search(len(s.members), func(i int) bool {
return !s.members[i].PathElement.Less(pe)
})

3
vendor/sigs.k8s.io/structured-merge-diff/v4/schema/elements.go сгенерированный поставляемый
Просмотреть файл

@ -73,7 +73,7 @@ type Atom struct {
}
// Scalar (AKA "primitive") represents a type which has a single value which is
// either numeric, string, or boolean.
// either numeric, string, or boolean, or untyped for any of them.
//
// TODO: split numeric into float/int? Something even more fine-grained?
type Scalar string
@ -82,6 +82,7 @@ const (
Numeric = Scalar("numeric")
String = Scalar("string")
Boolean = Scalar("boolean")
Untyped = Scalar("untyped")
)
// ElementRelationship is an enum of the different possible relationships

3
vendor/sigs.k8s.io/structured-merge-diff/v4/schema/schemaschema.go сгенерированный поставляемый
Просмотреть файл

@ -110,7 +110,7 @@ var SchemaSchemaYAML = `types:
scalar: string
- name: deduceInvalidDiscriminator
type:
scalar: bool
scalar: boolean
- name: fields
type:
list:
@ -145,6 +145,7 @@ var SchemaSchemaYAML = `types:
list:
elementType:
scalar: string
elementRelationship: atomic
- name: untyped
map:
fields:

460
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/compare.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,460 @@
/*
Copyright 2018 The Kubernetes 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 typed
import (
"fmt"
"strings"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
"sigs.k8s.io/structured-merge-diff/v4/schema"
"sigs.k8s.io/structured-merge-diff/v4/value"
)
// Comparison is the return value of a TypedValue.Compare() operation.
//
// No field will appear in more than one of the three fieldsets. If all of the
// fieldsets are empty, then the objects must have been equal.
type Comparison struct {
// Removed contains any fields removed by rhs (the right-hand-side
// object in the comparison).
Removed *fieldpath.Set
// Modified contains fields present in both objects but different.
Modified *fieldpath.Set
// Added contains any fields added by rhs.
Added *fieldpath.Set
}
// IsSame returns true if the comparison returned no changes (the two
// compared objects are similar).
func (c *Comparison) IsSame() bool {
return c.Removed.Empty() && c.Modified.Empty() && c.Added.Empty()
}
// String returns a human readable version of the comparison.
func (c *Comparison) String() string {
bld := strings.Builder{}
if !c.Modified.Empty() {
bld.WriteString(fmt.Sprintf("- Modified Fields:\n%v\n", c.Modified))
}
if !c.Added.Empty() {
bld.WriteString(fmt.Sprintf("- Added Fields:\n%v\n", c.Added))
}
if !c.Removed.Empty() {
bld.WriteString(fmt.Sprintf("- Removed Fields:\n%v\n", c.Removed))
}
return bld.String()
}
// ExcludeFields fields from the compare recursively removes the fields
// from the entire comparison
func (c *Comparison) ExcludeFields(fields *fieldpath.Set) *Comparison {
if fields == nil || fields.Empty() {
return c
}
c.Removed = c.Removed.RecursiveDifference(fields)
c.Modified = c.Modified.RecursiveDifference(fields)
c.Added = c.Added.RecursiveDifference(fields)
return c
}
type compareWalker struct {
lhs value.Value
rhs value.Value
schema *schema.Schema
typeRef schema.TypeRef
// Current path that we are comparing
path fieldpath.Path
// Resulting comparison.
comparison *Comparison
// internal housekeeping--don't set when constructing.
inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list
// Allocate only as many walkers as needed for the depth by storing them here.
spareWalkers *[]*compareWalker
allocator value.Allocator
}
// compare compares stuff.
func (w *compareWalker) compare(prefixFn func() string) (errs ValidationErrors) {
if w.lhs == nil && w.rhs == nil {
// check this condidition here instead of everywhere below.
return errorf("at least one of lhs and rhs must be provided")
}
a, ok := w.schema.Resolve(w.typeRef)
if !ok {
return errorf("schema error: no type found matching: %v", *w.typeRef.NamedType)
}
alhs := deduceAtom(a, w.lhs)
arhs := deduceAtom(a, w.rhs)
// deduceAtom does not fix the type for nil values
// nil is a wildcard and will accept whatever form the other operand takes
if w.rhs == nil {
errs = append(errs, handleAtom(alhs, w.typeRef, w)...)
} else if w.lhs == nil || alhs.Equals(&arhs) {
errs = append(errs, handleAtom(arhs, w.typeRef, w)...)
} else {
w2 := *w
errs = append(errs, handleAtom(alhs, w.typeRef, &w2)...)
errs = append(errs, handleAtom(arhs, w.typeRef, w)...)
}
if !w.inLeaf {
if w.lhs == nil {
w.comparison.Added.Insert(w.path)
} else if w.rhs == nil {
w.comparison.Removed.Insert(w.path)
}
}
return errs.WithLazyPrefix(prefixFn)
}
// doLeaf should be called on leaves before descending into children, if there
// will be a descent. It modifies w.inLeaf.
func (w *compareWalker) doLeaf() {
if w.inLeaf {
// We're in a "big leaf", an atomic map or list. Ignore
// subsequent leaves.
return
}
w.inLeaf = true
// We don't recurse into leaf fields for merging.
if w.lhs == nil {
w.comparison.Added.Insert(w.path)
} else if w.rhs == nil {
w.comparison.Removed.Insert(w.path)
} else if !value.EqualsUsing(w.allocator, w.rhs, w.lhs) {
// TODO: Equality is not sufficient for this.
// Need to implement equality check on the value type.
w.comparison.Modified.Insert(w.path)
}
}
func (w *compareWalker) doScalar(t *schema.Scalar) ValidationErrors {
// Make sure at least one side is a valid scalar.
lerrs := validateScalar(t, w.lhs, "lhs: ")
rerrs := validateScalar(t, w.rhs, "rhs: ")
if len(lerrs) > 0 && len(rerrs) > 0 {
return append(lerrs, rerrs...)
}
// All scalars are leaf fields.
w.doLeaf()
return nil
}
func (w *compareWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef, cmp *Comparison) *compareWalker {
if w.spareWalkers == nil {
// first descent.
w.spareWalkers = &[]*compareWalker{}
}
var w2 *compareWalker
if n := len(*w.spareWalkers); n > 0 {
w2, *w.spareWalkers = (*w.spareWalkers)[n-1], (*w.spareWalkers)[:n-1]
} else {
w2 = &compareWalker{}
}
*w2 = *w
w2.typeRef = tr
w2.path = append(w2.path, pe)
w2.lhs = nil
w2.rhs = nil
w2.comparison = cmp
return w2
}
func (w *compareWalker) finishDescent(w2 *compareWalker) {
// if the descent caused a realloc, ensure that we reuse the buffer
// for the next sibling.
w.path = w2.path[:len(w2.path)-1]
*w.spareWalkers = append(*w.spareWalkers, w2)
}
func (w *compareWalker) derefMap(prefix string, v value.Value) (value.Map, ValidationErrors) {
if v == nil {
return nil, nil
}
m, err := mapValue(w.allocator, v)
if err != nil {
return nil, errorf("%v: %v", prefix, err)
}
return m, nil
}
func (w *compareWalker) visitListItems(t *schema.List, lhs, rhs value.List) (errs ValidationErrors) {
rLen := 0
if rhs != nil {
rLen = rhs.Length()
}
lLen := 0
if lhs != nil {
lLen = lhs.Length()
}
maxLength := rLen
if lLen > maxLength {
maxLength = lLen
}
// Contains all the unique PEs between lhs and rhs, exactly once.
// Order doesn't matter since we're just tracking ownership in a set.
allPEs := make([]fieldpath.PathElement, 0, maxLength)
// Gather all the elements from lhs, indexed by PE, in a list for duplicates.
lValues := fieldpath.MakePathElementMap(lLen)
for i := 0; i < lLen; i++ {
child := lhs.At(i)
pe, err := listItemToPathElement(w.allocator, w.schema, t, child)
if err != nil {
errs = append(errs, errorf("element %v: %v", i, err.Error())...)
// If we can't construct the path element, we can't
// even report errors deeper in the schema, so bail on
// this element.
continue
}
if v, found := lValues.Get(pe); found {
list := v.([]value.Value)
lValues.Insert(pe, append(list, child))
} else {
lValues.Insert(pe, []value.Value{child})
allPEs = append(allPEs, pe)
}
}
// Gather all the elements from rhs, indexed by PE, in a list for duplicates.
rValues := fieldpath.MakePathElementMap(rLen)
for i := 0; i < rLen; i++ {
rValue := rhs.At(i)
pe, err := listItemToPathElement(w.allocator, w.schema, t, rValue)
if err != nil {
errs = append(errs, errorf("element %v: %v", i, err.Error())...)
// If we can't construct the path element, we can't
// even report errors deeper in the schema, so bail on
// this element.
continue
}
if v, found := rValues.Get(pe); found {
list := v.([]value.Value)
rValues.Insert(pe, append(list, rValue))
} else {
rValues.Insert(pe, []value.Value{rValue})
if _, found := lValues.Get(pe); !found {
allPEs = append(allPEs, pe)
}
}
}
for _, pe := range allPEs {
lList := []value.Value(nil)
if l, ok := lValues.Get(pe); ok {
lList = l.([]value.Value)
}
rList := []value.Value(nil)
if l, ok := rValues.Get(pe); ok {
rList = l.([]value.Value)
}
switch {
case len(lList) == 0 && len(rList) == 0:
// We shouldn't be here anyway.
return
// Normal use-case:
// We have no duplicates for this PE, compare items one-to-one.
case len(lList) <= 1 && len(rList) <= 1:
lValue := value.Value(nil)
if len(lList) != 0 {
lValue = lList[0]
}
rValue := value.Value(nil)
if len(rList) != 0 {
rValue = rList[0]
}
errs = append(errs, w.compareListItem(t, pe, lValue, rValue)...)
// Duplicates before & after use-case:
// Compare the duplicates lists as if they were atomic, mark modified if they changed.
case len(lList) >= 2 && len(rList) >= 2:
listEqual := func(lList, rList []value.Value) bool {
if len(lList) != len(rList) {
return false
}
for i := range lList {
if !value.Equals(lList[i], rList[i]) {
return false
}
}
return true
}
if !listEqual(lList, rList) {
w.comparison.Modified.Insert(append(w.path, pe))
}
// Duplicates before & not anymore use-case:
// Rcursively add new non-duplicate items, Remove duplicate marker,
case len(lList) >= 2:
if len(rList) != 0 {
errs = append(errs, w.compareListItem(t, pe, nil, rList[0])...)
}
w.comparison.Removed.Insert(append(w.path, pe))
// New duplicates use-case:
// Recursively remove old non-duplicate items, add duplicate marker.
case len(rList) >= 2:
if len(lList) != 0 {
errs = append(errs, w.compareListItem(t, pe, lList[0], nil)...)
}
w.comparison.Added.Insert(append(w.path, pe))
}
}
return
}
func (w *compareWalker) indexListPathElements(t *schema.List, list value.List) ([]fieldpath.PathElement, fieldpath.PathElementValueMap, ValidationErrors) {
var errs ValidationErrors
length := 0
if list != nil {
length = list.Length()
}
observed := fieldpath.MakePathElementValueMap(length)
pes := make([]fieldpath.PathElement, 0, length)
for i := 0; i < length; i++ {
child := list.At(i)
pe, err := listItemToPathElement(w.allocator, w.schema, t, child)
if err != nil {
errs = append(errs, errorf("element %v: %v", i, err.Error())...)
// If we can't construct the path element, we can't
// even report errors deeper in the schema, so bail on
// this element.
continue
}
// Ignore repeated occurences of `pe`.
if _, found := observed.Get(pe); found {
continue
}
observed.Insert(pe, child)
pes = append(pes, pe)
}
return pes, observed, errs
}
func (w *compareWalker) compareListItem(t *schema.List, pe fieldpath.PathElement, lChild, rChild value.Value) ValidationErrors {
w2 := w.prepareDescent(pe, t.ElementType, w.comparison)
w2.lhs = lChild
w2.rhs = rChild
errs := w2.compare(pe.String)
w.finishDescent(w2)
return errs
}
func (w *compareWalker) derefList(prefix string, v value.Value) (value.List, ValidationErrors) {
if v == nil {
return nil, nil
}
l, err := listValue(w.allocator, v)
if err != nil {
return nil, errorf("%v: %v", prefix, err)
}
return l, nil
}
func (w *compareWalker) doList(t *schema.List) (errs ValidationErrors) {
lhs, _ := w.derefList("lhs: ", w.lhs)
if lhs != nil {
defer w.allocator.Free(lhs)
}
rhs, _ := w.derefList("rhs: ", w.rhs)
if rhs != nil {
defer w.allocator.Free(rhs)
}
// If both lhs and rhs are empty/null, treat it as a
// leaf: this helps preserve the empty/null
// distinction.
emptyPromoteToLeaf := (lhs == nil || lhs.Length() == 0) && (rhs == nil || rhs.Length() == 0)
if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf {
w.doLeaf()
return nil
}
if lhs == nil && rhs == nil {
return nil
}
errs = w.visitListItems(t, lhs, rhs)
return errs
}
func (w *compareWalker) visitMapItem(t *schema.Map, out map[string]interface{}, key string, lhs, rhs value.Value) (errs ValidationErrors) {
fieldType := t.ElementType
if sf, ok := t.FindField(key); ok {
fieldType = sf.Type
}
pe := fieldpath.PathElement{FieldName: &key}
w2 := w.prepareDescent(pe, fieldType, w.comparison)
w2.lhs = lhs
w2.rhs = rhs
errs = append(errs, w2.compare(pe.String)...)
w.finishDescent(w2)
return errs
}
func (w *compareWalker) visitMapItems(t *schema.Map, lhs, rhs value.Map) (errs ValidationErrors) {
out := map[string]interface{}{}
value.MapZipUsing(w.allocator, lhs, rhs, value.Unordered, func(key string, lhsValue, rhsValue value.Value) bool {
errs = append(errs, w.visitMapItem(t, out, key, lhsValue, rhsValue)...)
return true
})
return errs
}
func (w *compareWalker) doMap(t *schema.Map) (errs ValidationErrors) {
lhs, _ := w.derefMap("lhs: ", w.lhs)
if lhs != nil {
defer w.allocator.Free(lhs)
}
rhs, _ := w.derefMap("rhs: ", w.rhs)
if rhs != nil {
defer w.allocator.Free(rhs)
}
// If both lhs and rhs are empty/null, treat it as a
// leaf: this helps preserve the empty/null
// distinction.
emptyPromoteToLeaf := (lhs == nil || lhs.Empty()) && (rhs == nil || rhs.Empty())
if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf {
w.doLeaf()
return nil
}
if lhs == nil && rhs == nil {
return nil
}
errs = append(errs, w.visitMapItems(t, lhs, rhs)...)
return errs
}

23
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/helpers.go сгенерированный поставляемый
Просмотреть файл

@ -197,7 +197,7 @@ func getAssociativeKeyDefault(s *schema.Schema, list *schema.List, fieldName str
return field.Default, nil
}
func keyedAssociativeListItemToPathElement(a value.Allocator, s *schema.Schema, list *schema.List, index int, child value.Value) (fieldpath.PathElement, error) {
func keyedAssociativeListItemToPathElement(a value.Allocator, s *schema.Schema, list *schema.List, child value.Value) (fieldpath.PathElement, error) {
pe := fieldpath.PathElement{}
if child.IsNull() {
// null entries are illegal.
@ -225,7 +225,7 @@ func keyedAssociativeListItemToPathElement(a value.Allocator, s *schema.Schema,
return pe, nil
}
func setItemToPathElement(list *schema.List, index int, child value.Value) (fieldpath.PathElement, error) {
func setItemToPathElement(child value.Value) (fieldpath.PathElement, error) {
pe := fieldpath.PathElement{}
switch {
case child.IsMap():
@ -245,16 +245,15 @@ func setItemToPathElement(list *schema.List, index int, child value.Value) (fiel
}
}
func listItemToPathElement(a value.Allocator, s *schema.Schema, list *schema.List, index int, child value.Value) (fieldpath.PathElement, error) {
if list.ElementRelationship == schema.Associative {
if len(list.Keys) > 0 {
return keyedAssociativeListItemToPathElement(a, s, list, index, child)
}
// If there's no keys, then we must be a set of primitives.
return setItemToPathElement(list, index, child)
func listItemToPathElement(a value.Allocator, s *schema.Schema, list *schema.List, child value.Value) (fieldpath.PathElement, error) {
if list.ElementRelationship != schema.Associative {
return fieldpath.PathElement{}, errors.New("invalid indexing of non-associative list")
}
// Use the index as a key for atomic lists.
return fieldpath.PathElement{Index: &index}, nil
if len(list.Keys) > 0 {
return keyedAssociativeListItemToPathElement(a, s, list, child)
}
// If there's no keys, then we must be a set of primitives.
return setItemToPathElement(child)
}

61
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/merge.go сгенерированный поставляемый
Просмотреть файл

@ -113,11 +113,12 @@ func (w *mergingWalker) doLeaf() {
w.rule(w)
}
func (w *mergingWalker) doScalar(t *schema.Scalar) (errs ValidationErrors) {
errs = append(errs, validateScalar(t, w.lhs, "lhs: ")...)
errs = append(errs, validateScalar(t, w.rhs, "rhs: ")...)
if len(errs) > 0 {
return errs
func (w *mergingWalker) doScalar(t *schema.Scalar) ValidationErrors {
// Make sure at least one side is a valid scalar.
lerrs := validateScalar(t, w.lhs, "lhs: ")
rerrs := validateScalar(t, w.rhs, "rhs: ")
if len(lerrs) > 0 && len(rerrs) > 0 {
return append(lerrs, rerrs...)
}
// All scalars are leaf fields.
@ -179,14 +180,18 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
}
out := make([]interface{}, 0, outLen)
rhsOrder, observedRHS, rhsErrs := w.indexListPathElements(t, rhs)
rhsPEs, observedRHS, rhsErrs := w.indexListPathElements(t, rhs, false)
errs = append(errs, rhsErrs...)
lhsOrder, observedLHS, lhsErrs := w.indexListPathElements(t, lhs)
lhsPEs, observedLHS, lhsErrs := w.indexListPathElements(t, lhs, true)
errs = append(errs, lhsErrs...)
if len(errs) != 0 {
return errs
}
sharedOrder := make([]*fieldpath.PathElement, 0, rLen)
for i := range rhsOrder {
pe := &rhsOrder[i]
for i := range rhsPEs {
pe := &rhsPEs[i]
if _, ok := observedLHS.Get(*pe); ok {
sharedOrder = append(sharedOrder, pe)
}
@ -198,13 +203,15 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
sharedOrder = sharedOrder[1:]
}
lLen, rLen = len(lhsOrder), len(rhsOrder)
mergedRHS := fieldpath.MakePathElementMap(len(rhsPEs))
lLen, rLen = len(lhsPEs), len(rhsPEs)
for lI, rI := 0, 0; lI < lLen || rI < rLen; {
if lI < lLen && rI < rLen {
pe := lhsOrder[lI]
if pe.Equals(rhsOrder[rI]) {
pe := lhsPEs[lI]
if pe.Equals(rhsPEs[rI]) {
// merge LHS & RHS items
lChild, _ := observedLHS.Get(pe)
mergedRHS.Insert(pe, struct{}{})
lChild, _ := observedLHS.Get(pe) // may be nil if the PE is duplicaated.
rChild, _ := observedRHS.Get(pe)
mergeOut, errs := w.mergeListItem(t, pe, lChild, rChild)
errs = append(errs, errs...)
@ -221,17 +228,17 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
}
continue
}
if _, ok := observedRHS.Get(pe); ok && nextShared != nil && !nextShared.Equals(lhsOrder[lI]) {
if _, ok := observedRHS.Get(pe); ok && nextShared != nil && !nextShared.Equals(lhsPEs[lI]) {
// shared item, but not the one we want in this round
lI++
continue
}
}
if lI < lLen {
pe := lhsOrder[lI]
pe := lhsPEs[lI]
if _, ok := observedRHS.Get(pe); !ok {
// take LHS item
lChild, _ := observedLHS.Get(pe)
// take LHS item using At to make sure we get the right item (observed may not contain the right item).
lChild := lhs.AtUsing(w.allocator, lI)
mergeOut, errs := w.mergeListItem(t, pe, lChild, nil)
errs = append(errs, errs...)
if mergeOut != nil {
@ -239,12 +246,16 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
}
lI++
continue
} else if _, ok := mergedRHS.Get(pe); ok {
// we've already merged it with RHS, we don't want to duplicate it, skip it.
lI++
}
}
if rI < rLen {
// Take the RHS item, merge with matching LHS item if possible
pe := rhsOrder[rI]
lChild, _ := observedLHS.Get(pe) // may be nil
pe := rhsPEs[rI]
mergedRHS.Insert(pe, struct{}{})
lChild, _ := observedLHS.Get(pe) // may be nil if absent or duplicaated.
rChild, _ := observedRHS.Get(pe)
mergeOut, errs := w.mergeListItem(t, pe, lChild, rChild)
errs = append(errs, errs...)
@ -271,7 +282,7 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
return errs
}
func (w *mergingWalker) indexListPathElements(t *schema.List, list value.List) ([]fieldpath.PathElement, fieldpath.PathElementValueMap, ValidationErrors) {
func (w *mergingWalker) indexListPathElements(t *schema.List, list value.List, allowDuplicates bool) ([]fieldpath.PathElement, fieldpath.PathElementValueMap, ValidationErrors) {
var errs ValidationErrors
length := 0
if list != nil {
@ -281,7 +292,7 @@ func (w *mergingWalker) indexListPathElements(t *schema.List, list value.List) (
pes := make([]fieldpath.PathElement, 0, length)
for i := 0; i < length; i++ {
child := list.At(i)
pe, err := listItemToPathElement(w.allocator, w.schema, t, i, child)
pe, err := listItemToPathElement(w.allocator, w.schema, t, child)
if err != nil {
errs = append(errs, errorf("element %v: %v", i, err.Error())...)
// If we can't construct the path element, we can't
@ -289,11 +300,15 @@ func (w *mergingWalker) indexListPathElements(t *schema.List, list value.List) (
// this element.
continue
}
if _, found := observed.Get(pe); found {
if _, found := observed.Get(pe); found && !allowDuplicates {
errs = append(errs, errorf("duplicate entries for key %v", pe.String())...)
continue
} else if !found {
observed.Insert(pe, child)
} else {
// Duplicated items are not merged with the new value, make them nil.
observed.Insert(pe, value.NewValueInterface(nil))
}
observed.Insert(pe, child)
pes = append(pes, pe)
}
return pes, observed, errs

12
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/parser.go сгенерированный поставляемый
Просмотреть файл

@ -93,13 +93,13 @@ func (p ParseableType) IsValid() bool {
// FromYAML parses a yaml string into an object with the current schema
// and the type "typename" or an error if validation fails.
func (p ParseableType) FromYAML(object YAMLObject) (*TypedValue, error) {
func (p ParseableType) FromYAML(object YAMLObject, opts ...ValidationOptions) (*TypedValue, error) {
var v interface{}
err := yaml.Unmarshal([]byte(object), &v)
if err != nil {
return nil, err
}
return AsTyped(value.NewValueInterface(v), p.Schema, p.TypeRef)
return AsTyped(value.NewValueInterface(v), p.Schema, p.TypeRef, opts...)
}
// FromUnstructured converts a go "interface{}" type, typically an
@ -108,8 +108,8 @@ func (p ParseableType) FromYAML(object YAMLObject) (*TypedValue, error) {
// The provided interface{} must be one of: map[string]interface{},
// map[interface{}]interface{}, []interface{}, int types, float types,
// string or boolean. Nested interface{} must also be one of these types.
func (p ParseableType) FromUnstructured(in interface{}) (*TypedValue, error) {
return AsTyped(value.NewValueInterface(in), p.Schema, p.TypeRef)
func (p ParseableType) FromUnstructured(in interface{}, opts ...ValidationOptions) (*TypedValue, error) {
return AsTyped(value.NewValueInterface(in), p.Schema, p.TypeRef, opts...)
}
// FromStructured converts a go "interface{}" type, typically an structured object in
@ -117,12 +117,12 @@ func (p ParseableType) FromUnstructured(in interface{}) (*TypedValue, error) {
// schema validation. The provided "interface{}" value must be a pointer so that the
// value can be modified via reflection. The provided "interface{}" may contain structs
// and types that are converted to Values by the jsonMarshaler interface.
func (p ParseableType) FromStructured(in interface{}) (*TypedValue, error) {
func (p ParseableType) FromStructured(in interface{}, opts ...ValidationOptions) (*TypedValue, error) {
v, err := value.NewValueReflect(in)
if err != nil {
return nil, fmt.Errorf("error creating struct value reflector: %v", err)
}
return AsTyped(v, p.Schema, p.TypeRef)
return AsTyped(v, p.Schema, p.TypeRef, opts...)
}
// DeducedParseableType is a ParseableType that deduces the type from

4
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/remove.go сгенерированный поставляемый
Просмотреть файл

@ -74,9 +74,9 @@ func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
iter := l.RangeUsing(w.allocator)
defer w.allocator.Free(iter)
for iter.Next() {
i, item := iter.Item()
_, item := iter.Item()
// Ignore error because we have already validated this list
pe, _ := listItemToPathElement(w.allocator, w.schema, t, i, item)
pe, _ := listItemToPathElement(w.allocator, w.schema, t, item)
path, _ := fieldpath.MakePath(pe)
// save items on the path when we shouldExtract
// but ignore them when we are removing (i.e. !w.shouldExtract)

24
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/tofieldset.go сгенерированный поставляемый
Просмотреть файл

@ -94,9 +94,31 @@ func (v *toFieldSetWalker) doScalar(t *schema.Scalar) ValidationErrors {
}
func (v *toFieldSetWalker) visitListItems(t *schema.List, list value.List) (errs ValidationErrors) {
// Keeps track of the PEs we've seen
seen := fieldpath.MakePathElementSet(list.Length())
// Keeps tracks of the PEs we've counted as duplicates
duplicates := fieldpath.MakePathElementSet(list.Length())
for i := 0; i < list.Length(); i++ {
child := list.At(i)
pe, _ := listItemToPathElement(v.allocator, v.schema, t, i, child)
pe, _ := listItemToPathElement(v.allocator, v.schema, t, child)
if seen.Has(pe) {
if duplicates.Has(pe) {
// do nothing
} else {
v.set.Insert(append(v.path, pe))
duplicates.Insert(pe)
}
} else {
seen.Insert(pe)
}
}
for i := 0; i < list.Length(); i++ {
child := list.At(i)
pe, _ := listItemToPathElement(v.allocator, v.schema, t, child)
if duplicates.Has(pe) {
continue
}
v2 := v.prepareDescent(pe, t.ElementType)
v2.value = child
errs = append(errs, v2.toFieldSet()...)

187
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/typed.go сгенерированный поставляемый
Просмотреть файл

@ -17,8 +17,6 @@ limitations under the License.
package typed
import (
"fmt"
"strings"
"sync"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
@ -26,16 +24,24 @@ import (
"sigs.k8s.io/structured-merge-diff/v4/value"
)
// ValidationOptions is the list of all the options available when running the validation.
type ValidationOptions int
const (
// AllowDuplicates means that sets and associative lists can have duplicate similar items.
AllowDuplicates ValidationOptions = iota
)
// 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.
func AsTyped(v value.Value, s *schema.Schema, typeRef schema.TypeRef) (*TypedValue, error) {
func AsTyped(v value.Value, s *schema.Schema, typeRef schema.TypeRef, opts ...ValidationOptions) (*TypedValue, error) {
tv := &TypedValue{
value: v,
typeRef: typeRef,
schema: s,
}
if err := tv.Validate(); err != nil {
if err := tv.Validate(opts...); err != nil {
return nil, err
}
return tv, nil
@ -45,6 +51,10 @@ func AsTyped(v value.Value, s *schema.Schema, typeRef schema.TypeRef) (*TypedVal
// conforms to the schema, for cases where that has already been checked or
// where you're going to call a method that validates as a side-effect (like
// ToFieldSet).
//
// Deprecated: This function was initially created because validation
// was expensive. Now that this has been solved, objects should always
// be created as validated, using `AsTyped`.
func AsTypedUnvalidated(v value.Value, s *schema.Schema, typeRef schema.TypeRef) *TypedValue {
tv := &TypedValue{
value: v,
@ -77,8 +87,14 @@ func (tv TypedValue) Schema() *schema.Schema {
}
// Validate returns an error with a list of every spec violation.
func (tv TypedValue) Validate() error {
func (tv TypedValue) Validate(opts ...ValidationOptions) error {
w := tv.walker()
for _, opt := range opts {
switch opt {
case AllowDuplicates:
w.allowDuplicates = true
}
}
defer w.finished()
if errs := w.validate(nil); len(errs) != 0 {
return errs
@ -113,6 +129,10 @@ func (tv TypedValue) Merge(pso *TypedValue) (*TypedValue, error) {
return merge(&tv, pso, ruleKeepRHS, nil)
}
var cmpwPool = sync.Pool{
New: func() interface{} { return &compareWalker{} },
}
// Compare compares the two objects. See the comments on the `Comparison`
// struct for details on the return value.
//
@ -120,33 +140,44 @@ func (tv TypedValue) Merge(pso *TypedValue) (*TypedValue, error) {
// match), or an error will be returned. Validation errors will be returned if
// the objects don't conform to the schema.
func (tv TypedValue) Compare(rhs *TypedValue) (c *Comparison, err error) {
c = &Comparison{
lhs := tv
if lhs.schema != rhs.schema {
return nil, errorf("expected objects with types from the same schema")
}
if !lhs.typeRef.Equals(&rhs.typeRef) {
return nil, errorf("expected objects of the same type, but got %v and %v", lhs.typeRef, rhs.typeRef)
}
cmpw := cmpwPool.Get().(*compareWalker)
defer func() {
cmpw.lhs = nil
cmpw.rhs = nil
cmpw.schema = nil
cmpw.typeRef = schema.TypeRef{}
cmpw.comparison = nil
cmpw.inLeaf = false
cmpwPool.Put(cmpw)
}()
cmpw.lhs = lhs.value
cmpw.rhs = rhs.value
cmpw.schema = lhs.schema
cmpw.typeRef = lhs.typeRef
cmpw.comparison = &Comparison{
Removed: fieldpath.NewSet(),
Modified: fieldpath.NewSet(),
Added: fieldpath.NewSet(),
}
_, err = merge(&tv, rhs, func(w *mergingWalker) {
if w.lhs == nil {
c.Added.Insert(w.path)
} else if w.rhs == nil {
c.Removed.Insert(w.path)
} else if !value.Equals(w.rhs, w.lhs) {
// TODO: Equality is not sufficient for this.
// Need to implement equality check on the value type.
c.Modified.Insert(w.path)
}
}, func(w *mergingWalker) {
if w.lhs == nil {
c.Added.Insert(w.path)
} else if w.rhs == nil {
c.Removed.Insert(w.path)
}
})
if err != nil {
return nil, err
if cmpw.allocator == nil {
cmpw.allocator = value.NewFreelistAllocator()
}
return c, nil
errs := cmpw.compare(nil)
if len(errs) > 0 {
return nil, errs
}
return cmpw.comparison, nil
}
// RemoveItems removes each provided list or map item from the value.
@ -161,63 +192,6 @@ func (tv TypedValue) ExtractItems(items *fieldpath.Set) *TypedValue {
return &tv
}
// NormalizeUnions takes the new object and normalizes the union:
// - If discriminator changed to non-nil, and a new field has been added
// that doesn't match, an error is returned,
// - If discriminator hasn't changed and two fields or more are set, an
// error is returned,
// - If discriminator changed to non-nil, all other fields but the
// discriminated one will be cleared,
// - Otherwise, If only one field is left, update discriminator to that value.
//
// Please note: union behavior isn't finalized yet and this is still experimental.
func (tv TypedValue) NormalizeUnions(new *TypedValue) (*TypedValue, error) {
var errs ValidationErrors
var normalizeFn = func(w *mergingWalker) {
if w.rhs != nil {
v := w.rhs.Unstructured()
w.out = &v
}
if err := normalizeUnions(w); err != nil {
errs = append(errs, errorf(err.Error())...)
}
}
out, mergeErrs := merge(&tv, new, func(w *mergingWalker) {}, normalizeFn)
if mergeErrs != nil {
errs = append(errs, mergeErrs.(ValidationErrors)...)
}
if len(errs) > 0 {
return nil, errs
}
return out, nil
}
// NormalizeUnionsApply specifically normalize unions on apply. It
// validates that the applied union is correct (there should be no
// ambiguity there), and clear the fields according to the sent intent.
//
// Please note: union behavior isn't finalized yet and this is still experimental.
func (tv TypedValue) NormalizeUnionsApply(new *TypedValue) (*TypedValue, error) {
var errs ValidationErrors
var normalizeFn = func(w *mergingWalker) {
if w.rhs != nil {
v := w.rhs.Unstructured()
w.out = &v
}
if err := normalizeUnionsApply(w); err != nil {
errs = append(errs, errorf(err.Error())...)
}
}
out, mergeErrs := merge(&tv, new, func(w *mergingWalker) {}, normalizeFn)
if mergeErrs != nil {
errs = append(errs, mergeErrs.(ValidationErrors)...)
}
if len(errs) > 0 {
return nil, errs
}
return out, nil
}
func (tv TypedValue) Empty() *TypedValue {
tv.value = value.NewValueInterface(nil)
return &tv
@ -273,50 +247,3 @@ func merge(lhs, rhs *TypedValue, rule, postRule mergeRule) (*TypedValue, error)
}
return out, nil
}
// Comparison is the return value of a TypedValue.Compare() operation.
//
// No field will appear in more than one of the three fieldsets. If all of the
// fieldsets are empty, then the objects must have been equal.
type Comparison struct {
// Removed contains any fields removed by rhs (the right-hand-side
// object in the comparison).
Removed *fieldpath.Set
// Modified contains fields present in both objects but different.
Modified *fieldpath.Set
// Added contains any fields added by rhs.
Added *fieldpath.Set
}
// IsSame returns true if the comparison returned no changes (the two
// compared objects are similar).
func (c *Comparison) IsSame() bool {
return c.Removed.Empty() && c.Modified.Empty() && c.Added.Empty()
}
// String returns a human readable version of the comparison.
func (c *Comparison) String() string {
bld := strings.Builder{}
if !c.Modified.Empty() {
bld.WriteString(fmt.Sprintf("- Modified Fields:\n%v\n", c.Modified))
}
if !c.Added.Empty() {
bld.WriteString(fmt.Sprintf("- Added Fields:\n%v\n", c.Added))
}
if !c.Removed.Empty() {
bld.WriteString(fmt.Sprintf("- Removed Fields:\n%v\n", c.Removed))
}
return bld.String()
}
// ExcludeFields fields from the compare recursively removes the fields
// from the entire comparison
func (c *Comparison) ExcludeFields(fields *fieldpath.Set) *Comparison {
if fields == nil || fields.Empty() {
return c
}
c.Removed = c.Removed.RecursiveDifference(fields)
c.Modified = c.Modified.RecursiveDifference(fields)
c.Added = c.Added.RecursiveDifference(fields)
return c
}

276
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/union.go сгенерированный поставляемый
Просмотреть файл

@ -1,276 +0,0 @@
/*
Copyright 2019 The Kubernetes 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 typed
import (
"fmt"
"strings"
"sigs.k8s.io/structured-merge-diff/v4/schema"
"sigs.k8s.io/structured-merge-diff/v4/value"
)
func normalizeUnions(w *mergingWalker) error {
atom, found := w.schema.Resolve(w.typeRef)
if !found {
panic(fmt.Sprintf("Unable to resolve schema in normalize union: %v/%v", w.schema, w.typeRef))
}
// Unions can only be in structures, and the struct must not have been removed
if atom.Map == nil || w.out == nil {
return nil
}
var old value.Map
if w.lhs != nil && !w.lhs.IsNull() {
old = w.lhs.AsMap()
}
for _, union := range atom.Map.Unions {
if err := newUnion(&union).Normalize(old, w.rhs.AsMap(), value.NewValueInterface(*w.out).AsMap()); err != nil {
return err
}
}
return nil
}
func normalizeUnionsApply(w *mergingWalker) error {
atom, found := w.schema.Resolve(w.typeRef)
if !found {
panic(fmt.Sprintf("Unable to resolve schema in normalize union: %v/%v", w.schema, w.typeRef))
}
// Unions can only be in structures, and the struct must not have been removed
if atom.Map == nil || w.out == nil {
return nil
}
var old value.Map
if w.lhs != nil && !w.lhs.IsNull() {
old = w.lhs.AsMap()
}
for _, union := range atom.Map.Unions {
out := value.NewValueInterface(*w.out)
if err := newUnion(&union).NormalizeApply(old, w.rhs.AsMap(), out.AsMap()); err != nil {
return err
}
*w.out = out.Unstructured()
}
return nil
}
type discriminated string
type field string
type discriminatedNames struct {
f2d map[field]discriminated
d2f map[discriminated]field
}
func newDiscriminatedName(f2d map[field]discriminated) discriminatedNames {
d2f := map[discriminated]field{}
for key, value := range f2d {
d2f[value] = key
}
return discriminatedNames{
f2d: f2d,
d2f: d2f,
}
}
func (dn discriminatedNames) toField(d discriminated) field {
if f, ok := dn.d2f[d]; ok {
return f
}
return field(d)
}
func (dn discriminatedNames) toDiscriminated(f field) discriminated {
if d, ok := dn.f2d[f]; ok {
return d
}
return discriminated(f)
}
type discriminator struct {
name string
}
func (d *discriminator) Set(m value.Map, v discriminated) {
if d == nil {
return
}
m.Set(d.name, value.NewValueInterface(string(v)))
}
func (d *discriminator) Get(m value.Map) discriminated {
if d == nil || m == nil {
return ""
}
val, ok := m.Get(d.name)
if !ok {
return ""
}
if !val.IsString() {
return ""
}
return discriminated(val.AsString())
}
type fieldsSet map[field]struct{}
// newFieldsSet returns a map of the fields that are part of the union and are set
// in the given map.
func newFieldsSet(m value.Map, fields []field) fieldsSet {
if m == nil {
return nil
}
set := fieldsSet{}
for _, f := range fields {
if subField, ok := m.Get(string(f)); ok && !subField.IsNull() {
set.Add(f)
}
}
return set
}
func (fs fieldsSet) Add(f field) {
if fs == nil {
fs = map[field]struct{}{}
}
fs[f] = struct{}{}
}
func (fs fieldsSet) One() *field {
for f := range fs {
return &f
}
return nil
}
func (fs fieldsSet) Has(f field) bool {
_, ok := fs[f]
return ok
}
func (fs fieldsSet) List() []field {
fields := []field{}
for f := range fs {
fields = append(fields, f)
}
return fields
}
func (fs fieldsSet) Difference(o fieldsSet) fieldsSet {
n := fieldsSet{}
for f := range fs {
if !o.Has(f) {
n.Add(f)
}
}
return n
}
func (fs fieldsSet) String() string {
s := []string{}
for k := range fs {
s = append(s, string(k))
}
return strings.Join(s, ", ")
}
type union struct {
deduceInvalidDiscriminator bool
d *discriminator
dn discriminatedNames
f []field
}
func newUnion(su *schema.Union) *union {
u := &union{}
if su.Discriminator != nil {
u.d = &discriminator{name: *su.Discriminator}
}
f2d := map[field]discriminated{}
for _, f := range su.Fields {
u.f = append(u.f, field(f.FieldName))
f2d[field(f.FieldName)] = discriminated(f.DiscriminatorValue)
}
u.dn = newDiscriminatedName(f2d)
u.deduceInvalidDiscriminator = su.DeduceInvalidDiscriminator
return u
}
// clear removes all the fields in map that are part of the union, but
// the one we decided to keep.
func (u *union) clear(m value.Map, f field) {
for _, fieldName := range u.f {
if field(fieldName) != f {
m.Delete(string(fieldName))
}
}
}
func (u *union) Normalize(old, new, out value.Map) error {
os := newFieldsSet(old, u.f)
ns := newFieldsSet(new, u.f)
diff := ns.Difference(os)
if u.d.Get(old) != u.d.Get(new) && u.d.Get(new) != "" {
if len(diff) == 1 && u.d.Get(new) != u.dn.toDiscriminated(*diff.One()) {
return fmt.Errorf("discriminator (%v) and field changed (%v) don't match", u.d.Get(new), diff.One())
}
if len(diff) > 1 {
return fmt.Errorf("multiple new fields added: %v", diff)
}
u.clear(out, u.dn.toField(u.d.Get(new)))
return nil
}
if len(ns) > 1 {
return fmt.Errorf("multiple fields set without discriminator change: %v", ns)
}
// Set discriminiator if it needs to be deduced.
if u.deduceInvalidDiscriminator && len(ns) == 1 {
u.d.Set(out, u.dn.toDiscriminated(*ns.One()))
}
return nil
}
func (u *union) NormalizeApply(applied, merged, out value.Map) error {
as := newFieldsSet(applied, u.f)
if len(as) > 1 {
return fmt.Errorf("more than one field of union applied: %v", as)
}
if len(as) == 0 {
// None is set, just leave.
return nil
}
// We have exactly one, discriminiator must match if set
if u.d.Get(applied) != "" && u.d.Get(applied) != u.dn.toDiscriminated(*as.One()) {
return fmt.Errorf("applied discriminator (%v) doesn't match applied field (%v)", u.d.Get(applied), *as.One())
}
// Update discriminiator if needed
if u.deduceInvalidDiscriminator {
u.d.Set(out, u.dn.toDiscriminated(*as.One()))
}
// Clear others fields.
u.clear(out, *as.One())
return nil
}

14
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/validate.go сгенерированный поставляемый
Просмотреть файл

@ -33,6 +33,7 @@ func (tv TypedValue) walker() *validatingObjectWalker {
v.value = tv.value
v.schema = tv.schema
v.typeRef = tv.typeRef
v.allowDuplicates = false
if v.allocator == nil {
v.allocator = value.NewFreelistAllocator()
}
@ -49,6 +50,9 @@ type validatingObjectWalker struct {
value value.Value
schema *schema.Schema
typeRef schema.TypeRef
// If set to true, duplicates will be allowed in
// associativeLists/sets.
allowDuplicates bool
// Allocate only as many walkers as needed for the depth by storing them here.
spareWalkers *[]*validatingObjectWalker
@ -102,6 +106,12 @@ func validateScalar(t *schema.Scalar, v value.Value, prefix string) (errs Valida
if !v.IsBool() {
return errorf("%vexpected boolean, got %v", prefix, v)
}
case schema.Untyped:
if !v.IsFloat() && !v.IsInt() && !v.IsString() && !v.IsBool() {
return errorf("%vexpected any scalar, got %v", prefix, v)
}
default:
return errorf("%vunexpected scalar type in schema: %v", prefix, *t)
}
return nil
}
@ -123,7 +133,7 @@ func (v *validatingObjectWalker) visitListItems(t *schema.List, list value.List)
pe.Index = &i
} else {
var err error
pe, err = listItemToPathElement(v.allocator, v.schema, t, i, child)
pe, err = listItemToPathElement(v.allocator, v.schema, t, child)
if err != nil {
errs = append(errs, errorf("element %v: %v", i, err.Error())...)
// If we can't construct the path element, we can't
@ -131,7 +141,7 @@ func (v *validatingObjectWalker) visitListItems(t *schema.List, list value.List)
// this element.
return
}
if observedKeys.Has(pe) {
if observedKeys.Has(pe) && !v.allowDuplicates {
errs = append(errs, errorf("duplicate entries for key %v", pe.String())...)
}
observedKeys.Insert(pe)

2
vendor/sigs.k8s.io/structured-merge-diff/v4/value/mapreflect.go сгенерированный поставляемый
Просмотреть файл

@ -136,7 +136,7 @@ func (r mapReflect) EqualsUsing(a Allocator, m Map) bool {
if !ok {
return false
}
return Equals(vr.mustReuse(lhsVal, entry, nil, nil), value)
return EqualsUsing(a, vr.mustReuse(lhsVal, entry, nil, nil), value)
})
}

8
vendor/sigs.k8s.io/structured-merge-diff/v4/value/mapunstructured.go сгенерированный поставляемый
Просмотреть файл

@ -88,12 +88,12 @@ func (m mapUnstructuredInterface) EqualsUsing(a Allocator, other Map) bool {
}
vv := a.allocValueUnstructured()
defer a.Free(vv)
return other.Iterate(func(key string, value Value) bool {
return other.IterateUsing(a, func(key string, value Value) bool {
lhsVal, ok := m[key]
if !ok {
return false
}
return Equals(vv.reuse(lhsVal), value)
return EqualsUsing(a, vv.reuse(lhsVal), value)
})
}
@ -168,12 +168,12 @@ func (m mapUnstructuredString) EqualsUsing(a Allocator, other Map) bool {
}
vv := a.allocValueUnstructured()
defer a.Free(vv)
return other.Iterate(func(key string, value Value) bool {
return other.IterateUsing(a, func(key string, value Value) bool {
lhsVal, ok := m[key]
if !ok {
return false
}
return Equals(vv.reuse(lhsVal), value)
return EqualsUsing(a, vv.reuse(lhsVal), value)
})
}

4
vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go сгенерированный поставляемый
Просмотреть файл

@ -154,7 +154,9 @@ func buildStructCacheEntry(t reflect.Type, infos map[string]*FieldCacheEntry, fi
if field.Type.Kind() == reflect.Ptr {
e = field.Type.Elem()
}
buildStructCacheEntry(e, infos, append(fieldPath, field.Index))
if e.Kind() == reflect.Struct {
buildStructCacheEntry(e, infos, append(fieldPath, field.Index))
}
continue
}
info := &FieldCacheEntry{JsonName: jsonName, isOmitEmpty: isOmitempty, fieldPath: append(fieldPath, field.Index), fieldType: field.Type}