From 6a11f9d46db8f4a627e4a59c61fca9c31c874298 Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Thu, 25 Oct 2018 16:47:01 -0700 Subject: [PATCH] update kube-openapi dep --- Godeps/Godeps.json | 26 ++-- .../kube-openapi/pkg/aggregator/aggregator.go | 12 +- .../kube-openapi/pkg/builder/openapi.go | 23 +--- .../k8s.io/kube-openapi/pkg/common/common.go | 6 + .../k8s.io/kube-openapi/pkg/generators/BUILD | 1 + .../pkg/generators/{README => README.md} | 9 +- .../kube-openapi/pkg/generators/api_linter.go | 121 +++++++++++++++- .../kube-openapi/pkg/generators/config.go | 91 ++++++++++++ .../kube-openapi/pkg/generators/extension.go | 8 +- .../kube-openapi/pkg/generators/openapi.go | 129 +++--------------- .../kube-openapi/pkg/generators/rules/BUILD | 1 + .../kube-openapi/pkg/generators/rules/OWNERS | 4 + .../generators/rules/omitempty_match_case.go | 64 +++++++++ .../kube-openapi/pkg/util/proto/document.go | 8 +- .../kube-openapi/pkg/util/proto/openapi.go | 2 + vendor/k8s.io/kube-openapi/pkg/util/util.go | 22 ++- 16 files changed, 366 insertions(+), 161 deletions(-) rename vendor/k8s.io/kube-openapi/pkg/generators/{README => README.md} (88%) create mode 100644 vendor/k8s.io/kube-openapi/pkg/generators/config.go create mode 100755 vendor/k8s.io/kube-openapi/pkg/generators/rules/OWNERS create mode 100644 vendor/k8s.io/kube-openapi/pkg/generators/rules/omitempty_match_case.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 943cc18cfc3..b1a58b61f54 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -3913,55 +3913,55 @@ }, { "ImportPath": "k8s.io/kube-openapi/cmd/openapi-gen", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/cmd/openapi-gen/args", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/aggregator", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/builder", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/common", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/generators", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/generators/rules", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/handler", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto/testing", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto/validation", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/sets", - "Rev": "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" + "Rev": "72693cb1fadd73ae2742f6fe29af77d1aecdd8cd" }, { "ImportPath": "k8s.io/utils/clock", diff --git a/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator.go b/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator.go index f05b5017252..cbeb3ef8a57 100644 --- a/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator.go +++ b/vendor/k8s.io/kube-openapi/pkg/aggregator/aggregator.go @@ -87,13 +87,13 @@ func (s *referenceWalker) walkSchema(schema *spec.Schema) { s.walkSchema(&v) schema.PatternProperties[k] = v } - for i, _ := range schema.AllOf { + for i := range schema.AllOf { s.walkSchema(&schema.AllOf[i]) } - for i, _ := range schema.AnyOf { + for i := range schema.AnyOf { s.walkSchema(&schema.AnyOf[i]) } - for i, _ := range schema.OneOf { + for i := range schema.OneOf { s.walkSchema(&schema.OneOf[i]) } if schema.Not != nil { @@ -109,7 +109,7 @@ func (s *referenceWalker) walkSchema(schema *spec.Schema) { if schema.Items.Schema != nil { s.walkSchema(schema.Items.Schema) } - for i, _ := range schema.Items.Schemas { + for i := range schema.Items.Schemas { s.walkSchema(&schema.Items.Schemas[i]) } } @@ -257,7 +257,9 @@ func mergeSpecs(dest, source *spec.Swagger, renameModelConflicts, ignorePathConf specCloned := false // Paths may be empty, due to [ACL constraints](http://goo.gl/8us55a#securityFiltering). if source.Paths == nil { - source.Paths = &spec.Paths{} + // When a source spec does not have any path, that means none of the definitions + // are used thus we should not do anything + return nil } if dest.Paths == nil { dest.Paths = &spec.Paths{} diff --git a/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go b/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go index f48700d5454..072c8ec4ae5 100644 --- a/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go +++ b/vendor/k8s.io/kube-openapi/pkg/builder/openapi.go @@ -20,7 +20,6 @@ import ( "encoding/json" "fmt" "net/http" - "reflect" "strings" restful "github.com/emicklei/go-restful" @@ -58,7 +57,7 @@ func BuildOpenAPIDefinitionsForResource(model interface{}, config *common.Config 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 - _, err := o.toSchema(getCanonicalTypeName(model)) + _, err := o.toSchema(util.GetCanonicalTypeName(model)) if err != nil { return nil, err } @@ -92,6 +91,7 @@ func newOpenAPI(config *common.Config) openAPI { SwaggerProps: spec.SwaggerProps{ Swagger: OpenAPIVersion, Definitions: spec.Definitions{}, + Responses: config.ResponseDefinitions, Paths: &spec.Paths{Paths: map[string]spec.PathItem{}}, Info: config.Info, }, @@ -135,21 +135,6 @@ func (o *openAPI) finalizeSwagger() (*spec.Swagger, error) { return o.swagger, nil } -func getCanonicalTypeName(model interface{}) string { - t := reflect.TypeOf(model) - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - if t.PkgPath() == "" { - return t.Name() - } - path := t.PkgPath() - if strings.Contains(path, "/vendor/") { - path = path[strings.Index(path, "/vendor/")+len("/vendor/"):] - } - return path + "." + t.Name() -} - func (o *openAPI) buildDefinitionRecursively(name string) error { uniqueName, extensions := o.config.GetDefinitionName(name) if _, ok := o.swagger.Definitions[uniqueName]; ok { @@ -335,7 +320,7 @@ func (o *openAPI) buildOperations(route restful.Route, inPathCommonParamsMap map } func (o *openAPI) buildResponse(model interface{}, description string) (spec.Response, error) { - schema, err := o.toSchema(getCanonicalTypeName(model)) + schema, err := o.toSchema(util.GetCanonicalTypeName(model)) if err != nil { return spec.Response{}, err } @@ -413,7 +398,7 @@ func (o *openAPI) buildParameter(restParam restful.ParameterData, bodySample int case restful.BodyParameterKind: if bodySample != nil { ret.In = "body" - ret.Schema, err = o.toSchema(getCanonicalTypeName(bodySample)) + ret.Schema, err = o.toSchema(util.GetCanonicalTypeName(bodySample)) return ret, err } else { // There is not enough information in the body parameter to build the definition. diff --git a/vendor/k8s.io/kube-openapi/pkg/common/common.go b/vendor/k8s.io/kube-openapi/pkg/common/common.go index 0d235876deb..7d5534b24ec 100644 --- a/vendor/k8s.io/kube-openapi/pkg/common/common.go +++ b/vendor/k8s.io/kube-openapi/pkg/common/common.go @@ -59,6 +59,12 @@ type Config struct { // will show up as ... "responses" : {"default" : $DefaultResponse} in the spec. DefaultResponse *spec.Response + // ResponseDefinitions will be added to "responses" under the top-level swagger object. This is an object + // that holds responses definitions that can be used across operations. This property does not define + // global responses for all operations. For more info please refer: + // https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields + ResponseDefinitions map[string]spec.Response + // CommonResponses will be added as a response to all operation specs. This is a good place to add common // responses such as authorization failed. CommonResponses map[int]spec.Response diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/BUILD b/vendor/k8s.io/kube-openapi/pkg/generators/BUILD index 6f6e02f2d69..80907b63cec 100644 --- a/vendor/k8s.io/kube-openapi/pkg/generators/BUILD +++ b/vendor/k8s.io/kube-openapi/pkg/generators/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "api_linter.go", + "config.go", "extension.go", "openapi.go", ], diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/README b/vendor/k8s.io/kube-openapi/pkg/generators/README.md similarity index 88% rename from vendor/k8s.io/kube-openapi/pkg/generators/README rename to vendor/k8s.io/kube-openapi/pkg/generators/README.md index feb19b401a9..72b4e5fb439 100644 --- a/vendor/k8s.io/kube-openapi/pkg/generators/README +++ b/vendor/k8s.io/kube-openapi/pkg/generators/README.md @@ -4,8 +4,9 @@ - To exclude a type or a member from a tagged package/type, add "+k8s:openapi-gen=false" tag to the comment lines. # OpenAPI Extensions + OpenAPI spec can have extensions on types. To define one or more extensions on a type or its member -add `+k8s:openapi-gen=x-kubernetes-$NAME:`$VALUE`` to the comment lines before type/member. A type/member can +add `+k8s:openapi-gen=x-kubernetes-$NAME:$VALUE` to the comment lines before type/member. A type/member can have multiple extensions. The rest of the line in the comment will be used as $VALUE so there is no need to escape or quote the value string. Extensions can be used to pass more information to client generators or documentation generators. For example a type might have a friendly name to be displayed in documentation or @@ -17,6 +18,7 @@ Custom types which otherwise don't map directly to OpenAPI can override their OpenAPI definition by implementing a function named "OpenAPIDefinition" with the following signature: +```go import openapi "k8s.io/kube-openapi/pkg/common" // ... @@ -35,12 +37,13 @@ the following signature: }, } } +``` Alternatively, the type can avoid the "openapi" import by defining the following methods. The following example produces the same OpenAPI definition as the example above: +```go func (_ Time) OpenAPISchemaType() []string { return []string{"string"} } func (_ Time) OpenAPISchemaFormat() string { return "date-time" } - -TODO(mehdy): Make k8s:openapi-gen a parameter to the generator now that OpenAPI has its own repo. +``` diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go b/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go index 9270d26320b..0351d22d4cc 100644 --- a/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go +++ b/vendor/k8s.io/kube-openapi/pkg/generators/api_linter.go @@ -17,16 +17,114 @@ limitations under the License. package generators import ( + "bytes" "fmt" "io" + "io/ioutil" + "os" + "sort" "k8s.io/kube-openapi/pkg/generators/rules" "github.com/golang/glog" + "k8s.io/gengo/generator" "k8s.io/gengo/types" ) -// apiLinter is the framework hosting mutliple API rules and recording API rule +const apiViolationFileType = "api-violation" + +type apiViolationFile struct { + // Since our file actually is unrelated to the package structure, use a + // path that hasn't been mangled by the framework. + unmangledPath string +} + +func (a apiViolationFile) AssembleFile(f *generator.File, path string) error { + path = a.unmangledPath + glog.V(2).Infof("Assembling file %q", path) + if path == "-" { + _, err := io.Copy(os.Stdout, &f.Body) + return err + } + + output, err := os.Create(path) + if err != nil { + return err + } + defer output.Close() + _, err = io.Copy(output, &f.Body) + return err +} + +func (a apiViolationFile) VerifyFile(f *generator.File, path string) error { + if path == "-" { + // Nothing to verify against. + return nil + } + path = a.unmangledPath + + formatted := f.Body.Bytes() + existing, err := ioutil.ReadFile(path) + if err != nil { + return fmt.Errorf("unable to read file %q for comparison: %v", path, err) + } + if bytes.Compare(formatted, existing) == 0 { + return nil + } + + // Be nice and find the first place where they differ + // (Copied from gengo's default file type) + i := 0 + for i < len(formatted) && i < len(existing) && formatted[i] == existing[i] { + i++ + } + eDiff, fDiff := existing[i:], formatted[i:] + if len(eDiff) > 100 { + eDiff = eDiff[:100] + } + if len(fDiff) > 100 { + fDiff = fDiff[:100] + } + return fmt.Errorf("output for %q differs; first existing/expected diff: \n %q\n %q", path, string(eDiff), string(fDiff)) +} + +func newAPIViolationGen() *apiViolationGen { + return &apiViolationGen{ + linter: newAPILinter(), + } +} + +type apiViolationGen struct { + generator.DefaultGen + + linter *apiLinter +} + +func (v *apiViolationGen) FileType() string { return apiViolationFileType } +func (v *apiViolationGen) Filename() string { + return "this file is ignored by the file assembler" +} + +func (v *apiViolationGen) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + glog.V(5).Infof("validating API rules for type %v", t) + if err := v.linter.validate(t); err != nil { + return err + } + return nil +} + +// Finalize prints the API rule violations to report file (if specified from +// arguments) or stdout (default) +func (v *apiViolationGen) Finalize(c *generator.Context, w io.Writer) error { + // NOTE: we don't return error here because we assume that the report file will + // get evaluated afterwards to determine if error should be raised. For example, + // you can have make rules that compare the report file with existing known + // violations (whitelist) and determine no error if no change is detected. + v.linter.report(w) + return nil +} + +// apiLinter is the framework hosting multiple API rules and recording API rule // violations type apiLinter struct { // API rules that implement APIRule interface and output API rule violations @@ -40,6 +138,7 @@ func newAPILinter() *apiLinter { return &apiLinter{ rules: []APIRule{ &rules.NamesMatch{}, + &rules.OmitEmptyMatchCase{}, }, } } @@ -57,6 +156,25 @@ type apiViolation struct { field string } +// apiViolations implements sort.Interface for []apiViolation based on the fields: rule, +// packageName, typeName and field. +type apiViolations []apiViolation + +func (a apiViolations) Len() int { return len(a) } +func (a apiViolations) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a apiViolations) Less(i, j int) bool { + if a[i].rule != a[j].rule { + return a[i].rule < a[j].rule + } + if a[i].packageName != a[j].packageName { + return a[i].packageName < a[j].packageName + } + if a[i].typeName != a[j].typeName { + return a[i].typeName < a[j].typeName + } + return a[i].field < a[j].field +} + // APIRule is the interface for validating API rule on Go types type APIRule interface { // Validate evaluates API rule on type t and returns a list of field names in @@ -90,6 +208,7 @@ func (l *apiLinter) validate(t *types.Type) error { // report prints any API rule violation to writer w and returns error if violation exists func (l *apiLinter) report(w io.Writer) error { + sort.Sort(apiViolations(l.violations)) for _, v := range l.violations { fmt.Fprintf(w, "API rule violation: %s,%s,%s,%s\n", v.rule, v.packageName, v.typeName, v.field) } diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/config.go b/vendor/k8s.io/kube-openapi/pkg/generators/config.go new file mode 100644 index 00000000000..1d7ffcb0e0a --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/config.go @@ -0,0 +1,91 @@ +/* +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 generators + +import ( + "fmt" + "path/filepath" + + "github.com/golang/glog" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" +) + +type identityNamer struct{} + +func (_ identityNamer) Name(t *types.Type) string { + return t.Name.String() +} + +var _ namer.Namer = identityNamer{} + +// NameSystems returns the name system used by the generators in this package. +func NameSystems() namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer("", nil), + "sorting_namer": identityNamer{}, + } +} + +// DefaultNameSystem returns the default name system for ordering the types to be +// processed by the generators in this package. +func DefaultNameSystem() string { + return "sorting_namer" +} + +func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { + boilerplate, err := arguments.LoadGoBoilerplate() + if err != nil { + glog.Fatalf("Failed loading boilerplate: %v", err) + } + header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) + header = append(header, []byte( + ` +// This file was autogenerated by openapi-gen. Do not edit it manually! + +`)...) + + reportPath := "-" + if customArgs, ok := arguments.CustomArgs.(*generatorargs.CustomArgs); ok { + reportPath = customArgs.ReportFilename + } + context.FileTypes[apiViolationFileType] = apiViolationFile{ + unmangledPath: reportPath, + } + + return generator.Packages{ + &generator.DefaultPackage{ + PackageName: filepath.Base(arguments.OutputPackagePath), + PackagePath: arguments.OutputPackagePath, + HeaderText: header, + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + return []generator.Generator{ + newOpenAPIGen( + arguments.OutputFileBaseName, + arguments.OutputPackagePath, + ), + newAPIViolationGen(), + } + }, + FilterFunc: apiTypeFilterFunc, + }, + } +} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/extension.go b/vendor/k8s.io/kube-openapi/pkg/generators/extension.go index befe38db248..14eab18f6b9 100644 --- a/vendor/k8s.io/kube-openapi/pkg/generators/extension.go +++ b/vendor/k8s.io/kube-openapi/pkg/generators/extension.go @@ -36,20 +36,20 @@ type extensionAttributes struct { // Extension tag to openapi extension attributes var tagToExtension = map[string]extensionAttributes{ - "patchMergeKey": extensionAttributes{ + "patchMergeKey": { xName: "x-kubernetes-patch-merge-key", kind: types.Slice, }, - "patchStrategy": extensionAttributes{ + "patchStrategy": { xName: "x-kubernetes-patch-strategy", kind: types.Slice, allowedValues: sets.NewString("merge", "retainKeys"), }, - "listMapKey": extensionAttributes{ + "listMapKey": { xName: "x-kubernetes-list-map-keys", kind: types.Slice, }, - "listType": extensionAttributes{ + "listType": { xName: "x-kubernetes-list-type", kind: types.Slice, allowedValues: sets.NewString("atomic", "set", "map"), diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go b/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go index d6c6275a78f..9f13fbc388a 100644 --- a/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go +++ b/vendor/k8s.io/kube-openapi/pkg/generators/openapi.go @@ -20,17 +20,14 @@ import ( "bytes" "fmt" "io" - "os" "path/filepath" "reflect" "sort" "strings" - "k8s.io/gengo/args" "k8s.io/gengo/generator" "k8s.io/gengo/namer" "k8s.io/gengo/types" - generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" openapi "k8s.io/kube-openapi/pkg/common" "github.com/golang/glog" @@ -88,69 +85,19 @@ func hasOptionalTag(m *types.Member) bool { return hasOptionalCommentTag || hasOptionalJsonTag } -type identityNamer struct{} - -func (_ identityNamer) Name(t *types.Type) string { - return t.Name.String() -} - -var _ namer.Namer = identityNamer{} - -// NameSystems returns the name system used by the generators in this package. -func NameSystems() namer.NameSystems { - return namer.NameSystems{ - "raw": namer.NewRawNamer("", nil), - "sorting_namer": identityNamer{}, +func apiTypeFilterFunc(c *generator.Context, t *types.Type) bool { + // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen + if strings.HasPrefix(t.Name.Name, "codecSelfer") { + return false } -} - -// DefaultNameSystem returns the default name system for ordering the types to be -// processed by the generators in this package. -func DefaultNameSystem() string { - return "sorting_namer" -} - -func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { - boilerplate, err := arguments.LoadGoBoilerplate() - if err != nil { - glog.Fatalf("Failed loading boilerplate: %v", err) + pkg := c.Universe.Package(t.Name.Package) + if hasOpenAPITagValue(pkg.Comments, tagValueTrue) { + return !hasOpenAPITagValue(t.CommentLines, tagValueFalse) } - header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) - header = append(header, []byte( - ` -// This file was autogenerated by openapi-gen. Do not edit it manually! - -`)...) - - reportFilename := "-" - if customArgs, ok := arguments.CustomArgs.(*generatorargs.CustomArgs); ok { - reportFilename = customArgs.ReportFilename - } - - return generator.Packages{ - &generator.DefaultPackage{ - PackageName: filepath.Base(arguments.OutputPackagePath), - PackagePath: arguments.OutputPackagePath, - HeaderText: header, - GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { - return []generator.Generator{NewOpenAPIGen(arguments.OutputFileBaseName, arguments.OutputPackagePath, context, newAPILinter(), reportFilename)} - }, - FilterFunc: func(c *generator.Context, t *types.Type) bool { - // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen - if strings.HasPrefix(t.Name.Name, "codecSelfer") { - return false - } - pkg := context.Universe.Package(t.Name.Package) - if hasOpenAPITagValue(pkg.Comments, tagValueTrue) { - return !hasOpenAPITagValue(t.CommentLines, tagValueFalse) - } - if hasOpenAPITagValue(t.CommentLines, tagValueTrue) { - return true - } - return false - }, - }, + if hasOpenAPITagValue(t.CommentLines, tagValueTrue) { + return true } + return false } const ( @@ -162,24 +109,17 @@ const ( type openAPIGen struct { generator.DefaultGen // TargetPackage is the package that will get GetOpenAPIDefinitions function returns all open API definitions. - targetPackage string - imports namer.ImportTracker - types []*types.Type - context *generator.Context - linter *apiLinter - reportFilename string + targetPackage string + imports namer.ImportTracker } -func NewOpenAPIGen(sanitizedName string, targetPackage string, context *generator.Context, linter *apiLinter, reportFilename string) generator.Generator { +func newOpenAPIGen(sanitizedName string, targetPackage string) generator.Generator { return &openAPIGen{ DefaultGen: generator.DefaultGen{ OptionalName: sanitizedName, }, - imports: generator.NewImportTracker(), - targetPackage: targetPackage, - context: context, - linter: linter, - reportFilename: reportFilename, + imports: generator.NewImportTracker(), + targetPackage: targetPackage, } } @@ -198,15 +138,6 @@ func (g *openAPIGen) Namers(c *generator.Context) namer.NameSystems { } } -func (g *openAPIGen) Filter(c *generator.Context, t *types.Type) bool { - // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen - if strings.HasPrefix(t.Name.Name, "codecSelfer") { - return false - } - g.types = append(g.types, t) - return true -} - func (g *openAPIGen) isOtherPackage(pkg string) bool { if pkg == g.targetPackage { return false @@ -239,7 +170,7 @@ func (g *openAPIGen) Init(c *generator.Context, w io.Writer) error { sw.Do("func GetOpenAPIDefinitions(ref $.ReferenceCallback|raw$) map[string]$.OpenAPIDefinition|raw$ {\n", argsFromType(nil)) sw.Do("return map[string]$.OpenAPIDefinition|raw${\n", argsFromType(nil)) - for _, t := range g.types { + for _, t := range c.Order { err := newOpenAPITypeWriter(sw).generateCall(t) if err != nil { return err @@ -253,10 +184,6 @@ func (g *openAPIGen) Init(c *generator.Context, w io.Writer) error { } func (g *openAPIGen) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { - glog.V(5).Infof("validating API rules for type %v", t) - if err := g.linter.validate(t); err != nil { - return err - } glog.V(5).Infof("generating for type %v", t) sw := generator.NewSnippetWriter(w, c, "$", "$") err := newOpenAPITypeWriter(sw).generate(t) @@ -678,27 +605,3 @@ func (g openAPITypeWriter) generateSliceProperty(t *types.Type) error { g.Do("},\n},\n},\n", nil) return nil } - -// Finalize prints the API rule violations to report file (if specified from arguments) or stdout (default) -func (g *openAPIGen) Finalize(c *generator.Context, w io.Writer) error { - // If report file isn't specified, return error to force user to choose either stdout ("-") or a file name - if len(g.reportFilename) == 0 { - return fmt.Errorf("empty report file name: please provide a valid file name or use the default \"-\" (stdout)") - } - // If stdout is specified, print violations and return error - if g.reportFilename == "-" { - return g.linter.report(os.Stdout) - } - // Otherwise, print violations to report file and return nil - f, err := os.Create(g.reportFilename) - if err != nil { - return err - } - defer f.Close() - g.linter.report(f) - // NOTE: we don't return error here because we assume that the report file will - // get evaluated afterwards to determine if error should be raised. For example, - // you can have make rules that compare the report file with existing known - // violations (whitelist) and determine no error if no change is detected. - return nil -} diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/rules/BUILD b/vendor/k8s.io/kube-openapi/pkg/generators/rules/BUILD index e5a31703b4f..4ace661c5cf 100644 --- a/vendor/k8s.io/kube-openapi/pkg/generators/rules/BUILD +++ b/vendor/k8s.io/kube-openapi/pkg/generators/rules/BUILD @@ -5,6 +5,7 @@ go_library( srcs = [ "doc.go", "names_match.go", + "omitempty_match_case.go", ], importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-openapi/pkg/generators/rules", importpath = "k8s.io/kube-openapi/pkg/generators/rules", diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/rules/OWNERS b/vendor/k8s.io/kube-openapi/pkg/generators/rules/OWNERS new file mode 100755 index 00000000000..235bc545b88 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/rules/OWNERS @@ -0,0 +1,4 @@ +reviewers: +- roycaihw +approvers: +- roycaihw diff --git a/vendor/k8s.io/kube-openapi/pkg/generators/rules/omitempty_match_case.go b/vendor/k8s.io/kube-openapi/pkg/generators/rules/omitempty_match_case.go new file mode 100644 index 00000000000..dd37ad8a578 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/generators/rules/omitempty_match_case.go @@ -0,0 +1,64 @@ +/* +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 rules + +import ( + "reflect" + "strings" + + "k8s.io/gengo/types" +) + +// OmitEmptyMatchCase implements APIRule interface. +// "omitempty" must appear verbatim (no case variants). +type OmitEmptyMatchCase struct{} + +func (n *OmitEmptyMatchCase) Name() string { + return "omitempty_match_case" +} + +func (n *OmitEmptyMatchCase) Validate(t *types.Type) ([]string, error) { + fields := make([]string, 0) + + // Only validate struct type and ignore the rest + switch t.Kind { + case types.Struct: + for _, m := range t.Members { + goName := m.Name + jsonTag, ok := reflect.StructTag(m.Tags).Lookup("json") + if !ok { + continue + } + + parts := strings.Split(jsonTag, ",") + if len(parts) < 2 { + // no tags other than name + continue + } + if parts[0] == "-" { + // not serialized + continue + } + for _, part := range parts[1:] { + if strings.EqualFold(part, "omitempty") && part != "omitempty" { + fields = append(fields, goName) + } + } + } + } + return fields, nil +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go index a57dcd363f6..890a39399f6 100644 --- a/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go @@ -196,20 +196,24 @@ func (d *Definitions) parseKind(s *openapi_v2.Schema, path *Path) (Schema, error } fields := map[string]Schema{} + fieldOrder := []string{} for _, namedSchema := range s.GetProperties().GetAdditionalProperties() { var err error - path := path.FieldPath(namedSchema.GetName()) - fields[namedSchema.GetName()], err = d.ParseSchema(namedSchema.GetValue(), &path) + name := namedSchema.GetName() + path := path.FieldPath(name) + fields[name], err = d.ParseSchema(namedSchema.GetValue(), &path) if err != nil { return nil, err } + fieldOrder = append(fieldOrder, name) } return &Kind{ BaseSchema: d.parseBaseSchema(s, path), RequiredFields: s.GetRequired(), Fields: fields, + FieldOrder: fieldOrder, }, nil } diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go index f26b5ef8810..46643aa5081 100644 --- a/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/openapi.go @@ -173,6 +173,8 @@ type Kind struct { RequiredFields []string // Maps field names to types. Fields map[string]Schema + // FieldOrder reports the canonical order for the fields. + FieldOrder []string } var _ Schema = &Kind{} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/util.go b/vendor/k8s.io/kube-openapi/pkg/util/util.go index bcc0c4d4bb5..c5c42cd44cd 100644 --- a/vendor/k8s.io/kube-openapi/pkg/util/util.go +++ b/vendor/k8s.io/kube-openapi/pkg/util/util.go @@ -16,7 +16,10 @@ limitations under the License. package util -import "strings" +import ( + "reflect" + "strings" +) // ToCanonicalName converts Golang package/type name into canonical OpenAPI name. // Examples: @@ -37,3 +40,20 @@ func ToCanonicalName(name string) string { } return strings.Join(nameParts, ".") } + +// GetCanonicalTypeName will find the canonical type name of a sample object, removing +// the "vendor" part of the path +func GetCanonicalTypeName(model interface{}) string { + t := reflect.TypeOf(model) + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + if t.PkgPath() == "" { + return t.Name() + } + path := t.PkgPath() + if strings.Contains(path, "/vendor/") { + path = path[strings.Index(path, "/vendor/")+len("/vendor/"):] + } + return path + "." + t.Name() +}