Merge pull request #1377 from RainbowMango/pr_update_k8s
Update kubernetes dependencies from v1.22.2 to v1.23.4
This commit is contained in:
commit
2d48dd495c
|
@ -63,6 +63,10 @@ func NewAgentCommand(ctx context.Context) *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init log flags
|
||||||
|
// TODO(@RainbowMango): Group the flags to "logs" flag set.
|
||||||
|
klog.InitFlags(flag.CommandLine)
|
||||||
|
|
||||||
opts.AddFlags(cmd.Flags(), controllers.ControllerNames())
|
opts.AddFlags(cmd.Flags(), controllers.ControllerNames())
|
||||||
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-agent"))
|
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-agent"))
|
||||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||||
|
|
|
@ -60,6 +60,10 @@ func NewControllerManagerCommand(ctx context.Context) *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init log flags
|
||||||
|
// TODO(@RainbowMango): Group the flags to "logs" flag set.
|
||||||
|
klog.InitFlags(flag.CommandLine)
|
||||||
|
|
||||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||||
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-controller-manager"))
|
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-controller-manager"))
|
||||||
opts.AddFlags(cmd.Flags(), controllers.ControllerNames())
|
opts.AddFlags(cmd.Flags(), controllers.ControllerNames())
|
||||||
|
|
|
@ -54,6 +54,10 @@ func NewSchedulerCommand(stopChan <-chan struct{}) *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init log flags
|
||||||
|
// TODO(@RainbowMango): Group the flags to "logs" flag set.
|
||||||
|
klog.InitFlags(flag.CommandLine)
|
||||||
|
|
||||||
opts.AddFlags(cmd.Flags())
|
opts.AddFlags(cmd.Flags())
|
||||||
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-scheduler"))
|
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-scheduler"))
|
||||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||||
|
|
|
@ -53,6 +53,10 @@ func NewWebhookCommand(ctx context.Context) *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init log flags
|
||||||
|
// TODO(@RainbowMango): Group the flags to "logs" flag set.
|
||||||
|
klog.InitFlags(flag.CommandLine)
|
||||||
|
|
||||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||||
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-webhook"))
|
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-webhook"))
|
||||||
opts.AddFlags(cmd.Flags())
|
opts.AddFlags(cmd.Flags())
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,10 @@ func NewWebhookCommand(ctx context.Context) *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init log flags
|
||||||
|
// TODO(@RainbowMango): Group the flags to "logs" flag set.
|
||||||
|
klog.InitFlags(flag.CommandLine)
|
||||||
|
|
||||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||||
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-interpreter-webhook-example"))
|
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-interpreter-webhook-example"))
|
||||||
opts.AddFlags(cmd.Flags())
|
opts.AddFlags(cmd.Flags())
|
||||||
|
|
71
go.mod
71
go.mod
|
@ -8,36 +8,36 @@ require (
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/google/uuid v1.1.2
|
github.com/google/uuid v1.1.2
|
||||||
github.com/kr/pretty v0.3.0
|
github.com/kr/pretty v0.3.0
|
||||||
github.com/onsi/ginkgo v1.16.4
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/onsi/gomega v1.16.0
|
github.com/onsi/gomega v1.17.0
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
github.com/spf13/cobra v1.2.1
|
github.com/spf13/cobra v1.2.1
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/vektra/mockery/v2 v2.9.4
|
github.com/vektra/mockery/v2 v2.9.4
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
||||||
golang.org/x/tools v0.1.5
|
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff
|
||||||
gomodules.xyz/jsonpatch/v2 v2.2.0
|
gomodules.xyz/jsonpatch/v2 v2.2.0
|
||||||
google.golang.org/grpc v1.40.0
|
google.golang.org/grpc v1.40.0
|
||||||
k8s.io/api v0.22.2
|
k8s.io/api v0.23.4
|
||||||
k8s.io/apiextensions-apiserver v0.22.2
|
k8s.io/apiextensions-apiserver v0.23.4
|
||||||
k8s.io/apimachinery v0.22.2
|
k8s.io/apimachinery v0.23.4
|
||||||
k8s.io/apiserver v0.22.2
|
k8s.io/apiserver v0.23.4
|
||||||
k8s.io/cli-runtime v0.22.2
|
k8s.io/cli-runtime v0.23.4
|
||||||
k8s.io/client-go v0.22.2
|
k8s.io/client-go v0.23.4
|
||||||
k8s.io/code-generator v0.22.2
|
k8s.io/code-generator v0.23.4
|
||||||
k8s.io/component-base v0.22.2
|
k8s.io/component-base v0.23.4
|
||||||
k8s.io/component-helpers v0.22.2
|
k8s.io/component-helpers v0.23.4
|
||||||
k8s.io/klog/v2 v2.9.0
|
k8s.io/klog/v2 v2.30.0
|
||||||
k8s.io/kube-aggregator v0.22.2
|
k8s.io/kube-aggregator v0.23.4
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
|
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
||||||
k8s.io/kubectl v0.22.2
|
k8s.io/kubectl v0.23.4
|
||||||
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b
|
k8s.io/utils v0.0.0-20211116205334-6203023598ed
|
||||||
sigs.k8s.io/cluster-api v1.0.1
|
sigs.k8s.io/cluster-api v1.0.1
|
||||||
sigs.k8s.io/controller-runtime v0.10.3
|
sigs.k8s.io/controller-runtime v0.11.1
|
||||||
sigs.k8s.io/kind v0.11.1
|
sigs.k8s.io/kind v0.11.1
|
||||||
sigs.k8s.io/mcs-api v0.1.0
|
sigs.k8s.io/mcs-api v0.1.0
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.1
|
||||||
sigs.k8s.io/yaml v1.3.0
|
sigs.k8s.io/yaml v1.3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,13 +57,13 @@ require (
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||||
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
|
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||||
github.com/go-errors/errors v1.0.1 // indirect
|
github.com/go-errors/errors v1.0.1 // indirect
|
||||||
github.com/go-logr/logr v0.4.0 // indirect
|
github.com/go-logr/logr v1.2.0 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||||
github.com/go-openapi/swag v0.19.14 // indirect
|
github.com/go-openapi/swag v0.19.14 // indirect
|
||||||
|
@ -82,7 +82,7 @@ require (
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.11 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||||
github.com/magiconair/properties v1.8.5 // indirect
|
github.com/magiconair/properties v1.8.5 // indirect
|
||||||
|
@ -95,7 +95,7 @@ require (
|
||||||
github.com/moby/spdystream v0.2.0 // indirect
|
github.com/moby/spdystream v0.2.0 // indirect
|
||||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
|
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||||
|
@ -106,7 +106,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.26.0 // indirect
|
github.com/prometheus/common v0.28.0 // indirect
|
||||||
github.com/prometheus/procfs v0.6.0 // indirect
|
github.com/prometheus/procfs v0.6.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.6.1 // indirect
|
github.com/rogpeppe/go-internal v1.6.1 // indirect
|
||||||
github.com/rs/zerolog v1.18.0 // indirect
|
github.com/rs/zerolog v1.18.0 // indirect
|
||||||
|
@ -135,18 +135,18 @@ require (
|
||||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
go.uber.org/zap v1.19.0 // indirect
|
go.uber.org/zap v1.19.1 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||||
golang.org/x/mod v0.4.2 // indirect
|
golang.org/x/mod v0.4.2 // indirect
|
||||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 // indirect
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
|
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 // indirect
|
||||||
golang.org/x/text v0.3.6 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 // indirect
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.63.2 // indirect
|
gopkg.in/ini.v1 v1.63.2 // indirect
|
||||||
|
@ -154,9 +154,10 @@ require (
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
k8s.io/cluster-bootstrap v0.22.2 // indirect
|
k8s.io/cluster-bootstrap v0.23.4 // indirect
|
||||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 // indirect
|
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c // indirect
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22 // indirect
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27 // indirect
|
||||||
sigs.k8s.io/kustomize/api v0.8.11 // indirect
|
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0 // indirect
|
sigs.k8s.io/kustomize/api v0.10.1 // indirect
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
141
go.sum
141
go.sum
|
@ -93,6 +93,7 @@ github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVK
|
||||||
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
|
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
|
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
|
@ -206,8 +207,9 @@ github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMi
|
||||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
|
|
||||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
|
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
|
||||||
|
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
||||||
github.com/evanphx/json-patch/v5 v5.2.0 h1:8ozOH5xxoMYDt5/u+yMTsVXydVCbTORFnOOoq2lumco=
|
github.com/evanphx/json-patch/v5 v5.2.0 h1:8ozOH5xxoMYDt5/u+yMTsVXydVCbTORFnOOoq2lumco=
|
||||||
github.com/evanphx/json-patch/v5 v5.2.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
github.com/evanphx/json-patch/v5 v5.2.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
||||||
|
@ -229,6 +231,7 @@ github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWp
|
||||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||||
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
|
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
|
||||||
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
|
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
@ -247,11 +250,13 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||||
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
|
|
||||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||||
|
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
|
||||||
|
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
|
github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
|
||||||
github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM=
|
|
||||||
github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
|
github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
|
||||||
|
github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk=
|
||||||
|
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
|
||||||
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
|
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
|
||||||
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||||
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||||
|
@ -315,6 +320,7 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
||||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
@ -357,6 +363,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||||
|
github.com/google/cel-go v0.9.0/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w=
|
||||||
|
github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
@ -483,8 +491,9 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
|
||||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
@ -568,8 +577,9 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
@ -593,16 +603,18 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
|
||||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||||
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
|
|
||||||
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
|
github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
|
||||||
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
@ -644,8 +656,9 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
|
|
||||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||||
|
github.com/prometheus/common v0.28.0 h1:vGVfV9KrDTvWt5boZO0I19g2E3CsWfpPPKZM9dt3mEw=
|
||||||
|
github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
@ -751,6 +764,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||||
|
@ -815,15 +829,18 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
|
||||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||||
|
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
|
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||||
|
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||||
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
|
|
||||||
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||||
|
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
|
||||||
|
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
@ -867,7 +884,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
@ -933,8 +949,12 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE=
|
|
||||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
|
||||||
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -1045,13 +1065,17 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 h1:M69LAlWZCshgp0QSzyDcSsSIejIEeuaCVpmwcKwyLMk=
|
||||||
|
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||||
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -1060,8 +1084,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -1137,8 +1162,9 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff h1:VX/uD7MK0AHXGiScH3fsieUQUcpmRERPDYtqZdJnA+Q=
|
||||||
|
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@ -1218,6 +1244,7 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
|
||||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
@ -1238,8 +1265,9 @@ google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKr
|
||||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 h1:z+ErRPu0+KS02Td3fOAgdX+lnPDh/VyaABEJPD4JRQs=
|
|
||||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 h1:NHN4wOCScVzKhPenJ2dt+BTs3X/XkBVI/Rh4iDt55T8=
|
||||||
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
@ -1336,44 +1364,62 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
|
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
|
||||||
k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
|
k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
|
||||||
k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw=
|
|
||||||
k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8=
|
k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8=
|
||||||
|
k8s.io/api v0.23.0/go.mod h1:8wmDdLBHBNxtOIytwLstXt5E9PddnZb0GaMcqsvDBpg=
|
||||||
|
k8s.io/api v0.23.4 h1:85gnfXQOWbJa1SiWGpE9EEtHs0UVvDyIsSMpEtl2D4E=
|
||||||
|
k8s.io/api v0.23.4/go.mod h1:i77F4JfyNNrhOjZF7OwwNJS5Y1S9dpwvb9iYRYRczfI=
|
||||||
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
|
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
|
||||||
k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
|
k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
|
||||||
k8s.io/apiextensions-apiserver v0.22.2 h1:zK7qI8Ery7j2CaN23UCFaC1hj7dMiI87n01+nKuewd4=
|
|
||||||
k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA=
|
k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA=
|
||||||
|
k8s.io/apiextensions-apiserver v0.23.0/go.mod h1:xIFAEEDlAZgpVBl/1VSjGDmLoXAWRG40+GsWhKhAxY4=
|
||||||
|
k8s.io/apiextensions-apiserver v0.23.4 h1:AFDUEu/yEf0YnuZhqhIFhPLPhhcQQVuR1u3WCh0rveU=
|
||||||
|
k8s.io/apiextensions-apiserver v0.23.4/go.mod h1:TWYAKymJx7nLMxWCgWm2RYGXHrGlVZnxIlGnvtfYu+g=
|
||||||
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
||||||
k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
|
k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
|
||||||
k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||||
k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk=
|
|
||||||
k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||||
|
k8s.io/apimachinery v0.23.0/go.mod h1:fFCTTBKvKcwTPFzjlcxp91uPFZr+JA0FubU4fLzzFYc=
|
||||||
|
k8s.io/apimachinery v0.23.4 h1:fhnuMd/xUL3Cjfl64j5ULKZ1/J9n8NuQEgNL+WXWfdM=
|
||||||
|
k8s.io/apimachinery v0.23.4/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
|
||||||
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
|
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
|
||||||
k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
|
k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
|
||||||
k8s.io/apiserver v0.22.2 h1:TdIfZJc6YNhu2WxeAOWq1TvukHF0Sfx0+ln4XK9qnL4=
|
|
||||||
k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI=
|
k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI=
|
||||||
k8s.io/cli-runtime v0.22.2 h1:fsd9rFk9FSaVq4SUq1fM27c8CFGsYZUJ/3BkgmjYWuY=
|
k8s.io/apiserver v0.23.0/go.mod h1:Cec35u/9zAepDPPFyT+UMrgqOCjgJ5qtfVJDxjZYmt4=
|
||||||
|
k8s.io/apiserver v0.23.4 h1:zNvQlG+C/ERjuUz4p7eY/0IWHaMixRSBoxgmyIdwo9Y=
|
||||||
|
k8s.io/apiserver v0.23.4/go.mod h1:A6l/ZcNtxGfPSqbFDoxxOjEjSKBaQmE+UTveOmMkpNc=
|
||||||
k8s.io/cli-runtime v0.22.2/go.mod h1:tkm2YeORFpbgQHEK/igqttvPTRIHFRz5kATlw53zlMI=
|
k8s.io/cli-runtime v0.22.2/go.mod h1:tkm2YeORFpbgQHEK/igqttvPTRIHFRz5kATlw53zlMI=
|
||||||
|
k8s.io/cli-runtime v0.23.4 h1:C3AFQmo4TK4dlVPLOI62gtHEHu0OfA2Cp4UVRZ1JXns=
|
||||||
|
k8s.io/cli-runtime v0.23.4/go.mod h1:7KywUNTUibmHPqmpDFuRO1kc9RhsufHv2lkjCm2YZyM=
|
||||||
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
|
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
|
||||||
k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
|
k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
|
||||||
k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc=
|
|
||||||
k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U=
|
k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U=
|
||||||
k8s.io/cluster-bootstrap v0.22.2 h1:jP6Nkp3CdSfr50cAn/7WGsNS52zrwMhvr0V+E3Vkh/w=
|
k8s.io/client-go v0.23.0/go.mod h1:hrDnpnK1mSr65lHHcUuIZIXDgEbzc7/683c6hyG4jTA=
|
||||||
|
k8s.io/client-go v0.23.4 h1:YVWvPeerA2gpUudLelvsolzH7c2sFoXXR5wM/sWqNFU=
|
||||||
|
k8s.io/client-go v0.23.4/go.mod h1:PKnIL4pqLuvYUK1WU7RLTMYKPiIh7MYShLshtRY9cj0=
|
||||||
k8s.io/cluster-bootstrap v0.22.2/go.mod h1:ZkmQKprEqvrUccMnbRHISsMscA1dsQ8SffM9nHq6CgE=
|
k8s.io/cluster-bootstrap v0.22.2/go.mod h1:ZkmQKprEqvrUccMnbRHISsMscA1dsQ8SffM9nHq6CgE=
|
||||||
|
k8s.io/cluster-bootstrap v0.23.4 h1:tYz2h91tY1zcxMk3qMajcPgkixqvB4+uFrOiznlp7Fo=
|
||||||
|
k8s.io/cluster-bootstrap v0.23.4/go.mod h1:H5UZ3a4ZvjyUIgTgW8VdnN1rm3DsRqhotqK9oDMHU1o=
|
||||||
k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
||||||
k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
||||||
k8s.io/code-generator v0.22.2 h1:+bUv9lpTnAWABtPkvO4x0kfz7j/kDEchVt0P/wXU3jQ=
|
|
||||||
k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
|
k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
|
||||||
|
k8s.io/code-generator v0.23.0/go.mod h1:vQvOhDXhuzqiVfM/YHp+dmg10WDZCchJVObc9MvowsE=
|
||||||
|
k8s.io/code-generator v0.23.4 h1:MmDMH74oo8YD4r+KdUzd/VVmXUeXf5u0owLI9wZWP5Y=
|
||||||
|
k8s.io/code-generator v0.23.4/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk=
|
||||||
k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
|
k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
|
||||||
k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk=
|
k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk=
|
||||||
k8s.io/component-base v0.22.2 h1:vNIvE0AIrLhjX8drH0BgCNJcR4QZxMXcJzBsDplDx9M=
|
|
||||||
k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug=
|
k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug=
|
||||||
k8s.io/component-helpers v0.22.2 h1:guQ9oYclE5LMydWFfAFA+u7SQgQzz2g+YgpJ5QooSyY=
|
k8s.io/component-base v0.23.0/go.mod h1:DHH5uiFvLC1edCpvcTDV++NKULdYYU6pR9Tt3HIKMKI=
|
||||||
|
k8s.io/component-base v0.23.4 h1:SziYh48+QKxK+ykJ3Ejqd98XdZIseVBG7sBaNLPqy6M=
|
||||||
|
k8s.io/component-base v0.23.4/go.mod h1:8o3Gg8i2vnUXGPOwciiYlkSaZT+p+7gA9Scoz8y4W4E=
|
||||||
k8s.io/component-helpers v0.22.2/go.mod h1:+N61JAR9aKYSWbnLA88YcFr9K/6ISYvRNybX7QW7Rs8=
|
k8s.io/component-helpers v0.22.2/go.mod h1:+N61JAR9aKYSWbnLA88YcFr9K/6ISYvRNybX7QW7Rs8=
|
||||||
|
k8s.io/component-helpers v0.23.4 h1:zCLeBuo3Qs0BqtJu767RXJgs5S9ruFJZcbM1aD+cMmc=
|
||||||
|
k8s.io/component-helpers v0.23.4/go.mod h1:1Pl7L4zukZ054ElzRbvmZ1FJIU8roBXFOeRFu8zipa4=
|
||||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw=
|
|
||||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||||
|
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c h1:GohjlNKauSai7gN4wsJkeZ3WAJx4Sh+oT/b5IYn5suA=
|
||||||
|
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||||
|
@ -1381,51 +1427,68 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||||
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||||
k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM=
|
|
||||||
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
||||||
k8s.io/kube-aggregator v0.22.2 h1:7rJfpqe/VQ4dFEs2D/QwxqigsXxIcKLBkYQij/D61Yk=
|
k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
|
||||||
k8s.io/kube-aggregator v0.22.2/go.mod h1:hsd0LEmVQSvMc0UzAwmcm/Gk3HzLp50mq/o6cu1ky2A=
|
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||||
|
k8s.io/kube-aggregator v0.23.4 h1:gLk78rGLVfUXCdD14NrKg/JFBmNNCZ8FEs3tYt+W6Zk=
|
||||||
|
k8s.io/kube-aggregator v0.23.4/go.mod h1:hpmPi4oaLBe014CkBCqzBYWok64H2C7Ka6FBLJvHgkg=
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
|
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
|
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||||
k8s.io/kubectl v0.22.2 h1:KMyYNZoBshaL3XKx04X07DtpoD4vMrdkfiN/G2Qx/PU=
|
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
|
||||||
k8s.io/kubectl v0.22.2/go.mod h1:BApg2j0edxLArCOfO0ievI27EeTQqBDMNU9VQH734iQ=
|
k8s.io/kubectl v0.22.2/go.mod h1:BApg2j0edxLArCOfO0ievI27EeTQqBDMNU9VQH734iQ=
|
||||||
|
k8s.io/kubectl v0.23.4 h1:mAa+zEOlyZieecEy+xSrhjkpMcukYyHWzcNdX28dzMY=
|
||||||
|
k8s.io/kubectl v0.23.4/go.mod h1:Dgb0Rvx/8JKS/C2EuvsNiQc6RZnX0SbHJVG3XUzH6ok=
|
||||||
k8s.io/metrics v0.22.2/go.mod h1:GUcsBtpsqQD1tKFS/2wCKu4ZBowwRncLOJH1rgWs3uw=
|
k8s.io/metrics v0.22.2/go.mod h1:GUcsBtpsqQD1tKFS/2wCKu4ZBowwRncLOJH1rgWs3uw=
|
||||||
|
k8s.io/metrics v0.23.4/go.mod h1:cl6sY9BdVT3DubbpqnkPIKi6mn/F2ltkU4yH1tEJ3Bo=
|
||||||
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
|
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs=
|
|
||||||
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
|
k8s.io/utils v0.0.0-20211116205334-6203023598ed h1:ck1fRPWPJWsMd8ZRFsWc6mh/zHp5fZ/shhbrgPUxDAE=
|
||||||
|
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22 h1:fmRfl9WJ4ApJn7LxNuED4m0t18qivVQOxP6aAYG9J6c=
|
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.25/go.mod h1:Mlj9PNLmG9bZ6BHFwFKDo5afkpWyUISkb9Me0GnK66I=
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27 h1:KQOkVzXrLNb0EP6W0FD6u3CCPAwgXFYwZitbj7K0P0Y=
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27/go.mod h1:tq2nT0Kx7W+/f2JVE+zxYtUhdjuELJkVpNz+x/QN5R4=
|
||||||
sigs.k8s.io/cluster-api v1.0.1 h1:0YXQoemI4WnZF8RzT9T2vCtnXAi22rD4Fx1Tj2hhCEM=
|
sigs.k8s.io/cluster-api v1.0.1 h1:0YXQoemI4WnZF8RzT9T2vCtnXAi22rD4Fx1Tj2hhCEM=
|
||||||
sigs.k8s.io/cluster-api v1.0.1/go.mod h1:/LkJXtsvhxTV4U0z1Y2Y1Gr2xebJ0/ce09Ab2M0XU/U=
|
sigs.k8s.io/cluster-api v1.0.1/go.mod h1:/LkJXtsvhxTV4U0z1Y2Y1Gr2xebJ0/ce09Ab2M0XU/U=
|
||||||
sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
|
sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
|
||||||
sigs.k8s.io/controller-runtime v0.10.3 h1:s5Ttmw/B4AuIbwrXD3sfBkXwnPMMWrqpVj4WRt1dano=
|
|
||||||
sigs.k8s.io/controller-runtime v0.10.3/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY=
|
sigs.k8s.io/controller-runtime v0.10.3/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY=
|
||||||
|
sigs.k8s.io/controller-runtime v0.11.1 h1:7YIHT2QnHJArj/dk9aUkYhfqfK5cIxPOX5gPECfdZLU=
|
||||||
|
sigs.k8s.io/controller-runtime v0.11.1/go.mod h1:KKwLiTooNGu+JmLZGn9Sl3Gjmfj66eMbCQznLP5zcqA=
|
||||||
sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
|
sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
|
||||||
|
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s=
|
||||||
|
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
|
||||||
sigs.k8s.io/kind v0.8.1/go.mod h1:oNKTxUVPYkV9lWzY6CVMNluVq8cBsyq+UgPJdvA3uu4=
|
sigs.k8s.io/kind v0.8.1/go.mod h1:oNKTxUVPYkV9lWzY6CVMNluVq8cBsyq+UgPJdvA3uu4=
|
||||||
sigs.k8s.io/kind v0.11.1 h1:pVzOkhUwMBrCB0Q/WllQDO3v14Y+o2V0tFgjTqIUjwA=
|
sigs.k8s.io/kind v0.11.1 h1:pVzOkhUwMBrCB0Q/WllQDO3v14Y+o2V0tFgjTqIUjwA=
|
||||||
sigs.k8s.io/kind v0.11.1/go.mod h1:fRpgVhtqAWrtLB9ED7zQahUimpUXuG/iHT88xYqEGIA=
|
sigs.k8s.io/kind v0.11.1/go.mod h1:fRpgVhtqAWrtLB9ED7zQahUimpUXuG/iHT88xYqEGIA=
|
||||||
sigs.k8s.io/kustomize/api v0.8.11 h1:LzQzlq6Z023b+mBtc6v72N2mSHYmN8x7ssgbf/hv0H8=
|
|
||||||
sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g=
|
sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g=
|
||||||
|
sigs.k8s.io/kustomize/api v0.10.1 h1:KgU7hfYoscuqag84kxtzKdEC3mKMb99DPI3a0eaV1d0=
|
||||||
|
sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8=
|
||||||
sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqwEJqCKN9sSR0xSs=
|
sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqwEJqCKN9sSR0xSs=
|
||||||
|
sigs.k8s.io/kustomize/cmd/config v0.10.2/go.mod h1:K2aW7nXJ0AaT+VA/eO0/dzFLxmpFcTzudmAgDwPY1HQ=
|
||||||
sigs.k8s.io/kustomize/kustomize/v4 v4.2.0/go.mod h1:MOkR6fmhwG7hEDRXBYELTi5GSFcLwfqwzTRHW3kv5go=
|
sigs.k8s.io/kustomize/kustomize/v4 v4.2.0/go.mod h1:MOkR6fmhwG7hEDRXBYELTi5GSFcLwfqwzTRHW3kv5go=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0 h1:9KhiCPKaVyuPcgOLJXkvytOvjMJLoxpjodiycb4gHsA=
|
sigs.k8s.io/kustomize/kustomize/v4 v4.4.1/go.mod h1:qOKJMMz2mBP+vcS7vK+mNz4HBLjaQSWRY22EF6Tb7Io=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.13.0 h1:9c+ETyNfSrVhxvphs+K2dzT3dh5oVPPEqPOE/cUpScY=
|
||||||
|
sigs.k8s.io/kustomize/kyaml v0.13.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
|
||||||
sigs.k8s.io/mcs-api v0.1.0 h1:edDbg0oRGfXw8TmZjKYep06LcJLv/qcYLidejnUp0PM=
|
sigs.k8s.io/mcs-api v0.1.0 h1:edDbg0oRGfXw8TmZjKYep06LcJLv/qcYLidejnUp0PM=
|
||||||
sigs.k8s.io/mcs-api v0.1.0/go.mod h1:gGiAryeFNB4GBsq2LBmVqSgKoobLxt+p7ii/WG5QYYw=
|
sigs.k8s.io/mcs-api v0.1.0/go.mod h1:gGiAryeFNB4GBsq2LBmVqSgKoobLxt+p7ii/WG5QYYw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
|
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.0/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||||
|
|
|
@ -18,13 +18,13 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/clock"
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/retry"
|
"k8s.io/client-go/util/retry"
|
||||||
"k8s.io/component-helpers/apimachinery/lease"
|
"k8s.io/component-helpers/apimachinery/lease"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"k8s.io/utils/clock"
|
||||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||||
|
|
|
@ -4,6 +4,7 @@ package versioned
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/cluster/v1alpha1"
|
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/cluster/v1alpha1"
|
||||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/config/v1alpha1"
|
configv1alpha1 "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/typed/config/v1alpha1"
|
||||||
|
@ -71,38 +72,57 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||||
// NewForConfig creates a new Clientset for the given config.
|
// NewForConfig creates a new Clientset for the given config.
|
||||||
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||||
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||||
configShallowCopy := *c
|
configShallowCopy := *c
|
||||||
|
|
||||||
|
// share the transport between all clients
|
||||||
|
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new Clientset for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||||
|
// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
|
||||||
|
configShallowCopy := *c
|
||||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||||
if configShallowCopy.Burst <= 0 {
|
if configShallowCopy.Burst <= 0 {
|
||||||
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
||||||
}
|
}
|
||||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cs Clientset
|
var cs Clientset
|
||||||
var err error
|
var err error
|
||||||
cs.clusterV1alpha1, err = clusterv1alpha1.NewForConfig(&configShallowCopy)
|
cs.clusterV1alpha1, err = clusterv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cs.configV1alpha1, err = configv1alpha1.NewForConfig(&configShallowCopy)
|
cs.configV1alpha1, err = configv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cs.policyV1alpha1, err = policyv1alpha1.NewForConfig(&configShallowCopy)
|
cs.policyV1alpha1, err = policyv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cs.workV1alpha1, err = workv1alpha1.NewForConfig(&configShallowCopy)
|
cs.workV1alpha1, err = workv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cs.workV1alpha2, err = workv1alpha2.NewForConfig(&configShallowCopy)
|
cs.workV1alpha2, err = workv1alpha2.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -112,15 +132,11 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||||
// panics if there is an error in the config.
|
// panics if there is an error in the config.
|
||||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||||
var cs Clientset
|
cs, err := NewForConfig(c)
|
||||||
cs.clusterV1alpha1 = clusterv1alpha1.NewForConfigOrDie(c)
|
if err != nil {
|
||||||
cs.configV1alpha1 = configv1alpha1.NewForConfigOrDie(c)
|
panic(err)
|
||||||
cs.policyV1alpha1 = policyv1alpha1.NewForConfigOrDie(c)
|
}
|
||||||
cs.workV1alpha1 = workv1alpha1.NewForConfigOrDie(c)
|
return cs
|
||||||
cs.workV1alpha2 = workv1alpha2.NewForConfigOrDie(c)
|
|
||||||
|
|
||||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
|
||||||
return &cs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Clientset for the given RESTClient.
|
// New creates a new Clientset for the given RESTClient.
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
|
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
|
||||||
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
|
@ -23,12 +25,28 @@ func (c *ClusterV1alpha1Client) Clusters() ClusterInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewForConfig creates a new ClusterV1alpha1Client for the given config.
|
// NewForConfig creates a new ClusterV1alpha1Client for the given config.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
func NewForConfig(c *rest.Config) (*ClusterV1alpha1Client, error) {
|
func NewForConfig(c *rest.Config) (*ClusterV1alpha1Client, error) {
|
||||||
config := *c
|
config := *c
|
||||||
if err := setConfigDefaults(&config); err != nil {
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
client, err := rest.RESTClientFor(&config)
|
httpClient, err := rest.HTTPClientFor(&config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewForConfigAndClient(&config, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new ClusterV1alpha1Client for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ClusterV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ func (c *FakeClusters) UpdateStatus(ctx context.Context, cluster *v1alpha1.Clust
|
||||||
// Delete takes name of the cluster and deletes it. Returns an error if one occurs.
|
// Delete takes name of the cluster and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewRootDeleteAction(clustersResource, name), &v1alpha1.Cluster{})
|
Invokes(testing.NewRootDeleteActionWithOptions(clustersResource, name, opts), &v1alpha1.Cluster{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||||
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
|
@ -23,12 +25,28 @@ func (c *ConfigV1alpha1Client) ResourceInterpreterWebhookConfigurations() Resour
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewForConfig creates a new ConfigV1alpha1Client for the given config.
|
// NewForConfig creates a new ConfigV1alpha1Client for the given config.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
func NewForConfig(c *rest.Config) (*ConfigV1alpha1Client, error) {
|
func NewForConfig(c *rest.Config) (*ConfigV1alpha1Client, error) {
|
||||||
config := *c
|
config := *c
|
||||||
if err := setConfigDefaults(&config); err != nil {
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
client, err := rest.RESTClientFor(&config)
|
httpClient, err := rest.HTTPClientFor(&config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewForConfigAndClient(&config, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new ConfigV1alpha1Client for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ConfigV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ func (c *FakeResourceInterpreterWebhookConfigurations) Update(ctx context.Contex
|
||||||
// Delete takes name of the resourceInterpreterWebhookConfiguration and deletes it. Returns an error if one occurs.
|
// Delete takes name of the resourceInterpreterWebhookConfiguration and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeResourceInterpreterWebhookConfigurations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeResourceInterpreterWebhookConfigurations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewRootDeleteAction(resourceinterpreterwebhookconfigurationsResource, name), &v1alpha1.ResourceInterpreterWebhookConfiguration{})
|
Invokes(testing.NewRootDeleteActionWithOptions(resourceinterpreterwebhookconfigurationsResource, name, opts), &v1alpha1.ResourceInterpreterWebhookConfiguration{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ func (c *FakeClusterOverridePolicies) Update(ctx context.Context, clusterOverrid
|
||||||
// Delete takes name of the clusterOverridePolicy and deletes it. Returns an error if one occurs.
|
// Delete takes name of the clusterOverridePolicy and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeClusterOverridePolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeClusterOverridePolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewRootDeleteAction(clusteroverridepoliciesResource, name), &v1alpha1.ClusterOverridePolicy{})
|
Invokes(testing.NewRootDeleteActionWithOptions(clusteroverridepoliciesResource, name, opts), &v1alpha1.ClusterOverridePolicy{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ func (c *FakeClusterPropagationPolicies) Update(ctx context.Context, clusterProp
|
||||||
// Delete takes name of the clusterPropagationPolicy and deletes it. Returns an error if one occurs.
|
// Delete takes name of the clusterPropagationPolicy and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeClusterPropagationPolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeClusterPropagationPolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewRootDeleteAction(clusterpropagationpoliciesResource, name), &v1alpha1.ClusterPropagationPolicy{})
|
Invokes(testing.NewRootDeleteActionWithOptions(clusterpropagationpoliciesResource, name, opts), &v1alpha1.ClusterPropagationPolicy{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ func (c *FakeOverridePolicies) Update(ctx context.Context, overridePolicy *v1alp
|
||||||
// Delete takes name of the overridePolicy and deletes it. Returns an error if one occurs.
|
// Delete takes name of the overridePolicy and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeOverridePolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeOverridePolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewDeleteAction(overridepoliciesResource, c.ns, name), &v1alpha1.OverridePolicy{})
|
Invokes(testing.NewDeleteActionWithOptions(overridepoliciesResource, c.ns, name, opts), &v1alpha1.OverridePolicy{})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ func (c *FakePropagationPolicies) Update(ctx context.Context, propagationPolicy
|
||||||
// Delete takes name of the propagationPolicy and deletes it. Returns an error if one occurs.
|
// Delete takes name of the propagationPolicy and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakePropagationPolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakePropagationPolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewDeleteAction(propagationpoliciesResource, c.ns, name), &v1alpha1.PropagationPolicy{})
|
Invokes(testing.NewDeleteActionWithOptions(propagationpoliciesResource, c.ns, name, opts), &v1alpha1.PropagationPolicy{})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||||
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
|
@ -38,12 +40,28 @@ func (c *PolicyV1alpha1Client) PropagationPolicies(namespace string) Propagation
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewForConfig creates a new PolicyV1alpha1Client for the given config.
|
// NewForConfig creates a new PolicyV1alpha1Client for the given config.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
func NewForConfig(c *rest.Config) (*PolicyV1alpha1Client, error) {
|
func NewForConfig(c *rest.Config) (*PolicyV1alpha1Client, error) {
|
||||||
config := *c
|
config := *c
|
||||||
if err := setConfigDefaults(&config); err != nil {
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
client, err := rest.RESTClientFor(&config)
|
httpClient, err := rest.HTTPClientFor(&config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewForConfigAndClient(&config, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new PolicyV1alpha1Client for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*PolicyV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ func (c *FakeClusterResourceBindings) UpdateStatus(ctx context.Context, clusterR
|
||||||
// Delete takes name of the clusterResourceBinding and deletes it. Returns an error if one occurs.
|
// Delete takes name of the clusterResourceBinding and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeClusterResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeClusterResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewRootDeleteAction(clusterresourcebindingsResource, name), &v1alpha1.ClusterResourceBinding{})
|
Invokes(testing.NewRootDeleteActionWithOptions(clusterresourcebindingsResource, name, opts), &v1alpha1.ClusterResourceBinding{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ func (c *FakeResourceBindings) UpdateStatus(ctx context.Context, resourceBinding
|
||||||
// Delete takes name of the resourceBinding and deletes it. Returns an error if one occurs.
|
// Delete takes name of the resourceBinding and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewDeleteAction(resourcebindingsResource, c.ns, name), &v1alpha1.ResourceBinding{})
|
Invokes(testing.NewDeleteActionWithOptions(resourcebindingsResource, c.ns, name, opts), &v1alpha1.ResourceBinding{})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ func (c *FakeWorks) UpdateStatus(ctx context.Context, work *v1alpha1.Work, opts
|
||||||
// Delete takes name of the work and deletes it. Returns an error if one occurs.
|
// Delete takes name of the work and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeWorks) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeWorks) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewDeleteAction(worksResource, c.ns, name), &v1alpha1.Work{})
|
Invokes(testing.NewDeleteActionWithOptions(worksResource, c.ns, name, opts), &v1alpha1.Work{})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
|
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
|
||||||
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
|
@ -33,12 +35,28 @@ func (c *WorkV1alpha1Client) Works(namespace string) WorkInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewForConfig creates a new WorkV1alpha1Client for the given config.
|
// NewForConfig creates a new WorkV1alpha1Client for the given config.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
func NewForConfig(c *rest.Config) (*WorkV1alpha1Client, error) {
|
func NewForConfig(c *rest.Config) (*WorkV1alpha1Client, error) {
|
||||||
config := *c
|
config := *c
|
||||||
if err := setConfigDefaults(&config); err != nil {
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
client, err := rest.RESTClientFor(&config)
|
httpClient, err := rest.HTTPClientFor(&config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewForConfigAndClient(&config, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new WorkV1alpha1Client for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*WorkV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ func (c *FakeClusterResourceBindings) UpdateStatus(ctx context.Context, clusterR
|
||||||
// Delete takes name of the clusterResourceBinding and deletes it. Returns an error if one occurs.
|
// Delete takes name of the clusterResourceBinding and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeClusterResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeClusterResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewRootDeleteAction(clusterresourcebindingsResource, name), &v1alpha2.ClusterResourceBinding{})
|
Invokes(testing.NewRootDeleteActionWithOptions(clusterresourcebindingsResource, name, opts), &v1alpha2.ClusterResourceBinding{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ func (c *FakeResourceBindings) UpdateStatus(ctx context.Context, resourceBinding
|
||||||
// Delete takes name of the resourceBinding and deletes it. Returns an error if one occurs.
|
// Delete takes name of the resourceBinding and deletes it. Returns an error if one occurs.
|
||||||
func (c *FakeResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
func (c *FakeResourceBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||||
_, err := c.Fake.
|
_, err := c.Fake.
|
||||||
Invokes(testing.NewDeleteAction(resourcebindingsResource, c.ns, name), &v1alpha2.ResourceBinding{})
|
Invokes(testing.NewDeleteActionWithOptions(resourcebindingsResource, c.ns, name, opts), &v1alpha2.ResourceBinding{})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
package v1alpha2
|
package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
v1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
v1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||||
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
|
@ -28,12 +30,28 @@ func (c *WorkV1alpha2Client) ResourceBindings(namespace string) ResourceBindingI
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewForConfig creates a new WorkV1alpha2Client for the given config.
|
// NewForConfig creates a new WorkV1alpha2Client for the given config.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
func NewForConfig(c *rest.Config) (*WorkV1alpha2Client, error) {
|
func NewForConfig(c *rest.Config) (*WorkV1alpha2Client, error) {
|
||||||
config := *c
|
config := *c
|
||||||
if err := setConfigDefaults(&config); err != nil {
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
client, err := rest.RESTClientFor(&config)
|
httpClient, err := rest.HTTPClientFor(&config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewForConfigAndClient(&config, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new WorkV1alpha2Client for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*WorkV1alpha2Client, error) {
|
||||||
|
config := *c
|
||||||
|
if err := setConfigDefaults(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -107,7 +107,7 @@ func (i *CommandInitOption) makeKarmadaAPIServerDeployment() *appsv1.Deployment
|
||||||
|
|
||||||
// Probes
|
// Probes
|
||||||
livenesProbe := &corev1.Probe{
|
livenesProbe := &corev1.Probe{
|
||||||
Handler: corev1.Handler{
|
ProbeHandler: corev1.ProbeHandler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/livez",
|
Path: "/livez",
|
||||||
Port: intstr.IntOrString{
|
Port: intstr.IntOrString{
|
||||||
|
@ -122,7 +122,7 @@ func (i *CommandInitOption) makeKarmadaAPIServerDeployment() *appsv1.Deployment
|
||||||
TimeoutSeconds: 5,
|
TimeoutSeconds: 5,
|
||||||
}
|
}
|
||||||
readinesProbe := &corev1.Probe{
|
readinesProbe := &corev1.Probe{
|
||||||
Handler: corev1.Handler{
|
ProbeHandler: corev1.ProbeHandler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/readyz",
|
Path: "/readyz",
|
||||||
Port: intstr.IntOrString{
|
Port: intstr.IntOrString{
|
||||||
|
@ -609,7 +609,7 @@ func (i *CommandInitOption) makeKarmadaWebhookDeployment() *appsv1.Deployment {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ReadinessProbe: &corev1.Probe{
|
ReadinessProbe: &corev1.Probe{
|
||||||
Handler: corev1.Handler{
|
ProbeHandler: corev1.ProbeHandler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
Path: "/readyz",
|
Path: "/readyz",
|
||||||
Port: intstr.IntOrString{
|
Port: intstr.IntOrString{
|
||||||
|
|
|
@ -180,7 +180,7 @@ func (i *CommandInitOption) makeETCDStatefulSet() *appsv1.StatefulSet {
|
||||||
|
|
||||||
// Probes
|
// Probes
|
||||||
livenesProbe := &corev1.Probe{
|
livenesProbe := &corev1.Probe{
|
||||||
Handler: corev1.Handler{
|
ProbeHandler: corev1.ProbeHandler{
|
||||||
Exec: &corev1.ExecAction{
|
Exec: &corev1.ExecAction{
|
||||||
Command: []string{
|
Command: []string{
|
||||||
"/bin/sh",
|
"/bin/sh",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# editor and IDE paraphernalia
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# macOS paraphernalia
|
||||||
|
.DS_Store
|
|
@ -412,6 +412,17 @@ func (d *partialArray) set(key string, val *lazyNode) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if idx < 0 {
|
||||||
|
if !SupportNegativeIndices {
|
||||||
|
return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||||
|
}
|
||||||
|
if idx < -len(*d) {
|
||||||
|
return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||||
|
}
|
||||||
|
idx += len(*d)
|
||||||
|
}
|
||||||
|
|
||||||
(*d)[idx] = val
|
(*d)[idx] = val
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -462,6 +473,16 @@ func (d *partialArray) get(key string) (*lazyNode, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if idx < 0 {
|
||||||
|
if !SupportNegativeIndices {
|
||||||
|
return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||||
|
}
|
||||||
|
if idx < -len(*d) {
|
||||||
|
return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||||
|
}
|
||||||
|
idx += len(*d)
|
||||||
|
}
|
||||||
|
|
||||||
if idx >= len(*d) {
|
if idx >= len(*d) {
|
||||||
return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||||
}
|
}
|
||||||
|
@ -547,6 +568,29 @@ func (p Patch) replace(doc *container, op Operation) error {
|
||||||
return errors.Wrapf(err, "replace operation failed to decode path")
|
return errors.Wrapf(err, "replace operation failed to decode path")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if path == "" {
|
||||||
|
val := op.value()
|
||||||
|
|
||||||
|
if val.which == eRaw {
|
||||||
|
if !val.tryDoc() {
|
||||||
|
if !val.tryAry() {
|
||||||
|
return errors.Wrapf(err, "replace operation value must be object or array")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val.which {
|
||||||
|
case eAry:
|
||||||
|
*doc = &val.ary
|
||||||
|
case eDoc:
|
||||||
|
*doc = &val.doc
|
||||||
|
case eRaw:
|
||||||
|
return errors.Wrapf(err, "replace operation hit impossible case")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
con, key := findObject(doc, path)
|
con, key := findObject(doc, path)
|
||||||
|
|
||||||
if con == nil {
|
if con == nil {
|
||||||
|
@ -613,6 +657,25 @@ func (p Patch) test(doc *container, op Operation) error {
|
||||||
return errors.Wrapf(err, "test operation failed to decode path")
|
return errors.Wrapf(err, "test operation failed to decode path")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if path == "" {
|
||||||
|
var self lazyNode
|
||||||
|
|
||||||
|
switch sv := (*doc).(type) {
|
||||||
|
case *partialDoc:
|
||||||
|
self.doc = *sv
|
||||||
|
self.which = eDoc
|
||||||
|
case *partialArray:
|
||||||
|
self.ary = *sv
|
||||||
|
self.which = eAry
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.equal(op.value()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
|
||||||
|
}
|
||||||
|
|
||||||
con, key := findObject(doc, path)
|
con, key := findObject(doc, path)
|
||||||
|
|
||||||
if con == nil {
|
if con == nil {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
run:
|
||||||
|
timeout: 1m
|
||||||
|
tests: true
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- asciicheck
|
||||||
|
- deadcode
|
||||||
|
- errcheck
|
||||||
|
- forcetypeassert
|
||||||
|
- gocritic
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- misspell
|
||||||
|
- revive
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
- typecheck
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-use-default: false
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 10
|
|
@ -0,0 +1,6 @@
|
||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v1.0.0-rc1
|
||||||
|
|
||||||
|
This is the first logged release. Major changes (including breaking changes)
|
||||||
|
have occurred since earlier tags.
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
Logr is open to pull-requests, provided they fit within the intended scope of
|
||||||
|
the project. Specifically, this library aims to be VERY small and minimalist,
|
||||||
|
with no external dependencies.
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
This project intends to follow [semantic versioning](http://semver.org) and
|
||||||
|
is very strict about compatibility. Any proposed changes MUST follow those
|
||||||
|
rules.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
As a logging library, logr must be as light-weight as possible. Any proposed
|
||||||
|
code change must include results of running the [benchmark](./benchmark)
|
||||||
|
before and after the change.
|
|
@ -1,112 +1,182 @@
|
||||||
# A more minimal logging API for Go
|
# A minimal logging API for Go
|
||||||
|
|
||||||
|
[](https://pkg.go.dev/github.com/go-logr/logr)
|
||||||
|
|
||||||
|
logr offers an(other) opinion on how Go programs and libraries can do logging
|
||||||
|
without becoming coupled to a particular logging implementation. This is not
|
||||||
|
an implementation of logging - it is an API. In fact it is two APIs with two
|
||||||
|
different sets of users.
|
||||||
|
|
||||||
|
The `Logger` type is intended for application and library authors. It provides
|
||||||
|
a relatively small API which can be used everywhere you want to emit logs. It
|
||||||
|
defers the actual act of writing logs (to files, to stdout, or whatever) to the
|
||||||
|
`LogSink` interface.
|
||||||
|
|
||||||
|
The `LogSink` interface is intended for logging library implementers. It is a
|
||||||
|
pure interface which can be implemented by logging frameworks to provide the actual logging
|
||||||
|
functionality.
|
||||||
|
|
||||||
|
This decoupling allows application and library developers to write code in
|
||||||
|
terms of `logr.Logger` (which has very low dependency fan-out) while the
|
||||||
|
implementation of logging is managed "up stack" (e.g. in or near `main()`.)
|
||||||
|
Application developers can then switch out implementations as necessary.
|
||||||
|
|
||||||
|
Many people assert that libraries should not be logging, and as such efforts
|
||||||
|
like this are pointless. Those people are welcome to convince the authors of
|
||||||
|
the tens-of-thousands of libraries that *DO* write logs that they are all
|
||||||
|
wrong. In the meantime, logr takes a more practical approach.
|
||||||
|
|
||||||
|
## Typical usage
|
||||||
|
|
||||||
|
Somewhere, early in an application's life, it will make a decision about which
|
||||||
|
logging library (implementation) it actually wants to use. Something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
func main() {
|
||||||
|
// ... other setup code ...
|
||||||
|
|
||||||
|
// Create the "root" logger. We have chosen the "logimpl" implementation,
|
||||||
|
// which takes some initial parameters and returns a logr.Logger.
|
||||||
|
logger := logimpl.New(param1, param2)
|
||||||
|
|
||||||
|
// ... other setup code ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Most apps will call into other libraries, create structures to govern the flow,
|
||||||
|
etc. The `logr.Logger` object can be passed to these other libraries, stored
|
||||||
|
in structs, or even used as a package-global variable, if needed. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
app := createTheAppObject(logger)
|
||||||
|
app.Run()
|
||||||
|
```
|
||||||
|
|
||||||
|
Outside of this early setup, no other packages need to know about the choice of
|
||||||
|
implementation. They write logs in terms of the `logr.Logger` that they
|
||||||
|
received:
|
||||||
|
|
||||||
|
```
|
||||||
|
type appObject struct {
|
||||||
|
// ... other fields ...
|
||||||
|
logger logr.Logger
|
||||||
|
// ... other fields ...
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *appObject) Run() {
|
||||||
|
app.logger.Info("starting up", "timestamp", time.Now())
|
||||||
|
|
||||||
|
// ... app code ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
If the Go standard library had defined an interface for logging, this project
|
||||||
|
probably would not be needed. Alas, here we are.
|
||||||
|
|
||||||
|
### Inspiration
|
||||||
|
|
||||||
Before you consider this package, please read [this blog post by the
|
Before you consider this package, please read [this blog post by the
|
||||||
inimitable Dave Cheney][warning-makes-no-sense]. I really appreciate what
|
inimitable Dave Cheney][warning-makes-no-sense]. We really appreciate what
|
||||||
he has to say, and it largely aligns with my own experiences. Too many
|
he has to say, and it largely aligns with our own experiences.
|
||||||
choices of levels means inconsistent logs.
|
|
||||||
|
|
||||||
This package offers a purely abstract interface, based on these ideas but with
|
### Differences from Dave's ideas
|
||||||
a few twists. Code can depend on just this interface and have the actual
|
|
||||||
logging implementation be injected from callers. Ideally only `main()` knows
|
|
||||||
what logging implementation is being used.
|
|
||||||
|
|
||||||
# Differences from Dave's ideas
|
|
||||||
|
|
||||||
The main differences are:
|
The main differences are:
|
||||||
|
|
||||||
1) Dave basically proposes doing away with the notion of a logging API in favor
|
1. Dave basically proposes doing away with the notion of a logging API in favor
|
||||||
of `fmt.Printf()`. I disagree, especially when you consider things like output
|
of `fmt.Printf()`. We disagree, especially when you consider things like output
|
||||||
locations, timestamps, file and line decorations, and structured logging. I
|
locations, timestamps, file and line decorations, and structured logging. This
|
||||||
restrict the API to just 2 types of logs: info and error.
|
package restricts the logging API to just 2 types of logs: info and error.
|
||||||
|
|
||||||
Info logs are things you want to tell the user which are not errors. Error
|
Info logs are things you want to tell the user which are not errors. Error
|
||||||
logs are, well, errors. If your code receives an `error` from a subordinate
|
logs are, well, errors. If your code receives an `error` from a subordinate
|
||||||
function call and is logging that `error` *and not returning it*, use error
|
function call and is logging that `error` *and not returning it*, use error
|
||||||
logs.
|
logs.
|
||||||
|
|
||||||
2) Verbosity-levels on info logs. This gives developers a chance to indicate
|
2. Verbosity-levels on info logs. This gives developers a chance to indicate
|
||||||
arbitrary grades of importance for info logs, without assigning names with
|
arbitrary grades of importance for info logs, without assigning names with
|
||||||
semantic meaning such as "warning", "trace", and "debug". Superficially this
|
semantic meaning such as "warning", "trace", and "debug." Superficially this
|
||||||
may feel very similar, but the primary difference is the lack of semantics.
|
may feel very similar, but the primary difference is the lack of semantics.
|
||||||
Because verbosity is a numerical value, it's safe to assume that an app running
|
Because verbosity is a numerical value, it's safe to assume that an app running
|
||||||
with higher verbosity means more (and less important) logs will be generated.
|
with higher verbosity means more (and less important) logs will be generated.
|
||||||
|
|
||||||
This is a BETA grade API.
|
## Implementations (non-exhaustive)
|
||||||
|
|
||||||
There are implementations for the following logging libraries:
|
There are implementations for the following logging libraries:
|
||||||
|
|
||||||
|
- **a function** (can bridge to non-structured libraries): [funcr](https://github.com/go-logr/logr/tree/master/funcr)
|
||||||
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
|
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
|
||||||
- **k8s.io/klog**: [klogr](https://git.k8s.io/klog/klogr)
|
- **k8s.io/klog** (for Kubernetes): [klogr](https://git.k8s.io/klog/klogr)
|
||||||
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
|
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
|
||||||
- **log** (the Go standard library logger):
|
- **log** (the Go standard library logger): [stdr](https://github.com/go-logr/stdr)
|
||||||
[stdr](https://github.com/go-logr/stdr)
|
|
||||||
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
|
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
|
||||||
- **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
|
- **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
|
||||||
- **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
|
- **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
|
||||||
|
- **github.com/rs/zerolog**: [zerologr](https://github.com/go-logr/zerologr)
|
||||||
|
|
||||||
# FAQ
|
## FAQ
|
||||||
|
|
||||||
## Conceptual
|
### Conceptual
|
||||||
|
|
||||||
## Why structured logging?
|
#### Why structured logging?
|
||||||
|
|
||||||
- **Structured logs are more easily queriable**: Since you've got
|
- **Structured logs are more easily queryable**: Since you've got
|
||||||
key-value pairs, it's much easier to query your structured logs for
|
key-value pairs, it's much easier to query your structured logs for
|
||||||
particular values by filtering on the contents of a particular key --
|
particular values by filtering on the contents of a particular key --
|
||||||
think searching request logs for error codes, Kubernetes reconcilers for
|
think searching request logs for error codes, Kubernetes reconcilers for
|
||||||
the name and namespace of the reconciled object, etc
|
the name and namespace of the reconciled object, etc.
|
||||||
|
|
||||||
- **Structured logging makes it easier to have cross-referencable logs**:
|
- **Structured logging makes it easier to have cross-referenceable logs**:
|
||||||
Similarly to searchability, if you maintain conventions around your
|
Similarly to searchability, if you maintain conventions around your
|
||||||
keys, it becomes easy to gather all log lines related to a particular
|
keys, it becomes easy to gather all log lines related to a particular
|
||||||
concept.
|
concept.
|
||||||
|
|
||||||
- **Structured logs allow better dimensions of filtering**: if you have
|
- **Structured logs allow better dimensions of filtering**: if you have
|
||||||
structure to your logs, you've got more precise control over how much
|
structure to your logs, you've got more precise control over how much
|
||||||
information is logged -- you might choose in a particular configuration
|
information is logged -- you might choose in a particular configuration
|
||||||
to log certain keys but not others, only log lines where a certain key
|
to log certain keys but not others, only log lines where a certain key
|
||||||
matches a certain value, etc, instead of just having v-levels and names
|
matches a certain value, etc., instead of just having v-levels and names
|
||||||
to key off of.
|
to key off of.
|
||||||
|
|
||||||
- **Structured logs better represent structured data**: sometimes, the
|
- **Structured logs better represent structured data**: sometimes, the
|
||||||
data that you want to log is inherently structured (think tuple-link
|
data that you want to log is inherently structured (think tuple-link
|
||||||
objects). Structured logs allow you to preserve that structure when
|
objects.) Structured logs allow you to preserve that structure when
|
||||||
outputting.
|
outputting.
|
||||||
|
|
||||||
## Why V-levels?
|
#### Why V-levels?
|
||||||
|
|
||||||
**V-levels give operators an easy way to control the chattiness of log
|
**V-levels give operators an easy way to control the chattiness of log
|
||||||
operations**. V-levels provide a way for a given package to distinguish
|
operations**. V-levels provide a way for a given package to distinguish
|
||||||
the relative importance or verbosity of a given log message. Then, if
|
the relative importance or verbosity of a given log message. Then, if
|
||||||
a particular logger or package is logging too many messages, the user
|
a particular logger or package is logging too many messages, the user
|
||||||
of the package can simply change the v-levels for that library.
|
of the package can simply change the v-levels for that library.
|
||||||
|
|
||||||
## Why not more named levels, like Warning?
|
#### Why not named levels, like Info/Warning/Error?
|
||||||
|
|
||||||
Read [Dave Cheney's post][warning-makes-no-sense]. Then read [Differences
|
Read [Dave Cheney's post][warning-makes-no-sense]. Then read [Differences
|
||||||
from Dave's ideas](#differences-from-daves-ideas).
|
from Dave's ideas](#differences-from-daves-ideas).
|
||||||
|
|
||||||
## Why not allow format strings, too?
|
#### Why not allow format strings, too?
|
||||||
|
|
||||||
**Format strings negate many of the benefits of structured logs**:
|
**Format strings negate many of the benefits of structured logs**:
|
||||||
|
|
||||||
- They're not easily searchable without resorting to fuzzy searching,
|
- They're not easily searchable without resorting to fuzzy searching,
|
||||||
regular expressions, etc
|
regular expressions, etc.
|
||||||
|
|
||||||
- They don't store structured data well, since contents are flattened into
|
- They don't store structured data well, since contents are flattened into
|
||||||
a string
|
a string.
|
||||||
|
|
||||||
- They're not cross-referencable
|
- They're not cross-referenceable.
|
||||||
|
|
||||||
- They don't compress easily, since the message is not constant
|
- They don't compress easily, since the message is not constant.
|
||||||
|
|
||||||
(unless you turn positional parameters into key-value pairs with numerical
|
(Unless you turn positional parameters into key-value pairs with numerical
|
||||||
keys, at which point you've gotten key-value logging with meaningless
|
keys, at which point you've gotten key-value logging with meaningless
|
||||||
keys)
|
keys.)
|
||||||
|
|
||||||
## Practical
|
### Practical
|
||||||
|
|
||||||
## Why key-value pairs, and not a map?
|
#### Why key-value pairs, and not a map?
|
||||||
|
|
||||||
Key-value pairs are *much* easier to optimize, especially around
|
Key-value pairs are *much* easier to optimize, especially around
|
||||||
allocations. Zap (a structured logger that inspired logr's interface) has
|
allocations. Zap (a structured logger that inspired logr's interface) has
|
||||||
|
@ -117,26 +187,26 @@ While the interface ends up being a little less obvious, you get
|
||||||
potentially better performance, plus avoid making users type
|
potentially better performance, plus avoid making users type
|
||||||
`map[string]string{}` every time they want to log.
|
`map[string]string{}` every time they want to log.
|
||||||
|
|
||||||
## What if my V-levels differ between libraries?
|
#### What if my V-levels differ between libraries?
|
||||||
|
|
||||||
That's fine. Control your V-levels on a per-logger basis, and use the
|
That's fine. Control your V-levels on a per-logger basis, and use the
|
||||||
`WithName` function to pass different loggers to different libraries.
|
`WithName` method to pass different loggers to different libraries.
|
||||||
|
|
||||||
Generally, you should take care to ensure that you have relatively
|
Generally, you should take care to ensure that you have relatively
|
||||||
consistent V-levels within a given logger, however, as this makes deciding
|
consistent V-levels within a given logger, however, as this makes deciding
|
||||||
on what verbosity of logs to request easier.
|
on what verbosity of logs to request easier.
|
||||||
|
|
||||||
## But I *really* want to use a format string!
|
#### But I really want to use a format string!
|
||||||
|
|
||||||
That's not actually a question. Assuming your question is "how do
|
That's not actually a question. Assuming your question is "how do
|
||||||
I convert my mental model of logging with format strings to logging with
|
I convert my mental model of logging with format strings to logging with
|
||||||
constant messages":
|
constant messages":
|
||||||
|
|
||||||
1. figure out what the error actually is, as you'd write in a TL;DR style,
|
1. Figure out what the error actually is, as you'd write in a TL;DR style,
|
||||||
and use that as a message
|
and use that as a message.
|
||||||
|
|
||||||
2. For every place you'd write a format specifier, look to the word before
|
2. For every place you'd write a format specifier, look to the word before
|
||||||
it, and add that as a key value pair
|
it, and add that as a key value pair.
|
||||||
|
|
||||||
For instance, consider the following examples (all taken from spots in the
|
For instance, consider the following examples (all taken from spots in the
|
||||||
Kubernetes codebase):
|
Kubernetes codebase):
|
||||||
|
@ -150,34 +220,59 @@ Kubernetes codebase):
|
||||||
response when requesting url", "attempt", retries, "after
|
response when requesting url", "attempt", retries, "after
|
||||||
seconds", seconds, "url", url)`
|
seconds", seconds, "url", url)`
|
||||||
|
|
||||||
If you *really* must use a format string, place it as a key value, and
|
If you *really* must use a format string, use it in a key's value, and
|
||||||
call `fmt.Sprintf` yourself -- for instance, `log.Printf("unable to
|
call `fmt.Sprintf` yourself. For instance: `log.Printf("unable to
|
||||||
reflect over type %T")` becomes `logger.Info("unable to reflect over
|
reflect over type %T")` becomes `logger.Info("unable to reflect over
|
||||||
type", "type", fmt.Sprintf("%T"))`. In general though, the cases where
|
type", "type", fmt.Sprintf("%T"))`. In general though, the cases where
|
||||||
this is necessary should be few and far between.
|
this is necessary should be few and far between.
|
||||||
|
|
||||||
## How do I choose my V-levels?
|
#### How do I choose my V-levels?
|
||||||
|
|
||||||
This is basically the only hard constraint: increase V-levels to denote
|
This is basically the only hard constraint: increase V-levels to denote
|
||||||
more verbose or more debug-y logs.
|
more verbose or more debug-y logs.
|
||||||
|
|
||||||
Otherwise, you can start out with `0` as "you always want to see this",
|
Otherwise, you can start out with `0` as "you always want to see this",
|
||||||
`1` as "common logging that you might *possibly* want to turn off", and
|
`1` as "common logging that you might *possibly* want to turn off", and
|
||||||
`10` as "I would like to performance-test your log collection stack".
|
`10` as "I would like to performance-test your log collection stack."
|
||||||
|
|
||||||
Then gradually choose levels in between as you need them, working your way
|
Then gradually choose levels in between as you need them, working your way
|
||||||
down from 10 (for debug and trace style logs) and up from 1 (for chattier
|
down from 10 (for debug and trace style logs) and up from 1 (for chattier
|
||||||
info-type logs).
|
info-type logs.)
|
||||||
|
|
||||||
## How do I choose my keys
|
#### How do I choose my keys?
|
||||||
|
|
||||||
- make your keys human-readable
|
Keys are fairly flexible, and can hold more or less any string
|
||||||
- constant keys are generally a good idea
|
value. For best compatibility with implementations and consistency
|
||||||
- be consistent across your codebase
|
with existing code in other projects, there are a few conventions you
|
||||||
- keys should naturally match parts of the message string
|
should consider.
|
||||||
|
|
||||||
|
- Make your keys human-readable.
|
||||||
|
- Constant keys are generally a good idea.
|
||||||
|
- Be consistent across your codebase.
|
||||||
|
- Keys should naturally match parts of the message string.
|
||||||
|
- Use lower case for simple keys and
|
||||||
|
[lowerCamelCase](https://en.wiktionary.org/wiki/lowerCamelCase) for
|
||||||
|
more complex ones. Kubernetes is one example of a project that has
|
||||||
|
[adopted that
|
||||||
|
convention](https://github.com/kubernetes/community/blob/HEAD/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments).
|
||||||
|
|
||||||
While key names are mostly unrestricted (and spaces are acceptable),
|
While key names are mostly unrestricted (and spaces are acceptable),
|
||||||
it's generally a good idea to stick to printable ascii characters, or at
|
it's generally a good idea to stick to printable ascii characters, or at
|
||||||
least match the general character set of your log lines.
|
least match the general character set of your log lines.
|
||||||
|
|
||||||
|
#### Why should keys be constant values?
|
||||||
|
|
||||||
|
The point of structured logging is to make later log processing easier. Your
|
||||||
|
keys are, effectively, the schema of each log message. If you use different
|
||||||
|
keys across instances of the same log line, you will make your structured logs
|
||||||
|
much harder to use. `Sprintf()` is for values, not for keys!
|
||||||
|
|
||||||
|
#### Why is this not a pure interface?
|
||||||
|
|
||||||
|
The Logger type is implemented as a struct in order to allow the Go compiler to
|
||||||
|
optimize things like high-V `Info` logs that are not triggered. Not all of
|
||||||
|
these implementations are implemented yet, but this structure was suggested as
|
||||||
|
a way to ensure they *can* be implemented. All of the real work is behind the
|
||||||
|
`LogSink` interface.
|
||||||
|
|
||||||
[warning-makes-no-sense]: http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
[warning-makes-no-sense]: http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
||||||
|
|
|
@ -16,36 +16,39 @@ limitations under the License.
|
||||||
|
|
||||||
package logr
|
package logr
|
||||||
|
|
||||||
// Discard returns a valid Logger that discards all messages logged to it.
|
// Discard returns a Logger that discards all messages logged to it. It can be
|
||||||
// It can be used whenever the caller is not interested in the logs.
|
// used whenever the caller is not interested in the logs. Logger instances
|
||||||
|
// produced by this function always compare as equal.
|
||||||
func Discard() Logger {
|
func Discard() Logger {
|
||||||
return DiscardLogger{}
|
return Logger{
|
||||||
|
level: 0,
|
||||||
|
sink: discardLogSink{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscardLogger is a Logger that discards all messages.
|
// discardLogSink is a LogSink that discards all messages.
|
||||||
type DiscardLogger struct{}
|
type discardLogSink struct{}
|
||||||
|
|
||||||
func (l DiscardLogger) Enabled() bool {
|
// Verify that it actually implements the interface
|
||||||
|
var _ LogSink = discardLogSink{}
|
||||||
|
|
||||||
|
func (l discardLogSink) Init(RuntimeInfo) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l discardLogSink) Enabled(int) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l DiscardLogger) Info(msg string, keysAndValues ...interface{}) {
|
func (l discardLogSink) Info(int, string, ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l DiscardLogger) Error(err error, msg string, keysAndValues ...interface{}) {
|
func (l discardLogSink) Error(error, string, ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l DiscardLogger) V(level int) Logger {
|
func (l discardLogSink) WithValues(...interface{}) LogSink {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l DiscardLogger) WithValues(keysAndValues ...interface{}) Logger {
|
func (l discardLogSink) WithName(string) LogSink {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l DiscardLogger) WithName(name string) Logger {
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that it actually implements the interface
|
|
||||||
var _ Logger = DiscardLogger{}
|
|
||||||
|
|
|
@ -16,83 +16,101 @@ limitations under the License.
|
||||||
|
|
||||||
// This design derives from Dave Cheney's blog:
|
// This design derives from Dave Cheney's blog:
|
||||||
// http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
// http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
||||||
//
|
|
||||||
// This is a BETA grade API. Until there is a significant 2nd implementation,
|
|
||||||
// I don't really know how it will change.
|
|
||||||
|
|
||||||
// Package logr defines abstract interfaces for logging. Packages can depend on
|
// Package logr defines a general-purpose logging API and abstract interfaces
|
||||||
// these interfaces and callers can implement logging in whatever way is
|
// to back that API. Packages in the Go ecosystem can depend on this package,
|
||||||
// appropriate.
|
// while callers can implement logging with whatever backend is appropriate.
|
||||||
//
|
//
|
||||||
// Usage
|
// Usage
|
||||||
//
|
//
|
||||||
// Logging is done using a Logger. Loggers can have name prefixes and named
|
// Logging is done using a Logger instance. Logger is a concrete type with
|
||||||
// values attached, so that all log messages logged with that Logger have some
|
// methods, which defers the actual logging to a LogSink interface. The main
|
||||||
// base context associated.
|
// methods of Logger are Info() and Error(). Arguments to Info() and Error()
|
||||||
|
// are key/value pairs rather than printf-style formatted strings, emphasizing
|
||||||
|
// "structured logging".
|
||||||
//
|
//
|
||||||
// The term "key" is used to refer to the name associated with a particular
|
// With Go's standard log package, we might write:
|
||||||
// value, to disambiguate it from the general Logger name.
|
// log.Printf("setting target value %s", targetValue)
|
||||||
//
|
//
|
||||||
// For instance, suppose we're trying to reconcile the state of an object, and
|
// With logr's structured logging, we'd write:
|
||||||
// we want to log that we've made some decision.
|
// logger.Info("setting target", "value", targetValue)
|
||||||
//
|
//
|
||||||
// With the traditional log package, we might write:
|
// Errors are much the same. Instead of:
|
||||||
|
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
|
||||||
|
//
|
||||||
|
// We'd write:
|
||||||
|
// logger.Error(err, "failed to open the pod bay door", "user", user)
|
||||||
|
//
|
||||||
|
// Info() and Error() are very similar, but they are separate methods so that
|
||||||
|
// LogSink implementations can choose to do things like attach additional
|
||||||
|
// information (such as stack traces) on calls to Error().
|
||||||
|
//
|
||||||
|
// Verbosity
|
||||||
|
//
|
||||||
|
// Often we want to log information only when the application in "verbose
|
||||||
|
// mode". To write log lines that are more verbose, Logger has a V() method.
|
||||||
|
// The higher the V-level of a log line, the less critical it is considered.
|
||||||
|
// Log-lines with V-levels that are not enabled (as per the LogSink) will not
|
||||||
|
// be written. Level V(0) is the default, and logger.V(0).Info() has the same
|
||||||
|
// meaning as logger.Info(). Negative V-levels have the same meaning as V(0).
|
||||||
|
//
|
||||||
|
// Where we might have written:
|
||||||
|
// if flVerbose >= 2 {
|
||||||
|
// log.Printf("an unusual thing happened")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// We can write:
|
||||||
|
// logger.V(2).Info("an unusual thing happened")
|
||||||
|
//
|
||||||
|
// Logger Names
|
||||||
|
//
|
||||||
|
// Logger instances can have name strings so that all messages logged through
|
||||||
|
// that instance have additional context. For example, you might want to add
|
||||||
|
// a subsystem name:
|
||||||
|
//
|
||||||
|
// logger.WithName("compactor").Info("started", "time", time.Now())
|
||||||
|
//
|
||||||
|
// The WithName() method returns a new Logger, which can be passed to
|
||||||
|
// constructors or other functions for further use. Repeated use of WithName()
|
||||||
|
// will accumulate name "segments". These name segments will be joined in some
|
||||||
|
// way by the LogSink implementation. It is strongly recommended that name
|
||||||
|
// segments contain simple identifiers (letters, digits, and hyphen), and do
|
||||||
|
// not contain characters that could muddle the log output or confuse the
|
||||||
|
// joining operation (e.g. whitespace, commas, periods, slashes, brackets,
|
||||||
|
// quotes, etc).
|
||||||
|
//
|
||||||
|
// Saved Values
|
||||||
|
//
|
||||||
|
// Logger instances can store any number of key/value pairs, which will be
|
||||||
|
// logged alongside all messages logged through that instance. For example,
|
||||||
|
// you might want to create a Logger instance per managed object:
|
||||||
|
//
|
||||||
|
// With the standard log package, we might write:
|
||||||
// log.Printf("decided to set field foo to value %q for object %s/%s",
|
// log.Printf("decided to set field foo to value %q for object %s/%s",
|
||||||
// targetValue, object.Namespace, object.Name)
|
// targetValue, object.Namespace, object.Name)
|
||||||
//
|
//
|
||||||
// With logr's structured logging, we'd write:
|
// With logr we'd write:
|
||||||
// // elsewhere in the file, set up the logger to log with the prefix of
|
// // Elsewhere: set up the logger to log the object name.
|
||||||
// // "reconcilers", and the named value target-type=Foo, for extra context.
|
// obj.logger = mainLogger.WithValues(
|
||||||
// log := mainLogger.WithName("reconcilers").WithValues("target-type", "Foo")
|
// "name", obj.name, "namespace", obj.namespace)
|
||||||
//
|
//
|
||||||
// // later on...
|
// // later on...
|
||||||
// log.Info("setting foo on object", "value", targetValue, "object", object)
|
// obj.logger.Info("setting foo", "value", targetValue)
|
||||||
//
|
//
|
||||||
// Depending on our logging implementation, we could then make logging decisions
|
// Best Practices
|
||||||
// based on field values (like only logging such events for objects in a certain
|
|
||||||
// namespace), or copy the structured information into a structured log store.
|
|
||||||
//
|
//
|
||||||
// For logging errors, Logger has a method called Error. Suppose we wanted to
|
// Logger has very few hard rules, with the goal that LogSink implementations
|
||||||
// log an error while reconciling. With the traditional log package, we might
|
// might have a lot of freedom to differentiate. There are, however, some
|
||||||
// write:
|
// things to consider.
|
||||||
// log.Errorf("unable to reconcile object %s/%s: %v", object.Namespace, object.Name, err)
|
|
||||||
//
|
|
||||||
// With logr, we'd instead write:
|
|
||||||
// // assuming the above setup for log
|
|
||||||
// log.Error(err, "unable to reconcile object", "object", object)
|
|
||||||
//
|
|
||||||
// This functions similarly to:
|
|
||||||
// log.Info("unable to reconcile object", "error", err, "object", object)
|
|
||||||
//
|
|
||||||
// However, it ensures that a standard key for the error value ("error") is used
|
|
||||||
// across all error logging. Furthermore, certain implementations may choose to
|
|
||||||
// attach additional information (such as stack traces) on calls to Error, so
|
|
||||||
// it's preferred to use Error to log errors.
|
|
||||||
//
|
|
||||||
// Parts of a log line
|
|
||||||
//
|
|
||||||
// Each log message from a Logger has four types of context:
|
|
||||||
// logger name, log verbosity, log message, and the named values.
|
|
||||||
//
|
|
||||||
// The Logger name consists of a series of name "segments" added by successive
|
|
||||||
// calls to WithName. These name segments will be joined in some way by the
|
|
||||||
// underlying implementation. It is strongly recommended that name segments
|
|
||||||
// contain simple identifiers (letters, digits, and hyphen), and do not contain
|
|
||||||
// characters that could muddle the log output or confuse the joining operation
|
|
||||||
// (e.g. whitespace, commas, periods, slashes, brackets, quotes, etc).
|
|
||||||
//
|
|
||||||
// Log verbosity represents how little a log matters. Level zero, the default,
|
|
||||||
// matters most. Increasing levels matter less and less. Try to avoid lots of
|
|
||||||
// different verbosity levels, and instead provide useful keys, logger names,
|
|
||||||
// and log messages for users to filter on. It's illegal to pass a log level
|
|
||||||
// below zero.
|
|
||||||
//
|
//
|
||||||
// The log message consists of a constant message attached to the log line.
|
// The log message consists of a constant message attached to the log line.
|
||||||
// This should generally be a simple description of what's occurring, and should
|
// This should generally be a simple description of what's occurring, and should
|
||||||
// never be a format string.
|
// never be a format string. Variable information can then be attached using
|
||||||
|
// named values.
|
||||||
//
|
//
|
||||||
// Variable information can then be attached using named values (key/value
|
// Keys are arbitrary strings, but should generally be constant values. Values
|
||||||
// pairs). Keys are arbitrary strings, while values may be any Go value.
|
// may be any Go value, but how the value is formatted is determined by the
|
||||||
|
// LogSink implementation.
|
||||||
//
|
//
|
||||||
// Key Naming Conventions
|
// Key Naming Conventions
|
||||||
//
|
//
|
||||||
|
@ -102,6 +120,7 @@ limitations under the License.
|
||||||
// * be constant (not dependent on input data)
|
// * be constant (not dependent on input data)
|
||||||
// * contain only printable characters
|
// * contain only printable characters
|
||||||
// * not contain whitespace or punctuation
|
// * not contain whitespace or punctuation
|
||||||
|
// * use lower case for simple keys and lowerCamelCase for more complex ones
|
||||||
//
|
//
|
||||||
// These guidelines help ensure that log data is processed properly regardless
|
// These guidelines help ensure that log data is processed properly regardless
|
||||||
// of the log implementation. For example, log implementations will try to
|
// of the log implementation. For example, log implementations will try to
|
||||||
|
@ -110,21 +129,22 @@ limitations under the License.
|
||||||
// While users are generally free to use key names of their choice, it's
|
// While users are generally free to use key names of their choice, it's
|
||||||
// generally best to avoid using the following keys, as they're frequently used
|
// generally best to avoid using the following keys, as they're frequently used
|
||||||
// by implementations:
|
// by implementations:
|
||||||
//
|
// * "caller": the calling information (file/line) of a particular log line
|
||||||
// * `"caller"`: the calling information (file/line) of a particular log line.
|
// * "error": the underlying error value in the `Error` method
|
||||||
// * `"error"`: the underlying error value in the `Error` method.
|
// * "level": the log level
|
||||||
// * `"level"`: the log level.
|
// * "logger": the name of the associated logger
|
||||||
// * `"logger"`: the name of the associated logger.
|
// * "msg": the log message
|
||||||
// * `"msg"`: the log message.
|
// * "stacktrace": the stack trace associated with a particular log line or
|
||||||
// * `"stacktrace"`: the stack trace associated with a particular log line or
|
// error (often from the `Error` message)
|
||||||
// error (often from the `Error` message).
|
// * "ts": the timestamp for a log line
|
||||||
// * `"ts"`: the timestamp for a log line.
|
|
||||||
//
|
//
|
||||||
// Implementations are encouraged to make use of these keys to represent the
|
// Implementations are encouraged to make use of these keys to represent the
|
||||||
// above concepts, when necessary (for example, in a pure-JSON output form, it
|
// above concepts, when necessary (for example, in a pure-JSON output form, it
|
||||||
// would be necessary to represent at least message and timestamp as ordinary
|
// would be necessary to represent at least message and timestamp as ordinary
|
||||||
// named values).
|
// named values).
|
||||||
//
|
//
|
||||||
|
// Break Glass
|
||||||
|
//
|
||||||
// Implementations may choose to give callers access to the underlying
|
// Implementations may choose to give callers access to the underlying
|
||||||
// logging implementation. The recommended pattern for this is:
|
// logging implementation. The recommended pattern for this is:
|
||||||
// // Underlier exposes access to the underlying logging implementation.
|
// // Underlier exposes access to the underlying logging implementation.
|
||||||
|
@ -134,81 +154,220 @@ limitations under the License.
|
||||||
// type Underlier interface {
|
// type Underlier interface {
|
||||||
// GetUnderlying() <underlying-type>
|
// GetUnderlying() <underlying-type>
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// Logger grants access to the sink to enable type assertions like this:
|
||||||
|
// func DoSomethingWithImpl(log logr.Logger) {
|
||||||
|
// if underlier, ok := log.GetSink()(impl.Underlier) {
|
||||||
|
// implLogger := underlier.GetUnderlying()
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Custom `With*` functions can be implemented by copying the complete
|
||||||
|
// Logger struct and replacing the sink in the copy:
|
||||||
|
// // WithFooBar changes the foobar parameter in the log sink and returns a
|
||||||
|
// // new logger with that modified sink. It does nothing for loggers where
|
||||||
|
// // the sink doesn't support that parameter.
|
||||||
|
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
|
||||||
|
// if foobarLogSink, ok := log.GetSink()(FoobarSink); ok {
|
||||||
|
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
|
||||||
|
// }
|
||||||
|
// return log
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Don't use New to construct a new Logger with a LogSink retrieved from an
|
||||||
|
// existing Logger. Source code attribution might not work correctly and
|
||||||
|
// unexported fields in Logger get lost.
|
||||||
|
//
|
||||||
|
// Beware that the same LogSink instance may be shared by different logger
|
||||||
|
// instances. Calling functions that modify the LogSink will affect all of
|
||||||
|
// those.
|
||||||
package logr
|
package logr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: consider adding back in format strings if they're really needed
|
// New returns a new Logger instance. This is primarily used by libraries
|
||||||
// TODO: consider other bits of zap/zapcore functionality like ObjectMarshaller (for arbitrary objects)
|
// implementing LogSink, rather than end users.
|
||||||
// TODO: consider other bits of glog functionality like Flush, OutputStats
|
func New(sink LogSink) Logger {
|
||||||
|
logger := Logger{}
|
||||||
// Logger represents the ability to log messages, both errors and not.
|
logger.setSink(sink)
|
||||||
type Logger interface {
|
sink.Init(runtimeInfo)
|
||||||
// Enabled tests whether this Logger is enabled. For example, commandline
|
return logger
|
||||||
// flags might be used to set the logging verbosity and disable some info
|
|
||||||
// logs.
|
|
||||||
Enabled() bool
|
|
||||||
|
|
||||||
// Info logs a non-error message with the given key/value pairs as context.
|
|
||||||
//
|
|
||||||
// The msg argument should be used to add some constant description to
|
|
||||||
// the log line. The key/value pairs can then be used to add additional
|
|
||||||
// variable information. The key/value pairs should alternate string
|
|
||||||
// keys and arbitrary values.
|
|
||||||
Info(msg string, keysAndValues ...interface{})
|
|
||||||
|
|
||||||
// Error logs an error, with the given message and key/value pairs as context.
|
|
||||||
// It functions similarly to calling Info with the "error" named value, but may
|
|
||||||
// have unique behavior, and should be preferred for logging errors (see the
|
|
||||||
// package documentations for more information).
|
|
||||||
//
|
|
||||||
// The msg field should be used to add context to any underlying error,
|
|
||||||
// while the err field should be used to attach the actual error that
|
|
||||||
// triggered this log line, if present.
|
|
||||||
Error(err error, msg string, keysAndValues ...interface{})
|
|
||||||
|
|
||||||
// V returns an Logger value for a specific verbosity level, relative to
|
|
||||||
// this Logger. In other words, V values are additive. V higher verbosity
|
|
||||||
// level means a log message is less important. It's illegal to pass a log
|
|
||||||
// level less than zero.
|
|
||||||
V(level int) Logger
|
|
||||||
|
|
||||||
// WithValues adds some key-value pairs of context to a logger.
|
|
||||||
// See Info for documentation on how key/value pairs work.
|
|
||||||
WithValues(keysAndValues ...interface{}) Logger
|
|
||||||
|
|
||||||
// WithName adds a new element to the logger's name.
|
|
||||||
// Successive calls with WithName continue to append
|
|
||||||
// suffixes to the logger's name. It's strongly recommended
|
|
||||||
// that name segments contain only letters, digits, and hyphens
|
|
||||||
// (see the package documentation for more information).
|
|
||||||
WithName(name string) Logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InfoLogger provides compatibility with code that relies on the v0.1.0
|
// setSink stores the sink and updates any related fields. It mutates the
|
||||||
// interface.
|
// logger and thus is only safe to use for loggers that are not currently being
|
||||||
//
|
// used concurrently.
|
||||||
// Deprecated: InfoLogger is an artifact of early versions of this API. New
|
func (l *Logger) setSink(sink LogSink) {
|
||||||
// users should never use it and existing users should use Logger instead. This
|
l.sink = sink
|
||||||
// will be removed in a future release.
|
}
|
||||||
type InfoLogger = Logger
|
|
||||||
|
|
||||||
|
// GetSink returns the stored sink.
|
||||||
|
func (l Logger) GetSink() LogSink {
|
||||||
|
return l.sink
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSink returns a copy of the logger with the new sink.
|
||||||
|
func (l Logger) WithSink(sink LogSink) Logger {
|
||||||
|
l.setSink(sink)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logger is an interface to an abstract logging implementation. This is a
|
||||||
|
// concrete type for performance reasons, but all the real work is passed on to
|
||||||
|
// a LogSink. Implementations of LogSink should provide their own constructors
|
||||||
|
// that return Logger, not LogSink.
|
||||||
|
//
|
||||||
|
// The underlying sink can be accessed through GetSink and be modified through
|
||||||
|
// WithSink. This enables the implementation of custom extensions (see "Break
|
||||||
|
// Glass" in the package documentation). Normally the sink should be used only
|
||||||
|
// indirectly.
|
||||||
|
type Logger struct {
|
||||||
|
sink LogSink
|
||||||
|
level int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabled tests whether this Logger is enabled. For example, commandline
|
||||||
|
// flags might be used to set the logging verbosity and disable some info logs.
|
||||||
|
func (l Logger) Enabled() bool {
|
||||||
|
return l.sink.Enabled(l.level)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info logs a non-error message with the given key/value pairs as context.
|
||||||
|
//
|
||||||
|
// The msg argument should be used to add some constant description to the log
|
||||||
|
// line. The key/value pairs can then be used to add additional variable
|
||||||
|
// information. The key/value pairs must alternate string keys and arbitrary
|
||||||
|
// values.
|
||||||
|
func (l Logger) Info(msg string, keysAndValues ...interface{}) {
|
||||||
|
if l.Enabled() {
|
||||||
|
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||||
|
withHelper.GetCallStackHelper()()
|
||||||
|
}
|
||||||
|
l.sink.Info(l.level, msg, keysAndValues...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error logs an error, with the given message and key/value pairs as context.
|
||||||
|
// It functions similarly to Info, but may have unique behavior, and should be
|
||||||
|
// preferred for logging errors (see the package documentations for more
|
||||||
|
// information).
|
||||||
|
//
|
||||||
|
// The msg argument should be used to add context to any underlying error,
|
||||||
|
// while the err argument should be used to attach the actual error that
|
||||||
|
// triggered this log line, if present.
|
||||||
|
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||||
|
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||||
|
withHelper.GetCallStackHelper()()
|
||||||
|
}
|
||||||
|
l.sink.Error(err, msg, keysAndValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// V returns a new Logger instance for a specific verbosity level, relative to
|
||||||
|
// this Logger. In other words, V-levels are additive. A higher verbosity
|
||||||
|
// level means a log message is less important. Negative V-levels are treated
|
||||||
|
// as 0.
|
||||||
|
func (l Logger) V(level int) Logger {
|
||||||
|
if level < 0 {
|
||||||
|
level = 0
|
||||||
|
}
|
||||||
|
l.level += level
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithValues returns a new Logger instance with additional key/value pairs.
|
||||||
|
// See Info for documentation on how key/value pairs work.
|
||||||
|
func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
|
||||||
|
l.setSink(l.sink.WithValues(keysAndValues...))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithName returns a new Logger instance with the specified name element added
|
||||||
|
// to the Logger's name. Successive calls with WithName append additional
|
||||||
|
// suffixes to the Logger's name. It's strongly recommended that name segments
|
||||||
|
// contain only letters, digits, and hyphens (see the package documentation for
|
||||||
|
// more information).
|
||||||
|
func (l Logger) WithName(name string) Logger {
|
||||||
|
l.setSink(l.sink.WithName(name))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCallDepth returns a Logger instance that offsets the call stack by the
|
||||||
|
// specified number of frames when logging call site information, if possible.
|
||||||
|
// This is useful for users who have helper functions between the "real" call
|
||||||
|
// site and the actual calls to Logger methods. If depth is 0 the attribution
|
||||||
|
// should be to the direct caller of this function. If depth is 1 the
|
||||||
|
// attribution should skip 1 call frame, and so on. Successive calls to this
|
||||||
|
// are additive.
|
||||||
|
//
|
||||||
|
// If the underlying log implementation supports a WithCallDepth(int) method,
|
||||||
|
// it will be called and the result returned. If the implementation does not
|
||||||
|
// support CallDepthLogSink, the original Logger will be returned.
|
||||||
|
//
|
||||||
|
// To skip one level, WithCallStackHelper() should be used instead of
|
||||||
|
// WithCallDepth(1) because it works with implementions that support the
|
||||||
|
// CallDepthLogSink and/or CallStackHelperLogSink interfaces.
|
||||||
|
func (l Logger) WithCallDepth(depth int) Logger {
|
||||||
|
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
|
||||||
|
l.setSink(withCallDepth.WithCallDepth(depth))
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCallStackHelper returns a new Logger instance that skips the direct
|
||||||
|
// caller when logging call site information, if possible. This is useful for
|
||||||
|
// users who have helper functions between the "real" call site and the actual
|
||||||
|
// calls to Logger methods and want to support loggers which depend on marking
|
||||||
|
// each individual helper function, like loggers based on testing.T.
|
||||||
|
//
|
||||||
|
// In addition to using that new logger instance, callers also must call the
|
||||||
|
// returned function.
|
||||||
|
//
|
||||||
|
// If the underlying log implementation supports a WithCallDepth(int) method,
|
||||||
|
// WithCallDepth(1) will be called to produce a new logger. If it supports a
|
||||||
|
// WithCallStackHelper() method, that will be also called. If the
|
||||||
|
// implementation does not support either of these, the original Logger will be
|
||||||
|
// returned.
|
||||||
|
func (l Logger) WithCallStackHelper() (func(), Logger) {
|
||||||
|
var helper func()
|
||||||
|
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
|
||||||
|
l.setSink(withCallDepth.WithCallDepth(1))
|
||||||
|
}
|
||||||
|
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||||
|
helper = withHelper.GetCallStackHelper()
|
||||||
|
} else {
|
||||||
|
helper = func() {}
|
||||||
|
}
|
||||||
|
return helper, l
|
||||||
|
}
|
||||||
|
|
||||||
|
// contextKey is how we find Loggers in a context.Context.
|
||||||
type contextKey struct{}
|
type contextKey struct{}
|
||||||
|
|
||||||
// FromContext returns a Logger constructed from ctx or nil if no
|
// FromContext returns a Logger from ctx or an error if no Logger is found.
|
||||||
// logger details are found.
|
func FromContext(ctx context.Context) (Logger, error) {
|
||||||
func FromContext(ctx context.Context) Logger {
|
|
||||||
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
||||||
return v
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return Logger{}, notFoundError{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromContextOrDiscard returns a Logger constructed from ctx or a Logger
|
// notFoundError exists to carry an IsNotFound method.
|
||||||
// that discards all messages if no logger details are found.
|
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 {
|
func FromContextOrDiscard(ctx context.Context) Logger {
|
||||||
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
||||||
return v
|
return v
|
||||||
|
@ -217,12 +376,59 @@ func FromContextOrDiscard(ctx context.Context) Logger {
|
||||||
return Discard()
|
return Discard()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext returns a new context derived from ctx that embeds the Logger.
|
// NewContext returns a new Context, derived from ctx, which carries the
|
||||||
func NewContext(ctx context.Context, l Logger) context.Context {
|
// provided Logger.
|
||||||
return context.WithValue(ctx, contextKey{}, l)
|
func NewContext(ctx context.Context, logger Logger) context.Context {
|
||||||
|
return context.WithValue(ctx, contextKey{}, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallDepthLogger represents a Logger that knows how to climb the call stack
|
// RuntimeInfo holds information that the logr "core" library knows which
|
||||||
|
// LogSinks might want to know.
|
||||||
|
type RuntimeInfo struct {
|
||||||
|
// CallDepth is the number of call frames the logr library adds between the
|
||||||
|
// end-user and the LogSink. LogSink implementations which choose to print
|
||||||
|
// the original logging site (e.g. file & line) should climb this many
|
||||||
|
// additional frames to find it.
|
||||||
|
CallDepth int
|
||||||
|
}
|
||||||
|
|
||||||
|
// runtimeInfo is a static global. It must not be changed at run time.
|
||||||
|
var runtimeInfo = RuntimeInfo{
|
||||||
|
CallDepth: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogSink represents a logging implementation. End-users will generally not
|
||||||
|
// interact with this type.
|
||||||
|
type LogSink interface {
|
||||||
|
// Init receives optional information about the logr library for LogSink
|
||||||
|
// implementations that need it.
|
||||||
|
Init(info RuntimeInfo)
|
||||||
|
|
||||||
|
// Enabled tests whether this LogSink is enabled at the specified V-level.
|
||||||
|
// For example, commandline flags might be used to set the logging
|
||||||
|
// verbosity and disable some info logs.
|
||||||
|
Enabled(level int) bool
|
||||||
|
|
||||||
|
// Info logs a non-error message with the given key/value pairs as context.
|
||||||
|
// The level argument is provided for optional logging. This method will
|
||||||
|
// only be called when Enabled(level) is true. See Logger.Info for more
|
||||||
|
// details.
|
||||||
|
Info(level int, msg string, keysAndValues ...interface{})
|
||||||
|
|
||||||
|
// Error logs an error, with the given message and key/value pairs as
|
||||||
|
// context. See Logger.Error for more details.
|
||||||
|
Error(err error, msg string, keysAndValues ...interface{})
|
||||||
|
|
||||||
|
// WithValues returns a new LogSink with additional key/value pairs. See
|
||||||
|
// Logger.WithValues for more details.
|
||||||
|
WithValues(keysAndValues ...interface{}) LogSink
|
||||||
|
|
||||||
|
// WithName returns a new LogSink with the specified name appended. See
|
||||||
|
// Logger.WithName for more details.
|
||||||
|
WithName(name string) LogSink
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallDepthLogSink represents a Logger that knows how to climb the call stack
|
||||||
// to identify the original call site and can offset the depth by a specified
|
// to identify the original call site and can offset the depth by a specified
|
||||||
// number of frames. This is useful for users who have helper functions
|
// number of frames. This is useful for users who have helper functions
|
||||||
// between the "real" call site and the actual calls to Logger methods.
|
// between the "real" call site and the actual calls to Logger methods.
|
||||||
|
@ -232,35 +438,59 @@ func NewContext(ctx context.Context, l Logger) context.Context {
|
||||||
//
|
//
|
||||||
// This is an optional interface and implementations are not required to
|
// This is an optional interface and implementations are not required to
|
||||||
// support it.
|
// support it.
|
||||||
type CallDepthLogger interface {
|
type CallDepthLogSink interface {
|
||||||
Logger
|
// WithCallDepth returns a LogSink that will offset the call
|
||||||
|
// stack by the specified number of frames when logging call
|
||||||
// WithCallDepth returns a Logger that will offset the call stack by the
|
// site information.
|
||||||
// specified number of frames when logging call site information. If depth
|
//
|
||||||
// is 0 the attribution should be to the direct caller of this method. If
|
// If depth is 0, the LogSink should skip exactly the number
|
||||||
// depth is 1 the attribution should skip 1 call frame, and so on.
|
// of call frames defined in RuntimeInfo.CallDepth when Info
|
||||||
|
// or Error are called, i.e. the attribution should be to the
|
||||||
|
// direct caller of Logger.Info or Logger.Error.
|
||||||
|
//
|
||||||
|
// If depth is 1 the attribution should skip 1 call frame, and so on.
|
||||||
// Successive calls to this are additive.
|
// Successive calls to this are additive.
|
||||||
WithCallDepth(depth int) Logger
|
WithCallDepth(depth int) LogSink
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithCallDepth returns a Logger that will offset the call stack by the
|
// CallStackHelperLogSink represents a Logger that knows how to climb
|
||||||
// specified number of frames when logging call site information, if possible.
|
// the call stack to identify the original call site and can skip
|
||||||
// This is useful for users who have helper functions between the "real" call
|
// intermediate helper functions if they mark themselves as
|
||||||
// site and the actual calls to Logger methods. If depth is 0 the attribution
|
// helper. Go's testing package uses that approach.
|
||||||
// should be to the direct caller of this function. If depth is 1 the
|
|
||||||
// attribution should skip 1 call frame, and so on. Successive calls to this
|
|
||||||
// are additive.
|
|
||||||
//
|
//
|
||||||
// If the underlying log implementation supports the CallDepthLogger interface,
|
// This is useful for users who have helper functions between the
|
||||||
// the WithCallDepth method will be called and the result returned. If the
|
// "real" call site and the actual calls to Logger methods.
|
||||||
// implementation does not support CallDepthLogger, the original Logger will be
|
// Implementations that log information about the call site (such as
|
||||||
// returned.
|
// file, function, or line) would otherwise log information about the
|
||||||
|
// intermediate helper functions.
|
||||||
//
|
//
|
||||||
// Callers which care about whether this was supported or not should test for
|
// This is an optional interface and implementations are not required
|
||||||
// CallDepthLogger support themselves.
|
// to support it. Implementations that choose to support this must not
|
||||||
func WithCallDepth(logger Logger, depth int) Logger {
|
// simply implement it as WithCallDepth(1), because
|
||||||
if decorator, ok := logger.(CallDepthLogger); ok {
|
// Logger.WithCallStackHelper will call both methods if they are
|
||||||
return decorator.WithCallDepth(depth)
|
// present. This should only be implemented for LogSinks that actually
|
||||||
}
|
// need it, as with testing.T.
|
||||||
return logger
|
type CallStackHelperLogSink interface {
|
||||||
|
// GetCallStackHelper returns a function that must be called
|
||||||
|
// to mark the direct caller as helper function when logging
|
||||||
|
// call site information.
|
||||||
|
GetCallStackHelper() func()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshaler is an optional interface that logged values may choose to
|
||||||
|
// implement. Loggers with structured output, such as JSON, should
|
||||||
|
// log the object return by the MarshalLog method instead of the
|
||||||
|
// original value.
|
||||||
|
type Marshaler interface {
|
||||||
|
// MarshalLog can be used to:
|
||||||
|
// - ensure that structs are not logged as strings when the original
|
||||||
|
// value has a String method: return a different type without a
|
||||||
|
// String method
|
||||||
|
// - select which fields of a complex type should get logged:
|
||||||
|
// return a simpler struct with fewer fields
|
||||||
|
// - log unexported fields: return a different struct
|
||||||
|
// with exported fields
|
||||||
|
//
|
||||||
|
// It may return any value of any type.
|
||||||
|
MarshalLog() interface{}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,670 @@
|
||||||
|
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package openapi.v3;
|
||||||
|
|
||||||
|
import "google/protobuf/any.proto";
|
||||||
|
|
||||||
|
// This option lets the proto compiler generate Java code inside the package
|
||||||
|
// name (see below) instead of inside an outer class. It creates a simpler
|
||||||
|
// developer experience by reducing one-level of name nesting and be
|
||||||
|
// consistent with most programming languages that don't support outer classes.
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
// The Java outer classname should be the filename in UpperCamelCase. This
|
||||||
|
// class is only used to hold proto descriptor, so developers don't need to
|
||||||
|
// work with it directly.
|
||||||
|
option java_outer_classname = "OpenAPIProto";
|
||||||
|
|
||||||
|
// The Java package name must be proto package name with proper prefix.
|
||||||
|
option java_package = "org.openapi_v3";
|
||||||
|
|
||||||
|
// A reasonable prefix for the Objective-C symbols generated from the package.
|
||||||
|
// It should at a minimum be 3 characters long, all uppercase, and convention
|
||||||
|
// is to use an abbreviation of the package name. Something short, but
|
||||||
|
// hopefully unique enough to not conflict with things that may come along in
|
||||||
|
// the future. 'GPB' is reserved for the protocol buffer implementation itself.
|
||||||
|
option objc_class_prefix = "OAS";
|
||||||
|
|
||||||
|
// The Go package name.
|
||||||
|
option go_package = "./openapiv3;openapi_v3";
|
||||||
|
|
||||||
|
message AdditionalPropertiesItem {
|
||||||
|
oneof oneof {
|
||||||
|
SchemaOrReference schema_or_reference = 1;
|
||||||
|
bool boolean = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Any {
|
||||||
|
google.protobuf.Any value = 1;
|
||||||
|
string yaml = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AnyOrExpression {
|
||||||
|
oneof oneof {
|
||||||
|
Any any = 1;
|
||||||
|
Expression expression = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A map of possible out-of band callbacks related to the parent operation. Each value in the map is a Path Item Object that describes a set of requests that may be initiated by the API provider and the expected responses. The key value used to identify the callback object is an expression, evaluated at runtime, that identifies a URL to use for the callback operation.
|
||||||
|
message Callback {
|
||||||
|
repeated NamedPathItem path = 1;
|
||||||
|
repeated NamedAny specification_extension = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CallbackOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
Callback callback = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message CallbacksOrReferences {
|
||||||
|
repeated NamedCallbackOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Holds a set of reusable objects for different aspects of the OAS. All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object.
|
||||||
|
message Components {
|
||||||
|
SchemasOrReferences schemas = 1;
|
||||||
|
ResponsesOrReferences responses = 2;
|
||||||
|
ParametersOrReferences parameters = 3;
|
||||||
|
ExamplesOrReferences examples = 4;
|
||||||
|
RequestBodiesOrReferences request_bodies = 5;
|
||||||
|
HeadersOrReferences headers = 6;
|
||||||
|
SecuritySchemesOrReferences security_schemes = 7;
|
||||||
|
LinksOrReferences links = 8;
|
||||||
|
CallbacksOrReferences callbacks = 9;
|
||||||
|
repeated NamedAny specification_extension = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contact information for the exposed API.
|
||||||
|
message Contact {
|
||||||
|
string name = 1;
|
||||||
|
string url = 2;
|
||||||
|
string email = 3;
|
||||||
|
repeated NamedAny specification_extension = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DefaultType {
|
||||||
|
oneof oneof {
|
||||||
|
double number = 1;
|
||||||
|
bool boolean = 2;
|
||||||
|
string string = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When request bodies or response payloads may be one of a number of different schemas, a `discriminator` object can be used to aid in serialization, deserialization, and validation. The discriminator is a specific object in a schema which is used to inform the consumer of the specification of an alternative schema based on the value associated with it. When using the discriminator, _inline_ schemas will not be considered.
|
||||||
|
message Discriminator {
|
||||||
|
string property_name = 1;
|
||||||
|
Strings mapping = 2;
|
||||||
|
repeated NamedAny specification_extension = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Document {
|
||||||
|
string openapi = 1;
|
||||||
|
Info info = 2;
|
||||||
|
repeated Server servers = 3;
|
||||||
|
Paths paths = 4;
|
||||||
|
Components components = 5;
|
||||||
|
repeated SecurityRequirement security = 6;
|
||||||
|
repeated Tag tags = 7;
|
||||||
|
ExternalDocs external_docs = 8;
|
||||||
|
repeated NamedAny specification_extension = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A single encoding definition applied to a single schema property.
|
||||||
|
message Encoding {
|
||||||
|
string content_type = 1;
|
||||||
|
HeadersOrReferences headers = 2;
|
||||||
|
string style = 3;
|
||||||
|
bool explode = 4;
|
||||||
|
bool allow_reserved = 5;
|
||||||
|
repeated NamedAny specification_extension = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Encodings {
|
||||||
|
repeated NamedEncoding additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Example {
|
||||||
|
string summary = 1;
|
||||||
|
string description = 2;
|
||||||
|
Any value = 3;
|
||||||
|
string external_value = 4;
|
||||||
|
repeated NamedAny specification_extension = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExampleOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
Example example = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExamplesOrReferences {
|
||||||
|
repeated NamedExampleOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Expression {
|
||||||
|
repeated NamedAny additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allows referencing an external resource for extended documentation.
|
||||||
|
message ExternalDocs {
|
||||||
|
string description = 1;
|
||||||
|
string url = 2;
|
||||||
|
repeated NamedAny specification_extension = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Header Object follows the structure of the Parameter Object with the following changes: 1. `name` MUST NOT be specified, it is given in the corresponding `headers` map. 1. `in` MUST NOT be specified, it is implicitly in `header`. 1. All traits that are affected by the location MUST be applicable to a location of `header` (for example, `style`).
|
||||||
|
message Header {
|
||||||
|
string description = 1;
|
||||||
|
bool required = 2;
|
||||||
|
bool deprecated = 3;
|
||||||
|
bool allow_empty_value = 4;
|
||||||
|
string style = 5;
|
||||||
|
bool explode = 6;
|
||||||
|
bool allow_reserved = 7;
|
||||||
|
SchemaOrReference schema = 8;
|
||||||
|
Any example = 9;
|
||||||
|
ExamplesOrReferences examples = 10;
|
||||||
|
MediaTypes content = 11;
|
||||||
|
repeated NamedAny specification_extension = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HeaderOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
Header header = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message HeadersOrReferences {
|
||||||
|
repeated NamedHeaderOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object provides metadata about the API. The metadata MAY be used by the clients if needed, and MAY be presented in editing or documentation generation tools for convenience.
|
||||||
|
message Info {
|
||||||
|
string title = 1;
|
||||||
|
string description = 2;
|
||||||
|
string terms_of_service = 3;
|
||||||
|
Contact contact = 4;
|
||||||
|
License license = 5;
|
||||||
|
string version = 6;
|
||||||
|
repeated NamedAny specification_extension = 7;
|
||||||
|
string summary = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ItemsItem {
|
||||||
|
repeated SchemaOrReference schema_or_reference = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// License information for the exposed API.
|
||||||
|
message License {
|
||||||
|
string name = 1;
|
||||||
|
string url = 2;
|
||||||
|
repeated NamedAny specification_extension = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The `Link object` represents a possible design-time link for a response. The presence of a link does not guarantee the caller's ability to successfully invoke it, rather it provides a known relationship and traversal mechanism between responses and other operations. Unlike _dynamic_ links (i.e. links provided **in** the response payload), the OAS linking mechanism does not require link information in the runtime response. For computing links, and providing instructions to execute them, a runtime expression is used for accessing values in an operation and using them as parameters while invoking the linked operation.
|
||||||
|
message Link {
|
||||||
|
string operation_ref = 1;
|
||||||
|
string operation_id = 2;
|
||||||
|
AnyOrExpression parameters = 3;
|
||||||
|
AnyOrExpression request_body = 4;
|
||||||
|
string description = 5;
|
||||||
|
Server server = 6;
|
||||||
|
repeated NamedAny specification_extension = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
Link link = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinksOrReferences {
|
||||||
|
repeated NamedLinkOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each Media Type Object provides schema and examples for the media type identified by its key.
|
||||||
|
message MediaType {
|
||||||
|
SchemaOrReference schema = 1;
|
||||||
|
Any example = 2;
|
||||||
|
ExamplesOrReferences examples = 3;
|
||||||
|
Encodings encoding = 4;
|
||||||
|
repeated NamedAny specification_extension = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MediaTypes {
|
||||||
|
repeated NamedMediaType additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of Any as ordered (name,value) pairs.
|
||||||
|
message NamedAny {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
Any value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of CallbackOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedCallbackOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
CallbackOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of Encoding as ordered (name,value) pairs.
|
||||||
|
message NamedEncoding {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
Encoding value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of ExampleOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedExampleOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
ExampleOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of HeaderOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedHeaderOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
HeaderOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of LinkOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedLinkOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
LinkOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of MediaType as ordered (name,value) pairs.
|
||||||
|
message NamedMediaType {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
MediaType value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of ParameterOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedParameterOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
ParameterOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of PathItem as ordered (name,value) pairs.
|
||||||
|
message NamedPathItem {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
PathItem value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of RequestBodyOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedRequestBodyOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
RequestBodyOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of ResponseOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedResponseOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
ResponseOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of SchemaOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedSchemaOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
SchemaOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of SecuritySchemeOrReference as ordered (name,value) pairs.
|
||||||
|
message NamedSecuritySchemeOrReference {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
SecuritySchemeOrReference value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of ServerVariable as ordered (name,value) pairs.
|
||||||
|
message NamedServerVariable {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
ServerVariable value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of string as ordered (name,value) pairs.
|
||||||
|
message NamedString {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
string value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically-generated message used to represent maps of StringArray as ordered (name,value) pairs.
|
||||||
|
message NamedStringArray {
|
||||||
|
// Map key
|
||||||
|
string name = 1;
|
||||||
|
// Mapped value
|
||||||
|
StringArray value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration details for a supported OAuth Flow
|
||||||
|
message OauthFlow {
|
||||||
|
string authorization_url = 1;
|
||||||
|
string token_url = 2;
|
||||||
|
string refresh_url = 3;
|
||||||
|
Strings scopes = 4;
|
||||||
|
repeated NamedAny specification_extension = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allows configuration of the supported OAuth Flows.
|
||||||
|
message OauthFlows {
|
||||||
|
OauthFlow implicit = 1;
|
||||||
|
OauthFlow password = 2;
|
||||||
|
OauthFlow client_credentials = 3;
|
||||||
|
OauthFlow authorization_code = 4;
|
||||||
|
repeated NamedAny specification_extension = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Object {
|
||||||
|
repeated NamedAny additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a single API operation on a path.
|
||||||
|
message Operation {
|
||||||
|
repeated string tags = 1;
|
||||||
|
string summary = 2;
|
||||||
|
string description = 3;
|
||||||
|
ExternalDocs external_docs = 4;
|
||||||
|
string operation_id = 5;
|
||||||
|
repeated ParameterOrReference parameters = 6;
|
||||||
|
RequestBodyOrReference request_body = 7;
|
||||||
|
Responses responses = 8;
|
||||||
|
CallbacksOrReferences callbacks = 9;
|
||||||
|
bool deprecated = 10;
|
||||||
|
repeated SecurityRequirement security = 11;
|
||||||
|
repeated Server servers = 12;
|
||||||
|
repeated NamedAny specification_extension = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a single operation parameter. A unique parameter is defined by a combination of a name and location.
|
||||||
|
message Parameter {
|
||||||
|
string name = 1;
|
||||||
|
string in = 2;
|
||||||
|
string description = 3;
|
||||||
|
bool required = 4;
|
||||||
|
bool deprecated = 5;
|
||||||
|
bool allow_empty_value = 6;
|
||||||
|
string style = 7;
|
||||||
|
bool explode = 8;
|
||||||
|
bool allow_reserved = 9;
|
||||||
|
SchemaOrReference schema = 10;
|
||||||
|
Any example = 11;
|
||||||
|
ExamplesOrReferences examples = 12;
|
||||||
|
MediaTypes content = 13;
|
||||||
|
repeated NamedAny specification_extension = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ParameterOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
Parameter parameter = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ParametersOrReferences {
|
||||||
|
repeated NamedParameterOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes the operations available on a single path. A Path Item MAY be empty, due to ACL constraints. The path itself is still exposed to the documentation viewer but they will not know which operations and parameters are available.
|
||||||
|
message PathItem {
|
||||||
|
string _ref = 1;
|
||||||
|
string summary = 2;
|
||||||
|
string description = 3;
|
||||||
|
Operation get = 4;
|
||||||
|
Operation put = 5;
|
||||||
|
Operation post = 6;
|
||||||
|
Operation delete = 7;
|
||||||
|
Operation options = 8;
|
||||||
|
Operation head = 9;
|
||||||
|
Operation patch = 10;
|
||||||
|
Operation trace = 11;
|
||||||
|
repeated Server servers = 12;
|
||||||
|
repeated ParameterOrReference parameters = 13;
|
||||||
|
repeated NamedAny specification_extension = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Holds the relative paths to the individual endpoints and their operations. The path is appended to the URL from the `Server Object` in order to construct the full URL. The Paths MAY be empty, due to ACL constraints.
|
||||||
|
message Paths {
|
||||||
|
repeated NamedPathItem path = 1;
|
||||||
|
repeated NamedAny specification_extension = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Properties {
|
||||||
|
repeated NamedSchemaOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A simple object to allow referencing other components in the specification, internally and externally. The Reference Object is defined by JSON Reference and follows the same structure, behavior and rules. For this specification, reference resolution is accomplished as defined by the JSON Reference specification and not by the JSON Schema specification.
|
||||||
|
message Reference {
|
||||||
|
string _ref = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RequestBodiesOrReferences {
|
||||||
|
repeated NamedRequestBodyOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a single request body.
|
||||||
|
message RequestBody {
|
||||||
|
string description = 1;
|
||||||
|
MediaTypes content = 2;
|
||||||
|
bool required = 3;
|
||||||
|
repeated NamedAny specification_extension = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RequestBodyOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
RequestBody request_body = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a single response from an API Operation, including design-time, static `links` to operations based on the response.
|
||||||
|
message Response {
|
||||||
|
string description = 1;
|
||||||
|
HeadersOrReferences headers = 2;
|
||||||
|
MediaTypes content = 3;
|
||||||
|
LinksOrReferences links = 4;
|
||||||
|
repeated NamedAny specification_extension = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResponseOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
Response response = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container for the expected responses of an operation. The container maps a HTTP response code to the expected response. The documentation is not necessarily expected to cover all possible HTTP response codes because they may not be known in advance. However, documentation is expected to cover a successful operation response and any known errors. The `default` MAY be used as a default response object for all HTTP codes that are not covered individually by the specification. The `Responses Object` MUST contain at least one response code, and it SHOULD be the response for a successful operation call.
|
||||||
|
message Responses {
|
||||||
|
ResponseOrReference default = 1;
|
||||||
|
repeated NamedResponseOrReference response_or_reference = 2;
|
||||||
|
repeated NamedAny specification_extension = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResponsesOrReferences {
|
||||||
|
repeated NamedResponseOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Schema Object allows the definition of input and output data types. These types can be objects, but also primitives and arrays. This object is an extended subset of the JSON Schema Specification Wright Draft 00. For more information about the properties, see JSON Schema Core and JSON Schema Validation. Unless stated otherwise, the property definitions follow the JSON Schema.
|
||||||
|
message Schema {
|
||||||
|
bool nullable = 1;
|
||||||
|
Discriminator discriminator = 2;
|
||||||
|
bool read_only = 3;
|
||||||
|
bool write_only = 4;
|
||||||
|
Xml xml = 5;
|
||||||
|
ExternalDocs external_docs = 6;
|
||||||
|
Any example = 7;
|
||||||
|
bool deprecated = 8;
|
||||||
|
string title = 9;
|
||||||
|
double multiple_of = 10;
|
||||||
|
double maximum = 11;
|
||||||
|
bool exclusive_maximum = 12;
|
||||||
|
double minimum = 13;
|
||||||
|
bool exclusive_minimum = 14;
|
||||||
|
int64 max_length = 15;
|
||||||
|
int64 min_length = 16;
|
||||||
|
string pattern = 17;
|
||||||
|
int64 max_items = 18;
|
||||||
|
int64 min_items = 19;
|
||||||
|
bool unique_items = 20;
|
||||||
|
int64 max_properties = 21;
|
||||||
|
int64 min_properties = 22;
|
||||||
|
repeated string required = 23;
|
||||||
|
repeated Any enum = 24;
|
||||||
|
string type = 25;
|
||||||
|
repeated SchemaOrReference all_of = 26;
|
||||||
|
repeated SchemaOrReference one_of = 27;
|
||||||
|
repeated SchemaOrReference any_of = 28;
|
||||||
|
Schema not = 29;
|
||||||
|
ItemsItem items = 30;
|
||||||
|
Properties properties = 31;
|
||||||
|
AdditionalPropertiesItem additional_properties = 32;
|
||||||
|
DefaultType default = 33;
|
||||||
|
string description = 34;
|
||||||
|
string format = 35;
|
||||||
|
repeated NamedAny specification_extension = 36;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SchemaOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
Schema schema = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message SchemasOrReferences {
|
||||||
|
repeated NamedSchemaOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lists the required security schemes to execute this operation. The name used for each property MUST correspond to a security scheme declared in the Security Schemes under the Components Object. Security Requirement Objects that contain multiple schemes require that all schemes MUST be satisfied for a request to be authorized. This enables support for scenarios where multiple query parameters or HTTP headers are required to convey security information. When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object, only one of the Security Requirement Objects in the list needs to be satisfied to authorize the request.
|
||||||
|
message SecurityRequirement {
|
||||||
|
repeated NamedStringArray additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defines a security scheme that can be used by the operations. Supported schemes are HTTP authentication, an API key (either as a header, a cookie parameter or as a query parameter), mutual TLS (use of a client certificate), OAuth2's common flows (implicit, password, application and access code) as defined in RFC6749, and OpenID Connect. Please note that currently (2019) the implicit flow is about to be deprecated OAuth 2.0 Security Best Current Practice. Recommended for most use case is Authorization Code Grant flow with PKCE.
|
||||||
|
message SecurityScheme {
|
||||||
|
string type = 1;
|
||||||
|
string description = 2;
|
||||||
|
string name = 3;
|
||||||
|
string in = 4;
|
||||||
|
string scheme = 5;
|
||||||
|
string bearer_format = 6;
|
||||||
|
OauthFlows flows = 7;
|
||||||
|
string open_id_connect_url = 8;
|
||||||
|
repeated NamedAny specification_extension = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SecuritySchemeOrReference {
|
||||||
|
oneof oneof {
|
||||||
|
SecurityScheme security_scheme = 1;
|
||||||
|
Reference reference = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message SecuritySchemesOrReferences {
|
||||||
|
repeated NamedSecuritySchemeOrReference additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An object representing a Server.
|
||||||
|
message Server {
|
||||||
|
string url = 1;
|
||||||
|
string description = 2;
|
||||||
|
ServerVariables variables = 3;
|
||||||
|
repeated NamedAny specification_extension = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An object representing a Server Variable for server URL template substitution.
|
||||||
|
message ServerVariable {
|
||||||
|
repeated string enum = 1;
|
||||||
|
string default = 2;
|
||||||
|
string description = 3;
|
||||||
|
repeated NamedAny specification_extension = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ServerVariables {
|
||||||
|
repeated NamedServerVariable additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any property starting with x- is valid.
|
||||||
|
message SpecificationExtension {
|
||||||
|
oneof oneof {
|
||||||
|
double number = 1;
|
||||||
|
bool boolean = 2;
|
||||||
|
string string = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message StringArray {
|
||||||
|
repeated string value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Strings {
|
||||||
|
repeated NamedString additional_properties = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds metadata to a single tag that is used by the Operation Object. It is not mandatory to have a Tag Object per tag defined in the Operation Object instances.
|
||||||
|
message Tag {
|
||||||
|
string name = 1;
|
||||||
|
string description = 2;
|
||||||
|
ExternalDocs external_docs = 3;
|
||||||
|
repeated NamedAny specification_extension = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A metadata object that allows for more fine-tuned XML model definitions. When using arrays, XML element names are *not* inferred (for singular/plural forms) and the `name` property SHOULD be used to add that information. See examples for expected behavior.
|
||||||
|
message Xml {
|
||||||
|
string name = 1;
|
||||||
|
string namespace = 2;
|
||||||
|
string prefix = 3;
|
||||||
|
bool attribute = 4;
|
||||||
|
bool wrapped = 5;
|
||||||
|
repeated NamedAny specification_extension = 6;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# OpenAPI v3 Protocol Buffer Models
|
||||||
|
|
||||||
|
This directory contains a Protocol Buffer-language model and related code for
|
||||||
|
supporting OpenAPI v3.
|
||||||
|
|
||||||
|
Gnostic applications and plugins can use OpenAPIv3.proto to generate Protocol
|
||||||
|
Buffer support code for their preferred languages.
|
||||||
|
|
||||||
|
OpenAPIv3.go is used by Gnostic to read JSON and YAML OpenAPI descriptions into
|
||||||
|
the Protocol Buffer-based datastructures generated from OpenAPIv3.proto.
|
||||||
|
|
||||||
|
OpenAPIv3.proto and OpenAPIv3.go are generated by the Gnostic compiler
|
||||||
|
generator, and OpenAPIv3.pb.go is generated by protoc, the Protocol Buffer
|
||||||
|
compiler, and protoc-gen-go, the Protocol Buffer Go code generation plugin.
|
||||||
|
|
||||||
|
openapi-3.1.json is a JSON schema for OpenAPI 3.1 that is automatically
|
||||||
|
generated from the OpenAPI 3.1 specification. It is not an official JSON Schema
|
||||||
|
for OpenAPI.
|
||||||
|
|
||||||
|
The schema-generator directory contains support code which generates
|
||||||
|
openapi-3.1.json from the OpenAPI 3.1 specification document (Markdown).
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 openapi_v3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/googleapis/gnostic/compiler"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseDocument reads an OpenAPI v3 description from a YAML/JSON representation.
|
||||||
|
func ParseDocument(b []byte) (*Document, error) {
|
||||||
|
info, err := compiler.ReadInfoFromBytes("", b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
root := info.Content[0]
|
||||||
|
return NewDocument(root, compiler.NewContextWithExtensions("$root", root, nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// YAMLValue produces a serialized YAML representation of the document.
|
||||||
|
func (d *Document) YAMLValue(comment string) ([]byte, error) {
|
||||||
|
rawInfo := d.ToRawInfo()
|
||||||
|
rawInfo = &yaml.Node{
|
||||||
|
Kind: yaml.DocumentNode,
|
||||||
|
Content: []*yaml.Node{rawInfo},
|
||||||
|
HeadComment: comment,
|
||||||
|
}
|
||||||
|
return yaml.Marshal(rawInfo)
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
A high-performance 100% compatible drop-in replacement of "encoding/json"
|
A high-performance 100% compatible drop-in replacement of "encoding/json"
|
||||||
|
|
||||||
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
|
|
||||||
|
|
||||||
# Benchmark
|
# Benchmark
|
||||||
|
|
||||||

|

|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.8.x
|
- 1.9.x
|
||||||
- 1.x
|
- 1.x
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/modern-go/concurrent"
|
|
||||||
packages = ["."]
|
|
||||||
revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a"
|
|
||||||
version = "1.0.0"
|
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "daee8a88b3498b61c5640056665b8b9eea062006f5e596bbb6a3ed9119a11ec7"
|
input-imports = []
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
@ -26,10 +26,6 @@
|
||||||
|
|
||||||
ignored = []
|
ignored = []
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/modern-go/concurrent"
|
|
||||||
version = "1.0.0"
|
|
||||||
|
|
||||||
[prune]
|
[prune]
|
||||||
go-tests = true
|
go-tests = true
|
||||||
unused-packages = true
|
unused-packages = true
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
//+build go1.18
|
||||||
|
|
||||||
|
package reflect2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// m escapes into the return value, but the caller of mapiterinit
|
||||||
|
// doesn't let the return value escape.
|
||||||
|
//go:noescape
|
||||||
|
//go:linkname mapiterinit reflect.mapiterinit
|
||||||
|
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer, it *hiter)
|
||||||
|
|
||||||
|
func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
|
||||||
|
var it hiter
|
||||||
|
mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj), &it)
|
||||||
|
return &UnsafeMapIterator{
|
||||||
|
hiter: &it,
|
||||||
|
pKeyRType: type2.pKeyRType,
|
||||||
|
pElemRType: type2.pElemRType,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
//+build go1.7
|
|
||||||
|
|
||||||
package reflect2
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
//go:linkname resolveTypeOff reflect.resolveTypeOff
|
|
||||||
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
|
|
|
@ -6,6 +6,9 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:linkname resolveTypeOff reflect.resolveTypeOff
|
||||||
|
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname makemap reflect.makemap
|
//go:linkname makemap reflect.makemap
|
||||||
func makemap(rtype unsafe.Pointer, cap int) (m unsafe.Pointer)
|
func makemap(rtype unsafe.Pointer, cap int) (m unsafe.Pointer)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
//+build !go1.18
|
||||||
|
|
||||||
|
package reflect2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// m escapes into the return value, but the caller of mapiterinit
|
||||||
|
// doesn't let the return value escape.
|
||||||
|
//go:noescape
|
||||||
|
//go:linkname mapiterinit reflect.mapiterinit
|
||||||
|
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) (val *hiter)
|
||||||
|
|
||||||
|
func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
|
||||||
|
return &UnsafeMapIterator{
|
||||||
|
hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)),
|
||||||
|
pKeyRType: type2.pKeyRType,
|
||||||
|
pElemRType: type2.pElemRType,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
//+build !go1.7
|
|
||||||
|
|
||||||
package reflect2
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
//+build !go1.9
|
|
||||||
|
|
||||||
package reflect2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:linkname makemap reflect.makemap
|
|
||||||
func makemap(rtype unsafe.Pointer) (m unsafe.Pointer)
|
|
||||||
|
|
||||||
func makeMapWithSize(rtype unsafe.Pointer, cap int) unsafe.Pointer {
|
|
||||||
return makemap(rtype)
|
|
||||||
}
|
|
|
@ -1,8 +1,9 @@
|
||||||
package reflect2
|
package reflect2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/modern-go/concurrent"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -130,13 +131,13 @@ var ConfigSafe = Config{UseSafeImplementation: true}.Froze()
|
||||||
|
|
||||||
type frozenConfig struct {
|
type frozenConfig struct {
|
||||||
useSafeImplementation bool
|
useSafeImplementation bool
|
||||||
cache *concurrent.Map
|
cache *sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg Config) Froze() *frozenConfig {
|
func (cfg Config) Froze() *frozenConfig {
|
||||||
return &frozenConfig{
|
return &frozenConfig{
|
||||||
useSafeImplementation: cfg.UseSafeImplementation,
|
useSafeImplementation: cfg.UseSafeImplementation,
|
||||||
cache: concurrent.NewMap(),
|
cache: new(sync.Map),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,11 +289,12 @@ func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnsafeCastString(str string) []byte {
|
func UnsafeCastString(str string) []byte {
|
||||||
|
bytes := make([]byte, 0)
|
||||||
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||||
sliceHeader := &reflect.SliceHeader{
|
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&bytes))
|
||||||
Data: stringHeader.Data,
|
sliceHeader.Data = stringHeader.Data
|
||||||
Cap: stringHeader.Len,
|
sliceHeader.Cap = stringHeader.Len
|
||||||
Len: stringHeader.Len,
|
sliceHeader.Len = stringHeader.Len
|
||||||
}
|
runtime.KeepAlive(str)
|
||||||
return *(*[]byte)(unsafe.Pointer(sliceHeader))
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
echo "" > coverage.txt
|
|
||||||
|
|
||||||
for d in $(go list github.com/modern-go/reflect2-tests/... | grep -v vendor); do
|
|
||||||
go test -coverprofile=profile.out -coverpkg=github.com/modern-go/reflect2 $d
|
|
||||||
if [ -f profile.out ]; then
|
|
||||||
cat profile.out >> coverage.txt
|
|
||||||
rm profile.out
|
|
||||||
fi
|
|
||||||
done
|
|
|
@ -1,17 +1,13 @@
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
package reflect2
|
package reflect2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// typelinks1 for 1.5 ~ 1.6
|
|
||||||
//go:linkname typelinks1 reflect.typelinks
|
|
||||||
func typelinks1() [][]unsafe.Pointer
|
|
||||||
|
|
||||||
// typelinks2 for 1.7 ~
|
// typelinks2 for 1.7 ~
|
||||||
//go:linkname typelinks2 reflect.typelinks
|
//go:linkname typelinks2 reflect.typelinks
|
||||||
func typelinks2() (sections []unsafe.Pointer, offset [][]int32)
|
func typelinks2() (sections []unsafe.Pointer, offset [][]int32)
|
||||||
|
@ -27,49 +23,10 @@ func discoverTypes() {
|
||||||
types = make(map[string]reflect.Type)
|
types = make(map[string]reflect.Type)
|
||||||
packages = make(map[string]map[string]reflect.Type)
|
packages = make(map[string]map[string]reflect.Type)
|
||||||
|
|
||||||
ver := runtime.Version()
|
loadGoTypes()
|
||||||
if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") {
|
|
||||||
loadGo15Types()
|
|
||||||
} else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") {
|
|
||||||
loadGo15Types()
|
|
||||||
} else {
|
|
||||||
loadGo17Types()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadGo15Types() {
|
func loadGoTypes() {
|
||||||
var obj interface{} = reflect.TypeOf(0)
|
|
||||||
typePtrss := typelinks1()
|
|
||||||
for _, typePtrs := range typePtrss {
|
|
||||||
for _, typePtr := range typePtrs {
|
|
||||||
(*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr
|
|
||||||
typ := obj.(reflect.Type)
|
|
||||||
if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
|
|
||||||
loadedType := typ.Elem()
|
|
||||||
pkgTypes := packages[loadedType.PkgPath()]
|
|
||||||
if pkgTypes == nil {
|
|
||||||
pkgTypes = map[string]reflect.Type{}
|
|
||||||
packages[loadedType.PkgPath()] = pkgTypes
|
|
||||||
}
|
|
||||||
types[loadedType.String()] = loadedType
|
|
||||||
pkgTypes[loadedType.Name()] = loadedType
|
|
||||||
}
|
|
||||||
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr &&
|
|
||||||
typ.Elem().Elem().Kind() == reflect.Struct {
|
|
||||||
loadedType := typ.Elem().Elem()
|
|
||||||
pkgTypes := packages[loadedType.PkgPath()]
|
|
||||||
if pkgTypes == nil {
|
|
||||||
pkgTypes = map[string]reflect.Type{}
|
|
||||||
packages[loadedType.PkgPath()] = pkgTypes
|
|
||||||
}
|
|
||||||
types[loadedType.String()] = loadedType
|
|
||||||
pkgTypes[loadedType.Name()] = loadedType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadGo17Types() {
|
|
||||||
var obj interface{} = reflect.TypeOf(0)
|
var obj interface{} = reflect.TypeOf(0)
|
||||||
sections, offset := typelinks2()
|
sections, offset := typelinks2()
|
||||||
for i, offs := range offset {
|
for i, offs := range offset {
|
||||||
|
|
|
@ -19,18 +19,12 @@ func typedslicecopy(elemType unsafe.Pointer, dst, src sliceHeader) int
|
||||||
|
|
||||||
//go:linkname mapassign reflect.mapassign
|
//go:linkname mapassign reflect.mapassign
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key, val unsafe.Pointer)
|
func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer, val unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname mapaccess reflect.mapaccess
|
//go:linkname mapaccess reflect.mapaccess
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func mapaccess(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
|
func mapaccess(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
|
||||||
|
|
||||||
// m escapes into the return value, but the caller of mapiterinit
|
|
||||||
// doesn't let the return value escape.
|
|
||||||
//go:noescape
|
|
||||||
//go:linkname mapiterinit reflect.mapiterinit
|
|
||||||
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) *hiter
|
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
//go:linkname mapiternext reflect.mapiternext
|
//go:linkname mapiternext reflect.mapiternext
|
||||||
func mapiternext(it *hiter)
|
func mapiternext(it *hiter)
|
||||||
|
@ -42,9 +36,21 @@ func ifaceE2I(rtype unsafe.Pointer, src interface{}, dst unsafe.Pointer)
|
||||||
// If you modify hiter, also change cmd/internal/gc/reflect.go to indicate
|
// If you modify hiter, also change cmd/internal/gc/reflect.go to indicate
|
||||||
// the layout of this structure.
|
// the layout of this structure.
|
||||||
type hiter struct {
|
type hiter struct {
|
||||||
key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/internal/gc/range.go).
|
key unsafe.Pointer
|
||||||
value unsafe.Pointer // Must be in second position (see cmd/internal/gc/range.go).
|
value unsafe.Pointer
|
||||||
// rest fields are ignored
|
t unsafe.Pointer
|
||||||
|
h unsafe.Pointer
|
||||||
|
buckets unsafe.Pointer
|
||||||
|
bptr unsafe.Pointer
|
||||||
|
overflow *[]unsafe.Pointer
|
||||||
|
oldoverflow *[]unsafe.Pointer
|
||||||
|
startBucket uintptr
|
||||||
|
offset uint8
|
||||||
|
wrapped bool
|
||||||
|
B uint8
|
||||||
|
i uint8
|
||||||
|
bucket uintptr
|
||||||
|
checkBucket uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// add returns p+x.
|
// add returns p+x.
|
||||||
|
|
|
@ -107,14 +107,6 @@ func (type2 *UnsafeMapType) Iterate(obj interface{}) MapIterator {
|
||||||
return type2.UnsafeIterate(objEFace.data)
|
return type2.UnsafeIterate(objEFace.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator {
|
|
||||||
return &UnsafeMapIterator{
|
|
||||||
hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)),
|
|
||||||
pKeyRType: type2.pKeyRType,
|
|
||||||
pElemRType: type2.pElemRType,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type UnsafeMapIterator struct {
|
type UnsafeMapIterator struct {
|
||||||
*hiter
|
*hiter
|
||||||
pKeyRType unsafe.Pointer
|
pKeyRType unsafe.Pointer
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
## 1.16.5
|
||||||
|
|
||||||
|
Ginkgo 2.0 now has a Release Candidate. 1.16.5 advertises the existence of the RC.
|
||||||
|
1.16.5 deprecates GinkgoParallelNode in favor of GinkgoParallelProcess
|
||||||
|
|
||||||
|
You can silence the RC advertisement by setting an `ACK_GINKG_RC=true` environment variable or creating a file in your home directory called `.ack-ginkgo-rc`
|
||||||
|
|
||||||
## 1.16.4
|
## 1.16.4
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
|
@ -1,23 +1,18 @@
|
||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.org/onsi/ginkgo)
|
|
||||||
[](https://github.com/onsi/ginkgo/actions?query=workflow%3Atest+branch%3Amaster)
|
[](https://github.com/onsi/ginkgo/actions?query=workflow%3Atest+branch%3Amaster)
|
||||||
|
|
||||||
Jump to the [docs](https://onsi.github.io/ginkgo/) | [中文文档](https://ke-chain.github.io/ginkgodoc) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)!
|
Jump to the [docs](https://onsi.github.io/ginkgo/) | [中文文档](https://ke-chain.github.io/ginkgodoc) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)!
|
||||||
|
|
||||||
If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW).
|
If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW).
|
||||||
|
|
||||||
# Ginkgo 2.0 is coming soon!
|
# Ginkgo 2.0 Release Candidate is available!
|
||||||
|
|
||||||
An effort is underway to develop and deliver Ginkgo 2.0. The work is happening in the [v2](https://github.com/onsi/ginkgo/tree/v2) branch and a changelog and migration guide is being maintained on that branch [here](https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md). Issue [#711](https://github.com/onsi/ginkgo/issues/711) is the central place for discussion and links to the original [proposal doc](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#).
|
An effort is underway to develop and deliver Ginkgo 2.0. The work is happening in the [ver2](https://github.com/onsi/ginkgo/tree/ver2) branch and a changelog and migration guide is being maintained on that branch [here](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md). Issue [#711](https://github.com/onsi/ginkgo/issues/711) is the central place for discussion.
|
||||||
|
|
||||||
As described in the [changelog](https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md) and [proposal](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#), Ginkgo 2.0 will clean up the Ginkgo codebase, deprecate and remove some v1 functionality, and add several new much-requested features. To help users get ready for the migration, Ginkgo v1 has started emitting deprecation warnings for features that will no longer be supported with links to documentation for how to migrate away from these features. If you have concerns or comments please chime in on [#711](https://github.com/onsi/ginkgo/issues/711).
|
As described in the [changelog](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md) and [proposal](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#), Ginkgo 2.0 will clean up the Ginkgo codebase, deprecate and remove some v1 functionality, and add several new much-requested features. To help users get ready for the migration, Ginkgo v1 has started emitting deprecation warnings for features that will no longer be supported with links to documentation for how to migrate away from these features. If you have concerns or comments please chime in on [#711](https://github.com/onsi/ginkgo/issues/711).
|
||||||
|
|
||||||
The current timeline for completion of 2.0 looks like:
|
Please start exploring and using the V2 release! To get started follow the [Using the Release Candidate](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta) directions in the migration guide.
|
||||||
|
|
||||||
- Early April 2021: first public release of 2.0, deprecation warnings land in v1.
|
|
||||||
- May 2021: first beta/rc of 2.0 with most new functionality in place.
|
|
||||||
- June/July 2021: 2.0 ships and fully replaces the 1.x codebase on master.
|
|
||||||
|
|
||||||
## TLDR
|
## TLDR
|
||||||
Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests.
|
Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests.
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "1.16.4"
|
const VERSION = "1.16.5"
|
||||||
|
|
||||||
type GinkgoConfigType struct {
|
type GinkgoConfigType struct {
|
||||||
RandomSeed int64
|
RandomSeed int64
|
||||||
|
|
|
@ -37,6 +37,7 @@ func BuildBootstrapCommand() *Command {
|
||||||
},
|
},
|
||||||
Command: func(args []string, additionalArgs []string) {
|
Command: func(args []string, additionalArgs []string) {
|
||||||
generateBootstrap(agouti, noDot, internal, customBootstrapFile)
|
generateBootstrap(agouti, noDot, internal, customBootstrapFile)
|
||||||
|
emitRCAdvertisement()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ func BuildGenerateCommand() *Command {
|
||||||
},
|
},
|
||||||
Command: func(args []string, additionalArgs []string) {
|
Command: func(args []string, additionalArgs []string) {
|
||||||
generateSpec(args, agouti, noDot, internal, customTestFile)
|
generateSpec(args, agouti, noDot, internal, customTestFile)
|
||||||
|
emitRCAdvertisement()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ func BuildHelpCommand() *Command {
|
||||||
func printHelp(args []string, additionalArgs []string) {
|
func printHelp(args []string, additionalArgs []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
usage()
|
usage()
|
||||||
|
emitRCAdvertisement()
|
||||||
} else {
|
} else {
|
||||||
command, found := commandMatching(args[0])
|
command, found := commandMatching(args[0])
|
||||||
if !found {
|
if !found {
|
||||||
|
@ -27,5 +28,6 @@ func printHelp(args []string, additionalArgs []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
usageForCommand(command, true)
|
usageForCommand(command, true)
|
||||||
|
emitRCAdvertisement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,9 +131,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/onsi/ginkgo/config"
|
"github.com/onsi/ginkgo/config"
|
||||||
|
"github.com/onsi/ginkgo/formatter"
|
||||||
"github.com/onsi/ginkgo/ginkgo/testsuite"
|
"github.com/onsi/ginkgo/ginkgo/testsuite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -243,6 +245,7 @@ func usageForCommand(command *Command, longForm bool) {
|
||||||
|
|
||||||
func complainAndQuit(complaint string) {
|
func complainAndQuit(complaint string) {
|
||||||
fmt.Fprintf(os.Stderr, "%s\nFor usage instructions:\n\tginkgo help\n", complaint)
|
fmt.Fprintf(os.Stderr, "%s\nFor usage instructions:\n\tginkgo help\n", complaint)
|
||||||
|
emitRCAdvertisement()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,3 +309,29 @@ func pluralizedWord(singular, plural string, count int) string {
|
||||||
}
|
}
|
||||||
return plural
|
return plural
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func emitRCAdvertisement() {
|
||||||
|
ackRC := os.Getenv("ACK_GINKGO_RC")
|
||||||
|
if ackRC != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err == nil {
|
||||||
|
_, err := os.Stat(filepath.Join(home, ".ack-ginkgo-rc"))
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out := formatter.F("\n{{light-yellow}}Ginkgo 2.0 is coming soon!{{/}}\n")
|
||||||
|
out += formatter.F("{{light-yellow}}=========================={{/}}\n")
|
||||||
|
out += formatter.F("{{bold}}{{green}}Ginkgo 2.0{{/}} is under active development and will introduce several new features, improvements, and a small handful of breaking changes.\n")
|
||||||
|
out += formatter.F("A release candidate for 2.0 is now available and 2.0 should GA in Fall 2021. {{bold}}Please give the RC a try and send us feedback!{{/}}\n")
|
||||||
|
out += formatter.F(" - To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md{{/}}\n")
|
||||||
|
out += formatter.F(" - For instructions on using the Release Candidate visit {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta{{/}}\n")
|
||||||
|
out += formatter.F(" - To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n")
|
||||||
|
out += formatter.F("To {{bold}}{{coral}}silence this notice{{/}}, set the environment variable: {{bold}}ACK_GINKGO_RC=true{{/}}\n")
|
||||||
|
out += formatter.F("Alternatively you can: {{bold}}touch $HOME/.ack-ginkgo-rc{{/}}")
|
||||||
|
|
||||||
|
fmt.Println(out)
|
||||||
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ func (r *SpecRunner) RunSpecs(args []string, additionalArgs []string) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Test Suite Failed\n")
|
fmt.Printf("Test Suite Failed\n")
|
||||||
|
emitRCAdvertisement()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,5 @@ func BuildVersionCommand() *Command {
|
||||||
|
|
||||||
func printVersion([]string, []string) {
|
func printVersion([]string, []string) {
|
||||||
fmt.Printf("Ginkgo Version %s\n", config.VERSION)
|
fmt.Printf("Ginkgo Version %s\n", config.VERSION)
|
||||||
|
emitRCAdvertisement()
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,9 +73,15 @@ func GinkgoRandomSeed() int64 {
|
||||||
return config.GinkgoConfig.RandomSeed
|
return config.GinkgoConfig.RandomSeed
|
||||||
}
|
}
|
||||||
|
|
||||||
//GinkgoParallelNode returns the parallel node number for the current ginkgo process
|
//GinkgoParallelNode is deprecated, use GinkgoParallelProcess instead
|
||||||
//The node number is 1-indexed
|
|
||||||
func GinkgoParallelNode() int {
|
func GinkgoParallelNode() int {
|
||||||
|
deprecationTracker.TrackDeprecation(types.Deprecations.ParallelNode(), codelocation.New(1))
|
||||||
|
return GinkgoParallelProcess()
|
||||||
|
}
|
||||||
|
|
||||||
|
//GinkgoParallelProcess returns the parallel process number for the current ginkgo process
|
||||||
|
//The process number is 1-indexed
|
||||||
|
func GinkgoParallelProcess() int {
|
||||||
return config.GinkgoConfig.ParallelNode
|
return config.GinkgoConfig.ParallelNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +115,7 @@ func GinkgoT(optionalOffset ...int) GinkgoTInterface {
|
||||||
//in the testing package's T.
|
//in the testing package's T.
|
||||||
type GinkgoTInterface interface {
|
type GinkgoTInterface interface {
|
||||||
Cleanup(func())
|
Cleanup(func())
|
||||||
|
Setenv(key, value string)
|
||||||
Error(args ...interface{})
|
Error(args ...interface{})
|
||||||
Errorf(format string, args ...interface{})
|
Errorf(format string, args ...interface{})
|
||||||
Fail()
|
Fail()
|
||||||
|
|
|
@ -34,6 +34,11 @@ func (t *ginkgoTestingTProxy) Cleanup(func()) {
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ginkgoTestingTProxy) Setenv(kev, value string) {
|
||||||
|
fmt.Println("Setenv is a noop for Ginkgo at the moment but will be implemented in V2")
|
||||||
|
// No-op until Cleanup is implemented
|
||||||
|
}
|
||||||
|
|
||||||
func (t *ginkgoTestingTProxy) Error(args ...interface{}) {
|
func (t *ginkgoTestingTProxy) Error(args ...interface{}) {
|
||||||
t.fail(fmt.Sprintln(args...), t.offset)
|
t.fail(fmt.Sprintln(args...), t.offset)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,14 @@ func (d deprecations) Measure() Deprecation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d deprecations) ParallelNode() Deprecation {
|
||||||
|
return Deprecation{
|
||||||
|
Message: "GinkgoParallelNode is deprecated and will be removed in Ginkgo V2. Please use GinkgoParallelProcess instead.",
|
||||||
|
DocLink: "renamed-ginkgoparallelnode",
|
||||||
|
Version: "1.16.5",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d deprecations) Convert() Deprecation {
|
func (d deprecations) Convert() Deprecation {
|
||||||
return Deprecation{
|
return Deprecation{
|
||||||
Message: "The convert command is deprecated in Ginkgo V2",
|
Message: "The convert command is deprecated in Ginkgo V2",
|
||||||
|
@ -99,16 +107,18 @@ func (d *DeprecationTracker) DidTrackDeprecations() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeprecationTracker) DeprecationsReport() string {
|
func (d *DeprecationTracker) DeprecationsReport() string {
|
||||||
out := formatter.F("{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n")
|
out := formatter.F("\n{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n")
|
||||||
out += formatter.F("{{light-yellow}}============================================={{/}}\n")
|
out += formatter.F("{{light-yellow}}============================================={{/}}\n")
|
||||||
out += formatter.F("Ginkgo 2.0 is under active development and will introduce (a small number of) breaking changes.\n")
|
out += formatter.F("{{bold}}{{green}}Ginkgo 2.0{{/}} is under active development and will introduce several new features, improvements, and a small handful of breaking changes.\n")
|
||||||
out += formatter.F("To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md{{/}}\n")
|
out += formatter.F("A release candidate for 2.0 is now available and 2.0 should GA in Fall 2021. {{bold}}Please give the RC a try and send us feedback!{{/}}\n")
|
||||||
out += formatter.F("To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n")
|
out += formatter.F(" - To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md{{/}}\n")
|
||||||
|
out += formatter.F(" - For instructions on using the Release Candidate visit {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta{{/}}\n")
|
||||||
|
out += formatter.F(" - To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n")
|
||||||
|
|
||||||
for deprecation, locations := range d.deprecations {
|
for deprecation, locations := range d.deprecations {
|
||||||
out += formatter.Fi(1, "{{yellow}}"+deprecation.Message+"{{/}}\n")
|
out += formatter.Fi(1, "{{yellow}}"+deprecation.Message+"{{/}}\n")
|
||||||
if deprecation.DocLink != "" {
|
if deprecation.DocLink != "" {
|
||||||
out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink)
|
out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink)
|
||||||
}
|
}
|
||||||
for _, location := range locations {
|
for _, location := range locations {
|
||||||
out += formatter.Fi(2, "{{gray}}%s{{/}}\n", location)
|
out += formatter.Fi(2, "{{gray}}%s{{/}}\n", location)
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
## 1.17.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- Add HaveField matcher [3a26311]
|
||||||
|
- add Error() assertions on the final error value of multi-return values (#480) [2f96943]
|
||||||
|
- separate out offsets and timeouts (#478) [18a4723]
|
||||||
|
- fix transformation error reporting (#479) [e001fab]
|
||||||
|
- allow transform functions to report errors (#472) [bf93408]
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
Stop using deprecated ioutil package (#467) [07f405d]
|
||||||
|
|
||||||
## 1.16.0
|
## 1.16.0
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"github.com/onsi/gomega/types"
|
"github.com/onsi/gomega/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const GOMEGA_VERSION = "1.16.0"
|
const GOMEGA_VERSION = "1.17.0"
|
||||||
|
|
||||||
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
||||||
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
||||||
|
@ -204,7 +204,8 @@ func Expect(actual interface{}, extra ...interface{}) Assertion {
|
||||||
// ExpectWithOffset(1, "foo").To(Equal("foo"))
|
// ExpectWithOffset(1, "foo").To(Equal("foo"))
|
||||||
//
|
//
|
||||||
// Unlike `Expect` and `Ω`, `ExpectWithOffset` takes an additional integer argument
|
// Unlike `Expect` and `Ω`, `ExpectWithOffset` takes an additional integer argument
|
||||||
// that is used to modify the call-stack offset when computing line numbers.
|
// that is used to modify the call-stack offset when computing line numbers. It is
|
||||||
|
// the same as `Expect(...).WithOffset`.
|
||||||
//
|
//
|
||||||
// This is most useful in helper functions that make assertions. If you want Gomega's
|
// This is most useful in helper functions that make assertions. If you want Gomega's
|
||||||
// error message to refer to the calling line in the test (as opposed to the line in the helper function)
|
// error message to refer to the calling line in the test (as opposed to the line in the helper function)
|
||||||
|
@ -300,6 +301,9 @@ For example:
|
||||||
}).Should(Succeed())
|
}).Should(Succeed())
|
||||||
|
|
||||||
will rerun the function until all assertions pass.
|
will rerun the function until all assertions pass.
|
||||||
|
|
||||||
|
`Eventually` specifying a timeout interval (and an optional polling interval) are
|
||||||
|
the same as `Eventually(...).WithTimeout` or `Eventually(...).WithTimeout(...).WithPolling`.
|
||||||
*/
|
*/
|
||||||
func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion {
|
func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||||
ensureDefaultGomegaIsConfigured()
|
ensureDefaultGomegaIsConfigured()
|
||||||
|
@ -309,6 +313,12 @@ func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||||
// EventuallyWithOffset operates like Eventually but takes an additional
|
// EventuallyWithOffset operates like Eventually but takes an additional
|
||||||
// initial argument to indicate an offset in the call stack. This is useful when building helper
|
// initial argument to indicate an offset in the call stack. This is useful when building helper
|
||||||
// functions that contain matchers. To learn more, read about `ExpectWithOffset`.
|
// functions that contain matchers. To learn more, read about `ExpectWithOffset`.
|
||||||
|
//
|
||||||
|
// `EventuallyWithOffset` is the same as `Eventually(...).WithOffset`.
|
||||||
|
//
|
||||||
|
// `EventuallyWithOffset` specifying a timeout interval (and an optional polling interval) are
|
||||||
|
// the same as `Eventually(...).WithOffset(...).WithTimeout` or
|
||||||
|
// `Eventually(...).WithOffset(...).WithTimeout(...).WithPolling`.
|
||||||
func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
|
func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||||
ensureDefaultGomegaIsConfigured()
|
ensureDefaultGomegaIsConfigured()
|
||||||
return Default.EventuallyWithOffset(offset, actual, intervals...)
|
return Default.EventuallyWithOffset(offset, actual, intervals...)
|
||||||
|
@ -337,6 +347,9 @@ func Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||||
// ConsistentlyWithOffset operates like Consistently but takes an additional
|
// ConsistentlyWithOffset operates like Consistently but takes an additional
|
||||||
// initial argument to indicate an offset in the call stack. This is useful when building helper
|
// initial argument to indicate an offset in the call stack. This is useful when building helper
|
||||||
// functions that contain matchers. To learn more, read about `ExpectWithOffset`.
|
// functions that contain matchers. To learn more, read about `ExpectWithOffset`.
|
||||||
|
//
|
||||||
|
// `ConsistentlyWithOffset` is the same as `Consistently(...).WithOffset` and
|
||||||
|
// optional `WithTimeout` and `WithPolling`.
|
||||||
func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
|
func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
|
||||||
ensureDefaultGomegaIsConfigured()
|
ensureDefaultGomegaIsConfigured()
|
||||||
return Default.ConsistentlyWithOffset(offset, actual, intervals...)
|
return Default.ConsistentlyWithOffset(offset, actual, intervals...)
|
||||||
|
|
|
@ -8,44 +8,64 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Assertion struct {
|
type Assertion struct {
|
||||||
actualInput interface{}
|
actuals []interface{} // actual value plus all extra values
|
||||||
|
actualIndex int // value to pass to the matcher
|
||||||
|
vet vetinari // the vet to call before calling Gomega matcher
|
||||||
offset int
|
offset int
|
||||||
extra []interface{}
|
|
||||||
g *Gomega
|
g *Gomega
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ...obligatory discworld reference, as "vetineer" doesn't sound ... quite right.
|
||||||
|
type vetinari func(assertion *Assertion, optionalDescription ...interface{}) bool
|
||||||
|
|
||||||
func NewAssertion(actualInput interface{}, g *Gomega, offset int, extra ...interface{}) *Assertion {
|
func NewAssertion(actualInput interface{}, g *Gomega, offset int, extra ...interface{}) *Assertion {
|
||||||
return &Assertion{
|
return &Assertion{
|
||||||
actualInput: actualInput,
|
actuals: append([]interface{}{actualInput}, extra...),
|
||||||
|
actualIndex: 0,
|
||||||
|
vet: (*Assertion).vetActuals,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
extra: extra,
|
|
||||||
g: g,
|
g: g,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (assertion *Assertion) WithOffset(offset int) types.Assertion {
|
||||||
|
assertion.offset = offset
|
||||||
|
return assertion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (assertion *Assertion) Error() types.Assertion {
|
||||||
|
return &Assertion{
|
||||||
|
actuals: assertion.actuals,
|
||||||
|
actualIndex: len(assertion.actuals) - 1,
|
||||||
|
vet: (*Assertion).vetError,
|
||||||
|
offset: assertion.offset,
|
||||||
|
g: assertion.g,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||||
assertion.g.THelper()
|
assertion.g.THelper()
|
||||||
return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
|
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||||
assertion.g.THelper()
|
assertion.g.THelper()
|
||||||
return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||||
assertion.g.THelper()
|
assertion.g.THelper()
|
||||||
return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
|
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||||
assertion.g.THelper()
|
assertion.g.THelper()
|
||||||
return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||||
assertion.g.THelper()
|
assertion.g.THelper()
|
||||||
return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string {
|
func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string {
|
||||||
|
@ -61,7 +81,8 @@ func (assertion *Assertion) buildDescription(optionalDescription ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
|
func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
|
||||||
matches, err := matcher.Match(assertion.actualInput)
|
actualInput := assertion.actuals[assertion.actualIndex]
|
||||||
|
matches, err := matcher.Match(actualInput)
|
||||||
assertion.g.THelper()
|
assertion.g.THelper()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
description := assertion.buildDescription(optionalDescription...)
|
description := assertion.buildDescription(optionalDescription...)
|
||||||
|
@ -71,9 +92,9 @@ func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool
|
||||||
if matches != desiredMatch {
|
if matches != desiredMatch {
|
||||||
var message string
|
var message string
|
||||||
if desiredMatch {
|
if desiredMatch {
|
||||||
message = matcher.FailureMessage(assertion.actualInput)
|
message = matcher.FailureMessage(actualInput)
|
||||||
} else {
|
} else {
|
||||||
message = matcher.NegatedFailureMessage(assertion.actualInput)
|
message = matcher.NegatedFailureMessage(actualInput)
|
||||||
}
|
}
|
||||||
description := assertion.buildDescription(optionalDescription...)
|
description := assertion.buildDescription(optionalDescription...)
|
||||||
assertion.g.Fail(description+message, 2+assertion.offset)
|
assertion.g.Fail(description+message, 2+assertion.offset)
|
||||||
|
@ -83,8 +104,11 @@ func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool {
|
// vetActuals vets the actual values, with the (optional) exception of a
|
||||||
success, message := vetExtras(assertion.extra)
|
// specific value, such as the first value in case non-error assertions, or the
|
||||||
|
// last value in case of Error()-based assertions.
|
||||||
|
func (assertion *Assertion) vetActuals(optionalDescription ...interface{}) bool {
|
||||||
|
success, message := vetActuals(assertion.actuals, assertion.actualIndex)
|
||||||
if success {
|
if success {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -95,12 +119,29 @@ func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func vetExtras(extras []interface{}) (bool, string) {
|
// vetError vets the actual values, except for the final error value, in case
|
||||||
for i, extra := range extras {
|
// the final error value is non-zero. Otherwise, it doesn't vet the actual
|
||||||
if extra != nil {
|
// values, as these are allowed to take on any values unless there is a non-zero
|
||||||
zeroValue := reflect.Zero(reflect.TypeOf(extra)).Interface()
|
// error value.
|
||||||
if !reflect.DeepEqual(zeroValue, extra) {
|
func (assertion *Assertion) vetError(optionalDescription ...interface{}) bool {
|
||||||
message := fmt.Sprintf("Unexpected non-nil/non-zero extra argument at index %d:\n\t<%T>: %#v", i+1, extra, extra)
|
if err := assertion.actuals[assertion.actualIndex]; err != nil {
|
||||||
|
// Go error result idiom: all other actual values must be zero values.
|
||||||
|
return assertion.vetActuals(optionalDescription...)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// vetActuals vets a slice of actual values, optionally skipping a particular
|
||||||
|
// value slice element, such as the first or last value slice element.
|
||||||
|
func vetActuals(actuals []interface{}, skipIndex int) (bool, string) {
|
||||||
|
for i, actual := range actuals {
|
||||||
|
if i == skipIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if actual != nil {
|
||||||
|
zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface()
|
||||||
|
if !reflect.DeepEqual(zeroValue, actual) {
|
||||||
|
message := fmt.Sprintf("Unexpected non-nil/non-zero argument at index %d:\n\t<%T>: %#v", i, actual, actual)
|
||||||
return false, message
|
return false, message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,21 @@ func NewAsyncAssertion(asyncType AsyncAssertionType, actualInput interface{}, g
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (assertion *AsyncAssertion) WithOffset(offset int) types.AsyncAssertion {
|
||||||
|
assertion.offset = offset
|
||||||
|
return assertion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (assertion *AsyncAssertion) WithTimeout(interval time.Duration) types.AsyncAssertion {
|
||||||
|
assertion.timeoutInterval = interval
|
||||||
|
return assertion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (assertion *AsyncAssertion) WithPolling(interval time.Duration) types.AsyncAssertion {
|
||||||
|
assertion.pollingInterval = interval
|
||||||
|
return assertion
|
||||||
|
}
|
||||||
|
|
||||||
func (assertion *AsyncAssertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
func (assertion *AsyncAssertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
|
||||||
assertion.g.THelper()
|
assertion.g.THelper()
|
||||||
return assertion.match(matcher, true, optionalDescription...)
|
return assertion.match(matcher, true, optionalDescription...)
|
||||||
|
@ -118,11 +133,11 @@ func (assertion *AsyncAssertion) pollActual() (interface{}, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
extras := []interface{}{}
|
extras := []interface{}{nil}
|
||||||
for _, value := range values[1:] {
|
for _, value := range values[1:] {
|
||||||
extras = append(extras, value.Interface())
|
extras = append(extras, value.Interface())
|
||||||
}
|
}
|
||||||
success, message := vetExtras(extras)
|
success, message := vetActuals(extras, 0)
|
||||||
if !success {
|
if !success {
|
||||||
return nil, errors.New(message)
|
return nil, errors.New(message)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,12 @@ func (g *Gomega) ConfigureWithT(t types.GomegaTestingT) *Gomega {
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gomega) Ω(atual interface{}, extra ...interface{}) types.Assertion {
|
func (g *Gomega) Ω(actual interface{}, extra ...interface{}) types.Assertion {
|
||||||
return g.ExpectWithOffset(0, atual, extra...)
|
return g.ExpectWithOffset(0, actual, extra...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gomega) Expect(atual interface{}, extra ...interface{}) types.Assertion {
|
func (g *Gomega) Expect(actual interface{}, extra ...interface{}) types.Assertion {
|
||||||
return g.ExpectWithOffset(0, atual, extra...)
|
return g.ExpectWithOffset(0, actual, extra...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gomega) ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) types.Assertion {
|
func (g *Gomega) ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) types.Assertion {
|
||||||
|
|
|
@ -342,6 +342,34 @@ func HaveKeyWithValue(key interface{}, value interface{}) types.GomegaMatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//HaveField succeeds if actual is a struct and the value at the passed in field
|
||||||
|
//matches the passed in matcher. By default HaveField used Equal() to perform the match,
|
||||||
|
//however a matcher can be passed in in stead.
|
||||||
|
//
|
||||||
|
//The field must be a string that resolves to the name of a field in the struct. Structs can be traversed
|
||||||
|
//using the '.' delimiter. If the field ends with '()' a method named field is assumed to exist on the struct and is invoked.
|
||||||
|
//Such methods must take no arguments and return a single value:
|
||||||
|
//
|
||||||
|
// type Book struct {
|
||||||
|
// Title string
|
||||||
|
// Author Person
|
||||||
|
// }
|
||||||
|
// type Person struct {
|
||||||
|
// FirstName string
|
||||||
|
// LastName string
|
||||||
|
// DOB time.Time
|
||||||
|
// }
|
||||||
|
// Expect(book).To(HaveField("Title", "Les Miserables"))
|
||||||
|
// Expect(book).To(HaveField("Title", ContainSubstring("Les"))
|
||||||
|
// Expect(book).To(HaveField("Person.FirstName", Equal("Victor"))
|
||||||
|
// Expect(book).To(HaveField("Person.DOB.Year()", BeNumerically("<", 1900))
|
||||||
|
func HaveField(field string, expected interface{}) types.GomegaMatcher {
|
||||||
|
return &matchers.HaveFieldMatcher{
|
||||||
|
Field: field,
|
||||||
|
Expected: expected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//BeNumerically performs numerical assertions in a type-agnostic way.
|
//BeNumerically performs numerical assertions in a type-agnostic way.
|
||||||
//Actual and expected should be numbers, though the specific type of
|
//Actual and expected should be numbers, though the specific type of
|
||||||
//number is irrelevant (float32, float64, uint8, etc...).
|
//number is irrelevant (float32, float64, uint8, etc...).
|
||||||
|
@ -485,10 +513,15 @@ func Not(matcher types.GomegaMatcher) types.GomegaMatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
//WithTransform applies the `transform` to the actual value and matches it against `matcher`.
|
//WithTransform applies the `transform` to the actual value and matches it against `matcher`.
|
||||||
//The given transform must be a function of one parameter that returns one value.
|
//The given transform must be either a function of one parameter that returns one value or a
|
||||||
|
// function of one parameter that returns two values, where the second value must be of the
|
||||||
|
// error type.
|
||||||
// var plus1 = func(i int) int { return i + 1 }
|
// var plus1 = func(i int) int { return i + 1 }
|
||||||
// Expect(1).To(WithTransform(plus1, Equal(2))
|
// Expect(1).To(WithTransform(plus1, Equal(2))
|
||||||
//
|
//
|
||||||
|
// var failingplus1 = func(i int) (int, error) { return 42, "this does not compute" }
|
||||||
|
// Expect(1).To(WithTransform(failingplus1, Equal(2)))
|
||||||
|
//
|
||||||
//And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions.
|
//And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions.
|
||||||
func WithTransform(transform interface{}, matcher types.GomegaMatcher) types.GomegaMatcher {
|
func WithTransform(transform interface{}, matcher types.GomegaMatcher) types.GomegaMatcher {
|
||||||
return matchers.NewWithTransformMatcher(transform, matcher)
|
return matchers.NewWithTransformMatcher(transform, matcher)
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package matchers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/onsi/gomega/format"
|
||||||
|
)
|
||||||
|
|
||||||
|
func extractField(actual interface{}, field string) (interface{}, error) {
|
||||||
|
fields := strings.SplitN(field, ".", 2)
|
||||||
|
actualValue := reflect.ValueOf(actual)
|
||||||
|
|
||||||
|
if actualValue.Kind() != reflect.Struct {
|
||||||
|
return nil, fmt.Errorf("HaveField encountered:\n%s\nWhich is not a struct.", format.Object(actual, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
var extractedValue reflect.Value
|
||||||
|
|
||||||
|
if strings.HasSuffix(fields[0], "()") {
|
||||||
|
extractedValue = actualValue.MethodByName(strings.TrimSuffix(fields[0], "()"))
|
||||||
|
if extractedValue == (reflect.Value{}) {
|
||||||
|
return nil, fmt.Errorf("HaveField could not find method named '%s' in struct of type %T.", fields[0], actual)
|
||||||
|
}
|
||||||
|
t := extractedValue.Type()
|
||||||
|
if t.NumIn() != 0 || t.NumOut() != 1 {
|
||||||
|
return nil, fmt.Errorf("HaveField found an invalid method named '%s' in struct of type %T.\nMethods must take no arguments and return exactly one value.", fields[0], actual)
|
||||||
|
}
|
||||||
|
extractedValue = extractedValue.Call([]reflect.Value{})[0]
|
||||||
|
} else {
|
||||||
|
extractedValue = actualValue.FieldByName(fields[0])
|
||||||
|
if extractedValue == (reflect.Value{}) {
|
||||||
|
return nil, fmt.Errorf("HaveField could not find field named '%s' in struct:\n%s", fields[0], format.Object(actual, 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fields) == 1 {
|
||||||
|
return extractedValue.Interface(), nil
|
||||||
|
} else {
|
||||||
|
return extractField(extractedValue.Interface(), fields[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type HaveFieldMatcher struct {
|
||||||
|
Field string
|
||||||
|
Expected interface{}
|
||||||
|
|
||||||
|
extractedField interface{}
|
||||||
|
expectedMatcher omegaMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (matcher *HaveFieldMatcher) Match(actual interface{}) (success bool, err error) {
|
||||||
|
matcher.extractedField, err = extractField(actual, matcher.Field)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var isMatcher bool
|
||||||
|
matcher.expectedMatcher, isMatcher = matcher.Expected.(omegaMatcher)
|
||||||
|
if !isMatcher {
|
||||||
|
matcher.expectedMatcher = &EqualMatcher{Expected: matcher.Expected}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matcher.expectedMatcher.Match(matcher.extractedField)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (matcher *HaveFieldMatcher) FailureMessage(actual interface{}) (message string) {
|
||||||
|
message = fmt.Sprintf("Value for field '%s' failed to satisfy matcher.\n", matcher.Field)
|
||||||
|
message += matcher.expectedMatcher.FailureMessage(matcher.extractedField)
|
||||||
|
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (matcher *HaveFieldMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||||
|
message = fmt.Sprintf("Value for field '%s' satisfied matcher, but should not have.\n", matcher.Field)
|
||||||
|
message += matcher.expectedMatcher.NegatedFailureMessage(matcher.extractedField)
|
||||||
|
|
||||||
|
return message
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package matchers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ func (matcher *HaveHTTPBodyMatcher) body(actual interface{}) ([]byte, error) {
|
||||||
if a.Body != nil {
|
if a.Body != nil {
|
||||||
defer a.Body.Close()
|
defer a.Body.Close()
|
||||||
var err error
|
var err error
|
||||||
matcher.cachedBody, err = ioutil.ReadAll(a.Body)
|
matcher.cachedBody, err = io.ReadAll(a.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading response body: %w", err)
|
return nil, fmt.Errorf("error reading response body: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package matchers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -78,7 +78,7 @@ func formatHttpResponse(input interface{}) string {
|
||||||
body := "<nil>"
|
body := "<nil>"
|
||||||
if resp.Body != nil {
|
if resp.Body != nil {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data = []byte("<error reading body>")
|
data = []byte("<error reading body>")
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
type WithTransformMatcher struct {
|
type WithTransformMatcher struct {
|
||||||
// input
|
// input
|
||||||
Transform interface{} // must be a function of one parameter that returns one value
|
Transform interface{} // must be a function of one parameter that returns one value and an optional error
|
||||||
Matcher types.GomegaMatcher
|
Matcher types.GomegaMatcher
|
||||||
|
|
||||||
// cached value
|
// cached value
|
||||||
|
@ -19,6 +19,9 @@ type WithTransformMatcher struct {
|
||||||
transformedValue interface{}
|
transformedValue interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reflect.Type for error
|
||||||
|
var errorT = reflect.TypeOf((*error)(nil)).Elem()
|
||||||
|
|
||||||
func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) *WithTransformMatcher {
|
func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) *WithTransformMatcher {
|
||||||
if transform == nil {
|
if transform == nil {
|
||||||
panic("transform function cannot be nil")
|
panic("transform function cannot be nil")
|
||||||
|
@ -27,8 +30,10 @@ func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher)
|
||||||
if txType.NumIn() != 1 {
|
if txType.NumIn() != 1 {
|
||||||
panic("transform function must have 1 argument")
|
panic("transform function must have 1 argument")
|
||||||
}
|
}
|
||||||
if txType.NumOut() != 1 {
|
if numout := txType.NumOut(); numout != 1 {
|
||||||
panic("transform function must have 1 return value")
|
if numout != 2 || !txType.Out(1).AssignableTo(errorT) {
|
||||||
|
panic("transform function must either have 1 return value, or 1 return value plus 1 error value")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &WithTransformMatcher{
|
return &WithTransformMatcher{
|
||||||
|
@ -57,6 +62,11 @@ func (m *WithTransformMatcher) Match(actual interface{}) (bool, error) {
|
||||||
// call the Transform function with `actual`
|
// call the Transform function with `actual`
|
||||||
fn := reflect.ValueOf(m.Transform)
|
fn := reflect.ValueOf(m.Transform)
|
||||||
result := fn.Call([]reflect.Value{param})
|
result := fn.Call([]reflect.Value{param})
|
||||||
|
if len(result) == 2 {
|
||||||
|
if !result[1].IsNil() {
|
||||||
|
return false, fmt.Errorf("Transform function failed: %s", result[1].Interface().(error).Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
m.transformedValue = result[0].Interface() // expect exactly one value
|
m.transformedValue = result[0].Interface() // expect exactly one value
|
||||||
|
|
||||||
return m.Matcher.Match(m.transformedValue)
|
return m.Matcher.Match(m.transformedValue)
|
||||||
|
|
|
@ -66,6 +66,10 @@ func MatchMayChangeInTheFuture(matcher GomegaMatcher, value interface{}) bool {
|
||||||
type AsyncAssertion interface {
|
type AsyncAssertion interface {
|
||||||
Should(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
Should(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
||||||
ShouldNot(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
ShouldNot(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
||||||
|
|
||||||
|
WithOffset(offset int) AsyncAssertion
|
||||||
|
WithTimeout(interval time.Duration) AsyncAssertion
|
||||||
|
WithPolling(interval time.Duration) AsyncAssertion
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assertions are returned by Ω and Expect and enable assertions against Gomega matchers
|
// Assertions are returned by Ω and Expect and enable assertions against Gomega matchers
|
||||||
|
@ -76,4 +80,8 @@ type Assertion interface {
|
||||||
To(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
To(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
||||||
ToNot(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
ToNot(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
||||||
NotTo(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
NotTo(matcher GomegaMatcher, optionalDescription ...interface{}) bool
|
||||||
|
|
||||||
|
WithOffset(offset int) Assertion
|
||||||
|
|
||||||
|
Error() Assertion
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Package require implements the same assertions as the `assert` package but
|
||||||
|
// stops test execution when a test fails.
|
||||||
|
//
|
||||||
|
// Example Usage
|
||||||
|
//
|
||||||
|
// The following is a complete example using require in a standard test function:
|
||||||
|
// import (
|
||||||
|
// "testing"
|
||||||
|
// "github.com/stretchr/testify/require"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func TestSomething(t *testing.T) {
|
||||||
|
//
|
||||||
|
// var a string = "Hello"
|
||||||
|
// var b string = "Hello"
|
||||||
|
//
|
||||||
|
// require.Equal(t, a, b, "The two words should be the same.")
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Assertions
|
||||||
|
//
|
||||||
|
// The `require` package have same global functions as in the `assert` package,
|
||||||
|
// but instead of returning a boolean result they call `t.FailNow()`.
|
||||||
|
//
|
||||||
|
// Every assertion function also takes an optional string message as the final argument,
|
||||||
|
// allowing custom error messages to be appended to the message the assertion method outputs.
|
||||||
|
package require
|
16
vendor/github.com/stretchr/testify/require/forward_requirements.go
generated
vendored
Normal file
16
vendor/github.com/stretchr/testify/require/forward_requirements.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package require
|
||||||
|
|
||||||
|
// Assertions provides assertion methods around the
|
||||||
|
// TestingT interface.
|
||||||
|
type Assertions struct {
|
||||||
|
t TestingT
|
||||||
|
}
|
||||||
|
|
||||||
|
// New makes a new Assertions object for the specified TestingT.
|
||||||
|
func New(t TestingT) *Assertions {
|
||||||
|
return &Assertions{
|
||||||
|
t: t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
{{.Comment}}
|
||||||
|
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
|
||||||
|
if h, ok := t.(tHelper); ok { h.Helper() }
|
||||||
|
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
|
||||||
|
t.FailNow()
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
||||||
|
{{.CommentWithoutT "a"}}
|
||||||
|
func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok { h.Helper() }
|
||||||
|
{{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package require
|
||||||
|
|
||||||
|
// TestingT is an interface wrapper around *testing.T
|
||||||
|
type TestingT interface {
|
||||||
|
Errorf(format string, args ...interface{})
|
||||||
|
FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
type tHelper interface {
|
||||||
|
Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
|
||||||
|
// for table driven tests.
|
||||||
|
type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{})
|
||||||
|
|
||||||
|
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
|
||||||
|
// for table driven tests.
|
||||||
|
type ValueAssertionFunc func(TestingT, interface{}, ...interface{})
|
||||||
|
|
||||||
|
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
|
||||||
|
// for table driven tests.
|
||||||
|
type BoolAssertionFunc func(TestingT, bool, ...interface{})
|
||||||
|
|
||||||
|
// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
|
||||||
|
// for table driven tests.
|
||||||
|
type ErrorAssertionFunc func(TestingT, error, ...interface{})
|
||||||
|
|
||||||
|
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs"
|
|
@ -1,4 +1,16 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## 1.19.1 (8 Sep 2021)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* [#1001][]: JSON: Fix complex number encoding with negative imaginary part. Thanks to @hemantjadon.
|
||||||
|
* [#1003][]: JSON: Fix inaccurate precision when encoding float32.
|
||||||
|
|
||||||
|
[#1001]: https://github.com/uber-go/zap/pull/1001
|
||||||
|
[#1003]: https://github.com/uber-go/zap/pull/1003
|
||||||
|
|
||||||
## 1.19.0 (9 Aug 2021)
|
## 1.19.0 (9 Aug 2021)
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,11 @@ func (enc *jsonEncoder) AddFloat64(key string, val float64) {
|
||||||
enc.AppendFloat64(val)
|
enc.AppendFloat64(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (enc *jsonEncoder) AddFloat32(key string, val float32) {
|
||||||
|
enc.addKey(key)
|
||||||
|
enc.AppendFloat32(val)
|
||||||
|
}
|
||||||
|
|
||||||
func (enc *jsonEncoder) AddInt64(key string, val int64) {
|
func (enc *jsonEncoder) AddInt64(key string, val int64) {
|
||||||
enc.addKey(key)
|
enc.addKey(key)
|
||||||
enc.AppendInt64(val)
|
enc.AppendInt64(val)
|
||||||
|
@ -228,7 +233,11 @@ func (enc *jsonEncoder) AppendComplex128(val complex128) {
|
||||||
// Because we're always in a quoted string, we can use strconv without
|
// Because we're always in a quoted string, we can use strconv without
|
||||||
// special-casing NaN and +/-Inf.
|
// special-casing NaN and +/-Inf.
|
||||||
enc.buf.AppendFloat(r, 64)
|
enc.buf.AppendFloat(r, 64)
|
||||||
enc.buf.AppendByte('+')
|
// If imaginary part is less than 0, minus (-) sign is added by default
|
||||||
|
// by AppendFloat.
|
||||||
|
if i >= 0 {
|
||||||
|
enc.buf.AppendByte('+')
|
||||||
|
}
|
||||||
enc.buf.AppendFloat(i, 64)
|
enc.buf.AppendFloat(i, 64)
|
||||||
enc.buf.AppendByte('i')
|
enc.buf.AppendByte('i')
|
||||||
enc.buf.AppendByte('"')
|
enc.buf.AppendByte('"')
|
||||||
|
@ -293,7 +302,6 @@ func (enc *jsonEncoder) AppendUint64(val uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
|
func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
|
||||||
func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) }
|
|
||||||
func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) }
|
func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) }
|
||||||
func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) }
|
func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) }
|
||||||
func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) }
|
func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) }
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
This is a work-in-progress HTTP/2 implementation for Go.
|
|
||||||
|
|
||||||
It will eventually live in the Go standard library and won't require
|
|
||||||
any changes to your code to use. It will just be automatic.
|
|
||||||
|
|
||||||
Status:
|
|
||||||
|
|
||||||
* The server support is pretty good. A few things are missing
|
|
||||||
but are being worked on.
|
|
||||||
* The client work has just started but shares a lot of code
|
|
||||||
is coming along much quicker.
|
|
||||||
|
|
||||||
Docs are at https://godoc.org/golang.org/x/net/http2
|
|
||||||
|
|
||||||
Demo test server at https://http2.golang.org/
|
|
||||||
|
|
||||||
Help & bug reports welcome!
|
|
||||||
|
|
||||||
Contributing: https://golang.org/doc/contribute.html
|
|
||||||
Bugs: https://golang.org/issue/new?title=x/net/http2:+
|
|
|
@ -6,6 +6,10 @@ package http2
|
||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
|
// The HTTP protocols are defined in terms of ASCII, not Unicode. This file
|
||||||
|
// contains helper functions which may use Unicode-aware functions which would
|
||||||
|
// otherwise be unsafe and could introduce vulnerabilities if used improperly.
|
||||||
|
|
||||||
// asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
|
// asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
|
||||||
// are equal, ASCII-case-insensitively.
|
// are equal, ASCII-case-insensitively.
|
||||||
func asciiEqualFold(s, t string) bool {
|
func asciiEqualFold(s, t string) bool {
|
||||||
|
|
|
@ -16,6 +16,12 @@ import (
|
||||||
|
|
||||||
// ClientConnPool manages a pool of HTTP/2 client connections.
|
// ClientConnPool manages a pool of HTTP/2 client connections.
|
||||||
type ClientConnPool interface {
|
type ClientConnPool interface {
|
||||||
|
// GetClientConn returns a specific HTTP/2 connection (usually
|
||||||
|
// a TLS-TCP connection) to an HTTP/2 server. On success, the
|
||||||
|
// returned ClientConn accounts for the upcoming RoundTrip
|
||||||
|
// call, so the caller should not omit it. If the caller needs
|
||||||
|
// to, ClientConn.RoundTrip can be called with a bogus
|
||||||
|
// new(http.Request) to release the stream reservation.
|
||||||
GetClientConn(req *http.Request, addr string) (*ClientConn, error)
|
GetClientConn(req *http.Request, addr string) (*ClientConn, error)
|
||||||
MarkDead(*ClientConn)
|
MarkDead(*ClientConn)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +48,7 @@ type clientConnPool struct {
|
||||||
conns map[string][]*ClientConn // key is host:port
|
conns map[string][]*ClientConn // key is host:port
|
||||||
dialing map[string]*dialCall // currently in-flight dials
|
dialing map[string]*dialCall // currently in-flight dials
|
||||||
keys map[*ClientConn][]string
|
keys map[*ClientConn][]string
|
||||||
addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
|
addConnCalls map[string]*addConnCall // in-flight addConnIfNeeded calls
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
|
func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
|
||||||
|
@ -54,28 +60,8 @@ const (
|
||||||
noDialOnMiss = false
|
noDialOnMiss = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// shouldTraceGetConn reports whether getClientConn should call any
|
|
||||||
// ClientTrace.GetConn hook associated with the http.Request.
|
|
||||||
//
|
|
||||||
// This complexity is needed to avoid double calls of the GetConn hook
|
|
||||||
// during the back-and-forth between net/http and x/net/http2 (when the
|
|
||||||
// net/http.Transport is upgraded to also speak http2), as well as support
|
|
||||||
// the case where x/net/http2 is being used directly.
|
|
||||||
func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
|
|
||||||
// If our Transport wasn't made via ConfigureTransport, always
|
|
||||||
// trace the GetConn hook if provided, because that means the
|
|
||||||
// http2 package is being used directly and it's the one
|
|
||||||
// dialing, as opposed to net/http.
|
|
||||||
if _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Otherwise, only use the GetConn hook if this connection has
|
|
||||||
// been used previously for other requests. For fresh
|
|
||||||
// connections, the net/http package does the dialing.
|
|
||||||
return !st.freshConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
|
||||||
|
// TODO(dneil): Dial a new connection when t.DisableKeepAlives is set?
|
||||||
if isConnectionCloseRequest(req) && dialOnMiss {
|
if isConnectionCloseRequest(req) && dialOnMiss {
|
||||||
// It gets its own connection.
|
// It gets its own connection.
|
||||||
traceGetConn(req, addr)
|
traceGetConn(req, addr)
|
||||||
|
@ -89,10 +75,14 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
|
||||||
for {
|
for {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
for _, cc := range p.conns[addr] {
|
for _, cc := range p.conns[addr] {
|
||||||
if st := cc.idleState(); st.canTakeNewRequest {
|
if cc.ReserveNewRequest() {
|
||||||
if p.shouldTraceGetConn(st) {
|
// When a connection is presented to us by the net/http package,
|
||||||
|
// the GetConn hook has already been called.
|
||||||
|
// Don't call it a second time here.
|
||||||
|
if !cc.getConnCalled {
|
||||||
traceGetConn(req, addr)
|
traceGetConn(req, addr)
|
||||||
}
|
}
|
||||||
|
cc.getConnCalled = false
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
return cc, nil
|
return cc, nil
|
||||||
}
|
}
|
||||||
|
@ -108,7 +98,13 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
|
||||||
if shouldRetryDial(call, req) {
|
if shouldRetryDial(call, req) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return call.res, call.err
|
cc, err := call.res, call.err
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if cc.ReserveNewRequest() {
|
||||||
|
return cc, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +201,7 @@ func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.err = err
|
c.err = err
|
||||||
} else {
|
} else {
|
||||||
|
cc.getConnCalled = true // already called by the net/http package
|
||||||
p.addConnLocked(key, cc)
|
p.addConnLocked(key, cc)
|
||||||
}
|
}
|
||||||
delete(p.addConnCalls, key)
|
delete(p.addConnCalls, key)
|
||||||
|
|
|
@ -53,6 +53,13 @@ func (e ErrCode) String() string {
|
||||||
return fmt.Sprintf("unknown error code 0x%x", uint32(e))
|
return fmt.Sprintf("unknown error code 0x%x", uint32(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e ErrCode) stringToken() string {
|
||||||
|
if s, ok := errCodeName[e]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("ERR_UNKNOWN_%d", uint32(e))
|
||||||
|
}
|
||||||
|
|
||||||
// ConnectionError is an error that results in the termination of the
|
// ConnectionError is an error that results in the termination of the
|
||||||
// entire connection.
|
// entire connection.
|
||||||
type ConnectionError ErrCode
|
type ConnectionError ErrCode
|
||||||
|
@ -67,6 +74,11 @@ type StreamError struct {
|
||||||
Cause error // optional additional detail
|
Cause error // optional additional detail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// errFromPeer is a sentinel error value for StreamError.Cause to
|
||||||
|
// indicate that the StreamError was sent from the peer over the wire
|
||||||
|
// and wasn't locally generated in the Transport.
|
||||||
|
var errFromPeer = errors.New("received from peer")
|
||||||
|
|
||||||
func streamError(id uint32, code ErrCode) StreamError {
|
func streamError(id uint32, code ErrCode) StreamError {
|
||||||
return StreamError{StreamID: id, Code: code}
|
return StreamError{StreamID: id, Code: code}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ var flagName = map[FrameType]map[Flags]string{
|
||||||
// a frameParser parses a frame given its FrameHeader and payload
|
// a frameParser parses a frame given its FrameHeader and payload
|
||||||
// bytes. The length of payload will always equal fh.Length (which
|
// bytes. The length of payload will always equal fh.Length (which
|
||||||
// might be 0).
|
// might be 0).
|
||||||
type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
|
type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error)
|
||||||
|
|
||||||
var frameParsers = map[FrameType]frameParser{
|
var frameParsers = map[FrameType]frameParser{
|
||||||
FrameData: parseDataFrame,
|
FrameData: parseDataFrame,
|
||||||
|
@ -267,6 +267,11 @@ type Framer struct {
|
||||||
lastFrame Frame
|
lastFrame Frame
|
||||||
errDetail error
|
errDetail error
|
||||||
|
|
||||||
|
// countError is a non-nil func that's called on a frame parse
|
||||||
|
// error with some unique error path token. It's initialized
|
||||||
|
// from Transport.CountError or Server.CountError.
|
||||||
|
countError func(errToken string)
|
||||||
|
|
||||||
// lastHeaderStream is non-zero if the last frame was an
|
// lastHeaderStream is non-zero if the last frame was an
|
||||||
// unfinished HEADERS/CONTINUATION.
|
// unfinished HEADERS/CONTINUATION.
|
||||||
lastHeaderStream uint32
|
lastHeaderStream uint32
|
||||||
|
@ -426,6 +431,7 @@ func NewFramer(w io.Writer, r io.Reader) *Framer {
|
||||||
fr := &Framer{
|
fr := &Framer{
|
||||||
w: w,
|
w: w,
|
||||||
r: r,
|
r: r,
|
||||||
|
countError: func(string) {},
|
||||||
logReads: logFrameReads,
|
logReads: logFrameReads,
|
||||||
logWrites: logFrameWrites,
|
logWrites: logFrameWrites,
|
||||||
debugReadLoggerf: log.Printf,
|
debugReadLoggerf: log.Printf,
|
||||||
|
@ -500,7 +506,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
|
||||||
if _, err := io.ReadFull(fr.r, payload); err != nil {
|
if _, err := io.ReadFull(fr.r, payload); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
|
f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ce, ok := err.(connError); ok {
|
if ce, ok := err.(connError); ok {
|
||||||
return nil, fr.connError(ce.Code, ce.Reason)
|
return nil, fr.connError(ce.Code, ce.Reason)
|
||||||
|
@ -588,13 +594,14 @@ func (f *DataFrame) Data() []byte {
|
||||||
return f.data
|
return f.data
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
|
func parseDataFrame(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
// DATA frames MUST be associated with a stream. If a
|
// DATA frames MUST be associated with a stream. If a
|
||||||
// DATA frame is received whose stream identifier
|
// DATA frame is received whose stream identifier
|
||||||
// field is 0x0, the recipient MUST respond with a
|
// field is 0x0, the recipient MUST respond with a
|
||||||
// connection error (Section 5.4.1) of type
|
// connection error (Section 5.4.1) of type
|
||||||
// PROTOCOL_ERROR.
|
// PROTOCOL_ERROR.
|
||||||
|
countError("frame_data_stream_0")
|
||||||
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
|
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
|
||||||
}
|
}
|
||||||
f := fc.getDataFrame()
|
f := fc.getDataFrame()
|
||||||
|
@ -605,6 +612,7 @@ func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, erro
|
||||||
var err error
|
var err error
|
||||||
payload, padSize, err = readByte(payload)
|
payload, padSize, err = readByte(payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
countError("frame_data_pad_byte_short")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -613,6 +621,7 @@ func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, erro
|
||||||
// length of the frame payload, the recipient MUST
|
// length of the frame payload, the recipient MUST
|
||||||
// treat this as a connection error.
|
// treat this as a connection error.
|
||||||
// Filed: https://github.com/http2/http2-spec/issues/610
|
// Filed: https://github.com/http2/http2-spec/issues/610
|
||||||
|
countError("frame_data_pad_too_big")
|
||||||
return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
|
return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
|
||||||
}
|
}
|
||||||
f.data = payload[:len(payload)-int(padSize)]
|
f.data = payload[:len(payload)-int(padSize)]
|
||||||
|
@ -695,7 +704,7 @@ type SettingsFrame struct {
|
||||||
p []byte
|
p []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
func parseSettingsFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
|
||||||
if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
|
if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
|
||||||
// When this (ACK 0x1) bit is set, the payload of the
|
// When this (ACK 0x1) bit is set, the payload of the
|
||||||
// SETTINGS frame MUST be empty. Receipt of a
|
// SETTINGS frame MUST be empty. Receipt of a
|
||||||
|
@ -703,6 +712,7 @@ func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error)
|
||||||
// field value other than 0 MUST be treated as a
|
// field value other than 0 MUST be treated as a
|
||||||
// connection error (Section 5.4.1) of type
|
// connection error (Section 5.4.1) of type
|
||||||
// FRAME_SIZE_ERROR.
|
// FRAME_SIZE_ERROR.
|
||||||
|
countError("frame_settings_ack_with_length")
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
if fh.StreamID != 0 {
|
if fh.StreamID != 0 {
|
||||||
|
@ -713,14 +723,17 @@ func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error)
|
||||||
// field is anything other than 0x0, the endpoint MUST
|
// field is anything other than 0x0, the endpoint MUST
|
||||||
// respond with a connection error (Section 5.4.1) of
|
// respond with a connection error (Section 5.4.1) of
|
||||||
// type PROTOCOL_ERROR.
|
// type PROTOCOL_ERROR.
|
||||||
|
countError("frame_settings_has_stream")
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
if len(p)%6 != 0 {
|
if len(p)%6 != 0 {
|
||||||
|
countError("frame_settings_mod_6")
|
||||||
// Expecting even number of 6 byte settings.
|
// Expecting even number of 6 byte settings.
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
f := &SettingsFrame{FrameHeader: fh, p: p}
|
f := &SettingsFrame{FrameHeader: fh, p: p}
|
||||||
if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
|
if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
|
||||||
|
countError("frame_settings_window_size_too_big")
|
||||||
// Values above the maximum flow control window size of 2^31 - 1 MUST
|
// Values above the maximum flow control window size of 2^31 - 1 MUST
|
||||||
// be treated as a connection error (Section 5.4.1) of type
|
// be treated as a connection error (Section 5.4.1) of type
|
||||||
// FLOW_CONTROL_ERROR.
|
// FLOW_CONTROL_ERROR.
|
||||||
|
@ -832,11 +845,13 @@ type PingFrame struct {
|
||||||
|
|
||||||
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
|
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
|
||||||
|
|
||||||
func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
|
func parsePingFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
|
||||||
if len(payload) != 8 {
|
if len(payload) != 8 {
|
||||||
|
countError("frame_ping_length")
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
if fh.StreamID != 0 {
|
if fh.StreamID != 0 {
|
||||||
|
countError("frame_ping_has_stream")
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
f := &PingFrame{FrameHeader: fh}
|
f := &PingFrame{FrameHeader: fh}
|
||||||
|
@ -872,11 +887,13 @@ func (f *GoAwayFrame) DebugData() []byte {
|
||||||
return f.debugData
|
return f.debugData
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
func parseGoAwayFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
|
||||||
if fh.StreamID != 0 {
|
if fh.StreamID != 0 {
|
||||||
|
countError("frame_goaway_has_stream")
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
if len(p) < 8 {
|
if len(p) < 8 {
|
||||||
|
countError("frame_goaway_short")
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
return &GoAwayFrame{
|
return &GoAwayFrame{
|
||||||
|
@ -912,7 +929,7 @@ func (f *UnknownFrame) Payload() []byte {
|
||||||
return f.p
|
return f.p
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
func parseUnknownFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
|
||||||
return &UnknownFrame{fh, p}, nil
|
return &UnknownFrame{fh, p}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,8 +940,9 @@ type WindowUpdateFrame struct {
|
||||||
Increment uint32 // never read with high bit set
|
Increment uint32 // never read with high bit set
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
|
||||||
if len(p) != 4 {
|
if len(p) != 4 {
|
||||||
|
countError("frame_windowupdate_bad_len")
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
|
inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
|
||||||
|
@ -936,8 +954,10 @@ func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, err
|
||||||
// control window MUST be treated as a connection
|
// control window MUST be treated as a connection
|
||||||
// error (Section 5.4.1).
|
// error (Section 5.4.1).
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
|
countError("frame_windowupdate_zero_inc_conn")
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
|
countError("frame_windowupdate_zero_inc_stream")
|
||||||
return nil, streamError(fh.StreamID, ErrCodeProtocol)
|
return nil, streamError(fh.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
return &WindowUpdateFrame{
|
return &WindowUpdateFrame{
|
||||||
|
@ -988,7 +1008,7 @@ func (f *HeadersFrame) HasPriority() bool {
|
||||||
return f.FrameHeader.Flags.Has(FlagHeadersPriority)
|
return f.FrameHeader.Flags.Has(FlagHeadersPriority)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
|
func parseHeadersFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
|
||||||
hf := &HeadersFrame{
|
hf := &HeadersFrame{
|
||||||
FrameHeader: fh,
|
FrameHeader: fh,
|
||||||
}
|
}
|
||||||
|
@ -997,11 +1017,13 @@ func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err er
|
||||||
// is received whose stream identifier field is 0x0, the recipient MUST
|
// is received whose stream identifier field is 0x0, the recipient MUST
|
||||||
// respond with a connection error (Section 5.4.1) of type
|
// respond with a connection error (Section 5.4.1) of type
|
||||||
// PROTOCOL_ERROR.
|
// PROTOCOL_ERROR.
|
||||||
|
countError("frame_headers_zero_stream")
|
||||||
return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
|
return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
|
||||||
}
|
}
|
||||||
var padLength uint8
|
var padLength uint8
|
||||||
if fh.Flags.Has(FlagHeadersPadded) {
|
if fh.Flags.Has(FlagHeadersPadded) {
|
||||||
if p, padLength, err = readByte(p); err != nil {
|
if p, padLength, err = readByte(p); err != nil {
|
||||||
|
countError("frame_headers_pad_short")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1009,16 +1031,19 @@ func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err er
|
||||||
var v uint32
|
var v uint32
|
||||||
p, v, err = readUint32(p)
|
p, v, err = readUint32(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
countError("frame_headers_prio_short")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hf.Priority.StreamDep = v & 0x7fffffff
|
hf.Priority.StreamDep = v & 0x7fffffff
|
||||||
hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
|
hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
|
||||||
p, hf.Priority.Weight, err = readByte(p)
|
p, hf.Priority.Weight, err = readByte(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
countError("frame_headers_prio_weight_short")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(p)-int(padLength) <= 0 {
|
if len(p)-int(padLength) < 0 {
|
||||||
|
countError("frame_headers_pad_too_big")
|
||||||
return nil, streamError(fh.StreamID, ErrCodeProtocol)
|
return nil, streamError(fh.StreamID, ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
hf.headerFragBuf = p[:len(p)-int(padLength)]
|
hf.headerFragBuf = p[:len(p)-int(padLength)]
|
||||||
|
@ -1125,11 +1150,13 @@ func (p PriorityParam) IsZero() bool {
|
||||||
return p == PriorityParam{}
|
return p == PriorityParam{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
|
func parsePriorityFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
|
countError("frame_priority_zero_stream")
|
||||||
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
|
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
|
||||||
}
|
}
|
||||||
if len(payload) != 5 {
|
if len(payload) != 5 {
|
||||||
|
countError("frame_priority_bad_length")
|
||||||
return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
|
return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
|
||||||
}
|
}
|
||||||
v := binary.BigEndian.Uint32(payload[:4])
|
v := binary.BigEndian.Uint32(payload[:4])
|
||||||
|
@ -1172,11 +1199,13 @@ type RSTStreamFrame struct {
|
||||||
ErrCode ErrCode
|
ErrCode ErrCode
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
|
||||||
if len(p) != 4 {
|
if len(p) != 4 {
|
||||||
|
countError("frame_rststream_bad_len")
|
||||||
return nil, ConnectionError(ErrCodeFrameSize)
|
return nil, ConnectionError(ErrCodeFrameSize)
|
||||||
}
|
}
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
|
countError("frame_rststream_zero_stream")
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
|
return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
|
||||||
|
@ -1202,8 +1231,9 @@ type ContinuationFrame struct {
|
||||||
headerFragBuf []byte
|
headerFragBuf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
|
func parseContinuationFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
|
||||||
if fh.StreamID == 0 {
|
if fh.StreamID == 0 {
|
||||||
|
countError("frame_continuation_zero_stream")
|
||||||
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
|
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
|
||||||
}
|
}
|
||||||
return &ContinuationFrame{fh, p}, nil
|
return &ContinuationFrame{fh, p}, nil
|
||||||
|
@ -1252,7 +1282,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool {
|
||||||
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
|
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
|
func parsePushPromise(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
|
||||||
pp := &PushPromiseFrame{
|
pp := &PushPromiseFrame{
|
||||||
FrameHeader: fh,
|
FrameHeader: fh,
|
||||||
}
|
}
|
||||||
|
@ -1263,6 +1293,7 @@ func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err err
|
||||||
// with. If the stream identifier field specifies the value
|
// with. If the stream identifier field specifies the value
|
||||||
// 0x0, a recipient MUST respond with a connection error
|
// 0x0, a recipient MUST respond with a connection error
|
||||||
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||||
|
countError("frame_pushpromise_zero_stream")
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
// The PUSH_PROMISE frame includes optional padding.
|
// The PUSH_PROMISE frame includes optional padding.
|
||||||
|
@ -1270,18 +1301,21 @@ func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err err
|
||||||
var padLength uint8
|
var padLength uint8
|
||||||
if fh.Flags.Has(FlagPushPromisePadded) {
|
if fh.Flags.Has(FlagPushPromisePadded) {
|
||||||
if p, padLength, err = readByte(p); err != nil {
|
if p, padLength, err = readByte(p); err != nil {
|
||||||
|
countError("frame_pushpromise_pad_short")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p, pp.PromiseID, err = readUint32(p)
|
p, pp.PromiseID, err = readUint32(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
countError("frame_pushpromise_promiseid_short")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pp.PromiseID = pp.PromiseID & (1<<31 - 1)
|
pp.PromiseID = pp.PromiseID & (1<<31 - 1)
|
||||||
|
|
||||||
if int(padLength) > len(p) {
|
if int(padLength) > len(p) {
|
||||||
// like the DATA frame, error out if padding is longer than the body.
|
// like the DATA frame, error out if padding is longer than the body.
|
||||||
|
countError("frame_pushpromise_pad_too_big")
|
||||||
return nil, ConnectionError(ErrCodeProtocol)
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
}
|
}
|
||||||
pp.headerFragBuf = p[:len(p)-int(padLength)]
|
pp.headerFragBuf = p[:len(p)-int(padLength)]
|
||||||
|
|
|
@ -140,25 +140,29 @@ func buildRootHuffmanNode() {
|
||||||
panic("unexpected size")
|
panic("unexpected size")
|
||||||
}
|
}
|
||||||
lazyRootHuffmanNode = newInternalNode()
|
lazyRootHuffmanNode = newInternalNode()
|
||||||
for i, code := range huffmanCodes {
|
// allocate a leaf node for each of the 256 symbols
|
||||||
addDecoderNode(byte(i), code, huffmanCodeLen[i])
|
leaves := new([256]node)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func addDecoderNode(sym byte, code uint32, codeLen uint8) {
|
for sym, code := range huffmanCodes {
|
||||||
cur := lazyRootHuffmanNode
|
codeLen := huffmanCodeLen[sym]
|
||||||
for codeLen > 8 {
|
|
||||||
codeLen -= 8
|
cur := lazyRootHuffmanNode
|
||||||
i := uint8(code >> codeLen)
|
for codeLen > 8 {
|
||||||
if cur.children[i] == nil {
|
codeLen -= 8
|
||||||
cur.children[i] = newInternalNode()
|
i := uint8(code >> codeLen)
|
||||||
|
if cur.children[i] == nil {
|
||||||
|
cur.children[i] = newInternalNode()
|
||||||
|
}
|
||||||
|
cur = cur.children[i]
|
||||||
|
}
|
||||||
|
shift := 8 - codeLen
|
||||||
|
start, end := int(uint8(code<<shift)), int(1<<shift)
|
||||||
|
|
||||||
|
leaves[sym].sym = byte(sym)
|
||||||
|
leaves[sym].codeLen = codeLen
|
||||||
|
for i := start; i < start+end; i++ {
|
||||||
|
cur.children[i] = &leaves[sym]
|
||||||
}
|
}
|
||||||
cur = cur.children[i]
|
|
||||||
}
|
|
||||||
shift := 8 - codeLen
|
|
||||||
start, end := int(uint8(code<<shift)), int(1<<shift)
|
|
||||||
for i := start; i < start+end; i++ {
|
|
||||||
cur.children[i] = &node{sym: sym, codeLen: codeLen}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,17 @@ type pipeBuffer interface {
|
||||||
io.Reader
|
io.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setBuffer initializes the pipe buffer.
|
||||||
|
// It has no effect if the pipe is already closed.
|
||||||
|
func (p *pipe) setBuffer(b pipeBuffer) {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
if p.err != nil || p.breakErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.b = b
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pipe) Len() int {
|
func (p *pipe) Len() int {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
|
@ -130,6 +130,12 @@ type Server struct {
|
||||||
// If nil, a default scheduler is chosen.
|
// If nil, a default scheduler is chosen.
|
||||||
NewWriteScheduler func() WriteScheduler
|
NewWriteScheduler func() WriteScheduler
|
||||||
|
|
||||||
|
// CountError, if non-nil, is called on HTTP/2 server errors.
|
||||||
|
// It's intended to increment a metric for monitoring, such
|
||||||
|
// as an expvar or Prometheus metric.
|
||||||
|
// The errType consists of only ASCII word characters.
|
||||||
|
CountError func(errType string)
|
||||||
|
|
||||||
// Internal state. This is a pointer (rather than embedded directly)
|
// Internal state. This is a pointer (rather than embedded directly)
|
||||||
// so that we don't embed a Mutex in this struct, which will make the
|
// so that we don't embed a Mutex in this struct, which will make the
|
||||||
// struct non-copyable, which might break some callers.
|
// struct non-copyable, which might break some callers.
|
||||||
|
@ -259,16 +265,12 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
||||||
|
|
||||||
s.TLSConfig.PreferServerCipherSuites = true
|
s.TLSConfig.PreferServerCipherSuites = true
|
||||||
|
|
||||||
haveNPN := false
|
if !strSliceContains(s.TLSConfig.NextProtos, NextProtoTLS) {
|
||||||
for _, p := range s.TLSConfig.NextProtos {
|
|
||||||
if p == NextProtoTLS {
|
|
||||||
haveNPN = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !haveNPN {
|
|
||||||
s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
|
s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
|
||||||
}
|
}
|
||||||
|
if !strSliceContains(s.TLSConfig.NextProtos, "http/1.1") {
|
||||||
|
s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, "http/1.1")
|
||||||
|
}
|
||||||
|
|
||||||
if s.TLSNextProto == nil {
|
if s.TLSNextProto == nil {
|
||||||
s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
|
s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
|
||||||
|
@ -409,6 +411,9 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
||||||
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
||||||
|
|
||||||
fr := NewFramer(sc.bw, c)
|
fr := NewFramer(sc.bw, c)
|
||||||
|
if s.CountError != nil {
|
||||||
|
fr.countError = s.CountError
|
||||||
|
}
|
||||||
fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
|
fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
|
||||||
fr.MaxHeaderListSize = sc.maxHeaderListSize()
|
fr.MaxHeaderListSize = sc.maxHeaderListSize()
|
||||||
fr.SetMaxReadFrameSize(s.maxReadFrameSize())
|
fr.SetMaxReadFrameSize(s.maxReadFrameSize())
|
||||||
|
@ -714,7 +719,15 @@ func (sc *serverConn) canonicalHeader(v string) string {
|
||||||
sc.canonHeader = make(map[string]string)
|
sc.canonHeader = make(map[string]string)
|
||||||
}
|
}
|
||||||
cv = http.CanonicalHeaderKey(v)
|
cv = http.CanonicalHeaderKey(v)
|
||||||
sc.canonHeader[v] = cv
|
// maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
|
||||||
|
// entries in the canonHeader cache. This should be larger than the number
|
||||||
|
// of unique, uncommon header keys likely to be sent by the peer, while not
|
||||||
|
// so high as to permit unreaasonable memory usage if the peer sends an unbounded
|
||||||
|
// number of unique header keys.
|
||||||
|
const maxCachedCanonicalHeaders = 32
|
||||||
|
if len(sc.canonHeader) < maxCachedCanonicalHeaders {
|
||||||
|
sc.canonHeader[v] = cv
|
||||||
|
}
|
||||||
return cv
|
return cv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,7 +833,7 @@ func (sc *serverConn) serve() {
|
||||||
})
|
})
|
||||||
sc.unackedSettings++
|
sc.unackedSettings++
|
||||||
|
|
||||||
// Each connection starts with intialWindowSize inflow tokens.
|
// Each connection starts with initialWindowSize inflow tokens.
|
||||||
// If a higher value is configured, we add more tokens.
|
// If a higher value is configured, we add more tokens.
|
||||||
if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
|
if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
|
||||||
sc.sendWindowUpdate(nil, int(diff))
|
sc.sendWindowUpdate(nil, int(diff))
|
||||||
|
@ -860,6 +873,15 @@ func (sc *serverConn) serve() {
|
||||||
case res := <-sc.wroteFrameCh:
|
case res := <-sc.wroteFrameCh:
|
||||||
sc.wroteFrame(res)
|
sc.wroteFrame(res)
|
||||||
case res := <-sc.readFrameCh:
|
case res := <-sc.readFrameCh:
|
||||||
|
// Process any written frames before reading new frames from the client since a
|
||||||
|
// written frame could have triggered a new stream to be started.
|
||||||
|
if sc.writingFrameAsync {
|
||||||
|
select {
|
||||||
|
case wroteRes := <-sc.wroteFrameCh:
|
||||||
|
sc.wroteFrame(wroteRes)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
if !sc.processFrameFromReader(res) {
|
if !sc.processFrameFromReader(res) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1394,7 +1416,7 @@ func (sc *serverConn) processFrame(f Frame) error {
|
||||||
// First frame received must be SETTINGS.
|
// First frame received must be SETTINGS.
|
||||||
if !sc.sawFirstSettings {
|
if !sc.sawFirstSettings {
|
||||||
if _, ok := f.(*SettingsFrame); !ok {
|
if _, ok := f.(*SettingsFrame); !ok {
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("first_settings", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
sc.sawFirstSettings = true
|
sc.sawFirstSettings = true
|
||||||
}
|
}
|
||||||
|
@ -1419,7 +1441,7 @@ func (sc *serverConn) processFrame(f Frame) error {
|
||||||
case *PushPromiseFrame:
|
case *PushPromiseFrame:
|
||||||
// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
|
// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
|
||||||
// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("push_promise", ConnectionError(ErrCodeProtocol))
|
||||||
default:
|
default:
|
||||||
sc.vlogf("http2: server ignoring frame: %v", f.Header())
|
sc.vlogf("http2: server ignoring frame: %v", f.Header())
|
||||||
return nil
|
return nil
|
||||||
|
@ -1439,7 +1461,7 @@ func (sc *serverConn) processPing(f *PingFrame) error {
|
||||||
// identifier field value other than 0x0, the recipient MUST
|
// identifier field value other than 0x0, the recipient MUST
|
||||||
// respond with a connection error (Section 5.4.1) of type
|
// respond with a connection error (Section 5.4.1) of type
|
||||||
// PROTOCOL_ERROR."
|
// PROTOCOL_ERROR."
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
|
if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
|
||||||
return nil
|
return nil
|
||||||
|
@ -1458,7 +1480,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
|
||||||
// or PRIORITY on a stream in this state MUST be
|
// or PRIORITY on a stream in this state MUST be
|
||||||
// treated as a connection error (Section 5.4.1) of
|
// treated as a connection error (Section 5.4.1) of
|
||||||
// type PROTOCOL_ERROR."
|
// type PROTOCOL_ERROR."
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("stream_idle", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
if st == nil {
|
if st == nil {
|
||||||
// "WINDOW_UPDATE can be sent by a peer that has sent a
|
// "WINDOW_UPDATE can be sent by a peer that has sent a
|
||||||
|
@ -1469,7 +1491,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !st.flow.add(int32(f.Increment)) {
|
if !st.flow.add(int32(f.Increment)) {
|
||||||
return streamError(f.StreamID, ErrCodeFlowControl)
|
return sc.countError("bad_flow", streamError(f.StreamID, ErrCodeFlowControl))
|
||||||
}
|
}
|
||||||
default: // connection-level flow control
|
default: // connection-level flow control
|
||||||
if !sc.flow.add(int32(f.Increment)) {
|
if !sc.flow.add(int32(f.Increment)) {
|
||||||
|
@ -1490,7 +1512,7 @@ func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
|
||||||
// identifying an idle stream is received, the
|
// identifying an idle stream is received, the
|
||||||
// recipient MUST treat this as a connection error
|
// recipient MUST treat this as a connection error
|
||||||
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("reset_idle_stream", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
if st != nil {
|
if st != nil {
|
||||||
st.cancelCtx()
|
st.cancelCtx()
|
||||||
|
@ -1542,7 +1564,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
|
||||||
// Why is the peer ACKing settings we never sent?
|
// Why is the peer ACKing settings we never sent?
|
||||||
// The spec doesn't mention this case, but
|
// The spec doesn't mention this case, but
|
||||||
// hang up on them anyway.
|
// hang up on them anyway.
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("ack_mystery", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1550,7 +1572,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
|
||||||
// This isn't actually in the spec, but hang up on
|
// This isn't actually in the spec, but hang up on
|
||||||
// suspiciously large settings frames or those with
|
// suspiciously large settings frames or those with
|
||||||
// duplicate entries.
|
// duplicate entries.
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("settings_big_or_dups", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
if err := f.ForeachSetting(sc.processSetting); err != nil {
|
if err := f.ForeachSetting(sc.processSetting); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1617,7 +1639,7 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
|
||||||
// control window to exceed the maximum size as a
|
// control window to exceed the maximum size as a
|
||||||
// connection error (Section 5.4.1) of type
|
// connection error (Section 5.4.1) of type
|
||||||
// FLOW_CONTROL_ERROR."
|
// FLOW_CONTROL_ERROR."
|
||||||
return ConnectionError(ErrCodeFlowControl)
|
return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -1650,7 +1672,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
||||||
// or PRIORITY on a stream in this state MUST be
|
// or PRIORITY on a stream in this state MUST be
|
||||||
// treated as a connection error (Section 5.4.1) of
|
// treated as a connection error (Section 5.4.1) of
|
||||||
// type PROTOCOL_ERROR."
|
// type PROTOCOL_ERROR."
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("data_on_idle", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
// "If a DATA frame is received whose stream is not in "open"
|
// "If a DATA frame is received whose stream is not in "open"
|
||||||
|
@ -1667,7 +1689,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
||||||
// and return any flow control bytes since we're not going
|
// and return any flow control bytes since we're not going
|
||||||
// to consume them.
|
// to consume them.
|
||||||
if sc.inflow.available() < int32(f.Length) {
|
if sc.inflow.available() < int32(f.Length) {
|
||||||
return streamError(id, ErrCodeFlowControl)
|
return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
|
||||||
}
|
}
|
||||||
// Deduct the flow control from inflow, since we're
|
// Deduct the flow control from inflow, since we're
|
||||||
// going to immediately add it back in
|
// going to immediately add it back in
|
||||||
|
@ -1680,7 +1702,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
||||||
// Already have a stream error in flight. Don't send another.
|
// Already have a stream error in flight. Don't send another.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return streamError(id, ErrCodeStreamClosed)
|
return sc.countError("closed", streamError(id, ErrCodeStreamClosed))
|
||||||
}
|
}
|
||||||
if st.body == nil {
|
if st.body == nil {
|
||||||
panic("internal error: should have a body in this state")
|
panic("internal error: should have a body in this state")
|
||||||
|
@ -1692,12 +1714,12 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
||||||
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
|
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
|
||||||
// value of a content-length header field does not equal the sum of the
|
// value of a content-length header field does not equal the sum of the
|
||||||
// DATA frame payload lengths that form the body.
|
// DATA frame payload lengths that form the body.
|
||||||
return streamError(id, ErrCodeProtocol)
|
return sc.countError("send_too_much", streamError(id, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
if f.Length > 0 {
|
if f.Length > 0 {
|
||||||
// Check whether the client has flow control quota.
|
// Check whether the client has flow control quota.
|
||||||
if st.inflow.available() < int32(f.Length) {
|
if st.inflow.available() < int32(f.Length) {
|
||||||
return streamError(id, ErrCodeFlowControl)
|
return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))
|
||||||
}
|
}
|
||||||
st.inflow.take(int32(f.Length))
|
st.inflow.take(int32(f.Length))
|
||||||
|
|
||||||
|
@ -1705,7 +1727,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
||||||
wrote, err := st.body.Write(data)
|
wrote, err := st.body.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sc.sendWindowUpdate(nil, int(f.Length)-wrote)
|
sc.sendWindowUpdate(nil, int(f.Length)-wrote)
|
||||||
return streamError(id, ErrCodeStreamClosed)
|
return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed))
|
||||||
}
|
}
|
||||||
if wrote != len(data) {
|
if wrote != len(data) {
|
||||||
panic("internal error: bad Writer")
|
panic("internal error: bad Writer")
|
||||||
|
@ -1791,7 +1813,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||||
// stream identifier MUST respond with a connection error
|
// stream identifier MUST respond with a connection error
|
||||||
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||||
if id%2 != 1 {
|
if id%2 != 1 {
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("headers_even", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
// A HEADERS frame can be used to create a new stream or
|
// A HEADERS frame can be used to create a new stream or
|
||||||
// send a trailer for an open one. If we already have a stream
|
// send a trailer for an open one. If we already have a stream
|
||||||
|
@ -1808,7 +1830,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||||
// this state, it MUST respond with a stream error (Section 5.4.2) of
|
// this state, it MUST respond with a stream error (Section 5.4.2) of
|
||||||
// type STREAM_CLOSED.
|
// type STREAM_CLOSED.
|
||||||
if st.state == stateHalfClosedRemote {
|
if st.state == stateHalfClosedRemote {
|
||||||
return streamError(id, ErrCodeStreamClosed)
|
return sc.countError("headers_half_closed", streamError(id, ErrCodeStreamClosed))
|
||||||
}
|
}
|
||||||
return st.processTrailerHeaders(f)
|
return st.processTrailerHeaders(f)
|
||||||
}
|
}
|
||||||
|
@ -1819,7 +1841,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||||
// receives an unexpected stream identifier MUST respond with
|
// receives an unexpected stream identifier MUST respond with
|
||||||
// a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
// a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||||
if id <= sc.maxClientStreamID {
|
if id <= sc.maxClientStreamID {
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("stream_went_down", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
sc.maxClientStreamID = id
|
sc.maxClientStreamID = id
|
||||||
|
|
||||||
|
@ -1836,14 +1858,14 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||||
if sc.curClientStreams+1 > sc.advMaxStreams {
|
if sc.curClientStreams+1 > sc.advMaxStreams {
|
||||||
if sc.unackedSettings == 0 {
|
if sc.unackedSettings == 0 {
|
||||||
// They should know better.
|
// They should know better.
|
||||||
return streamError(id, ErrCodeProtocol)
|
return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
// Assume it's a network race, where they just haven't
|
// Assume it's a network race, where they just haven't
|
||||||
// received our last SETTINGS update. But actually
|
// received our last SETTINGS update. But actually
|
||||||
// this can't happen yet, because we don't yet provide
|
// this can't happen yet, because we don't yet provide
|
||||||
// a way for users to adjust server parameters at
|
// a way for users to adjust server parameters at
|
||||||
// runtime.
|
// runtime.
|
||||||
return streamError(id, ErrCodeRefusedStream)
|
return sc.countError("over_max_streams_race", streamError(id, ErrCodeRefusedStream))
|
||||||
}
|
}
|
||||||
|
|
||||||
initialState := stateOpen
|
initialState := stateOpen
|
||||||
|
@ -1853,7 +1875,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||||
st := sc.newStream(id, 0, initialState)
|
st := sc.newStream(id, 0, initialState)
|
||||||
|
|
||||||
if f.HasPriority() {
|
if f.HasPriority() {
|
||||||
if err := checkPriority(f.StreamID, f.Priority); err != nil {
|
if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sc.writeSched.AdjustStream(st.id, f.Priority)
|
sc.writeSched.AdjustStream(st.id, f.Priority)
|
||||||
|
@ -1897,15 +1919,15 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
||||||
sc := st.sc
|
sc := st.sc
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
if st.gotTrailerHeader {
|
if st.gotTrailerHeader {
|
||||||
return ConnectionError(ErrCodeProtocol)
|
return sc.countError("dup_trailers", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
st.gotTrailerHeader = true
|
st.gotTrailerHeader = true
|
||||||
if !f.StreamEnded() {
|
if !f.StreamEnded() {
|
||||||
return streamError(st.id, ErrCodeProtocol)
|
return sc.countError("trailers_not_ended", streamError(st.id, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(f.PseudoFields()) > 0 {
|
if len(f.PseudoFields()) > 0 {
|
||||||
return streamError(st.id, ErrCodeProtocol)
|
return sc.countError("trailers_pseudo", streamError(st.id, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
if st.trailer != nil {
|
if st.trailer != nil {
|
||||||
for _, hf := range f.RegularFields() {
|
for _, hf := range f.RegularFields() {
|
||||||
|
@ -1914,7 +1936,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
||||||
// TODO: send more details to the peer somehow. But http2 has
|
// TODO: send more details to the peer somehow. But http2 has
|
||||||
// no way to send debug data at a stream level. Discuss with
|
// no way to send debug data at a stream level. Discuss with
|
||||||
// HTTP folk.
|
// HTTP folk.
|
||||||
return streamError(st.id, ErrCodeProtocol)
|
return sc.countError("trailers_bogus", streamError(st.id, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
st.trailer[key] = append(st.trailer[key], hf.Value)
|
st.trailer[key] = append(st.trailer[key], hf.Value)
|
||||||
}
|
}
|
||||||
|
@ -1923,13 +1945,13 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPriority(streamID uint32, p PriorityParam) error {
|
func (sc *serverConn) checkPriority(streamID uint32, p PriorityParam) error {
|
||||||
if streamID == p.StreamDep {
|
if streamID == p.StreamDep {
|
||||||
// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
|
// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
|
||||||
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
|
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
|
||||||
// Section 5.3.3 says that a stream can depend on one of its dependencies,
|
// Section 5.3.3 says that a stream can depend on one of its dependencies,
|
||||||
// so it's only self-dependencies that are forbidden.
|
// so it's only self-dependencies that are forbidden.
|
||||||
return streamError(streamID, ErrCodeProtocol)
|
return sc.countError("priority", streamError(streamID, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1938,7 +1960,7 @@ func (sc *serverConn) processPriority(f *PriorityFrame) error {
|
||||||
if sc.inGoAway {
|
if sc.inGoAway {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := checkPriority(f.StreamID, f.PriorityParam); err != nil {
|
if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
|
sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
|
||||||
|
@ -1995,7 +2017,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||||
isConnect := rp.method == "CONNECT"
|
isConnect := rp.method == "CONNECT"
|
||||||
if isConnect {
|
if isConnect {
|
||||||
if rp.path != "" || rp.scheme != "" || rp.authority == "" {
|
if rp.path != "" || rp.scheme != "" || rp.authority == "" {
|
||||||
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
} else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
|
} else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
|
||||||
// See 8.1.2.6 Malformed Requests and Responses:
|
// See 8.1.2.6 Malformed Requests and Responses:
|
||||||
|
@ -2008,13 +2030,13 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||||
// "All HTTP/2 requests MUST include exactly one valid
|
// "All HTTP/2 requests MUST include exactly one valid
|
||||||
// value for the :method, :scheme, and :path
|
// value for the :method, :scheme, and :path
|
||||||
// pseudo-header fields"
|
// pseudo-header fields"
|
||||||
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyOpen := !f.StreamEnded()
|
bodyOpen := !f.StreamEnded()
|
||||||
if rp.method == "HEAD" && bodyOpen {
|
if rp.method == "HEAD" && bodyOpen {
|
||||||
// HEAD requests can't have bodies
|
// HEAD requests can't have bodies
|
||||||
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
return nil, nil, sc.countError("head_body", streamError(f.StreamID, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
rp.header = make(http.Header)
|
rp.header = make(http.Header)
|
||||||
|
@ -2097,7 +2119,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
|
||||||
var err error
|
var err error
|
||||||
url_, err = url.ParseRequestURI(rp.path)
|
url_, err = url.ParseRequestURI(rp.path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, streamError(st.id, ErrCodeProtocol)
|
return nil, nil, sc.countError("bad_path", streamError(st.id, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
requestURI = rp.path
|
requestURI = rp.path
|
||||||
}
|
}
|
||||||
|
@ -2980,3 +3002,31 @@ func h1ServerKeepAlivesDisabled(hs *http.Server) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sc *serverConn) countError(name string, err error) error {
|
||||||
|
if sc == nil || sc.srv == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f := sc.srv.CountError
|
||||||
|
if f == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var typ string
|
||||||
|
var code ErrCode
|
||||||
|
switch e := err.(type) {
|
||||||
|
case ConnectionError:
|
||||||
|
typ = "conn"
|
||||||
|
code = ErrCode(e)
|
||||||
|
case StreamError:
|
||||||
|
typ = "stream"
|
||||||
|
code = ErrCode(e.Code)
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
codeStr := errCodeName[code]
|
||||||
|
if codeStr == "" {
|
||||||
|
codeStr = strconv.Itoa(int(code))
|
||||||
|
}
|
||||||
|
f(fmt.Sprintf("%s_%s_%s", typ, codeStr, name))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue