bump kube-openapi

This commit is contained in:
Jordan Liggitt
2023-01-06 12:21:58 -05:00
parent 00cd2ae3bc
commit d78de56d76
68 changed files with 177 additions and 190 deletions

View File

@@ -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 {

View File

@@ -13,4 +13,3 @@ func AdaptWebServices(webServices []*restful.WebService) []common.RouteContainer
}
return containers
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -18,11 +18,9 @@ package handler
import (
"bytes"
"compress/gzip"
"crypto/sha512"
"encoding/json"
"fmt"
"mime"
"net/http"
"strconv"
"sync"
@@ -41,15 +39,6 @@ import (
"k8s.io/kube-openapi/pkg/validation/spec"
)
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"
)
func computeETag(data []byte) string {
if data == nil {
return ""
@@ -70,12 +59,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{}
@@ -146,14 +129,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.

View File

@@ -21,7 +21,6 @@ import (
"crypto/sha512"
"encoding/json"
"fmt"
"mime"
"net/http"
"net/url"
"path"
@@ -41,13 +40,6 @@ 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"
)
@@ -84,12 +76,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 ""
@@ -191,6 +177,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))
}

View File

@@ -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.

View File

@@ -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"
)
// Example https://swagger.io/specification/#example-object

View File

@@ -18,8 +18,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"
)
type ExternalDocumentation struct {

View File

@@ -56,7 +56,7 @@ func (m *MediaType) UnmarshalJSON(data []byte) error {
// 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

View File

@@ -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"
)
// 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

View File

@@ -20,8 +20,8 @@ import (
"encoding/json"
"strings"
"k8s.io/kube-openapi/pkg/validation/spec"
"github.com/go-openapi/swag"
"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

View File

@@ -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"
)
// RequestBody describes a single request body, more at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#requestBodyObject

View File

@@ -20,8 +20,8 @@ import (
"encoding/json"
"strconv"
"k8s.io/kube-openapi/pkg/validation/spec"
"github.com/go-openapi/swag"
"k8s.io/kube-openapi/pkg/validation/spec"
)
// Responses holds the list of possible responses as they are returned from executing this operation
@@ -149,7 +149,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

View File

@@ -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"
)
// SecurityRequirementProps describes the required security schemes to execute an operation, more at https://swagger.io/specification/#security-requirement-object

View File

@@ -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

View File

@@ -18,9 +18,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"
)
type Server struct {

View File

@@ -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())

View File

@@ -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
}

View File

@@ -13,7 +13,6 @@
// limitations under the License.
/*
Package errors provides an Error interface and several concrete types
implementing this interface to manage API errors and JSON-schema validation
errors.
@@ -23,6 +22,5 @@ it defines.
It is used throughout the various go-openapi toolkit libraries
(https://github.com/go-openapi).
*/
package errors

View File

@@ -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:

View File

@@ -184,7 +184,7 @@ func MinimumUint(path, in string, data, min uint64, exclusive bool) *errors.Vali
// MultipleOf validates if the provided number is a multiple of the factor
func MultipleOf(path, in string, data, factor float64) *errors.Validation {
// multipleOf factor must be positive
if factor < 0 {
if factor <= 0 {
return errors.MultipleOfMustBePositive(path, in, factor)
}
var mult float64
@@ -202,7 +202,7 @@ func MultipleOf(path, in string, data, factor float64) *errors.Validation {
// MultipleOfInt validates if the provided integer is a multiple of the factor
func MultipleOfInt(path, in string, data int64, factor int64) *errors.Validation {
// multipleOf factor must be positive
if factor < 0 {
if factor <= 0 {
return errors.MultipleOfMustBePositive(path, in, factor)
}
mult := data / factor
@@ -214,6 +214,10 @@ func MultipleOfInt(path, in string, data int64, factor int64) *errors.Validation
// MultipleOfUint validates if the provided unsigned integer is a multiple of the factor
func MultipleOfUint(path, in string, data, factor uint64) *errors.Validation {
// multipleOf factor must be positive
if factor == 0 {
return errors.MultipleOfMustBePositive(path, in, factor)
}
mult := data / factor
if mult*factor != data {
return errors.NotMultipleOf(path, in, factor, data)