From 0d4fb3e340d820a6195b2e440612fcb42633b9b2 Mon Sep 17 00:00:00 2001 From: Levi Blackstone Date: Thu, 11 Nov 2021 17:00:03 -0700 Subject: [PATCH] [schema] Add IsOverlay option to disable codegen for particular types (#8338) Add a new `IsOverlay` option to schema types and functions that allows providers to document overlays in the schema. This makes it easier to generate API docs consistently, even for code that is generated outside of the typical codegen process. --- CHANGELOG_PENDING.md | 3 + developer-docs/providers/metaschema.md | 18 +- pkg/codegen/dotnet/gen.go | 35 ++ pkg/codegen/go/gen.go | 53 ++- pkg/codegen/internal/test/sdk_driver.go | 6 +- .../test/testdata/schema/overlay.json | 87 +++++ .../simple-resource-schema/docs/_index.md | 2 + .../docs/codegen-manifest.json | 2 + .../docs/overlayfunction/_index.md | 190 ++++++++++ .../docs/overlayresource/_index.md | 328 ++++++++++++++++++ .../simple-resource-schema/schema.json | 40 +++ pkg/codegen/nodejs/gen.go | 40 +++ pkg/codegen/python/gen.go | 47 +++ pkg/codegen/python/gen_resource_mappings.go | 10 + pkg/codegen/schema/schema.go | 22 +- pkg/codegen/schema/schema_test.go | 38 ++ 16 files changed, 911 insertions(+), 10 deletions(-) create mode 100644 pkg/codegen/internal/test/testdata/schema/overlay.json create mode 100644 pkg/codegen/internal/test/testdata/simple-resource-schema/docs/overlayfunction/_index.md create mode 100644 pkg/codegen/internal/test/testdata/simple-resource-schema/docs/overlayresource/_index.md diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 5ecddce92..f15971a83 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,3 +1,6 @@ ### Improvements +- [schema] Add IsOverlay option to disable codegen for particular types + [#8338](https://github.com/pulumi/pulumi/pull/8338) + ### Bug Fixes diff --git a/developer-docs/providers/metaschema.md b/developer-docs/providers/metaschema.md index 4136ed0d7..5c496c966 100644 --- a/developer-docs/providers/metaschema.md +++ b/developer-docs/providers/metaschema.md @@ -297,7 +297,7 @@ Enum: `"boolean"` | `"integer"` | `"number"` | `"string"` #### `deprecationMessage` -Indicates whether or not the value is deprecated. +Indicates whether the value is deprecated. `string` @@ -339,7 +339,7 @@ Describes a function. #### `deprecationMessage` -Indicates whether or not the function is deprecated +Indicates whether the function is deprecated `string` @@ -564,7 +564,7 @@ Additional language-specific data about the default value. #### `deprecationMessage` -Indicates whether or not the property is deprecated +Indicates whether the property is deprecated `string` @@ -627,7 +627,7 @@ Items: [Alias Definition](#alias-definition) #### `deprecationMessage` -Indicates whether or not the resource is deprecated +Indicates whether the resource is deprecated `string` @@ -653,7 +653,15 @@ Additional properties: [Property Definition](#property-definition) #### `isComponent` -Indicates whether or not the resource is a component. +Indicates whether the resource is a component. + +`boolean` + +--- + +#### `isOverlay` + +Indicates whether the resource is an overlay (code is generated by the package rather than by the core Pulumi codegen). `boolean` diff --git a/pkg/codegen/dotnet/gen.go b/pkg/codegen/dotnet/gen.go index 5e9508b9d..46a9c6709 100644 --- a/pkg/codegen/dotnet/gen.go +++ b/pkg/codegen/dotnet/gen.go @@ -1995,6 +1995,11 @@ func (mod *modContext) gen(fs fs) error { // Resources for _, r := range mod.resources { + if r.IsOverlay { + // This resource code is generated by the provider, so no further action is required. + continue + } + imports := map[string]codegen.StringSet{} mod.getImportsForResource(r, imports, r) @@ -2017,6 +2022,11 @@ func (mod *modContext) gen(fs fs) error { // Functions for _, f := range mod.functions { + if f.IsOverlay { + // This function code is generated by the provider, so no further action is required. + continue + } + code, err := mod.genFunctionFileCode(f) if err != nil { return err @@ -2026,6 +2036,11 @@ func (mod *modContext) gen(fs fs) error { // Nested types for _, t := range mod.types { + if t.IsOverlay { + // This type is generated by the provider, so no further action is required. + continue + } + if mod.details(t).inputType { buffer := &bytes.Buffer{} mod.genHeader(buffer, pulumiImports) @@ -2186,6 +2201,11 @@ func generateModuleContextMap(tool string, pkg *schema.Package) (map[string]*mod computePropertyNames(pkg.Config, propertyNames) computePropertyNames(pkg.Provider.InputProperties, propertyNames) for _, r := range pkg.Resources { + if r.IsOverlay { + // This resource code is generated by the provider, so no further action is required. + continue + } + computePropertyNames(r.Properties, propertyNames) computePropertyNames(r.InputProperties, propertyNames) if r.StateInputs != nil { @@ -2193,6 +2213,11 @@ func generateModuleContextMap(tool string, pkg *schema.Package) (map[string]*mod } } for _, f := range pkg.Functions { + if f.IsOverlay { + // This function code is generated by the provider, so no further action is required. + continue + } + if f.Inputs != nil { computePropertyNames(f.Inputs.Properties, propertyNames) } @@ -2289,6 +2314,11 @@ func generateModuleContextMap(tool string, pkg *schema.Package) (map[string]*mod // Find input and output types referenced by functions. for _, f := range pkg.Functions { + if f.IsOverlay { + // This function code is generated by the provider, so no further action is required. + continue + } + mod := getModFromToken(f.Token, pkg) if !f.IsMethod { mod.functions = append(mod.functions, f) @@ -2347,6 +2377,11 @@ func LanguageResources(tool string, pkg *schema.Package) (map[string]LanguageRes continue } for _, r := range mod.resources { + if r.IsOverlay { + // This resource code is generated by the provider, so no further action is required. + continue + } + lr := LanguageResource{ Resource: r, Package: namespaceName(info.Namespaces, modName), diff --git a/pkg/codegen/go/gen.go b/pkg/codegen/go/gen.go index 9d72cc9f4..241176758 100644 --- a/pkg/codegen/go/gen.go +++ b/pkg/codegen/go/gen.go @@ -2019,6 +2019,10 @@ func rewriteCyclicObjectFields(pkg *schema.Package) { func (pkg *pkgContext) genType(w io.Writer, obj *schema.ObjectType) { contract.Assert(!obj.IsInputShape()) + if obj.IsOverlay { + // This type is generated by the provider, so no further action is required. + return + } pkg.genPlainType(w, pkg.tokenToType(obj.Token), obj.Comment, "", obj.Properties) pkg.genInputTypes(w, obj.InputShape, pkg.detailsForType(obj)) @@ -2130,6 +2134,10 @@ func (pkg *pkgContext) genTypeRegistrations(w io.Writer, objTypes []*schema.Obje // Input types. if !pkg.disableInputTypeRegistrations { for _, obj := range objTypes { + if obj.IsOverlay { + // This type is generated by the provider, so no further action is required. + continue + } name, details := pkg.tokenToType(obj.Token), pkg.detailsForType(obj) fmt.Fprintf(w, "\tpulumi.RegisterInputType(reflect.TypeOf((*%[1]sInput)(nil)).Elem(), %[1]sArgs{})\n", name) if details.ptrElement { @@ -2152,6 +2160,10 @@ func (pkg *pkgContext) genTypeRegistrations(w io.Writer, objTypes []*schema.Obje // Output types. for _, obj := range objTypes { + if obj.IsOverlay { + // This type is generated by the provider, so no further action is required. + continue + } name, details := pkg.tokenToType(obj.Token), pkg.detailsForType(obj) fmt.Fprintf(w, "\tpulumi.RegisterOutputType(%sOutput{})\n", name) if details.ptrElement { @@ -2510,6 +2522,17 @@ func (pkg *pkgContext) genConfig(w io.Writer, variables []*schema.Property) erro // definition and its registration to support rehydrating providers. func (pkg *pkgContext) genResourceModule(w io.Writer) { contract.Assert(len(pkg.resources) != 0) + allResourcesAreOverlays := true + for _, r := range pkg.resources { + if !r.IsOverlay { + allResourcesAreOverlays = false + break + } + } + if allResourcesAreOverlays { + // If all resources in this module are overlays, skip further code generation. + return + } basePath := pkg.importBasePath @@ -2545,6 +2568,10 @@ func (pkg *pkgContext) genResourceModule(w io.Writer) { fmt.Fprintf(w, "func (m *module) Construct(ctx *pulumi.Context, name, typ, urn string) (r pulumi.Resource, err error) {\n") fmt.Fprintf(w, "\tswitch typ {\n") for _, r := range pkg.resources { + if r.IsOverlay { + // This resource code is generated by the provider, so no further action is required. + continue + } if r.IsProvider { contract.Assert(provider == nil) provider = r @@ -3029,6 +3056,11 @@ func LanguageResources(tool string, pkg *schema.Package) (map[string]LanguageRes pkg := packages[mod] for _, r := range pkg.resources { + if r.IsOverlay { + // This resource code is generated by the provider, so no further action is required. + continue + } + packagePath := path.Join(goPkgInfo.ImportBasePath, pkg.mod) resources[r.Token] = LanguageResource{ Resource: r, @@ -3142,6 +3174,11 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error // Resources for _, r := range pkg.resources { + if r.IsOverlay { + // This resource code is generated by the provider, so no further action is required. + continue + } + importsAndAliases := map[string]string{} pkg.getImports(r, importsAndAliases) @@ -3157,6 +3194,11 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error // Functions for _, f := range pkg.functions { + if f.IsOverlay { + // This function code is generated by the provider, so no further action is required. + continue + } + fileName := path.Join(mod, camel(tokenToName(f.Token))+".go") code := pkg.genFunctionCodeFile(f) setFile(fileName, code) @@ -3248,7 +3290,7 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error } // If there are resources in this module, register the module with the runtime. - if len(pkg.resources) != 0 { + if len(pkg.resources) != 0 && !allResourcesAreOverlays(pkg.resources) { buffer := &bytes.Buffer{} pkg.genResourceModule(buffer) @@ -3259,6 +3301,15 @@ func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error return files, nil } +func allResourcesAreOverlays(resources []*schema.Resource) bool { + for _, r := range resources { + if !r.IsOverlay { + return false + } + } + return true +} + // goPackage returns the suggested package name for the given string. func goPackage(name string) string { return strings.ReplaceAll(name, "-", "") diff --git a/pkg/codegen/internal/test/sdk_driver.go b/pkg/codegen/internal/test/sdk_driver.go index 2f204322d..22054dbf4 100644 --- a/pkg/codegen/internal/test/sdk_driver.go +++ b/pkg/codegen/internal/test/sdk_driver.go @@ -217,11 +217,11 @@ type SDKCodegenOptions struct { Checks map[string]CodegenCheck } -// `TestSDKCodegen` runs the complete set of SDK code generation tests +// TestSDKCodegen runs the complete set of SDK code generation tests // against a particular language's code generator. It also verifies // that the generated code is structurally sound. // -// The tests files live in `pkg/codegen/internal/test/testdata` and +// The test files live in `pkg/codegen/internal/test/testdata` and // are registered in `var sdkTests` in `sdk_driver.go`. // // An SDK code generation test files consists of a schema and a set of @@ -245,7 +245,7 @@ type SDKCodegenOptions struct { // PULUMI_ACCEPT=true go test ./... // // This will rebuild subfolders such as `go/` from scratch and store -// the set of code-generated file names in `go/codegen-manfiest.json`. +// the set of code-generated file names in `go/codegen-manifest.json`. // If these outputs look correct, they need to be checked into git and // will then serve as the expected values for the normal test runs: // diff --git a/pkg/codegen/internal/test/testdata/schema/overlay.json b/pkg/codegen/internal/test/testdata/schema/overlay.json new file mode 100644 index 000000000..65d3778d8 --- /dev/null +++ b/pkg/codegen/internal/test/testdata/schema/overlay.json @@ -0,0 +1,87 @@ +{ + "version": "0.0.1", + "name": "example", + "types": { + "example::ConfigMap": { + "properties": { + "config": { + "type": "string" + } + }, + "type": "object" + }, + "example::ConfigMapOverlay": { + "isOverlay": true, + "properties": { + "config": { + "type": "string" + } + }, + "type": "object" + } + }, + "resources": { + "example::Resource": { + "properties": { + "foo": { + "$ref": "#/types/example::ConfigMapOverlay" + } + }, + "inputProperties": { + "foo": { + "$ref": "#/types/example::ConfigMapOverlay" + } + }, + "type": "object" + }, + "example::OverlayResource": { + "isOverlay": true, + "properties": { + "foo": { + "$ref": "#/types/example::ConfigMapOverlay" + } + }, + "inputProperties": { + "foo": { + "$ref": "#/types/example::ConfigMapOverlay" + } + }, + "type": "object" + } + }, + "functions": { + "example::Function": { + "inputs": { + "properties": { + "arg1": { + "type": "string" + } + } + }, + "outputs": { + "properties": { + "result": { + "type": "string" + } + } + } + }, + "example::OverlayFunction": { + "isOverlay": true, + "inputs": { + "properties": { + "arg1": { + "type": "string" + } + } + }, + "outputs": { + "properties": { + "result": { + "type": "string" + } + } + } + } + } +} diff --git a/pkg/codegen/internal/test/testdata/simple-resource-schema/docs/_index.md b/pkg/codegen/internal/test/testdata/simple-resource-schema/docs/_index.md index ebf7803bc..8119fbbdb 100644 --- a/pkg/codegen/internal/test/testdata/simple-resource-schema/docs/_index.md +++ b/pkg/codegen/internal/test/testdata/simple-resource-schema/docs/_index.md @@ -14,6 +14,7 @@ no_edit_this_page: true

Resources