From d1213fd88d6d30090194811a5edbb2b6392237e8 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Mon, 26 Feb 2024 14:41:31 -0800 Subject: [PATCH 01/24] Commit latest integration results --- .../pkg/generated/openapi_generated.go | 46 +++---------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/test/integration/pkg/generated/openapi_generated.go b/test/integration/pkg/generated/openapi_generated.go index 9d6b6d84d..86269dc53 100644 --- a/test/integration/pkg/generated/openapi_generated.go +++ b/test/integration/pkg/generated/openapi_generated.go @@ -1080,16 +1080,7 @@ func schema_test_integration_testdata_valuevalidation_Foo(ref common.ReferenceCa "celField": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ - "x-kubernetes-validations": []interface{}{ - map[string]interface{}{ - "rule": "self.length() > 0", - "message": "string message", - }, - map[string]interface{}{ - "rule": "self.length() % 2 == 0", - "messageExpression": "self + ' hello'", - }, - }, + "x-kubernetes-validations": []interface{}{map[string]interface{}{"message": "string message", "rule": "self.length() > 0"}, map[string]interface{}{"messageExpression": "self + ' hello'", "rule": "self.length() % 2 == 0"}}, }, }, SchemaProps: spec.SchemaProps{ @@ -1103,12 +1094,7 @@ func schema_test_integration_testdata_valuevalidation_Foo(ref common.ReferenceCa }, VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ - "x-kubernetes-validations": []interface{}{ - map[string]interface{}{ - "rule": "self == oldSelf", - "message": "foo", - }, - }, + "x-kubernetes-validations": []interface{}{map[string]interface{}{"message": "foo", "rule": "self == oldSelf"}}, }, }, }, @@ -1126,12 +1112,7 @@ func schema_test_integration_testdata_valuevalidation_Foo2(ref common.ReferenceC }, VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ - "x-kubernetes-validations": []interface{}{ - map[string]interface{}{ - "rule": "self == oldSelf", - "message": "foo2", - }, - }, + "x-kubernetes-validations": []interface{}{map[string]interface{}{"message": "foo2", "rule": "self == oldSelf"}}, }, }, }, @@ -1149,12 +1130,7 @@ func schema_test_integration_testdata_valuevalidation_Foo3(ref common.ReferenceC }, VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ - "x-kubernetes-validations": []interface{}{ - map[string]interface{}{ - "rule": "self == oldSelf", - "message": "foo3", - }, - }, + "x-kubernetes-validations": []interface{}{map[string]interface{}{"message": "foo3", "rule": "self == oldSelf"}}, }, }, }, @@ -1168,12 +1144,7 @@ func schema_test_integration_testdata_valuevalidation_Foo3(ref common.ReferenceC }, VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ - "x-kubernetes-validations": []interface{}{ - map[string]interface{}{ - "rule": "self == oldSelf", - "message": "foo3", - }, - }, + "x-kubernetes-validations": []interface{}{map[string]interface{}{"message": "foo3", "rule": "self == oldSelf"}}, }, }, }, @@ -1191,12 +1162,7 @@ func schema_test_integration_testdata_valuevalidation_Foo5(ref common.ReferenceC }, VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ - "x-kubernetes-validations": []interface{}{ - map[string]interface{}{ - "rule": "self == oldSelf", - "message": "foo5", - }, - }, + "x-kubernetes-validations": []interface{}{map[string]interface{}{"message": "foo5", "rule": "self == oldSelf"}}, }, }, }, From ffcc404b4306f28f4a30ed4e8954ec9a8bfa1021 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:05:08 -0800 Subject: [PATCH 02/24] Use our own sets pkg instead of gengo --- pkg/generators/extension.go | 2 +- pkg/generators/extension_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/generators/extension.go b/pkg/generators/extension.go index e37d93ef7..a2c38e8ca 100644 --- a/pkg/generators/extension.go +++ b/pkg/generators/extension.go @@ -21,8 +21,8 @@ import ( "sort" "strings" - "k8s.io/gengo/examples/set-gen/sets" "k8s.io/gengo/types" + "k8s.io/kube-openapi/pkg/util/sets" ) const extensionPrefix = "x-kubernetes-" diff --git a/pkg/generators/extension_test.go b/pkg/generators/extension_test.go index 7c2c0dff1..1e844a726 100644 --- a/pkg/generators/extension_test.go +++ b/pkg/generators/extension_test.go @@ -21,8 +21,8 @@ import ( "strings" "testing" - "k8s.io/gengo/examples/set-gen/sets" "k8s.io/gengo/types" + "k8s.io/kube-openapi/pkg/util/sets" ) func TestSingleTagExtension(t *testing.T) { From bdea9976016f38522ccd6825a1ade14494393347 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:06:49 -0800 Subject: [PATCH 03/24] Convert imports to gengo/v2 This does not fix all the logic. That will be done subsequently. TO REPEAT: git grep -l 'k8s.io/gengo/[^v][^2]' \ | while read F; do \ sed -i 's|k8s.io/gengo/\([^v]\)|k8s.io/gengo/v2/\1|' $F done --- cmd/openapi-gen/args/args.go | 2 +- pkg/generators/api_linter.go | 4 ++-- pkg/generators/config.go | 8 ++++---- pkg/generators/enum.go | 4 ++-- pkg/generators/enum_test.go | 4 ++-- pkg/generators/extension.go | 2 +- pkg/generators/extension_test.go | 2 +- pkg/generators/markers.go | 4 ++-- pkg/generators/markers_test.go | 2 +- pkg/generators/openapi.go | 8 ++++---- pkg/generators/openapi_test.go | 8 ++++---- pkg/generators/rules/idl_tag.go | 2 +- pkg/generators/rules/idl_tag_test.go | 2 +- pkg/generators/rules/names_match.go | 2 +- pkg/generators/rules/names_match_test.go | 2 +- pkg/generators/rules/omitempty_match_case.go | 2 +- pkg/generators/rules/omitempty_match_case_test.go | 2 +- pkg/generators/union.go | 2 +- 18 files changed, 31 insertions(+), 31 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 19783370e..354314827 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -21,7 +21,7 @@ import ( "path/filepath" "github.com/spf13/pflag" - "k8s.io/gengo/args" + "k8s.io/gengo/v2/args" ) // CustomArgs is used by the gengo framework to pass args specific to this generator. diff --git a/pkg/generators/api_linter.go b/pkg/generators/api_linter.go index 2763cf884..13ed38cbb 100644 --- a/pkg/generators/api_linter.go +++ b/pkg/generators/api_linter.go @@ -25,8 +25,8 @@ import ( "k8s.io/kube-openapi/pkg/generators/rules" - "k8s.io/gengo/generator" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/generator" + "k8s.io/gengo/v2/types" "k8s.io/klog/v2" ) diff --git a/pkg/generators/config.go b/pkg/generators/config.go index d728f2a32..d71df7160 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -20,10 +20,10 @@ import ( "fmt" "path/filepath" - "k8s.io/gengo/args" - "k8s.io/gengo/generator" - "k8s.io/gengo/namer" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/args" + "k8s.io/gengo/v2/generator" + "k8s.io/gengo/v2/namer" + "k8s.io/gengo/v2/types" "k8s.io/klog/v2" generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" diff --git a/pkg/generators/enum.go b/pkg/generators/enum.go index 933d61690..1cdb5979f 100644 --- a/pkg/generators/enum.go +++ b/pkg/generators/enum.go @@ -22,8 +22,8 @@ import ( "sort" "strings" - "k8s.io/gengo/generator" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/generator" + "k8s.io/gengo/v2/types" ) const tagEnumType = "enum" diff --git a/pkg/generators/enum_test.go b/pkg/generators/enum_test.go index 93c51a59e..b96ff4eb5 100644 --- a/pkg/generators/enum_test.go +++ b/pkg/generators/enum_test.go @@ -21,8 +21,8 @@ import ( "sort" "testing" - "k8s.io/gengo/generator" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/generator" + "k8s.io/gengo/v2/types" ) func TestParseEnums(t *testing.T) { diff --git a/pkg/generators/extension.go b/pkg/generators/extension.go index a2c38e8ca..27d2b5d03 100644 --- a/pkg/generators/extension.go +++ b/pkg/generators/extension.go @@ -21,7 +21,7 @@ import ( "sort" "strings" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" "k8s.io/kube-openapi/pkg/util/sets" ) diff --git a/pkg/generators/extension_test.go b/pkg/generators/extension_test.go index 1e844a726..7964bdbc4 100644 --- a/pkg/generators/extension_test.go +++ b/pkg/generators/extension_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" "k8s.io/kube-openapi/pkg/util/sets" ) diff --git a/pkg/generators/markers.go b/pkg/generators/markers.go index 7421f6c41..064d904c9 100644 --- a/pkg/generators/markers.go +++ b/pkg/generators/markers.go @@ -24,8 +24,8 @@ import ( "strconv" "strings" - defaultergen "k8s.io/gengo/examples/defaulter-gen/generators" - "k8s.io/gengo/types" + defaultergen "k8s.io/gengo/v2/examples/defaulter-gen/generators" + "k8s.io/gengo/v2/types" openapi "k8s.io/kube-openapi/pkg/common" "k8s.io/kube-openapi/pkg/validation/spec" ) diff --git a/pkg/generators/markers_test.go b/pkg/generators/markers_test.go index 284996ca2..36f0ff10d 100644 --- a/pkg/generators/markers_test.go +++ b/pkg/generators/markers_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" "k8s.io/kube-openapi/pkg/generators" "k8s.io/kube-openapi/pkg/validation/spec" "k8s.io/utils/ptr" diff --git a/pkg/generators/openapi.go b/pkg/generators/openapi.go index b6fd741b5..4fff79b0c 100644 --- a/pkg/generators/openapi.go +++ b/pkg/generators/openapi.go @@ -26,10 +26,10 @@ import ( "sort" "strings" - defaultergen "k8s.io/gengo/examples/defaulter-gen/generators" - "k8s.io/gengo/generator" - "k8s.io/gengo/namer" - "k8s.io/gengo/types" + defaultergen "k8s.io/gengo/v2/examples/defaulter-gen/generators" + "k8s.io/gengo/v2/generator" + "k8s.io/gengo/v2/namer" + "k8s.io/gengo/v2/types" openapi "k8s.io/kube-openapi/pkg/common" "k8s.io/kube-openapi/pkg/validation/spec" diff --git a/pkg/generators/openapi_test.go b/pkg/generators/openapi_test.go index d29ba0830..2982d13b8 100644 --- a/pkg/generators/openapi_test.go +++ b/pkg/generators/openapi_test.go @@ -26,10 +26,10 @@ import ( "go/format" "github.com/stretchr/testify/assert" - "k8s.io/gengo/generator" - "k8s.io/gengo/namer" - "k8s.io/gengo/parser" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/generator" + "k8s.io/gengo/v2/namer" + "k8s.io/gengo/v2/parser" + "k8s.io/gengo/v2/types" ) func construct(t *testing.T, files map[string]string, testNamer namer.Namer) (*parser.Builder, types.Universe, []*types.Type) { diff --git a/pkg/generators/rules/idl_tag.go b/pkg/generators/rules/idl_tag.go index 0abe0aa07..a35a0b222 100644 --- a/pkg/generators/rules/idl_tag.go +++ b/pkg/generators/rules/idl_tag.go @@ -1,7 +1,7 @@ package rules import ( - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" ) const ListTypeIDLTag = "listType" diff --git a/pkg/generators/rules/idl_tag_test.go b/pkg/generators/rules/idl_tag_test.go index d3c41e3d5..e334f3269 100644 --- a/pkg/generators/rules/idl_tag_test.go +++ b/pkg/generators/rules/idl_tag_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" ) func TestListTypeMissing(t *testing.T) { diff --git a/pkg/generators/rules/names_match.go b/pkg/generators/rules/names_match.go index 53e870c1a..af30edc5e 100644 --- a/pkg/generators/rules/names_match.go +++ b/pkg/generators/rules/names_match.go @@ -22,7 +22,7 @@ import ( "k8s.io/kube-openapi/pkg/util/sets" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" ) var ( diff --git a/pkg/generators/rules/names_match_test.go b/pkg/generators/rules/names_match_test.go index 05c78116c..e45e6d1bb 100644 --- a/pkg/generators/rules/names_match_test.go +++ b/pkg/generators/rules/names_match_test.go @@ -20,7 +20,7 @@ import ( "reflect" "testing" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" ) func TestNamesMatch(t *testing.T) { diff --git a/pkg/generators/rules/omitempty_match_case.go b/pkg/generators/rules/omitempty_match_case.go index dd37ad8a5..d83875964 100644 --- a/pkg/generators/rules/omitempty_match_case.go +++ b/pkg/generators/rules/omitempty_match_case.go @@ -20,7 +20,7 @@ import ( "reflect" "strings" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" ) // OmitEmptyMatchCase implements APIRule interface. diff --git a/pkg/generators/rules/omitempty_match_case_test.go b/pkg/generators/rules/omitempty_match_case_test.go index 07276ff32..0234773a1 100644 --- a/pkg/generators/rules/omitempty_match_case_test.go +++ b/pkg/generators/rules/omitempty_match_case_test.go @@ -20,7 +20,7 @@ import ( "reflect" "testing" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" ) func TestOmitEmptyMatchCase(t *testing.T) { diff --git a/pkg/generators/union.go b/pkg/generators/union.go index 89f564e43..afd067280 100644 --- a/pkg/generators/union.go +++ b/pkg/generators/union.go @@ -20,7 +20,7 @@ import ( "fmt" "sort" - "k8s.io/gengo/types" + "k8s.io/gengo/v2/types" ) const tagUnionMember = "union" From ab79d754ebfba33c3ea89756cb9ff79a5ac74e14 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:05:52 -0800 Subject: [PATCH 04/24] Don't auto-set the Go header file flag --- cmd/openapi-gen/args/args.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 354314827..8b1b3573d 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -18,7 +18,6 @@ package args import ( "fmt" - "path/filepath" "github.com/spf13/pflag" "k8s.io/gengo/v2/args" @@ -39,8 +38,6 @@ func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { // WithoutDefaultFlagParsing() disables implicit addition of command line flags and parsing, // which allows registering custom arguments afterwards genericArgs := args.Default().WithoutDefaultFlagParsing() - genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kube-openapi/boilerplate/boilerplate.go.txt") - customArgs := &CustomArgs{} genericArgs.CustomArgs = customArgs From a5de5005fa1799a460934cb680c520ff75d769c7 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:12:50 -0800 Subject: [PATCH 05/24] Fix kube-openapi wrt gengo/v2 Also get rid of targetPackage - it's not a package, it's a directory. We can't pretend an arbitrary output dir is a Go package or that the directory path has anything to do with the package name. Go is particular in its definition - a package has at least one .go file in it. If the output dir doesn't (yet), then it's not a resolvable package - even if it SEEMS like it should be. Fortunately, since the directory we emit to is never one of the input directories, we don't need to try to elide the "local" package name from type references. Also, we don't actually make any such type references. If that were to change, we could easily adapt - scan the inputs' SourcePaths for the output dir and, IFF found, pass it down. But the odds of needing that are ~0 at this point. --- cmd/openapi-gen/args/args.go | 25 +++++++++++++++++-------- pkg/generators/config.go | 11 +++++++---- pkg/generators/openapi.go | 10 ---------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 8b1b3573d..548a82caa 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -25,6 +25,8 @@ import ( // CustomArgs is used by the gengo framework to pass args specific to this generator. type CustomArgs struct { + OutputPackage string // must be a Go import-path + // ReportFilename is added to CustomArgs for specifying name of report file used // by API linter. If specified, API rule violations will be printed to report file. // Otherwise default value "-" will be used which indicates stdout. @@ -51,23 +53,30 @@ func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { // AddFlags add the generator flags to the flag set. func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { - fs.StringVarP(&c.ReportFilename, "report-filename", "r", c.ReportFilename, "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.") + fs.StringVar(&c.OutputPackage, "output-package", "", + "the base Go import-path under which to generate results") + fs.StringVarP(&c.ReportFilename, "report-filename", "r", "-", + "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.") } // Validate checks the given arguments. func Validate(genericArgs *args.GeneratorArgs) error { + if len(genericArgs.OutputBase) == 0 { + return fmt.Errorf("--output-base must be specified") + } + if len(genericArgs.OutputFileBaseName) == 0 { + return fmt.Errorf("--output-file-base cannot be empty") + } + c, ok := genericArgs.CustomArgs.(*CustomArgs) if !ok { return fmt.Errorf("input arguments don't contain valid custom arguments") } - if len(c.ReportFilename) == 0 { - return fmt.Errorf("report filename cannot be empty. specify a valid filename or use \"-\" for stdout") - } - if len(genericArgs.OutputFileBaseName) == 0 { - return fmt.Errorf("output file base name cannot be empty") + if len(c.OutputPackage) == 0 { + return fmt.Errorf("--output-package must be specified") } - if len(genericArgs.OutputPackagePath) == 0 { - return fmt.Errorf("output package cannot be empty") + if len(c.ReportFilename) == 0 { + return fmt.Errorf("--report-filename must be specified (use \"-\" for stdout)") } return nil } diff --git a/pkg/generators/config.go b/pkg/generators/config.go index d71df7160..667c32b71 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -63,8 +63,10 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat `)...) + customArgs := arguments.CustomArgs.(*generatorargs.CustomArgs) + reportPath := "-" - if customArgs, ok := arguments.CustomArgs.(*generatorargs.CustomArgs); ok { + if customArgs.ReportFilename != "" { reportPath = customArgs.ReportFilename } context.FileTypes[apiViolationFileType] = apiViolationFile{ @@ -73,14 +75,15 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat return generator.Packages{ &generator.DefaultPackage{ - PackageName: filepath.Base(arguments.OutputPackagePath), - PackagePath: arguments.OutputPackagePath, + PackageName: filepath.Base(arguments.OutputBase), + PackagePath: customArgs.OutputPackage, + Source: arguments.OutputBase, HeaderText: header, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ newOpenAPIGen( arguments.OutputFileBaseName, - arguments.OutputPackagePath, + customArgs.OutputPackage, ), newAPIViolationGen(), } diff --git a/pkg/generators/openapi.go b/pkg/generators/openapi.go index 4fff79b0c..6e0b8c544 100644 --- a/pkg/generators/openapi.go +++ b/pkg/generators/openapi.go @@ -155,16 +155,6 @@ func (g *openAPIGen) Namers(c *generator.Context) namer.NameSystems { } } -func (g *openAPIGen) isOtherPackage(pkg string) bool { - if pkg == g.targetPackage { - return false - } - if strings.HasSuffix(pkg, "\""+g.targetPackage+"\"") { - return false - } - return true -} - func (g *openAPIGen) Imports(c *generator.Context) []string { importLines := []string{} for _, singleImport := range g.imports.ImportLines() { From 5fef66a63ca6a7785c7ee5515423e86370138bfe Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:14:44 -0800 Subject: [PATCH 06/24] Rename DefaultPackage to SimplePackage (gengo/v2) --- pkg/generators/config.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/generators/config.go b/pkg/generators/config.go index 667c32b71..5a6985b96 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -74,12 +74,12 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat } return generator.Packages{ - &generator.DefaultPackage{ - PackageName: filepath.Base(arguments.OutputBase), - PackagePath: customArgs.OutputPackage, - Source: arguments.OutputBase, - HeaderText: header, - GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + &generator.SimplePackage{ + PkgName: filepath.Base(arguments.OutputBase), + PkgPath: customArgs.OutputPackage, + PkgDir: arguments.OutputBase, + HeaderComment: header, + GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ newOpenAPIGen( arguments.OutputFileBaseName, From f82efc807325814c089b640ae4988cbf13864858 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:15:24 -0800 Subject: [PATCH 07/24] Drop `gengo/v2/generator.Packages` type --- pkg/generators/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/generators/config.go b/pkg/generators/config.go index 5a6985b96..bbe04f6d5 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -51,7 +51,7 @@ func DefaultNameSystem() string { return "sorting_namer" } -func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { +func Packages(context *generator.Context, arguments *args.GeneratorArgs) []generator.Package { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { klog.Fatalf("Failed loading boilerplate: %v", err) @@ -73,7 +73,7 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat unmangledPath: reportPath, } - return generator.Packages{ + return []generator.Package{ &generator.SimplePackage{ PkgName: filepath.Base(arguments.OutputBase), PkgPath: customArgs.OutputPackage, From 007cebbe3ff522aaeb12f312f18fa36a903ee810 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:16:27 -0800 Subject: [PATCH 08/24] Rename `gengo/v2/generator.Package` -> `Target` --- cmd/openapi-gen/openapi-gen.go | 2 +- pkg/generators/config.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/openapi-gen/openapi-gen.go b/cmd/openapi-gen/openapi-gen.go index c446e80b8..5ebfb6b99 100644 --- a/cmd/openapi-gen/openapi-gen.go +++ b/cmd/openapi-gen/openapi-gen.go @@ -50,7 +50,7 @@ func main() { if err := genericArgs.Execute( generators.NameSystems(), generators.DefaultNameSystem(), - generators.Packages, + generators.GetTargets, ); err != nil { log.Fatalf("OpenAPI code generation error: %v", err) } diff --git a/pkg/generators/config.go b/pkg/generators/config.go index bbe04f6d5..dc64722dc 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -51,7 +51,7 @@ func DefaultNameSystem() string { return "sorting_namer" } -func Packages(context *generator.Context, arguments *args.GeneratorArgs) []generator.Package { +func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []generator.Target { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { klog.Fatalf("Failed loading boilerplate: %v", err) @@ -73,8 +73,8 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) []gener unmangledPath: reportPath, } - return []generator.Package{ - &generator.SimplePackage{ + return []generator.Target{ + &generator.SimpleTarget{ PkgName: filepath.Base(arguments.OutputBase), PkgPath: customArgs.OutputPackage, PkgDir: arguments.OutputBase, From 4079daf5a9b6de88d6ada533b8fc3d687399299f Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:16:58 -0800 Subject: [PATCH 09/24] Rename gengo/v2 DefaultGen -> GolangGenerator --- pkg/generators/api_linter.go | 2 +- pkg/generators/openapi.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/generators/api_linter.go b/pkg/generators/api_linter.go index 13ed38cbb..0a4ff1745 100644 --- a/pkg/generators/api_linter.go +++ b/pkg/generators/api_linter.go @@ -94,7 +94,7 @@ func newAPIViolationGen() *apiViolationGen { } type apiViolationGen struct { - generator.DefaultGen + generator.GolangGenerator linter *apiLinter } diff --git a/pkg/generators/openapi.go b/pkg/generators/openapi.go index 6e0b8c544..005da6d2e 100644 --- a/pkg/generators/openapi.go +++ b/pkg/generators/openapi.go @@ -124,16 +124,16 @@ const ( // openApiGen produces a file with auto-generated OpenAPI functions. type openAPIGen struct { - generator.DefaultGen + generator.GolangGenerator // TargetPackage is the package that will get GetOpenAPIDefinitions function returns all open API definitions. targetPackage string imports namer.ImportTracker } -func newOpenAPIGen(sanitizedName string, targetPackage string) generator.Generator { +func newOpenAPIGen(outputFilename string, targetPackage string) generator.Generator { return &openAPIGen{ - DefaultGen: generator.DefaultGen{ - OptionalName: sanitizedName, + GolangGenerator: generator.GolangGenerator{ + OutputFilename: outputFilename, }, imports: generator.NewImportTrackerForPackage(targetPackage), targetPackage: targetPackage, From 4946e68c8c54dd04e32acbd0ce0ef0281f6d9dd2 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:17:50 -0800 Subject: [PATCH 10/24] Type-assert gengo CustomArgs blindly If it does fail, it is catastophic. Don't bother trying to handle it. --- cmd/openapi-gen/args/args.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 548a82caa..46b5aba29 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -68,10 +68,8 @@ func Validate(genericArgs *args.GeneratorArgs) error { return fmt.Errorf("--output-file-base cannot be empty") } - c, ok := genericArgs.CustomArgs.(*CustomArgs) - if !ok { - return fmt.Errorf("input arguments don't contain valid custom arguments") - } + c := genericArgs.CustomArgs.(*CustomArgs) + if len(c.OutputPackage) == 0 { return fmt.Errorf("--output-package must be specified") } From 39f912738c084d5023aeb4cfc7680014d61e65f3 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:18:23 -0800 Subject: [PATCH 11/24] gengo/v2 moves the OutputBase flag to each tool ...and rename to --output-dir --- cmd/openapi-gen/args/args.go | 9 ++++++--- pkg/generators/config.go | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 46b5aba29..a65201f8d 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -25,6 +25,7 @@ import ( // CustomArgs is used by the gengo framework to pass args specific to this generator. type CustomArgs struct { + OutputDir string // must be a directory path OutputPackage string // must be a Go import-path // ReportFilename is added to CustomArgs for specifying name of report file used @@ -53,6 +54,8 @@ func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { // AddFlags add the generator flags to the flag set. func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { + fs.StringVar(&c.OutputDir, "output-dir", "", + "the base directory under which to generate results") fs.StringVar(&c.OutputPackage, "output-package", "", "the base Go import-path under which to generate results") fs.StringVarP(&c.ReportFilename, "report-filename", "r", "-", @@ -61,15 +64,15 @@ func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { // Validate checks the given arguments. func Validate(genericArgs *args.GeneratorArgs) error { - if len(genericArgs.OutputBase) == 0 { - return fmt.Errorf("--output-base must be specified") - } if len(genericArgs.OutputFileBaseName) == 0 { return fmt.Errorf("--output-file-base cannot be empty") } c := genericArgs.CustomArgs.(*CustomArgs) + if len(c.OutputDir) == 0 { + return fmt.Errorf("--output-dir must be specified") + } if len(c.OutputPackage) == 0 { return fmt.Errorf("--output-package must be specified") } diff --git a/pkg/generators/config.go b/pkg/generators/config.go index dc64722dc..092f90b8b 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -75,9 +75,9 @@ func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []gen return []generator.Target{ &generator.SimpleTarget{ - PkgName: filepath.Base(arguments.OutputBase), + PkgName: filepath.Base(customArgs.OutputDir), PkgPath: customArgs.OutputPackage, - PkgDir: arguments.OutputBase, + PkgDir: customArgs.OutputDir, HeaderComment: header, GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ From ce262fba51872ffb9a6dd5563f0ac3382d8432fa Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:19:12 -0800 Subject: [PATCH 12/24] Rename output-package -> output-pkg (gengo/v2) --- cmd/openapi-gen/args/args.go | 10 +++++----- pkg/generators/config.go | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index a65201f8d..fe8bffc0e 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -25,8 +25,8 @@ import ( // CustomArgs is used by the gengo framework to pass args specific to this generator. type CustomArgs struct { - OutputDir string // must be a directory path - OutputPackage string // must be a Go import-path + OutputDir string // must be a directory path + OutputPkg string // must be a Go import-path // ReportFilename is added to CustomArgs for specifying name of report file used // by API linter. If specified, API rule violations will be printed to report file. @@ -56,7 +56,7 @@ func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&c.OutputDir, "output-dir", "", "the base directory under which to generate results") - fs.StringVar(&c.OutputPackage, "output-package", "", + fs.StringVar(&c.OutputPkg, "output-pkg", "", "the base Go import-path under which to generate results") fs.StringVarP(&c.ReportFilename, "report-filename", "r", "-", "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.") @@ -73,8 +73,8 @@ func Validate(genericArgs *args.GeneratorArgs) error { if len(c.OutputDir) == 0 { return fmt.Errorf("--output-dir must be specified") } - if len(c.OutputPackage) == 0 { - return fmt.Errorf("--output-package must be specified") + if len(c.OutputPkg) == 0 { + return fmt.Errorf("--output-pkg must be specified") } if len(c.ReportFilename) == 0 { return fmt.Errorf("--report-filename must be specified (use \"-\" for stdout)") diff --git a/pkg/generators/config.go b/pkg/generators/config.go index 092f90b8b..ee3cc9ca0 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -76,14 +76,14 @@ func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []gen return []generator.Target{ &generator.SimpleTarget{ PkgName: filepath.Base(customArgs.OutputDir), - PkgPath: customArgs.OutputPackage, + PkgPath: customArgs.OutputPkg, PkgDir: customArgs.OutputDir, HeaderComment: header, GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ newOpenAPIGen( arguments.OutputFileBaseName, - customArgs.OutputPackage, + customArgs.OutputPkg, ), newAPIViolationGen(), } From 48882fadf24a2c9487e0d4e1e712d4cf58dc2c33 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:19:42 -0800 Subject: [PATCH 13/24] genego/v2 moves OutputFileBase flag to each tool --- cmd/openapi-gen/args/args.go | 16 ++++++++-------- pkg/generators/config.go | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index fe8bffc0e..25af0c22f 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -25,8 +25,9 @@ import ( // CustomArgs is used by the gengo framework to pass args specific to this generator. type CustomArgs struct { - OutputDir string // must be a directory path - OutputPkg string // must be a Go import-path + OutputDir string // must be a directory path + OutputPkg string // must be a Go import-path + OutputFile string // ReportFilename is added to CustomArgs for specifying name of report file used // by API linter. If specified, API rule violations will be printed to report file. @@ -46,8 +47,6 @@ func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { // Default value for report filename is "-", which stands for stdout customArgs.ReportFilename = "-" - // Default value for output file base name - genericArgs.OutputFileBaseName = "openapi_generated" return genericArgs, customArgs } @@ -58,16 +57,14 @@ func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { "the base directory under which to generate results") fs.StringVar(&c.OutputPkg, "output-pkg", "", "the base Go import-path under which to generate results") + fs.StringVar(&c.OutputFile, "output-file", "generated.openapi.go", + "the name of the file to be generated") fs.StringVarP(&c.ReportFilename, "report-filename", "r", "-", "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.") } // Validate checks the given arguments. func Validate(genericArgs *args.GeneratorArgs) error { - if len(genericArgs.OutputFileBaseName) == 0 { - return fmt.Errorf("--output-file-base cannot be empty") - } - c := genericArgs.CustomArgs.(*CustomArgs) if len(c.OutputDir) == 0 { @@ -76,6 +73,9 @@ func Validate(genericArgs *args.GeneratorArgs) error { if len(c.OutputPkg) == 0 { return fmt.Errorf("--output-pkg must be specified") } + if len(c.OutputFile) == 0 { + return fmt.Errorf("--output-file must be specified") + } if len(c.ReportFilename) == 0 { return fmt.Errorf("--report-filename must be specified (use \"-\" for stdout)") } diff --git a/pkg/generators/config.go b/pkg/generators/config.go index ee3cc9ca0..778dda765 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -82,7 +82,7 @@ func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []gen GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ newOpenAPIGen( - arguments.OutputFileBaseName, + customArgs.OutputFile, customArgs.OutputPkg, ), newAPIViolationGen(), From 13a77a31a4dd385eeefeda2223d9212961cc31b1 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:20:31 -0800 Subject: [PATCH 14/24] gengo/v2 moves go-header-file flag to each tool --- cmd/openapi-gen/args/args.go | 4 ++++ cmd/openapi-gen/openapi-gen.go | 8 ++++---- pkg/generators/config.go | 15 ++++----------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 25af0c22f..10b21e31b 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -29,6 +29,8 @@ type CustomArgs struct { OutputPkg string // must be a Go import-path OutputFile string + GoHeaderFile string + // ReportFilename is added to CustomArgs for specifying name of report file used // by API linter. If specified, API rule violations will be printed to report file. // Otherwise default value "-" will be used which indicates stdout. @@ -59,6 +61,8 @@ func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { "the base Go import-path under which to generate results") fs.StringVar(&c.OutputFile, "output-file", "generated.openapi.go", "the name of the file to be generated") + fs.StringVar(&c.GoHeaderFile, "go-header-file", "", + "the path to a file containing boilerplate header text; the string \"YEAR\" will be replaced with the current 4-digit year") fs.StringVarP(&c.ReportFilename, "report-filename", "r", "-", "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.") } diff --git a/cmd/openapi-gen/openapi-gen.go b/cmd/openapi-gen/openapi-gen.go index 5ebfb6b99..94b308eca 100644 --- a/cmd/openapi-gen/openapi-gen.go +++ b/cmd/openapi-gen/openapi-gen.go @@ -24,12 +24,11 @@ import ( "flag" "log" - generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" - "k8s.io/kube-openapi/pkg/generators" - "github.com/spf13/pflag" - + "k8s.io/gengo/v2/args" "k8s.io/klog/v2" + generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" + "k8s.io/kube-openapi/pkg/generators" ) func main() { @@ -51,6 +50,7 @@ func main() { generators.NameSystems(), generators.DefaultNameSystem(), generators.GetTargets, + args.StdBuildTag, ); err != nil { log.Fatalf("OpenAPI code generation error: %v", err) } diff --git a/pkg/generators/config.go b/pkg/generators/config.go index 778dda765..1b9ece6ed 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -17,7 +17,6 @@ limitations under the License. package generators import ( - "fmt" "path/filepath" "k8s.io/gengo/v2/args" @@ -52,18 +51,12 @@ func DefaultNameSystem() string { } func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []generator.Target { - boilerplate, err := arguments.LoadGoBoilerplate() + customArgs := arguments.CustomArgs.(*generatorargs.CustomArgs) + + boilerplate, err := args.GoBoilerplate(customArgs.GoHeaderFile, args.StdBuildTag, args.StdGeneratedBy) if err != nil { klog.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! - -`)...) - - customArgs := arguments.CustomArgs.(*generatorargs.CustomArgs) reportPath := "-" if customArgs.ReportFilename != "" { @@ -78,7 +71,7 @@ func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []gen PkgName: filepath.Base(customArgs.OutputDir), PkgPath: customArgs.OutputPkg, PkgDir: customArgs.OutputDir, - HeaderComment: header, + HeaderComment: boilerplate, GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ newOpenAPIGen( From ee2c702b8153cadb1d9c043cc5f020e5eb9f06de Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:21:21 -0800 Subject: [PATCH 15/24] Kill gengo WithoutDefaultFlagParsing (gone in v2) --- cmd/openapi-gen/args/args.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 10b21e31b..414b2ea6f 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -41,9 +41,7 @@ type CustomArgs struct { // of using default flag parsing allows registering custom arguments afterwards func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { // Default() sets a couple of flag default values for example the boilerplate. - // WithoutDefaultFlagParsing() disables implicit addition of command line flags and parsing, - // which allows registering custom arguments afterwards - genericArgs := args.Default().WithoutDefaultFlagParsing() + genericArgs := args.Default() customArgs := &CustomArgs{} genericArgs.CustomArgs = customArgs From 07de3d434f4354baa7c9fca0149d95af40496770 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:22:20 -0800 Subject: [PATCH 16/24] Get rid of InputDirs flag --- cmd/openapi-gen/openapi-gen.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/openapi-gen/openapi-gen.go b/cmd/openapi-gen/openapi-gen.go index 94b308eca..6c47e3c86 100644 --- a/cmd/openapi-gen/openapi-gen.go +++ b/cmd/openapi-gen/openapi-gen.go @@ -51,6 +51,7 @@ func main() { generators.DefaultNameSystem(), generators.GetTargets, args.StdBuildTag, + pflag.Args(), ); err != nil { log.Fatalf("OpenAPI code generation error: %v", err) } From f147b07a39fa7ff1b60c4f58dc8fa7d784b6e6dd Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:24:10 -0800 Subject: [PATCH 17/24] ParseSymbolReference is no longer exported --- pkg/generators/markers.go | 3 +-- pkg/generators/openapi.go | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/pkg/generators/markers.go b/pkg/generators/markers.go index 064d904c9..7f0fe985a 100644 --- a/pkg/generators/markers.go +++ b/pkg/generators/markers.go @@ -24,7 +24,6 @@ import ( "strconv" "strings" - defaultergen "k8s.io/gengo/v2/examples/defaulter-gen/generators" "k8s.io/gengo/v2/types" openapi "k8s.io/kube-openapi/pkg/common" "k8s.io/kube-openapi/pkg/validation/spec" @@ -456,7 +455,7 @@ func parseMarkers(markerComments []string, prefix string) (map[string]any, error if len(key) == 0 { return nil, fmt.Errorf("cannot have empty key for marker comment") - } else if _, ok := defaultergen.ParseSymbolReference(value, ""); ok { + } else if _, ok := parseSymbolReference(value, ""); ok { // Skip ref markers continue } else if len(value) == 0 { diff --git a/pkg/generators/openapi.go b/pkg/generators/openapi.go index 005da6d2e..0ad5f068d 100644 --- a/pkg/generators/openapi.go +++ b/pkg/generators/openapi.go @@ -23,10 +23,10 @@ import ( "io" "path/filepath" "reflect" + "regexp" "sort" "strings" - defaultergen "k8s.io/gengo/v2/examples/defaulter-gen/generators" "k8s.io/gengo/v2/generator" "k8s.io/gengo/v2/namer" "k8s.io/gengo/v2/types" @@ -701,7 +701,7 @@ func defaultFromComments(comments []string, commentPath string, t *types.Type) ( } var i interface{} - if id, ok := defaultergen.ParseSymbolReference(tag, commentPath); ok { + if id, ok := parseSymbolReference(tag, commentPath); ok { klog.Errorf("%v, %v", id, commentPath) return nil, &id, nil } else if err := json.Unmarshal([]byte(tag), &i); err != nil { @@ -710,6 +710,31 @@ func defaultFromComments(comments []string, commentPath string, t *types.Type) ( return i, nil, nil } +var refRE = regexp.MustCompile(`^ref\((?P[^"]+)\)$`) +var refREIdentIndex = refRE.SubexpIndex("reference") + +// parseSymbolReference looks for strings that match one of the following: +// - ref(Ident) +// - ref(pkgpath.Ident) +// If the input string matches either of these, it will return the (optional) +// pkgpath, the Ident, and true. Otherwise it will return empty strings and +// false. +// +// This is borrowed from k8s.io/code-generator. +func parseSymbolReference(s, sourcePackage string) (types.Name, bool) { + matches := refRE.FindStringSubmatch(s) + if len(matches) < refREIdentIndex || matches[refREIdentIndex] == "" { + return types.Name{}, false + } + + contents := matches[refREIdentIndex] + name := types.ParseFullyQualifiedName(contents) + if len(name.Package) == 0 { + name.Package = sourcePackage + } + return name, true +} + func implementsCustomUnmarshalling(t *types.Type) bool { switch t.Kind { case types.Pointer: From c6b9085c9b4bd886ab298599a7f4ee5847e5e68f Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:24:58 -0800 Subject: [PATCH 18/24] Get rid of gengo CustomArgs (gone in v2) --- cmd/openapi-gen/args/args.go | 43 ++++++++++++++-------------------- cmd/openapi-gen/openapi-gen.go | 22 ++++++++++------- pkg/generators/config.go | 25 +++++++++----------- 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/cmd/openapi-gen/args/args.go b/cmd/openapi-gen/args/args.go index 414b2ea6f..d53282b7a 100644 --- a/cmd/openapi-gen/args/args.go +++ b/cmd/openapi-gen/args/args.go @@ -20,65 +20,58 @@ import ( "fmt" "github.com/spf13/pflag" - "k8s.io/gengo/v2/args" ) -// CustomArgs is used by the gengo framework to pass args specific to this generator. -type CustomArgs struct { +type Args struct { OutputDir string // must be a directory path OutputPkg string // must be a Go import-path OutputFile string GoHeaderFile string - // ReportFilename is added to CustomArgs for specifying name of report file used + // ReportFilename is added to Args for specifying name of report file used // by API linter. If specified, API rule violations will be printed to report file. // Otherwise default value "-" will be used which indicates stdout. ReportFilename string } -// NewDefaults returns default arguments for the generator. Returning the arguments instead +// New returns default arguments for the generator. Returning the arguments instead // of using default flag parsing allows registering custom arguments afterwards -func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { - // Default() sets a couple of flag default values for example the boilerplate. - genericArgs := args.Default() - customArgs := &CustomArgs{} - genericArgs.CustomArgs = customArgs +func New() *Args { + args := &Args{} // Default value for report filename is "-", which stands for stdout - customArgs.ReportFilename = "-" + args.ReportFilename = "-" - return genericArgs, customArgs + return args } // AddFlags add the generator flags to the flag set. -func (c *CustomArgs) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&c.OutputDir, "output-dir", "", +func (args *Args) AddFlags(fs *pflag.FlagSet) { + fs.StringVar(&args.OutputDir, "output-dir", "", "the base directory under which to generate results") - fs.StringVar(&c.OutputPkg, "output-pkg", "", + fs.StringVar(&args.OutputPkg, "output-pkg", "", "the base Go import-path under which to generate results") - fs.StringVar(&c.OutputFile, "output-file", "generated.openapi.go", + fs.StringVar(&args.OutputFile, "output-file", "generated.openapi.go", "the name of the file to be generated") - fs.StringVar(&c.GoHeaderFile, "go-header-file", "", + fs.StringVar(&args.GoHeaderFile, "go-header-file", "", "the path to a file containing boilerplate header text; the string \"YEAR\" will be replaced with the current 4-digit year") - fs.StringVarP(&c.ReportFilename, "report-filename", "r", "-", + fs.StringVarP(&args.ReportFilename, "report-filename", "r", "-", "Name of report file used by API linter to print API violations. Default \"-\" stands for standard output. NOTE that if valid filename other than \"-\" is specified, API linter won't return error on detected API violations. This allows further check of existing API violations without stopping the OpenAPI generation toolchain.") } // Validate checks the given arguments. -func Validate(genericArgs *args.GeneratorArgs) error { - c := genericArgs.CustomArgs.(*CustomArgs) - - if len(c.OutputDir) == 0 { +func (args *Args) Validate() error { + if len(args.OutputDir) == 0 { return fmt.Errorf("--output-dir must be specified") } - if len(c.OutputPkg) == 0 { + if len(args.OutputPkg) == 0 { return fmt.Errorf("--output-pkg must be specified") } - if len(c.OutputFile) == 0 { + if len(args.OutputFile) == 0 { return fmt.Errorf("--output-file must be specified") } - if len(c.ReportFilename) == 0 { + if len(args.ReportFilename) == 0 { return fmt.Errorf("--report-filename must be specified (use \"-\" for stdout)") } return nil diff --git a/cmd/openapi-gen/openapi-gen.go b/cmd/openapi-gen/openapi-gen.go index 6c47e3c86..ba8fce8d9 100644 --- a/cmd/openapi-gen/openapi-gen.go +++ b/cmd/openapi-gen/openapi-gen.go @@ -25,32 +25,36 @@ import ( "log" "github.com/spf13/pflag" - "k8s.io/gengo/v2/args" + gengo "k8s.io/gengo/v2/args" + "k8s.io/gengo/v2/generator" "k8s.io/klog/v2" - generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" + "k8s.io/kube-openapi/cmd/openapi-gen/args" "k8s.io/kube-openapi/pkg/generators" ) func main() { klog.InitFlags(nil) - genericArgs, customArgs := generatorargs.NewDefaults() + args := args.New() - genericArgs.AddFlags(pflag.CommandLine) - customArgs.AddFlags(pflag.CommandLine) + args.AddFlags(pflag.CommandLine) flag.Set("logtostderr", "true") pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() - if err := generatorargs.Validate(genericArgs); err != nil { + if err := args.Validate(); err != nil { log.Fatalf("Arguments validation error: %v", err) } + myTargets := func(context *generator.Context) []generator.Target { + return generators.GetTargets(context, args) + } + // Generates the code for the OpenAPIDefinitions. - if err := genericArgs.Execute( + if err := gengo.Execute( generators.NameSystems(), generators.DefaultNameSystem(), - generators.GetTargets, - args.StdBuildTag, + myTargets, + gengo.StdBuildTag, pflag.Args(), ); err != nil { log.Fatalf("OpenAPI code generation error: %v", err) diff --git a/pkg/generators/config.go b/pkg/generators/config.go index 1b9ece6ed..61a73fbde 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -19,13 +19,12 @@ package generators import ( "path/filepath" - "k8s.io/gengo/v2/args" + gengo "k8s.io/gengo/v2/args" "k8s.io/gengo/v2/generator" "k8s.io/gengo/v2/namer" "k8s.io/gengo/v2/types" "k8s.io/klog/v2" - - generatorargs "k8s.io/kube-openapi/cmd/openapi-gen/args" + "k8s.io/kube-openapi/cmd/openapi-gen/args" ) type identityNamer struct{} @@ -50,17 +49,15 @@ func DefaultNameSystem() string { return "sorting_namer" } -func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []generator.Target { - customArgs := arguments.CustomArgs.(*generatorargs.CustomArgs) - - boilerplate, err := args.GoBoilerplate(customArgs.GoHeaderFile, args.StdBuildTag, args.StdGeneratedBy) +func GetTargets(context *generator.Context, args *args.Args) []generator.Target { + boilerplate, err := gengo.GoBoilerplate(args.GoHeaderFile, gengo.StdBuildTag, gengo.StdGeneratedBy) if err != nil { klog.Fatalf("Failed loading boilerplate: %v", err) } reportPath := "-" - if customArgs.ReportFilename != "" { - reportPath = customArgs.ReportFilename + if args.ReportFilename != "" { + reportPath = args.ReportFilename } context.FileTypes[apiViolationFileType] = apiViolationFile{ unmangledPath: reportPath, @@ -68,15 +65,15 @@ func GetTargets(context *generator.Context, arguments *args.GeneratorArgs) []gen return []generator.Target{ &generator.SimpleTarget{ - PkgName: filepath.Base(customArgs.OutputDir), - PkgPath: customArgs.OutputPkg, - PkgDir: customArgs.OutputDir, + PkgName: filepath.Base(args.OutputPkg), + PkgPath: args.OutputPkg, + PkgDir: args.OutputDir, HeaderComment: boilerplate, GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ newOpenAPIGen( - customArgs.OutputFile, - customArgs.OutputPkg, + args.OutputFile, + args.OutputPkg, ), newAPIViolationGen(), } From 66f3980e814efc644a694cbe87675ea579753a3c Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:25:20 -0800 Subject: [PATCH 19/24] The gengo "args" package is gone --- cmd/openapi-gen/openapi-gen.go | 2 +- pkg/generators/config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/openapi-gen/openapi-gen.go b/cmd/openapi-gen/openapi-gen.go index ba8fce8d9..b466019ad 100644 --- a/cmd/openapi-gen/openapi-gen.go +++ b/cmd/openapi-gen/openapi-gen.go @@ -25,7 +25,7 @@ import ( "log" "github.com/spf13/pflag" - gengo "k8s.io/gengo/v2/args" + "k8s.io/gengo/v2" "k8s.io/gengo/v2/generator" "k8s.io/klog/v2" "k8s.io/kube-openapi/cmd/openapi-gen/args" diff --git a/pkg/generators/config.go b/pkg/generators/config.go index 61a73fbde..098d400a6 100644 --- a/pkg/generators/config.go +++ b/pkg/generators/config.go @@ -19,7 +19,7 @@ package generators import ( "path/filepath" - gengo "k8s.io/gengo/v2/args" + "k8s.io/gengo/v2" "k8s.io/gengo/v2/generator" "k8s.io/gengo/v2/namer" "k8s.io/gengo/v2/types" From c91b59f6a44d1376b96a872112b23d4133f66d08 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Fri, 16 Feb 2024 16:25:47 -0800 Subject: [PATCH 20/24] Gengo utils moved --- pkg/generators/enum.go | 3 ++- pkg/generators/extension.go | 3 ++- pkg/generators/openapi.go | 9 +++++---- pkg/generators/rules/idl_tag.go | 3 ++- pkg/generators/union.go | 13 +++++++------ 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pkg/generators/enum.go b/pkg/generators/enum.go index 1cdb5979f..dfc30ebc8 100644 --- a/pkg/generators/enum.go +++ b/pkg/generators/enum.go @@ -22,6 +22,7 @@ import ( "sort" "strings" + "k8s.io/gengo/v2" "k8s.io/gengo/v2/generator" "k8s.io/gengo/v2/types" ) @@ -163,7 +164,7 @@ func isEnumType(stringType *types.Type, t *types.Type) bool { } func hasEnumTag(t *types.Type) bool { - return types.ExtractCommentTags("+", t.CommentLines)[tagEnumType] != nil + return gengo.ExtractCommentTags("+", t.CommentLines)[tagEnumType] != nil } // whitespaceRegex is the regex for consecutive whitespaces. diff --git a/pkg/generators/extension.go b/pkg/generators/extension.go index 27d2b5d03..42d385416 100644 --- a/pkg/generators/extension.go +++ b/pkg/generators/extension.go @@ -21,6 +21,7 @@ import ( "sort" "strings" + "k8s.io/gengo/v2" "k8s.io/gengo/v2/types" "k8s.io/kube-openapi/pkg/util/sets" ) @@ -171,7 +172,7 @@ func parseExtensions(comments []string) ([]extension, []error) { } } // Next, generate extensions from "idlTags" (e.g. +listType) - tagValues := types.ExtractCommentTags("+", comments) + tagValues := gengo.ExtractCommentTags("+", comments) for _, idlTag := range sortedMapKeys(tagValues) { xAttrs, exists := tagToExtension[idlTag] if !exists { diff --git a/pkg/generators/openapi.go b/pkg/generators/openapi.go index 0ad5f068d..cbf6dcaf2 100644 --- a/pkg/generators/openapi.go +++ b/pkg/generators/openapi.go @@ -27,6 +27,7 @@ import ( "sort" "strings" + "k8s.io/gengo/v2" "k8s.io/gengo/v2/generator" "k8s.io/gengo/v2/namer" "k8s.io/gengo/v2/types" @@ -57,11 +58,11 @@ var tempPatchTags = [...]string{ } func getOpenAPITagValue(comments []string) []string { - return types.ExtractCommentTags("+", comments)[tagName] + return gengo.ExtractCommentTags("+", comments)[tagName] } func getSingleTagsValue(comments []string, tag string) (string, error) { - tags, ok := types.ExtractCommentTags("+", comments)[tag] + tags, ok := gengo.ExtractCommentTags("+", comments)[tag] if !ok || len(tags) == 0 { return "", nil } @@ -85,9 +86,9 @@ func hasOpenAPITagValue(comments []string, value string) bool { // its comments. If +optional is present it returns true. If +required is present // it returns false. Otherwise, it returns true if `omitempty` JSON tag is present func isOptional(m *types.Member) (bool, error) { - hasOptionalCommentTag := types.ExtractCommentTags( + hasOptionalCommentTag := gengo.ExtractCommentTags( "+", m.CommentLines)[tagOptional] != nil - hasRequiredCommentTag := types.ExtractCommentTags( + hasRequiredCommentTag := gengo.ExtractCommentTags( "+", m.CommentLines)[tagRequired] != nil if hasOptionalCommentTag && hasRequiredCommentTag { return false, fmt.Errorf("member %s cannot be both optional and required", m.Name) diff --git a/pkg/generators/rules/idl_tag.go b/pkg/generators/rules/idl_tag.go index a35a0b222..e4b0f7cd3 100644 --- a/pkg/generators/rules/idl_tag.go +++ b/pkg/generators/rules/idl_tag.go @@ -1,6 +1,7 @@ package rules import ( + "k8s.io/gengo/v2" "k8s.io/gengo/v2/types" ) @@ -24,7 +25,7 @@ func (l *ListTypeMissing) Validate(t *types.Type) ([]string, error) { switch t.Kind { case types.Struct: for _, m := range t.Members { - hasListType := types.ExtractCommentTags("+", m.CommentLines)[ListTypeIDLTag] != nil + hasListType := gengo.ExtractCommentTags("+", m.CommentLines)[ListTypeIDLTag] != nil if m.Name == "Items" && m.Type.Kind == types.Slice && hasNamedMember(t, "ListMeta") { if hasListType { diff --git a/pkg/generators/union.go b/pkg/generators/union.go index afd067280..bfcba1ad7 100644 --- a/pkg/generators/union.go +++ b/pkg/generators/union.go @@ -20,6 +20,7 @@ import ( "fmt" "sort" + "k8s.io/gengo/v2" "k8s.io/gengo/v2/types" ) @@ -141,7 +142,7 @@ func parseEmbeddedUnion(t *types.Type) ([]union, []error) { // embedded types. func parseUnionStruct(t *types.Type) (*union, []error) { errors := []error{} - if types.ExtractCommentTags("+", t.CommentLines)[tagUnionMember] == nil { + if gengo.ExtractCommentTags("+", t.CommentLines)[tagUnionMember] == nil { return nil, nil } @@ -156,11 +157,11 @@ func parseUnionStruct(t *types.Type) (*union, []error) { errors = append(errors, fmt.Errorf("union structures can't have embedded fields: %v.%v", t.Name, m.Name)) continue } - if types.ExtractCommentTags("+", m.CommentLines)[tagUnionDeprecated] != nil { + if gengo.ExtractCommentTags("+", m.CommentLines)[tagUnionDeprecated] != nil { errors = append(errors, fmt.Errorf("union struct can't have unionDeprecated members: %v.%v", t.Name, m.Name)) continue } - if types.ExtractCommentTags("+", m.CommentLines)[tagUnionDiscriminator] != nil { + if gengo.ExtractCommentTags("+", m.CommentLines)[tagUnionDiscriminator] != nil { errors = append(errors, u.setDiscriminator(jsonName)...) } else { if optional, err := isOptional(&m); !optional || err != nil { @@ -186,14 +187,14 @@ func parseUnionMembers(t *types.Type) (*union, []error) { if shouldInlineMembers(&m) { continue } - if types.ExtractCommentTags("+", m.CommentLines)[tagUnionDiscriminator] != nil { + if gengo.ExtractCommentTags("+", m.CommentLines)[tagUnionDiscriminator] != nil { errors = append(errors, u.setDiscriminator(jsonName)...) } - if types.ExtractCommentTags("+", m.CommentLines)[tagUnionMember] != nil { + if gengo.ExtractCommentTags("+", m.CommentLines)[tagUnionMember] != nil { errors = append(errors, fmt.Errorf("union tag is not accepted on struct members: %v.%v", t.Name, m.Name)) continue } - if types.ExtractCommentTags("+", m.CommentLines)[tagUnionDeprecated] != nil { + if gengo.ExtractCommentTags("+", m.CommentLines)[tagUnionDeprecated] != nil { if optional, err := isOptional(&m); !optional || err != nil { errors = append(errors, fmt.Errorf("union members must be optional: %v.%v", t.Name, m.Name)) } From cb8c818e759e2fa0d73f8cf13f1d50955645101c Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Sat, 24 Feb 2024 17:05:33 -0800 Subject: [PATCH 21/24] GolangGenerator -> GoGenerator --- pkg/generators/api_linter.go | 2 +- pkg/generators/openapi.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/generators/api_linter.go b/pkg/generators/api_linter.go index 0a4ff1745..5deff4d5a 100644 --- a/pkg/generators/api_linter.go +++ b/pkg/generators/api_linter.go @@ -94,7 +94,7 @@ func newAPIViolationGen() *apiViolationGen { } type apiViolationGen struct { - generator.GolangGenerator + generator.GoGenerator linter *apiLinter } diff --git a/pkg/generators/openapi.go b/pkg/generators/openapi.go index cbf6dcaf2..f70b6748d 100644 --- a/pkg/generators/openapi.go +++ b/pkg/generators/openapi.go @@ -125,7 +125,7 @@ const ( // openApiGen produces a file with auto-generated OpenAPI functions. type openAPIGen struct { - generator.GolangGenerator + generator.GoGenerator // TargetPackage is the package that will get GetOpenAPIDefinitions function returns all open API definitions. targetPackage string imports namer.ImportTracker @@ -133,7 +133,7 @@ type openAPIGen struct { func newOpenAPIGen(outputFilename string, targetPackage string) generator.Generator { return &openAPIGen{ - GolangGenerator: generator.GolangGenerator{ + GoGenerator: generator.GoGenerator{ OutputFilename: outputFilename, }, imports: generator.NewImportTrackerForPackage(targetPackage), From b9a9bc3efda215e80efe28641d3cd07c097722f6 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Mon, 26 Feb 2024 10:45:04 -0800 Subject: [PATCH 22/24] Run go get k8s.io/gengo/v2 --- go.mod | 14 ++++++------ go.sum | 47 ++++++++++++--------------------------- test/integration/go.mod | 14 ++++++------ test/integration/go.sum | 49 ++++++++++++----------------------------- 4 files changed, 42 insertions(+), 82 deletions(-) diff --git a/go.mod b/go.mod index 1f7b6c933..c18b21c28 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module k8s.io/kube-openapi -go 1.21 +go 1.21.3 require ( github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 @@ -21,7 +21,7 @@ require ( google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 + k8s.io/gengo/v2 v2.0.0-20240226174109-00c4be8627da k8s.io/klog/v2 v2.80.1 k8s.io/utils v0.0.0-20230726121419-3b25d923346b sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd @@ -39,10 +39,10 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/tools v0.4.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.16.1 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect ) diff --git a/go.sum b/go.sum index 03cbef686..aa0030141 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -22,7 +21,6 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -34,7 +32,6 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -66,32 +63,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= @@ -100,7 +83,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -109,9 +91,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/gengo/v2 v2.0.0-20240226174109-00c4be8627da h1:TthpcphFcSU/2R2/j67duxXOSRdUGP2ZOAG4TyGgz5c= +k8s.io/gengo/v2 v2.0.0-20240226174109-00c4be8627da/go.mod h1:5177teI4XU3cmd0ZSDKF3jxMubfjilA5FNOegKTCgK4= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= diff --git a/test/integration/go.mod b/test/integration/go.mod index bc30f6e81..155d68db5 100644 --- a/test/integration/go.mod +++ b/test/integration/go.mod @@ -1,6 +1,6 @@ module k8s.io/kube-openapi/test/integration -go 1.21 +go 1.21.3 require ( github.com/emicklei/go-restful/v3 v3.8.0 @@ -26,15 +26,15 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/tools v0.4.0 // indirect + golang.org/x/mod v0.15.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.18.0 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect + k8s.io/gengo/v2 v2.0.0-20240226174109-00c4be8627da // indirect k8s.io/klog/v2 v2.80.1 // indirect ) diff --git a/test/integration/go.sum b/test/integration/go.sum index 37bc83f63..e244b0643 100644 --- a/test/integration/go.sum +++ b/test/integration/go.sum @@ -8,7 +8,6 @@ github.com/getkin/kin-openapi v0.76.0 h1:j77zg3Ec+k+r+GA3d8hBoXpAc6KX9TbBPrwQGBI github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -24,7 +23,6 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -36,7 +34,6 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -69,32 +66,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= @@ -104,24 +87,20 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/gengo/v2 v2.0.0-20240226174109-00c4be8627da h1:TthpcphFcSU/2R2/j67duxXOSRdUGP2ZOAG4TyGgz5c= +k8s.io/gengo/v2 v2.0.0-20240226174109-00c4be8627da/go.mod h1:5177teI4XU3cmd0ZSDKF3jxMubfjilA5FNOegKTCgK4= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From 571c24bc17707249eac2ac428f23e079943b441d Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Sun, 25 Feb 2024 14:55:27 -0800 Subject: [PATCH 23/24] Fix pkg/generators/openapi_test w/ packagestest The changes appear large but are mostly mechanical. Understand one and you pretty much understand them all. --- go.mod | 8 +- go.sum | 20 +- pkg/generators/openapi_test.go | 2580 +++++++++++++++++++------------- 3 files changed, 1535 insertions(+), 1073 deletions(-) diff --git a/go.mod b/go.mod index c18b21c28..ead437565 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/onsi/gomega v1.19.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.1 + golang.org/x/tools v0.18.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 @@ -39,10 +40,9 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/mod v0.15.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.16.1 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect ) diff --git a/go.sum b/go.sum index aa0030141..295b62b0a 100644 --- a/go.sum +++ b/go.sum @@ -63,18 +63,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= diff --git a/pkg/generators/openapi_test.go b/pkg/generators/openapi_test.go index 2982d13b8..82b321969 100644 --- a/pkg/generators/openapi_test.go +++ b/pkg/generators/openapi_test.go @@ -19,48 +19,38 @@ package generators import ( "bytes" "fmt" + "go/format" "path/filepath" "strings" "testing" - "go/format" - - "github.com/stretchr/testify/assert" + "github.com/google/go-cmp/cmp" + "golang.org/x/tools/go/packages" + "golang.org/x/tools/go/packages/packagestest" "k8s.io/gengo/v2/generator" "k8s.io/gengo/v2/namer" "k8s.io/gengo/v2/parser" "k8s.io/gengo/v2/types" ) -func construct(t *testing.T, files map[string]string, testNamer namer.Namer) (*parser.Builder, types.Universe, []*types.Type) { - b := parser.New() - for name, src := range files { - if err := b.AddFileForTest(filepath.Dir(name), name, []byte(src)); err != nil { - t.Fatal(err) - } +func construct(t *testing.T, cfg *packages.Config, nameSystems namer.NameSystems, defaultSystem string, pkg string) *generator.Context { + p := parser.New() + if err := p.LoadPackagesWithConfigForTesting(cfg, pkg); err != nil { + t.Fatalf("failed to load package: %v", err) } - u, err := b.FindTypes() + c, err := generator.NewContext(p, nameSystems, defaultSystem) if err != nil { - t.Fatal(err) + t.Fatalf("failed to make a context: %v", err) } - orderer := namer.Orderer{Namer: testNamer} - o := orderer.OrderUniverse(u) - return b, u, o + return c } -func testOpenAPITypeWriter(t *testing.T, code string) (error, error, *assert.Assertions, *bytes.Buffer, *bytes.Buffer, []string) { - return testOpenAPITypeWriterWithFiles(t, code, nil) -} - -func testOpenAPITypeWriterWithFiles(t *testing.T, code string, testFiles map[string]string) (error, error, *assert.Assertions, *bytes.Buffer, *bytes.Buffer, []string) { - assert := assert.New(t) - if testFiles == nil { - testFiles = map[string]string{} - } - testFiles["base/foo/bar.go"] = code - outputPackage := "base/output" - imports := generator.NewImportTrackerForPackage(outputPackage) - rawNamer := namer.NewRawNamer(outputPackage, imports) +func testOpenAPITypeWriter(t *testing.T, cfg *packages.Config) (error, error, *bytes.Buffer, *bytes.Buffer, []string) { + pkgBase := "example.com/base" + inputPkg := filepath.Join(pkgBase, "foo") + outputPkg := filepath.Join(pkgBase, "output") + imports := generator.NewImportTrackerForPackage(outputPkg) + rawNamer := namer.NewRawNamer(outputPkg, imports) namers := namer.NameSystems{ "raw": rawNamer, "private": &namer.NameStrategy{ @@ -70,12 +60,9 @@ func testOpenAPITypeWriterWithFiles(t *testing.T, code string, testFiles map[str PrependPackageNames: 4, // enough to fully qualify from k8s.io/api/... }, } - builder, universe, _ := construct(t, testFiles, rawNamer) - context, err := generator.NewContext(builder, namers, "raw") - if err != nil { - t.Fatal(err) - } - blahT := universe.Type(types.Name{Package: "base/foo", Name: "Blah"}) + context := construct(t, cfg, namers, "raw", inputPkg) + universe := context.Universe + blahT := universe.Type(types.Name{Package: inputPkg, Name: "Blah"}) callBuffer := &bytes.Buffer{} callSW := generator.NewSnippetWriter(callBuffer, context, "$", "$") @@ -85,83 +72,106 @@ func testOpenAPITypeWriterWithFiles(t *testing.T, code string, testFiles map[str funcSW := generator.NewSnippetWriter(funcBuffer, context, "$", "$") funcError := newOpenAPITypeWriter(funcSW, context).generate(blahT) - return callError, funcError, assert, callBuffer, funcBuffer, imports.ImportLines() + return callError, funcError, callBuffer, funcBuffer, imports.ImportLines() } -func TestSimple(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo - -// Blah is a test. -// +k8s:openapi-gen=true -// +k8s:openapi-gen=x-kubernetes-type-tag:type_test -type Blah struct { - // A simple string - String string - // A simple int - Int int `+"`"+`json:",omitempty"`+"`"+` - // An int considered string simple int - IntString int `+"`"+`json:",string"`+"`"+` - // A simple int64 - Int64 int64 - // A simple int32 - Int32 int32 - // A simple int16 - Int16 int16 - // A simple int8 - Int8 int8 - // A simple int - Uint uint - // A simple int64 - Uint64 uint64 - // A simple int32 - Uint32 uint32 - // A simple int16 - Uint16 uint16 - // A simple int8 - Uint8 uint8 - // A simple byte - Byte byte - // A simple boolean - Bool bool - // A simple float64 - Float64 float64 - // A simple float32 - Float32 float32 - // a base64 encoded characters - ByteArray []byte - // a member with an extension - // +k8s:openapi-gen=x-kubernetes-member-tag:member_test - WithExtension string - // a member with struct tag as extension - // +patchStrategy=merge - // +patchMergeKey=pmk - WithStructTagExtension string `+"`"+`patchStrategy:"merge" patchMergeKey:"pmk"`+"`"+` - // a member with a list type - // +listType=atomic - // +default=["foo", "bar"] - WithListType []string - // a member with a map type - // +listType=atomic - // +default={"foo": "bar", "fizz": "buzz"} - Map map[string]string - // a member with a string pointer - // +default="foo" - StringPointer *string - // an int member with a default - // +default=1 - OmittedInt int `+"`"+`json:"omitted,omitempty"`+"`"+` -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) +// NOTE: the usual order of arguments for an assertion would be want, got, but +// this helper function flips that in favor of callsite readability. +func assertEqual(t *testing.T, got, want string) { + t.Helper() + want = strings.TrimSpace(want) + got = strings.TrimSpace(got) + if !cmp.Equal(want, got) { + t.Errorf("Wrong result:\n%s", cmp.Diff(want, got)) } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { +} + +func TestSimple(t *testing.T) { + inputFile := ` + package foo + + // Blah is a test. + // +k8s:openapi-gen=true + // +k8s:openapi-gen=x-kubernetes-type-tag:type_test + type Blah struct { + // A simple string + String string + // A simple int + Int int ` + "`" + `json:",omitempty"` + "`" + ` + // An int considered string simple int + IntString int ` + "`" + `json:",string"` + "`" + ` + // A simple int64 + Int64 int64 + // A simple int32 + Int32 int32 + // A simple int16 + Int16 int16 + // A simple int8 + Int8 int8 + // A simple int + Uint uint + // A simple int64 + Uint64 uint64 + // A simple int32 + Uint32 uint32 + // A simple int16 + Uint16 uint16 + // A simple int8 + Uint8 uint8 + // A simple byte + Byte byte + // A simple boolean + Bool bool + // A simple float64 + Float64 float64 + // A simple float32 + Float32 float32 + // a base64 encoded characters + ByteArray []byte + // a member with an extension + // +k8s:openapi-gen=x-kubernetes-member-tag:member_test + WithExtension string + // a member with struct tag as extension + // +patchStrategy=merge + // +patchMergeKey=pmk + WithStructTagExtension string ` + "`" + `patchStrategy:"merge" patchMergeKey:"pmk"` + "`" + ` + // a member with a list type + // +listType=atomic + // +default=["foo", "bar"] + WithListType []string + // a member with a map type + // +listType=atomic + // +default={"foo": "bar", "fizz": "buzz"} + Map map[string]string + // a member with a string pointer + // +default="foo" + StringPointer *string + // an int member with a default + // +default=1 + OmittedInt int ` + "`" + `json:"omitted,omitempty"` + "`" + ` + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -383,28 +393,38 @@ Extensions: spec.Extensions{ }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestEmptyProperties(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Blah demonstrate a struct without fields. -type Blah struct { -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Blah demonstrate a struct without fields. + type Blah struct { + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -413,36 +433,46 @@ Type: []string{"object"}, }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestNestedStruct(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Nested is used as struct field -type Nested struct { - // A simple string - String string -} + // Nested is used as struct field + type Nested struct { + // A simple string + String string + } -// Blah demonstrate a struct with struct field. -type Blah struct { - // A struct field - Field Nested -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Blah demonstrate a struct with struct field. + type Blah struct { + // A struct field + Field Nested + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -453,7 +483,7 @@ Properties: map[string]spec.Schema{ SchemaProps: spec.SchemaProps{ Description: "A struct field", Default: map[string]interface {}{}, -Ref: ref("base/foo.Nested"), +Ref: ref("example.com/base/foo.Nested"), }, }, }, @@ -461,38 +491,49 @@ Required: []string{"Field"}, }, }, Dependencies: []string{ -"base/foo.Nested",}, +"example.com/base/foo.Nested",}, } -} - -`, funcBuffer.String()) +}`) + }) } func TestNestedStructPointer(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Nested is used as struct pointer field -type Nested struct { - // A simple string - String string -} + // Nested is used as struct pointer field + type Nested struct { + // A simple string + String string + } -// Blah demonstrate a struct with struct pointer field. -type Blah struct { - // A struct pointer field - Field *Nested -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Blah demonstrate a struct with struct pointer field. + type Blah struct { + // A struct pointer field + Field *Nested + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -502,7 +543,7 @@ Properties: map[string]spec.Schema{ "Field": { SchemaProps: spec.SchemaProps{ Description: "A struct pointer field", -Ref: ref("base/foo.Nested"), +Ref: ref("example.com/base/foo.Nested"), }, }, }, @@ -510,38 +551,48 @@ Required: []string{"Field"}, }, }, Dependencies: []string{ -"base/foo.Nested",}, +"example.com/base/foo.Nested",}, } -} - -`, funcBuffer.String()) +}`) + }) } func TestEmbeddedStruct(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Nested is used as embedded struct field -type Nested struct { - // A simple string - String string -} + // Nested is used as embedded struct field + type Nested struct { + // A simple string + String string + } -// Blah demonstrate a struct with embedded struct field. -type Blah struct { - // An embedded struct field - Nested -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Blah demonstrate a struct with embedded struct field. + type Blah struct { + // An embedded struct field + Nested + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -552,7 +603,7 @@ Properties: map[string]spec.Schema{ SchemaProps: spec.SchemaProps{ Description: "An embedded struct field", Default: map[string]interface {}{}, -Ref: ref("base/foo.Nested"), +Ref: ref("example.com/base/foo.Nested"), }, }, }, @@ -560,41 +611,51 @@ Required: []string{"Nested"}, }, }, Dependencies: []string{ -"base/foo.Nested",}, +"example.com/base/foo.Nested",}, } -} - -`, funcBuffer.String()) +}`) + }) } func TestSingleEmbeddedStruct(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -import "time" + import "time" -// Nested is used as embedded struct field -type Nested struct { - // A simple string - time.Duration -} + // Nested is used as embedded struct field + type Nested struct { + // A simple string + time.Duration + } -// Blah demonstrate a struct with embedded struct field. -type Blah struct { - // An embedded struct field - // +default="10ms" - Nested `+"`"+`json:"nested,omitempty" protobuf:"bytes,5,opt,name=nested"`+"`"+` -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Blah demonstrate a struct with embedded struct field. + type Blah struct { + // An embedded struct field + // +default="10ms" + Nested ` + "`" + `json:"nested,omitempty" protobuf:"bytes,5,opt,name=nested"` + "`" + ` + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -605,45 +666,55 @@ Properties: map[string]spec.Schema{ SchemaProps: spec.SchemaProps{ Description: "An embedded struct field", Default: "10ms", -Ref: ref("base/foo.Nested"), +Ref: ref("example.com/base/foo.Nested"), }, }, }, }, }, Dependencies: []string{ -"base/foo.Nested",}, -} +"example.com/base/foo.Nested",}, } - -`, funcBuffer.String()) +}`) + }) } func TestEmbeddedInlineStruct(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Nested is used as embedded inline struct field -type Nested struct { - // A simple string - String string -} + // Nested is used as embedded inline struct field + type Nested struct { + // A simple string + String string + } -// Blah demonstrate a struct with embedded inline struct field. -type Blah struct { - // An embedded inline struct field - Nested `+"`"+`json:",inline,omitempty"`+"`"+` -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Blah demonstrate a struct with embedded inline struct field. + type Blah struct { + // An embedded inline struct field + Nested ` + "`" + `json:",inline,omitempty"` + "`" + ` + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -663,36 +734,46 @@ Required: []string{"String"}, }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestEmbeddedInlineStructPointer(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Nested is used as embedded inline struct pointer field. -type Nested struct { - // A simple string - String string -} + // Nested is used as embedded inline struct pointer field. + type Nested struct { + // A simple string + String string + } -// Blah demonstrate a struct with embedded inline struct pointer field. -type Blah struct { - // An embedded inline struct pointer field - *Nested `+"`"+`json:",inline,omitempty"`+"`"+` -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Blah demonstrate a struct with embedded inline struct pointer field. + type Blah struct { + // An embedded inline struct pointer field + *Nested ` + "`" + `json:",inline,omitempty"` + "`" + ` + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -712,30 +793,40 @@ Required: []string{"String"}, }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestNestedMapString(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Map sample tests openAPIGen.generateMapProperty method. -type Blah struct { - // A sample String to String map - StringToArray map[string]map[string]string -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Map sample tests openAPIGen.generateMapProperty method. + type Blah struct { + // A sample String to String map + StringToArray map[string]map[string]string + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -771,30 +862,40 @@ Required: []string{"StringToArray"}, }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestNestedMapInt(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Map sample tests openAPIGen.generateMapProperty method. -type Blah struct { - // A sample String to String map - StringToArray map[string]map[string]int -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Map sample tests openAPIGen.generateMapProperty method. + type Blah struct { + // A sample String to String map + StringToArray map[string]map[string]int + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -830,30 +931,40 @@ Required: []string{"StringToArray"}, }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestNestedMapBoolean(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Map sample tests openAPIGen.generateMapProperty method. -type Blah struct { - // A sample String to String map - StringToArray map[string]map[string]bool -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // Map sample tests openAPIGen.generateMapProperty method. + type Blah struct { + // A sample String to String map + StringToArray map[string]map[string]bool + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -889,229 +1000,331 @@ Required: []string{"StringToArray"}, }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestFailingSample1(t *testing.T) { - _, funcErr, assert, _, _, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Map sample tests openAPIGen.generateMapProperty method. -type Blah struct { - // A sample String to String map - StringToArray map[string]map[string]map[int]string -} - `) - if assert.Error(funcErr, "An error was expected") { - assert.Equal(funcErr, fmt.Errorf("failed to generate map property in base/foo.Blah: StringToArray: map with non-string keys are not supported by OpenAPI in map[int]string")) - } + // Map sample tests openAPIGen.generateMapProperty method. + type Blah struct { + // A sample String to String map + StringToArray map[string]map[string]map[int]string + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + _, funcErr, _, _, _ := testOpenAPITypeWriter(t, e.Config) + if funcErr == nil { + t.Fatalf("An error was expected") + } + assertEqual(t, + "failed to generate map property in example.com/base/foo.Blah: StringToArray: map with non-string keys are not supported by OpenAPI in map[int]string", + funcErr.Error()) + }) } func TestFailingSample2(t *testing.T) { - _, funcErr, assert, _, _, _ := testOpenAPITypeWriter(t, ` -package foo - -// Map sample tests openAPIGen.generateMapProperty method. -type Blah struct { - // A sample String to String map - StringToArray map[int]string -} `) - if assert.Error(funcErr, "An error was expected") { - assert.Equal(funcErr, fmt.Errorf("failed to generate map property in base/foo.Blah: StringToArray: map with non-string keys are not supported by OpenAPI in map[int]string")) - } + inputFile := ` + package foo + + // Map sample tests openAPIGen.generateMapProperty method. + type Blah struct { + // A sample String to String map + StringToArray map[int]string + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + _, funcErr, _, _, _ := testOpenAPITypeWriter(t, e.Config) + if funcErr == nil { + t.Fatalf("An error was expected") + } + assertEqual(t, + "failed to generate map property in example.com/base/foo.Blah: StringToArray: map with non-string keys are not supported by OpenAPI in map[int]string", + funcErr.Error()) + }) } func TestFailingDefaultEnforced(t *testing.T) { tests := []struct { definition string - expectedError error - }{ - { - definition: ` -package foo - -type Blah struct { - // +default=5 - Int int -} `, - expectedError: fmt.Errorf("failed to generate default in base/foo.Blah: Int: invalid default value (5) for non-pointer/non-omitempty. If specified, must be: 0"), - }, - { - definition: ` -package foo - -type Blah struct { - // +default={"foo": 5} - Struct struct{ - foo int - } -} `, - expectedError: fmt.Errorf(`failed to generate default in base/foo.Blah: Struct: invalid default value (map[string]interface {}{"foo":5}) for non-pointer/non-omitempty. If specified, must be: {}`), - }, - { - definition: ` -package foo + expectedError string + }{{ + definition: ` + package foo + + type Blah struct { + // +default=5 + Int int + }`, + expectedError: "failed to generate default in example.com/base/foo.Blah: Int: invalid default value (5) for non-pointer/non-omitempty. If specified, must be: 0", + }, { + definition: ` + package foo + + type Blah struct { + // +default={"foo": 5} + Struct struct{ + foo int + } + }`, + expectedError: `failed to generate default in example.com/base/foo.Blah: Struct: invalid default value (map[string]interface {}{"foo":5}) for non-pointer/non-omitempty. If specified, must be: {}`, + }, { + definition: ` + package foo + + type Blah struct { + List []Item -type Blah struct { - List []Item + } -} + // +default="foo" + type Item string`, + expectedError: `failed to generate slice property in example.com/base/foo.Blah: List: invalid default value ("foo") for non-pointer/non-omitempty. If specified, must be: ""`, + }, { + definition: ` + package foo -// +default="foo" -type Item string `, - expectedError: fmt.Errorf(`failed to generate slice property in base/foo.Blah: List: invalid default value ("foo") for non-pointer/non-omitempty. If specified, must be: ""`), - }, - { - definition: ` -package foo + type Blah struct { + Map map[string]Item -type Blah struct { - Map map[string]Item + } -} - -// +default="foo" -type Item string `, - expectedError: fmt.Errorf(`failed to generate map property in base/foo.Blah: Map: invalid default value ("foo") for non-pointer/non-omitempty. If specified, must be: ""`), - }, - } + // +default="foo" + type Item string`, + expectedError: `failed to generate map property in example.com/base/foo.Blah: Map: invalid default value ("foo") for non-pointer/non-omitempty. If specified, must be: ""`, + }} for i, test := range tests { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - _, funcErr, assert, _, _, _ := testOpenAPITypeWriter(t, test.definition) - if assert.Error(funcErr, "An error was expected") { - assert.Equal(funcErr, test.expectedError) - } + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": test.definition, + }, + }}) + defer e.Cleanup() + + _, funcErr, _, _, _ := testOpenAPITypeWriter(t, e.Config) + if funcErr == nil { + t.Fatalf("An error was expected") + } + assertEqual(t, test.expectedError, funcErr.Error()) + }) }) } } func TestCustomDef(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -import openapi "k8s.io/kube-openapi/pkg/common" + import openapi "k8s.io/kube-openapi/pkg/common" -type Blah struct { -} + type Blah struct { + } -func (_ Blah) OpenAPIDefinition() openapi.OpenAPIDefinition { - return openapi.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "date-time", + func (_ Blah) OpenAPIDefinition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "date-time", + }, + }, + } + }` + commonFile := `package common + + type OpenAPIDefinition struct {}` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, }, - }, - } -} -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": foo.Blah{}.OpenAPIDefinition(), -`, callBuffer.String()) - assert.Equal(``, funcBuffer.String()) + }, { + Name: "k8s.io/kube-openapi/pkg/common", + Files: map[string]interface{}{ + "common.go": commonFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": foo.Blah{}.OpenAPIDefinition(),`) + assertEqual(t, "", funcBuffer.String()) + }) } func TestCustomDefV3(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -import openapi "k8s.io/kube-openapi/pkg/common" + import openapi "k8s.io/kube-openapi/pkg/common" -type Blah struct { -} + type Blah struct { + } -func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { - return openapi.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "date-time", + func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "date-time", + }, + }, + } + }` + commonFile := `package common + + type OpenAPIDefinition struct {}` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, }, - }, - } -} -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": foo.Blah{}.OpenAPIV3Definition(), -`, callBuffer.String()) - assert.Equal(``, funcBuffer.String()) + }, { + Name: "k8s.io/kube-openapi/pkg/common", + Files: map[string]interface{}{ + "common.go": commonFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": foo.Blah{}.OpenAPIV3Definition(),`) + assertEqual(t, "", funcBuffer.String()) + }) } func TestCustomDefV2AndV3(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -import openapi "k8s.io/kube-openapi/pkg/common" + import openapi "k8s.io/kube-openapi/pkg/common" -type Blah struct { -} + type Blah struct { + } -func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { - return openapi.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "date-time", - }, - }, - } -} + func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "date-time", + }, + }, + } + } -func (_ Blah) OpenAPIDefinition() openapi.OpenAPIDefinition { - return openapi.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "date-time", + func (_ Blah) OpenAPIDefinition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "date-time", + }, + }, + } + }` + commonFile := `package common + + type OpenAPIDefinition struct {}` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, }, - }, - } -} -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": common.EmbedOpenAPIDefinitionIntoV2Extension(foo.Blah{}.OpenAPIV3Definition(), foo.Blah{}.OpenAPIDefinition()), -`, callBuffer.String()) - assert.Equal(``, funcBuffer.String()) + }, { + Name: "k8s.io/kube-openapi/pkg/common", + Files: map[string]interface{}{ + "common.go": commonFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": common.EmbedOpenAPIDefinitionIntoV2Extension(foo.Blah{}.OpenAPIV3Definition(), foo.Blah{}.OpenAPIDefinition()),`) + assertEqual(t, "", funcBuffer.String()) + }) } func TestCustomDefs(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Blah is a custom type -type Blah struct { -} + // Blah is a custom type + type Blah struct { + } -func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } -func (_ Blah) OpenAPISchemaFormat() string { return "date-time" } -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } + func (_ Blah) OpenAPISchemaFormat() string { return "date-time" }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1121,44 +1334,62 @@ Format:foo.Blah{}.OpenAPISchemaFormat(), }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestCustomDefsV3(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -import openapi "k8s.io/kube-openapi/pkg/common" + import openapi "k8s.io/kube-openapi/pkg/common" -// Blah is a custom type -type Blah struct { -} + // Blah is a custom type + type Blah struct { + } -func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { - return openapi.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "date-time", + func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "date-time", + }, + }, + } + } + + func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } + func (_ Blah) OpenAPISchemaFormat() string { return "date-time" }` + commonFile := `package common + + type OpenAPIDefinition struct {}` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, }, - }, - } -} + }, { + Name: "k8s.io/kube-openapi/pkg/common", + Files: map[string]interface{}{ + "common.go": commonFile, + }, + }}) + defer e.Cleanup() -func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } -func (_ Blah) OpenAPISchemaFormat() string { return "date-time" } -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.EmbedOpenAPIDefinitionIntoV2Extension(foo.Blah{}.OpenAPIV3Definition(), common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1168,33 +1399,42 @@ Format:foo.Blah{}.OpenAPISchemaFormat(), }, }, }) -} - -`, funcBuffer.String()) +}`) + }) } func TestV3OneOfTypes(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// Blah is a custom type -type Blah struct { -} + // Blah is a custom type + type Blah struct { + } -func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } -func (_ Blah) OpenAPISchemaFormat() string { return "date-time" } -func (_ Blah) OpenAPIV3OneOfTypes() []string { return []string{"string", "number"} } + func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } + func (_ Blah) OpenAPISchemaFormat() string { return "date-time" } + func (_ Blah) OpenAPIV3OneOfTypes() []string { return []string{"string", "number"} }` -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.EmbedOpenAPIDefinitionIntoV2Extension(common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1212,36 +1452,45 @@ Format:foo.Blah{}.OpenAPISchemaFormat(), }, }, }) +}`) + }) } -`, funcBuffer.String()) -} +func TestPointer(t *testing.T) { + inputFile := ` + package foo + + // PointerSample demonstrate pointer's properties + type Blah struct { + // A string pointer + StringPointer *string + // A struct pointer + StructPointer *Blah + // A slice pointer + SlicePointer *[]string + // A map pointer + MapPointer *map[string]string + }` + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() -func TestPointer(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo - -// PointerSample demonstrate pointer's properties -type Blah struct { - // A string pointer - StringPointer *string - // A struct pointer - StructPointer *Blah - // A slice pointer - SlicePointer *[]string - // A map pointer - MapPointer *map[string]string -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1258,7 +1507,7 @@ Format: "", "StructPointer": { SchemaProps: spec.SchemaProps{ Description: "A struct pointer", -Ref: ref("base/foo.Blah"), +Ref: ref("example.com/base/foo.Blah"), }, }, "SlicePointer": { @@ -1297,34 +1546,43 @@ Required: []string{"StringPointer","StructPointer","SlicePointer","MapPointer"}, }, }, Dependencies: []string{ -"base/foo.Blah",}, +"example.com/base/foo.Blah",}, } -} - -`, funcBuffer.String()) +}`) + }) } func TestNestedLists(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo - -// Blah is a test. -// +k8s:openapi-gen=true -// +k8s:openapi-gen=x-kubernetes-type-tag:type_test -type Blah struct { - // Nested list - NestedList [][]int64 -} -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + inputFile := ` + package foo + + // Blah is a test. + // +k8s:openapi-gen=true + // +k8s:openapi-gen=x-kubernetes-type-tag:type_test + type Blah struct { + // Nested list + NestedList [][]int64 + }` + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1363,32 +1621,41 @@ Extensions: spec.Extensions{ }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestNestListOfMaps(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo - -// Blah is a test. -// +k8s:openapi-gen=true -// +k8s:openapi-gen=x-kubernetes-type-tag:type_test -type Blah struct { - // Nested list of maps - NestedListOfMaps [][]map[string]string -} -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + inputFile := ` + package foo + + // Blah is a test. + // +k8s:openapi-gen=true + // +k8s:openapi-gen=x-kubernetes-type-tag:type_test + type Blah struct { + // Nested list of maps + NestedListOfMaps [][]map[string]string + }` + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1435,40 +1702,49 @@ Extensions: spec.Extensions{ }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestExtensions(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo - -// Blah is a test. -// +k8s:openapi-gen=true -// +k8s:openapi-gen=x-kubernetes-type-tag:type_test -type Blah struct { - // a member with a list type with two map keys - // +listType=map - // +listMapKey=port - // +listMapKey=protocol - WithListField []string - - // another member with a list type with one map key - // +listType=map - // +listMapKey=port - WithListField2 []string -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + inputFile := ` + package foo + + // Blah is a test. + // +k8s:openapi-gen=true + // +k8s:openapi-gen=x-kubernetes-type-tag:type_test + type Blah struct { + // a member with a list type with two map keys + // +listType=map + // +listMapKey=port + // +listMapKey=protocol + WithListField []string + + // another member with a list type with one map key + // +listType=map + // +listMapKey=port + WithListField2 []string + }` + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1532,39 +1808,48 @@ Extensions: spec.Extensions{ }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestUnion(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo - -// Blah is a test. -// +k8s:openapi-gen=true -// +k8s:openapi-gen=x-kubernetes-type-tag:type_test -// +union -type Blah struct { - // +unionDiscriminator - Discriminator *string `+"`"+`json:"discriminator"`+"`"+` - // +optional - Numeric int `+"`"+`json:"numeric"`+"`"+` - // +optional - String string `+"`"+`json:"string"`+"`"+` - // +optional - Float float64 `+"`"+`json:"float"`+"`"+` -} - `) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + inputFile := ` + package foo + + // Blah is a test. + // +k8s:openapi-gen=true + // +k8s:openapi-gen=x-kubernetes-type-tag:type_test + // +union + type Blah struct { + // +unionDiscriminator + Discriminator *string ` + "`" + `json:"discriminator"` + "`" + ` + // +optional + Numeric int ` + "`" + `json:"numeric"` + "`" + ` + // +optional + String string ` + "`" + `json:"string"` + "`" + ` + // +optional + Float float64 ` + "`" + `json:"float"` + "`" + ` + }` + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1618,54 +1903,66 @@ map[string]interface{}{ }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestEnumAlias(t *testing.T) { - callErr, funcErr, assert, _, funcBuffer, _ := testOpenAPITypeWriterWithFiles(t, ` - package foo + inputFile := ` + package foo - import "base/bar" - - // EnumType is the enumType. - // +enum - type EnumType = bar.EnumType - - // EnumA is a. - const EnumA EnumType = bar.EnumA - // EnumB is b. - const EnumB EnumType = bar.EnumB - - // Blah is a test. - // +k8s:openapi-gen=true - type Blah struct { - // Value is the value. - Value EnumType - } + import "example.com/base/bar" - `, map[string]string{"base/bar/foo.go": ` - package bar - - // EnumType is the enumType. - // +enum - type EnumType string - - // EnumA is a. - const EnumA EnumType = "a" - // EnumB is b. - const EnumB EnumType = "b" - `}) - - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - _ = assert - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // EnumType is the enumType. + // +enum + type EnumType = bar.EnumType + + // EnumA is a. + const EnumA EnumType = bar.EnumA + // EnumB is b. + const EnumB EnumType = bar.EnumB + + // Blah is a test. + // +k8s:openapi-gen=true + type Blah struct { + // Value is the value. + Value EnumType + }` + otherFile := ` + package bar + + // EnumType is the enumType. + // +enum + type EnumType string + + // EnumA is a. + const EnumA EnumType = "a" + // EnumB is b. + const EnumB EnumType = "b"` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }, { + Name: "example.com/base/bar", + Files: map[string]interface{}{ + "bar.go": otherFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, _, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1674,7 +1971,7 @@ Type: []string{"object"}, Properties: map[string]spec.Schema{ "Value": { SchemaProps: spec.SchemaProps{`+"\n"+ - "Description: \"Value is the value.\\n\\nPossible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` + "Description: \"Value is the value.\\n\\nPossible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` Default: "", Type: []string{"string"}, Format: "", @@ -1686,45 +1983,54 @@ Required: []string{"Value"}, }, }, } +}`) + }) } -`, funcBuffer.String()) +func TestEnum(t *testing.T) { + inputFile := ` + package foo -} + // EnumType is the enumType. + // +enum + type EnumType string -func TestEnum(t *testing.T) { - callErr, funcErr, assert, _, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo - -// EnumType is the enumType. -// +enum -type EnumType string - -// EnumA is a. -const EnumA EnumType = "a" -// EnumB is b. -const EnumB EnumType = "b" - -// Blah is a test. -// +k8s:openapi-gen=true -// +k8s:openapi-gen=x-kubernetes-type-tag:type_test -type Blah struct { - // Value is the value. - Value EnumType - NoCommentEnum EnumType - // +optional - OptionalEnum *EnumType - List []EnumType - Map map[string]EnumType -}`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - _ = assert - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // EnumA is a. + const EnumA EnumType = "a" + // EnumB is b. + const EnumB EnumType = "b" + + // Blah is a test. + // +k8s:openapi-gen=true + // +k8s:openapi-gen=x-kubernetes-type-tag:type_test + type Blah struct { + // Value is the value. + Value EnumType + NoCommentEnum EnumType + // +optional + OptionalEnum *EnumType + List []EnumType + Map map[string]EnumType + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, _, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1733,7 +2039,7 @@ Type: []string{"object"}, Properties: map[string]spec.Schema{ "Value": { SchemaProps: spec.SchemaProps{`+"\n"+ - "Description: \"Value is the value.\\n\\nPossible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` + "Description: \"Value is the value.\\n\\nPossible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` Default: "", Type: []string{"string"}, Format: "", @@ -1742,7 +2048,7 @@ Enum: []interface{}{"a", "b"}, }, "NoCommentEnum": { SchemaProps: spec.SchemaProps{`+"\n"+ - "Description: \"Possible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` + "Description: \"Possible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` Default: "", Type: []string{"string"}, Format: "", @@ -1751,7 +2057,7 @@ Enum: []interface{}{"a", "b"}, }, "OptionalEnum": { SchemaProps: spec.SchemaProps{`+"\n"+ - "Description: \"Possible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` + "Description: \"Possible enum values:\\n - `\\\"a\\\"` is a.\\n - `\\\"b\\\"` is b.\","+` Type: []string{"string"}, Format: "", Enum: []interface{}{"a", "b"}, @@ -1798,48 +2104,69 @@ Extensions: spec.Extensions{ }, }, } -} - -`, funcBuffer.String()) +}`) + }) } func TestSymbolReference(t *testing.T) { - callErr, funcErr, assert, _, funcBuffer, imports := testOpenAPITypeWriter(t, ` -package foo - -// +k8s:openapi-gen=true -type Blah struct { - // +default="A Default Value" - // +optional - Value *string - - // User constant local to the output package fully qualified - // +default=ref(base/output.MyConst) - // +optional - FullyQualifiedOutputValue *string - - // Local to types but not to output - // +default=ref(MyConst) - // +optional - LocalValue *string - - // +default=ref(base/foo.MyConst) - // +optional - FullyQualifiedLocalValue *string - - // +default=ref(k8s.io/api/v1.TerminationPathDefault) - // +optional - FullyQualifiedExternalValue *string -} - `) - assert.NoError(funcErr) - assert.NoError(callErr) - assert.ElementsMatch(imports, []string{`foo "base/foo"`, `v1 "k8s.io/api/v1"`, `common "k8s.io/kube-openapi/pkg/common"`, `spec "k8s.io/kube-openapi/pkg/validation/spec"`}) - - if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { - t.Fatal(err) - } else { - assert.Equal(string(formatted), `func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + inputFile := ` + package foo + + // +k8s:openapi-gen=true + type Blah struct { + // +default="A Default Value" + // +optional + Value *string + + // User constant local to the output package fully qualified + // +default=ref(example.com/base/output.MyConst) + // +optional + FullyQualifiedOutputValue *string + + // Local to types but not to output + // +default=ref(MyConst) + // +optional + LocalValue *string + + // +default=ref(example.com/base/foo.MyConst) + // +optional + FullyQualifiedLocalValue *string + + // +default=ref(k8s.io/api/v1.TerminationPathDefault) + // +optional + FullyQualifiedExternalValue *string + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, _, funcBuffer, imports := testOpenAPITypeWriter(t, e.Config) + if funcErr != nil { + t.Fatalf("Unexpected funcErr: %v", funcErr) + } + if callErr != nil { + t.Fatalf("Unexpected callErr: %v", callErr) + } + expImports := []string{ + `foo "example.com/base/foo"`, + `v1 "k8s.io/api/v1"`, + `common "k8s.io/kube-openapi/pkg/common"`, + `spec "k8s.io/kube-openapi/pkg/validation/spec"`, + } + if !cmp.Equal(imports, expImports) { + t.Errorf("wrong imports:\n%s", cmp.Diff(expImports, imports)) + } + + if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { + t.Fatal(err) + } else { + assertEqual(t, string(formatted), `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1886,81 +2213,100 @@ type Blah struct { }, }, } -} - -`) - } - +}`) + } + }) } // Show that types with unmarshalJSON in their hierarchy do not have struct // defaults enforced, and that aliases and embededd types are respected func TestMustEnforceDefaultStruct(t *testing.T) { - callErr, funcErr, assert, _, funcBuffer, imports := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -type Time struct { - value interface{} -} + type Time struct { + value interface{} + } -type TimeWithoutUnmarshal struct { - value interface{} -} + type TimeWithoutUnmarshal struct { + value interface{} + } -func (_ TimeWithoutUnmarshal) OpenAPISchemaType() []string { return []string{"string"} } -func (_ TimeWithoutUnmarshal) OpenAPISchemaFormat() string { return "date-time" } + func (_ TimeWithoutUnmarshal) OpenAPISchemaType() []string { return []string{"string"} } + func (_ TimeWithoutUnmarshal) OpenAPISchemaFormat() string { return "date-time" } -func (_ Time) UnmarshalJSON([]byte) error { - return nil -} + func (_ Time) UnmarshalJSON([]byte) error { + return nil + } -func (_ Time) OpenAPISchemaType() []string { return []string{"string"} } -func (_ Time) OpenAPISchemaFormat() string { return "date-time" } + func (_ Time) OpenAPISchemaType() []string { return []string{"string"} } + func (_ Time) OpenAPISchemaFormat() string { return "date-time" } -// Time with UnmarshalJSON defined on pointer instead of struct -type MicroTime struct { - value interface{} -} + // Time with UnmarshalJSON defined on pointer instead of struct + type MicroTime struct { + value interface{} + } -func (t *MicroTime) UnmarshalJSON([]byte) error { - return nil -} + func (t *MicroTime) UnmarshalJSON([]byte) error { + return nil + } -func (_ MicroTime) OpenAPISchemaType() []string { return []string{"string"} } -func (_ MicroTime) OpenAPISchemaFormat() string { return "date-time" } + func (_ MicroTime) OpenAPISchemaType() []string { return []string{"string"} } + func (_ MicroTime) OpenAPISchemaFormat() string { return "date-time" } -type Int64 int64 + type Int64 int64 -type Duration struct { - Int64 -} + type Duration struct { + Int64 + } -func (_ Duration) OpenAPISchemaType() []string { return []string{"string"} } -func (_ Duration) OpenAPISchemaFormat() string { return "" } + func (_ Duration) OpenAPISchemaType() []string { return []string{"string"} } + func (_ Duration) OpenAPISchemaFormat() string { return "" } -type NothingSpecial struct { - Field string -} + type NothingSpecial struct { + Field string + } -// +k8s:openapi-gen=true -type Blah struct { - Embedded Duration - PointerUnmarshal MicroTime - StructUnmarshal Time - NoUnmarshal TimeWithoutUnmarshal - Regular NothingSpecial -} - `) - assert.NoError(funcErr) - assert.NoError(callErr) - assert.ElementsMatch(imports, []string{`foo "base/foo"`, `common "k8s.io/kube-openapi/pkg/common"`, `spec "k8s.io/kube-openapi/pkg/validation/spec"`}) - - if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { - t.Fatal(err) - } else { - assert.Equal(string(formatted), `func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + // +k8s:openapi-gen=true + type Blah struct { + Embedded Duration + PointerUnmarshal MicroTime + StructUnmarshal Time + NoUnmarshal TimeWithoutUnmarshal + Regular NothingSpecial + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, _, funcBuffer, imports := testOpenAPITypeWriter(t, e.Config) + if funcErr != nil { + t.Fatalf("Unexpected funcErr: %v", funcErr) + } + if callErr != nil { + t.Fatalf("Unexpected callErr: %v", callErr) + } + expImports := []string{ + `foo "example.com/base/foo"`, + `common "k8s.io/kube-openapi/pkg/common"`, + `spec "k8s.io/kube-openapi/pkg/validation/spec"`, + } + if !cmp.Equal(imports, expImports) { + t.Errorf("wrong imports:\n%s", cmp.Diff(expImports, imports)) + } + + if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { + t.Fatal(err) + } else { + assertEqual(t, string(formatted), `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1969,29 +2315,29 @@ type Blah struct { "Embedded": { SchemaProps: spec.SchemaProps{ Default: 0, - Ref: ref("base/foo.Duration"), + Ref: ref("example.com/base/foo.Duration"), }, }, "PointerUnmarshal": { SchemaProps: spec.SchemaProps{ - Ref: ref("base/foo.MicroTime"), + Ref: ref("example.com/base/foo.MicroTime"), }, }, "StructUnmarshal": { SchemaProps: spec.SchemaProps{ - Ref: ref("base/foo.Time"), + Ref: ref("example.com/base/foo.Time"), }, }, "NoUnmarshal": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("base/foo.TimeWithoutUnmarshal"), + Ref: ref("example.com/base/foo.TimeWithoutUnmarshal"), }, }, "Regular": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("base/foo.NothingSpecial"), + Ref: ref("example.com/base/foo.NothingSpecial"), }, }, }, @@ -1999,58 +2345,77 @@ type Blah struct { }, }, Dependencies: []string{ - "base/foo.Duration", "base/foo.MicroTime", "base/foo.NothingSpecial", "base/foo.Time", "base/foo.TimeWithoutUnmarshal"}, + "example.com/base/foo.Duration", "example.com/base/foo.MicroTime", "example.com/base/foo.NothingSpecial", "example.com/base/foo.Time", "example.com/base/foo.TimeWithoutUnmarshal"}, } +}`) + } + }) } -`) - } +func TestMarkerComments(t *testing.T) { + inputFile := ` + package foo -} + // +k8s:openapi-gen=true + // +k8s:validation:maxProperties=10 + // +k8s:validation:minProperties=1 + // +k8s:validation:exclusiveMinimum + // +k8s:validation:exclusiveMaximum + type Blah struct { -func TestMarkerComments(t *testing.T) { + // Integer with min and max values + // +k8s:validation:minimum=0 + // +k8s:validation:maximum=10 + // +k8s:validation:exclusiveMinimum + // +k8s:validation:exclusiveMaximum + IntValue int + + // String with min and max lengths + // +k8s:validation:minLength=1 + // +k8s:validation:maxLength=10 + // +k8s:validation:pattern="^foo$[0-9]+" + StringValue string + + // +k8s:validation:maxitems=10 + // +k8s:validation:minItems=1 + // +k8s:validation:uniqueItems + ArrayValue []string + + // +k8s:validation:maxProperties=10 + // +k8s:validation:minProperties=1 + ObjValue map[string]interface{} + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() - callErr, funcErr, assert, _, funcBuffer, imports := testOpenAPITypeWriter(t, ` -package foo - -// +k8s:openapi-gen=true -// +k8s:validation:maxProperties=10 -// +k8s:validation:minProperties=1 -// +k8s:validation:exclusiveMinimum -// +k8s:validation:exclusiveMaximum -type Blah struct { - - // Integer with min and max values - // +k8s:validation:minimum=0 - // +k8s:validation:maximum=10 - // +k8s:validation:exclusiveMinimum - // +k8s:validation:exclusiveMaximum - IntValue int - - // String with min and max lengths - // +k8s:validation:minLength=1 - // +k8s:validation:maxLength=10 - // +k8s:validation:pattern="^foo$[0-9]+" - StringValue string - - // +k8s:validation:maxitems=10 - // +k8s:validation:minItems=1 - // +k8s:validation:uniqueItems - ArrayValue []string - - // +k8s:validation:maxProperties=10 - // +k8s:validation:minProperties=1 - ObjValue map[string]interface{} -} - `) - assert.NoError(funcErr) - assert.NoError(callErr) - assert.ElementsMatch(imports, []string{`foo "base/foo"`, `common "k8s.io/kube-openapi/pkg/common"`, `spec "k8s.io/kube-openapi/pkg/validation/spec"`, `ptr "k8s.io/utils/ptr"`}) - - if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { - t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) - } else { - formatted_expected, ree := format.Source([]byte(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + callErr, funcErr, _, funcBuffer, imports := testOpenAPITypeWriter(t, e.Config) + if funcErr != nil { + t.Fatalf("Unexpected funcErr: %v", funcErr) + } + if callErr != nil { + t.Fatalf("Unexpected callErr: %v", callErr) + } + expImports := []string{ + `foo "example.com/base/foo"`, + `common "k8s.io/kube-openapi/pkg/common"`, + `spec "k8s.io/kube-openapi/pkg/validation/spec"`, + `ptr "k8s.io/utils/ptr"`, + } + if !cmp.Equal(imports, expImports) { + t.Errorf("wrong imports:\n%s", cmp.Diff(expImports, imports)) + } + + if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { + t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) + } else { + formatted_expected, ree := format.Source([]byte(`func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2121,19 +2486,17 @@ type Blah struct { }, }, } - } - -`)) - if ree != nil { - t.Fatal(ree) + }`)) + if ree != nil { + t.Fatal(ree) + } + assertEqual(t, string(formatted), string(formatted_expected)) } - assert.Equal(string(formatted), string(formatted_expected)) - } + }) } func TestCELMarkerComments(t *testing.T) { - - callErr, funcErr, assert, _, funcBuffer, imports := testOpenAPITypeWriter(t, ` + inputFile := ` package foo // +k8s:openapi-gen=true @@ -2147,17 +2510,37 @@ func TestCELMarkerComments(t *testing.T) { // +k8s:validation:cel[1]:optionalOldSelf // +optional Field string - } - `) + }` - assert.NoError(funcErr) - assert.NoError(callErr) - assert.ElementsMatch(imports, []string{`foo "base/foo"`, `common "k8s.io/kube-openapi/pkg/common"`, `spec "k8s.io/kube-openapi/pkg/validation/spec"`}) + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, _, funcBuffer, imports := testOpenAPITypeWriter(t, e.Config) + if funcErr != nil { + t.Fatalf("Unexpected funcErr: %v", funcErr) + } + if callErr != nil { + t.Fatalf("Unexpected callErr: %v", callErr) + } + expImports := []string{ + `foo "example.com/base/foo"`, + `common "k8s.io/kube-openapi/pkg/common"`, + `spec "k8s.io/kube-openapi/pkg/validation/spec"`, + } + if !cmp.Equal(imports, expImports) { + t.Errorf("wrong imports:\n%s", cmp.Diff(expImports, imports)) + } - if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { - t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) - } else { - formatted_expected, ree := format.Source([]byte(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { + t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) + } else { + formatted_expected, ree := format.Source([]byte(`func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2184,19 +2567,17 @@ func TestCELMarkerComments(t *testing.T) { }, }, } - } - -`)) - if ree != nil { - t.Fatal(ree) + }`)) + if ree != nil { + t.Fatal(ree) + } + assertEqual(t, string(formatted_expected), string(formatted)) } - assert.Equal(string(formatted_expected), string(formatted)) - } + }) } func TestMultilineCELMarkerComments(t *testing.T) { - - callErr, funcErr, assert, _, funcBuffer, imports := testOpenAPITypeWriter(t, ` + inputFile := ` package foo // +k8s:openapi-gen=true @@ -2214,17 +2595,37 @@ func TestMultilineCELMarkerComments(t *testing.T) { // +k8s:validation:cel[1]:optionalOldSelf // +optional Field string - } - `) + }` - assert.NoError(funcErr) - assert.NoError(callErr) - assert.ElementsMatch(imports, []string{`foo "base/foo"`, `common "k8s.io/kube-openapi/pkg/common"`, `spec "k8s.io/kube-openapi/pkg/validation/spec"`}) + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, _, funcBuffer, imports := testOpenAPITypeWriter(t, e.Config) + if funcErr != nil { + t.Fatalf("Unexpected funcErr: %v", funcErr) + } + if callErr != nil { + t.Fatalf("Unexpected callErr: %v", callErr) + } + expImports := []string{ + `foo "example.com/base/foo"`, + `common "k8s.io/kube-openapi/pkg/common"`, + `spec "k8s.io/kube-openapi/pkg/validation/spec"`, + } + if !cmp.Equal(imports, expImports) { + t.Errorf("wrong imports:\n%s", cmp.Diff(expImports, imports)) + } - if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { - t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) - } else { - formatted_expected, ree := format.Source([]byte(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { + t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) + } else { + formatted_expected, ree := format.Source([]byte(`func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2251,18 +2652,17 @@ func TestMultilineCELMarkerComments(t *testing.T) { }, }, } - } - -`)) - if ree != nil { - t.Fatal(ree) + }`)) + if ree != nil { + t.Fatal(ree) + } + assertEqual(t, string(formatted_expected), string(formatted)) } - assert.Equal(string(formatted_expected), string(formatted)) - } + }) } func TestRequired(t *testing.T) { - callErr, funcErr, assert, _, funcBuffer, imports := testOpenAPITypeWriter(t, ` + inputFile := ` package foo // +k8s:openapi-gen=true @@ -2274,24 +2674,44 @@ func TestRequired(t *testing.T) { RequiredField string // +required - RequiredPointerField *string `+"`json:\"requiredPointerField,omitempty\"`"+` + RequiredPointerField *string ` + "`json:\"requiredPointerField,omitempty\"`" + ` // +optional - OptionalPointerField *string `+"`json:\"optionalPointerField,omitempty\"`"+` + OptionalPointerField *string ` + "`json:\"optionalPointerField,omitempty\"`" + ` ImplicitlyRequiredField string - ImplicitlyOptionalField string `+"`json:\"implicitlyOptionalField,omitempty\"`"+` - } - `) + ImplicitlyOptionalField string ` + "`json:\"implicitlyOptionalField,omitempty\"`" + ` + }` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() - assert.NoError(funcErr) - assert.NoError(callErr) - assert.ElementsMatch(imports, []string{`foo "base/foo"`, `common "k8s.io/kube-openapi/pkg/common"`, `spec "k8s.io/kube-openapi/pkg/validation/spec"`}) + callErr, funcErr, _, funcBuffer, imports := testOpenAPITypeWriter(t, e.Config) + if funcErr != nil { + t.Fatalf("Unexpected funcErr: %v", funcErr) + } + if callErr != nil { + t.Fatalf("Unexpected callErr: %v", callErr) + } + expImports := []string{ + `foo "example.com/base/foo"`, + `common "k8s.io/kube-openapi/pkg/common"`, + `spec "k8s.io/kube-openapi/pkg/validation/spec"`, + } + if !cmp.Equal(imports, expImports) { + t.Errorf("wrong imports:\n%s", cmp.Diff(expImports, imports)) + } - if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { - t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) - } else { - formatted_expected, ree := format.Source([]byte(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + if formatted, err := format.Source(funcBuffer.Bytes()); err != nil { + t.Fatalf("%v\n%v", err, string(funcBuffer.Bytes())) + } else { + formatted_expected, ree := format.Source([]byte(`func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2341,64 +2761,99 @@ func TestRequired(t *testing.T) { }, }, } - } - -`)) - if ree != nil { - t.Fatal(ree) + }`)) + if ree != nil { + t.Fatal(ree) + } + assertEqual(t, string(formatted_expected), string(formatted)) } - assert.Equal(string(formatted_expected), string(formatted)) - } + }) // Show specifying both is an error - callErr, funcErr, assert, _, _, _ = testOpenAPITypeWriter(t, ` - package foo + badFile := ` + package foo - // +k8s:openapi-gen=true - type Blah struct { - // +optional - // +required - ConfusingField string - } -`) - assert.NoError(callErr) - assert.ErrorContains(funcErr, "cannot be both optional and required") + // +k8s:openapi-gen=true + type Blah struct { + // +optional + // +required + ConfusingField string + }` + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": badFile, + }, + }}) + defer e.Cleanup() + + callErr, funcErr, _, _, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Errorf("Unexpected callErr: %v", callErr) + } + if funcErr == nil { + t.Fatalf("Expected funcErr") + } + if !strings.Contains(funcErr.Error(), "cannot be both optional and required") { + t.Errorf("Unexpected error: %v", funcErr) + } + }) } func TestMarkerCommentsCustomDefsV3(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -import openapi "k8s.io/kube-openapi/pkg/common" + import openapi "k8s.io/kube-openapi/pkg/common" -// +k8s:validation:maxProperties=10 -type Blah struct { -} + // +k8s:validation:maxProperties=10 + type Blah struct { + } -func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { - return openapi.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - MaxProperties: ptr.To[int64](10), - Format: "ipv4", + func (_ Blah) OpenAPIV3Definition() openapi.OpenAPIDefinition { + return openapi.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + MaxProperties: ptr.To[int64](10), + Format: "ipv4", + }, + }, + } + } + + func (_ Blah) OpenAPISchemaType() []string { return []string{"object"} } + func (_ Blah) OpenAPISchemaFormat() string { return "ipv4" }` + commonFile := `package common + + type OpenAPIDefinition struct {}` + + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, }, - }, - } -} + }, { + Name: "k8s.io/kube-openapi/pkg/common", + Files: map[string]interface{}{ + "common.go": commonFile, + }, + }}) + defer e.Cleanup() -func (_ Blah) OpenAPISchemaType() []string { return []string{"object"} } -func (_ Blah) OpenAPISchemaFormat() string { return "ipv4" } -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.EmbedOpenAPIDefinitionIntoV2Extension(foo.Blah{}.OpenAPIV3Definition(), common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2408,33 +2863,41 @@ MaxProperties: ptr.To[int64](10), }, }, }) -} - -`, funcBuffer.String()) +}`) + }) } func TestMarkerCommentsV3OneOfTypes(t *testing.T) { - callErr, funcErr, assert, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, ` -package foo + inputFile := ` + package foo -// +k8s:validation:maxLength=10 -type Blah struct { -} + // +k8s:validation:maxLength=10 + type Blah struct { + } -func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } -func (_ Blah) OpenAPIV3OneOfTypes() []string { return []string{"string", "array"} } -func (_ Blah) OpenAPISchemaFormat() string { return "ipv4" } + func (_ Blah) OpenAPISchemaType() []string { return []string{"string"} } + func (_ Blah) OpenAPIV3OneOfTypes() []string { return []string{"string", "array"} } + func (_ Blah) OpenAPISchemaFormat() string { return "ipv4" }` + packagestest.TestAll(t, func(t *testing.T, x packagestest.Exporter) { + e := packagestest.Export(t, x, []packagestest.Module{{ + Name: "example.com/base/foo", + Files: map[string]interface{}{ + "foo.go": inputFile, + }, + }}) + defer e.Cleanup() -`) - if callErr != nil { - t.Fatal(callErr) - } - if funcErr != nil { - t.Fatal(funcErr) - } - assert.Equal(`"base/foo.Blah": schema_base_foo_Blah(ref), -`, callBuffer.String()) - assert.Equal(`func schema_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { + callErr, funcErr, callBuffer, funcBuffer, _ := testOpenAPITypeWriter(t, e.Config) + if callErr != nil { + t.Fatal(callErr) + } + if funcErr != nil { + t.Fatal(funcErr) + } + assertEqual(t, callBuffer.String(), + `"example.com/base/foo.Blah": schema_examplecom_base_foo_Blah(ref),`) + assertEqual(t, funcBuffer.String(), + `func schema_examplecom_base_foo_Blah(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.EmbedOpenAPIDefinitionIntoV2Extension(common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -2452,7 +2915,6 @@ MaxLength: ptr.To[int64](10), }, }, }) -} - -`, funcBuffer.String()) +}`) + }) } From 9f9049d3054033589c09262be6c8128c419b6003 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Mon, 26 Feb 2024 12:48:27 -0800 Subject: [PATCH 24/24] Fix ./test/integration for gengo/v2 --- test/integration/integration_suite_test.go | 80 +++++++++---------- .../pkg/generated/openapi_generated.go | 4 +- 2 files changed, 40 insertions(+), 44 deletions(-) diff --git a/test/integration/integration_suite_test.go b/test/integration/integration_suite_test.go index 35e895820..a49b0765a 100644 --- a/test/integration/integration_suite_test.go +++ b/test/integration/integration_suite_test.go @@ -28,24 +28,15 @@ import ( ) const ( - headerFilePath = "../../boilerplate/boilerplate.go.txt" - testdataDir = "./testdata" - testPkgDir = "k8s.io/kube-openapi/test/integration/testdata" - inputDir = testPkgDir + "/listtype" + - "," + testPkgDir + "/maptype" + - "," + testPkgDir + "/structtype" + - "," + testPkgDir + "/dummytype" + - "," + testPkgDir + "/uniontype" + - "," + testPkgDir + "/enumtype" + - "," + testPkgDir + "/custom" + - "," + testPkgDir + "/valuevalidation" + - "," + testPkgDir + "/defaults" - outputBase = "pkg" - outputPackage = "generated" - outputBaseFileName = "openapi_generated" + headerFilePath = "../../boilerplate/boilerplate.go.txt" + testdataDir = "./testdata" + testPkgRoot = "k8s.io/kube-openapi/test/integration/testdata" + outputPkg = testPkgRoot + "/pkg/generated" + generatedCodeFileName = "openapi_generated.go" + goldenCodeFilePath = "pkg/generated/" + generatedCodeFileName generatedSwaggerFileName = "generated.v2.json" - generatedReportFileName = "generated.v2.report" goldenSwaggerFileName = "golden.v2.json" + generatedReportFileName = "generated.v2.report" goldenReportFileName = "golden.v2.report" generatedOpenAPIv3FileName = "generated.v3.json" goldenOpenAPIv3Filename = "golden.v3.json" @@ -58,6 +49,18 @@ var ( tempDir string terr error openAPIGenPath string + + inputDirs = []string{ + filepath.Join(testPkgRoot, "listtype"), + filepath.Join(testPkgRoot, "maptype"), + filepath.Join(testPkgRoot, "structtype"), + filepath.Join(testPkgRoot, "dummytype"), + filepath.Join(testPkgRoot, "uniontype"), + filepath.Join(testPkgRoot, "enumtype"), + filepath.Join(testPkgRoot, "custom"), + filepath.Join(testPkgRoot, "valuevalidation"), + filepath.Join(testPkgRoot, "defaults"), + } ) func generatedFile(filename string) string { return filepath.Join(tempDir, filename) } @@ -84,18 +87,16 @@ var _ = BeforeSuite(func() { Expect(berr).ShouldNot(HaveOccurred()) openAPIGenPath = binaryPath - // Run the OpenAPI code generator, creating OpenAPIDefinition code - // to be compiled into builder. - By("processing go idl with openapi-gen") - gr := generatedFile(generatedReportFileName) - command := exec.Command(openAPIGenPath, - "-i", inputDir, - "-o", outputBase, - "-p", outputPackage, - "-O", outputBaseFileName, - "-r", gr, - "-h", headerFilePath, - ) + // Run the OpenAPI code generator. + By("running openapi-gen") + args := append([]string{ + "--output-dir", tempDir, + "--output-pkg", outputPkg, + "--output-file", generatedCodeFileName, + "--report-filename", generatedFile(generatedReportFileName), + "--go-header-file", headerFilePath, + }, inputDirs...) + command := exec.Command(openAPIGenPath, args...) command.Dir = workingDirectory session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) Expect(err).ShouldNot(HaveOccurred()) @@ -136,16 +137,13 @@ var _ = AfterSuite(func() { }) var _ = Describe("Open API Definitions Generation", func() { - Describe("openapi-gen --verify", func() { - It("Verifies that the existing files are correct", func() { - command := exec.Command(openAPIGenPath, - "-i", inputDir, - "-o", outputBase, - "-p", outputPackage, - "-O", outputBaseFileName, - "-r", testdataFile(goldenReportFileName), - "-h", headerFilePath, - "--verify-only", + Describe("Validating generated code", func() { + It("Generated code should match golden files", func() { + // Diff the generated code against the golden code. Exit code should be zero. + command := exec.Command( + "diff", "-u", + goldenCodeFilePath, + generatedFile(generatedCodeFileName), ) command.Dir = workingDirectory session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) @@ -158,7 +156,7 @@ var _ = Describe("Open API Definitions Generation", func() { It("Generated OpenAPI swagger definitions should match golden files", func() { // Diff the generated swagger against the golden swagger. Exit code should be zero. command := exec.Command( - "diff", + "diff", "-u", testdataFile(goldenSwaggerFileName), generatedFile(generatedSwaggerFileName), ) @@ -173,7 +171,7 @@ var _ = Describe("Open API Definitions Generation", func() { It("Generated OpenAPI swagger definitions should match golden files", func() { // Diff the generated swagger against the golden swagger. Exit code should be zero. command := exec.Command( - "diff", + "diff", "-u", testdataFile(goldenOpenAPIv3Filename), generatedFile(generatedOpenAPIv3FileName), ) @@ -188,7 +186,7 @@ var _ = Describe("Open API Definitions Generation", func() { It("Generated API rule violations should match golden report files", func() { // Diff the generated report against the golden report. Exit code should be zero. command := exec.Command( - "diff", + "diff", "-u", testdataFile(goldenReportFileName), generatedFile(generatedReportFileName), ) diff --git a/test/integration/pkg/generated/openapi_generated.go b/test/integration/pkg/generated/openapi_generated.go index 86269dc53..993ef5815 100644 --- a/test/integration/pkg/generated/openapi_generated.go +++ b/test/integration/pkg/generated/openapi_generated.go @@ -17,9 +17,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by openapi-gen.go. DO NOT EDIT. - -// This file was autogenerated by openapi-gen. Do not edit it manually! +// Code generated by openapi-gen. DO NOT EDIT. package generated