Update vendor dep
Signed-off-by: jwcesign <jiangwei115@huawei.com>
This commit is contained in:
parent
218a0b2400
commit
a18702b1c8
|
@ -1,10 +1,21 @@
|
|||
# Change history of go-restful
|
||||
|
||||
## [v3.9.0] - 20221-07-21
|
||||
## [v3.10.1] - 2022-11-19
|
||||
|
||||
- fix broken 3.10.0 by using path package for joining paths
|
||||
|
||||
## [v3.10.0] - 2022-10-11 - BROKEN
|
||||
|
||||
- changed tokenizer to match std route match behavior; do not trimright the path (#511)
|
||||
- Add MIME_ZIP (#512)
|
||||
- Add MIME_ZIP and HEADER_ContentDisposition (#513)
|
||||
- Changed how to get query parameter issue #510
|
||||
|
||||
## [v3.9.0] - 2022-07-21
|
||||
|
||||
- add support for http.Handler implementations to work as FilterFunction, issue #504 (thanks to https://github.com/ggicci)
|
||||
|
||||
## [v3.8.0] - 20221-06-06
|
||||
## [v3.8.0] - 2022-06-06
|
||||
|
||||
- use exact matching of allowed domain entries, issue #489 (#493)
|
||||
- this changes fixes [security] Authorization Bypass Through User-Controlled Key
|
||||
|
|
|
@ -7,12 +7,14 @@ package restful
|
|||
const (
|
||||
MIME_XML = "application/xml" // Accept or Content-Type used in Consumes() and/or Produces()
|
||||
MIME_JSON = "application/json" // Accept or Content-Type used in Consumes() and/or Produces()
|
||||
MIME_ZIP = "application/zip" // Accept or Content-Type used in Consumes() and/or Produces()
|
||||
MIME_OCTET = "application/octet-stream" // If Content-Type is not present in request, use the default
|
||||
|
||||
HEADER_Allow = "Allow"
|
||||
HEADER_Accept = "Accept"
|
||||
HEADER_Origin = "Origin"
|
||||
HEADER_ContentType = "Content-Type"
|
||||
HEADER_ContentDisposition = "Content-Disposition"
|
||||
HEADER_LastModified = "Last-Modified"
|
||||
HEADER_AcceptEncoding = "Accept-Encoding"
|
||||
HEADER_ContentEncoding = "Content-Encoding"
|
||||
|
|
|
@ -31,7 +31,8 @@ func NewRequest(httpRequest *http.Request) *Request {
|
|||
// a "Unable to unmarshal content of type:" response is returned.
|
||||
// Valid values are restful.MIME_JSON and restful.MIME_XML
|
||||
// Example:
|
||||
// restful.DefaultRequestContentType(restful.MIME_JSON)
|
||||
//
|
||||
// restful.DefaultRequestContentType(restful.MIME_JSON)
|
||||
func DefaultRequestContentType(mime string) {
|
||||
defaultRequestContentType = mime
|
||||
}
|
||||
|
@ -48,7 +49,7 @@ func (r *Request) PathParameters() map[string]string {
|
|||
|
||||
// QueryParameter returns the (first) Query parameter value by its name
|
||||
func (r *Request) QueryParameter(name string) string {
|
||||
return r.Request.FormValue(name)
|
||||
return r.Request.URL.Query().Get(name)
|
||||
}
|
||||
|
||||
// QueryParameters returns the all the query parameters values by name
|
||||
|
|
|
@ -109,6 +109,9 @@ func (r *Response) EntityWriter() (EntityReaderWriter, bool) {
|
|||
if DefaultResponseMimeType == MIME_XML {
|
||||
return entityAccessRegistry.accessorAt(MIME_XML)
|
||||
}
|
||||
if DefaultResponseMimeType == MIME_ZIP {
|
||||
return entityAccessRegistry.accessorAt(MIME_ZIP)
|
||||
}
|
||||
// Fallback to whatever the route says it can produce.
|
||||
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
||||
for _, each := range r.routeProduces {
|
||||
|
|
|
@ -164,7 +164,7 @@ func tokenizePath(path string) []string {
|
|||
if "/" == path {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(strings.Trim(path, "/"), "/")
|
||||
return strings.Split(strings.TrimLeft(path, "/"), "/")
|
||||
}
|
||||
|
||||
// for debugging
|
||||
|
@ -176,3 +176,5 @@ func (r *Route) String() string {
|
|||
func (r *Route) EnableContentEncoding(enabled bool) {
|
||||
r.contentEncodingEnabled = &enabled
|
||||
}
|
||||
|
||||
var TrimRightSlashEnabled = false
|
||||
|
|
|
@ -7,6 +7,7 @@ package restful
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
@ -46,11 +47,12 @@ type RouteBuilder struct {
|
|||
// Do evaluates each argument with the RouteBuilder itself.
|
||||
// This allows you to follow DRY principles without breaking the fluent programming style.
|
||||
// Example:
|
||||
// ws.Route(ws.DELETE("/{name}").To(t.deletePerson).Do(Returns200, Returns500))
|
||||
//
|
||||
// func Returns500(b *RouteBuilder) {
|
||||
// b.Returns(500, "Internal Server Error", restful.ServiceError{})
|
||||
// }
|
||||
// ws.Route(ws.DELETE("/{name}").To(t.deletePerson).Do(Returns200, Returns500))
|
||||
//
|
||||
// func Returns500(b *RouteBuilder) {
|
||||
// b.Returns(500, "Internal Server Error", restful.ServiceError{})
|
||||
// }
|
||||
func (b *RouteBuilder) Do(oneArgBlocks ...func(*RouteBuilder)) *RouteBuilder {
|
||||
for _, each := range oneArgBlocks {
|
||||
each(b)
|
||||
|
@ -352,7 +354,7 @@ func (b *RouteBuilder) Build() Route {
|
|||
}
|
||||
|
||||
func concatPath(path1, path2 string) string {
|
||||
return strings.TrimRight(path1, "/") + "/" + strings.TrimLeft(path2, "/")
|
||||
return path.Join(path1, path2)
|
||||
}
|
||||
|
||||
var anonymousFuncCount int32
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
go:
|
||||
- 1.14.x
|
||||
- 1.15.x
|
||||
install:
|
||||
- GO111MODULE=off go get -u gotest.tools/gotestsum
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
language: go
|
||||
notifications:
|
||||
slack:
|
||||
secure: a5VgoiwB1G/AZqzmephPZIhEB9avMlsWSlVnM1dSAtYAwdrQHGTQxAmpOxYIoSPDhWNN5bfZmjd29++UlTwLcHSR+e0kJhH6IfDlsHj/HplNCJ9tyI0zYc7XchtdKgeMxMzBKCzgwFXGSbQGydXTliDNBo0HOzmY3cou/daMFTP60K+offcjS+3LRAYb1EroSRXZqrk1nuF/xDL3792DZUdPMiFR/L/Df6y74D6/QP4sTkTDFQitz4Wy/7jbsfj8dG6qK2zivgV6/l+w4OVjFkxVpPXogDWY10vVXNVynqxfJ7to2d1I9lNCHE2ilBCkWMIPdyJF7hjF8pKW+82yP4EzRh0vu8Xn0HT5MZpQxdRY/YMxNrWaG7SxsoEaO4q5uhgdzAqLYY3TRa7MjIK+7Ur+aqOeTXn6OKwVi0CjvZ6mIU3WUKSwiwkFZMbjRAkSb5CYwMEfGFO/z964xz83qGt6WAtBXNotqCQpTIiKtDHQeLOMfksHImCg6JLhQcWBVxamVgu0G3Pdh8Y6DyPnxraXY95+QDavbjqv7TeYT9T/FNnrkXaTTK0s4iWE5H4ACU0Qvz0wUYgfQrZv0/Hp7V17+rabUwnzYySHCy9SWX/7OV9Cfh31iMp9ZIffr76xmmThtOEqs8TrTtU6BWI3rWwvA9cXQipZTVtL0oswrGw=
|
||||
script:
|
||||
- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./...
|
|
@ -1,8 +1,6 @@
|
|||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
golint:
|
||||
min-confidence: 0
|
||||
gocyclo:
|
||||
min-complexity: 30
|
||||
maligned:
|
||||
|
@ -12,6 +10,8 @@ linters-settings:
|
|||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 4
|
||||
paralleltest:
|
||||
ignore-missing: true
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
|
@ -39,3 +39,12 @@ linters:
|
|||
- nestif
|
||||
- godot
|
||||
- errorlint
|
||||
- varcheck
|
||||
- interfacer
|
||||
- deadcode
|
||||
- golint
|
||||
- ifshort
|
||||
- structcheck
|
||||
- nosnakecase
|
||||
- varnamelen
|
||||
- exhaustruct
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
go:
|
||||
- 1.14.x
|
||||
- 1.x
|
||||
install:
|
||||
- go get gotest.tools/gotestsum
|
||||
jobs:
|
||||
include:
|
||||
# include linting job, but only for latest go version and amd64 arch
|
||||
- go: 1.x
|
||||
arch: amd64
|
||||
install:
|
||||
go get github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||
script:
|
||||
- golangci-lint run --new-from-rev master
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
language: go
|
||||
notifications:
|
||||
slack:
|
||||
secure: OpQG/36F7DSF00HLm9WZMhyqFCYYyYTsVDObW226cWiR8PWYiNfLZiSEvIzT1Gx4dDjhigKTIqcLhG34CkL5iNXDjm9Yyo2RYhQPlK8NErNqUEXuBqn4RqYHW48VGhEhOyDd4Ei0E2FN5ZbgpvHgtpkdZ6XDi64r3Ac89isP9aPHXQTuv2Jog6b4/OKKiUTftLcTIst0p4Cp3gqOJWf1wnoj+IadWiECNVQT6zb47IYjtyw6+uV8iUjTzdKcRB6Zc6b4Dq7JAg1Zd7Jfxkql3hlKp4PNlRf9Cy7y5iA3G7MLyg3FcPX5z2kmcyPt2jOTRMBWUJ5zIQpOxizAcN8WsT3WWBL5KbuYK6k0PzujrIDLqdxGpNmjkkMfDBT9cKmZpm2FdW+oZgPFJP+oKmAo4u4KJz/vjiPTXgQlN5bmrLuRMCp+AwC5wkIohTqWZVPE2TK6ZSnMYcg/W39s+RP/9mJoyryAvPSpBOLTI+biCgaUCTOAZxNTWpMFc3tPYntc41WWkdKcooZ9JA5DwfcaVFyTGQ3YXz+HvX6G1z/gW0Q/A4dBi9mj2iE1xm7tRTT+4VQ2AXFvSEI1HJpfPgYnwAtwOD1v3Qm2EUHk9sCdtEDR4wVGEPIVn44GnwFMnGKx9JWppMPYwFu3SVDdHt+E+LOlhZUply11Aa+IVrT2KUQ=
|
||||
script:
|
||||
- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./...
|
|
@ -7,8 +7,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
defaultHttpPort = ":80"
|
||||
defaultHttpsPort = ":443"
|
||||
defaultHTTPPort = ":80"
|
||||
defaultHTTPSPort = ":443"
|
||||
)
|
||||
|
||||
// Regular expressions used by the normalizations
|
||||
|
@ -18,13 +18,14 @@ var rxDupSlashes = regexp.MustCompile(`/{2,}`)
|
|||
// NormalizeURL will normalize the specified URL
|
||||
// This was added to replace a previous call to the no longer maintained purell library:
|
||||
// The call that was used looked like the following:
|
||||
// url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes))
|
||||
//
|
||||
// url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes))
|
||||
//
|
||||
// To explain all that was included in the call above, purell.FlagsSafe was really just the following:
|
||||
// - FlagLowercaseScheme
|
||||
// - FlagLowercaseHost
|
||||
// - FlagRemoveDefaultPort
|
||||
// - FlagRemoveDuplicateSlashes (and this was mixed in with the |)
|
||||
// - FlagLowercaseScheme
|
||||
// - FlagLowercaseHost
|
||||
// - FlagRemoveDefaultPort
|
||||
// - FlagRemoveDuplicateSlashes (and this was mixed in with the |)
|
||||
func NormalizeURL(u *url.URL) {
|
||||
lowercaseScheme(u)
|
||||
lowercaseHost(u)
|
||||
|
@ -48,7 +49,7 @@ func removeDefaultPort(u *url.URL) {
|
|||
if len(u.Host) > 0 {
|
||||
scheme := strings.ToLower(u.Scheme)
|
||||
u.Host = rxPort.ReplaceAllStringFunc(u.Host, func(val string) string {
|
||||
if (scheme == "http" && val == defaultHttpPort) || (scheme == "https" && val == defaultHttpsPort) {
|
||||
if (scheme == "http" && val == defaultHTTPPort) || (scheme == "https" && val == defaultHTTPSPort) {
|
||||
return ""
|
||||
}
|
||||
return val
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
@ -141,12 +140,11 @@ func CallerInfo() []string {
|
|||
}
|
||||
|
||||
parts := strings.Split(file, "/")
|
||||
file = parts[len(parts)-1]
|
||||
if len(parts) > 1 {
|
||||
filename := parts[len(parts)-1]
|
||||
dir := parts[len(parts)-2]
|
||||
if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
|
||||
path, _ := filepath.Abs(file)
|
||||
callers = append(callers, fmt.Sprintf("%s:%d", path, line))
|
||||
if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" {
|
||||
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,7 +528,7 @@ func isNil(object interface{}) bool {
|
|||
[]reflect.Kind{
|
||||
reflect.Chan, reflect.Func,
|
||||
reflect.Interface, reflect.Map,
|
||||
reflect.Ptr, reflect.Slice},
|
||||
reflect.Ptr, reflect.Slice, reflect.UnsafePointer},
|
||||
kind)
|
||||
|
||||
if isNilableKind && value.IsNil() {
|
||||
|
@ -818,49 +816,44 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
|||
return true // we consider nil to be equal to the nil set
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
ok = false
|
||||
}
|
||||
}()
|
||||
|
||||
listKind := reflect.TypeOf(list).Kind()
|
||||
subsetKind := reflect.TypeOf(subset).Kind()
|
||||
|
||||
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
|
||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
||||
}
|
||||
|
||||
subsetKind := reflect.TypeOf(subset).Kind()
|
||||
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
|
||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
||||
}
|
||||
|
||||
subsetValue := reflect.ValueOf(subset)
|
||||
if subsetKind == reflect.Map && listKind == reflect.Map {
|
||||
listValue := reflect.ValueOf(list)
|
||||
subsetKeys := subsetValue.MapKeys()
|
||||
subsetMap := reflect.ValueOf(subset)
|
||||
actualMap := reflect.ValueOf(list)
|
||||
|
||||
for i := 0; i < len(subsetKeys); i++ {
|
||||
subsetKey := subsetKeys[i]
|
||||
subsetElement := subsetValue.MapIndex(subsetKey).Interface()
|
||||
listElement := listValue.MapIndex(subsetKey).Interface()
|
||||
for _, k := range subsetMap.MapKeys() {
|
||||
ev := subsetMap.MapIndex(k)
|
||||
av := actualMap.MapIndex(k)
|
||||
|
||||
if !ObjectsAreEqual(subsetElement, listElement) {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, subsetElement), msgAndArgs...)
|
||||
if !av.IsValid() {
|
||||
return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
|
||||
}
|
||||
if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
|
||||
return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
for i := 0; i < subsetValue.Len(); i++ {
|
||||
element := subsetValue.Index(i).Interface()
|
||||
subsetList := reflect.ValueOf(subset)
|
||||
for i := 0; i < subsetList.Len(); i++ {
|
||||
element := subsetList.Index(i).Interface()
|
||||
ok, found := containsElement(list, element)
|
||||
if !ok {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
|
||||
}
|
||||
if !found {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -879,34 +872,28 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
|
|||
return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
ok = false
|
||||
}
|
||||
}()
|
||||
|
||||
listKind := reflect.TypeOf(list).Kind()
|
||||
subsetKind := reflect.TypeOf(subset).Kind()
|
||||
|
||||
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
|
||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
||||
}
|
||||
|
||||
subsetKind := reflect.TypeOf(subset).Kind()
|
||||
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
|
||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
||||
}
|
||||
|
||||
subsetValue := reflect.ValueOf(subset)
|
||||
if subsetKind == reflect.Map && listKind == reflect.Map {
|
||||
listValue := reflect.ValueOf(list)
|
||||
subsetKeys := subsetValue.MapKeys()
|
||||
subsetMap := reflect.ValueOf(subset)
|
||||
actualMap := reflect.ValueOf(list)
|
||||
|
||||
for i := 0; i < len(subsetKeys); i++ {
|
||||
subsetKey := subsetKeys[i]
|
||||
subsetElement := subsetValue.MapIndex(subsetKey).Interface()
|
||||
listElement := listValue.MapIndex(subsetKey).Interface()
|
||||
for _, k := range subsetMap.MapKeys() {
|
||||
ev := subsetMap.MapIndex(k)
|
||||
av := actualMap.MapIndex(k)
|
||||
|
||||
if !ObjectsAreEqual(subsetElement, listElement) {
|
||||
if !av.IsValid() {
|
||||
return true
|
||||
}
|
||||
if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -914,8 +901,9 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
|
|||
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
|
||||
}
|
||||
|
||||
for i := 0; i < subsetValue.Len(); i++ {
|
||||
element := subsetValue.Index(i).Interface()
|
||||
subsetList := reflect.ValueOf(subset)
|
||||
for i := 0; i < subsetList.Len(); i++ {
|
||||
element := subsetList.Index(i).Interface()
|
||||
ok, found := containsElement(list, element)
|
||||
if !ok {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
||||
|
|
|
@ -218,16 +218,22 @@ func (c *Call) Unset() *Call {
|
|||
|
||||
foundMatchingCall := false
|
||||
|
||||
for i, call := range c.Parent.ExpectedCalls {
|
||||
// in-place filter slice for calls to be removed - iterate from 0'th to last skipping unnecessary ones
|
||||
var index int // write index
|
||||
for _, call := range c.Parent.ExpectedCalls {
|
||||
if call.Method == c.Method {
|
||||
_, diffCount := call.Arguments.Diff(c.Arguments)
|
||||
if diffCount == 0 {
|
||||
foundMatchingCall = true
|
||||
// Remove from ExpectedCalls
|
||||
c.Parent.ExpectedCalls = append(c.Parent.ExpectedCalls[:i], c.Parent.ExpectedCalls[i+1:]...)
|
||||
// Remove from ExpectedCalls - just skip it
|
||||
continue
|
||||
}
|
||||
}
|
||||
c.Parent.ExpectedCalls[index] = call
|
||||
index++
|
||||
}
|
||||
// trim slice up to last copied index
|
||||
c.Parent.ExpectedCalls = c.Parent.ExpectedCalls[:index]
|
||||
|
||||
if !foundMatchingCall {
|
||||
unlockOnce.Do(c.unlock)
|
||||
|
|
|
@ -70,11 +70,14 @@ func SetLogger(logger logr.Logger) {
|
|||
// routing log entries through klogr into klog and then into the actual Logger
|
||||
// backend.
|
||||
func SetLoggerWithOptions(logger logr.Logger, opts ...LoggerOption) {
|
||||
logging.logger = &logger
|
||||
logging.loggerOptions = loggerOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(&logging.loggerOptions)
|
||||
}
|
||||
logging.logger = &logWriter{
|
||||
Logger: logger,
|
||||
writeKlogBuffer: logging.loggerOptions.writeKlogBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
// ContextualLogger determines whether the logger passed to
|
||||
|
@ -93,6 +96,22 @@ func FlushLogger(flush func()) LoggerOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WriteKlogBuffer sets a callback that will be invoked by klog to write output
|
||||
// produced by non-structured log calls like Infof.
|
||||
//
|
||||
// The buffer will contain exactly the same data that klog normally would write
|
||||
// into its own output stream(s). In particular this includes the header, if
|
||||
// klog is configured to write one. The callback then can divert that data into
|
||||
// its own output streams. The buffer may or may not end in a line break.
|
||||
//
|
||||
// Without such a callback, klog will call the logger's Info or Error method
|
||||
// with just the message string (i.e. no header).
|
||||
func WriteKlogBuffer(write func([]byte)) LoggerOption {
|
||||
return func(o *loggerOptions) {
|
||||
o.writeKlogBuffer = write
|
||||
}
|
||||
}
|
||||
|
||||
// LoggerOption implements the functional parameter paradigm for
|
||||
// SetLoggerWithOptions.
|
||||
type LoggerOption func(o *loggerOptions)
|
||||
|
@ -100,6 +119,13 @@ type LoggerOption func(o *loggerOptions)
|
|||
type loggerOptions struct {
|
||||
contextualLogger bool
|
||||
flush func()
|
||||
writeKlogBuffer func([]byte)
|
||||
}
|
||||
|
||||
// logWriter combines a logger (always set) with a write callback (optional).
|
||||
type logWriter struct {
|
||||
Logger
|
||||
writeKlogBuffer func([]byte)
|
||||
}
|
||||
|
||||
// ClearLogger removes a backing Logger implementation if one was set earlier
|
||||
|
@ -152,7 +178,7 @@ func Background() Logger {
|
|||
if logging.loggerOptions.contextualLogger {
|
||||
// Is non-nil because logging.loggerOptions.contextualLogger is
|
||||
// only true if a logger was set.
|
||||
return *logging.logger
|
||||
return logging.logger.Logger
|
||||
}
|
||||
|
||||
return klogLogger
|
||||
|
|
|
@ -40,44 +40,33 @@ type Buffer struct {
|
|||
next *Buffer
|
||||
}
|
||||
|
||||
// Buffers manages the reuse of individual buffer instances. It is thread-safe.
|
||||
type Buffers struct {
|
||||
// mu protects the free list. It is separate from the main mutex
|
||||
// so buffers can be grabbed and printed to without holding the main lock,
|
||||
// for better parallelization.
|
||||
mu sync.Mutex
|
||||
|
||||
// freeList is a list of byte buffers, maintained under mu.
|
||||
freeList *Buffer
|
||||
var buffers = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(Buffer)
|
||||
},
|
||||
}
|
||||
|
||||
// GetBuffer returns a new, ready-to-use buffer.
|
||||
func (bl *Buffers) GetBuffer() *Buffer {
|
||||
bl.mu.Lock()
|
||||
b := bl.freeList
|
||||
if b != nil {
|
||||
bl.freeList = b.next
|
||||
}
|
||||
bl.mu.Unlock()
|
||||
if b == nil {
|
||||
b = new(Buffer)
|
||||
} else {
|
||||
b.next = nil
|
||||
b.Reset()
|
||||
}
|
||||
func GetBuffer() *Buffer {
|
||||
b := buffers.Get().(*Buffer)
|
||||
b.Reset()
|
||||
return b
|
||||
}
|
||||
|
||||
// PutBuffer returns a buffer to the free list.
|
||||
func (bl *Buffers) PutBuffer(b *Buffer) {
|
||||
func PutBuffer(b *Buffer) {
|
||||
if b.Len() >= 256 {
|
||||
// Let big buffers die a natural death.
|
||||
// Let big buffers die a natural death, without relying on
|
||||
// sync.Pool behavior. The documentation implies that items may
|
||||
// get deallocated while stored there ("If the Pool holds the
|
||||
// only reference when this [= be removed automatically]
|
||||
// happens, the item might be deallocated."), but
|
||||
// https://github.com/golang/go/issues/23199 leans more towards
|
||||
// having such a size limit.
|
||||
return
|
||||
}
|
||||
bl.mu.Lock()
|
||||
b.next = bl.freeList
|
||||
bl.freeList = b
|
||||
bl.mu.Unlock()
|
||||
|
||||
buffers.Put(b)
|
||||
}
|
||||
|
||||
// Some custom tiny helper functions to print the log header efficiently.
|
||||
|
@ -121,7 +110,8 @@ func (buf *Buffer) someDigits(i, d int) int {
|
|||
return copy(buf.Tmp[i:], buf.Tmp[j:])
|
||||
}
|
||||
|
||||
// FormatHeader formats a log header using the provided file name and line number.
|
||||
// FormatHeader formats a log header using the provided file name and line number
|
||||
// and writes it into the buffer.
|
||||
func (buf *Buffer) FormatHeader(s severity.Severity, file string, line int, now time.Time) {
|
||||
if line < 0 {
|
||||
line = 0 // not a real line number, but acceptable to someDigits
|
||||
|
@ -157,3 +147,30 @@ func (buf *Buffer) FormatHeader(s severity.Severity, file string, line int, now
|
|||
buf.Tmp[n+2] = ' '
|
||||
buf.Write(buf.Tmp[:n+3])
|
||||
}
|
||||
|
||||
// SprintHeader formats a log header and returns a string. This is a simpler
|
||||
// version of FormatHeader for use in ktesting.
|
||||
func (buf *Buffer) SprintHeader(s severity.Severity, now time.Time) string {
|
||||
if s > severity.FatalLog {
|
||||
s = severity.InfoLog // for safety.
|
||||
}
|
||||
|
||||
// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
|
||||
// It's worth about 3X. Fprintf is hard.
|
||||
_, month, day := now.Date()
|
||||
hour, minute, second := now.Clock()
|
||||
// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
|
||||
buf.Tmp[0] = severity.Char[s]
|
||||
buf.twoDigits(1, int(month))
|
||||
buf.twoDigits(3, day)
|
||||
buf.Tmp[5] = ' '
|
||||
buf.twoDigits(6, hour)
|
||||
buf.Tmp[8] = ':'
|
||||
buf.twoDigits(9, minute)
|
||||
buf.Tmp[11] = ':'
|
||||
buf.twoDigits(12, second)
|
||||
buf.Tmp[14] = '.'
|
||||
buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
|
||||
buf.Tmp[21] = ']'
|
||||
return string(buf.Tmp[:22])
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ import (
|
|||
"github.com/go-logr/logr"
|
||||
)
|
||||
|
||||
type textWriter interface {
|
||||
WriteText(*bytes.Buffer)
|
||||
}
|
||||
|
||||
// WithValues implements LogSink.WithValues. The old key/value pairs are
|
||||
// assumed to be well-formed, the new ones are checked and padded if
|
||||
// necessary. It returns a new slice.
|
||||
|
@ -91,11 +95,66 @@ func MergeKVs(first, second []interface{}) []interface{} {
|
|||
return merged
|
||||
}
|
||||
|
||||
type Formatter struct {
|
||||
AnyToStringHook AnyToStringFunc
|
||||
}
|
||||
|
||||
type AnyToStringFunc func(v interface{}) string
|
||||
|
||||
// MergeKVsInto is a variant of MergeKVs which directly formats the key/value
|
||||
// pairs into a buffer.
|
||||
func (f Formatter) MergeAndFormatKVs(b *bytes.Buffer, first, second []interface{}) {
|
||||
if len(first) == 0 && len(second) == 0 {
|
||||
// Nothing to do at all.
|
||||
return
|
||||
}
|
||||
|
||||
if len(first) == 0 && len(second)%2 == 0 {
|
||||
// Nothing to be overridden, second slice is well-formed
|
||||
// and can be used directly.
|
||||
for i := 0; i < len(second); i += 2 {
|
||||
f.KVFormat(b, second[i], second[i+1])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Determine which keys are in the second slice so that we can skip
|
||||
// them when iterating over the first one. The code intentionally
|
||||
// favors performance over completeness: we assume that keys are string
|
||||
// constants and thus compare equal when the string values are equal. A
|
||||
// string constant being overridden by, for example, a fmt.Stringer is
|
||||
// not handled.
|
||||
overrides := map[interface{}]bool{}
|
||||
for i := 0; i < len(second); i += 2 {
|
||||
overrides[second[i]] = true
|
||||
}
|
||||
for i := 0; i < len(first); i += 2 {
|
||||
key := first[i]
|
||||
if overrides[key] {
|
||||
continue
|
||||
}
|
||||
f.KVFormat(b, key, first[i+1])
|
||||
}
|
||||
// Round down.
|
||||
l := len(second)
|
||||
l = l / 2 * 2
|
||||
for i := 1; i < l; i += 2 {
|
||||
f.KVFormat(b, second[i-1], second[i])
|
||||
}
|
||||
if len(second)%2 == 1 {
|
||||
f.KVFormat(b, second[len(second)-1], missingValue)
|
||||
}
|
||||
}
|
||||
|
||||
func MergeAndFormatKVs(b *bytes.Buffer, first, second []interface{}) {
|
||||
Formatter{}.MergeAndFormatKVs(b, first, second)
|
||||
}
|
||||
|
||||
const missingValue = "(MISSING)"
|
||||
|
||||
// KVListFormat serializes all key/value pairs into the provided buffer.
|
||||
// A space gets inserted before the first pair and between each pair.
|
||||
func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
|
||||
func (f Formatter) KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
|
||||
for i := 0; i < len(keysAndValues); i += 2 {
|
||||
var v interface{}
|
||||
k := keysAndValues[i]
|
||||
|
@ -104,69 +163,93 @@ func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
|
|||
} else {
|
||||
v = missingValue
|
||||
}
|
||||
b.WriteByte(' ')
|
||||
// Keys are assumed to be well-formed according to
|
||||
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments
|
||||
// for the sake of performance. Keys with spaces,
|
||||
// special characters, etc. will break parsing.
|
||||
if sK, ok := k.(string); ok {
|
||||
// Avoid one allocation when the key is a string, which
|
||||
// normally it should be.
|
||||
b.WriteString(sK)
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("%s", k))
|
||||
}
|
||||
|
||||
// The type checks are sorted so that more frequently used ones
|
||||
// come first because that is then faster in the common
|
||||
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
|
||||
// than plain strings
|
||||
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
|
||||
switch v := v.(type) {
|
||||
case fmt.Stringer:
|
||||
writeStringValue(b, true, StringerToString(v))
|
||||
case string:
|
||||
writeStringValue(b, true, v)
|
||||
case error:
|
||||
writeStringValue(b, true, ErrorToString(v))
|
||||
case logr.Marshaler:
|
||||
value := MarshalerToValue(v)
|
||||
// A marshaler that returns a string is useful for
|
||||
// delayed formatting of complex values. We treat this
|
||||
// case like a normal string. This is useful for
|
||||
// multi-line support.
|
||||
//
|
||||
// We could do this by recursively formatting a value,
|
||||
// but that comes with the risk of infinite recursion
|
||||
// if a marshaler returns itself. Instead we call it
|
||||
// only once and rely on it returning the intended
|
||||
// value directly.
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
writeStringValue(b, true, value)
|
||||
default:
|
||||
writeStringValue(b, false, fmt.Sprintf("%+v", value))
|
||||
}
|
||||
case []byte:
|
||||
// In https://github.com/kubernetes/klog/pull/237 it was decided
|
||||
// to format byte slices with "%+q". The advantages of that are:
|
||||
// - readable output if the bytes happen to be printable
|
||||
// - non-printable bytes get represented as unicode escape
|
||||
// sequences (\uxxxx)
|
||||
//
|
||||
// The downsides are that we cannot use the faster
|
||||
// strconv.Quote here and that multi-line output is not
|
||||
// supported. If developers know that a byte array is
|
||||
// printable and they want multi-line output, they can
|
||||
// convert the value to string before logging it.
|
||||
b.WriteByte('=')
|
||||
b.WriteString(fmt.Sprintf("%+q", v))
|
||||
default:
|
||||
writeStringValue(b, false, fmt.Sprintf("%+v", v))
|
||||
}
|
||||
f.KVFormat(b, k, v)
|
||||
}
|
||||
}
|
||||
|
||||
func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
|
||||
Formatter{}.KVListFormat(b, keysAndValues...)
|
||||
}
|
||||
|
||||
// KVFormat serializes one key/value pair into the provided buffer.
|
||||
// A space gets inserted before the pair.
|
||||
func (f Formatter) KVFormat(b *bytes.Buffer, k, v interface{}) {
|
||||
b.WriteByte(' ')
|
||||
// Keys are assumed to be well-formed according to
|
||||
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments
|
||||
// for the sake of performance. Keys with spaces,
|
||||
// special characters, etc. will break parsing.
|
||||
if sK, ok := k.(string); ok {
|
||||
// Avoid one allocation when the key is a string, which
|
||||
// normally it should be.
|
||||
b.WriteString(sK)
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("%s", k))
|
||||
}
|
||||
|
||||
// The type checks are sorted so that more frequently used ones
|
||||
// come first because that is then faster in the common
|
||||
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
|
||||
// than plain strings
|
||||
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
|
||||
switch v := v.(type) {
|
||||
case textWriter:
|
||||
writeTextWriterValue(b, v)
|
||||
case fmt.Stringer:
|
||||
writeStringValue(b, true, StringerToString(v))
|
||||
case string:
|
||||
writeStringValue(b, true, v)
|
||||
case error:
|
||||
writeStringValue(b, true, ErrorToString(v))
|
||||
case logr.Marshaler:
|
||||
value := MarshalerToValue(v)
|
||||
// A marshaler that returns a string is useful for
|
||||
// delayed formatting of complex values. We treat this
|
||||
// case like a normal string. This is useful for
|
||||
// multi-line support.
|
||||
//
|
||||
// We could do this by recursively formatting a value,
|
||||
// but that comes with the risk of infinite recursion
|
||||
// if a marshaler returns itself. Instead we call it
|
||||
// only once and rely on it returning the intended
|
||||
// value directly.
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
writeStringValue(b, true, value)
|
||||
default:
|
||||
writeStringValue(b, false, f.AnyToString(value))
|
||||
}
|
||||
case []byte:
|
||||
// In https://github.com/kubernetes/klog/pull/237 it was decided
|
||||
// to format byte slices with "%+q". The advantages of that are:
|
||||
// - readable output if the bytes happen to be printable
|
||||
// - non-printable bytes get represented as unicode escape
|
||||
// sequences (\uxxxx)
|
||||
//
|
||||
// The downsides are that we cannot use the faster
|
||||
// strconv.Quote here and that multi-line output is not
|
||||
// supported. If developers know that a byte array is
|
||||
// printable and they want multi-line output, they can
|
||||
// convert the value to string before logging it.
|
||||
b.WriteByte('=')
|
||||
b.WriteString(fmt.Sprintf("%+q", v))
|
||||
default:
|
||||
writeStringValue(b, false, f.AnyToString(v))
|
||||
}
|
||||
}
|
||||
|
||||
func KVFormat(b *bytes.Buffer, k, v interface{}) {
|
||||
Formatter{}.KVFormat(b, k, v)
|
||||
}
|
||||
|
||||
// AnyToString is the historic fallback formatter.
|
||||
func (f Formatter) AnyToString(v interface{}) string {
|
||||
if f.AnyToStringHook != nil {
|
||||
return f.AnyToStringHook(v)
|
||||
}
|
||||
return fmt.Sprintf("%+v", v)
|
||||
}
|
||||
|
||||
// StringerToString converts a Stringer to a string,
|
||||
// handling panics if they occur.
|
||||
func StringerToString(s fmt.Stringer) (ret string) {
|
||||
|
@ -203,6 +286,16 @@ func ErrorToString(err error) (ret string) {
|
|||
return
|
||||
}
|
||||
|
||||
func writeTextWriterValue(b *bytes.Buffer, v textWriter) {
|
||||
b.WriteRune('=')
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Fprintf(b, `"<panic: %s>"`, err)
|
||||
}
|
||||
}()
|
||||
v.WriteText(b)
|
||||
}
|
||||
|
||||
func writeStringValue(b *bytes.Buffer, quote bool, v string) {
|
||||
data := []byte(v)
|
||||
index := bytes.IndexByte(data, '\n')
|
||||
|
|
|
@ -17,8 +17,10 @@ limitations under the License.
|
|||
package klog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
)
|
||||
|
@ -31,11 +33,30 @@ type ObjectRef struct {
|
|||
|
||||
func (ref ObjectRef) String() string {
|
||||
if ref.Namespace != "" {
|
||||
return fmt.Sprintf("%s/%s", ref.Namespace, ref.Name)
|
||||
var builder strings.Builder
|
||||
builder.Grow(len(ref.Namespace) + len(ref.Name) + 1)
|
||||
builder.WriteString(ref.Namespace)
|
||||
builder.WriteRune('/')
|
||||
builder.WriteString(ref.Name)
|
||||
return builder.String()
|
||||
}
|
||||
return ref.Name
|
||||
}
|
||||
|
||||
func (ref ObjectRef) WriteText(out *bytes.Buffer) {
|
||||
out.WriteRune('"')
|
||||
ref.writeUnquoted(out)
|
||||
out.WriteRune('"')
|
||||
}
|
||||
|
||||
func (ref ObjectRef) writeUnquoted(out *bytes.Buffer) {
|
||||
if ref.Namespace != "" {
|
||||
out.WriteString(ref.Namespace)
|
||||
out.WriteRune('/')
|
||||
}
|
||||
out.WriteString(ref.Name)
|
||||
}
|
||||
|
||||
// MarshalLog ensures that loggers with support for structured output will log
|
||||
// as a struct by removing the String method via a custom type.
|
||||
func (ref ObjectRef) MarshalLog() interface{} {
|
||||
|
@ -117,31 +138,31 @@ var _ fmt.Stringer = kobjSlice{}
|
|||
var _ logr.Marshaler = kobjSlice{}
|
||||
|
||||
func (ks kobjSlice) String() string {
|
||||
objectRefs, err := ks.process()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
objectRefs, errStr := ks.process()
|
||||
if errStr != "" {
|
||||
return errStr
|
||||
}
|
||||
return fmt.Sprintf("%v", objectRefs)
|
||||
}
|
||||
|
||||
func (ks kobjSlice) MarshalLog() interface{} {
|
||||
objectRefs, err := ks.process()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
objectRefs, errStr := ks.process()
|
||||
if errStr != "" {
|
||||
return errStr
|
||||
}
|
||||
return objectRefs
|
||||
}
|
||||
|
||||
func (ks kobjSlice) process() ([]interface{}, error) {
|
||||
func (ks kobjSlice) process() (objs []interface{}, err string) {
|
||||
s := reflect.ValueOf(ks.arg)
|
||||
switch s.Kind() {
|
||||
case reflect.Invalid:
|
||||
// nil parameter, print as nil.
|
||||
return nil, nil
|
||||
return nil, ""
|
||||
case reflect.Slice:
|
||||
// Okay, handle below.
|
||||
default:
|
||||
return nil, fmt.Errorf("<KObjSlice needs a slice, got type %T>", ks.arg)
|
||||
return nil, fmt.Sprintf("<KObjSlice needs a slice, got type %T>", ks.arg)
|
||||
}
|
||||
objectRefs := make([]interface{}, 0, s.Len())
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
|
@ -151,8 +172,41 @@ func (ks kobjSlice) process() ([]interface{}, error) {
|
|||
} else if v, ok := item.(KMetadata); ok {
|
||||
objectRefs = append(objectRefs, KObj(v))
|
||||
} else {
|
||||
return nil, fmt.Errorf("<KObjSlice needs a slice of values implementing KMetadata, got type %T>", item)
|
||||
return nil, fmt.Sprintf("<KObjSlice needs a slice of values implementing KMetadata, got type %T>", item)
|
||||
}
|
||||
}
|
||||
return objectRefs, ""
|
||||
}
|
||||
|
||||
var nilToken = []byte("<nil>")
|
||||
|
||||
func (ks kobjSlice) WriteText(out *bytes.Buffer) {
|
||||
s := reflect.ValueOf(ks.arg)
|
||||
switch s.Kind() {
|
||||
case reflect.Invalid:
|
||||
// nil parameter, print as empty slice.
|
||||
out.WriteString("[]")
|
||||
return
|
||||
case reflect.Slice:
|
||||
// Okay, handle below.
|
||||
default:
|
||||
fmt.Fprintf(out, `"<KObjSlice needs a slice, got type %T>"`, ks.arg)
|
||||
return
|
||||
}
|
||||
out.Write([]byte{'['})
|
||||
defer out.Write([]byte{']'})
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
if i > 0 {
|
||||
out.Write([]byte{' '})
|
||||
}
|
||||
item := s.Index(i).Interface()
|
||||
if item == nil {
|
||||
out.Write(nilToken)
|
||||
} else if v, ok := item.(KMetadata); ok {
|
||||
KObj(v).writeUnquoted(out)
|
||||
} else {
|
||||
fmt.Fprintf(out, "<KObjSlice needs a slice of values implementing KMetadata, got type %T>", item)
|
||||
return
|
||||
}
|
||||
}
|
||||
return objectRefs, nil
|
||||
}
|
||||
|
|
|
@ -91,8 +91,6 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
||||
"k8s.io/klog/v2/internal/buffer"
|
||||
"k8s.io/klog/v2/internal/clock"
|
||||
"k8s.io/klog/v2/internal/dbg"
|
||||
|
@ -453,7 +451,7 @@ type settings struct {
|
|||
|
||||
// logger is the global Logger chosen by users of klog, nil if
|
||||
// none is available.
|
||||
logger *Logger
|
||||
logger *logWriter
|
||||
|
||||
// loggerOptions contains the options that were supplied for
|
||||
// globalLogger.
|
||||
|
@ -525,6 +523,11 @@ func (s settings) deepCopy() settings {
|
|||
}
|
||||
s.vmodule.filter = filter
|
||||
|
||||
if s.logger != nil {
|
||||
logger := *s.logger
|
||||
s.logger = &logger
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -532,11 +535,6 @@ func (s settings) deepCopy() settings {
|
|||
type loggingT struct {
|
||||
settings
|
||||
|
||||
// bufferCache maintains the free list. It uses its own mutex
|
||||
// so buffers can be grabbed and printed to without holding the main lock,
|
||||
// for better parallelization.
|
||||
bufferCache buffer.Buffers
|
||||
|
||||
// flushD holds a flushDaemon that frequently flushes log file buffers.
|
||||
// Uses its own mutex.
|
||||
flushD *flushDaemon
|
||||
|
@ -664,7 +662,7 @@ func (l *loggingT) header(s severity.Severity, depth int) (*buffer.Buffer, strin
|
|||
|
||||
// formatHeader formats a log header using the provided file name and line number.
|
||||
func (l *loggingT) formatHeader(s severity.Severity, file string, line int) *buffer.Buffer {
|
||||
buf := l.bufferCache.GetBuffer()
|
||||
buf := buffer.GetBuffer()
|
||||
if l.skipHeaders {
|
||||
return buf
|
||||
}
|
||||
|
@ -673,17 +671,18 @@ func (l *loggingT) formatHeader(s severity.Severity, file string, line int) *buf
|
|||
return buf
|
||||
}
|
||||
|
||||
func (l *loggingT) println(s severity.Severity, logger *logr.Logger, filter LogFilter, args ...interface{}) {
|
||||
func (l *loggingT) println(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
|
||||
l.printlnDepth(s, logger, filter, 1, args...)
|
||||
}
|
||||
|
||||
func (l *loggingT) printlnDepth(s severity.Severity, logger *logr.Logger, filter LogFilter, depth int, args ...interface{}) {
|
||||
func (l *loggingT) printlnDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
|
||||
buf, file, line := l.header(s, depth)
|
||||
// if logger is set, we clear the generated header as we rely on the backing
|
||||
// logger implementation to print headers
|
||||
if logger != nil {
|
||||
l.bufferCache.PutBuffer(buf)
|
||||
buf = l.bufferCache.GetBuffer()
|
||||
// If a logger is set and doesn't support writing a formatted buffer,
|
||||
// we clear the generated header as we rely on the backing
|
||||
// logger implementation to print headers.
|
||||
if logger != nil && logger.writeKlogBuffer == nil {
|
||||
buffer.PutBuffer(buf)
|
||||
buf = buffer.GetBuffer()
|
||||
}
|
||||
if filter != nil {
|
||||
args = filter.Filter(args)
|
||||
|
@ -692,17 +691,18 @@ func (l *loggingT) printlnDepth(s severity.Severity, logger *logr.Logger, filter
|
|||
l.output(s, logger, buf, depth, file, line, false)
|
||||
}
|
||||
|
||||
func (l *loggingT) print(s severity.Severity, logger *logr.Logger, filter LogFilter, args ...interface{}) {
|
||||
func (l *loggingT) print(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
|
||||
l.printDepth(s, logger, filter, 1, args...)
|
||||
}
|
||||
|
||||
func (l *loggingT) printDepth(s severity.Severity, logger *logr.Logger, filter LogFilter, depth int, args ...interface{}) {
|
||||
func (l *loggingT) printDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
|
||||
buf, file, line := l.header(s, depth)
|
||||
// if logr is set, we clear the generated header as we rely on the backing
|
||||
// logr implementation to print headers
|
||||
if logger != nil {
|
||||
l.bufferCache.PutBuffer(buf)
|
||||
buf = l.bufferCache.GetBuffer()
|
||||
// If a logger is set and doesn't support writing a formatted buffer,
|
||||
// we clear the generated header as we rely on the backing
|
||||
// logger implementation to print headers.
|
||||
if logger != nil && logger.writeKlogBuffer == nil {
|
||||
buffer.PutBuffer(buf)
|
||||
buf = buffer.GetBuffer()
|
||||
}
|
||||
if filter != nil {
|
||||
args = filter.Filter(args)
|
||||
|
@ -714,17 +714,18 @@ func (l *loggingT) printDepth(s severity.Severity, logger *logr.Logger, filter L
|
|||
l.output(s, logger, buf, depth, file, line, false)
|
||||
}
|
||||
|
||||
func (l *loggingT) printf(s severity.Severity, logger *logr.Logger, filter LogFilter, format string, args ...interface{}) {
|
||||
func (l *loggingT) printf(s severity.Severity, logger *logWriter, filter LogFilter, format string, args ...interface{}) {
|
||||
l.printfDepth(s, logger, filter, 1, format, args...)
|
||||
}
|
||||
|
||||
func (l *loggingT) printfDepth(s severity.Severity, logger *logr.Logger, filter LogFilter, depth int, format string, args ...interface{}) {
|
||||
func (l *loggingT) printfDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, format string, args ...interface{}) {
|
||||
buf, file, line := l.header(s, depth)
|
||||
// if logr is set, we clear the generated header as we rely on the backing
|
||||
// logr implementation to print headers
|
||||
if logger != nil {
|
||||
l.bufferCache.PutBuffer(buf)
|
||||
buf = l.bufferCache.GetBuffer()
|
||||
// If a logger is set and doesn't support writing a formatted buffer,
|
||||
// we clear the generated header as we rely on the backing
|
||||
// logger implementation to print headers.
|
||||
if logger != nil && logger.writeKlogBuffer == nil {
|
||||
buffer.PutBuffer(buf)
|
||||
buf = buffer.GetBuffer()
|
||||
}
|
||||
if filter != nil {
|
||||
format, args = filter.FilterF(format, args)
|
||||
|
@ -739,13 +740,14 @@ func (l *loggingT) printfDepth(s severity.Severity, logger *logr.Logger, filter
|
|||
// printWithFileLine behaves like print but uses the provided file and line number. If
|
||||
// alsoLogToStderr is true, the log message always appears on standard error; it
|
||||
// will also appear in the log file unless --logtostderr is set.
|
||||
func (l *loggingT) printWithFileLine(s severity.Severity, logger *logr.Logger, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
|
||||
func (l *loggingT) printWithFileLine(s severity.Severity, logger *logWriter, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
|
||||
buf := l.formatHeader(s, file, line)
|
||||
// if logr is set, we clear the generated header as we rely on the backing
|
||||
// logr implementation to print headers
|
||||
if logger != nil {
|
||||
l.bufferCache.PutBuffer(buf)
|
||||
buf = l.bufferCache.GetBuffer()
|
||||
// If a logger is set and doesn't support writing a formatted buffer,
|
||||
// we clear the generated header as we rely on the backing
|
||||
// logger implementation to print headers.
|
||||
if logger != nil && logger.writeKlogBuffer == nil {
|
||||
buffer.PutBuffer(buf)
|
||||
buf = buffer.GetBuffer()
|
||||
}
|
||||
if filter != nil {
|
||||
args = filter.Filter(args)
|
||||
|
@ -758,7 +760,7 @@ func (l *loggingT) printWithFileLine(s severity.Severity, logger *logr.Logger, f
|
|||
}
|
||||
|
||||
// if loggr is specified, will call loggr.Error, otherwise output with logging module.
|
||||
func (l *loggingT) errorS(err error, logger *logr.Logger, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
|
||||
func (l *loggingT) errorS(err error, logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
|
||||
if filter != nil {
|
||||
msg, keysAndValues = filter.FilterS(msg, keysAndValues)
|
||||
}
|
||||
|
@ -770,7 +772,7 @@ func (l *loggingT) errorS(err error, logger *logr.Logger, filter LogFilter, dept
|
|||
}
|
||||
|
||||
// if loggr is specified, will call loggr.Info, otherwise output with logging module.
|
||||
func (l *loggingT) infoS(logger *logr.Logger, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
|
||||
func (l *loggingT) infoS(logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
|
||||
if filter != nil {
|
||||
msg, keysAndValues = filter.FilterS(msg, keysAndValues)
|
||||
}
|
||||
|
@ -785,7 +787,7 @@ func (l *loggingT) infoS(logger *logr.Logger, filter LogFilter, depth int, msg s
|
|||
// set log severity by s
|
||||
func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string, keysAndValues ...interface{}) {
|
||||
// Only create a new buffer if we don't have one cached.
|
||||
b := l.bufferCache.GetBuffer()
|
||||
b := buffer.GetBuffer()
|
||||
// The message is always quoted, even if it contains line breaks.
|
||||
// If developers want multi-line output, they should use a small, fixed
|
||||
// message and put the multi-line output into a value.
|
||||
|
@ -796,7 +798,7 @@ func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string,
|
|||
serialize.KVListFormat(&b.Buffer, keysAndValues...)
|
||||
l.printDepth(s, logging.logger, nil, depth+1, &b.Buffer)
|
||||
// Make the buffer available for reuse.
|
||||
l.bufferCache.PutBuffer(b)
|
||||
buffer.PutBuffer(b)
|
||||
}
|
||||
|
||||
// redirectBuffer is used to set an alternate destination for the logs
|
||||
|
@ -851,7 +853,7 @@ func LogToStderr(stderr bool) {
|
|||
}
|
||||
|
||||
// output writes the data to the log files and releases the buffer.
|
||||
func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buffer, depth int, file string, line int, alsoToStderr bool) {
|
||||
func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Buffer, depth int, file string, line int, alsoToStderr bool) {
|
||||
var isLocked = true
|
||||
l.mu.Lock()
|
||||
defer func() {
|
||||
|
@ -867,13 +869,17 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
|
|||
}
|
||||
}
|
||||
data := buf.Bytes()
|
||||
if log != nil {
|
||||
// TODO: set 'severity' and caller information as structured log info
|
||||
// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
|
||||
if s == severity.ErrorLog {
|
||||
logging.logger.WithCallDepth(depth+3).Error(nil, string(data))
|
||||
if logger != nil {
|
||||
if logger.writeKlogBuffer != nil {
|
||||
logger.writeKlogBuffer(data)
|
||||
} else {
|
||||
log.WithCallDepth(depth + 3).Info(string(data))
|
||||
// TODO: set 'severity' and caller information as structured log info
|
||||
// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
|
||||
if s == severity.ErrorLog {
|
||||
logger.WithCallDepth(depth+3).Error(nil, string(data))
|
||||
} else {
|
||||
logger.WithCallDepth(depth + 3).Info(string(data))
|
||||
}
|
||||
}
|
||||
} else if l.toStderr {
|
||||
os.Stderr.Write(data)
|
||||
|
@ -948,7 +954,7 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
|
|||
timeoutFlush(ExitFlushTimeout)
|
||||
OsExit(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
|
||||
}
|
||||
l.bufferCache.PutBuffer(buf)
|
||||
buffer.PutBuffer(buf)
|
||||
|
||||
if stats := severityStats[s]; stats != nil {
|
||||
atomic.AddInt64(&stats.lines, 1)
|
||||
|
@ -1282,7 +1288,7 @@ func (l *loggingT) setV(pc uintptr) Level {
|
|||
// See the documentation of V for more information.
|
||||
type Verbose struct {
|
||||
enabled bool
|
||||
logr *logr.Logger
|
||||
logger *logWriter
|
||||
}
|
||||
|
||||
func newVerbose(level Level, b bool) Verbose {
|
||||
|
@ -1290,7 +1296,7 @@ func newVerbose(level Level, b bool) Verbose {
|
|||
return Verbose{b, nil}
|
||||
}
|
||||
v := logging.logger.V(int(level))
|
||||
return Verbose{b, &v}
|
||||
return Verbose{b, &logWriter{Logger: v, writeKlogBuffer: logging.loggerOptions.writeKlogBuffer}}
|
||||
}
|
||||
|
||||
// V reports whether verbosity at the call site is at least the requested level.
|
||||
|
@ -1313,6 +1319,13 @@ func newVerbose(level Level, b bool) Verbose {
|
|||
// less than or equal to the value of the -vmodule pattern matching the source file
|
||||
// containing the call.
|
||||
func V(level Level) Verbose {
|
||||
return VDepth(1, level)
|
||||
}
|
||||
|
||||
// VDepth is a variant of V that accepts a number of stack frames that will be
|
||||
// skipped when checking the -vmodule patterns. VDepth(0) is equivalent to
|
||||
// V().
|
||||
func VDepth(depth int, level Level) Verbose {
|
||||
// This function tries hard to be cheap unless there's work to do.
|
||||
// The fast path is two atomic loads and compares.
|
||||
|
||||
|
@ -1329,7 +1342,7 @@ func V(level Level) Verbose {
|
|||
// but if V logging is enabled we're slow anyway.
|
||||
logging.mu.Lock()
|
||||
defer logging.mu.Unlock()
|
||||
if runtime.Callers(2, logging.pcs[:]) == 0 {
|
||||
if runtime.Callers(2+depth, logging.pcs[:]) == 0 {
|
||||
return newVerbose(level, false)
|
||||
}
|
||||
// runtime.Callers returns "return PCs", but we want
|
||||
|
@ -1357,7 +1370,7 @@ func (v Verbose) Enabled() bool {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) Info(args ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.print(severity.InfoLog, v.logr, logging.filter, args...)
|
||||
logging.print(severity.InfoLog, v.logger, logging.filter, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1378,7 @@ func (v Verbose) Info(args ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) InfoDepth(depth int, args ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.printDepth(severity.InfoLog, v.logr, logging.filter, depth, args...)
|
||||
logging.printDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1373,7 +1386,7 @@ func (v Verbose) InfoDepth(depth int, args ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) Infoln(args ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.println(severity.InfoLog, v.logr, logging.filter, args...)
|
||||
logging.println(severity.InfoLog, v.logger, logging.filter, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1381,7 +1394,7 @@ func (v Verbose) Infoln(args ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) InfolnDepth(depth int, args ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.printlnDepth(severity.InfoLog, v.logr, logging.filter, depth, args...)
|
||||
logging.printlnDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1389,7 +1402,7 @@ func (v Verbose) InfolnDepth(depth int, args ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) Infof(format string, args ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.printf(severity.InfoLog, v.logr, logging.filter, format, args...)
|
||||
logging.printf(severity.InfoLog, v.logger, logging.filter, format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1397,7 +1410,7 @@ func (v Verbose) Infof(format string, args ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) InfofDepth(depth int, format string, args ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.printfDepth(severity.InfoLog, v.logr, logging.filter, depth, format, args...)
|
||||
logging.printfDepth(severity.InfoLog, v.logger, logging.filter, depth, format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1405,7 +1418,7 @@ func (v Verbose) InfofDepth(depth int, format string, args ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) InfoS(msg string, keysAndValues ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.infoS(v.logr, logging.filter, 0, msg, keysAndValues...)
|
||||
logging.infoS(v.logger, logging.filter, 0, msg, keysAndValues...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1419,14 +1432,14 @@ func InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.infoS(v.logr, logging.filter, depth, msg, keysAndValues...)
|
||||
logging.infoS(v.logger, logging.filter, depth, msg, keysAndValues...)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: Use ErrorS instead.
|
||||
func (v Verbose) Error(err error, msg string, args ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.errorS(err, v.logr, logging.filter, 0, msg, args...)
|
||||
logging.errorS(err, v.logger, logging.filter, 0, msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1434,7 +1447,7 @@ func (v Verbose) Error(err error, msg string, args ...interface{}) {
|
|||
// See the documentation of V for usage.
|
||||
func (v Verbose) ErrorS(err error, msg string, keysAndValues ...interface{}) {
|
||||
if v.enabled {
|
||||
logging.errorS(err, v.logr, logging.filter, 0, msg, keysAndValues...)
|
||||
logging.errorS(err, v.logger, logging.filter, 0, msg, keysAndValues...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,19 +42,21 @@ func (l *klogger) Init(info logr.RuntimeInfo) {
|
|||
l.callDepth += info.CallDepth
|
||||
}
|
||||
|
||||
func (l klogger) Info(level int, msg string, kvList ...interface{}) {
|
||||
func (l *klogger) Info(level int, msg string, kvList ...interface{}) {
|
||||
merged := serialize.MergeKVs(l.values, kvList)
|
||||
if l.prefix != "" {
|
||||
msg = l.prefix + ": " + msg
|
||||
}
|
||||
V(Level(level)).InfoSDepth(l.callDepth+1, msg, merged...)
|
||||
// Skip this function.
|
||||
VDepth(l.callDepth+1, Level(level)).InfoSDepth(l.callDepth+1, msg, merged...)
|
||||
}
|
||||
|
||||
func (l klogger) Enabled(level int) bool {
|
||||
return V(Level(level)).Enabled()
|
||||
func (l *klogger) Enabled(level int) bool {
|
||||
// Skip this function and logr.Logger.Info where Enabled is called.
|
||||
return VDepth(l.callDepth+2, Level(level)).Enabled()
|
||||
}
|
||||
|
||||
func (l klogger) Error(err error, msg string, kvList ...interface{}) {
|
||||
func (l *klogger) Error(err error, msg string, kvList ...interface{}) {
|
||||
merged := serialize.MergeKVs(l.values, kvList)
|
||||
if l.prefix != "" {
|
||||
msg = l.prefix + ": " + msg
|
||||
|
|
|
@ -327,6 +327,21 @@ func BuildOpenAPISpecFromRoutes(webServices []common.RouteContainer, config *com
|
|||
return a.spec, nil
|
||||
}
|
||||
|
||||
// BuildOpenAPIDefinitionsForResource builds a partial OpenAPI spec given a sample object and common.Config to customize it.
|
||||
// BuildOpenAPIDefinitionsForResources returns the OpenAPI spec which includes the definitions for the
|
||||
// passed type names.
|
||||
func BuildOpenAPIDefinitionsForResources(config *common.Config, names ...string) (map[string]*spec.Schema, error) {
|
||||
o := newOpenAPI(config)
|
||||
// We can discard the return value of toSchema because all we care about is the side effect of calling it.
|
||||
// All the models created for this resource get added to o.swagger.Definitions
|
||||
for _, name := range names {
|
||||
_, err := o.toSchema(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return o.spec.Components.Schemas, nil
|
||||
}
|
||||
func (o *openAPI) findCommonParameters(routes []common.Route) (map[interface{}]*spec3.Parameter, error) {
|
||||
commonParamsMap := make(map[interface{}]*spec3.Parameter, 0)
|
||||
paramOpsCountByName := make(map[interface{}]int, 0)
|
||||
|
|
|
@ -246,38 +246,42 @@ var schemaTypeFormatMap = map[string]typeInfo{
|
|||
// the spec does not need to be simple type,format) or can even return a simple type,format (e.g. IntOrString). For simple
|
||||
// type formats, the benefit of adding OpenAPIDefinitionGetter interface is to keep both type and property documentation.
|
||||
// Example:
|
||||
// type Sample struct {
|
||||
// ...
|
||||
// // port of the server
|
||||
// port IntOrString
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// type Sample struct {
|
||||
// ...
|
||||
// // port of the server
|
||||
// port IntOrString
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// // IntOrString documentation...
|
||||
// type IntOrString { ... }
|
||||
//
|
||||
// Adding IntOrString to this function:
|
||||
// "port" : {
|
||||
// format: "string",
|
||||
// type: "int-or-string",
|
||||
// Description: "port of the server"
|
||||
// }
|
||||
//
|
||||
// "port" : {
|
||||
// format: "string",
|
||||
// type: "int-or-string",
|
||||
// Description: "port of the server"
|
||||
// }
|
||||
//
|
||||
// Implement OpenAPIDefinitionGetter for IntOrString:
|
||||
//
|
||||
// "port" : {
|
||||
// $Ref: "#/definitions/IntOrString"
|
||||
// Description: "port of the server"
|
||||
// }
|
||||
// "port" : {
|
||||
// $Ref: "#/definitions/IntOrString"
|
||||
// Description: "port of the server"
|
||||
// }
|
||||
//
|
||||
// ...
|
||||
// definitions:
|
||||
// {
|
||||
// "IntOrString": {
|
||||
// format: "string",
|
||||
// type: "int-or-string",
|
||||
// Description: "IntOrString documentation..." // new
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "IntOrString": {
|
||||
// format: "string",
|
||||
// type: "int-or-string",
|
||||
// Description: "IntOrString documentation..." // new
|
||||
// }
|
||||
// }
|
||||
func OpenAPITypeFormat(typeName string) (string, string) {
|
||||
mapped, ok := schemaTypeFormatMap[typeName]
|
||||
if !ok {
|
||||
|
|
|
@ -13,4 +13,3 @@ func AdaptWebServices(webServices []*restful.WebService) []common.RouteContainer
|
|||
}
|
||||
return containers
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
|
@ -64,7 +63,7 @@ func (a apiViolationFile) VerifyFile(f *generator.File, path string) error {
|
|||
path = a.unmangledPath
|
||||
|
||||
formatted := f.Body.Bytes()
|
||||
existing, err := ioutil.ReadFile(path)
|
||||
existing, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read file %q for comparison: %v", path, err)
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@ func newEnumContext(c *generator.Context) *enumContext {
|
|||
// If the given type is a known enum type, returns the enumType, true
|
||||
// Otherwise, returns nil, false
|
||||
func (ec *enumContext) EnumType(t *types.Type) (enum *enumType, isEnum bool) {
|
||||
// if t is a pointer, use its underlying type instead
|
||||
if t.Kind == types.Pointer {
|
||||
t = t.Elem
|
||||
}
|
||||
enum, ok := ec.enumTypes[t.Name]
|
||||
return enum, ok
|
||||
}
|
||||
|
@ -74,9 +78,12 @@ func (et *enumType) ValueStrings() []string {
|
|||
// DescriptionLines returns a description of the enum in this format:
|
||||
//
|
||||
// Possible enum values:
|
||||
// - `"value1"` description 1
|
||||
// - `"value2"` description 2
|
||||
// - `"value1"` description 1
|
||||
// - `"value2"` description 2
|
||||
func (et *enumType) DescriptionLines() []string {
|
||||
if len(et.Values) == 0 {
|
||||
return nil
|
||||
}
|
||||
var lines []string
|
||||
for _, value := range et.Values {
|
||||
lines = append(lines, value.Description())
|
||||
|
@ -90,9 +97,9 @@ func parseEnums(c *generator.Context) enumMap {
|
|||
// First, find the builtin "string" type
|
||||
stringType := c.Universe.Type(types.Name{Name: "string"})
|
||||
|
||||
// find all enum types.
|
||||
enumTypes := make(enumMap)
|
||||
for _, p := range c.Universe {
|
||||
// find all enum types.
|
||||
for _, t := range p.Types {
|
||||
if isEnumType(stringType, t) {
|
||||
if _, ok := enumTypes[t.Name]; !ok {
|
||||
|
@ -102,7 +109,10 @@ func parseEnums(c *generator.Context) enumMap {
|
|||
}
|
||||
}
|
||||
}
|
||||
// find all enum values from constants, and try to match each with its type.
|
||||
}
|
||||
|
||||
// find all enum values from constants, and try to match each with its type.
|
||||
for _, p := range c.Universe {
|
||||
for _, c := range p.Constants {
|
||||
enumType := c.Underlying
|
||||
if _, ok := enumTypes[enumType.Name]; ok {
|
||||
|
@ -125,7 +135,7 @@ func (et *enumType) appendValue(value *enumValue) {
|
|||
|
||||
// Description returns the description line for the enumValue
|
||||
// with the format:
|
||||
// - `"FooValue"` is the Foo value
|
||||
// - `"FooValue"` is the Foo value
|
||||
func (ev *enumValue) Description() string {
|
||||
comment := strings.TrimSpace(ev.Comment)
|
||||
// The comment should starts with the type name, trim it first.
|
||||
|
|
|
@ -686,7 +686,7 @@ func (g openAPITypeWriter) generateProperty(m *types.Member, parent *types.Type)
|
|||
g.generateSimpleProperty(typeString, format)
|
||||
if enumType, isEnum := g.enumContext.EnumType(m.Type); isEnum {
|
||||
// original type is an enum, add "Enum: " and the values
|
||||
g.Do("Enum: []interface{}{$.$}", strings.Join(enumType.ValueStrings(), ", "))
|
||||
g.Do("Enum: []interface{}{$.$},\n", strings.Join(enumType.ValueStrings(), ", "))
|
||||
}
|
||||
g.Do("},\n},\n", nil)
|
||||
return nil
|
||||
|
|
|
@ -56,24 +56,29 @@ Go field names must be CamelCase. JSON field names must be camelCase. Other than
|
|||
initial letter, the two should almost always match. No underscores nor dashes in either.
|
||||
This rule verifies the convention "Other than capitalization of the initial letter, the two should almost always match."
|
||||
Examples (also in unit test):
|
||||
Go name | JSON name | match
|
||||
podSpec false
|
||||
PodSpec podSpec true
|
||||
PodSpec PodSpec false
|
||||
podSpec podSpec false
|
||||
PodSpec spec false
|
||||
Spec podSpec false
|
||||
JSONSpec jsonSpec true
|
||||
JSONSpec jsonspec false
|
||||
HTTPJSONSpec httpJSONSpec true
|
||||
|
||||
Go name | JSON name | match
|
||||
podSpec false
|
||||
PodSpec podSpec true
|
||||
PodSpec PodSpec false
|
||||
podSpec podSpec false
|
||||
PodSpec spec false
|
||||
Spec podSpec false
|
||||
JSONSpec jsonSpec true
|
||||
JSONSpec jsonspec false
|
||||
HTTPJSONSpec httpJSONSpec true
|
||||
|
||||
NOTE: this validator cannot tell two sequential all-capital words from one word, therefore the case below
|
||||
is also considered matched.
|
||||
HTTPJSONSpec httpjsonSpec true
|
||||
|
||||
HTTPJSONSpec httpjsonSpec true
|
||||
|
||||
NOTE: JSON names in jsonNameBlacklist should skip evaluation
|
||||
true
|
||||
podSpec true
|
||||
podSpec - true
|
||||
podSpec metadata true
|
||||
|
||||
true
|
||||
podSpec true
|
||||
podSpec - true
|
||||
podSpec metadata true
|
||||
*/
|
||||
type NamesMatch struct{}
|
||||
|
||||
|
@ -114,14 +119,15 @@ func (n *NamesMatch) Validate(t *types.Type) ([]string, error) {
|
|||
|
||||
// namesMatch evaluates if goName and jsonName match the API rule
|
||||
// TODO: Use an off-the-shelf CamelCase solution instead of implementing this logic. The following existing
|
||||
// packages have been tried out:
|
||||
// github.com/markbates/inflect
|
||||
// github.com/segmentio/go-camelcase
|
||||
// github.com/iancoleman/strcase
|
||||
// github.com/fatih/camelcase
|
||||
// Please see https://github.com/kubernetes/kube-openapi/pull/83#issuecomment-400842314 for more details
|
||||
// about why they don't satisfy our need. What we need can be a function that detects an acronym at the
|
||||
// beginning of a string.
|
||||
//
|
||||
// packages have been tried out:
|
||||
// github.com/markbates/inflect
|
||||
// github.com/segmentio/go-camelcase
|
||||
// github.com/iancoleman/strcase
|
||||
// github.com/fatih/camelcase
|
||||
// Please see https://github.com/kubernetes/kube-openapi/pull/83#issuecomment-400842314 for more details
|
||||
// about why they don't satisfy our need. What we need can be a function that detects an acronym at the
|
||||
// beginning of a string.
|
||||
func namesMatch(goName, jsonName string) bool {
|
||||
if jsonNameBlacklist.Has(jsonName) {
|
||||
return true
|
||||
|
|
|
@ -18,11 +18,8 @@ package handler
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha512"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
@ -42,12 +39,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
jsonExt = ".json"
|
||||
|
||||
mimeJson = "application/json"
|
||||
// TODO(mehdy): change @68f4ded to a version tag when gnostic add version tags.
|
||||
mimePb = "application/com.github.googleapis.gnostic.OpenAPIv2@68f4ded+protobuf"
|
||||
mimePbGz = "application/x-gzip"
|
||||
subTypeProtobufDeprecated = "com.github.proto-openapi.spec.v2@v1.0+protobuf"
|
||||
subTypeProtobuf = "com.github.proto-openapi.spec.v2.v1.0+protobuf"
|
||||
subTypeJSON = "json"
|
||||
)
|
||||
|
||||
func computeETag(data []byte) string {
|
||||
|
@ -70,12 +64,6 @@ type OpenAPIService struct {
|
|||
etagCache handler.HandlerCache
|
||||
}
|
||||
|
||||
func init() {
|
||||
mime.AddExtensionType(".json", mimeJson)
|
||||
mime.AddExtensionType(".pb-v1", mimePb)
|
||||
mime.AddExtensionType(".gz", mimePbGz)
|
||||
}
|
||||
|
||||
// NewOpenAPIService builds an OpenAPIService starting with the given spec.
|
||||
func NewOpenAPIService(spec *spec.Swagger) (*OpenAPIService, error) {
|
||||
o := &OpenAPIService{}
|
||||
|
@ -117,7 +105,7 @@ func (o *OpenAPIService) UpdateSpec(openapiSpec *spec.Swagger) (err error) {
|
|||
o.rwMutex.Lock()
|
||||
defer o.rwMutex.Unlock()
|
||||
o.jsonCache = o.jsonCache.New(func() ([]byte, error) {
|
||||
return json.Marshal(openapiSpec)
|
||||
return openapiSpec.MarshalJSON()
|
||||
})
|
||||
o.protoCache = o.protoCache.New(func() ([]byte, error) {
|
||||
json, err := o.jsonCache.Get()
|
||||
|
@ -146,14 +134,6 @@ func ToProtoBinary(json []byte) ([]byte, error) {
|
|||
return proto.Marshal(document)
|
||||
}
|
||||
|
||||
func toGzip(data []byte) []byte {
|
||||
var buf bytes.Buffer
|
||||
zw := gzip.NewWriter(&buf)
|
||||
zw.Write(data)
|
||||
zw.Close()
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// RegisterOpenAPIVersionedService registers a handler to provide access to provided swagger spec.
|
||||
//
|
||||
// Deprecated: use OpenAPIService.RegisterOpenAPIVersionedService instead.
|
||||
|
@ -168,12 +148,14 @@ func RegisterOpenAPIVersionedService(spec *spec.Swagger, servePath string, handl
|
|||
// RegisterOpenAPIVersionedService registers a handler to provide access to provided swagger spec.
|
||||
func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handler common.PathHandler) error {
|
||||
accepted := []struct {
|
||||
Type string
|
||||
SubType string
|
||||
GetDataAndETag func() ([]byte, string, time.Time, error)
|
||||
Type string
|
||||
SubType string
|
||||
ReturnedContentType string
|
||||
GetDataAndETag func() ([]byte, string, time.Time, error)
|
||||
}{
|
||||
{"application", "json", o.getSwaggerBytes},
|
||||
{"application", "com.github.proto-openapi.spec.v2@v1.0+protobuf", o.getSwaggerPbBytes},
|
||||
{"application", subTypeJSON, "application/" + subTypeJSON, o.getSwaggerBytes},
|
||||
{"application", subTypeProtobufDeprecated, "application/" + subTypeProtobuf, o.getSwaggerPbBytes},
|
||||
{"application", subTypeProtobuf, "application/" + subTypeProtobuf, o.getSwaggerPbBytes},
|
||||
}
|
||||
|
||||
handler.Handle(servePath, gziphandler.GzipHandler(http.HandlerFunc(
|
||||
|
@ -192,7 +174,6 @@ func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handl
|
|||
if clause.SubType != accepts.SubType && clause.SubType != "*" {
|
||||
continue
|
||||
}
|
||||
|
||||
// serve the first matching media type in the sorted clause list
|
||||
data, etag, lastModified, err := accepts.GetDataAndETag()
|
||||
if err != nil {
|
||||
|
@ -203,6 +184,9 @@ func (o *OpenAPIService) RegisterOpenAPIVersionedService(servePath string, handl
|
|||
return
|
||||
}
|
||||
}
|
||||
// Set Content-Type header in the reponse
|
||||
w.Header().Set("Content-Type", accepts.ReturnedContentType)
|
||||
|
||||
// ETag must be enclosed in double quotes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
||||
w.Header().Set("Etag", strconv.Quote(etag))
|
||||
// ServeContent will take care of caching using eTag.
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"crypto/sha512"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
|
@ -41,15 +40,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
jsonExt = ".json"
|
||||
|
||||
mimeJson = "application/json"
|
||||
// TODO(mehdy): change @68f4ded to a version tag when gnostic add version tags.
|
||||
mimePb = "application/com.github.googleapis.gnostic.OpenAPIv3@68f4ded+protobuf"
|
||||
mimePbGz = "application/x-gzip"
|
||||
|
||||
subTypeProtobuf = "com.github.proto-openapi.spec.v3@v1.0+protobuf"
|
||||
subTypeJSON = "json"
|
||||
subTypeProtobufDeprecated = "com.github.proto-openapi.spec.v3@v1.0+protobuf"
|
||||
subTypeProtobuf = "com.github.proto-openapi.spec.v3.v1.0+protobuf"
|
||||
subTypeJSON = "json"
|
||||
)
|
||||
|
||||
// OpenAPIV3Discovery is the format of the Discovery document for OpenAPI V3
|
||||
|
@ -84,12 +77,6 @@ type OpenAPIV3Group struct {
|
|||
etagCache handler.HandlerCache
|
||||
}
|
||||
|
||||
func init() {
|
||||
mime.AddExtensionType(".json", mimeJson)
|
||||
mime.AddExtensionType(".pb-v1", mimePb)
|
||||
mime.AddExtensionType(".gz", mimePbGz)
|
||||
}
|
||||
|
||||
func computeETag(data []byte) string {
|
||||
if data == nil {
|
||||
return ""
|
||||
|
@ -154,7 +141,7 @@ func (o *OpenAPIService) getSingleGroupBytes(getType string, group string) ([]by
|
|||
}
|
||||
etagBytes, err := v.etagCache.Get()
|
||||
return specBytes, string(etagBytes), v.lastModified, err
|
||||
} else if getType == subTypeProtobuf {
|
||||
} else if getType == subTypeProtobuf || getType == subTypeProtobufDeprecated {
|
||||
specPb, err := v.pbCache.Get()
|
||||
if err != nil {
|
||||
return nil, "", v.lastModified, err
|
||||
|
@ -191,6 +178,8 @@ func ToV3ProtoBinary(json []byte) ([]byte, error) {
|
|||
|
||||
func (o *OpenAPIService) HandleDiscovery(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ := o.getGroupBytes()
|
||||
w.Header().Set("Etag", strconv.Quote(computeETag(data)))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
http.ServeContent(w, r, "/openapi/v3", time.Now(), bytes.NewReader(data))
|
||||
}
|
||||
|
||||
|
@ -210,11 +199,13 @@ func (o *OpenAPIService) HandleGroupVersion(w http.ResponseWriter, r *http.Reque
|
|||
}
|
||||
|
||||
accepted := []struct {
|
||||
Type string
|
||||
SubType string
|
||||
Type string
|
||||
SubType string
|
||||
ReturnedContentType string
|
||||
}{
|
||||
{"application", subTypeJSON},
|
||||
{"application", subTypeProtobuf},
|
||||
{"application", subTypeJSON, "application/" + subTypeJSON},
|
||||
{"application", subTypeProtobuf, "application/" + subTypeProtobuf},
|
||||
{"application", subTypeProtobufDeprecated, "application/" + subTypeProtobuf},
|
||||
}
|
||||
|
||||
for _, clause := range clauses {
|
||||
|
@ -229,6 +220,9 @@ func (o *OpenAPIService) HandleGroupVersion(w http.ResponseWriter, r *http.Reque
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Set Content-Type header in the reponse
|
||||
w.Header().Set("Content-Type", accepts.ReturnedContentType)
|
||||
|
||||
// ETag must be enclosed in double quotes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
||||
w.Header().Set("Etag", strconv.Quote(etag))
|
||||
|
||||
|
|
|
@ -18,3 +18,7 @@ package internal
|
|||
|
||||
// Used by tests to selectively disable experimental JSON unmarshaler
|
||||
var UseOptimizedJSONUnmarshaling bool = true
|
||||
var UseOptimizedJSONUnmarshalingV3 bool = true
|
||||
|
||||
// Used by tests to selectively disable experimental JSON marshaler
|
||||
var UseOptimizedJSONMarshaling bool = true
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/jsonreference"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
)
|
||||
|
||||
// DeterministicMarshal calls the jsonv2 library with the deterministic
|
||||
// flag in order to have stable marshaling.
|
||||
func DeterministicMarshal(in any) ([]byte, error) {
|
||||
return jsonv2.MarshalOptions{Deterministic: true}.Marshal(jsonv2.EncodeOptions{}, in)
|
||||
}
|
||||
|
||||
// JSONRefFromMap populates a json reference object if the map v contains a $ref key.
|
||||
func JSONRefFromMap(jsonRef *jsonreference.Ref, v map[string]interface{}) error {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
if vv, ok := v["$ref"]; ok {
|
||||
if str, ok := vv.(string); ok {
|
||||
ref, err := jsonreference.New(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*jsonRef = ref
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SanitizeExtensions sanitizes the input map such that non extension
|
||||
// keys (non x-*, X-*) keys are dropped from the map. Returns the new
|
||||
// modified map, or nil if the map is now empty.
|
||||
func SanitizeExtensions(e map[string]interface{}) map[string]interface{} {
|
||||
for k := range e {
|
||||
if !IsExtensionKey(k) {
|
||||
delete(e, k)
|
||||
}
|
||||
}
|
||||
if len(e) == 0 {
|
||||
e = nil
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// IsExtensionKey returns true if the input string is of format x-* or X-*
|
||||
func IsExtensionKey(k string) bool {
|
||||
return len(k) > 1 && (k[0] == 'x' || k[0] == 'X') && k[1] == '-'
|
||||
}
|
|
@ -34,6 +34,13 @@ type MarshalOptions struct {
|
|||
// unknown JSON object members.
|
||||
DiscardUnknownMembers bool
|
||||
|
||||
// Deterministic specifies that the same input value will be serialized
|
||||
// as the exact same output bytes. Different processes of
|
||||
// the same program will serialize equal values to the same bytes,
|
||||
// but different versions of the same program are not guaranteed
|
||||
// to produce the exact same sequence of bytes.
|
||||
Deterministic bool
|
||||
|
||||
// formatDepth is the depth at which we respect the format flag.
|
||||
formatDepth int
|
||||
// format is custom formatting for the value at the specified depth.
|
||||
|
|
|
@ -62,7 +62,7 @@ func unmarshalValueAny(uo UnmarshalOptions, dec *Decoder) (any, error) {
|
|||
}
|
||||
return dec.stringCache.make(val), nil
|
||||
case '0':
|
||||
fv, _ := parseFloat(val, 64) // ignore error since readValue gaurantees val is valid
|
||||
fv, _ := parseFloat(val, 64) // ignore error since readValue guarantees val is valid
|
||||
return fv, nil
|
||||
default:
|
||||
panic("BUG: invalid kind: " + k.String())
|
||||
|
@ -99,13 +99,32 @@ func marshalObjectAny(mo MarshalOptions, enc *Encoder, obj map[string]any) error
|
|||
if !enc.options.AllowInvalidUTF8 {
|
||||
enc.tokens.last.disableNamespace()
|
||||
}
|
||||
for name, val := range obj {
|
||||
if err := enc.WriteToken(String(name)); err != nil {
|
||||
return err
|
||||
if !mo.Deterministic || len(obj) <= 1 {
|
||||
for name, val := range obj {
|
||||
if err := enc.WriteToken(String(name)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := marshalValueAny(mo, enc, val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := marshalValueAny(mo, enc, val); err != nil {
|
||||
return err
|
||||
} else {
|
||||
names := getStrings(len(obj))
|
||||
var i int
|
||||
for name := range obj {
|
||||
(*names)[i] = name
|
||||
i++
|
||||
}
|
||||
names.Sort()
|
||||
for _, name := range *names {
|
||||
if err := enc.WriteToken(String(name)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := marshalValueAny(mo, enc, obj[name]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
putStrings(names)
|
||||
}
|
||||
if err := enc.WriteToken(ObjectEnd); err != nil {
|
||||
return err
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
@ -228,13 +230,7 @@ func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler {
|
|||
}
|
||||
}
|
||||
val := enc.UnusedBuffer()
|
||||
var b []byte
|
||||
if va.Kind() == reflect.Array {
|
||||
// TODO(https://go.dev/issue/47066): Avoid reflect.Value.Slice.
|
||||
b = va.Slice(0, va.Len()).Bytes()
|
||||
} else {
|
||||
b = va.Bytes()
|
||||
}
|
||||
b := va.Bytes()
|
||||
n := len(`"`) + encodedLen(len(b)) + len(`"`)
|
||||
if cap(val) < n {
|
||||
val = make([]byte, n)
|
||||
|
@ -248,19 +244,19 @@ func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler {
|
|||
}
|
||||
unmarshalDefault := fncs.unmarshal
|
||||
fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error {
|
||||
decode, decodedLen := decodeBase64, decodedLenBase64
|
||||
decode, decodedLen, encodedLen := decodeBase64, decodedLenBase64, encodedLenBase64
|
||||
if uo.format != "" && uo.formatDepth == dec.tokens.depth() {
|
||||
switch uo.format {
|
||||
case "base64":
|
||||
decode, decodedLen = decodeBase64, decodedLenBase64
|
||||
decode, decodedLen, encodedLen = decodeBase64, decodedLenBase64, encodedLenBase64
|
||||
case "base64url":
|
||||
decode, decodedLen = decodeBase64URL, decodedLenBase64URL
|
||||
decode, decodedLen, encodedLen = decodeBase64URL, decodedLenBase64URL, encodedLenBase64URL
|
||||
case "base32":
|
||||
decode, decodedLen = decodeBase32, decodedLenBase32
|
||||
decode, decodedLen, encodedLen = decodeBase32, decodedLenBase32, encodedLenBase32
|
||||
case "base32hex":
|
||||
decode, decodedLen = decodeBase32Hex, decodedLenBase32Hex
|
||||
decode, decodedLen, encodedLen = decodeBase32Hex, decodedLenBase32Hex, encodedLenBase32Hex
|
||||
case "base16", "hex":
|
||||
decode, decodedLen = decodeBase16, decodedLenBase16
|
||||
decode, decodedLen, encodedLen = decodeBase16, decodedLenBase16, encodedLenBase16
|
||||
case "array":
|
||||
uo.format = ""
|
||||
return unmarshalDefault(uo, dec, va)
|
||||
|
@ -290,23 +286,28 @@ func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler {
|
|||
n--
|
||||
}
|
||||
n = decodedLen(n)
|
||||
var b []byte
|
||||
b := va.Bytes()
|
||||
if va.Kind() == reflect.Array {
|
||||
// TODO(https://go.dev/issue/47066): Avoid reflect.Value.Slice.
|
||||
b = va.Slice(0, va.Len()).Bytes()
|
||||
if n != len(b) {
|
||||
err := fmt.Errorf("decoded base64 length of %d mismatches array length of %d", n, len(b))
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
}
|
||||
} else {
|
||||
b = va.Bytes()
|
||||
if b == nil || cap(b) < n {
|
||||
b = make([]byte, n)
|
||||
} else {
|
||||
b = b[:n]
|
||||
}
|
||||
}
|
||||
if _, err := decode(b, val); err != nil {
|
||||
n2, err := decode(b, val)
|
||||
if err == nil && len(val) != encodedLen(n2) {
|
||||
// TODO(https://go.dev/issue/53845): RFC 4648, section 3.3,
|
||||
// specifies that non-alphabet characters must be rejected.
|
||||
// Unfortunately, the "base32" and "base64" packages allow
|
||||
// '\r' and '\n' characters by default.
|
||||
err = errors.New("illegal data at input byte " + strconv.Itoa(bytes.IndexAny(val, "\r\n")))
|
||||
}
|
||||
if err != nil {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
}
|
||||
if va.Kind() == reflect.Slice {
|
||||
|
@ -412,7 +413,7 @@ func makeUintArshaler(t reflect.Type) *arshaler {
|
|||
return nil
|
||||
}
|
||||
|
||||
x := math.Float64frombits(uint64(va.Uint()))
|
||||
x := math.Float64frombits(va.Uint())
|
||||
return enc.writeNumber(x, rawUintNumber, mo.StringifyNumbers)
|
||||
}
|
||||
fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error {
|
||||
|
@ -450,7 +451,7 @@ func makeUintArshaler(t reflect.Type) *arshaler {
|
|||
err := fmt.Errorf("cannot parse %q as unsigned integer: %w", val, strconv.ErrRange)
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
}
|
||||
va.SetUint(uint64(n))
|
||||
va.SetUint(n)
|
||||
return nil
|
||||
}
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
|
||||
|
@ -549,23 +550,9 @@ func makeFloatArshaler(t reflect.Type) *arshaler {
|
|||
return &fncs
|
||||
}
|
||||
|
||||
var mapIterPool = sync.Pool{
|
||||
New: func() any { return new(reflect.MapIter) },
|
||||
}
|
||||
|
||||
func getMapIter(mv reflect.Value) *reflect.MapIter {
|
||||
iter := mapIterPool.Get().(*reflect.MapIter)
|
||||
iter.Reset(mv)
|
||||
return iter
|
||||
}
|
||||
func putMapIter(iter *reflect.MapIter) {
|
||||
iter.Reset(reflect.Value{}) // allow underlying map to be garbage collected
|
||||
mapIterPool.Put(iter)
|
||||
}
|
||||
|
||||
func makeMapArshaler(t reflect.Type) *arshaler {
|
||||
// NOTE: The logic below disables namespaces for tracking duplicate names
|
||||
// when handling map keys with a unique represention.
|
||||
// when handling map keys with a unique representation.
|
||||
|
||||
// NOTE: Values retrieved from a map are not addressable,
|
||||
// so we shallow copy the values to make them addressable and
|
||||
|
@ -641,24 +628,76 @@ func makeMapArshaler(t reflect.Type) *arshaler {
|
|||
enc.tokens.last.disableNamespace()
|
||||
}
|
||||
|
||||
// NOTE: Map entries are serialized in a non-deterministic order.
|
||||
// Users that need stable output should call RawValue.Canonicalize.
|
||||
// TODO(go1.19): Remove use of a sync.Pool with reflect.MapIter.
|
||||
// Calling reflect.Value.MapRange no longer allocates.
|
||||
// See https://go.dev/cl/400675.
|
||||
iter := getMapIter(va.Value)
|
||||
defer putMapIter(iter)
|
||||
for iter.Next() {
|
||||
k.SetIterKey(iter)
|
||||
if err := marshalKey(mko, enc, k); err != nil {
|
||||
// TODO: If err is errMissingName, then wrap it as a
|
||||
// SemanticError since this key type cannot be serialized
|
||||
// as a JSON string.
|
||||
return err
|
||||
switch {
|
||||
case !mo.Deterministic || n <= 1:
|
||||
for iter := va.Value.MapRange(); iter.Next(); {
|
||||
k.SetIterKey(iter)
|
||||
if err := marshalKey(mko, enc, k); err != nil {
|
||||
// TODO: If err is errMissingName, then wrap it as a
|
||||
// SemanticError since this key type cannot be serialized
|
||||
// as a JSON string.
|
||||
return err
|
||||
}
|
||||
v.SetIterValue(iter)
|
||||
if err := marshalVal(mo, enc, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v.SetIterValue(iter)
|
||||
if err := marshalVal(mo, enc, v); err != nil {
|
||||
return err
|
||||
case !nonDefaultKey && t.Key().Kind() == reflect.String:
|
||||
names := getStrings(n)
|
||||
for i, iter := 0, va.Value.MapRange(); i < n && iter.Next(); i++ {
|
||||
k.SetIterKey(iter)
|
||||
(*names)[i] = k.String()
|
||||
}
|
||||
names.Sort()
|
||||
for _, name := range *names {
|
||||
if err := enc.WriteToken(String(name)); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(https://go.dev/issue/57061): Use v.SetMapIndexOf.
|
||||
k.SetString(name)
|
||||
v.Set(va.MapIndex(k.Value))
|
||||
if err := marshalVal(mo, enc, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
putStrings(names)
|
||||
default:
|
||||
type member struct {
|
||||
name string // unquoted name
|
||||
key addressableValue
|
||||
}
|
||||
members := make([]member, n)
|
||||
keys := reflect.MakeSlice(reflect.SliceOf(t.Key()), n, n)
|
||||
for i, iter := 0, va.Value.MapRange(); i < n && iter.Next(); i++ {
|
||||
// Marshal the member name.
|
||||
k := addressableValue{keys.Index(i)} // indexed slice element is always addressable
|
||||
k.SetIterKey(iter)
|
||||
if err := marshalKey(mko, enc, k); err != nil {
|
||||
// TODO: If err is errMissingName, then wrap it as a
|
||||
// SemanticError since this key type cannot be serialized
|
||||
// as a JSON string.
|
||||
return err
|
||||
}
|
||||
name := enc.unwriteOnlyObjectMemberName()
|
||||
members[i] = member{name, k}
|
||||
}
|
||||
// TODO: If AllowDuplicateNames is enabled, then sort according
|
||||
// to reflect.Value as well if the names are equal.
|
||||
// See internal/fmtsort.
|
||||
// TODO(https://go.dev/issue/47619): Use slices.SortFunc instead.
|
||||
sort.Slice(members, func(i, j int) bool {
|
||||
return lessUTF16(members[i].name, members[j].name)
|
||||
})
|
||||
for _, member := range members {
|
||||
if err := enc.WriteToken(String(member.name)); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(https://go.dev/issue/57061): Use v.SetMapIndexOf.
|
||||
v.Set(va.MapIndex(member.key.Value))
|
||||
if err := marshalVal(mo, enc, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -856,7 +895,7 @@ func makeStructArshaler(t reflect.Type) *arshaler {
|
|||
// 2. The object namespace is guaranteed to be disabled.
|
||||
// 3. The object name is guaranteed to be valid and pre-escaped.
|
||||
// 4. There is no need to flush the buffer (for unwrite purposes).
|
||||
// 5. There is no possibility of an error occuring.
|
||||
// 5. There is no possibility of an error occurring.
|
||||
if optimizeCommon {
|
||||
// Append any delimiters or optional whitespace.
|
||||
if enc.tokens.last.length() > 0 {
|
||||
|
@ -996,7 +1035,7 @@ func makeStructArshaler(t reflect.Type) *arshaler {
|
|||
|
||||
if fields.inlinedFallback == nil {
|
||||
// Skip unknown value since we have no place to store it.
|
||||
if err := dec.skipValue(); err != nil {
|
||||
if err := dec.SkipValue(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
@ -89,35 +90,61 @@ func marshalInlinedFallbackAll(mo MarshalOptions, enc *Encoder, va addressableVa
|
|||
}
|
||||
return nil
|
||||
} else {
|
||||
if v.Len() == 0 {
|
||||
m := v // must be a map[string]V
|
||||
n := m.Len()
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
m := v
|
||||
mk := newAddressableValue(stringType)
|
||||
mv := newAddressableValue(m.Type().Elem())
|
||||
for iter := m.MapRange(); iter.Next(); {
|
||||
b, err := appendString(enc.UnusedBuffer(), iter.Key().String(), !enc.options.AllowInvalidUTF8, nil)
|
||||
marshalKey := func(mk addressableValue) error {
|
||||
b, err := appendString(enc.UnusedBuffer(), mk.String(), !enc.options.AllowInvalidUTF8, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if insertUnquotedName != nil {
|
||||
isVerbatim := consumeSimpleString(b) == len(b)
|
||||
isVerbatim := bytes.IndexByte(b, '\\') < 0
|
||||
name := unescapeStringMayCopy(b, isVerbatim)
|
||||
if !insertUnquotedName(name) {
|
||||
return &SyntacticError{str: "duplicate name " + string(b) + " in object"}
|
||||
}
|
||||
}
|
||||
if err := enc.WriteValue(b); err != nil {
|
||||
return err
|
||||
return enc.WriteValue(b)
|
||||
}
|
||||
marshalVal := f.fncs.marshal
|
||||
if mo.Marshalers != nil {
|
||||
marshalVal, _ = mo.Marshalers.lookup(marshalVal, mv.Type())
|
||||
}
|
||||
if !mo.Deterministic || n <= 1 {
|
||||
for iter := m.MapRange(); iter.Next(); {
|
||||
mk.SetIterKey(iter)
|
||||
if err := marshalKey(mk); err != nil {
|
||||
return err
|
||||
}
|
||||
mv.Set(iter.Value())
|
||||
if err := marshalVal(mo, enc, mv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
mv.Set(iter.Value())
|
||||
marshal := f.fncs.marshal
|
||||
if mo.Marshalers != nil {
|
||||
marshal, _ = mo.Marshalers.lookup(marshal, mv.Type())
|
||||
} else {
|
||||
names := getStrings(n)
|
||||
for i, iter := 0, m.Value.MapRange(); i < n && iter.Next(); i++ {
|
||||
mk.SetIterKey(iter)
|
||||
(*names)[i] = mk.String()
|
||||
}
|
||||
if err := marshal(mo, enc, mv); err != nil {
|
||||
return err
|
||||
names.Sort()
|
||||
for _, name := range *names {
|
||||
mk.SetString(name)
|
||||
if err := marshalKey(mk); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(https://go.dev/issue/57061): Use mv.SetMapIndexOf.
|
||||
mv.Set(m.MapIndex(mk.Value))
|
||||
if err := marshalVal(mo, enc, mv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
putStrings(names)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -162,7 +189,7 @@ func unmarshalInlinedFallbackNext(uo UnmarshalOptions, dec *Decoder, va addressa
|
|||
} else {
|
||||
name := string(unquotedName) // TODO: Intern this?
|
||||
|
||||
m := v
|
||||
m := v // must be a map[string]V
|
||||
if m.IsNil() {
|
||||
m.Set(reflect.MakeMap(m.Type()))
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ var (
|
|||
)
|
||||
|
||||
// MarshalerV1 is implemented by types that can marshal themselves.
|
||||
// It is recommended that types implement MarshalerV2 unless
|
||||
// the implementation is trying to avoid a hard dependency on this package.
|
||||
// It is recommended that types implement MarshalerV2 unless the implementation
|
||||
// is trying to avoid a hard dependency on the "jsontext" package.
|
||||
//
|
||||
// It is recommended that implementations return a buffer that is safe
|
||||
// for the caller to retain and potentially mutate.
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
@ -85,25 +86,39 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
|||
fncs.nonDefault = true
|
||||
fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error {
|
||||
format := time.RFC3339Nano
|
||||
isRFC3339 := true
|
||||
if mo.format != "" && mo.formatDepth == enc.tokens.depth() {
|
||||
var err error
|
||||
format, err = checkTimeFormat(mo.format)
|
||||
format, isRFC3339, err = checkTimeFormat(mo.format)
|
||||
if err != nil {
|
||||
return &SemanticError{action: "marshal", GoType: t, Err: err}
|
||||
}
|
||||
}
|
||||
|
||||
tt := va.Interface().(time.Time)
|
||||
if y := tt.Year(); y < 0 || y >= 10000 {
|
||||
// RFC 3339 is clear that years are 4 digits exactly.
|
||||
// See https://go.dev/issue/4556#c15 for more discussion.
|
||||
err := fmt.Errorf("year %d outside of range [0,9999]", y)
|
||||
return &SemanticError{action: "marshal", GoType: t, Err: err}
|
||||
}
|
||||
b := enc.UnusedBuffer()
|
||||
b = append(b, '"')
|
||||
b = tt.AppendFormat(b, format)
|
||||
b = append(b, '"')
|
||||
if isRFC3339 {
|
||||
// Not all Go timestamps can be represented as valid RFC 3339.
|
||||
// Explicitly check for these edge cases.
|
||||
// See https://go.dev/issue/4556 and https://go.dev/issue/54580.
|
||||
var err error
|
||||
switch b := b[len(`"`) : len(b)-len(`"`)]; {
|
||||
case b[len("9999")] != '-': // year must be exactly 4 digits wide
|
||||
err = errors.New("year outside of range [0,9999]")
|
||||
case b[len(b)-1] != 'Z':
|
||||
c := b[len(b)-len("Z07:00")]
|
||||
if ('0' <= c && c <= '9') || parseDec2(b[len(b)-len("07:00"):]) >= 24 {
|
||||
err = errors.New("timezone hour outside of range [0,23]")
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return &SemanticError{action: "marshal", GoType: t, Err: err}
|
||||
}
|
||||
return enc.WriteValue(b) // RFC 3339 never needs JSON escaping
|
||||
}
|
||||
// The format may contain special characters that need escaping.
|
||||
// Verify that the result is a valid JSON string (common case),
|
||||
// otherwise escape the string correctly (slower case).
|
||||
|
@ -113,10 +128,11 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
|||
return enc.WriteValue(b)
|
||||
}
|
||||
fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error {
|
||||
format := time.RFC3339Nano
|
||||
format := time.RFC3339
|
||||
isRFC3339 := true
|
||||
if uo.format != "" && uo.formatDepth == dec.tokens.depth() {
|
||||
var err error
|
||||
format, err = checkTimeFormat(uo.format)
|
||||
format, isRFC3339, err = checkTimeFormat(uo.format)
|
||||
if err != nil {
|
||||
return &SemanticError{action: "unmarshal", GoType: t, Err: err}
|
||||
}
|
||||
|
@ -136,6 +152,29 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
|||
case '"':
|
||||
val = unescapeStringMayCopy(val, flags.isVerbatim())
|
||||
tt2, err := time.Parse(format, string(val))
|
||||
if isRFC3339 && err == nil {
|
||||
// TODO(https://go.dev/issue/54580): RFC 3339 specifies
|
||||
// the exact grammar of a valid timestamp. However,
|
||||
// the parsing functionality in "time" is too loose and
|
||||
// incorrectly accepts invalid timestamps as valid.
|
||||
// Remove these manual checks when "time" checks it for us.
|
||||
newParseError := func(layout, value, layoutElem, valueElem, message string) error {
|
||||
return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message}
|
||||
}
|
||||
switch {
|
||||
case val[len("2006-01-02T")+1] == ':': // hour must be two digits
|
||||
err = newParseError(format, string(val), "15", string(val[len("2006-01-02T"):][:1]), "")
|
||||
case val[len("2006-01-02T15:04:05")] == ',': // sub-second separator must be a period
|
||||
err = newParseError(format, string(val), ".", ",", "")
|
||||
case val[len(val)-1] != 'Z':
|
||||
switch {
|
||||
case parseDec2(val[len(val)-len("07:00"):]) >= 24: // timezone hour must be in range
|
||||
err = newParseError(format, string(val), "Z07:00", string(val[len(val)-len("Z07:00"):]), ": timezone hour out of range")
|
||||
case parseDec2(val[len(val)-len("00"):]) >= 60: // timezone minute must be in range
|
||||
err = newParseError(format, string(val), "Z07:00", string(val[len(val)-len("Z07:00"):]), ": timezone minute out of range")
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
|
||||
}
|
||||
|
@ -149,48 +188,54 @@ func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
|
|||
return fncs
|
||||
}
|
||||
|
||||
func checkTimeFormat(format string) (string, error) {
|
||||
func checkTimeFormat(format string) (string, bool, error) {
|
||||
// We assume that an exported constant in the time package will
|
||||
// always start with an uppercase ASCII letter.
|
||||
if len(format) > 0 && 'A' <= format[0] && format[0] <= 'Z' {
|
||||
switch format {
|
||||
case "ANSIC":
|
||||
return time.ANSIC, nil
|
||||
return time.ANSIC, false, nil
|
||||
case "UnixDate":
|
||||
return time.UnixDate, nil
|
||||
return time.UnixDate, false, nil
|
||||
case "RubyDate":
|
||||
return time.RubyDate, nil
|
||||
return time.RubyDate, false, nil
|
||||
case "RFC822":
|
||||
return time.RFC822, nil
|
||||
return time.RFC822, false, nil
|
||||
case "RFC822Z":
|
||||
return time.RFC822Z, nil
|
||||
return time.RFC822Z, false, nil
|
||||
case "RFC850":
|
||||
return time.RFC850, nil
|
||||
return time.RFC850, false, nil
|
||||
case "RFC1123":
|
||||
return time.RFC1123, nil
|
||||
return time.RFC1123, false, nil
|
||||
case "RFC1123Z":
|
||||
return time.RFC1123Z, nil
|
||||
return time.RFC1123Z, false, nil
|
||||
case "RFC3339":
|
||||
return time.RFC3339, nil
|
||||
return time.RFC3339, true, nil
|
||||
case "RFC3339Nano":
|
||||
return time.RFC3339Nano, nil
|
||||
return time.RFC3339Nano, true, nil
|
||||
case "Kitchen":
|
||||
return time.Kitchen, nil
|
||||
return time.Kitchen, false, nil
|
||||
case "Stamp":
|
||||
return time.Stamp, nil
|
||||
return time.Stamp, false, nil
|
||||
case "StampMilli":
|
||||
return time.StampMilli, nil
|
||||
return time.StampMilli, false, nil
|
||||
case "StampMicro":
|
||||
return time.StampMicro, nil
|
||||
return time.StampMicro, false, nil
|
||||
case "StampNano":
|
||||
return time.StampNano, nil
|
||||
return time.StampNano, false, nil
|
||||
default:
|
||||
// Reject any format that is an exported Go identifier in case
|
||||
// new format constants are added to the time package.
|
||||
if strings.TrimFunc(format, isLetterOrDigit) == "" {
|
||||
return "", fmt.Errorf("undefined format layout: %v", format)
|
||||
return "", false, fmt.Errorf("undefined format layout: %v", format)
|
||||
}
|
||||
}
|
||||
}
|
||||
return format, nil
|
||||
return format, false, nil
|
||||
}
|
||||
|
||||
// parseDec2 parses b as an unsigned, base-10, 2-digit number.
|
||||
// It panics if len(b) < 2. The result is undefined if digits are not base-10.
|
||||
func parseDec2(b []byte) byte {
|
||||
return 10*(b[0]-'0') + (b[1] - '0')
|
||||
}
|
||||
|
|
12
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/decode.go
generated
vendored
12
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/decode.go
generated
vendored
|
@ -347,9 +347,9 @@ func (d *Decoder) PeekKind() Kind {
|
|||
return next
|
||||
}
|
||||
|
||||
// skipValue is semantically equivalent to calling ReadValue and discarding
|
||||
// SkipValue is semantically equivalent to calling ReadValue and discarding
|
||||
// the result except that memory is not wasted trying to hold the entire result.
|
||||
func (d *Decoder) skipValue() error {
|
||||
func (d *Decoder) SkipValue() error {
|
||||
switch d.PeekKind() {
|
||||
case '{', '[':
|
||||
// For JSON objects and arrays, keep skipping all tokens
|
||||
|
@ -374,7 +374,7 @@ func (d *Decoder) skipValue() error {
|
|||
}
|
||||
|
||||
// ReadToken reads the next Token, advancing the read offset.
|
||||
// The returned token is only valid until the next Peek or Read call.
|
||||
// The returned token is only valid until the next Peek, Read, or Skip call.
|
||||
// It returns io.EOF if there are no more tokens.
|
||||
func (d *Decoder) ReadToken() (Token, error) {
|
||||
// Determine the next kind.
|
||||
|
@ -585,7 +585,7 @@ func (f valueFlags) isCanonical() bool { return f&stringNonCanonical == 0 }
|
|||
|
||||
// ReadValue returns the next raw JSON value, advancing the read offset.
|
||||
// The value is stripped of any leading or trailing whitespace.
|
||||
// The returned value is only valid until the next Peek or Read call and
|
||||
// The returned value is only valid until the next Peek, Read, or Skip call and
|
||||
// may not be mutated while the Decoder remains in use.
|
||||
// If the decoder is currently at the end token for an object or array,
|
||||
// then it reports a SyntacticError and the internal state remains unchanged.
|
||||
|
@ -1013,7 +1013,7 @@ func (d *Decoder) InputOffset() int64 {
|
|||
// UnreadBuffer returns the data remaining in the unread buffer,
|
||||
// which may contain zero or more bytes.
|
||||
// The returned buffer must not be mutated while Decoder continues to be used.
|
||||
// The buffer contents are valid until the next Peek or Read call.
|
||||
// The buffer contents are valid until the next Peek, Read, or Skip call.
|
||||
func (d *Decoder) UnreadBuffer() []byte {
|
||||
return d.unreadBuffer()
|
||||
}
|
||||
|
@ -1213,7 +1213,7 @@ func consumeStringResumable(flags *valueFlags, b []byte, resumeOffset int, valid
|
|||
return n, &SyntacticError{str: "invalid escape sequence " + strconv.Quote(string(b[n:n+6])) + " within string"}
|
||||
}
|
||||
// Only certain control characters can use the \uFFFF notation
|
||||
// for canonical formating (per RFC 8785, section 3.2.2.2.).
|
||||
// for canonical formatting (per RFC 8785, section 3.2.2.2.).
|
||||
switch v1 {
|
||||
// \uFFFF notation not permitted for these characters.
|
||||
case '\b', '\f', '\n', '\r', '\t':
|
||||
|
|
9
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/doc.go
generated
vendored
9
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/doc.go
generated
vendored
|
@ -8,8 +8,7 @@
|
|||
// primitive data types such as booleans, strings, and numbers,
|
||||
// in addition to structured data types such as objects and arrays.
|
||||
//
|
||||
//
|
||||
// Terminology
|
||||
// # Terminology
|
||||
//
|
||||
// This package uses the terms "encode" and "decode" for syntactic functionality
|
||||
// that is concerned with processing JSON based on its grammar, and
|
||||
|
@ -32,8 +31,7 @@
|
|||
//
|
||||
// See RFC 8259 for more information.
|
||||
//
|
||||
//
|
||||
// Specifications
|
||||
// # Specifications
|
||||
//
|
||||
// Relevant specifications include RFC 4627, RFC 7159, RFC 7493, RFC 8259,
|
||||
// and RFC 8785. Each RFC is generally a stricter subset of another RFC.
|
||||
|
@ -60,8 +58,7 @@
|
|||
// In particular, it makes specific choices about behavior that RFC 8259
|
||||
// leaves as undefined in order to ensure greater interoperability.
|
||||
//
|
||||
//
|
||||
// JSON Representation of Go structs
|
||||
// # JSON Representation of Go structs
|
||||
//
|
||||
// A Go struct is naturally represented as a JSON object,
|
||||
// where each Go struct field corresponds with a JSON object member.
|
||||
|
|
24
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/encode.go
generated
vendored
24
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/encode.go
generated
vendored
|
@ -347,6 +347,30 @@ func (e *Encoder) unwriteEmptyObjectMember(prevName *string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// unwriteOnlyObjectMemberName unwrites the only object member name
|
||||
// and returns the unquoted name.
|
||||
func (e *Encoder) unwriteOnlyObjectMemberName() string {
|
||||
if last := e.tokens.last; !last.isObject() || last.length() != 1 {
|
||||
panic("BUG: must be called on an object after writing first name")
|
||||
}
|
||||
|
||||
// Unwrite the name and whitespace.
|
||||
b := trimSuffixString(e.buf)
|
||||
isVerbatim := bytes.IndexByte(e.buf[len(b):], '\\') < 0
|
||||
name := string(unescapeStringMayCopy(e.buf[len(b):], isVerbatim))
|
||||
e.buf = trimSuffixWhitespace(b)
|
||||
|
||||
// Undo state changes.
|
||||
e.tokens.last.decrement()
|
||||
if !e.options.AllowDuplicateNames {
|
||||
if e.tokens.last.isActiveNamespace() {
|
||||
e.namespaces.last().removeLast()
|
||||
}
|
||||
e.names.clearLast()
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func trimSuffixWhitespace(b []byte) []byte {
|
||||
// NOTE: The arguments and logic are kept simple to keep this inlineable.
|
||||
n := len(b) - 1
|
||||
|
|
32
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/pools.go
generated
vendored
32
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/pools.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"io"
|
||||
"math/bits"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
@ -148,3 +149,34 @@ func putStreamingDecoder(d *Decoder) {
|
|||
streamingDecoderPool.Put(d)
|
||||
}
|
||||
}
|
||||
|
||||
var stringsPools = &sync.Pool{New: func() any { return new(stringSlice) }}
|
||||
|
||||
type stringSlice []string
|
||||
|
||||
// getStrings returns a non-nil pointer to a slice with length n.
|
||||
func getStrings(n int) *stringSlice {
|
||||
s := stringsPools.Get().(*stringSlice)
|
||||
if cap(*s) < n {
|
||||
*s = make([]string, n)
|
||||
}
|
||||
*s = (*s)[:n]
|
||||
return s
|
||||
}
|
||||
|
||||
func putStrings(s *stringSlice) {
|
||||
if cap(*s) > 1<<10 {
|
||||
*s = nil // avoid pinning arbitrarily large amounts of memory
|
||||
}
|
||||
stringsPools.Put(s)
|
||||
}
|
||||
|
||||
// Sort sorts the string slice according to RFC 8785, section 3.2.3.
|
||||
func (ss *stringSlice) Sort() {
|
||||
// TODO(https://go.dev/issue/47619): Use slices.SortFunc instead.
|
||||
sort.Sort(ss)
|
||||
}
|
||||
|
||||
func (ss *stringSlice) Len() int { return len(*ss) }
|
||||
func (ss *stringSlice) Less(i, j int) bool { return lessUTF16((*ss)[i], (*ss)[j]) }
|
||||
func (ss *stringSlice) Swap(i, j int) { (*ss)[i], (*ss)[j] = (*ss)[j], (*ss)[i] }
|
||||
|
|
4
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/state.go
generated
vendored
4
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/state.go
generated
vendored
|
@ -721,7 +721,7 @@ func (s *uintSet) has(i uint) bool {
|
|||
return s.lo.has(i)
|
||||
} else {
|
||||
i -= 64
|
||||
iHi, iLo := int(i/64), uint(i%64)
|
||||
iHi, iLo := int(i/64), i%64
|
||||
return iHi < len(s.hi) && s.hi[iHi].has(iLo)
|
||||
}
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ func (s *uintSet) insert(i uint) bool {
|
|||
return !has
|
||||
} else {
|
||||
i -= 64
|
||||
iHi, iLo := int(i/64), uint(i%64)
|
||||
iHi, iLo := int(i/64), i%64
|
||||
if iHi >= len(s.hi) {
|
||||
s.hi = append(s.hi, make([]uintSet64, iHi+1-len(s.hi))...)
|
||||
s.hi = s.hi[:cap(s.hi)]
|
||||
|
|
10
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/token.go
generated
vendored
10
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/token.go
generated
vendored
|
@ -112,7 +112,7 @@ func Bool(b bool) Token {
|
|||
return False
|
||||
}
|
||||
|
||||
// String construct a Token representing a JSON string.
|
||||
// String constructs a Token representing a JSON string.
|
||||
// The provided string should contain valid UTF-8, otherwise invalid characters
|
||||
// may be mangled as the Unicode replacement character.
|
||||
func String(s string) Token {
|
||||
|
@ -225,7 +225,7 @@ func (t Token) appendString(dst []byte, validateUTF8, preserveRaw bool, escapeRu
|
|||
}
|
||||
|
||||
// String returns the unescaped string value for a JSON string.
|
||||
// For other JSON kinds, this returns the raw JSON represention.
|
||||
// For other JSON kinds, this returns the raw JSON representation.
|
||||
func (t Token) String() string {
|
||||
// This is inlinable to take advantage of "function outlining".
|
||||
// This avoids an allocation for the string(b) conversion
|
||||
|
@ -373,10 +373,10 @@ func (t Token) Int() int64 {
|
|||
case 'i':
|
||||
return int64(t.num)
|
||||
case 'u':
|
||||
if uint64(t.num) > maxInt64 {
|
||||
if t.num > maxInt64 {
|
||||
return maxInt64
|
||||
}
|
||||
return int64(uint64(t.num))
|
||||
return int64(t.num)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ func (t Token) Uint() uint64 {
|
|||
// Handle exact integer value.
|
||||
switch t.str[0] {
|
||||
case 'u':
|
||||
return uint64(t.num)
|
||||
return t.num
|
||||
case 'i':
|
||||
if int64(t.num) < minUint64 {
|
||||
return minUint64
|
||||
|
|
56
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/value.go
generated
vendored
56
vendor/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/value.go
generated
vendored
|
@ -263,7 +263,7 @@ func reorderObjects(d *Decoder, scratch *[]byte) {
|
|||
afterValue := d.InputOffset()
|
||||
|
||||
if isSorted && len(*members) > 0 {
|
||||
isSorted = lessUTF16(prevName, name)
|
||||
isSorted = lessUTF16(prevName, []byte(name))
|
||||
}
|
||||
*members = append(*members, memberName{name, beforeName, afterValue})
|
||||
prevName = name
|
||||
|
@ -317,7 +317,7 @@ func reorderObjects(d *Decoder, scratch *[]byte) {
|
|||
// to the UTF-16 codepoints of the UTF-8 encoded input strings.
|
||||
// This implements the ordering specified in RFC 8785, section 3.2.3.
|
||||
// The inputs must be valid UTF-8, otherwise this may panic.
|
||||
func lessUTF16(x, y []byte) bool {
|
||||
func lessUTF16[Bytes []byte | string](x, y Bytes) bool {
|
||||
// NOTE: This is an optimized, allocation-free implementation
|
||||
// of lessUTF16Simple in fuzz_test.go. FuzzLessUTF16 verifies that the
|
||||
// two implementations agree on the result of comparing any two strings.
|
||||
|
@ -326,8 +326,13 @@ func lessUTF16(x, y []byte) bool {
|
|||
return ('\u0000' <= r && r <= '\uD7FF') || ('\uE000' <= r && r <= '\uFFFF')
|
||||
}
|
||||
|
||||
var invalidUTF8 bool
|
||||
x0, y0 := x, y
|
||||
for {
|
||||
if len(x) == 0 || len(y) == 0 {
|
||||
if len(x) == len(y) && invalidUTF8 {
|
||||
return string(x0) < string(y0)
|
||||
}
|
||||
return len(x) < len(y)
|
||||
}
|
||||
|
||||
|
@ -341,35 +346,36 @@ func lessUTF16(x, y []byte) bool {
|
|||
}
|
||||
|
||||
// Decode next pair of runes as UTF-8.
|
||||
rx, nx := utf8.DecodeRune(x)
|
||||
ry, ny := utf8.DecodeRune(y)
|
||||
// TODO(https://go.dev/issue/56948): Use a generic implementation
|
||||
// of utf8.DecodeRune, or rely on a compiler optimization to statically
|
||||
// hide the cost of a type switch (https://go.dev/issue/57072).
|
||||
var rx, ry rune
|
||||
var nx, ny int
|
||||
switch any(x).(type) {
|
||||
case string:
|
||||
rx, nx = utf8.DecodeRuneInString(string(x))
|
||||
ry, ny = utf8.DecodeRuneInString(string(y))
|
||||
case []byte:
|
||||
rx, nx = utf8.DecodeRune([]byte(x))
|
||||
ry, ny = utf8.DecodeRune([]byte(y))
|
||||
}
|
||||
|
||||
selfx := isUTF16Self(rx)
|
||||
selfy := isUTF16Self(ry)
|
||||
switch {
|
||||
|
||||
// Both runes encode as either a single or surrogate pair
|
||||
// of UTF-16 codepoints.
|
||||
case isUTF16Self(rx) == isUTF16Self(ry):
|
||||
if rx != ry {
|
||||
return rx < ry
|
||||
}
|
||||
|
||||
// The x rune is a single UTF-16 codepoint, while
|
||||
// the y rune is a surrogate pair of UTF-16 codepoints.
|
||||
case isUTF16Self(rx):
|
||||
ry, _ := utf16.EncodeRune(ry)
|
||||
if rx != ry {
|
||||
return rx < ry
|
||||
}
|
||||
panic("BUG: invalid UTF-8") // implies rx is an unpaired surrogate half
|
||||
|
||||
case selfx && !selfy:
|
||||
ry, _ = utf16.EncodeRune(ry)
|
||||
// The y rune is a single UTF-16 codepoint, while
|
||||
// the x rune is a surrogate pair of UTF-16 codepoints.
|
||||
case isUTF16Self(ry):
|
||||
rx, _ := utf16.EncodeRune(rx)
|
||||
if rx != ry {
|
||||
return rx < ry
|
||||
}
|
||||
panic("BUG: invalid UTF-8") // implies ry is an unpaired surrogate half
|
||||
case selfy && !selfx:
|
||||
rx, _ = utf16.EncodeRune(rx)
|
||||
}
|
||||
if rx != ry {
|
||||
return rx < ry
|
||||
}
|
||||
invalidUTF8 = invalidUTF8 || (rx == utf8.RuneError && nx == 1) || (ry == utf8.RuneError && ny == 1)
|
||||
x, y = x[nx:], y[ny:]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package schemaconv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/schema"
|
||||
)
|
||||
|
||||
// ToSchemaFromOpenAPI converts a directory of OpenAPI schemas to an smd Schema.
|
||||
// - models: a map from definition name to OpenAPI V3 structural schema for each definition.
|
||||
// Key in map is used to resolve references in the schema.
|
||||
// - preserveUnknownFields: flag indicating whether unknown fields in all schemas should be preserved.
|
||||
// - returns: nil and an error if there is a parse error, or if schema does not satisfy a
|
||||
// required structural schema invariant for conversion. If no error, returns
|
||||
// a new smd schema.
|
||||
//
|
||||
// Schema should be validated as structural before using with this function, or
|
||||
// there may be information lost.
|
||||
func ToSchemaFromOpenAPI(models map[string]*spec.Schema, preserveUnknownFields bool) (*schema.Schema, error) {
|
||||
c := convert{
|
||||
preserveUnknownFields: preserveUnknownFields,
|
||||
output: &schema.Schema{},
|
||||
}
|
||||
|
||||
for name, spec := range models {
|
||||
// Skip/Ignore top-level references
|
||||
if len(spec.Ref.String()) > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var a schema.Atom
|
||||
|
||||
// Hard-coded schemas for now as proto_models implementation functions.
|
||||
// https://github.com/kubernetes/kube-openapi/issues/364
|
||||
if name == quantityResource {
|
||||
a = schema.Atom{
|
||||
Scalar: untypedDef.Atom.Scalar,
|
||||
}
|
||||
} else if name == rawExtensionResource {
|
||||
a = untypedDef.Atom
|
||||
} else {
|
||||
c2 := c.push(name, &a)
|
||||
c2.visitSpec(spec)
|
||||
c.pop(c2)
|
||||
}
|
||||
|
||||
c.insertTypeDef(name, a)
|
||||
}
|
||||
|
||||
if len(c.errorMessages) > 0 {
|
||||
return nil, errors.New(strings.Join(c.errorMessages, "\n"))
|
||||
}
|
||||
|
||||
c.addCommonTypes()
|
||||
return c.output, nil
|
||||
}
|
||||
|
||||
func (c *convert) visitSpec(m *spec.Schema) {
|
||||
// Check if this schema opts its descendants into preserve-unknown-fields
|
||||
if p, ok := m.Extensions["x-kubernetes-preserve-unknown-fields"]; ok && p == true {
|
||||
c.preserveUnknownFields = true
|
||||
}
|
||||
a := c.top()
|
||||
*a = c.parseSchema(m)
|
||||
}
|
||||
|
||||
func (c *convert) parseSchema(m *spec.Schema) schema.Atom {
|
||||
// k8s-generated OpenAPI specs have historically used only one value for
|
||||
// type and starting with OpenAPIV3 it is only allowed to be
|
||||
// a single string.
|
||||
typ := ""
|
||||
if len(m.Type) > 0 {
|
||||
typ = m.Type[0]
|
||||
}
|
||||
|
||||
// Structural Schemas produced by kubernetes follow very specific rules which
|
||||
// we can use to infer the SMD type:
|
||||
switch typ {
|
||||
case "":
|
||||
// According to Swagger docs:
|
||||
// https://swagger.io/docs/specification/data-models/data-types/#any
|
||||
//
|
||||
// If no type is specified, it is equivalent to accepting any type.
|
||||
return schema.Atom{
|
||||
Scalar: ptr(schema.Scalar("untyped")),
|
||||
List: c.parseList(m),
|
||||
Map: c.parseObject(m),
|
||||
}
|
||||
|
||||
case "object":
|
||||
return schema.Atom{
|
||||
Map: c.parseObject(m),
|
||||
}
|
||||
case "array":
|
||||
return schema.Atom{
|
||||
List: c.parseList(m),
|
||||
}
|
||||
case "integer", "boolean", "number", "string":
|
||||
return convertPrimitive(typ, m.Format)
|
||||
default:
|
||||
c.reportError("unrecognized type: '%v'", typ)
|
||||
return schema.Atom{
|
||||
Scalar: ptr(schema.Scalar("untyped")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) makeOpenAPIRef(specSchema *spec.Schema) schema.TypeRef {
|
||||
refString := specSchema.Ref.String()
|
||||
|
||||
// Special-case handling for $ref stored inside a single-element allOf
|
||||
if len(refString) == 0 && len(specSchema.AllOf) == 1 && len(specSchema.AllOf[0].Ref.String()) > 0 {
|
||||
refString = specSchema.AllOf[0].Ref.String()
|
||||
}
|
||||
|
||||
if _, n := path.Split(refString); len(n) > 0 {
|
||||
//!TODO: Refactor the field ElementRelationship override
|
||||
// we can generate the types with overrides ahead of time rather than
|
||||
// requiring the hacky runtime support
|
||||
// (could just create a normalized key struct containing all customizations
|
||||
// to deduplicate)
|
||||
mapRelationship, err := getMapElementRelationship(specSchema.Extensions)
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
}
|
||||
|
||||
if len(mapRelationship) > 0 {
|
||||
return schema.TypeRef{
|
||||
NamedType: &n,
|
||||
ElementRelationship: &mapRelationship,
|
||||
}
|
||||
}
|
||||
|
||||
return schema.TypeRef{
|
||||
NamedType: &n,
|
||||
}
|
||||
|
||||
}
|
||||
var inlined schema.Atom
|
||||
|
||||
// compute the type inline
|
||||
c2 := c.push("inlined in "+c.currentName, &inlined)
|
||||
c2.preserveUnknownFields = c.preserveUnknownFields
|
||||
c2.visitSpec(specSchema)
|
||||
c.pop(c2)
|
||||
|
||||
return schema.TypeRef{
|
||||
Inlined: inlined,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) parseObject(s *spec.Schema) *schema.Map {
|
||||
var fields []schema.StructField
|
||||
for name, member := range s.Properties {
|
||||
fields = append(fields, schema.StructField{
|
||||
Name: name,
|
||||
Type: c.makeOpenAPIRef(&member),
|
||||
Default: member.Default,
|
||||
})
|
||||
}
|
||||
|
||||
// AdditionalProperties informs the schema of any "unknown" keys
|
||||
// Unknown keys are enforced by the ElementType field.
|
||||
elementType := func() schema.TypeRef {
|
||||
if s.AdditionalProperties == nil {
|
||||
// According to openAPI spec, an object without properties and without
|
||||
// additionalProperties is assumed to be a free-form object.
|
||||
if c.preserveUnknownFields || len(s.Properties) == 0 {
|
||||
return schema.TypeRef{
|
||||
NamedType: &deducedName,
|
||||
}
|
||||
}
|
||||
|
||||
// If properties are specified, do not implicitly allow unknown
|
||||
// fields
|
||||
return schema.TypeRef{}
|
||||
} else if s.AdditionalProperties.Schema != nil {
|
||||
// Unknown fields use the referred schema
|
||||
return c.makeOpenAPIRef(s.AdditionalProperties.Schema)
|
||||
|
||||
} else if s.AdditionalProperties.Allows {
|
||||
// A boolean instead of a schema was provided. Deduce the
|
||||
// type from the value provided at runtime.
|
||||
return schema.TypeRef{
|
||||
NamedType: &deducedName,
|
||||
}
|
||||
} else {
|
||||
// Additional Properties are explicitly disallowed by the user.
|
||||
// Ensure element type is empty.
|
||||
return schema.TypeRef{}
|
||||
}
|
||||
}()
|
||||
|
||||
relationship, err := getMapElementRelationship(s.Extensions)
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
}
|
||||
|
||||
return &schema.Map{
|
||||
Fields: fields,
|
||||
ElementRelationship: relationship,
|
||||
ElementType: elementType,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) parseList(s *spec.Schema) *schema.List {
|
||||
relationship, mapKeys, err := getListElementRelationship(s.Extensions)
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
}
|
||||
elementType := func() schema.TypeRef {
|
||||
if s.Items != nil {
|
||||
if s.Items.Schema == nil || s.Items.Len() != 1 {
|
||||
c.reportError("structural schema arrays must have exactly one member subtype")
|
||||
return schema.TypeRef{
|
||||
NamedType: &deducedName,
|
||||
}
|
||||
}
|
||||
|
||||
subSchema := s.Items.Schema
|
||||
if subSchema == nil {
|
||||
subSchema = &s.Items.Schemas[0]
|
||||
}
|
||||
return c.makeOpenAPIRef(subSchema)
|
||||
} else if len(s.Type) > 0 && len(s.Type[0]) > 0 {
|
||||
c.reportError("`items` must be specified on arrays")
|
||||
}
|
||||
|
||||
// A list with no items specified is treated as "untyped".
|
||||
return schema.TypeRef{
|
||||
NamedType: &untypedName,
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
return &schema.List{
|
||||
ElementRelationship: relationship,
|
||||
Keys: mapKeys,
|
||||
ElementType: elementType,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package schemaconv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/schema"
|
||||
)
|
||||
|
||||
// ToSchema converts openapi definitions into a schema suitable for structured
|
||||
// merge (i.e. kubectl apply v2).
|
||||
func ToSchema(models proto.Models) (*schema.Schema, error) {
|
||||
return ToSchemaWithPreserveUnknownFields(models, false)
|
||||
}
|
||||
|
||||
// ToSchemaWithPreserveUnknownFields converts openapi definitions into a schema suitable for structured
|
||||
// merge (i.e. kubectl apply v2), it will preserve unknown fields if specified.
|
||||
func ToSchemaWithPreserveUnknownFields(models proto.Models, preserveUnknownFields bool) (*schema.Schema, error) {
|
||||
c := convert{
|
||||
preserveUnknownFields: preserveUnknownFields,
|
||||
output: &schema.Schema{},
|
||||
}
|
||||
for _, name := range models.ListModels() {
|
||||
model := models.LookupModel(name)
|
||||
|
||||
var a schema.Atom
|
||||
c2 := c.push(name, &a)
|
||||
model.Accept(c2)
|
||||
c.pop(c2)
|
||||
|
||||
c.insertTypeDef(name, a)
|
||||
}
|
||||
|
||||
if len(c.errorMessages) > 0 {
|
||||
return nil, errors.New(strings.Join(c.errorMessages, "\n"))
|
||||
}
|
||||
|
||||
c.addCommonTypes()
|
||||
return c.output, nil
|
||||
}
|
||||
|
||||
func (c *convert) makeRef(model proto.Schema, preserveUnknownFields bool) schema.TypeRef {
|
||||
var tr schema.TypeRef
|
||||
if r, ok := model.(*proto.Ref); ok {
|
||||
if r.Reference() == "io.k8s.apimachinery.pkg.runtime.RawExtension" {
|
||||
return schema.TypeRef{
|
||||
NamedType: &untypedName,
|
||||
}
|
||||
}
|
||||
// reference a named type
|
||||
_, n := path.Split(r.Reference())
|
||||
tr.NamedType = &n
|
||||
|
||||
mapRelationship, err := getMapElementRelationship(model.GetExtensions())
|
||||
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
}
|
||||
|
||||
// empty string means unset.
|
||||
if len(mapRelationship) > 0 {
|
||||
tr.ElementRelationship = &mapRelationship
|
||||
}
|
||||
} else {
|
||||
// compute the type inline
|
||||
c2 := c.push("inlined in "+c.currentName, &tr.Inlined)
|
||||
c2.preserveUnknownFields = preserveUnknownFields
|
||||
model.Accept(c2)
|
||||
c.pop(c2)
|
||||
|
||||
if tr == (schema.TypeRef{}) {
|
||||
// emit warning?
|
||||
tr.NamedType = &untypedName
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (c *convert) VisitKind(k *proto.Kind) {
|
||||
preserveUnknownFields := c.preserveUnknownFields
|
||||
if p, ok := k.GetExtensions()["x-kubernetes-preserve-unknown-fields"]; ok && p == true {
|
||||
preserveUnknownFields = true
|
||||
}
|
||||
|
||||
a := c.top()
|
||||
a.Map = &schema.Map{}
|
||||
for _, name := range k.FieldOrder {
|
||||
member := k.Fields[name]
|
||||
tr := c.makeRef(member, preserveUnknownFields)
|
||||
a.Map.Fields = append(a.Map.Fields, schema.StructField{
|
||||
Name: name,
|
||||
Type: tr,
|
||||
Default: member.GetDefault(),
|
||||
})
|
||||
}
|
||||
|
||||
unions, err := makeUnions(k.GetExtensions())
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
return
|
||||
}
|
||||
// TODO: We should check that the fields and discriminator
|
||||
// specified in the union are actual fields in the struct.
|
||||
a.Map.Unions = unions
|
||||
|
||||
if preserveUnknownFields {
|
||||
a.Map.ElementType = schema.TypeRef{
|
||||
NamedType: &deducedName,
|
||||
}
|
||||
}
|
||||
|
||||
a.Map.ElementRelationship, err = getMapElementRelationship(k.GetExtensions())
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitArray(a *proto.Array) {
|
||||
relationship, mapKeys, err := getListElementRelationship(a.GetExtensions())
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
}
|
||||
|
||||
atom := c.top()
|
||||
atom.List = &schema.List{
|
||||
ElementType: c.makeRef(a.SubType, c.preserveUnknownFields),
|
||||
ElementRelationship: relationship,
|
||||
Keys: mapKeys,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitMap(m *proto.Map) {
|
||||
relationship, err := getMapElementRelationship(m.GetExtensions())
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
}
|
||||
|
||||
a := c.top()
|
||||
a.Map = &schema.Map{
|
||||
ElementType: c.makeRef(m.SubType, c.preserveUnknownFields),
|
||||
ElementRelationship: relationship,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitPrimitive(p *proto.Primitive) {
|
||||
a := c.top()
|
||||
if c.currentName == quantityResource {
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
} else {
|
||||
*a = convertPrimitive(p.Type, p.Format)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitArbitrary(a *proto.Arbitrary) {
|
||||
*c.top() = deducedDef.Atom
|
||||
}
|
||||
|
||||
func (c *convert) VisitReference(proto.Reference) {
|
||||
// Do nothing, we handle references specially
|
||||
}
|
|
@ -17,43 +17,18 @@ limitations under the License.
|
|||
package schemaconv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
quantityResource = "io.k8s.apimachinery.pkg.api.resource.Quantity"
|
||||
quantityResource = "io.k8s.apimachinery.pkg.api.resource.Quantity"
|
||||
rawExtensionResource = "io.k8s.apimachinery.pkg.runtime.RawExtension"
|
||||
)
|
||||
|
||||
// ToSchema converts openapi definitions into a schema suitable for structured
|
||||
// merge (i.e. kubectl apply v2).
|
||||
func ToSchema(models proto.Models) (*schema.Schema, error) {
|
||||
return ToSchemaWithPreserveUnknownFields(models, false)
|
||||
}
|
||||
|
||||
// ToSchemaWithPreserveUnknownFields converts openapi definitions into a schema suitable for structured
|
||||
// merge (i.e. kubectl apply v2), it will preserve unknown fields if specified.
|
||||
func ToSchemaWithPreserveUnknownFields(models proto.Models, preserveUnknownFields bool) (*schema.Schema, error) {
|
||||
c := convert{
|
||||
input: models,
|
||||
preserveUnknownFields: preserveUnknownFields,
|
||||
output: &schema.Schema{},
|
||||
}
|
||||
if err := c.convertAll(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.addCommonTypes()
|
||||
return c.output, nil
|
||||
}
|
||||
|
||||
type convert struct {
|
||||
input proto.Models
|
||||
preserveUnknownFields bool
|
||||
output *schema.Schema
|
||||
|
||||
|
@ -64,7 +39,6 @@ type convert struct {
|
|||
|
||||
func (c *convert) push(name string, a *schema.Atom) *convert {
|
||||
return &convert{
|
||||
input: c.input,
|
||||
preserveUnknownFields: c.preserveUnknownFields,
|
||||
output: c.output,
|
||||
currentName: name,
|
||||
|
@ -78,30 +52,17 @@ func (c *convert) pop(c2 *convert) {
|
|||
c.errorMessages = append(c.errorMessages, c2.errorMessages...)
|
||||
}
|
||||
|
||||
func (c *convert) convertAll() error {
|
||||
for _, name := range c.input.ListModels() {
|
||||
model := c.input.LookupModel(name)
|
||||
c.insertTypeDef(name, model)
|
||||
}
|
||||
if len(c.errorMessages) > 0 {
|
||||
return errors.New(strings.Join(c.errorMessages, "\n"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *convert) reportError(format string, args ...interface{}) {
|
||||
c.errorMessages = append(c.errorMessages,
|
||||
c.currentName+": "+fmt.Sprintf(format, args...),
|
||||
)
|
||||
}
|
||||
|
||||
func (c *convert) insertTypeDef(name string, model proto.Schema) {
|
||||
func (c *convert) insertTypeDef(name string, atom schema.Atom) {
|
||||
def := schema.TypeDef{
|
||||
Name: name,
|
||||
Atom: atom,
|
||||
}
|
||||
c2 := c.push(name, &def.Atom)
|
||||
model.Accept(c2)
|
||||
c.pop(c2)
|
||||
if def.Atom == (schema.Atom{}) {
|
||||
// This could happen if there were a top-level reference.
|
||||
return
|
||||
|
@ -156,46 +117,6 @@ var deducedDef schema.TypeDef = schema.TypeDef{
|
|||
},
|
||||
}
|
||||
|
||||
func (c *convert) makeRef(model proto.Schema, preserveUnknownFields bool) schema.TypeRef {
|
||||
var tr schema.TypeRef
|
||||
if r, ok := model.(*proto.Ref); ok {
|
||||
if r.Reference() == "io.k8s.apimachinery.pkg.runtime.RawExtension" {
|
||||
return schema.TypeRef{
|
||||
NamedType: &untypedName,
|
||||
}
|
||||
}
|
||||
// reference a named type
|
||||
_, n := path.Split(r.Reference())
|
||||
tr.NamedType = &n
|
||||
|
||||
ext := model.GetExtensions()
|
||||
if val, ok := ext["x-kubernetes-map-type"]; ok {
|
||||
switch val {
|
||||
case "atomic":
|
||||
relationship := schema.Atomic
|
||||
tr.ElementRelationship = &relationship
|
||||
case "granular":
|
||||
relationship := schema.Separable
|
||||
tr.ElementRelationship = &relationship
|
||||
default:
|
||||
c.reportError("unknown map type %v", val)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// compute the type inline
|
||||
c2 := c.push("inlined in "+c.currentName, &tr.Inlined)
|
||||
c2.preserveUnknownFields = preserveUnknownFields
|
||||
model.Accept(c2)
|
||||
c.pop(c2)
|
||||
|
||||
if tr == (schema.TypeRef{}) {
|
||||
// emit warning?
|
||||
tr.NamedType = &untypedName
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func makeUnions(extensions map[string]interface{}) ([]schema.Union, error) {
|
||||
schemaUnions := []schema.Union{}
|
||||
if iunions, ok := extensions["x-kubernetes-unions"]; ok {
|
||||
|
@ -299,52 +220,6 @@ func makeUnion(extensions map[string]interface{}) (schema.Union, error) {
|
|||
return union, nil
|
||||
}
|
||||
|
||||
func (c *convert) VisitKind(k *proto.Kind) {
|
||||
preserveUnknownFields := c.preserveUnknownFields
|
||||
if p, ok := k.GetExtensions()["x-kubernetes-preserve-unknown-fields"]; ok && p == true {
|
||||
preserveUnknownFields = true
|
||||
}
|
||||
|
||||
a := c.top()
|
||||
a.Map = &schema.Map{}
|
||||
for _, name := range k.FieldOrder {
|
||||
member := k.Fields[name]
|
||||
tr := c.makeRef(member, preserveUnknownFields)
|
||||
a.Map.Fields = append(a.Map.Fields, schema.StructField{
|
||||
Name: name,
|
||||
Type: tr,
|
||||
Default: member.GetDefault(),
|
||||
})
|
||||
}
|
||||
|
||||
unions, err := makeUnions(k.GetExtensions())
|
||||
if err != nil {
|
||||
c.reportError(err.Error())
|
||||
return
|
||||
}
|
||||
// TODO: We should check that the fields and discriminator
|
||||
// specified in the union are actual fields in the struct.
|
||||
a.Map.Unions = unions
|
||||
|
||||
if preserveUnknownFields {
|
||||
a.Map.ElementType = schema.TypeRef{
|
||||
NamedType: &deducedName,
|
||||
}
|
||||
}
|
||||
|
||||
ext := k.GetExtensions()
|
||||
if val, ok := ext["x-kubernetes-map-type"]; ok {
|
||||
switch val {
|
||||
case "atomic":
|
||||
a.Map.ElementRelationship = schema.Atomic
|
||||
case "granular":
|
||||
a.Map.ElementRelationship = schema.Separable
|
||||
default:
|
||||
c.reportError("unknown map type %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toStringSlice(o interface{}) (out []string, ok bool) {
|
||||
switch t := o.(type) {
|
||||
case []interface{}:
|
||||
|
@ -355,117 +230,108 @@ func toStringSlice(o interface{}) (out []string, ok bool) {
|
|||
}
|
||||
}
|
||||
return out, true
|
||||
case []string:
|
||||
return t, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (c *convert) VisitArray(a *proto.Array) {
|
||||
atom := c.top()
|
||||
atom.List = &schema.List{
|
||||
ElementRelationship: schema.Atomic,
|
||||
}
|
||||
l := atom.List
|
||||
l.ElementType = c.makeRef(a.SubType, c.preserveUnknownFields)
|
||||
|
||||
ext := a.GetExtensions()
|
||||
|
||||
if val, ok := ext["x-kubernetes-list-type"]; ok {
|
||||
if val == "atomic" {
|
||||
l.ElementRelationship = schema.Atomic
|
||||
} else if val == "set" {
|
||||
l.ElementRelationship = schema.Associative
|
||||
} else if val == "map" {
|
||||
l.ElementRelationship = schema.Associative
|
||||
if keys, ok := ext["x-kubernetes-list-map-keys"]; ok {
|
||||
if keyNames, ok := toStringSlice(keys); ok {
|
||||
l.Keys = keyNames
|
||||
} else {
|
||||
c.reportError("uninterpreted map keys: %#v", keys)
|
||||
}
|
||||
} else {
|
||||
c.reportError("missing map keys")
|
||||
}
|
||||
} else {
|
||||
c.reportError("unknown list type %v", val)
|
||||
l.ElementRelationship = schema.Atomic
|
||||
}
|
||||
} else if val, ok := ext["x-kubernetes-patch-strategy"]; ok {
|
||||
if val == "merge" || val == "merge,retainKeys" {
|
||||
l.ElementRelationship = schema.Associative
|
||||
if key, ok := ext["x-kubernetes-patch-merge-key"]; ok {
|
||||
if keyName, ok := key.(string); ok {
|
||||
l.Keys = []string{keyName}
|
||||
} else {
|
||||
c.reportError("uninterpreted merge key: %#v", key)
|
||||
}
|
||||
} else {
|
||||
// It's not an error for this to be absent, it
|
||||
// means it's a set.
|
||||
}
|
||||
} else if val == "retainKeys" {
|
||||
} else {
|
||||
c.reportError("unknown patch strategy %v", val)
|
||||
l.ElementRelationship = schema.Atomic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitMap(m *proto.Map) {
|
||||
a := c.top()
|
||||
a.Map = &schema.Map{}
|
||||
a.Map.ElementType = c.makeRef(m.SubType, c.preserveUnknownFields)
|
||||
|
||||
ext := m.GetExtensions()
|
||||
if val, ok := ext["x-kubernetes-map-type"]; ok {
|
||||
switch val {
|
||||
case "atomic":
|
||||
a.Map.ElementRelationship = schema.Atomic
|
||||
case "granular":
|
||||
a.Map.ElementRelationship = schema.Separable
|
||||
default:
|
||||
c.reportError("unknown map type %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ptr(s schema.Scalar) *schema.Scalar { return &s }
|
||||
|
||||
func (c *convert) VisitPrimitive(p *proto.Primitive) {
|
||||
a := c.top()
|
||||
if c.currentName == quantityResource {
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
} else {
|
||||
switch p.Type {
|
||||
case proto.Integer:
|
||||
a.Scalar = ptr(schema.Numeric)
|
||||
case proto.Number:
|
||||
a.Scalar = ptr(schema.Numeric)
|
||||
case proto.String:
|
||||
switch p.Format {
|
||||
case "":
|
||||
a.Scalar = ptr(schema.String)
|
||||
case "byte":
|
||||
// byte really means []byte and is encoded as a string.
|
||||
a.Scalar = ptr(schema.String)
|
||||
case "int-or-string":
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
case "date-time":
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
default:
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
}
|
||||
case proto.Boolean:
|
||||
a.Scalar = ptr(schema.Boolean)
|
||||
// Basic conversion functions to convert OpenAPI schema definitions to
|
||||
// SMD Schema atoms
|
||||
func convertPrimitive(typ string, format string) (a schema.Atom) {
|
||||
switch typ {
|
||||
case "integer":
|
||||
a.Scalar = ptr(schema.Numeric)
|
||||
case "number":
|
||||
a.Scalar = ptr(schema.Numeric)
|
||||
case "string":
|
||||
switch format {
|
||||
case "":
|
||||
a.Scalar = ptr(schema.String)
|
||||
case "byte":
|
||||
// byte really means []byte and is encoded as a string.
|
||||
a.Scalar = ptr(schema.String)
|
||||
case "int-or-string":
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
case "date-time":
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
default:
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
}
|
||||
case "boolean":
|
||||
a.Scalar = ptr(schema.Boolean)
|
||||
default:
|
||||
a.Scalar = ptr(schema.Scalar("untyped"))
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func getListElementRelationship(ext map[string]any) (schema.ElementRelationship, []string, error) {
|
||||
if val, ok := ext["x-kubernetes-list-type"]; ok {
|
||||
switch val {
|
||||
case "atomic":
|
||||
return schema.Atomic, nil, nil
|
||||
case "set":
|
||||
return schema.Associative, nil, nil
|
||||
case "map":
|
||||
keys, ok := ext["x-kubernetes-list-map-keys"]
|
||||
|
||||
if !ok {
|
||||
return schema.Associative, nil, fmt.Errorf("missing map keys")
|
||||
}
|
||||
|
||||
keyNames, ok := toStringSlice(keys)
|
||||
if !ok {
|
||||
return schema.Associative, nil, fmt.Errorf("uninterpreted map keys: %#v", keys)
|
||||
}
|
||||
|
||||
return schema.Associative, keyNames, nil
|
||||
default:
|
||||
return schema.Atomic, nil, fmt.Errorf("unknown list type %v", val)
|
||||
}
|
||||
} else if val, ok := ext["x-kubernetes-patch-strategy"]; ok {
|
||||
switch val {
|
||||
case "merge", "merge,retainKeys":
|
||||
if key, ok := ext["x-kubernetes-patch-merge-key"]; ok {
|
||||
keyName, ok := key.(string)
|
||||
|
||||
if !ok {
|
||||
return schema.Associative, nil, fmt.Errorf("uninterpreted merge key: %#v", key)
|
||||
}
|
||||
|
||||
return schema.Associative, []string{keyName}, nil
|
||||
}
|
||||
// It's not an error for x-kubernetes-patch-merge-key to be absent,
|
||||
// it means it's a set
|
||||
return schema.Associative, nil, nil
|
||||
case "retainKeys":
|
||||
return schema.Atomic, nil, nil
|
||||
default:
|
||||
return schema.Atomic, nil, fmt.Errorf("unknown patch strategy %v", val)
|
||||
}
|
||||
}
|
||||
|
||||
// Treat as atomic by default
|
||||
return schema.Atomic, nil, nil
|
||||
}
|
||||
|
||||
// Returns map element relationship if specified, or empty string if unspecified
|
||||
func getMapElementRelationship(ext map[string]any) (schema.ElementRelationship, error) {
|
||||
val, ok := ext["x-kubernetes-map-type"]
|
||||
if !ok {
|
||||
// unset Map element relationship
|
||||
return "", nil
|
||||
}
|
||||
|
||||
switch val {
|
||||
case "atomic":
|
||||
return schema.Atomic, nil
|
||||
case "granular":
|
||||
return schema.Separable, nil
|
||||
default:
|
||||
return "", fmt.Errorf("unknown map type %v", val)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *convert) VisitArbitrary(a *proto.Arbitrary) {
|
||||
*c.top() = deducedDef.Atom
|
||||
}
|
||||
|
||||
func (c *convert) VisitReference(proto.Reference) {
|
||||
// Do nothing, we handle references specially
|
||||
}
|
||||
|
|
|
@ -18,7 +18,10 @@ package spec3
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
|
@ -41,6 +44,9 @@ func (e *Encoding) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (e *Encoding) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
}
|
||||
if err := json.Unmarshal(data, &e.EncodingProps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -50,6 +56,20 @@ func (e *Encoding) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoding) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
EncodingProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
e.EncodingProps = x.EncodingProps
|
||||
return nil
|
||||
}
|
||||
|
||||
type EncodingProps struct {
|
||||
// Content Type for encoding a specific property
|
||||
ContentType string `json:"contentType,omitempty"`
|
||||
|
@ -58,7 +78,7 @@ type EncodingProps struct {
|
|||
// Describes how a specific property value will be serialized depending on its type
|
||||
Style string `json:"style,omitempty"`
|
||||
// When this is true, property values of type array or object generate separate parameters for each value of the array, or key-value-pair of the map. For other types of properties this property has no effect
|
||||
Explode string `json:"explode,omitempty"`
|
||||
Explode bool `json:"explode,omitempty"`
|
||||
// AllowReserved determines whether the parameter value SHOULD allow reserved characters, as defined by RFC3986
|
||||
AllowReserved bool `json:"allowReserved,omitempty"`
|
||||
}
|
||||
|
|
|
@ -19,8 +19,11 @@ package spec3
|
|||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// Example https://swagger.io/specification/#example-object
|
||||
|
@ -49,6 +52,9 @@ func (e *Example) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (e *Example) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
}
|
||||
if err := json.Unmarshal(data, &e.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -61,6 +67,23 @@ func (e *Example) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *Example) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ExampleProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&e.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
e.ExampleProps = x.ExampleProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExampleProps struct {
|
||||
// Summary holds a short description of the example
|
||||
Summary string `json:"summary,omitempty"`
|
||||
|
|
|
@ -18,8 +18,11 @@ package spec3
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
type ExternalDocumentation struct {
|
||||
|
@ -48,6 +51,9 @@ func (e *ExternalDocumentation) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (e *ExternalDocumentation) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, e)
|
||||
}
|
||||
if err := json.Unmarshal(data, &e.ExternalDocumentationProps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -56,3 +62,16 @@ func (e *ExternalDocumentation) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ExternalDocumentation) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ExternalDocumentationProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
e.ExternalDocumentationProps = x.ExternalDocumentationProps
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
package spec3
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// refChance is the chance that a particular component will use a $ref
|
||||
// instead of fuzzed. Expressed as a fraction 1/n, currently there is
|
||||
// a 1/3 chance that a ref will be used.
|
||||
const refChance = 3
|
||||
|
||||
const alphaNumChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
func randAlphanumString() string {
|
||||
arr := make([]string, rand.Intn(10)+5)
|
||||
for i := 0; i < len(arr); i++ {
|
||||
arr[i] = string(alphaNumChars[rand.Intn(len(alphaNumChars))])
|
||||
}
|
||||
return strings.Join(arr, "")
|
||||
}
|
||||
|
||||
var OpenAPIV3FuzzFuncs []interface{} = []interface{}{
|
||||
func(s *string, c fuzz.Continue) {
|
||||
// All OpenAPI V3 map keys must follow the corresponding
|
||||
// regex. Note that this restricts the range for all other
|
||||
// string values as well.
|
||||
str := randAlphanumString()
|
||||
*s = str
|
||||
},
|
||||
func(o *OpenAPI, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(o)
|
||||
o.Version = "3.0.0"
|
||||
},
|
||||
func(r *interface{}, c fuzz.Continue) {
|
||||
switch c.Intn(3) {
|
||||
case 0:
|
||||
*r = nil
|
||||
case 1:
|
||||
n := c.RandString() + "x"
|
||||
*r = n
|
||||
case 2:
|
||||
n := c.Float64()
|
||||
*r = n
|
||||
}
|
||||
},
|
||||
func(v **spec.Info, c fuzz.Continue) {
|
||||
// Info is never nil
|
||||
*v = &spec.Info{}
|
||||
c.FuzzNoCustom(*v)
|
||||
(*v).Title = c.RandString() + "x"
|
||||
},
|
||||
func(v *Paths, c fuzz.Continue) {
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
num := c.Intn(5)
|
||||
if num > 0 {
|
||||
v.Paths = make(map[string]*Path)
|
||||
}
|
||||
for i := 0; i < num; i++ {
|
||||
val := Path{}
|
||||
c.Fuzz(&val)
|
||||
v.Paths["/"+c.RandString()] = &val
|
||||
}
|
||||
},
|
||||
func(v *SecurityScheme, c fuzz.Continue) {
|
||||
if c.Intn(refChance) == 0 {
|
||||
c.Fuzz(&v.Refable)
|
||||
return
|
||||
}
|
||||
switch c.Intn(4) {
|
||||
case 0:
|
||||
v.Type = "apiKey"
|
||||
v.Name = c.RandString() + "x"
|
||||
switch c.Intn(3) {
|
||||
case 0:
|
||||
v.In = "query"
|
||||
case 1:
|
||||
v.In = "header"
|
||||
case 2:
|
||||
v.In = "cookie"
|
||||
}
|
||||
case 1:
|
||||
v.Type = "http"
|
||||
case 2:
|
||||
v.Type = "oauth2"
|
||||
v.Flows = make(map[string]*OAuthFlow)
|
||||
flow := OAuthFlow{}
|
||||
flow.AuthorizationUrl = c.RandString() + "x"
|
||||
v.Flows["implicit"] = &flow
|
||||
flow.Scopes = make(map[string]string)
|
||||
flow.Scopes["foo"] = "bar"
|
||||
case 3:
|
||||
v.Type = "openIdConnect"
|
||||
v.OpenIdConnectUrl = "https://" + c.RandString()
|
||||
}
|
||||
v.Scheme = "basic"
|
||||
},
|
||||
func(v *spec.Ref, c fuzz.Continue) {
|
||||
switch c.Intn(7) {
|
||||
case 0:
|
||||
*v = spec.MustCreateRef("#/components/schemas/" + randAlphanumString())
|
||||
case 1:
|
||||
*v = spec.MustCreateRef("#/components/responses/" + randAlphanumString())
|
||||
case 2:
|
||||
*v = spec.MustCreateRef("#/components/headers/" + randAlphanumString())
|
||||
case 3:
|
||||
*v = spec.MustCreateRef("#/components/securitySchemes/" + randAlphanumString())
|
||||
case 5:
|
||||
*v = spec.MustCreateRef("#/components/parameters/" + randAlphanumString())
|
||||
case 6:
|
||||
*v = spec.MustCreateRef("#/components/requestBodies/" + randAlphanumString())
|
||||
}
|
||||
},
|
||||
func(v *Parameter, c fuzz.Continue) {
|
||||
if c.Intn(refChance) == 0 {
|
||||
c.Fuzz(&v.Refable)
|
||||
return
|
||||
}
|
||||
c.Fuzz(&v.ParameterProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
|
||||
switch c.Intn(3) {
|
||||
case 0:
|
||||
// Header param
|
||||
v.In = "query"
|
||||
case 1:
|
||||
v.In = "header"
|
||||
case 2:
|
||||
v.In = "cookie"
|
||||
}
|
||||
},
|
||||
func(v *RequestBody, c fuzz.Continue) {
|
||||
if c.Intn(refChance) == 0 {
|
||||
c.Fuzz(&v.Refable)
|
||||
return
|
||||
}
|
||||
c.Fuzz(&v.RequestBodyProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
},
|
||||
func(v *Header, c fuzz.Continue) {
|
||||
if c.Intn(refChance) == 0 {
|
||||
c.Fuzz(&v.Refable)
|
||||
return
|
||||
}
|
||||
c.Fuzz(&v.HeaderProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
},
|
||||
func(v *ResponsesProps, c fuzz.Continue) {
|
||||
c.Fuzz(&v.Default)
|
||||
n := c.Intn(5)
|
||||
for i := 0; i < n; i++ {
|
||||
r2 := Response{}
|
||||
c.Fuzz(&r2)
|
||||
// HTTP Status code in 100-599 Range
|
||||
code := c.Intn(500) + 100
|
||||
v.StatusCodeResponses = make(map[int]*Response)
|
||||
v.StatusCodeResponses[code] = &r2
|
||||
}
|
||||
},
|
||||
func(v *Response, c fuzz.Continue) {
|
||||
if c.Intn(refChance) == 0 {
|
||||
c.Fuzz(&v.Refable)
|
||||
return
|
||||
}
|
||||
c.Fuzz(&v.ResponseProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
},
|
||||
func(v *spec.Extensions, c fuzz.Continue) {
|
||||
numChildren := c.Intn(5)
|
||||
for i := 0; i < numChildren; i++ {
|
||||
if *v == nil {
|
||||
*v = spec.Extensions{}
|
||||
}
|
||||
(*v)["x-"+c.RandString()] = c.RandString()
|
||||
}
|
||||
},
|
||||
func(v *spec.ExternalDocumentation, c fuzz.Continue) {
|
||||
c.Fuzz(&v.Description)
|
||||
v.URL = "https://" + randAlphanumString()
|
||||
},
|
||||
func(v *spec.SchemaURL, c fuzz.Continue) {
|
||||
*v = spec.SchemaURL("https://" + randAlphanumString())
|
||||
},
|
||||
func(v *spec.SchemaOrBool, c fuzz.Continue) {
|
||||
*v = spec.SchemaOrBool{}
|
||||
|
||||
if c.RandBool() {
|
||||
v.Allows = c.RandBool()
|
||||
} else {
|
||||
v.Schema = &spec.Schema{}
|
||||
v.Allows = true
|
||||
c.Fuzz(&v.Schema)
|
||||
}
|
||||
},
|
||||
func(v *spec.SchemaOrArray, c fuzz.Continue) {
|
||||
*v = spec.SchemaOrArray{}
|
||||
if c.RandBool() {
|
||||
schema := spec.Schema{}
|
||||
c.Fuzz(&schema)
|
||||
v.Schema = &schema
|
||||
} else {
|
||||
v.Schemas = []spec.Schema{}
|
||||
numChildren := c.Intn(5)
|
||||
for i := 0; i < numChildren; i++ {
|
||||
schema := spec.Schema{}
|
||||
c.Fuzz(&schema)
|
||||
v.Schemas = append(v.Schemas, schema)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
func(v *spec.SchemaOrStringArray, c fuzz.Continue) {
|
||||
if c.RandBool() {
|
||||
*v = spec.SchemaOrStringArray{}
|
||||
if c.RandBool() {
|
||||
c.Fuzz(&v.Property)
|
||||
} else {
|
||||
c.Fuzz(&v.Schema)
|
||||
}
|
||||
}
|
||||
},
|
||||
func(v *spec.Schema, c fuzz.Continue) {
|
||||
if c.Intn(refChance) == 0 {
|
||||
c.Fuzz(&v.Ref)
|
||||
return
|
||||
}
|
||||
if c.RandBool() {
|
||||
// file schema
|
||||
c.Fuzz(&v.Default)
|
||||
c.Fuzz(&v.Description)
|
||||
c.Fuzz(&v.Example)
|
||||
c.Fuzz(&v.ExternalDocs)
|
||||
|
||||
c.Fuzz(&v.Format)
|
||||
c.Fuzz(&v.ReadOnly)
|
||||
c.Fuzz(&v.Required)
|
||||
c.Fuzz(&v.Title)
|
||||
v.Type = spec.StringOrArray{"file"}
|
||||
|
||||
} else {
|
||||
// normal schema
|
||||
c.Fuzz(&v.SchemaProps)
|
||||
c.Fuzz(&v.SwaggerSchemaProps)
|
||||
c.Fuzz(&v.VendorExtensible)
|
||||
c.Fuzz(&v.ExtraProps)
|
||||
}
|
||||
|
||||
},
|
||||
}
|
|
@ -20,6 +20,8 @@ import (
|
|||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
|
@ -50,6 +52,9 @@ func (h *Header) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (h *Header) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, h)
|
||||
}
|
||||
if err := json.Unmarshal(data, &h.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -63,6 +68,22 @@ func (h *Header) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (h *Header) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
HeaderProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&h.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
h.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
h.HeaderProps = x.HeaderProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// HeaderProps a struct that describes a header object
|
||||
type HeaderProps struct {
|
||||
// Description holds a brief description of the parameter
|
||||
|
|
|
@ -18,7 +18,10 @@ package spec3
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
|
@ -44,6 +47,9 @@ func (m *MediaType) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (m *MediaType) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, m)
|
||||
}
|
||||
if err := json.Unmarshal(data, &m.MediaTypeProps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -53,10 +59,24 @@ func (m *MediaType) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *MediaType) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
MediaTypeProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
m.MediaTypeProps = x.MediaTypeProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MediaTypeProps a struct that allows you to specify content format, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#mediaTypeObject
|
||||
type MediaTypeProps struct {
|
||||
// Schema holds the schema defining the type used for the media type
|
||||
Schema *spec.Schema `json:"schema,omitempty"`
|
||||
Schema *spec.Schema `json:"schema,omitempty"`
|
||||
// Example of the media type
|
||||
Example interface{} `json:"example,omitempty"`
|
||||
// Examples of the media type. Each example object should match the media type and specific schema if present
|
||||
|
|
|
@ -19,8 +19,10 @@ package spec3
|
|||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// Operation describes a single API operation on a path, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#operationObject
|
||||
|
@ -46,12 +48,28 @@ func (o *Operation) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
func (o *Operation) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, o)
|
||||
}
|
||||
if err := json.Unmarshal(data, &o.OperationProps); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, &o.VendorExtensible)
|
||||
}
|
||||
|
||||
func (o *Operation) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
OperationProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
o.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
o.OperationProps = x.OperationProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// OperationProps describes a single API operation on a path, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#operationObject
|
||||
type OperationProps struct {
|
||||
// Tags holds a list of tags for API documentation control
|
||||
|
@ -73,7 +91,7 @@ type OperationProps struct {
|
|||
// Deprecated declares this operation to be deprecated
|
||||
Deprecated bool `json:"deprecated,omitempty"`
|
||||
// SecurityRequirement holds a declaration of which security mechanisms can be used for this operation
|
||||
SecurityRequirement []*SecurityRequirement `json:"security,omitempty"`
|
||||
SecurityRequirement []map[string][]string `json:"security,omitempty"`
|
||||
// Servers contains an alternative server array to service this operation
|
||||
Servers []*Server `json:"servers,omitempty"`
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import (
|
|||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
|
@ -50,6 +52,10 @@ func (p *Parameter) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (p *Parameter) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &p.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -63,6 +69,22 @@ func (p *Parameter) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Parameter) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ParameterProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&p.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
p.ParameterProps = x.ParameterProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParameterProps a struct that describes a single operation parameter, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#parameterObject
|
||||
type ParameterProps struct {
|
||||
// Name holds the name of the parameter
|
||||
|
|
|
@ -18,10 +18,13 @@ package spec3
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// Paths describes the available paths and operations for the API, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#pathsObject
|
||||
|
@ -45,6 +48,9 @@ func (p *Paths) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
func (p *Paths) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
}
|
||||
var res map[string]json.RawMessage
|
||||
if err := json.Unmarshal(data, &res); err != nil {
|
||||
return err
|
||||
|
@ -74,6 +80,59 @@ func (p *Paths) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch k := tok.Kind(); k {
|
||||
case 'n':
|
||||
*p = Paths{}
|
||||
return nil
|
||||
case '{':
|
||||
for {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tok.Kind() == '}' {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch k := tok.String(); {
|
||||
case internal.IsExtensionKey(k):
|
||||
var ext any
|
||||
if err := opts.UnmarshalNext(dec, &ext); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Extensions == nil {
|
||||
p.Extensions = make(map[string]any)
|
||||
}
|
||||
p.Extensions[k] = ext
|
||||
case len(k) > 0 && k[0] == '/':
|
||||
pi := Path{}
|
||||
if err := opts.UnmarshalNext(dec, &pi); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Paths == nil {
|
||||
p.Paths = make(map[string]*Path)
|
||||
}
|
||||
p.Paths[k] = &pi
|
||||
default:
|
||||
_, err := dec.ReadValue() // skip value
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown JSON kind: %v", k)
|
||||
}
|
||||
}
|
||||
|
||||
// Path describes the operations available on a single path, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#pathItemObject
|
||||
//
|
||||
// Note that this struct is actually a thin wrapper around PathProps to make it referable and extensible
|
||||
|
@ -101,6 +160,9 @@ func (p *Path) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (p *Path) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, p)
|
||||
}
|
||||
if err := json.Unmarshal(data, &p.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -113,6 +175,24 @@ func (p *Path) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Path) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
PathProps
|
||||
}
|
||||
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&p.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
p.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
p.PathProps = x.PathProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PathProps describes the operations available on a single path, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#pathItemObject
|
||||
type PathProps struct {
|
||||
// Summary holds a summary for all operations in this path
|
||||
|
|
|
@ -19,8 +19,10 @@ package spec3
|
|||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// RequestBody describes a single request body, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#requestBodyObject
|
||||
|
@ -50,6 +52,9 @@ func (r *RequestBody) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (r *RequestBody) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -71,3 +76,19 @@ type RequestBodyProps struct {
|
|||
// Required determines if the request body is required in the request
|
||||
Required bool `json:"required,omitempty"`
|
||||
}
|
||||
|
||||
func (r *RequestBody) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
RequestBodyProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&r.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
r.RequestBodyProps = x.RequestBodyProps
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -18,10 +18,13 @@ package spec3
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// Responses holds the list of possible responses as they are returned from executing this operation
|
||||
|
@ -46,13 +49,15 @@ func (r *Responses) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (r *Responses) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.ResponsesProps); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.VendorExtensible); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -78,25 +83,91 @@ func (r ResponsesProps) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// UnmarshalJSON unmarshals responses from JSON
|
||||
func (r *ResponsesProps) UnmarshalJSON(data []byte) error {
|
||||
var res map[string]*Response
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
var res map[string]json.RawMessage
|
||||
if err := json.Unmarshal(data, &res); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
if v, ok := res["default"]; ok {
|
||||
r.Default = v
|
||||
value := Response{}
|
||||
if err := json.Unmarshal(v, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Default = &value
|
||||
delete(res, "default")
|
||||
}
|
||||
for k, v := range res {
|
||||
// Take all integral keys
|
||||
if nk, err := strconv.Atoi(k); err == nil {
|
||||
if r.StatusCodeResponses == nil {
|
||||
r.StatusCodeResponses = map[int]*Response{}
|
||||
}
|
||||
r.StatusCodeResponses[nk] = v
|
||||
value := Response{}
|
||||
if err := json.Unmarshal(v, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
r.StatusCodeResponses[nk] = &value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) (err error) {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch k := tok.Kind(); k {
|
||||
case 'n':
|
||||
*r = Responses{}
|
||||
return nil
|
||||
case '{':
|
||||
for {
|
||||
tok, err := dec.ReadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tok.Kind() == '}' {
|
||||
return nil
|
||||
}
|
||||
switch k := tok.String(); {
|
||||
case internal.IsExtensionKey(k):
|
||||
var ext any
|
||||
if err := opts.UnmarshalNext(dec, &ext); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Extensions == nil {
|
||||
r.Extensions = make(map[string]any)
|
||||
}
|
||||
r.Extensions[k] = ext
|
||||
case k == "default":
|
||||
resp := Response{}
|
||||
if err := opts.UnmarshalNext(dec, &resp); err != nil {
|
||||
return err
|
||||
}
|
||||
r.ResponsesProps.Default = &resp
|
||||
default:
|
||||
if nk, err := strconv.Atoi(k); err == nil {
|
||||
resp := Response{}
|
||||
if err := opts.UnmarshalNext(dec, &resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.StatusCodeResponses == nil {
|
||||
r.StatusCodeResponses = map[int]*Response{}
|
||||
}
|
||||
r.StatusCodeResponses[nk] = &resp
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown JSON kind: %v", k)
|
||||
}
|
||||
}
|
||||
|
||||
// Response describes a single response from an API Operation, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responseObject
|
||||
//
|
||||
// Note that this struct is actually a thin wrapper around ResponseProps to make it referable and extensible
|
||||
|
@ -124,6 +195,9 @@ func (r *Response) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (r *Response) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -133,7 +207,22 @@ func (r *Response) UnmarshalJSON(data []byte) error {
|
|||
if err := json.Unmarshal(data, &r.VendorExtensible); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Response) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ResponseProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&r.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
r.ResponseProps = x.ResponseProps
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -149,7 +238,6 @@ type ResponseProps struct {
|
|||
Links map[string]*Link `json:"links,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
// Link represents a possible design-time link for a response, more at https://swagger.io/specification/#link-object
|
||||
type Link struct {
|
||||
spec.Refable
|
||||
|
@ -175,6 +263,9 @@ func (r *Link) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (r *Link) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, r)
|
||||
}
|
||||
if err := json.Unmarshal(data, &r.Refable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -188,6 +279,22 @@ func (r *Link) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (l *Link) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
LinkProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.JSONRefFromMap(&l.Ref.Ref, x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
l.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
l.LinkProps = x.LinkProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// LinkProps describes a single response from an API Operation, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responseObject
|
||||
type LinkProps struct {
|
||||
// OperationId is the name of an existing, resolvable OAS operation
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
Copyright 2021 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// SecurityRequirementProps describes the required security schemes to execute an operation, more at https://swagger.io/specification/#security-requirement-object
|
||||
//
|
||||
// Note that this struct is actually a thin wrapper around SecurityRequirementProps to make it referable and extensible
|
||||
type SecurityRequirement struct {
|
||||
SecurityRequirementProps
|
||||
spec.VendorExtensible
|
||||
}
|
||||
|
||||
// MarshalJSON is a custom marshal function that knows how to encode SecurityRequirement as JSON
|
||||
func (s *SecurityRequirement) MarshalJSON() ([]byte, error) {
|
||||
b1, err := json.Marshal(s.SecurityRequirementProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b2, err := json.Marshal(s.VendorExtensible)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON hydrates this items instance with the data from JSON
|
||||
func (s *SecurityRequirement) UnmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, &s.SecurityRequirementProps); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, &s.VendorExtensible)
|
||||
}
|
||||
|
||||
// SecurityRequirementProps describes the required security schemes to execute an operation, more at https://swagger.io/specification/#security-requirement-object
|
||||
type SecurityRequirementProps map[string][]string
|
|
@ -19,8 +19,8 @@ package spec3
|
|||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// SecurityScheme defines reusable Security Scheme Object, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject
|
||||
|
|
|
@ -18,9 +18,11 @@ package spec3
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
|
@ -51,6 +53,10 @@ func (s *Server) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (s *Server) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, s)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &s.ServerProps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -60,6 +66,20 @@ func (s *Server) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ServerProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.ServerProps = x.ServerProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerVariable struct {
|
||||
ServerVariableProps
|
||||
spec.VendorExtensible
|
||||
|
@ -88,6 +108,9 @@ func (s *ServerVariable) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (s *ServerVariable) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, s)
|
||||
}
|
||||
if err := json.Unmarshal(data, &s.ServerVariableProps); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -96,3 +119,17 @@ func (s *ServerVariable) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ServerVariable) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
|
||||
var x struct {
|
||||
spec.Extensions
|
||||
ServerVariableProps
|
||||
}
|
||||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.ServerVariableProps = x.ServerVariableProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@ limitations under the License.
|
|||
package spec3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
|
@ -35,3 +39,12 @@ type OpenAPI struct {
|
|||
// ExternalDocs holds additional external documentation
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
func (o *OpenAPI) UnmarshalJSON(data []byte) error {
|
||||
type OpenAPIWithNoFunctions OpenAPI
|
||||
p := (*OpenAPIWithNoFunctions)(o)
|
||||
if internal.UseOptimizedJSONUnmarshalingV3 {
|
||||
return jsonv2.Unmarshal(data, &p)
|
||||
}
|
||||
return json.Unmarshal(data, &p)
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ func (d *Definitions) ParseSchemaV3(s *openapi_v3.Schema, path *Path) (Schema, e
|
|||
switch s.GetType() {
|
||||
case object:
|
||||
for _, extension := range s.GetSpecificationExtension() {
|
||||
if extension.Name == "x-kuberentes-group-version-kind" {
|
||||
if extension.Name == "x-kubernetes-group-version-kind" {
|
||||
// Objects with x-kubernetes-group-version-kind are always top
|
||||
// level types.
|
||||
return d.parseV3Kind(s, path)
|
||||
|
@ -285,7 +285,7 @@ func parseV3Interface(def *yaml.Node) (interface{}, error) {
|
|||
|
||||
func (d *Definitions) parseV3BaseSchema(s *openapi_v3.Schema, path *Path) (*BaseSchema, error) {
|
||||
if s == nil {
|
||||
return nil, fmt.Errorf("cannot initializae BaseSchema from nil")
|
||||
return nil, fmt.Errorf("cannot initialize BaseSchema from nil")
|
||||
}
|
||||
|
||||
def, err := parseV3Interface(s.GetDefault().ToRawInfo())
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package testing
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
|
@ -42,7 +41,7 @@ func (f *Fake) OpenAPISchema() (*openapi_v2.Document, error) {
|
|||
f.err = err
|
||||
return
|
||||
}
|
||||
spec, err := ioutil.ReadFile(f.Path)
|
||||
spec, err := os.ReadFile(f.Path)
|
||||
if err != nil {
|
||||
f.err = err
|
||||
return
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package testing
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
@ -47,7 +46,7 @@ func (f *FakeV3) OpenAPIV3Schema(groupVersion string) (*openapi_v3.Document, err
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
spec, err := ioutil.ReadFile(filepath.Join(f.Path, groupVersion+".json"))
|
||||
spec, err := os.ReadFile(filepath.Join(f.Path, groupVersion+".json"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
// in GetCanonicalTypeName means Go type names with full package path.
|
||||
//
|
||||
// Examples of REST friendly OpenAPI name:
|
||||
//
|
||||
// Input: k8s.io/api/core/v1.Pod
|
||||
// Output: io.k8s.api.core.v1.Pod
|
||||
//
|
||||
|
@ -45,6 +46,7 @@ func ToCanonicalName(name string) string {
|
|||
// ToRESTFriendlyName converts Golang package/type canonical name into REST friendly OpenAPI name.
|
||||
//
|
||||
// Examples of REST friendly OpenAPI name:
|
||||
//
|
||||
// Input: k8s.io/api/core/v1.Pod
|
||||
// Output: io.k8s.api.core.v1.Pod
|
||||
//
|
||||
|
@ -71,18 +73,21 @@ func ToRESTFriendlyName(name string) string {
|
|||
// OpenAPI canonical names are Go type names with full package path, for uniquely indentifying
|
||||
// a model / Go type. If a Go type is vendored from another package, only the path after "/vendor/"
|
||||
// should be used. For custom resource definition (CRD), the canonical name is expected to be
|
||||
// group/version.kind
|
||||
//
|
||||
// group/version.kind
|
||||
//
|
||||
// Examples of canonical name:
|
||||
// Go type: k8s.io/kubernetes/pkg/apis/core.Pod
|
||||
// CRD: csi.storage.k8s.io/v1alpha1.CSINodeInfo
|
||||
//
|
||||
// Go type: k8s.io/kubernetes/pkg/apis/core.Pod
|
||||
// CRD: csi.storage.k8s.io/v1alpha1.CSINodeInfo
|
||||
//
|
||||
// Example for vendored Go type:
|
||||
// Original full path: k8s.io/kubernetes/vendor/k8s.io/api/core/v1.Pod
|
||||
// Canonical name: k8s.io/api/core/v1.Pod
|
||||
//
|
||||
// Original full path: vendor/k8s.io/api/core/v1.Pod
|
||||
// Canonical name: k8s.io/api/core/v1.Pod
|
||||
// Original full path: k8s.io/kubernetes/vendor/k8s.io/api/core/v1.Pod
|
||||
// Canonical name: k8s.io/api/core/v1.Pod
|
||||
//
|
||||
// Original full path: vendor/k8s.io/api/core/v1.Pod
|
||||
// Canonical name: k8s.io/api/core/v1.Pod
|
||||
type OpenAPICanonicalTypeNamer interface {
|
||||
OpenAPICanonicalTypeName() string
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ type Header struct {
|
|||
|
||||
// MarshalJSON marshal this to JSON
|
||||
func (h Header) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(h)
|
||||
}
|
||||
b1, err := json.Marshal(h.CommonValidations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -62,6 +65,20 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||
return swag.ConcatJSON(b1, b2, b3, b4), nil
|
||||
}
|
||||
|
||||
func (h Header) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
CommonValidations commonValidationsOmitZero `json:",inline"`
|
||||
SimpleSchema simpleSchemaOmitZero `json:",inline"`
|
||||
Extensions
|
||||
HeaderProps
|
||||
}
|
||||
x.CommonValidations = commonValidationsOmitZero(h.CommonValidations)
|
||||
x.SimpleSchema = simpleSchemaOmitZero(h.SimpleSchema)
|
||||
x.Extensions = internal.SanitizeExtensions(h.Extensions)
|
||||
x.HeaderProps = h.HeaderProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this header from JSON
|
||||
func (h *Header) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
|
@ -94,12 +111,8 @@ func (h *Header) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Dec
|
|||
|
||||
h.CommonValidations = x.CommonValidations
|
||||
h.SimpleSchema = x.SimpleSchema
|
||||
h.Extensions = x.Extensions
|
||||
h.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
h.HeaderProps = x.HeaderProps
|
||||
|
||||
h.Extensions.sanitize()
|
||||
if len(h.Extensions) == 0 {
|
||||
h.Extensions = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -89,17 +89,9 @@ func (e Extensions) GetObject(key string, out interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e Extensions) sanitize() {
|
||||
for k := range e {
|
||||
if !isExtensionKey(k) {
|
||||
delete(e, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e Extensions) sanitizeWithExtra() (extra map[string]any) {
|
||||
for k, v := range e {
|
||||
if !isExtensionKey(k) {
|
||||
if !internal.IsExtensionKey(k) {
|
||||
if extra == nil {
|
||||
extra = make(map[string]any)
|
||||
}
|
||||
|
@ -110,10 +102,6 @@ func (e Extensions) sanitizeWithExtra() (extra map[string]any) {
|
|||
return extra
|
||||
}
|
||||
|
||||
func isExtensionKey(k string) bool {
|
||||
return len(k) > 1 && (k[0] == 'x' || k[0] == 'X') && k[1] == '-'
|
||||
}
|
||||
|
||||
// VendorExtensible composition block.
|
||||
type VendorExtensible struct {
|
||||
Extensions Extensions
|
||||
|
@ -181,6 +169,9 @@ type Info struct {
|
|||
|
||||
// MarshalJSON marshal this to JSON
|
||||
func (i Info) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(i)
|
||||
}
|
||||
b1, err := json.Marshal(i.InfoProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -192,6 +183,16 @@ func (i Info) MarshalJSON() ([]byte, error) {
|
|||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (i Info) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Extensions
|
||||
InfoProps
|
||||
}
|
||||
x.Extensions = i.Extensions
|
||||
x.InfoProps = i.InfoProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON marshal this from JSON
|
||||
func (i *Info) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
|
@ -212,11 +213,7 @@ func (i *Info) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decod
|
|||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Extensions.sanitize()
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
i.VendorExtensible.Extensions = x.Extensions
|
||||
i.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
i.InfoProps = x.InfoProps
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -37,6 +37,18 @@ type SimpleSchema struct {
|
|||
Example interface{} `json:"example,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type simpleSchemaOmitZero struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Nullable bool `json:"nullable,omitzero"`
|
||||
Format string `json:"format,omitempty"`
|
||||
Items *Items `json:"items,omitzero"`
|
||||
CollectionFormat string `json:"collectionFormat,omitempty"`
|
||||
Default interface{} `json:"default,omitempty"`
|
||||
Example interface{} `json:"example,omitempty"`
|
||||
}
|
||||
|
||||
// CommonValidations describe common JSON-schema validations
|
||||
type CommonValidations struct {
|
||||
Maximum *float64 `json:"maximum,omitempty"`
|
||||
|
@ -53,6 +65,23 @@ type CommonValidations struct {
|
|||
Enum []interface{} `json:"enum,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type commonValidationsOmitZero struct {
|
||||
Maximum *float64 `json:"maximum,omitempty"`
|
||||
ExclusiveMaximum bool `json:"exclusiveMaximum,omitzero"`
|
||||
Minimum *float64 `json:"minimum,omitempty"`
|
||||
ExclusiveMinimum bool `json:"exclusiveMinimum,omitzero"`
|
||||
MaxLength *int64 `json:"maxLength,omitempty"`
|
||||
MinLength *int64 `json:"minLength,omitempty"`
|
||||
Pattern string `json:"pattern,omitempty"`
|
||||
MaxItems *int64 `json:"maxItems,omitempty"`
|
||||
MinItems *int64 `json:"minItems,omitempty"`
|
||||
UniqueItems bool `json:"uniqueItems,omitzero"`
|
||||
MultipleOf *float64 `json:"multipleOf,omitempty"`
|
||||
Enum []interface{} `json:"enum,omitempty"`
|
||||
}
|
||||
|
||||
// Items a limited subset of JSON-Schema's items object.
|
||||
// It is used by parameter definitions that are not located in "body".
|
||||
//
|
||||
|
@ -105,18 +134,18 @@ func (i *Items) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco
|
|||
if err := i.Refable.Ref.fromMap(x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Extensions.sanitize()
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
|
||||
i.CommonValidations = x.CommonValidations
|
||||
i.SimpleSchema = x.SimpleSchema
|
||||
i.VendorExtensible.Extensions = x.Extensions
|
||||
i.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON converts this items object to JSON
|
||||
func (i Items) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(i)
|
||||
}
|
||||
b1, err := json.Marshal(i.CommonValidations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -135,3 +164,17 @@ func (i Items) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
return swag.ConcatJSON(b4, b3, b1, b2), nil
|
||||
}
|
||||
|
||||
func (i Items) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
CommonValidations commonValidationsOmitZero `json:",inline"`
|
||||
SimpleSchema simpleSchemaOmitZero `json:",inline"`
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
Extensions
|
||||
}
|
||||
x.CommonValidations = commonValidationsOmitZero(i.CommonValidations)
|
||||
x.SimpleSchema = simpleSchemaOmitZero(i.SimpleSchema)
|
||||
x.Ref = i.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(i.Extensions)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
|
|
@ -42,6 +42,23 @@ type OperationProps struct {
|
|||
Responses *Responses `json:"responses,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type operationPropsOmitZero struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
Consumes []string `json:"consumes,omitempty"`
|
||||
Produces []string `json:"produces,omitempty"`
|
||||
Schemes []string `json:"schemes,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Summary string `json:"summary,omitempty"`
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitzero"`
|
||||
ID string `json:"operationId,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty,omitzero"`
|
||||
Security []map[string][]string `json:"security,omitempty"`
|
||||
Parameters []Parameter `json:"parameters,omitempty"`
|
||||
Responses *Responses `json:"responses,omitzero"`
|
||||
}
|
||||
|
||||
// MarshalJSON takes care of serializing operation properties to JSON
|
||||
//
|
||||
// We use a custom marhaller here to handle a special cases related to
|
||||
|
@ -96,17 +113,16 @@ func (o *Operation) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.
|
|||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Extensions.sanitize()
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
o.VendorExtensible.Extensions = x.Extensions
|
||||
o.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
o.OperationProps = OperationProps(x.OperationPropsNoMethods)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON converts this items object to JSON
|
||||
func (o Operation) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(o)
|
||||
}
|
||||
b1, err := json.Marshal(o.OperationProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -118,3 +134,13 @@ func (o Operation) MarshalJSON() ([]byte, error) {
|
|||
concated := swag.ConcatJSON(b1, b2)
|
||||
return concated, nil
|
||||
}
|
||||
|
||||
func (o Operation) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Extensions
|
||||
OperationProps operationPropsOmitZero `json:",inline"`
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(o.Extensions)
|
||||
x.OperationProps = operationPropsOmitZero(o.OperationProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,17 @@ type ParamProps struct {
|
|||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type paramPropsOmitZero struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
In string `json:"in,omitempty"`
|
||||
Required bool `json:"required,omitzero"`
|
||||
Schema *Schema `json:"schema,omitzero"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitzero"`
|
||||
}
|
||||
|
||||
// Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn).
|
||||
//
|
||||
// There are five possible parameter types.
|
||||
|
@ -109,19 +120,18 @@ func (p *Parameter) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.
|
|||
if err := p.Refable.Ref.fromMap(x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Extensions.sanitize()
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
p.CommonValidations = x.CommonValidations
|
||||
p.SimpleSchema = x.SimpleSchema
|
||||
p.VendorExtensible.Extensions = x.Extensions
|
||||
p.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
p.ParamProps = x.ParamProps
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON converts this items object to JSON
|
||||
func (p Parameter) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(p)
|
||||
}
|
||||
b1, err := json.Marshal(p.CommonValidations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -144,3 +154,19 @@ func (p Parameter) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
return swag.ConcatJSON(b3, b1, b2, b4, b5), nil
|
||||
}
|
||||
|
||||
func (p Parameter) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
CommonValidations commonValidationsOmitZero `json:",inline"`
|
||||
SimpleSchema simpleSchemaOmitZero `json:",inline"`
|
||||
ParamProps paramPropsOmitZero `json:",inline"`
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
Extensions
|
||||
}
|
||||
x.CommonValidations = commonValidationsOmitZero(p.CommonValidations)
|
||||
x.SimpleSchema = simpleSchemaOmitZero(p.SimpleSchema)
|
||||
x.Extensions = internal.SanitizeExtensions(p.Extensions)
|
||||
x.ParamProps = paramPropsOmitZero(p.ParamProps)
|
||||
x.Ref = p.Refable.Ref.String()
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
|
|
@ -70,24 +70,20 @@ func (p *PathItem) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.D
|
|||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Extensions = x.Extensions
|
||||
p.PathItemProps = x.PathItemProps
|
||||
|
||||
if err := p.Refable.Ref.fromMap(p.Extensions); err != nil {
|
||||
if err := p.Refable.Ref.fromMap(x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Extensions.sanitize()
|
||||
if len(p.Extensions) == 0 {
|
||||
p.Extensions = nil
|
||||
}
|
||||
p.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
p.PathItemProps = x.PathItemProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON converts this items object to JSON
|
||||
func (p PathItem) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(p)
|
||||
}
|
||||
b3, err := json.Marshal(p.Refable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -103,3 +99,15 @@ func (p PathItem) MarshalJSON() ([]byte, error) {
|
|||
concated := swag.ConcatJSON(b3, b4, b5)
|
||||
return concated, nil
|
||||
}
|
||||
|
||||
func (p PathItem) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
Extensions
|
||||
PathItemProps
|
||||
}
|
||||
x.Ref = p.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(p.Extensions)
|
||||
x.PathItemProps = p.PathItemProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco
|
|||
}
|
||||
|
||||
switch k := tok.String(); {
|
||||
case isExtensionKey(k):
|
||||
case internal.IsExtensionKey(k):
|
||||
ext = nil
|
||||
if err := opts.UnmarshalNext(dec, &ext); err != nil {
|
||||
return err
|
||||
|
@ -114,7 +114,9 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco
|
|||
p.Paths[k] = pi
|
||||
default:
|
||||
_, err := dec.ReadValue() // skip value
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@ -124,6 +126,9 @@ func (p *Paths) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Deco
|
|||
|
||||
// MarshalJSON converts this items object to JSON
|
||||
func (p Paths) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(p)
|
||||
}
|
||||
b1, err := json.Marshal(p.VendorExtensible)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -142,3 +147,18 @@ func (p Paths) MarshalJSON() ([]byte, error) {
|
|||
concated := swag.ConcatJSON(b1, b2)
|
||||
return concated, nil
|
||||
}
|
||||
|
||||
func (p Paths) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
m := make(map[string]any, len(p.Extensions)+len(p.Paths))
|
||||
for k, v := range p.Extensions {
|
||||
if internal.IsExtensionKey(k) {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
for k, v := range p.Paths {
|
||||
if strings.HasPrefix(k, "/") {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
return opts.MarshalNext(enc, m)
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/go-openapi/jsonreference"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
)
|
||||
|
||||
// Refable is a struct for things that accept a $ref property
|
||||
|
@ -149,19 +151,5 @@ func (r *Ref) UnmarshalJSON(d []byte) error {
|
|||
}
|
||||
|
||||
func (r *Ref) fromMap(v map[string]interface{}) error {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if vv, ok := v["$ref"]; ok {
|
||||
if str, ok := vv.(string); ok {
|
||||
ref, err := jsonreference.New(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*r = Ref{Ref: ref}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return internal.JSONRefFromMap(&r.Ref, v)
|
||||
}
|
||||
|
|
|
@ -30,6 +30,15 @@ type ResponseProps struct {
|
|||
Examples map[string]interface{} `json:"examples,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type responsePropsOmitZero struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
Schema *Schema `json:"schema,omitzero"`
|
||||
Headers map[string]Header `json:"headers,omitempty"`
|
||||
Examples map[string]interface{} `json:"examples,omitempty"`
|
||||
}
|
||||
|
||||
// Response describes a single response from an API Operation.
|
||||
//
|
||||
// For more information: http://goo.gl/8us55a#responseObject
|
||||
|
@ -68,23 +77,20 @@ func (r *Response) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.D
|
|||
return err
|
||||
}
|
||||
|
||||
r.Extensions = x.Extensions
|
||||
r.ResponseProps = x.ResponseProps
|
||||
|
||||
if err := r.Refable.Ref.fromMap(r.Extensions); err != nil {
|
||||
if err := r.Refable.Ref.fromMap(x.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Extensions.sanitize()
|
||||
if len(r.Extensions) == 0 {
|
||||
r.Extensions = nil
|
||||
}
|
||||
r.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
r.ResponseProps = x.ResponseProps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON converts this items object to JSON
|
||||
func (r Response) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(r)
|
||||
}
|
||||
b1, err := json.Marshal(r.ResponseProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -100,6 +106,18 @@ func (r Response) MarshalJSON() ([]byte, error) {
|
|||
return swag.ConcatJSON(b1, b2, b3), nil
|
||||
}
|
||||
|
||||
func (r Response) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
Extensions
|
||||
ResponseProps responsePropsOmitZero `json:",inline"`
|
||||
}
|
||||
x.Ref = r.Refable.Ref.String()
|
||||
x.Extensions = internal.SanitizeExtensions(r.Extensions)
|
||||
x.ResponseProps = responsePropsOmitZero(r.ResponseProps)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// NewResponse creates a new response instance
|
||||
func NewResponse() *Response {
|
||||
return new(Response)
|
||||
|
|
|
@ -63,6 +63,9 @@ func (r *Responses) UnmarshalJSON(data []byte) error {
|
|||
|
||||
// MarshalJSON converts this items object to JSON
|
||||
func (r Responses) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(r)
|
||||
}
|
||||
b1, err := json.Marshal(r.ResponsesProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -75,6 +78,25 @@ func (r Responses) MarshalJSON() ([]byte, error) {
|
|||
return concated, nil
|
||||
}
|
||||
|
||||
func (r Responses) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
type ArbitraryKeys map[string]interface{}
|
||||
var x struct {
|
||||
ArbitraryKeys
|
||||
Default *Response `json:"default,omitempty"`
|
||||
}
|
||||
x.ArbitraryKeys = make(map[string]any, len(r.Extensions)+len(r.StatusCodeResponses))
|
||||
for k, v := range r.Extensions {
|
||||
if internal.IsExtensionKey(k) {
|
||||
x.ArbitraryKeys[k] = v
|
||||
}
|
||||
}
|
||||
for k, v := range r.StatusCodeResponses {
|
||||
x.ArbitraryKeys[strconv.Itoa(k)] = v
|
||||
}
|
||||
x.Default = r.Default
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// ResponsesProps describes all responses for an operation.
|
||||
// It tells what is the default response and maps all responses with a
|
||||
// HTTP status code.
|
||||
|
@ -148,7 +170,7 @@ func (r *Responses) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.
|
|||
return nil
|
||||
}
|
||||
switch k := tok.String(); {
|
||||
case isExtensionKey(k):
|
||||
case internal.IsExtensionKey(k):
|
||||
ext = nil
|
||||
if err := opts.UnmarshalNext(dec, &ext); err != nil {
|
||||
return err
|
||||
|
|
|
@ -196,6 +196,46 @@ type SchemaProps struct {
|
|||
Definitions Definitions `json:"definitions,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type schemaPropsOmitZero struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Ref Ref `json:"-"`
|
||||
Schema SchemaURL `json:"-"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Type StringOrArray `json:"type,omitzero"`
|
||||
Nullable bool `json:"nullable,omitzero"`
|
||||
Format string `json:"format,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Default interface{} `json:"default,omitzero"`
|
||||
Maximum *float64 `json:"maximum,omitempty"`
|
||||
ExclusiveMaximum bool `json:"exclusiveMaximum,omitzero"`
|
||||
Minimum *float64 `json:"minimum,omitempty"`
|
||||
ExclusiveMinimum bool `json:"exclusiveMinimum,omitzero"`
|
||||
MaxLength *int64 `json:"maxLength,omitempty"`
|
||||
MinLength *int64 `json:"minLength,omitempty"`
|
||||
Pattern string `json:"pattern,omitempty"`
|
||||
MaxItems *int64 `json:"maxItems,omitempty"`
|
||||
MinItems *int64 `json:"minItems,omitempty"`
|
||||
UniqueItems bool `json:"uniqueItems,omitzero"`
|
||||
MultipleOf *float64 `json:"multipleOf,omitempty"`
|
||||
Enum []interface{} `json:"enum,omitempty"`
|
||||
MaxProperties *int64 `json:"maxProperties,omitempty"`
|
||||
MinProperties *int64 `json:"minProperties,omitempty"`
|
||||
Required []string `json:"required,omitempty"`
|
||||
Items *SchemaOrArray `json:"items,omitzero"`
|
||||
AllOf []Schema `json:"allOf,omitempty"`
|
||||
OneOf []Schema `json:"oneOf,omitempty"`
|
||||
AnyOf []Schema `json:"anyOf,omitempty"`
|
||||
Not *Schema `json:"not,omitzero"`
|
||||
Properties map[string]Schema `json:"properties,omitempty"`
|
||||
AdditionalProperties *SchemaOrBool `json:"additionalProperties,omitzero"`
|
||||
PatternProperties map[string]Schema `json:"patternProperties,omitempty"`
|
||||
Dependencies Dependencies `json:"dependencies,omitempty"`
|
||||
AdditionalItems *SchemaOrBool `json:"additionalItems,omitzero"`
|
||||
Definitions Definitions `json:"definitions,omitempty"`
|
||||
}
|
||||
|
||||
// SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4)
|
||||
type SwaggerSchemaProps struct {
|
||||
Discriminator string `json:"discriminator,omitempty"`
|
||||
|
@ -204,6 +244,15 @@ type SwaggerSchemaProps struct {
|
|||
Example interface{} `json:"example,omitempty"`
|
||||
}
|
||||
|
||||
// Marshaling structure only, always edit along with corresponding
|
||||
// struct (or compilation will fail).
|
||||
type swaggerSchemaPropsOmitZero struct {
|
||||
Discriminator string `json:"discriminator,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitzero"`
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitzero"`
|
||||
Example interface{} `json:"example,omitempty"`
|
||||
}
|
||||
|
||||
// Schema 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 based on the [JSON Schema Specification Draft 4](http://json-schema.org/)
|
||||
|
@ -434,6 +483,9 @@ func (s *Schema) WithExternalDocs(description, url string) *Schema {
|
|||
|
||||
// MarshalJSON marshal this to JSON
|
||||
func (s Schema) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
b1, err := json.Marshal(s.SchemaProps)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("schema props %v", err)
|
||||
|
@ -465,6 +517,31 @@ func (s Schema) MarshalJSON() ([]byte, error) {
|
|||
return swag.ConcatJSON(b1, b2, b3, b4, b5, b6), nil
|
||||
}
|
||||
|
||||
func (s Schema) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
type ArbitraryKeys map[string]interface{}
|
||||
var x struct {
|
||||
ArbitraryKeys
|
||||
SchemaProps schemaPropsOmitZero `json:",inline"`
|
||||
SwaggerSchemaProps swaggerSchemaPropsOmitZero `json:",inline"`
|
||||
Schema string `json:"$schema,omitempty"`
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
}
|
||||
x.ArbitraryKeys = make(map[string]any, len(s.Extensions)+len(s.ExtraProps))
|
||||
for k, v := range s.Extensions {
|
||||
if internal.IsExtensionKey(k) {
|
||||
x.ArbitraryKeys[k] = v
|
||||
}
|
||||
}
|
||||
for k, v := range s.ExtraProps {
|
||||
x.ArbitraryKeys[k] = v
|
||||
}
|
||||
x.SchemaProps = schemaPropsOmitZero(s.SchemaProps)
|
||||
x.SwaggerSchemaProps = swaggerSchemaPropsOmitZero(s.SwaggerSchemaProps)
|
||||
x.Ref = s.Ref.String()
|
||||
x.Schema = string(s.Schema)
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON marshal this from JSON
|
||||
func (s *Schema) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
|
@ -547,7 +624,7 @@ func (s *Schema) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Dec
|
|||
}
|
||||
|
||||
s.ExtraProps = x.Extensions.sanitizeWithExtra()
|
||||
s.VendorExtensible.Extensions = x.Extensions
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.SchemaProps = x.SchemaProps
|
||||
s.SwaggerSchemaProps = x.SwaggerSchemaProps
|
||||
return nil
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"encoding/json"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"k8s.io/kube-openapi/pkg/internal"
|
||||
jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
|
||||
)
|
||||
|
||||
|
@ -45,6 +46,9 @@ type SecurityScheme struct {
|
|||
|
||||
// MarshalJSON marshal this to JSON
|
||||
func (s SecurityScheme) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
b1, err := json.Marshal(s.SecuritySchemeProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -56,6 +60,16 @@ func (s SecurityScheme) MarshalJSON() ([]byte, error) {
|
|||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (s SecurityScheme) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Extensions
|
||||
SecuritySchemeProps
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(s.Extensions)
|
||||
x.SecuritySchemeProps = s.SecuritySchemeProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON marshal this from JSON
|
||||
func (s *SecurityScheme) UnmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, &s.SecuritySchemeProps); err != nil {
|
||||
|
@ -72,11 +86,7 @@ func (s *SecurityScheme) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *js
|
|||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Extensions.sanitize()
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
s.VendorExtensible.Extensions = x.Extensions
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.SecuritySchemeProps = x.SecuritySchemeProps
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ type Swagger struct {
|
|||
|
||||
// MarshalJSON marshals this swagger structure to json
|
||||
func (s Swagger) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
b1, err := json.Marshal(s.SwaggerProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -46,12 +49,22 @@ func (s Swagger) MarshalJSON() ([]byte, error) {
|
|||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this swagger structure to json
|
||||
func (s Swagger) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Extensions
|
||||
SwaggerProps
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(s.Extensions)
|
||||
x.SwaggerProps = s.SwaggerProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals a swagger spec from json
|
||||
func (s *Swagger) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
return jsonv2.Unmarshal(data, s)
|
||||
}
|
||||
|
||||
var sw Swagger
|
||||
if err := json.Unmarshal(data, &sw.SwaggerProps); err != nil {
|
||||
return err
|
||||
|
@ -75,15 +88,8 @@ func (s *Swagger) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.De
|
|||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Extensions = x.Extensions
|
||||
s.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
s.SwaggerProps = x.SwaggerProps
|
||||
|
||||
s.Extensions.sanitize()
|
||||
if len(s.Extensions) == 0 {
|
||||
s.Extensions = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -126,6 +132,9 @@ var jsFalse = []byte("false")
|
|||
|
||||
// MarshalJSON convert this object to JSON
|
||||
func (s SchemaOrBool) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
if s.Schema != nil {
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
|
@ -136,6 +145,18 @@ func (s SchemaOrBool) MarshalJSON() ([]byte, error) {
|
|||
return jsTrue, nil
|
||||
}
|
||||
|
||||
// MarshalJSON convert this object to JSON
|
||||
func (s SchemaOrBool) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
if s.Schema != nil {
|
||||
return opts.MarshalNext(enc, s.Schema)
|
||||
}
|
||||
|
||||
if s.Schema == nil && !s.Allows {
|
||||
return enc.WriteToken(jsonv2.False)
|
||||
}
|
||||
return enc.WriteToken(jsonv2.True)
|
||||
}
|
||||
|
||||
// UnmarshalJSON converts this bool or schema object from a JSON structure
|
||||
func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
|
@ -143,15 +164,15 @@ func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
|
||||
var nw SchemaOrBool
|
||||
if len(data) >= 4 {
|
||||
if data[0] == '{' {
|
||||
var sch Schema
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Schema = &sch
|
||||
if len(data) > 0 && data[0] == '{' {
|
||||
var sch Schema
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Allows = !(data[0] == 'f' && data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e')
|
||||
nw.Schema = &sch
|
||||
nw.Allows = true
|
||||
} else {
|
||||
json.Unmarshal(data, &nw.Allows)
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
|
@ -185,6 +206,9 @@ type SchemaOrStringArray struct {
|
|||
|
||||
// MarshalJSON converts this schema object or array into JSON structure
|
||||
func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
if len(s.Property) > 0 {
|
||||
return json.Marshal(s.Property)
|
||||
}
|
||||
|
@ -194,6 +218,17 @@ func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) {
|
|||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
// MarshalJSON converts this schema object or array into JSON structure
|
||||
func (s SchemaOrStringArray) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
if len(s.Property) > 0 {
|
||||
return opts.MarshalNext(enc, s.Property)
|
||||
}
|
||||
if s.Schema != nil {
|
||||
return opts.MarshalNext(enc, s.Schema)
|
||||
}
|
||||
return enc.WriteToken(jsonv2.Null)
|
||||
}
|
||||
|
||||
// UnmarshalJSON converts this schema object or array from a JSON structure
|
||||
func (s *SchemaOrStringArray) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
|
@ -347,12 +382,23 @@ func (s *SchemaOrArray) ContainsType(name string) bool {
|
|||
|
||||
// MarshalJSON converts this schema object or array into JSON structure
|
||||
func (s SchemaOrArray) MarshalJSON() ([]byte, error) {
|
||||
if len(s.Schemas) > 0 {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(s)
|
||||
}
|
||||
if s.Schemas != nil {
|
||||
return json.Marshal(s.Schemas)
|
||||
}
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
|
||||
// MarshalJSON converts this schema object or array into JSON structure
|
||||
func (s SchemaOrArray) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
if s.Schemas != nil {
|
||||
return opts.MarshalNext(enc, s.Schemas)
|
||||
}
|
||||
return opts.MarshalNext(enc, s.Schema)
|
||||
}
|
||||
|
||||
// UnmarshalJSON converts this schema object or array from a JSON structure
|
||||
func (s *SchemaOrArray) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
|
|
|
@ -41,6 +41,9 @@ type Tag struct {
|
|||
|
||||
// MarshalJSON marshal this to JSON
|
||||
func (t Tag) MarshalJSON() ([]byte, error) {
|
||||
if internal.UseOptimizedJSONMarshaling {
|
||||
return internal.DeterministicMarshal(t)
|
||||
}
|
||||
b1, err := json.Marshal(t.TagProps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -52,6 +55,16 @@ func (t Tag) MarshalJSON() ([]byte, error) {
|
|||
return swag.ConcatJSON(b1, b2), nil
|
||||
}
|
||||
|
||||
func (t Tag) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
|
||||
var x struct {
|
||||
Extensions
|
||||
TagProps
|
||||
}
|
||||
x.Extensions = internal.SanitizeExtensions(t.Extensions)
|
||||
x.TagProps = t.TagProps
|
||||
return opts.MarshalNext(enc, x)
|
||||
}
|
||||
|
||||
// UnmarshalJSON marshal this from JSON
|
||||
func (t *Tag) UnmarshalJSON(data []byte) error {
|
||||
if internal.UseOptimizedJSONUnmarshaling {
|
||||
|
@ -72,11 +85,7 @@ func (t *Tag) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decode
|
|||
if err := opts.UnmarshalNext(dec, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
x.Extensions.sanitize()
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
t.VendorExtensible.Extensions = x.Extensions
|
||||
t.Extensions = internal.SanitizeExtensions(x.Extensions)
|
||||
t.TagProps = x.TagProps
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package custom_metrics
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
)
|
||||
|
||||
func Convert_v1_ObjectReference_To_custom_metrics_ObjectReference(in *v1.ObjectReference, out *ObjectReference, s conversion.Scope) error {
|
||||
out.APIVersion = in.APIVersion
|
||||
|
||||
out.Kind = in.Kind
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
out.UID = in.UID
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
out.FieldPath = in.FieldPath
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_custom_metrics_ObjectReference_To_v1_ObjectReference(in *ObjectReference, out *v1.ObjectReference, s conversion.Scope) error {
|
||||
out.APIVersion = in.APIVersion
|
||||
|
||||
out.Kind = in.Kind
|
||||
out.Namespace = in.Namespace
|
||||
out.Name = in.Name
|
||||
out.UID = in.UID
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
out.FieldPath = in.FieldPath
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +groupName=custom.metrics.k8s.io
|
||||
|
||||
// Package custom_metrics defines an API for using custom metrics.
|
||||
package custom_metrics // import "k8s.io/metrics/pkg/apis/custom_metrics"
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package install installs the experimental API group, making it available as
|
||||
// an option to all of the API encoding/decoding machinery.
|
||||
package install
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/metrics/pkg/apis/custom_metrics"
|
||||
"k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
|
||||
"k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
|
||||
)
|
||||
|
||||
// Install registers the API group and adds types to a scheme
|
||||
func Install(scheme *runtime.Scheme) {
|
||||
utilruntime.Must(custom_metrics.AddToScheme(scheme))
|
||||
utilruntime.Must(v1beta2.AddToScheme(scheme))
|
||||
utilruntime.Must(v1beta1.AddToScheme(scheme))
|
||||
utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1beta2.SchemeGroupVersion))
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package custom_metrics
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "custom.metrics.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&MetricValue{},
|
||||
&MetricValueList{},
|
||||
&MetricListOptions{},
|
||||
)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package custom_metrics
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
type MetricIdentifier struct {
|
||||
// name is the name of the given metric
|
||||
Name string
|
||||
// selector represents the label selector that could be used to select
|
||||
// this metric, and will generally just be the selector passed in to
|
||||
// the query used to fetch this metric.
|
||||
// +optional
|
||||
Selector *metav1.LabelSelector
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// a list of values for a given metric for some set of objects
|
||||
type MetricValueList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
// the value of the metric across the described objects
|
||||
Items []MetricValue `json:"items"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// a metric value for some object
|
||||
type MetricValue struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
// a reference to the described object
|
||||
DescribedObject ObjectReference
|
||||
|
||||
Metric MetricIdentifier
|
||||
|
||||
// indicates the time at which the metrics were produced
|
||||
Timestamp metav1.Time
|
||||
|
||||
// indicates the window ([Timestamp-Window, Timestamp]) from
|
||||
// which these metrics were calculated, when returning rate
|
||||
// metrics calculated from cumulative metrics (or zero for
|
||||
// non-calculated instantaneous metrics).
|
||||
WindowSeconds *int64
|
||||
|
||||
// the value of the metric for this
|
||||
Value resource.Quantity
|
||||
}
|
||||
|
||||
// allObjects is a wildcard used to select metrics
|
||||
// for all objects matching the given label selector
|
||||
const AllObjects = "*"
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MetricListOptions is used to select metrics by their label selectors
|
||||
type MetricListOptions struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
// A selector to restrict the list of returned objects by their labels.
|
||||
// Defaults to everything.
|
||||
// +optional
|
||||
LabelSelector string
|
||||
|
||||
// A selector to restrict the list of returned metrics by their labels
|
||||
// +optional
|
||||
MetricLabelSelector string
|
||||
}
|
||||
|
||||
// NOTE: ObjectReference is copied from k8s.io/kubernetes/pkg/api/types.go. We
|
||||
// cannot depend on k8s.io/kubernetes/pkg/api because that creates cyclic
|
||||
// dependency between k8s.io/metrics and k8s.io/kubernetes. We cannot depend on
|
||||
// k8s.io/client-go/pkg/api because the package is going to be deprecated soon.
|
||||
// There is no need to keep it an exact copy. Each repo can define its own
|
||||
// internal objects.
|
||||
|
||||
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
||||
type ObjectReference struct {
|
||||
Kind string
|
||||
Namespace string
|
||||
Name string
|
||||
UID types.UID
|
||||
APIVersion string
|
||||
ResourceVersion string
|
||||
FieldPath string
|
||||
}
|
40
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/conversion.go
generated
vendored
Normal file
40
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/conversion.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/metrics/pkg/apis/custom_metrics"
|
||||
)
|
||||
|
||||
func Convert_v1beta1_MetricValue_To_custom_metrics_MetricValue(in *MetricValue, out *custom_metrics.MetricValue, s conversion.Scope) error {
|
||||
if err := autoConvert_v1beta1_MetricValue_To_custom_metrics_MetricValue(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Metric.Name = in.MetricName
|
||||
out.Metric.Selector = in.Selector
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_custom_metrics_MetricValue_To_v1beta1_MetricValue(in *custom_metrics.MetricValue, out *MetricValue, s conversion.Scope) error {
|
||||
if err := autoConvert_custom_metrics_MetricValue_To_v1beta1_MetricValue(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.MetricName = in.Metric.Name
|
||||
out.Selector = in.Metric.Selector
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:protobuf-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/metrics/pkg/apis/custom_metrics
|
||||
// +k8s:openapi-gen=true
|
||||
|
||||
// Package v1beta1 is the v1beta1 version of the custom_metrics API.
|
||||
package v1beta1 // import "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
|
1011
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go
generated
vendored
Normal file
1011
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
80
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto
generated
vendored
Normal file
80
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package k8s.io.metrics.pkg.apis.custom_metrics.v1beta1;
|
||||
|
||||
import "k8s.io/api/core/v1/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/api/resource/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
|
||||
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1";
|
||||
|
||||
// MetricListOptions is used to select metrics by their label selectors
|
||||
message MetricListOptions {
|
||||
// A selector to restrict the list of returned objects by their labels.
|
||||
// Defaults to everything.
|
||||
// +optional
|
||||
optional string labelSelector = 1;
|
||||
|
||||
// A selector to restrict the list of returned metrics by their labels
|
||||
// +optional
|
||||
optional string metricLabelSelector = 2;
|
||||
}
|
||||
|
||||
// MetricValue is a metric value for some object
|
||||
message MetricValue {
|
||||
// a reference to the described object
|
||||
optional k8s.io.api.core.v1.ObjectReference describedObject = 1;
|
||||
|
||||
// the name of the metric
|
||||
optional string metricName = 2;
|
||||
|
||||
// indicates the time at which the metrics were produced
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time timestamp = 3;
|
||||
|
||||
// indicates the window ([Timestamp-Window, Timestamp]) from
|
||||
// which these metrics were calculated, when returning rate
|
||||
// metrics calculated from cumulative metrics (or zero for
|
||||
// non-calculated instantaneous metrics).
|
||||
optional int64 window = 4;
|
||||
|
||||
// the value of the metric for this
|
||||
optional k8s.io.apimachinery.pkg.api.resource.Quantity value = 5;
|
||||
|
||||
// selector represents the label selector that could be used to select
|
||||
// this metric, and will generally just be the selector passed in to
|
||||
// the query used to fetch this metric.
|
||||
// When left blank, only the metric's Name will be used to gather metrics.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 6;
|
||||
}
|
||||
|
||||
// MetricValueList is a list of values for a given metric for some set of objects
|
||||
message MetricValueList {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
|
||||
|
||||
// the value of the metric across the described objects
|
||||
repeated MetricValue items = 2;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "custom.metrics.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&MetricValue{},
|
||||
&MetricValueList{},
|
||||
&MetricListOptions{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MetricValueList is a list of values for a given metric for some set of objects
|
||||
type MetricValueList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// the value of the metric across the described objects
|
||||
Items []MetricValue `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MetricValue is a metric value for some object
|
||||
type MetricValue struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// a reference to the described object
|
||||
DescribedObject v1.ObjectReference `json:"describedObject" protobuf:"bytes,1,name=describedObject"`
|
||||
|
||||
// the name of the metric
|
||||
MetricName string `json:"metricName" protobuf:"bytes,2,name=metricName"`
|
||||
|
||||
// indicates the time at which the metrics were produced
|
||||
Timestamp metav1.Time `json:"timestamp" protobuf:"bytes,3,name=timestamp"`
|
||||
|
||||
// indicates the window ([Timestamp-Window, Timestamp]) from
|
||||
// which these metrics were calculated, when returning rate
|
||||
// metrics calculated from cumulative metrics (or zero for
|
||||
// non-calculated instantaneous metrics).
|
||||
WindowSeconds *int64 `json:"window,omitempty" protobuf:"bytes,4,opt,name=window"`
|
||||
|
||||
// the value of the metric for this
|
||||
Value resource.Quantity `json:"value" protobuf:"bytes,5,name=value"`
|
||||
|
||||
// selector represents the label selector that could be used to select
|
||||
// this metric, and will generally just be the selector passed in to
|
||||
// the query used to fetch this metric.
|
||||
// When left blank, only the metric's Name will be used to gather metrics.
|
||||
// +optional
|
||||
Selector *metav1.LabelSelector `json:"selector" protobuf:"bytes,6,opt,name=selector"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MetricListOptions is used to select metrics by their label selectors
|
||||
type MetricListOptions struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// A selector to restrict the list of returned objects by their labels.
|
||||
// Defaults to everything.
|
||||
// +optional
|
||||
LabelSelector string `json:"labelSelector,omitempty" protobuf:"bytes,1,opt,name=labelSelector"`
|
||||
|
||||
// A selector to restrict the list of returned metrics by their labels
|
||||
// +optional
|
||||
MetricLabelSelector string `json:"metricLabelSelector,omitempty" protobuf:"bytes,2,opt,name=metricLabelSelector"`
|
||||
}
|
||||
|
||||
// AllObjects is a wildcard used to select metrics
|
||||
// for all objects matching the given label selector
|
||||
const AllObjects = "*"
|
157
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go
generated
vendored
Normal file
157
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
custommetrics "k8s.io/metrics/pkg/apis/custom_metrics"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*MetricListOptions)(nil), (*custommetrics.MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(a.(*MetricListOptions), b.(*custommetrics.MetricListOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*custommetrics.MetricListOptions)(nil), (*MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(a.(*custommetrics.MetricListOptions), b.(*MetricListOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*MetricValueList)(nil), (*custommetrics.MetricValueList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_MetricValueList_To_custom_metrics_MetricValueList(a.(*MetricValueList), b.(*custommetrics.MetricValueList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*custommetrics.MetricValueList)(nil), (*MetricValueList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_custom_metrics_MetricValueList_To_v1beta1_MetricValueList(a.(*custommetrics.MetricValueList), b.(*MetricValueList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*custommetrics.MetricValue)(nil), (*MetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_custom_metrics_MetricValue_To_v1beta1_MetricValue(a.(*custommetrics.MetricValue), b.(*MetricValue), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*MetricValue)(nil), (*custommetrics.MetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_MetricValue_To_custom_metrics_MetricValue(a.(*MetricValue), b.(*custommetrics.MetricValue), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
|
||||
out.LabelSelector = in.LabelSelector
|
||||
out.MetricLabelSelector = in.MetricLabelSelector
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions is an autogenerated conversion function.
|
||||
func Convert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
|
||||
out.LabelSelector = in.LabelSelector
|
||||
out.MetricLabelSelector = in.MetricLabelSelector
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions is an autogenerated conversion function.
|
||||
func Convert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
|
||||
return autoConvert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_MetricValue_To_custom_metrics_MetricValue(in *MetricValue, out *custommetrics.MetricValue, s conversion.Scope) error {
|
||||
if err := custommetrics.Convert_v1_ObjectReference_To_custom_metrics_ObjectReference(&in.DescribedObject, &out.DescribedObject, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// WARNING: in.MetricName requires manual conversion: does not exist in peer-type
|
||||
out.Timestamp = in.Timestamp
|
||||
out.WindowSeconds = (*int64)(unsafe.Pointer(in.WindowSeconds))
|
||||
out.Value = in.Value
|
||||
// WARNING: in.Selector requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_custom_metrics_MetricValue_To_v1beta1_MetricValue(in *custommetrics.MetricValue, out *MetricValue, s conversion.Scope) error {
|
||||
if err := custommetrics.Convert_custom_metrics_ObjectReference_To_v1_ObjectReference(&in.DescribedObject, &out.DescribedObject, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// WARNING: in.Metric requires manual conversion: does not exist in peer-type
|
||||
out.Timestamp = in.Timestamp
|
||||
out.WindowSeconds = (*int64)(unsafe.Pointer(in.WindowSeconds))
|
||||
out.Value = in.Value
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_MetricValueList_To_custom_metrics_MetricValueList(in *MetricValueList, out *custommetrics.MetricValueList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]custommetrics.MetricValue, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_MetricValue_To_custom_metrics_MetricValue(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_MetricValueList_To_custom_metrics_MetricValueList is an autogenerated conversion function.
|
||||
func Convert_v1beta1_MetricValueList_To_custom_metrics_MetricValueList(in *MetricValueList, out *custommetrics.MetricValueList, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_MetricValueList_To_custom_metrics_MetricValueList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_custom_metrics_MetricValueList_To_v1beta1_MetricValueList(in *custommetrics.MetricValueList, out *MetricValueList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]MetricValue, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_custom_metrics_MetricValue_To_v1beta1_MetricValue(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_custom_metrics_MetricValueList_To_v1beta1_MetricValueList is an autogenerated conversion function.
|
||||
func Convert_custom_metrics_MetricValueList_To_v1beta1_MetricValueList(in *custommetrics.MetricValueList, out *MetricValueList, s conversion.Scope) error {
|
||||
return autoConvert_custom_metrics_MetricValueList_To_v1beta1_MetricValueList(in, out, s)
|
||||
}
|
123
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go
generated
vendored
Normal file
123
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricListOptions) DeepCopyInto(out *MetricListOptions) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricListOptions.
|
||||
func (in *MetricListOptions) DeepCopy() *MetricListOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricListOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricListOptions) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricValue) DeepCopyInto(out *MetricValue) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.DescribedObject = in.DescribedObject
|
||||
in.Timestamp.DeepCopyInto(&out.Timestamp)
|
||||
if in.WindowSeconds != nil {
|
||||
in, out := &in.WindowSeconds, &out.WindowSeconds
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
out.Value = in.Value.DeepCopy()
|
||||
if in.Selector != nil {
|
||||
in, out := &in.Selector, &out.Selector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricValue.
|
||||
func (in *MetricValue) DeepCopy() *MetricValue {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricValue)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricValue) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricValueList) DeepCopyInto(out *MetricValueList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]MetricValue, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricValueList.
|
||||
func (in *MetricValueList) DeepCopy() *MetricValueList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricValueList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricValueList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:protobuf-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/metrics/pkg/apis/custom_metrics
|
||||
// +k8s:openapi-gen=true
|
||||
|
||||
// Package v1beta2 is the v1beta2 version of the custom_metrics API.
|
||||
package v1beta2 // import "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
|
1180
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/generated.pb.go
generated
vendored
Normal file
1180
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/generated.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
85
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/generated.proto
generated
vendored
Normal file
85
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/generated.proto
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package k8s.io.metrics.pkg.apis.custom_metrics.v1beta2;
|
||||
|
||||
import "k8s.io/api/core/v1/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/api/resource/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
|
||||
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2";
|
||||
|
||||
// MetricIdentifier identifies a metric by name and, optionally, selector
|
||||
message MetricIdentifier {
|
||||
// name is the name of the given metric
|
||||
optional string name = 1;
|
||||
|
||||
// selector represents the label selector that could be used to select
|
||||
// this metric, and will generally just be the selector passed in to
|
||||
// the query used to fetch this metric.
|
||||
// When left blank, only the metric's Name will be used to gather metrics.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2;
|
||||
}
|
||||
|
||||
// MetricListOptions is used to select metrics by their label selectors
|
||||
message MetricListOptions {
|
||||
// A selector to restrict the list of returned objects by their labels.
|
||||
// Defaults to everything.
|
||||
// +optional
|
||||
optional string labelSelector = 1;
|
||||
|
||||
// A selector to restrict the list of returned metrics by their labels
|
||||
// +optional
|
||||
optional string metricLabelSelector = 2;
|
||||
}
|
||||
|
||||
// MetricValue is the metric value for some object
|
||||
message MetricValue {
|
||||
// a reference to the described object
|
||||
optional k8s.io.api.core.v1.ObjectReference describedObject = 1;
|
||||
|
||||
optional MetricIdentifier metric = 2;
|
||||
|
||||
// indicates the time at which the metrics were produced
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time timestamp = 3;
|
||||
|
||||
// indicates the window ([Timestamp-Window, Timestamp]) from
|
||||
// which these metrics were calculated, when returning rate
|
||||
// metrics calculated from cumulative metrics (or zero for
|
||||
// non-calculated instantaneous metrics).
|
||||
optional int64 windowSeconds = 4;
|
||||
|
||||
// the value of the metric for this
|
||||
optional k8s.io.apimachinery.pkg.api.resource.Quantity value = 5;
|
||||
}
|
||||
|
||||
// MetricValueList is a list of values for a given metric for some set of objects
|
||||
message MetricValueList {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
|
||||
|
||||
// the value of the metric across the described objects
|
||||
repeated MetricValue items = 2;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "custom.metrics.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta2"}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&MetricValue{},
|
||||
&MetricValueList{},
|
||||
&MetricListOptions{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// MetricIdentifier identifies a metric by name and, optionally, selector
|
||||
type MetricIdentifier struct {
|
||||
// name is the name of the given metric
|
||||
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
|
||||
// selector represents the label selector that could be used to select
|
||||
// this metric, and will generally just be the selector passed in to
|
||||
// the query used to fetch this metric.
|
||||
// When left blank, only the metric's Name will be used to gather metrics.
|
||||
// +optional
|
||||
Selector *metav1.LabelSelector `json:"selector" protobuf:"bytes,2,opt,name=selector"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MetricValueList is a list of values for a given metric for some set of objects
|
||||
type MetricValueList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// the value of the metric across the described objects
|
||||
Items []MetricValue `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MetricValue is the metric value for some object
|
||||
type MetricValue struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// a reference to the described object
|
||||
DescribedObject v1.ObjectReference `json:"describedObject" protobuf:"bytes,1,name=describedObject"`
|
||||
|
||||
Metric MetricIdentifier `json:"metric" protobuf:"bytes,2,name=metric"`
|
||||
|
||||
// indicates the time at which the metrics were produced
|
||||
Timestamp metav1.Time `json:"timestamp" protobuf:"bytes,3,name=timestamp"`
|
||||
|
||||
// indicates the window ([Timestamp-Window, Timestamp]) from
|
||||
// which these metrics were calculated, when returning rate
|
||||
// metrics calculated from cumulative metrics (or zero for
|
||||
// non-calculated instantaneous metrics).
|
||||
WindowSeconds *int64 `json:"windowSeconds,omitempty" protobuf:"bytes,4,opt,name=windowSeconds"`
|
||||
|
||||
// the value of the metric for this
|
||||
Value resource.Quantity `json:"value" protobuf:"bytes,5,name=value"`
|
||||
}
|
||||
|
||||
// AllObjects is a wildcard used to select metrics
|
||||
// for all objects matching the given label selector
|
||||
const AllObjects = "*"
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MetricListOptions is used to select metrics by their label selectors
|
||||
type MetricListOptions struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// A selector to restrict the list of returned objects by their labels.
|
||||
// Defaults to everything.
|
||||
// +optional
|
||||
LabelSelector string `json:"labelSelector,omitempty" protobuf:"bytes,1,opt,name=labelSelector"`
|
||||
|
||||
// A selector to restrict the list of returned metrics by their labels
|
||||
// +optional
|
||||
MetricLabelSelector string `json:"metricLabelSelector,omitempty" protobuf:"bytes,2,opt,name=metricLabelSelector"`
|
||||
}
|
203
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.conversion.go
generated
vendored
Normal file
203
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.conversion.go
generated
vendored
Normal file
|
@ -0,0 +1,203 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
custommetrics "k8s.io/metrics/pkg/apis/custom_metrics"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*MetricIdentifier)(nil), (*custommetrics.MetricIdentifier)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta2_MetricIdentifier_To_custom_metrics_MetricIdentifier(a.(*MetricIdentifier), b.(*custommetrics.MetricIdentifier), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*custommetrics.MetricIdentifier)(nil), (*MetricIdentifier)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier(a.(*custommetrics.MetricIdentifier), b.(*MetricIdentifier), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*MetricListOptions)(nil), (*custommetrics.MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(a.(*MetricListOptions), b.(*custommetrics.MetricListOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*custommetrics.MetricListOptions)(nil), (*MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(a.(*custommetrics.MetricListOptions), b.(*MetricListOptions), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*MetricValue)(nil), (*custommetrics.MetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta2_MetricValue_To_custom_metrics_MetricValue(a.(*MetricValue), b.(*custommetrics.MetricValue), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*custommetrics.MetricValue)(nil), (*MetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_custom_metrics_MetricValue_To_v1beta2_MetricValue(a.(*custommetrics.MetricValue), b.(*MetricValue), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*MetricValueList)(nil), (*custommetrics.MetricValueList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta2_MetricValueList_To_custom_metrics_MetricValueList(a.(*MetricValueList), b.(*custommetrics.MetricValueList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*custommetrics.MetricValueList)(nil), (*MetricValueList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_custom_metrics_MetricValueList_To_v1beta2_MetricValueList(a.(*custommetrics.MetricValueList), b.(*MetricValueList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta2_MetricIdentifier_To_custom_metrics_MetricIdentifier(in *MetricIdentifier, out *custommetrics.MetricIdentifier, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Selector = (*v1.LabelSelector)(unsafe.Pointer(in.Selector))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta2_MetricIdentifier_To_custom_metrics_MetricIdentifier is an autogenerated conversion function.
|
||||
func Convert_v1beta2_MetricIdentifier_To_custom_metrics_MetricIdentifier(in *MetricIdentifier, out *custommetrics.MetricIdentifier, s conversion.Scope) error {
|
||||
return autoConvert_v1beta2_MetricIdentifier_To_custom_metrics_MetricIdentifier(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier(in *custommetrics.MetricIdentifier, out *MetricIdentifier, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Selector = (*v1.LabelSelector)(unsafe.Pointer(in.Selector))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier is an autogenerated conversion function.
|
||||
func Convert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier(in *custommetrics.MetricIdentifier, out *MetricIdentifier, s conversion.Scope) error {
|
||||
return autoConvert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
|
||||
out.LabelSelector = in.LabelSelector
|
||||
out.MetricLabelSelector = in.MetricLabelSelector
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions is an autogenerated conversion function.
|
||||
func Convert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
|
||||
return autoConvert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
|
||||
out.LabelSelector = in.LabelSelector
|
||||
out.MetricLabelSelector = in.MetricLabelSelector
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions is an autogenerated conversion function.
|
||||
func Convert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
|
||||
return autoConvert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta2_MetricValue_To_custom_metrics_MetricValue(in *MetricValue, out *custommetrics.MetricValue, s conversion.Scope) error {
|
||||
if err := custommetrics.Convert_v1_ObjectReference_To_custom_metrics_ObjectReference(&in.DescribedObject, &out.DescribedObject, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta2_MetricIdentifier_To_custom_metrics_MetricIdentifier(&in.Metric, &out.Metric, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Timestamp = in.Timestamp
|
||||
out.WindowSeconds = (*int64)(unsafe.Pointer(in.WindowSeconds))
|
||||
out.Value = in.Value
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta2_MetricValue_To_custom_metrics_MetricValue is an autogenerated conversion function.
|
||||
func Convert_v1beta2_MetricValue_To_custom_metrics_MetricValue(in *MetricValue, out *custommetrics.MetricValue, s conversion.Scope) error {
|
||||
return autoConvert_v1beta2_MetricValue_To_custom_metrics_MetricValue(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_custom_metrics_MetricValue_To_v1beta2_MetricValue(in *custommetrics.MetricValue, out *MetricValue, s conversion.Scope) error {
|
||||
if err := custommetrics.Convert_custom_metrics_ObjectReference_To_v1_ObjectReference(&in.DescribedObject, &out.DescribedObject, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier(&in.Metric, &out.Metric, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Timestamp = in.Timestamp
|
||||
out.WindowSeconds = (*int64)(unsafe.Pointer(in.WindowSeconds))
|
||||
out.Value = in.Value
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_custom_metrics_MetricValue_To_v1beta2_MetricValue is an autogenerated conversion function.
|
||||
func Convert_custom_metrics_MetricValue_To_v1beta2_MetricValue(in *custommetrics.MetricValue, out *MetricValue, s conversion.Scope) error {
|
||||
return autoConvert_custom_metrics_MetricValue_To_v1beta2_MetricValue(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta2_MetricValueList_To_custom_metrics_MetricValueList(in *MetricValueList, out *custommetrics.MetricValueList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]custommetrics.MetricValue, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta2_MetricValue_To_custom_metrics_MetricValue(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta2_MetricValueList_To_custom_metrics_MetricValueList is an autogenerated conversion function.
|
||||
func Convert_v1beta2_MetricValueList_To_custom_metrics_MetricValueList(in *MetricValueList, out *custommetrics.MetricValueList, s conversion.Scope) error {
|
||||
return autoConvert_v1beta2_MetricValueList_To_custom_metrics_MetricValueList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_custom_metrics_MetricValueList_To_v1beta2_MetricValueList(in *custommetrics.MetricValueList, out *MetricValueList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]MetricValue, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_custom_metrics_MetricValue_To_v1beta2_MetricValue(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_custom_metrics_MetricValueList_To_v1beta2_MetricValueList is an autogenerated conversion function.
|
||||
func Convert_custom_metrics_MetricValueList_To_v1beta2_MetricValueList(in *custommetrics.MetricValueList, out *MetricValueList, s conversion.Scope) error {
|
||||
return autoConvert_custom_metrics_MetricValueList_To_v1beta2_MetricValueList(in, out, s)
|
||||
}
|
140
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.deepcopy.go
generated
vendored
Normal file
140
vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.deepcopy.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricIdentifier) DeepCopyInto(out *MetricIdentifier) {
|
||||
*out = *in
|
||||
if in.Selector != nil {
|
||||
in, out := &in.Selector, &out.Selector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricIdentifier.
|
||||
func (in *MetricIdentifier) DeepCopy() *MetricIdentifier {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricIdentifier)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricListOptions) DeepCopyInto(out *MetricListOptions) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricListOptions.
|
||||
func (in *MetricListOptions) DeepCopy() *MetricListOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricListOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricListOptions) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricValue) DeepCopyInto(out *MetricValue) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.DescribedObject = in.DescribedObject
|
||||
in.Metric.DeepCopyInto(&out.Metric)
|
||||
in.Timestamp.DeepCopyInto(&out.Timestamp)
|
||||
if in.WindowSeconds != nil {
|
||||
in, out := &in.WindowSeconds, &out.WindowSeconds
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
out.Value = in.Value.DeepCopy()
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricValue.
|
||||
func (in *MetricValue) DeepCopy() *MetricValue {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricValue)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricValue) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricValueList) DeepCopyInto(out *MetricValueList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]MetricValue, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricValueList.
|
||||
func (in *MetricValueList) DeepCopy() *MetricValueList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricValueList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricValueList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
156
vendor/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go
generated
vendored
Normal file
156
vendor/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go
generated
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package custom_metrics
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricIdentifier) DeepCopyInto(out *MetricIdentifier) {
|
||||
*out = *in
|
||||
if in.Selector != nil {
|
||||
in, out := &in.Selector, &out.Selector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricIdentifier.
|
||||
func (in *MetricIdentifier) DeepCopy() *MetricIdentifier {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricIdentifier)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricListOptions) DeepCopyInto(out *MetricListOptions) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricListOptions.
|
||||
func (in *MetricListOptions) DeepCopy() *MetricListOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricListOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricListOptions) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricValue) DeepCopyInto(out *MetricValue) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.DescribedObject = in.DescribedObject
|
||||
in.Metric.DeepCopyInto(&out.Metric)
|
||||
in.Timestamp.DeepCopyInto(&out.Timestamp)
|
||||
if in.WindowSeconds != nil {
|
||||
in, out := &in.WindowSeconds, &out.WindowSeconds
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
out.Value = in.Value.DeepCopy()
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricValue.
|
||||
func (in *MetricValue) DeepCopy() *MetricValue {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricValue)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricValue) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MetricValueList) DeepCopyInto(out *MetricValueList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]MetricValue, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricValueList.
|
||||
func (in *MetricValueList) DeepCopy() *MetricValueList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MetricValueList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *MetricValueList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ObjectReference) DeepCopyInto(out *ObjectReference) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectReference.
|
||||
func (in *ObjectReference) DeepCopy() *ObjectReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ObjectReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue