2020-03-09 17:35:20 +00:00
|
|
|
//go:generate go run bundler.go
|
|
|
|
|
2020-02-27 18:04:34 +00:00
|
|
|
// Copyright 2016-2020, Pulumi Corporation.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
// Pulling out some of the repeated strings tokens into constants would harm readability, so we just ignore the
|
|
|
|
// goconst linter's warning.
|
|
|
|
//
|
2023-01-06 00:07:45 +00:00
|
|
|
//nolint:lll, goconst
|
2020-02-27 18:04:34 +00:00
|
|
|
package docs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2021-11-10 19:07:43 +00:00
|
|
|
"embed"
|
2021-11-13 02:37:17 +00:00
|
|
|
"errors"
|
2020-02-27 18:04:34 +00:00
|
|
|
"fmt"
|
2024-03-21 13:41:07 +00:00
|
|
|
"go/format"
|
2020-03-09 17:35:20 +00:00
|
|
|
"html"
|
|
|
|
"html/template"
|
2020-02-27 18:04:34 +00:00
|
|
|
"path"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
|
2024-03-21 13:41:07 +00:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/pcl"
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2024-03-21 13:41:07 +00:00
|
|
|
"github.com/golang/glog"
|
2022-04-29 22:04:15 +00:00
|
|
|
"github.com/pgavlin/goldmark"
|
|
|
|
|
2022-04-21 11:23:36 +00:00
|
|
|
"github.com/pulumi/pulumi-java/pkg/codegen/java"
|
|
|
|
yaml "github.com/pulumi/pulumi-yaml/pkg/pulumiyaml/codegen"
|
2021-03-17 13:20:05 +00:00
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/dotnet"
|
|
|
|
go_gen "github.com/pulumi/pulumi/pkg/v3/codegen/go"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/nodejs"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/python"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
|
2023-06-28 16:02:04 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/slice"
|
2024-02-20 15:44:37 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
|
2022-12-12 14:55:35 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
2020-02-27 18:04:34 +00:00
|
|
|
)
|
|
|
|
|
2021-11-10 19:07:43 +00:00
|
|
|
//go:embed templates/*.tmpl
|
|
|
|
var packagedTemplates embed.FS
|
2020-03-19 19:18:18 +00:00
|
|
|
|
2021-11-10 19:07:43 +00:00
|
|
|
// NOTE: This lookup map can be removed when all Pulumi-managed packages
|
|
|
|
// have a DisplayName in their schema. See pulumi/pulumi#7813.
|
|
|
|
// This lookup table no longer needs to be updated for new providers
|
|
|
|
// and is considered stale.
|
2021-10-06 15:03:21 +00:00
|
|
|
//
|
2021-10-18 05:36:31 +00:00
|
|
|
// titleLookup is a map of package name to the desired display name.
|
2021-10-06 15:03:21 +00:00
|
|
|
func titleLookup(shortName string) (string, bool) {
|
|
|
|
v, ok := map[string]string{
|
2021-10-18 05:36:31 +00:00
|
|
|
"aiven": "Aiven",
|
|
|
|
"akamai": "Akamai",
|
|
|
|
"alicloud": "Alibaba Cloud",
|
|
|
|
"auth0": "Auth0",
|
|
|
|
"aws": "AWS Classic",
|
2022-12-03 13:40:20 +00:00
|
|
|
"awsx": "AWSx (Pulumi Crosswalk for AWS)",
|
2021-10-18 05:36:31 +00:00
|
|
|
"aws-apigateway": "AWS API Gateway",
|
|
|
|
"aws-miniflux": "Miniflux",
|
|
|
|
"aws-native": "AWS Native",
|
|
|
|
"aws-quickstart-aurora-mysql": "AWS QuickStart Aurora MySQL",
|
|
|
|
"aws-quickstart-aurora-postgres": "AWS QuickStart Aurora PostgreSQL",
|
|
|
|
"aws-quickstart-redshift": "AWS QuickStart Redshift",
|
|
|
|
"aws-serverless": "AWS Serverless",
|
|
|
|
"aws-quickstart-vpc": "AWS QuickStart VPC",
|
|
|
|
"aws-s3-replicated-bucket": "AWS S3 Replicated Bucket",
|
|
|
|
"azure": "Azure Classic",
|
2022-12-03 13:40:20 +00:00
|
|
|
"azure-justrun": "Azure Justrun",
|
2021-10-18 05:36:31 +00:00
|
|
|
"azure-native": "Azure Native",
|
|
|
|
"azure-quickstart-acr-geo-replication": "Azure QuickStart ACR Geo Replication",
|
|
|
|
"azure-quickstart-aks": "Azure QuickStart AKS",
|
|
|
|
"azure-quickstart-compute": "Azure QuickStart Compute",
|
|
|
|
"azure-quickstart-sql": "Azure QuickStart SQL",
|
2022-12-03 13:40:20 +00:00
|
|
|
"azuread": "Azure Active Directory (Azure AD)",
|
2021-10-18 05:36:31 +00:00
|
|
|
"azuredevops": "Azure DevOps",
|
|
|
|
"azuresel": "Azure",
|
|
|
|
"civo": "Civo",
|
|
|
|
"cloudamqp": "CloudAMQP",
|
|
|
|
"cloudflare": "Cloudflare",
|
|
|
|
"cloudinit": "cloud-init",
|
2023-01-05 02:13:41 +00:00
|
|
|
"confluentcloud": "Confluent Cloud",
|
2023-01-05 02:17:57 +00:00
|
|
|
"confluent": "Confluent Cloud (Deprecated)",
|
2022-12-03 13:40:20 +00:00
|
|
|
"consul": "HashiCorp Consul",
|
2021-10-18 05:36:31 +00:00
|
|
|
"coredns-helm": "CoreDNS (Helm)",
|
|
|
|
"datadog": "Datadog",
|
|
|
|
"digitalocean": "DigitalOcean",
|
|
|
|
"dnsimple": "DNSimple",
|
|
|
|
"docker": "Docker",
|
|
|
|
"docker-buildkit": "Docker BuildKit",
|
|
|
|
"eks": "Amazon EKS",
|
|
|
|
"equinix-metal": "Equinix Metal",
|
|
|
|
"f5bigip": "f5 BIG-IP",
|
|
|
|
"fastly": "Fastly",
|
2022-12-03 13:40:20 +00:00
|
|
|
"gcp": "Google Cloud (GCP) Classic",
|
2021-10-18 05:36:31 +00:00
|
|
|
"gcp-global-cloudrun": "Google Global Cloud Run",
|
|
|
|
"gcp-project-scaffold": "Google Project Scaffolding",
|
|
|
|
"google-native": "Google Cloud Native",
|
|
|
|
"github": "GitHub",
|
|
|
|
"github-serverless-webhook": "GitHub Serverless Webhook",
|
|
|
|
"gitlab": "GitLab",
|
|
|
|
"hcloud": "Hetzner Cloud",
|
|
|
|
"istio-helm": "Istio (Helm)",
|
|
|
|
"jaeger-helm": "Jaeger (Helm)",
|
|
|
|
"kafka": "Kafka",
|
|
|
|
"keycloak": "Keycloak",
|
|
|
|
"kong": "Kong",
|
|
|
|
"kubernetes": "Kubernetes",
|
|
|
|
"libvirt": "libvirt",
|
|
|
|
"linode": "Linode",
|
|
|
|
"mailgun": "Mailgun",
|
|
|
|
"minio": "MinIO",
|
|
|
|
"mongodbatlas": "MongoDB Atlas",
|
|
|
|
"mysql": "MySQL",
|
|
|
|
"newrelic": "New Relic",
|
2021-10-18 12:24:46 +00:00
|
|
|
"kubernetes-ingress-nginx": "NGINX Ingress Controller (Helm)",
|
|
|
|
"kubernetes-coredns": "CoreDNS (Helm)",
|
|
|
|
"kubernetes-cert-manager": "Jetstack Cert Manager (Helm)",
|
2022-12-03 13:40:20 +00:00
|
|
|
"nomad": "HashiCorp Nomad",
|
2021-10-18 05:36:31 +00:00
|
|
|
"ns1": "NS1",
|
|
|
|
"okta": "Okta",
|
|
|
|
"openstack": "OpenStack",
|
|
|
|
"opsgenie": "Opsgenie",
|
|
|
|
"packet": "Packet",
|
|
|
|
"pagerduty": "PagerDuty",
|
2023-01-12 22:37:57 +00:00
|
|
|
"pulumi-std": "Pulumi Standard Library",
|
2021-10-18 05:36:31 +00:00
|
|
|
"postgresql": "PostgreSQL",
|
|
|
|
"prometheus-helm": "Prometheus (Helm)",
|
|
|
|
"rabbitmq": "RabbitMQ",
|
2022-12-03 13:53:21 +00:00
|
|
|
"rancher2": "Rancher2",
|
2021-10-18 05:36:31 +00:00
|
|
|
"random": "random",
|
2022-12-03 13:55:19 +00:00
|
|
|
"rke": "Rancher Kubernetes Engine (RKE)",
|
2021-10-18 05:36:31 +00:00
|
|
|
"run-my-darn-container": "Run My Darn Container",
|
|
|
|
"shipa": "Shipa",
|
|
|
|
"signalfx": "SignalFx",
|
|
|
|
"snowflake": "Snowflake",
|
|
|
|
"splunk": "Splunk",
|
|
|
|
"spotinst": "Spotinst",
|
|
|
|
"sumologic": "Sumo Logic",
|
|
|
|
"tls": "TLS",
|
|
|
|
"vault": "Vault",
|
|
|
|
"venafi": "Venafi",
|
|
|
|
"vsphere": "vSphere",
|
|
|
|
"wavefront": "Wavefront",
|
|
|
|
"yandex": "Yandex",
|
2021-10-06 15:03:21 +00:00
|
|
|
}[shortName]
|
|
|
|
return v, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
// Property anchor tag separator, used in a property anchor tag id to separate the
|
|
|
|
// property and language (e.g. property~lang).
|
|
|
|
const propertyLangSeparator = "_"
|
|
|
|
|
2024-03-21 13:41:07 +00:00
|
|
|
type languageConstructorSyntax struct {
|
|
|
|
resources map[string]string
|
|
|
|
invokes map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
type constructorSyntaxData struct {
|
|
|
|
typescript *languageConstructorSyntax
|
|
|
|
python *languageConstructorSyntax
|
|
|
|
golang *languageConstructorSyntax
|
|
|
|
csharp *languageConstructorSyntax
|
|
|
|
java *languageConstructorSyntax
|
|
|
|
yaml *languageConstructorSyntax
|
|
|
|
}
|
|
|
|
|
|
|
|
func emptyLanguageConstructorSyntax() *languageConstructorSyntax {
|
|
|
|
return &languageConstructorSyntax{
|
|
|
|
resources: map[string]string{},
|
|
|
|
invokes: map[string]string{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func newConstructorSyntaxData() *constructorSyntaxData {
|
|
|
|
return &constructorSyntaxData{
|
|
|
|
typescript: emptyLanguageConstructorSyntax(),
|
|
|
|
python: emptyLanguageConstructorSyntax(),
|
|
|
|
golang: emptyLanguageConstructorSyntax(),
|
|
|
|
csharp: emptyLanguageConstructorSyntax(),
|
|
|
|
java: emptyLanguageConstructorSyntax(),
|
|
|
|
yaml: emptyLanguageConstructorSyntax(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
type docGenContext struct {
|
|
|
|
internalModMap map[string]*modContext
|
|
|
|
|
|
|
|
supportedLanguages []string
|
|
|
|
snippetLanguages []string
|
|
|
|
templates *template.Template
|
|
|
|
docHelpers map[string]codegen.DocLanguageHelper
|
|
|
|
|
|
|
|
// The language-specific info objects for a certain package (provider).
|
|
|
|
goPkgInfo go_gen.GoPackageInfo
|
|
|
|
csharpPkgInfo dotnet.CSharpPackageInfo
|
|
|
|
nodePkgInfo nodejs.NodePackageInfo
|
|
|
|
pythonPkgInfo python.PackageInfo
|
|
|
|
|
|
|
|
// langModuleNameLookup is a map of module name to its language-specific
|
|
|
|
// name.
|
|
|
|
langModuleNameLookup map[string]string
|
2023-03-17 18:30:55 +00:00
|
|
|
|
|
|
|
// Maps a *modContext, *schema.Resource, or *schema.Function to the link that was assigned to it.
|
|
|
|
moduleConflictLinkMap map[interface{}]string
|
2024-03-21 13:41:07 +00:00
|
|
|
|
|
|
|
constructorSyntaxData *constructorSyntaxData
|
2021-10-06 15:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// modules is a map of a module name and information
|
|
|
|
// about it. This is crux of all API docs generation
|
|
|
|
// as the modContext carries information about the resources,
|
|
|
|
// functions, as well other modules within each module.
|
|
|
|
func (dctx *docGenContext) modules() map[string]*modContext {
|
|
|
|
return dctx.internalModMap
|
|
|
|
}
|
|
|
|
|
|
|
|
func (dctx *docGenContext) setModules(modules map[string]*modContext) {
|
|
|
|
m := map[string]*modContext{}
|
|
|
|
for k, v := range modules {
|
|
|
|
m[k] = v.withDocGenContext(dctx)
|
2020-04-09 16:43:38 +00:00
|
|
|
}
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx.internalModMap = m
|
|
|
|
}
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
func newDocGenContext() *docGenContext {
|
2022-04-21 11:23:36 +00:00
|
|
|
supportedLanguages := []string{"csharp", "go", "nodejs", "python", "yaml", "java"}
|
2021-10-06 15:03:21 +00:00
|
|
|
docHelpers := make(map[string]codegen.DocLanguageHelper)
|
2020-03-12 00:58:12 +00:00
|
|
|
for _, lang := range supportedLanguages {
|
|
|
|
switch lang {
|
|
|
|
case "csharp":
|
2020-03-20 15:17:58 +00:00
|
|
|
docHelpers[lang] = &dotnet.DocLanguageHelper{}
|
2020-03-12 00:58:12 +00:00
|
|
|
case "go":
|
2020-03-20 15:17:58 +00:00
|
|
|
docHelpers[lang] = &go_gen.DocLanguageHelper{}
|
2020-03-12 00:58:12 +00:00
|
|
|
case "nodejs":
|
2020-03-20 15:17:58 +00:00
|
|
|
docHelpers[lang] = &nodejs.DocLanguageHelper{}
|
2020-03-12 00:58:12 +00:00
|
|
|
case "python":
|
2020-03-20 15:17:58 +00:00
|
|
|
docHelpers[lang] = &python.DocLanguageHelper{}
|
2022-04-21 11:23:36 +00:00
|
|
|
case "yaml":
|
|
|
|
docHelpers[lang] = &yaml.DocLanguageHelper{}
|
|
|
|
case "java":
|
|
|
|
docHelpers[lang] = &java.DocLanguageHelper{}
|
2020-03-12 00:58:12 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-19 19:18:18 +00:00
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
return &docGenContext{
|
2023-03-17 18:30:55 +00:00
|
|
|
supportedLanguages: supportedLanguages,
|
|
|
|
snippetLanguages: []string{"csharp", "go", "python", "typescript", "yaml", "java"},
|
|
|
|
langModuleNameLookup: map[string]string{},
|
|
|
|
docHelpers: docHelpers,
|
|
|
|
moduleConflictLinkMap: map[interface{}]string{},
|
2021-10-06 15:03:21 +00:00
|
|
|
}
|
2020-03-12 00:58:12 +00:00
|
|
|
}
|
2020-03-09 17:35:20 +00:00
|
|
|
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
type typeDetails struct {
|
|
|
|
inputType bool
|
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
// header represents the header of each resource markdown file.
|
|
|
|
type header struct {
|
2020-04-21 11:28:44 +00:00
|
|
|
Title string
|
|
|
|
TitleTag string
|
|
|
|
MetaDesc string
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
// property represents an input or an output property.
|
|
|
|
type property struct {
|
2020-05-22 21:53:34 +00:00
|
|
|
// ID is the `id` attribute that will be attached to the DOM element containing the property.
|
|
|
|
ID string
|
2020-03-20 15:17:58 +00:00
|
|
|
// DisplayName is the property name with word-breaks.
|
|
|
|
DisplayName string
|
2020-03-09 17:35:20 +00:00
|
|
|
Name string
|
|
|
|
Comment string
|
2020-12-10 02:18:34 +00:00
|
|
|
Types []propertyType
|
2020-03-09 17:35:20 +00:00
|
|
|
DeprecationMessage string
|
2020-05-22 21:53:34 +00:00
|
|
|
Link string
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2022-05-17 20:59:47 +00:00
|
|
|
IsRequired bool
|
|
|
|
IsInput bool
|
|
|
|
IsReplaceOnChanges bool
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
|
2020-12-14 22:40:14 +00:00
|
|
|
// enum represents an enum.
|
|
|
|
type enum struct {
|
|
|
|
ID string // ID is the `id` attribute attached to the DOM element containing the enum.
|
|
|
|
DisplayName string // DisplayName is the enum name with word-breaks.
|
|
|
|
Name string // Name is the language-specific enum name.
|
|
|
|
Value string
|
|
|
|
Comment string
|
|
|
|
DeprecationMessage string
|
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
// docNestedType represents a complex type.
|
|
|
|
type docNestedType struct {
|
2021-02-09 17:04:02 +00:00
|
|
|
Name string
|
2023-08-09 00:52:32 +00:00
|
|
|
Input bool
|
2021-02-09 17:04:02 +00:00
|
|
|
AnchorID string
|
|
|
|
Properties map[string][]property
|
|
|
|
EnumValues map[string][]enum
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
// propertyType represents the type of a property.
|
|
|
|
type propertyType struct {
|
2021-04-17 22:33:23 +00:00
|
|
|
DisplayName string
|
|
|
|
DescriptionName string // Name used in description list.
|
|
|
|
Name string
|
2020-03-09 17:35:20 +00:00
|
|
|
// Link can be a link to an anchor tag on the same
|
|
|
|
// page, or to another page/site.
|
|
|
|
Link string
|
|
|
|
}
|
|
|
|
|
2021-04-17 22:33:23 +00:00
|
|
|
// paramSeparator is for data passed to the separator template.
|
|
|
|
type paramSeparator struct {
|
|
|
|
Indent string
|
|
|
|
}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
// formalParam represents the formal parameters of a constructor
|
|
|
|
// or a lookup function.
|
|
|
|
type formalParam struct {
|
2020-03-09 17:35:20 +00:00
|
|
|
Name string
|
2020-03-12 00:58:12 +00:00
|
|
|
Type propertyType
|
2020-03-09 17:35:20 +00:00
|
|
|
|
|
|
|
// This is the language specific optional type indicator.
|
|
|
|
// For example, in nodejs this is the character "?" and in Go
|
|
|
|
// it's "*".
|
|
|
|
OptionalFlag string
|
|
|
|
|
|
|
|
DefaultValue string
|
2020-04-17 18:46:02 +00:00
|
|
|
|
|
|
|
// Comment is an optional description of the parameter.
|
|
|
|
Comment string
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
|
2020-04-02 00:22:23 +00:00
|
|
|
type packageDetails struct {
|
2023-01-05 21:08:16 +00:00
|
|
|
DisplayName string
|
|
|
|
Repository string
|
|
|
|
RepositoryName string
|
|
|
|
License string
|
|
|
|
Notes string
|
|
|
|
Version string
|
2020-04-02 00:22:23 +00:00
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
type resourceDocArgs struct {
|
|
|
|
Header header
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2020-04-17 18:45:06 +00:00
|
|
|
Tool string
|
|
|
|
// LangChooserLanguages is a comma-separated list of languages to pass to the
|
2020-05-16 00:33:56 +00:00
|
|
|
// language chooser shortcode. Use this to customize the languages shown for a
|
|
|
|
// resource. By default, the language chooser will show all languages supported
|
|
|
|
// by Pulumi for all resources.
|
2024-07-09 14:54:50 +00:00
|
|
|
// Supported values are "typescript", "python", "go", "csharp", "java", "yaml"
|
2020-04-17 18:45:06 +00:00
|
|
|
LangChooserLanguages string
|
|
|
|
|
2024-03-21 13:41:07 +00:00
|
|
|
// CreationExampleSyntax is a map from language to the rendered HTML for the
|
|
|
|
// creation example syntax where the key is the language name and the value is
|
|
|
|
// a piece of code that shows how to create a new instance of the resource with default placeholder values.
|
|
|
|
CreationExampleSyntax map[string]string
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
// Comment represents the introductory resource comment.
|
2020-04-07 00:01:33 +00:00
|
|
|
Comment string
|
2024-07-09 14:54:50 +00:00
|
|
|
ExamplesSection examplesSection
|
2020-04-07 00:01:33 +00:00
|
|
|
DeprecationMessage string
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2020-11-09 14:12:58 +00:00
|
|
|
// Import
|
|
|
|
ImportDocs string
|
|
|
|
|
2020-04-17 18:46:02 +00:00
|
|
|
// ConstructorParams is a map from language to the rendered HTML for the constructor's
|
|
|
|
// arguments.
|
2020-03-09 17:35:20 +00:00
|
|
|
ConstructorParams map[string]string
|
2020-04-17 18:46:02 +00:00
|
|
|
// ConstructorParamsTyped is the typed set of parameters for the constructor, in order.
|
|
|
|
ConstructorParamsTyped map[string][]formalParam
|
2020-03-09 17:35:20 +00:00
|
|
|
// ConstructorResource is the resource that is being constructed or
|
|
|
|
// is the result of a constructor-like function.
|
2020-03-12 00:58:12 +00:00
|
|
|
ConstructorResource map[string]propertyType
|
|
|
|
// ArgsRequired is a flag indicating if the args param is required
|
|
|
|
// when creating a new resource.
|
|
|
|
ArgsRequired bool
|
|
|
|
|
|
|
|
// InputProperties is a map per language and a corresponding slice of
|
|
|
|
// input properties accepted as args while creating a new resource.
|
|
|
|
InputProperties map[string][]property
|
|
|
|
// OutputProperties is a map per language and a corresponding slice of
|
|
|
|
// output properties returned when a new instance of the resource is
|
|
|
|
// created.
|
|
|
|
OutputProperties map[string][]property
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
// LookupParams is a map of the param string to be rendered per language
|
|
|
|
// for looking-up a resource.
|
|
|
|
LookupParams map[string]string
|
2020-03-12 00:58:12 +00:00
|
|
|
// StateInputs is a map per language and the corresponding slice of
|
|
|
|
// state input properties required while looking-up an existing resource.
|
|
|
|
StateInputs map[string][]property
|
|
|
|
// StateParam is the type name of the state param, if any.
|
|
|
|
StateParam string
|
|
|
|
|
|
|
|
// NestedTypes is a slice of the nested types used in the input and
|
|
|
|
// output properties.
|
|
|
|
NestedTypes []docNestedType
|
Resource docs: emit supporting types beyond the 200 limit (#16185)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Originally motivated by uncontrolled pseudo-recurcive type expansion in
AWS WafV2, we've limited the number of types that we should in the docs
to 200: https://github.com/pulumi/pulumi/pull/12070
Our large customer that publishes their own packages and docs came back
to us and said they have legitimate use cases with more than 200 types:
#15507
I've grabbed stats about our current packages and still found a few
offenders:
```
"aws:lex/v2modelsIntent:V2modelsIntent" 920
"aws:wafv2/ruleGroup:RuleGroup" 310
"aws:wafv2/webAcl:WebAcl" 523
"azure-native:datafactory:Dataset" 256
"azure-native:datafactory:LinkedService" 299
"azure-native:datafactory:Pipeline" 618
"azure-native:datamigration:ServiceTask" 291
"azure-native:datamigration:Task" 291
"aws-native:quicksight:Analysis" 589
"aws-native:quicksight:Dashboard" 606
"aws-native:quicksight:Template" 590
```
Therefore, I'm not entirely removing the limit in this PR, but
a) bumping the default to 1000
b) applying 200 to the known offenders only
I don't love it's hard coded, but I haven't found a place to add simple
configuration nob. Anyway, it's slightly less hard-coded than it used to
be.
Fixes #15507
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
- Existing docs gen tests cover that I haven't broken anything
- I re-generated the AWS docs and they had no changes
<!---
User-facing changes require a CHANGELOG entry.
-->
- [x] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-05-13 14:58:33 +00:00
|
|
|
// Maximum number of nested types to show.
|
|
|
|
MaxNestedTypes int
|
2020-04-02 00:22:23 +00:00
|
|
|
|
2021-08-12 21:31:15 +00:00
|
|
|
// A list of methods associated with the resource.
|
|
|
|
Methods []methodDocArgs
|
|
|
|
|
2020-04-02 00:22:23 +00:00
|
|
|
PackageDetails packageDetails
|
2020-03-12 00:58:12 +00:00
|
|
|
}
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2020-04-03 18:26:52 +00:00
|
|
|
// typeUsage represents a nested type's usage.
|
|
|
|
type typeUsage struct {
|
2020-03-12 00:58:12 +00:00
|
|
|
Input bool
|
|
|
|
Output bool
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
// nestedTypeUsageInfo is a type-alias for a map of Pulumi type-tokens
|
2020-04-03 18:26:52 +00:00
|
|
|
// and whether or not the type is used as an input and/or output
|
2020-03-12 00:58:12 +00:00
|
|
|
// properties.
|
2020-04-03 18:26:52 +00:00
|
|
|
type nestedTypeUsageInfo map[string]typeUsage
|
2020-03-12 00:58:12 +00:00
|
|
|
|
|
|
|
func (ss nestedTypeUsageInfo) add(s string, input bool) {
|
|
|
|
if v, ok := ss[s]; ok {
|
|
|
|
if input {
|
|
|
|
v.Input = true
|
|
|
|
} else {
|
|
|
|
v.Output = true
|
|
|
|
}
|
|
|
|
ss[s] = v
|
|
|
|
return
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-04-03 18:26:52 +00:00
|
|
|
ss[s] = typeUsage{
|
2020-03-12 00:58:12 +00:00
|
|
|
Input: input,
|
|
|
|
Output: !input,
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:26:52 +00:00
|
|
|
// contains returns true if the token already exists and matches the
|
|
|
|
// input or output flag of the token.
|
|
|
|
func (ss nestedTypeUsageInfo) contains(token string, input bool) bool {
|
|
|
|
a, ok := ss[token]
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if input && a.Input {
|
|
|
|
return true
|
|
|
|
} else if !input && a.Output {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type modContext struct {
|
2022-12-12 14:55:35 +00:00
|
|
|
pkg schema.PackageReference
|
2021-10-06 15:03:21 +00:00
|
|
|
mod string
|
|
|
|
inputTypes []*schema.ObjectType
|
|
|
|
resources []*schema.Resource
|
|
|
|
functions []*schema.Function
|
|
|
|
typeDetails map[*schema.ObjectType]*typeDetails
|
|
|
|
children []*modContext
|
|
|
|
tool string
|
|
|
|
docGenContext *docGenContext
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *modContext) withDocGenContext(dctx *docGenContext) *modContext {
|
|
|
|
if mod == nil {
|
|
|
|
return nil
|
|
|
|
}
|
all: Fix revive issues
Fixes the following issues found by revive
included in the latest release of golangci-lint.
Full list of issues:
**pkg**
```
backend/display/object_diff.go:47:10: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
backend/display/object_diff.go:716:12: redefines-builtin-id: redefinition of the built-in function delete (revive)
backend/display/object_diff.go:742:14: redefines-builtin-id: redefinition of the built-in function delete (revive)
backend/display/object_diff.go:983:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (revive)
backend/httpstate/backend.go:1814:4: redefines-builtin-id: redefinition of the built-in function cap (revive)
backend/httpstate/backend.go:1824:5: redefines-builtin-id: redefinition of the built-in function cap (revive)
backend/httpstate/client/client.go:444:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
backend/httpstate/client/client.go:455:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
cmd/pulumi/org.go:113:4: if-return: redundant if ...; err != nil check, just return error instead. (revive)
cmd/pulumi/util.go:216:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
codegen/docs/gen.go:428:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
codegen/hcl2/model/expression.go:2151:5: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:151:2: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:329:3: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:381:5: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/nodejs/gen.go:1367:5: redefines-builtin-id: redefinition of the built-in function copy (revive)
codegen/python/gen_program_expressions.go:136:2: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/python/gen_program_expressions.go:142:3: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/report/report.go:126:6: redefines-builtin-id: redefinition of the built-in function panic (revive)
codegen/schema/docs_test.go:210:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
codegen/schema/schema.go:790:2: redefines-builtin-id: redefinition of the built-in type any (revive)
codegen/schema/schema.go:793:4: redefines-builtin-id: redefinition of the built-in type any (revive)
resource/deploy/plan.go:506:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
resource/deploy/snapshot_test.go:59:3: redefines-builtin-id: redefinition of the built-in function copy (revive)
resource/deploy/state_builder.go:108:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
```
**sdk**
```
go/common/resource/plugin/context.go:142:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
go/common/resource/plugin/plugin.go:142:12: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (revive)
go/common/resource/properties_diff.go:114:2: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:117:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:122:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:127:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:132:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/util/deepcopy/copy.go:30:1: redefines-builtin-id: redefinition of the built-in function copy (revive)
go/common/workspace/creds.go:242:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi-language-go/main.go:569:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi-language-go/main.go:706:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi/run_test.go:925:2: redefines-builtin-id: redefinition of the built-in type any (revive)
go/pulumi/run_test.go:933:3: redefines-builtin-id: redefinition of the built-in type any (revive)
nodejs/cmd/pulumi-language-nodejs/main.go:778:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/cmd/pulumi-language-python/main.go:1011:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/cmd/pulumi-language-python/main.go:863:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/python.go:230:2: redefines-builtin-id: redefinition of the built-in function print (revive)
```
**tests**
```
integration/integration_util_test.go:282:11: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
```
2023-03-20 23:48:02 +00:00
|
|
|
newctx := *mod
|
|
|
|
newctx.docGenContext = dctx
|
2023-06-28 16:02:04 +00:00
|
|
|
children := slice.Prealloc[*modContext](len(newctx.children))
|
all: Fix revive issues
Fixes the following issues found by revive
included in the latest release of golangci-lint.
Full list of issues:
**pkg**
```
backend/display/object_diff.go:47:10: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
backend/display/object_diff.go:716:12: redefines-builtin-id: redefinition of the built-in function delete (revive)
backend/display/object_diff.go:742:14: redefines-builtin-id: redefinition of the built-in function delete (revive)
backend/display/object_diff.go:983:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (revive)
backend/httpstate/backend.go:1814:4: redefines-builtin-id: redefinition of the built-in function cap (revive)
backend/httpstate/backend.go:1824:5: redefines-builtin-id: redefinition of the built-in function cap (revive)
backend/httpstate/client/client.go:444:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
backend/httpstate/client/client.go:455:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
cmd/pulumi/org.go:113:4: if-return: redundant if ...; err != nil check, just return error instead. (revive)
cmd/pulumi/util.go:216:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
codegen/docs/gen.go:428:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
codegen/hcl2/model/expression.go:2151:5: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:151:2: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:329:3: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:381:5: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/nodejs/gen.go:1367:5: redefines-builtin-id: redefinition of the built-in function copy (revive)
codegen/python/gen_program_expressions.go:136:2: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/python/gen_program_expressions.go:142:3: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/report/report.go:126:6: redefines-builtin-id: redefinition of the built-in function panic (revive)
codegen/schema/docs_test.go:210:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
codegen/schema/schema.go:790:2: redefines-builtin-id: redefinition of the built-in type any (revive)
codegen/schema/schema.go:793:4: redefines-builtin-id: redefinition of the built-in type any (revive)
resource/deploy/plan.go:506:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
resource/deploy/snapshot_test.go:59:3: redefines-builtin-id: redefinition of the built-in function copy (revive)
resource/deploy/state_builder.go:108:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
```
**sdk**
```
go/common/resource/plugin/context.go:142:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
go/common/resource/plugin/plugin.go:142:12: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (revive)
go/common/resource/properties_diff.go:114:2: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:117:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:122:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:127:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:132:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/util/deepcopy/copy.go:30:1: redefines-builtin-id: redefinition of the built-in function copy (revive)
go/common/workspace/creds.go:242:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi-language-go/main.go:569:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi-language-go/main.go:706:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi/run_test.go:925:2: redefines-builtin-id: redefinition of the built-in type any (revive)
go/pulumi/run_test.go:933:3: redefines-builtin-id: redefinition of the built-in type any (revive)
nodejs/cmd/pulumi-language-nodejs/main.go:778:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/cmd/pulumi-language-python/main.go:1011:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/cmd/pulumi-language-python/main.go:863:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/python.go:230:2: redefines-builtin-id: redefinition of the built-in function print (revive)
```
**tests**
```
integration/integration_util_test.go:282:11: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
```
2023-03-20 23:48:02 +00:00
|
|
|
for _, c := range newctx.children {
|
2021-10-06 15:03:21 +00:00
|
|
|
children = append(children, c.withDocGenContext(dctx))
|
|
|
|
}
|
all: Fix revive issues
Fixes the following issues found by revive
included in the latest release of golangci-lint.
Full list of issues:
**pkg**
```
backend/display/object_diff.go:47:10: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
backend/display/object_diff.go:716:12: redefines-builtin-id: redefinition of the built-in function delete (revive)
backend/display/object_diff.go:742:14: redefines-builtin-id: redefinition of the built-in function delete (revive)
backend/display/object_diff.go:983:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (revive)
backend/httpstate/backend.go:1814:4: redefines-builtin-id: redefinition of the built-in function cap (revive)
backend/httpstate/backend.go:1824:5: redefines-builtin-id: redefinition of the built-in function cap (revive)
backend/httpstate/client/client.go:444:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
backend/httpstate/client/client.go:455:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
cmd/pulumi/org.go:113:4: if-return: redundant if ...; err != nil check, just return error instead. (revive)
cmd/pulumi/util.go:216:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
codegen/docs/gen.go:428:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
codegen/hcl2/model/expression.go:2151:5: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:151:2: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:329:3: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/hcl2/syntax/comments.go:381:5: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/nodejs/gen.go:1367:5: redefines-builtin-id: redefinition of the built-in function copy (revive)
codegen/python/gen_program_expressions.go:136:2: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/python/gen_program_expressions.go:142:3: redefines-builtin-id: redefinition of the built-in function close (revive)
codegen/report/report.go:126:6: redefines-builtin-id: redefinition of the built-in function panic (revive)
codegen/schema/docs_test.go:210:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
codegen/schema/schema.go:790:2: redefines-builtin-id: redefinition of the built-in type any (revive)
codegen/schema/schema.go:793:4: redefines-builtin-id: redefinition of the built-in type any (revive)
resource/deploy/plan.go:506:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
resource/deploy/snapshot_test.go:59:3: redefines-builtin-id: redefinition of the built-in function copy (revive)
resource/deploy/state_builder.go:108:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
```
**sdk**
```
go/common/resource/plugin/context.go:142:2: redefines-builtin-id: redefinition of the built-in function copy (revive)
go/common/resource/plugin/plugin.go:142:12: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (revive)
go/common/resource/properties_diff.go:114:2: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:117:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:122:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:127:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/resource/properties_diff.go:132:4: redefines-builtin-id: redefinition of the built-in function len (revive)
go/common/util/deepcopy/copy.go:30:1: redefines-builtin-id: redefinition of the built-in function copy (revive)
go/common/workspace/creds.go:242:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi-language-go/main.go:569:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi-language-go/main.go:706:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
go/pulumi/run_test.go:925:2: redefines-builtin-id: redefinition of the built-in type any (revive)
go/pulumi/run_test.go:933:3: redefines-builtin-id: redefinition of the built-in type any (revive)
nodejs/cmd/pulumi-language-nodejs/main.go:778:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/cmd/pulumi-language-python/main.go:1011:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/cmd/pulumi-language-python/main.go:863:2: if-return: redundant if ...; err != nil check, just return error instead. (revive)
python/python.go:230:2: redefines-builtin-id: redefinition of the built-in function print (revive)
```
**tests**
```
integration/integration_util_test.go:282:11: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive)
```
2023-03-20 23:48:02 +00:00
|
|
|
newctx.children = children
|
|
|
|
return &newctx
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2024-07-09 14:54:50 +00:00
|
|
|
// getSupportedLanguages returns the list of supported languages based on the overlay configuration.
|
|
|
|
// If `isOverlay` is false or `overlaySupportedLanguages` is empty/nil, it returns the default list of supported languages.
|
|
|
|
// Otherwise, it filters the `overlaySupportedLanguages` to ensure that they are a subset of the default supported languages.
|
|
|
|
func (dctx *docGenContext) getSupportedLanguages(isOverlay bool, overlaySupportedLanguages []string) []string {
|
|
|
|
if !isOverlay || len(overlaySupportedLanguages) == 0 {
|
|
|
|
return dctx.supportedLanguages
|
|
|
|
}
|
|
|
|
var supportedLanguages []string
|
|
|
|
allLanguages := codegen.NewStringSet(dctx.supportedLanguages...)
|
|
|
|
for _, lang := range overlaySupportedLanguages {
|
|
|
|
if allLanguages.Has(lang) {
|
|
|
|
supportedLanguages = append(supportedLanguages, lang)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return supportedLanguages
|
|
|
|
}
|
|
|
|
|
|
|
|
// getSupportedSnippetLanguages returns a comma separated string containing the supported snippet languages for the given type
|
|
|
|
// based on the overlay configuration.
|
|
|
|
// If the type is not an overlay or if there are no overlay supported languages, all languages are supported.
|
|
|
|
// Internally this calls the getSupportedLanguages function to retrieve the supported languages and replaces "nodejs"
|
|
|
|
// with "typescript" because snippet languages expect "typescript" instead of "nodejs".
|
|
|
|
func (dctx *docGenContext) getSupportedSnippetLanguages(isOverlay bool, overlaySupportedLanguages []string) string {
|
|
|
|
supportedLanguages := dctx.getSupportedLanguages(isOverlay, overlaySupportedLanguages)
|
|
|
|
supportedSnippetLanguages := make([]string, len(supportedLanguages))
|
|
|
|
for idx, lang := range supportedLanguages {
|
|
|
|
if lang == "nodejs" {
|
|
|
|
lang = "typescript"
|
|
|
|
}
|
|
|
|
supportedSnippetLanguages[idx] = lang
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(supportedSnippetLanguages, ",")
|
|
|
|
}
|
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
func resourceName(r *schema.Resource) string {
|
|
|
|
if r.IsProvider {
|
|
|
|
return "Provider"
|
|
|
|
}
|
2020-04-28 00:47:01 +00:00
|
|
|
return strings.Title(tokenToName(r.Token))
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
func (dctx *docGenContext) getLanguageDocHelper(lang string) codegen.DocLanguageHelper {
|
|
|
|
if h, ok := dctx.docHelpers[lang]; ok {
|
2020-03-12 00:58:12 +00:00
|
|
|
return h
|
|
|
|
}
|
2021-11-13 02:37:17 +00:00
|
|
|
panic(fmt.Errorf("could not find a doc lang helper for %s", lang))
|
2020-03-12 00:58:12 +00:00
|
|
|
}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
type propertyCharacteristics struct {
|
|
|
|
// input is a flag indicating if the property is an input type.
|
|
|
|
input bool
|
|
|
|
}
|
|
|
|
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
func (mod *modContext) details(t *schema.ObjectType) *typeDetails {
|
|
|
|
details, ok := mod.typeDetails[t]
|
|
|
|
if !ok {
|
|
|
|
details = &typeDetails{}
|
|
|
|
if mod.typeDetails == nil {
|
|
|
|
mod.typeDetails = map[*schema.ObjectType]*typeDetails{}
|
|
|
|
}
|
|
|
|
mod.typeDetails[t] = details
|
|
|
|
}
|
|
|
|
return details
|
|
|
|
}
|
|
|
|
|
2020-05-16 00:33:56 +00:00
|
|
|
// getLanguageModuleName transforms the current module's name to a
|
|
|
|
// language-specific name using the language info, if any, for the
|
|
|
|
// current package.
|
|
|
|
func (mod *modContext) getLanguageModuleName(lang string) string {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-05-16 00:33:56 +00:00
|
|
|
modName := mod.mod
|
2020-04-03 18:26:52 +00:00
|
|
|
lookupKey := lang + "_" + modName
|
2021-10-06 15:03:21 +00:00
|
|
|
if v, ok := mod.docGenContext.langModuleNameLookup[lookupKey]; ok {
|
2020-04-03 18:26:52 +00:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
switch lang {
|
|
|
|
case "go":
|
2020-08-21 22:34:57 +00:00
|
|
|
// Go module names use lowercase.
|
|
|
|
modName = strings.ToLower(modName)
|
2021-10-06 15:03:21 +00:00
|
|
|
if override, ok := dctx.goPkgInfo.ModuleToPackage[modName]; ok {
|
2020-04-03 18:26:52 +00:00
|
|
|
modName = override
|
|
|
|
}
|
|
|
|
case "csharp":
|
2021-10-06 15:03:21 +00:00
|
|
|
if override, ok := dctx.csharpPkgInfo.Namespaces[modName]; ok {
|
2020-04-03 18:26:52 +00:00
|
|
|
modName = override
|
|
|
|
}
|
2020-04-11 01:28:14 +00:00
|
|
|
case "nodejs":
|
2021-10-06 15:03:21 +00:00
|
|
|
if override, ok := dctx.nodePkgInfo.ModuleToPackage[modName]; ok {
|
2020-04-11 01:28:14 +00:00
|
|
|
modName = override
|
|
|
|
}
|
2020-08-19 15:34:06 +00:00
|
|
|
case "python":
|
2021-10-06 15:03:21 +00:00
|
|
|
if override, ok := dctx.pythonPkgInfo.ModuleNameOverrides[modName]; ok {
|
2020-08-19 15:34:06 +00:00
|
|
|
modName = override
|
|
|
|
}
|
2020-04-03 18:26:52 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
mod.docGenContext.langModuleNameLookup[lookupKey] = modName
|
2020-04-03 18:26:52 +00:00
|
|
|
return modName
|
|
|
|
}
|
|
|
|
|
2020-04-07 00:01:33 +00:00
|
|
|
// cleanTypeString removes any namespaces from the generated type string for all languages.
|
|
|
|
// The result of this function should be used display purposes only.
|
|
|
|
func (mod *modContext) cleanTypeString(t schema.Type, langTypeString, lang, modName string, isInput bool) string {
|
2020-04-10 21:07:52 +00:00
|
|
|
switch lang {
|
Display full type names in Python references in the docs (#15784)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Currently, our resource API docs for Python only display a type name
itself. If the type is defined in a different module, we do not indicate
this explicitly, which causes confusion.
For example, [K8s Pod
Inputs](https://www.pulumi.com/registry/packages/kubernetes/api-docs/core/v1/pod/#inputs)
is in `core.v1` module itself but refer to the `meta.v1.ObjectMeta`
type. Node.js docs display the type as
<img width="719" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/fb3e8fc5-7dc8-4661-ac6f-95e7d7918cfc">
but Python simply shows
<img width="725" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/4cd4c09c-13cb-4070-b716-0b78ad98379b">
The same problem exists when we reference types from external packages,
and even for composed types like `Sequence[some_external_type]`.
This PR removes a special case for Python that reduces a full type name
to its name. Instead, it executes on the same path as Node.js and C#.
I had to apply some cleaning to Python types to remove underscore
prefixes of modules. We use underscore-prefixed imports in SDK gen, but
they should not be visible in user docs.
I expect we need to apply the same fix to Go, but I suggest we do that
as a follow-up.
Testing: the existing test suite seems adequate for testing the change.
All the discrepancies look like improvements to me.
Fixes #15137
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [x] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-04-01 14:59:50 +00:00
|
|
|
case "go":
|
2020-12-09 20:20:11 +00:00
|
|
|
langTypeString = cleanOptionalIdentifier(langTypeString, lang)
|
2020-04-07 00:01:33 +00:00
|
|
|
parts := strings.Split(langTypeString, ".")
|
|
|
|
return parts[len(parts)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanCSharpName := func(pkgName, objModName string) string {
|
2020-04-10 21:07:52 +00:00
|
|
|
// C# types can be wrapped in enumerable types such as List<> or Dictionary<>, so we have to
|
|
|
|
// only replace the namespace between the < and the > characters.
|
|
|
|
qualifier := "Inputs"
|
|
|
|
if !isInput {
|
|
|
|
qualifier = "Outputs"
|
|
|
|
}
|
|
|
|
|
2020-04-07 00:01:33 +00:00
|
|
|
var csharpNS string
|
|
|
|
// This type could be at the package-level, so it won't have a module name.
|
|
|
|
if objModName != "" {
|
|
|
|
csharpNS = fmt.Sprintf("Pulumi.%s.%s.%s.", title(pkgName, lang), title(objModName, lang), qualifier)
|
|
|
|
} else {
|
|
|
|
csharpNS = fmt.Sprintf("Pulumi.%s.%s.", title(pkgName, lang), qualifier)
|
|
|
|
}
|
|
|
|
return strings.ReplaceAll(langTypeString, csharpNS, "")
|
|
|
|
}
|
|
|
|
|
2020-04-10 21:07:52 +00:00
|
|
|
cleanNodeJSName := func(objModName string) string {
|
2020-04-11 01:28:14 +00:00
|
|
|
// The nodejs codegen currently doesn't use the ModuleToPackage override available
|
|
|
|
// in the k8s package's schema. So we'll manually strip some known module names for k8s.
|
|
|
|
// TODO[pulumi/pulumi#4325]: Remove this block once the nodejs code gen is able to use the
|
|
|
|
// package name overrides for modules.
|
|
|
|
if isKubernetesPackage(mod.pkg) {
|
|
|
|
langTypeString = strings.ReplaceAll(langTypeString, "k8s.io.", "")
|
|
|
|
langTypeString = strings.ReplaceAll(langTypeString, "apiserver.", "")
|
|
|
|
langTypeString = strings.ReplaceAll(langTypeString, "rbac.authorization.v1.", "")
|
|
|
|
langTypeString = strings.ReplaceAll(langTypeString, "rbac.authorization.v1alpha1.", "")
|
|
|
|
langTypeString = strings.ReplaceAll(langTypeString, "rbac.authorization.v1beta1.", "")
|
|
|
|
}
|
2020-04-10 21:07:52 +00:00
|
|
|
objModName = strings.ReplaceAll(objModName, "/", ".") + "."
|
|
|
|
return strings.ReplaceAll(langTypeString, objModName, "")
|
|
|
|
}
|
|
|
|
|
Display full type names in Python references in the docs (#15784)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Currently, our resource API docs for Python only display a type name
itself. If the type is defined in a different module, we do not indicate
this explicitly, which causes confusion.
For example, [K8s Pod
Inputs](https://www.pulumi.com/registry/packages/kubernetes/api-docs/core/v1/pod/#inputs)
is in `core.v1` module itself but refer to the `meta.v1.ObjectMeta`
type. Node.js docs display the type as
<img width="719" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/fb3e8fc5-7dc8-4661-ac6f-95e7d7918cfc">
but Python simply shows
<img width="725" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/4cd4c09c-13cb-4070-b716-0b78ad98379b">
The same problem exists when we reference types from external packages,
and even for composed types like `Sequence[some_external_type]`.
This PR removes a special case for Python that reduces a full type name
to its name. Instead, it executes on the same path as Node.js and C#.
I had to apply some cleaning to Python types to remove underscore
prefixes of modules. We use underscore-prefixed imports in SDK gen, but
they should not be visible in user docs.
I expect we need to apply the same fix to Go, but I suggest we do that
as a follow-up.
Testing: the existing test suite seems adequate for testing the change.
All the discrepancies look like improvements to me.
Fixes #15137
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [x] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-04-01 14:59:50 +00:00
|
|
|
cleanPythonName := func(objModName string) string {
|
|
|
|
// SDK codegen aliases imported top-level inputs as _root_inputs and _root_enums, e.g.
|
|
|
|
// from .. import _inputs as _root_inputs
|
|
|
|
// This is our implementation detail, so we shouldn't show this prefix
|
|
|
|
// in end-user documentation. Remove them here.
|
|
|
|
// Top-level arg types will be displayed without any module prefix.
|
|
|
|
objModName = strings.Replace(objModName, "root_enums.", "", 1)
|
|
|
|
objModName = strings.Replace(objModName, "root_inputs.", "", 1)
|
|
|
|
|
|
|
|
// SDK codegen aliases imported modules with underscored names, e.g.
|
|
|
|
// from ... import meta as _meta
|
|
|
|
// Therefore, type references for Python all have _ before module names.
|
|
|
|
// This is our implementation detail, so we shouldn't show those underscores
|
|
|
|
// in end-user documentation. Remove them here.
|
|
|
|
// We need to keep underscores inside module names though, as in 'pulumi_random'.
|
|
|
|
return removeLeadingUnderscores(objModName)
|
|
|
|
}
|
|
|
|
|
2023-08-09 00:52:32 +00:00
|
|
|
switch t := t.(type) {
|
|
|
|
case *schema.ObjectType:
|
|
|
|
// Strip "Args" suffixes from display names for everything but Python inputs.
|
|
|
|
if lang != "python" || (lang == "python" && !isInput) {
|
|
|
|
name := tokenToName(t.Token)
|
|
|
|
nameWithArgs := name + "Args"
|
|
|
|
|
|
|
|
// If the langTypeString looks like it's a concatenation of its name and "Args", strip out the "Args".
|
|
|
|
if strings.Contains(langTypeString, nameWithArgs) {
|
|
|
|
langTypeString = strings.ReplaceAll(langTypeString, nameWithArgs, name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-10 21:07:52 +00:00
|
|
|
switch t := t.(type) {
|
|
|
|
case *schema.ArrayType:
|
|
|
|
if schema.IsPrimitiveType(t.ElementType) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
return mod.cleanTypeString(t.ElementType, langTypeString, lang, modName, isInput)
|
|
|
|
case *schema.UnionType:
|
|
|
|
for _, e := range t.ElementTypes {
|
|
|
|
if schema.IsPrimitiveType(e) {
|
|
|
|
continue
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
2020-04-10 21:07:52 +00:00
|
|
|
return mod.cleanTypeString(e, langTypeString, lang, modName, isInput)
|
|
|
|
}
|
|
|
|
case *schema.ObjectType:
|
|
|
|
objTypeModName := mod.pkg.TokenToModule(t.Token)
|
|
|
|
if objTypeModName != mod.mod {
|
2020-05-16 00:33:56 +00:00
|
|
|
modName = mod.getLanguageModuleName(lang)
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-10 21:07:52 +00:00
|
|
|
|
Display full type names in Python references in the docs (#15784)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Currently, our resource API docs for Python only display a type name
itself. If the type is defined in a different module, we do not indicate
this explicitly, which causes confusion.
For example, [K8s Pod
Inputs](https://www.pulumi.com/registry/packages/kubernetes/api-docs/core/v1/pod/#inputs)
is in `core.v1` module itself but refer to the `meta.v1.ObjectMeta`
type. Node.js docs display the type as
<img width="719" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/fb3e8fc5-7dc8-4661-ac6f-95e7d7918cfc">
but Python simply shows
<img width="725" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/4cd4c09c-13cb-4070-b716-0b78ad98379b">
The same problem exists when we reference types from external packages,
and even for composed types like `Sequence[some_external_type]`.
This PR removes a special case for Python that reduces a full type name
to its name. Instead, it executes on the same path as Node.js and C#.
I had to apply some cleaning to Python types to remove underscore
prefixes of modules. We use underscore-prefixed imports in SDK gen, but
they should not be visible in user docs.
I expect we need to apply the same fix to Go, but I suggest we do that
as a follow-up.
Testing: the existing test suite seems adequate for testing the change.
All the discrepancies look like improvements to me.
Fixes #15137
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [x] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-04-01 14:59:50 +00:00
|
|
|
switch lang {
|
|
|
|
case "nodejs":
|
2020-04-10 21:07:52 +00:00
|
|
|
return cleanNodeJSName(modName)
|
Display full type names in Python references in the docs (#15784)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Currently, our resource API docs for Python only display a type name
itself. If the type is defined in a different module, we do not indicate
this explicitly, which causes confusion.
For example, [K8s Pod
Inputs](https://www.pulumi.com/registry/packages/kubernetes/api-docs/core/v1/pod/#inputs)
is in `core.v1` module itself but refer to the `meta.v1.ObjectMeta`
type. Node.js docs display the type as
<img width="719" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/fb3e8fc5-7dc8-4661-ac6f-95e7d7918cfc">
but Python simply shows
<img width="725" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/4cd4c09c-13cb-4070-b716-0b78ad98379b">
The same problem exists when we reference types from external packages,
and even for composed types like `Sequence[some_external_type]`.
This PR removes a special case for Python that reduces a full type name
to its name. Instead, it executes on the same path as Node.js and C#.
I had to apply some cleaning to Python types to remove underscore
prefixes of modules. We use underscore-prefixed imports in SDK gen, but
they should not be visible in user docs.
I expect we need to apply the same fix to Go, but I suggest we do that
as a follow-up.
Testing: the existing test suite seems adequate for testing the change.
All the discrepancies look like improvements to me.
Fixes #15137
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [x] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-04-01 14:59:50 +00:00
|
|
|
case "csharp":
|
2022-12-12 14:55:35 +00:00
|
|
|
return cleanCSharpName(mod.pkg.Name(), modName)
|
Display full type names in Python references in the docs (#15784)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Currently, our resource API docs for Python only display a type name
itself. If the type is defined in a different module, we do not indicate
this explicitly, which causes confusion.
For example, [K8s Pod
Inputs](https://www.pulumi.com/registry/packages/kubernetes/api-docs/core/v1/pod/#inputs)
is in `core.v1` module itself but refer to the `meta.v1.ObjectMeta`
type. Node.js docs display the type as
<img width="719" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/fb3e8fc5-7dc8-4661-ac6f-95e7d7918cfc">
but Python simply shows
<img width="725" alt="image"
src="https://github.com/pulumi/pulumi/assets/1454008/4cd4c09c-13cb-4070-b716-0b78ad98379b">
The same problem exists when we reference types from external packages,
and even for composed types like `Sequence[some_external_type]`.
This PR removes a special case for Python that reduces a full type name
to its name. Instead, it executes on the same path as Node.js and C#.
I had to apply some cleaning to Python types to remove underscore
prefixes of modules. We use underscore-prefixed imports in SDK gen, but
they should not be visible in user docs.
I expect we need to apply the same fix to Go, but I suggest we do that
as a follow-up.
Testing: the existing test suite seems adequate for testing the change.
All the discrepancies look like improvements to me.
Fixes #15137
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [x] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-04-01 14:59:50 +00:00
|
|
|
case "python":
|
|
|
|
return cleanPythonName(langTypeString)
|
|
|
|
default:
|
|
|
|
return strings.ReplaceAll(langTypeString, modName, "")
|
2020-04-10 21:07:52 +00:00
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
// typeString returns a property type suitable for docs with its display name and the anchor link to
|
|
|
|
// a type if the type of the property is an array or an object.
|
|
|
|
func (mod *modContext) typeString(t schema.Type, lang string, characteristics propertyCharacteristics, insertWordBreaks bool) propertyType {
|
2021-06-24 16:17:55 +00:00
|
|
|
t = codegen.PlainType(t)
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
docLanguageHelper := mod.docGenContext.getLanguageDocHelper(lang)
|
2020-05-16 00:33:56 +00:00
|
|
|
modName := mod.getLanguageModuleName(lang)
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get package definition for %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
langTypeString := docLanguageHelper.GetLanguageTypeString(def, modName, t, characteristics.input)
|
2021-06-24 16:17:55 +00:00
|
|
|
|
|
|
|
if optional, ok := t.(*schema.OptionalType); ok {
|
|
|
|
t = optional.ElementType
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
// If the type is an object type, let's also wrap it with a link to the supporting type
|
|
|
|
// on the same page using an anchor tag.
|
|
|
|
var href string
|
2020-02-27 18:04:34 +00:00
|
|
|
switch t := t.(type) {
|
|
|
|
case *schema.ArrayType:
|
2020-03-17 20:37:40 +00:00
|
|
|
elementLangType := mod.typeString(t.ElementType, lang, characteristics, false)
|
2020-03-09 17:35:20 +00:00
|
|
|
href = elementLangType.Link
|
2020-02-27 18:04:34 +00:00
|
|
|
case *schema.ObjectType:
|
2020-03-09 17:35:20 +00:00
|
|
|
tokenName := tokenToName(t.Token)
|
2020-04-07 00:01:33 +00:00
|
|
|
// Links to anchor tags on the same page must be lower-cased.
|
2022-12-07 18:40:42 +00:00
|
|
|
href = "#" + strings.ToLower(tokenName)
|
2020-12-14 22:40:14 +00:00
|
|
|
case *schema.EnumType:
|
|
|
|
tokenName := tokenToName(t.Token)
|
|
|
|
// Links to anchor tags on the same page must be lower-cased.
|
2022-12-07 18:40:42 +00:00
|
|
|
href = "#" + strings.ToLower(tokenName)
|
2020-12-14 22:40:14 +00:00
|
|
|
case *schema.UnionType:
|
|
|
|
var elements []string
|
|
|
|
for _, e := range t.ElementTypes {
|
|
|
|
elementLangType := mod.typeString(e, lang, characteristics, false)
|
|
|
|
elements = append(elements, elementLangType.DisplayName)
|
|
|
|
}
|
|
|
|
langTypeString = strings.Join(elements, " | ")
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 21:17:14 +00:00
|
|
|
// Strip the namespace/module prefix for the type's display name.
|
2020-04-07 00:01:33 +00:00
|
|
|
displayName := langTypeString
|
|
|
|
if !schema.IsPrimitiveType(t) {
|
|
|
|
displayName = mod.cleanTypeString(t, langTypeString, lang, modName, characteristics.input)
|
2020-03-23 21:17:14 +00:00
|
|
|
}
|
|
|
|
|
2022-05-26 17:44:40 +00:00
|
|
|
displayName = cleanOptionalIdentifier(displayName, lang)
|
|
|
|
langTypeString = cleanOptionalIdentifier(langTypeString, lang)
|
|
|
|
|
|
|
|
// Name and DisplayName should be html-escaped to avoid throwing off rendering for template types in languages like
|
|
|
|
// csharp, Java etc. If word-breaks need to be inserted, then the type string should be html-escaped first.
|
|
|
|
displayName = html.EscapeString(displayName)
|
2020-03-09 17:35:20 +00:00
|
|
|
if insertWordBreaks {
|
2020-03-23 21:17:14 +00:00
|
|
|
displayName = wbr(displayName)
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
2020-04-14 20:34:53 +00:00
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
return propertyType{
|
2022-05-26 17:44:40 +00:00
|
|
|
Name: html.EscapeString(langTypeString),
|
2020-03-23 21:17:14 +00:00
|
|
|
DisplayName: displayName,
|
|
|
|
Link: href,
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 20:34:53 +00:00
|
|
|
// cleanOptionalIdentifier removes the type identifier (i.e. "?" in "string?").
|
|
|
|
func cleanOptionalIdentifier(s, lang string) string {
|
|
|
|
switch lang {
|
|
|
|
case "nodejs":
|
|
|
|
return strings.TrimSuffix(s, "?")
|
|
|
|
case "go":
|
|
|
|
return strings.TrimPrefix(s, "*")
|
|
|
|
case "csharp":
|
|
|
|
return strings.TrimSuffix(s, "?")
|
|
|
|
case "python":
|
2020-08-19 15:34:06 +00:00
|
|
|
if strings.HasPrefix(s, "Optional[") && strings.HasSuffix(s, "]") {
|
|
|
|
s = strings.TrimPrefix(s, "Optional[")
|
|
|
|
s = strings.TrimSuffix(s, "]")
|
|
|
|
return s
|
|
|
|
}
|
2020-04-14 20:34:53 +00:00
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2020-04-17 18:46:02 +00:00
|
|
|
// Resources typically take the same set of parameters to their constructors, and these
|
|
|
|
// are the default comments/descriptions for them.
|
|
|
|
const (
|
|
|
|
ctorNameArgComment = "The unique name of the resource."
|
|
|
|
ctorArgsArgComment = "The arguments to resource properties."
|
|
|
|
ctorOptsArgComment = "Bag of options to control resource's behavior."
|
|
|
|
)
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
func (mod *modContext) genConstructorTS(r *schema.Resource, argsOptional bool) []formalParam {
|
2020-02-27 18:04:34 +00:00
|
|
|
name := resourceName(r)
|
2021-10-06 15:03:21 +00:00
|
|
|
docLangHelper := mod.docGenContext.getLanguageDocHelper("nodejs")
|
2020-04-14 00:27:38 +00:00
|
|
|
|
|
|
|
var argsType string
|
2020-06-22 16:27:17 +00:00
|
|
|
optsType := "CustomResourceOptions"
|
2020-05-06 19:11:31 +00:00
|
|
|
// The args type for k8s package differs from the rest depending on whether we are dealing with
|
|
|
|
// overlay resources or regular k8s resources.
|
2020-04-14 00:27:38 +00:00
|
|
|
if isKubernetesPackage(mod.pkg) {
|
2020-05-06 19:11:31 +00:00
|
|
|
if mod.isKubernetesOverlayModule() {
|
|
|
|
if name == "CustomResource" {
|
|
|
|
argsType = name + "Args"
|
|
|
|
} else {
|
|
|
|
argsType = name + "Opts"
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// The non-schema-based k8s codegen does not apply a suffix to the input types.
|
|
|
|
argsType = name
|
|
|
|
}
|
2020-06-22 16:27:17 +00:00
|
|
|
|
|
|
|
if mod.isComponentResource() {
|
|
|
|
optsType = "ComponentResourceOptions"
|
|
|
|
}
|
2020-04-14 00:27:38 +00:00
|
|
|
} else {
|
|
|
|
argsType = name + "Args"
|
|
|
|
}
|
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
argsFlag := ""
|
|
|
|
if argsOptional {
|
|
|
|
argsFlag = "?"
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
return []formalParam{
|
2020-03-09 17:35:20 +00:00
|
|
|
{
|
|
|
|
Name: "name",
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-03-09 17:35:20 +00:00
|
|
|
Name: "string",
|
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorNameArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "args",
|
|
|
|
OptionalFlag: argsFlag,
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-03-09 17:35:20 +00:00
|
|
|
Name: argsType,
|
2022-12-07 18:40:42 +00:00
|
|
|
Link: "#inputs",
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorArgsArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "opts",
|
|
|
|
OptionalFlag: "?",
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-06-22 16:27:17 +00:00
|
|
|
Name: optsType,
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, optsType),
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorOptsArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
func (mod *modContext) genConstructorGo(r *schema.Resource, argsOptional bool) []formalParam {
|
2020-02-27 18:04:34 +00:00
|
|
|
name := resourceName(r)
|
|
|
|
argsType := name + "Args"
|
2020-03-09 17:35:20 +00:00
|
|
|
argsFlag := ""
|
|
|
|
if argsOptional {
|
|
|
|
argsFlag = "*"
|
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
docLangHelper := mod.docGenContext.getLanguageDocHelper("go")
|
2020-09-20 18:56:52 +00:00
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
return []formalParam{
|
2020-03-09 17:35:20 +00:00
|
|
|
{
|
|
|
|
Name: "ctx",
|
|
|
|
OptionalFlag: "*",
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-04-14 00:27:38 +00:00
|
|
|
Name: "Context",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "Context"),
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-04-18 20:06:43 +00:00
|
|
|
Comment: "Context object for the current deployment.",
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "name",
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-03-09 17:35:20 +00:00
|
|
|
Name: "string",
|
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorNameArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "args",
|
|
|
|
OptionalFlag: argsFlag,
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-03-09 17:35:20 +00:00
|
|
|
Name: argsType,
|
2022-12-07 18:40:42 +00:00
|
|
|
Link: "#inputs",
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorArgsArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "opts",
|
|
|
|
OptionalFlag: "...",
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-04-14 00:27:38 +00:00
|
|
|
Name: "ResourceOption",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "ResourceOption"),
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorOptsArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
func (mod *modContext) genConstructorCS(r *schema.Resource, argsOptional bool) []formalParam {
|
2020-02-27 18:04:34 +00:00
|
|
|
name := resourceName(r)
|
2020-06-22 16:27:17 +00:00
|
|
|
optsType := "CustomResourceOptions"
|
|
|
|
|
2021-02-09 17:04:02 +00:00
|
|
|
if isKubernetesPackage(mod.pkg) && mod.isComponentResource() {
|
|
|
|
optsType = "ComponentResourceOptions"
|
2020-04-14 00:27:38 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
var argsFlag string
|
2020-02-27 18:04:34 +00:00
|
|
|
var argsDefault string
|
2020-03-09 17:35:20 +00:00
|
|
|
if argsOptional {
|
2020-02-27 18:04:34 +00:00
|
|
|
// If the number of required input properties was zero, we can make the args object optional.
|
|
|
|
argsDefault = " = null"
|
2020-03-09 17:35:20 +00:00
|
|
|
argsFlag = "?"
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
docLangHelper := mod.docGenContext.getLanguageDocHelper("csharp")
|
2020-09-20 18:56:52 +00:00
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
return []formalParam{
|
2020-03-09 17:35:20 +00:00
|
|
|
{
|
|
|
|
Name: "name",
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-03-09 17:35:20 +00:00
|
|
|
Name: "string",
|
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorNameArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "args",
|
|
|
|
OptionalFlag: argsFlag,
|
|
|
|
DefaultValue: argsDefault,
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-03-17 20:37:40 +00:00
|
|
|
Name: name + "Args",
|
2022-12-07 18:40:42 +00:00
|
|
|
Link: "#inputs",
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorArgsArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "opts",
|
|
|
|
OptionalFlag: "?",
|
|
|
|
DefaultValue: " = null",
|
2020-03-12 00:58:12 +00:00
|
|
|
Type: propertyType{
|
2020-06-22 16:27:17 +00:00
|
|
|
Name: optsType,
|
2023-12-12 12:19:42 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "Pulumi."+optsType),
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-04-17 18:46:02 +00:00
|
|
|
Comment: ctorOptsArgComment,
|
2020-03-09 17:35:20 +00:00
|
|
|
},
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-21 11:23:36 +00:00
|
|
|
func (mod *modContext) genConstructorYaml() []formalParam {
|
|
|
|
return []formalParam{
|
|
|
|
{
|
|
|
|
Name: "properties",
|
|
|
|
Comment: ctorArgsArgComment,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "options",
|
|
|
|
Comment: ctorOptsArgComment,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *modContext) genConstructorJava(r *schema.Resource, argsOverload bool) []formalParam {
|
|
|
|
name := resourceName(r)
|
|
|
|
optsType := "CustomResourceOptions"
|
|
|
|
|
|
|
|
if mod.isComponentResource() {
|
|
|
|
optsType = "ComponentResourceOptions"
|
|
|
|
}
|
|
|
|
|
|
|
|
docLangHelper := mod.docGenContext.getLanguageDocHelper("java")
|
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
2022-04-21 11:23:36 +00:00
|
|
|
result := []formalParam{
|
|
|
|
{
|
|
|
|
Name: "name",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: "String",
|
|
|
|
},
|
|
|
|
Comment: ctorNameArgComment,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "args",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: name + "Args",
|
2022-12-07 18:40:42 +00:00
|
|
|
Link: "#inputs",
|
2022-04-21 11:23:36 +00:00
|
|
|
},
|
|
|
|
Comment: ctorArgsArgComment,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if !argsOverload {
|
|
|
|
result = append(result, formalParam{
|
|
|
|
Name: "options",
|
|
|
|
OptionalFlag: "@Nullable",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: optsType,
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, optsType),
|
2022-04-21 11:23:36 +00:00
|
|
|
},
|
|
|
|
Comment: ctorOptsArgComment,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-04-17 22:33:23 +00:00
|
|
|
func (mod *modContext) genConstructorPython(r *schema.Resource, argsOptional, argsOverload bool) []formalParam {
|
2021-10-06 15:03:21 +00:00
|
|
|
docLanguageHelper := mod.docGenContext.getLanguageDocHelper("python")
|
2020-08-19 15:34:06 +00:00
|
|
|
isK8sOverlayMod := mod.isKubernetesOverlayModule()
|
2022-12-12 14:55:35 +00:00
|
|
|
isDockerImageResource := mod.pkg.Name() == "docker" && resourceName(r) == "Image"
|
2020-08-19 15:34:06 +00:00
|
|
|
|
|
|
|
// Kubernetes overlay resources use a different ordering of formal params in Python.
|
2021-12-16 20:15:38 +00:00
|
|
|
if isK8sOverlayMod && r.IsOverlay {
|
2020-08-19 15:34:06 +00:00
|
|
|
return getKubernetesOverlayPythonFormalParams(mod.mod)
|
|
|
|
} else if isDockerImageResource {
|
|
|
|
return getDockerImagePythonFormalParams()
|
|
|
|
}
|
|
|
|
|
2023-01-12 17:04:35 +00:00
|
|
|
// We perform at least three appends before iterating over input types.
|
2023-06-28 16:02:04 +00:00
|
|
|
params := slice.Prealloc[formalParam](3 + len(r.InputProperties))
|
2021-04-17 22:33:23 +00:00
|
|
|
|
|
|
|
params = append(params, formalParam{
|
|
|
|
Name: "resource_name",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: "str",
|
|
|
|
},
|
|
|
|
Comment: ctorNameArgComment,
|
|
|
|
})
|
|
|
|
|
|
|
|
if argsOverload {
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
// Determine whether we need to use the alternate args class name (e.g. `<Resource>InitArgs` instead of
|
|
|
|
// `<Resource>Args`) due to an input type with the same name as the resource in the same module.
|
|
|
|
resName := resourceName(r)
|
2023-12-12 12:19:42 +00:00
|
|
|
resArgsName := resName + "Args"
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
for _, inputType := range mod.inputTypes {
|
|
|
|
inputTypeName := strings.Title(tokenToName(inputType.Token))
|
|
|
|
if resName == inputTypeName {
|
2023-12-12 12:19:42 +00:00
|
|
|
resArgsName = resName + "InitArgs"
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
optionalFlag, defaultVal, descriptionName := "", "", resArgsName
|
2021-04-17 22:33:23 +00:00
|
|
|
typeName := descriptionName
|
|
|
|
if argsOptional {
|
|
|
|
optionalFlag, defaultVal, typeName = "optional", " = None", fmt.Sprintf("Optional[%s]", typeName)
|
|
|
|
}
|
|
|
|
params = append(params, formalParam{
|
|
|
|
Name: "args",
|
|
|
|
OptionalFlag: optionalFlag,
|
|
|
|
DefaultValue: defaultVal,
|
|
|
|
Type: propertyType{
|
|
|
|
Name: typeName,
|
|
|
|
DescriptionName: descriptionName,
|
2022-12-07 18:40:42 +00:00
|
|
|
Link: "#inputs",
|
2021-04-17 22:33:23 +00:00
|
|
|
},
|
|
|
|
Comment: ctorArgsArgComment,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-08-19 15:34:06 +00:00
|
|
|
params = append(params, formalParam{
|
|
|
|
Name: "opts",
|
2021-04-17 22:33:23 +00:00
|
|
|
OptionalFlag: "optional",
|
2020-08-19 15:34:06 +00:00
|
|
|
DefaultValue: " = None",
|
|
|
|
Type: propertyType{
|
2021-04-17 22:33:23 +00:00
|
|
|
Name: "Optional[ResourceOptions]",
|
|
|
|
DescriptionName: "ResourceOptions",
|
2022-12-07 18:43:26 +00:00
|
|
|
Link: "/docs/reference/pkg/python/pulumi/#pulumi.ResourceOptions",
|
2020-08-19 15:34:06 +00:00
|
|
|
},
|
2021-04-17 22:33:23 +00:00
|
|
|
Comment: ctorOptsArgComment,
|
2020-08-19 15:34:06 +00:00
|
|
|
})
|
2021-04-17 22:33:23 +00:00
|
|
|
|
|
|
|
if argsOverload {
|
|
|
|
return params
|
|
|
|
}
|
|
|
|
|
2020-08-19 15:34:06 +00:00
|
|
|
for _, p := range r.InputProperties {
|
|
|
|
// If the property defines a const value, then skip it.
|
|
|
|
// For example, in k8s, `apiVersion` and `kind` are often hard-coded
|
|
|
|
// in the SDK and are not really user-provided input properties.
|
|
|
|
if p.ConstValue != nil {
|
|
|
|
continue
|
|
|
|
}
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
typ := docLanguageHelper.GetLanguageTypeString(def, mod.mod, codegen.PlainType(codegen.OptionalType(p)), true /*input*/)
|
2020-08-19 15:34:06 +00:00
|
|
|
params = append(params, formalParam{
|
|
|
|
Name: python.InitParamName(p.Name),
|
|
|
|
DefaultValue: " = None",
|
|
|
|
Type: propertyType{
|
2022-03-04 08:17:41 +00:00
|
|
|
Name: typ,
|
2020-08-19 15:34:06 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return params
|
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
func (mod *modContext) genNestedTypes(member interface{}, resourceType bool) []docNestedType {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-03-12 00:58:12 +00:00
|
|
|
tokens := nestedTypeUsageInfo{}
|
|
|
|
// Collect all of the types for this "member" as a map of resource names
|
|
|
|
// and if it appears in an input object and/or output object.
|
|
|
|
mod.getTypes(member, tokens)
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2023-06-28 16:02:04 +00:00
|
|
|
sortedTokens := slice.Prealloc[string](len(tokens))
|
2021-02-09 17:04:02 +00:00
|
|
|
for token := range tokens {
|
2021-11-19 16:23:06 +00:00
|
|
|
sortedTokens = append(sortedTokens, token)
|
|
|
|
}
|
|
|
|
sort.Strings(sortedTokens)
|
|
|
|
|
|
|
|
var typs []docNestedType
|
|
|
|
for _, token := range sortedTokens {
|
2022-12-12 14:55:35 +00:00
|
|
|
for iter := mod.pkg.Types().Range(); iter.Next(); {
|
|
|
|
t, err := iter.Type()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "error iterating types")
|
2020-12-14 22:40:14 +00:00
|
|
|
switch typ := t.(type) {
|
|
|
|
case *schema.ObjectType:
|
2021-06-24 16:17:55 +00:00
|
|
|
if typ.Token != token || len(typ.Properties) == 0 || typ.IsInputShape() {
|
2020-12-14 22:40:14 +00:00
|
|
|
continue
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
2020-04-03 18:26:52 +00:00
|
|
|
|
2021-02-09 17:04:02 +00:00
|
|
|
// Create a map to hold the per-language properties of this object.
|
2020-12-14 22:40:14 +00:00
|
|
|
props := make(map[string][]property)
|
2021-10-06 15:03:21 +00:00
|
|
|
for _, lang := range dctx.supportedLanguages {
|
2021-06-24 16:17:55 +00:00
|
|
|
props[lang] = mod.getProperties(typ.Properties, lang, true, true, false)
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
2020-05-02 00:13:56 +00:00
|
|
|
|
2020-12-14 22:40:14 +00:00
|
|
|
name := strings.Title(tokenToName(typ.Token))
|
|
|
|
typs = append(typs, docNestedType{
|
2021-02-09 17:04:02 +00:00
|
|
|
Name: wbr(name),
|
|
|
|
AnchorID: strings.ToLower(name),
|
|
|
|
Properties: props,
|
2020-12-14 22:40:14 +00:00
|
|
|
})
|
|
|
|
case *schema.EnumType:
|
|
|
|
if typ.Token != token || len(typ.Elements) == 0 {
|
2020-05-02 00:13:56 +00:00
|
|
|
continue
|
|
|
|
}
|
2020-12-14 22:40:14 +00:00
|
|
|
name := strings.Title(tokenToName(typ.Token))
|
|
|
|
|
|
|
|
enums := make(map[string][]enum)
|
2021-10-06 15:03:21 +00:00
|
|
|
for _, lang := range dctx.supportedLanguages {
|
|
|
|
docLangHelper := dctx.getLanguageDocHelper(lang)
|
2020-12-14 22:40:14 +00:00
|
|
|
|
|
|
|
var langEnumValues []enum
|
|
|
|
for _, e := range typ.Elements {
|
2020-12-16 17:22:44 +00:00
|
|
|
enumName, err := docLangHelper.GetEnumName(e, name)
|
2020-12-14 22:40:14 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
enumID := strings.ToLower(name + propertyLangSeparator + lang)
|
|
|
|
langEnumValues = append(langEnumValues, enum{
|
|
|
|
ID: enumID,
|
|
|
|
DisplayName: wbr(enumName),
|
|
|
|
Name: enumName,
|
|
|
|
Value: fmt.Sprintf("%v", e.Value),
|
|
|
|
Comment: e.Comment,
|
|
|
|
DeprecationMessage: e.DeprecationMessage,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
enums[lang] = langEnumValues
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
|
|
|
|
2020-12-14 22:40:14 +00:00
|
|
|
typs = append(typs, docNestedType{
|
|
|
|
Name: wbr(name),
|
|
|
|
AnchorID: strings.ToLower(name),
|
|
|
|
EnumValues: enums,
|
|
|
|
})
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-09 17:35:20 +00:00
|
|
|
|
2020-12-14 22:40:14 +00:00
|
|
|
sort.Slice(typs, func(i, j int) bool {
|
|
|
|
return typs[i].Name < typs[j].Name
|
2020-02-27 18:04:34 +00:00
|
|
|
})
|
|
|
|
|
2020-12-14 22:40:14 +00:00
|
|
|
return typs
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
// getProperties returns a slice of properties that can be rendered for docs for
|
|
|
|
// the provided slice of properties in the schema.
|
2021-06-24 16:17:55 +00:00
|
|
|
func (mod *modContext) getProperties(properties []*schema.Property, lang string, input, nested, isProvider bool,
|
2021-02-13 00:11:56 +00:00
|
|
|
) []property {
|
2021-08-13 00:20:13 +00:00
|
|
|
return mod.getPropertiesWithIDPrefixAndExclude(properties, lang, input, nested, isProvider, "", nil)
|
2021-08-12 21:31:15 +00:00
|
|
|
}
|
|
|
|
|
2021-08-13 00:20:13 +00:00
|
|
|
func (mod *modContext) getPropertiesWithIDPrefixAndExclude(properties []*schema.Property, lang string, input, nested,
|
2023-03-03 16:36:39 +00:00
|
|
|
isProvider bool, idPrefix string, exclude func(name string) bool,
|
|
|
|
) []property {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-03-09 17:35:20 +00:00
|
|
|
if len(properties) == 0 {
|
|
|
|
return nil
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2023-06-28 16:02:04 +00:00
|
|
|
docProperties := slice.Prealloc[property](len(properties))
|
2020-03-09 17:35:20 +00:00
|
|
|
for _, prop := range properties {
|
|
|
|
if prop == nil {
|
|
|
|
continue
|
|
|
|
}
|
2020-04-17 18:45:06 +00:00
|
|
|
|
2021-08-12 21:31:15 +00:00
|
|
|
if exclude != nil && exclude(prop.Name) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-04-17 18:45:06 +00:00
|
|
|
// If the property has a const value, then don't show it as an input property.
|
|
|
|
// Even though it is a valid property, it is used by the language code gen to
|
|
|
|
// generate the appropriate defaults for it. These cannot be overridden by users.
|
|
|
|
if prop.ConstValue != nil {
|
2020-04-07 00:01:33 +00:00
|
|
|
continue
|
|
|
|
}
|
2020-03-17 20:37:40 +00:00
|
|
|
|
2021-06-24 16:17:55 +00:00
|
|
|
characteristics := propertyCharacteristics{input: input}
|
2020-03-19 19:18:18 +00:00
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
langDocHelper := dctx.getLanguageDocHelper(lang)
|
2020-08-19 15:34:06 +00:00
|
|
|
name, err := langDocHelper.GetPropertyName(prop)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
propLangName := name
|
|
|
|
|
2021-08-12 21:31:15 +00:00
|
|
|
propID := idPrefix + strings.ToLower(propLangName+propertyLangSeparator+lang)
|
2020-05-22 21:53:34 +00:00
|
|
|
|
2020-12-10 02:18:34 +00:00
|
|
|
propTypes := make([]propertyType, 0)
|
2021-06-24 16:17:55 +00:00
|
|
|
if typ, isUnion := codegen.UnwrapType(prop.Type).(*schema.UnionType); isUnion {
|
2020-12-10 02:18:34 +00:00
|
|
|
for _, elementType := range typ.ElementTypes {
|
|
|
|
propTypes = append(propTypes, mod.typeString(elementType, lang, characteristics, true))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
propTypes = append(propTypes, mod.typeString(prop.Type, lang, characteristics, true))
|
|
|
|
}
|
|
|
|
|
2021-02-13 00:11:56 +00:00
|
|
|
comment := prop.Comment
|
2024-03-14 22:10:14 +00:00
|
|
|
link := "#" + propID
|
|
|
|
|
|
|
|
// Check if type is defined in a package external to the current package. If
|
|
|
|
// it is external, update comment to indicate to user that type is defined
|
|
|
|
// in another package and link there.
|
|
|
|
if isExt := isExternalType(codegen.UnwrapType(prop.Type), mod.pkg); isExt {
|
|
|
|
packageName := tokenToPackageName(fmt.Sprintf("%v", codegen.UnwrapType(prop.Type)))
|
2024-04-19 06:20:33 +00:00
|
|
|
extPkgLink := "/registry/packages/" + packageName
|
2024-03-14 22:10:14 +00:00
|
|
|
comment += fmt.Sprintf("\nThis type is defined in the [%s](%s) package.", getPackageDisplayName(packageName), extPkgLink)
|
|
|
|
}
|
|
|
|
|
2021-02-13 00:11:56 +00:00
|
|
|
// Default values for Provider inputs correspond to environment variables, so add that info to the docs.
|
|
|
|
if isProvider && input && prop.DefaultValue != nil && len(prop.DefaultValue.Environment) > 0 {
|
|
|
|
var suffix string
|
|
|
|
if len(prop.DefaultValue.Environment) > 1 {
|
|
|
|
suffix = "s"
|
|
|
|
}
|
|
|
|
comment += fmt.Sprintf(" It can also be sourced from the following environment variable%s: ", suffix)
|
|
|
|
for i, v := range prop.DefaultValue.Environment {
|
|
|
|
comment += fmt.Sprintf("`%s`", v)
|
|
|
|
if i != len(prop.DefaultValue.Environment)-1 {
|
|
|
|
comment += ", "
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
docProperties = append(docProperties, property{
|
2020-05-22 21:53:34 +00:00
|
|
|
ID: propID,
|
2020-03-20 15:17:58 +00:00
|
|
|
DisplayName: wbr(propLangName),
|
|
|
|
Name: propLangName,
|
2021-02-13 00:11:56 +00:00
|
|
|
Comment: comment,
|
2020-03-09 17:35:20 +00:00
|
|
|
DeprecationMessage: prop.DeprecationMessage,
|
2021-06-24 16:17:55 +00:00
|
|
|
IsRequired: prop.IsRequired(),
|
2020-03-19 19:18:18 +00:00
|
|
|
IsInput: input,
|
2022-05-17 20:59:47 +00:00
|
|
|
// We indicate that a property will replace if either
|
|
|
|
// a) we will force the replace at the engine level
|
|
|
|
// b) we are told that the provider will require a replace
|
|
|
|
IsReplaceOnChanges: prop.ReplaceOnChanges || prop.WillReplaceOnChanges,
|
2024-03-14 22:10:14 +00:00
|
|
|
Link: link,
|
2020-12-10 02:18:34 +00:00
|
|
|
Types: propTypes,
|
2020-03-09 17:35:20 +00:00
|
|
|
})
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-04-18 21:17:08 +00:00
|
|
|
// Sort required props to move them to the top of the properties list, then by name.
|
2020-04-09 22:57:17 +00:00
|
|
|
sort.SliceStable(docProperties, func(i, j int) bool {
|
2020-04-18 21:17:08 +00:00
|
|
|
pi, pj := docProperties[i], docProperties[j]
|
|
|
|
switch {
|
|
|
|
case pi.IsRequired != pj.IsRequired:
|
|
|
|
return pi.IsRequired && !pj.IsRequired
|
|
|
|
default:
|
|
|
|
return pi.Name < pj.Name
|
|
|
|
}
|
2020-04-09 22:57:17 +00:00
|
|
|
})
|
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
return docProperties
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-07-08 00:24:07 +00:00
|
|
|
func getDockerImagePythonFormalParams() []formalParam {
|
|
|
|
return []formalParam{
|
|
|
|
{
|
|
|
|
Name: "image_name",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "build",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "local_image_name",
|
|
|
|
DefaultValue: "=None",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "registry",
|
|
|
|
DefaultValue: "=None",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "skip_push",
|
|
|
|
DefaultValue: "=None",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "opts",
|
|
|
|
DefaultValue: "=None",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-17 18:46:02 +00:00
|
|
|
// Returns the rendered HTML for the resource's constructor, as well as the specific arguments.
|
|
|
|
func (mod *modContext) genConstructors(r *schema.Resource, allOptionalInputs bool) (map[string]string, map[string][]formalParam) {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-04-17 18:46:02 +00:00
|
|
|
renderedParams := make(map[string]string)
|
|
|
|
formalParams := make(map[string][]formalParam)
|
2020-07-08 00:24:07 +00:00
|
|
|
|
2021-04-17 22:33:23 +00:00
|
|
|
// Add an extra language for Python's ResourceArg __init__ overload.
|
2021-10-06 15:03:21 +00:00
|
|
|
langs := append(dctx.supportedLanguages, "pythonargs")
|
2022-04-21 11:23:36 +00:00
|
|
|
// Add an extra language for Java's ResourceArg overload.
|
|
|
|
langs = append(langs, "javaargs")
|
2021-04-17 22:33:23 +00:00
|
|
|
|
|
|
|
for _, lang := range langs {
|
2020-03-09 17:35:20 +00:00
|
|
|
var (
|
|
|
|
paramTemplate string
|
2020-03-17 20:37:40 +00:00
|
|
|
params []formalParam
|
2020-03-09 17:35:20 +00:00
|
|
|
)
|
|
|
|
b := &bytes.Buffer{}
|
|
|
|
|
2021-04-17 22:33:23 +00:00
|
|
|
paramSeparatorTemplate := "param_separator"
|
|
|
|
ps := paramSeparator{}
|
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
switch lang {
|
|
|
|
case "nodejs":
|
|
|
|
params = mod.genConstructorTS(r, allOptionalInputs)
|
2020-03-17 20:37:40 +00:00
|
|
|
paramTemplate = "ts_formal_param"
|
2020-03-09 17:35:20 +00:00
|
|
|
case "go":
|
|
|
|
params = mod.genConstructorGo(r, allOptionalInputs)
|
2020-03-17 20:37:40 +00:00
|
|
|
paramTemplate = "go_formal_param"
|
2020-03-09 17:35:20 +00:00
|
|
|
case "csharp":
|
|
|
|
params = mod.genConstructorCS(r, allOptionalInputs)
|
2020-03-17 20:37:40 +00:00
|
|
|
paramTemplate = "csharp_formal_param"
|
2022-04-21 11:23:36 +00:00
|
|
|
case "java":
|
|
|
|
fallthrough
|
|
|
|
case "javaargs":
|
|
|
|
argsOverload := lang == "javaargs"
|
|
|
|
params = mod.genConstructorJava(r, argsOverload)
|
|
|
|
paramTemplate = "java_formal_param"
|
2020-03-17 20:37:40 +00:00
|
|
|
case "python":
|
2021-04-17 22:33:23 +00:00
|
|
|
fallthrough
|
|
|
|
case "pythonargs":
|
|
|
|
argsOverload := lang == "pythonargs"
|
|
|
|
params = mod.genConstructorPython(r, allOptionalInputs, argsOverload)
|
2020-03-17 20:37:40 +00:00
|
|
|
paramTemplate = "py_formal_param"
|
2021-04-17 22:33:23 +00:00
|
|
|
paramSeparatorTemplate = "py_param_separator"
|
|
|
|
ps = paramSeparator{Indent: strings.Repeat(" ", len("def (")+len(resourceName(r)))}
|
2022-04-21 11:23:36 +00:00
|
|
|
case "yaml":
|
|
|
|
params = mod.genConstructorYaml()
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2022-04-21 11:23:36 +00:00
|
|
|
if paramTemplate != "" {
|
|
|
|
for i, p := range params {
|
|
|
|
if i != 0 {
|
|
|
|
if err := dctx.templates.ExecuteTemplate(b, paramSeparatorTemplate, ps); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err := dctx.templates.ExecuteTemplate(b, paramTemplate, p); err != nil {
|
2020-03-09 17:35:20 +00:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-04-17 18:46:02 +00:00
|
|
|
renderedParams[lang] = b.String()
|
|
|
|
formalParams[lang] = params
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-04-17 18:46:02 +00:00
|
|
|
|
|
|
|
return renderedParams, formalParams
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
// getConstructorResourceInfo returns a map of per-language information about
|
|
|
|
// the resource being constructed.
|
2022-04-21 11:23:36 +00:00
|
|
|
func (mod *modContext) getConstructorResourceInfo(resourceTypeName, tok string) map[string]propertyType {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2022-04-21 11:23:36 +00:00
|
|
|
docLangHelper := dctx.getLanguageDocHelper("yaml")
|
2020-03-12 00:58:12 +00:00
|
|
|
resourceMap := make(map[string]propertyType)
|
2020-03-09 17:35:20 +00:00
|
|
|
resourceDisplayName := resourceTypeName
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
for _, lang := range dctx.supportedLanguages {
|
2020-04-11 01:28:14 +00:00
|
|
|
// Use the module to package lookup to transform the module name to its normalized package name.
|
2020-05-16 00:33:56 +00:00
|
|
|
modName := mod.getLanguageModuleName(lang)
|
2020-03-09 17:35:20 +00:00
|
|
|
// Reset the type name back to the display name.
|
|
|
|
resourceTypeName = resourceDisplayName
|
|
|
|
|
|
|
|
switch lang {
|
2022-04-21 11:23:36 +00:00
|
|
|
case "nodejs", "go", "python", "java":
|
2020-03-12 00:58:12 +00:00
|
|
|
// Intentionally left blank.
|
2020-03-09 17:35:20 +00:00
|
|
|
case "csharp":
|
2022-12-12 14:55:35 +00:00
|
|
|
namespace := title(mod.pkg.Name(), lang)
|
|
|
|
if ns, ok := dctx.csharpPkgInfo.Namespaces[mod.pkg.Name()]; ok {
|
2020-05-13 16:32:40 +00:00
|
|
|
namespace = ns
|
|
|
|
}
|
2020-04-14 00:27:38 +00:00
|
|
|
if mod.mod == "" {
|
2020-05-13 16:32:40 +00:00
|
|
|
resourceTypeName = fmt.Sprintf("Pulumi.%s.%s", namespace, resourceTypeName)
|
2020-04-14 00:27:38 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2020-05-13 16:32:40 +00:00
|
|
|
resourceTypeName = fmt.Sprintf("Pulumi.%s.%s.%s", namespace, modName, resourceTypeName)
|
2022-04-21 11:23:36 +00:00
|
|
|
case "yaml":
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-04-21 11:23:36 +00:00
|
|
|
resourceMap[lang] = propertyType{
|
|
|
|
Name: resourceTypeName,
|
2022-12-12 14:55:35 +00:00
|
|
|
DisplayName: docLangHelper.GetLanguageTypeString(def, mod.mod, &schema.ResourceType{Token: tok}, false),
|
2022-04-21 11:23:36 +00:00
|
|
|
}
|
|
|
|
continue
|
2020-03-09 17:35:20 +00:00
|
|
|
default:
|
2021-11-13 02:37:17 +00:00
|
|
|
panic(fmt.Errorf("cannot generate constructor info for unhandled language %q", lang))
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-03-23 21:17:14 +00:00
|
|
|
parts := strings.Split(resourceTypeName, ".")
|
|
|
|
displayName := parts[len(parts)-1]
|
2020-09-20 18:56:52 +00:00
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
resourceMap[lang] = propertyType{
|
2020-03-23 21:17:14 +00:00
|
|
|
Name: resourceDisplayName,
|
|
|
|
DisplayName: displayName,
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-03-09 17:35:20 +00:00
|
|
|
|
|
|
|
return resourceMap
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
func (mod *modContext) getTSLookupParams(r *schema.Resource, stateParam string) []formalParam {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
|
|
|
docLangHelper := dctx.getLanguageDocHelper("nodejs")
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2020-09-20 18:56:52 +00:00
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
return []formalParam{
|
|
|
|
{
|
|
|
|
Name: "name",
|
2020-04-15 19:56:28 +00:00
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
Type: propertyType{
|
|
|
|
Name: "string",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "id",
|
|
|
|
Type: propertyType{
|
2020-04-03 18:26:52 +00:00
|
|
|
Name: "Input<ID>",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "ID"),
|
2020-03-17 20:37:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "state",
|
|
|
|
OptionalFlag: "?",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: stateParam,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "opts",
|
|
|
|
OptionalFlag: "?",
|
|
|
|
Type: propertyType{
|
2020-04-03 18:26:52 +00:00
|
|
|
Name: "CustomResourceOptions",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "CustomResourceOptions"),
|
2020-03-17 20:37:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *modContext) getGoLookupParams(r *schema.Resource, stateParam string) []formalParam {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
|
|
|
docLangHelper := dctx.getLanguageDocHelper("go")
|
2020-09-20 18:56:52 +00:00
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
return []formalParam{
|
|
|
|
{
|
|
|
|
Name: "ctx",
|
|
|
|
OptionalFlag: "*",
|
|
|
|
Type: propertyType{
|
2020-04-03 18:26:52 +00:00
|
|
|
Name: "Context",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "Context"),
|
2020-03-17 20:37:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "name",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: "string",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "id",
|
|
|
|
Type: propertyType{
|
2020-04-03 18:26:52 +00:00
|
|
|
Name: "IDInput",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "IDInput"),
|
2020-03-17 20:37:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "state",
|
|
|
|
OptionalFlag: "*",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: stateParam,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "opts",
|
|
|
|
OptionalFlag: "...",
|
|
|
|
Type: propertyType{
|
2020-04-03 18:26:52 +00:00
|
|
|
Name: "ResourceOption",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "ResourceOption"),
|
2020-03-17 20:37:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *modContext) getCSLookupParams(r *schema.Resource, stateParam string) []formalParam {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
|
|
|
docLangHelper := dctx.getLanguageDocHelper("csharp")
|
2020-09-20 18:56:52 +00:00
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
return []formalParam{
|
|
|
|
{
|
|
|
|
Name: "name",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: "string",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "id",
|
|
|
|
Type: propertyType{
|
2020-04-03 18:26:52 +00:00
|
|
|
Name: "Input<string>",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "Pulumi.Input"),
|
2020-03-17 20:37:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "state",
|
|
|
|
OptionalFlag: "?",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: stateParam,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "opts",
|
|
|
|
OptionalFlag: "?",
|
|
|
|
DefaultValue: " = null",
|
|
|
|
Type: propertyType{
|
2020-04-03 18:26:52 +00:00
|
|
|
Name: "CustomResourceOptions",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "Pulumi.CustomResourceOptions"),
|
2020-03-17 20:37:40 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-21 11:23:36 +00:00
|
|
|
func (mod *modContext) getJavaLookupParams(r *schema.Resource, stateParam string) []formalParam {
|
|
|
|
dctx := mod.docGenContext
|
|
|
|
docLangHelper := dctx.getLanguageDocHelper("java")
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-04-21 11:23:36 +00:00
|
|
|
|
|
|
|
return []formalParam{
|
|
|
|
{
|
|
|
|
Name: "name",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: "String",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "id",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: "Output<String>",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "Output"),
|
2022-04-21 11:23:36 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "state",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: stateParam,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "options",
|
|
|
|
Type: propertyType{
|
|
|
|
Name: "CustomResourceOptions",
|
2022-12-12 14:55:35 +00:00
|
|
|
Link: docLangHelper.GetDocLinkForPulumiType(def, "CustomResourceOptions"),
|
2022-04-21 11:23:36 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 15:34:06 +00:00
|
|
|
func (mod *modContext) getPythonLookupParams(r *schema.Resource, stateParam string) []formalParam {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-08-19 15:34:06 +00:00
|
|
|
// The input properties for a resource needs to be exploded as
|
|
|
|
// individual constructor params.
|
2021-10-06 15:03:21 +00:00
|
|
|
docLanguageHelper := dctx.getLanguageDocHelper("python")
|
2023-06-28 16:02:04 +00:00
|
|
|
params := slice.Prealloc[formalParam](len(r.StateInputs.Properties))
|
2020-08-19 15:34:06 +00:00
|
|
|
for _, p := range r.StateInputs.Properties {
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
|
|
|
typ := docLanguageHelper.GetLanguageTypeString(def, mod.mod, codegen.PlainType(codegen.OptionalType(p)), true /*input*/)
|
2020-08-19 15:34:06 +00:00
|
|
|
params = append(params, formalParam{
|
|
|
|
Name: python.PyName(p.Name),
|
|
|
|
DefaultValue: " = None",
|
|
|
|
Type: propertyType{
|
2021-06-24 16:17:55 +00:00
|
|
|
Name: typ,
|
2020-08-19 15:34:06 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return params
|
|
|
|
}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
// genLookupParams generates a map of per-language way of rendering the formal parameters of the lookup function
|
|
|
|
// used to lookup an existing resource.
|
|
|
|
func (mod *modContext) genLookupParams(r *schema.Resource, stateParam string) map[string]string {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-03-17 20:37:40 +00:00
|
|
|
lookupParams := make(map[string]string)
|
|
|
|
if r.StateInputs == nil {
|
|
|
|
return lookupParams
|
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
for _, lang := range dctx.supportedLanguages {
|
2020-03-17 20:37:40 +00:00
|
|
|
var (
|
|
|
|
paramTemplate string
|
|
|
|
params []formalParam
|
|
|
|
)
|
|
|
|
b := &bytes.Buffer{}
|
|
|
|
|
2021-04-17 22:33:23 +00:00
|
|
|
paramSeparatorTemplate := "param_separator"
|
|
|
|
ps := paramSeparator{}
|
|
|
|
|
2020-03-17 20:37:40 +00:00
|
|
|
switch lang {
|
|
|
|
case "nodejs":
|
|
|
|
params = mod.getTSLookupParams(r, stateParam)
|
|
|
|
paramTemplate = "ts_formal_param"
|
|
|
|
case "go":
|
|
|
|
params = mod.getGoLookupParams(r, stateParam)
|
|
|
|
paramTemplate = "go_formal_param"
|
|
|
|
case "csharp":
|
|
|
|
params = mod.getCSLookupParams(r, stateParam)
|
|
|
|
paramTemplate = "csharp_formal_param"
|
2022-04-21 11:23:36 +00:00
|
|
|
case "java":
|
|
|
|
params = mod.getJavaLookupParams(r, stateParam)
|
|
|
|
paramTemplate = "java_formal_param"
|
2020-03-17 20:37:40 +00:00
|
|
|
case "python":
|
2020-08-19 15:34:06 +00:00
|
|
|
params = mod.getPythonLookupParams(r, stateParam)
|
2020-03-17 20:37:40 +00:00
|
|
|
paramTemplate = "py_formal_param"
|
2021-04-17 22:33:23 +00:00
|
|
|
paramSeparatorTemplate = "py_param_separator"
|
|
|
|
ps = paramSeparator{Indent: strings.Repeat(" ", len("def get("))}
|
2020-03-17 20:37:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
n := len(params)
|
|
|
|
for i, p := range params {
|
2021-10-06 15:03:21 +00:00
|
|
|
if err := dctx.templates.ExecuteTemplate(b, paramTemplate, p); err != nil {
|
2020-03-17 20:37:40 +00:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if i != n-1 {
|
2021-10-06 15:03:21 +00:00
|
|
|
if err := dctx.templates.ExecuteTemplate(b, paramSeparatorTemplate, ps); err != nil {
|
2020-03-17 20:37:40 +00:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lookupParams[lang] = b.String()
|
|
|
|
}
|
|
|
|
return lookupParams
|
|
|
|
}
|
|
|
|
|
2020-04-14 00:27:38 +00:00
|
|
|
// filterOutputProperties removes the input properties from the output properties list
|
2020-04-10 23:12:05 +00:00
|
|
|
// (since input props are implicitly output props), returning only "output" props.
|
|
|
|
func filterOutputProperties(inputProps []*schema.Property, props []*schema.Property) []*schema.Property {
|
|
|
|
var outputProps []*schema.Property
|
|
|
|
inputMap := make(map[string]bool, len(inputProps))
|
|
|
|
for _, p := range inputProps {
|
|
|
|
inputMap[p.Name] = true
|
|
|
|
}
|
|
|
|
for _, p := range props {
|
|
|
|
if _, found := inputMap[p.Name]; !found {
|
|
|
|
outputProps = append(outputProps, p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return outputProps
|
|
|
|
}
|
|
|
|
|
2020-04-21 11:28:44 +00:00
|
|
|
func (mod *modContext) genResourceHeader(r *schema.Resource) header {
|
|
|
|
resourceName := resourceName(r)
|
2020-12-17 18:44:57 +00:00
|
|
|
var metaDescription string
|
2020-04-21 11:28:44 +00:00
|
|
|
var titleTag string
|
|
|
|
if mod.mod == "" {
|
2021-02-17 04:03:06 +00:00
|
|
|
metaDescription = fmt.Sprintf("Documentation for the %s.%s resource "+
|
|
|
|
"with examples, input properties, output properties, "+
|
2022-12-12 14:55:35 +00:00
|
|
|
"lookup functions, and supporting types.", mod.pkg.Name(), resourceName)
|
|
|
|
titleTag = fmt.Sprintf("%s.%s", mod.pkg.Name(), resourceName)
|
2020-04-21 11:28:44 +00:00
|
|
|
} else {
|
2020-12-17 18:44:57 +00:00
|
|
|
metaDescription = fmt.Sprintf("Documentation for the %s.%s.%s resource "+
|
|
|
|
"with examples, input properties, output properties, "+
|
2022-12-12 14:55:35 +00:00
|
|
|
"lookup functions, and supporting types.", mod.pkg.Name(), mod.mod, resourceName)
|
|
|
|
titleTag = fmt.Sprintf("%s.%s.%s", mod.pkg.Name(), mod.mod, resourceName)
|
2020-04-21 11:28:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return header{
|
|
|
|
Title: resourceName,
|
|
|
|
TitleTag: titleTag,
|
2020-12-17 18:44:57 +00:00
|
|
|
MetaDesc: metaDescription,
|
2020-04-21 11:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
// genResource is the entrypoint for generating a doc for a resource
|
|
|
|
// from its Pulumi schema.
|
2020-03-12 00:58:12 +00:00
|
|
|
func (mod *modContext) genResource(r *schema.Resource) resourceDocArgs {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-02-27 18:04:34 +00:00
|
|
|
// Create a resource module file into which all of this resource's types will go.
|
|
|
|
name := resourceName(r)
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
inputProps := make(map[string][]property)
|
|
|
|
outputProps := make(map[string][]property)
|
|
|
|
stateInputs := make(map[string][]property)
|
2020-04-14 00:27:38 +00:00
|
|
|
|
|
|
|
var filteredOutputProps []*schema.Property
|
|
|
|
// Provider resources do not have output properties, so there won't be anything to filter.
|
|
|
|
if !r.IsProvider {
|
|
|
|
filteredOutputProps = filterOutputProperties(r.InputProperties, r.Properties)
|
|
|
|
}
|
2020-04-18 21:17:08 +00:00
|
|
|
|
2022-11-25 18:34:49 +00:00
|
|
|
// All custom resources have an implicit `id` output property, that we must inject into the docs.
|
|
|
|
if !r.IsComponent {
|
|
|
|
filteredOutputProps = append(filteredOutputProps, &schema.Property{
|
|
|
|
Name: "id",
|
|
|
|
Comment: "The provider-assigned unique ID for this managed resource.",
|
|
|
|
Type: schema.StringType,
|
|
|
|
})
|
|
|
|
}
|
2020-04-18 21:17:08 +00:00
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
for _, lang := range dctx.supportedLanguages {
|
2021-06-24 16:17:55 +00:00
|
|
|
inputProps[lang] = mod.getProperties(r.InputProperties, lang, true, false, r.IsProvider)
|
|
|
|
outputProps[lang] = mod.getProperties(filteredOutputProps, lang, false, false, r.IsProvider)
|
2020-03-09 17:35:20 +00:00
|
|
|
if r.IsProvider {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if r.StateInputs != nil {
|
2021-06-24 16:17:55 +00:00
|
|
|
stateProps := mod.getProperties(r.StateInputs.Properties, lang, true, false, r.IsProvider)
|
2020-05-22 21:53:34 +00:00
|
|
|
for i := 0; i < len(stateProps); i++ {
|
|
|
|
id := "state_" + stateProps[i].ID
|
|
|
|
stateProps[i].ID = id
|
2022-12-07 18:40:42 +00:00
|
|
|
stateProps[i].Link = "#" + id
|
2020-05-22 21:53:34 +00:00
|
|
|
}
|
|
|
|
stateInputs[lang] = stateProps
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
|
|
|
allOptionalInputs := true
|
|
|
|
for _, prop := range r.InputProperties {
|
2020-03-09 17:35:20 +00:00
|
|
|
// If at least one prop is required, then break.
|
2021-06-24 16:17:55 +00:00
|
|
|
if prop.IsRequired() {
|
2020-03-09 17:35:20 +00:00
|
|
|
allOptionalInputs = false
|
|
|
|
break
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %s", mod.pkg.Name())
|
2020-04-02 00:22:23 +00:00
|
|
|
packageDetails := packageDetails{
|
2023-01-17 18:22:12 +00:00
|
|
|
DisplayName: getPackageDisplayName(def.Name),
|
|
|
|
Repository: def.Repository,
|
|
|
|
RepositoryName: getRepositoryName(def.Repository),
|
|
|
|
License: def.License,
|
|
|
|
Notes: def.Attribution,
|
2020-04-02 00:22:23 +00:00
|
|
|
}
|
|
|
|
|
2020-04-17 18:46:02 +00:00
|
|
|
renderedCtorParams, typedCtorParams := mod.genConstructors(r, allOptionalInputs)
|
2020-03-17 20:37:40 +00:00
|
|
|
stateParam := name + "State"
|
2024-03-21 13:41:07 +00:00
|
|
|
creationExampleSyntax := map[string]string{}
|
|
|
|
if !r.IsProvider && err == nil {
|
|
|
|
if example, found := dctx.constructorSyntaxData.typescript.resources[r.Token]; found {
|
|
|
|
if strings.Contains(example, "notImplemented") || strings.Contains(example, "PANIC") {
|
2024-06-25 22:41:47 +00:00
|
|
|
example = ""
|
2024-03-21 13:41:07 +00:00
|
|
|
}
|
|
|
|
creationExampleSyntax["typescript"] = example
|
|
|
|
}
|
|
|
|
if example, found := dctx.constructorSyntaxData.python.resources[r.Token]; found {
|
|
|
|
if strings.Contains(example, "not_implemented") || strings.Contains(example, "PANIC") {
|
2024-06-25 22:41:47 +00:00
|
|
|
example = ""
|
2024-03-21 13:41:07 +00:00
|
|
|
}
|
|
|
|
creationExampleSyntax["python"] = example
|
|
|
|
}
|
|
|
|
if example, found := dctx.constructorSyntaxData.csharp.resources[r.Token]; found {
|
|
|
|
if strings.Contains(example, "NotImplemented") || strings.Contains(example, "PANIC") {
|
2024-06-25 22:41:47 +00:00
|
|
|
example = ""
|
2024-03-21 13:41:07 +00:00
|
|
|
}
|
|
|
|
creationExampleSyntax["csharp"] = example
|
|
|
|
}
|
|
|
|
if example, found := dctx.constructorSyntaxData.golang.resources[r.Token]; found {
|
|
|
|
modified := strings.ReplaceAll(example, "_, err =", "example, err :=")
|
|
|
|
modified = strings.ReplaceAll(modified, "_, err :=", "example, err :=")
|
|
|
|
if strings.Contains(modified, "notImplemented") || strings.Contains(modified, "PANIC") {
|
2024-06-25 22:41:47 +00:00
|
|
|
modified = ""
|
2024-03-21 13:41:07 +00:00
|
|
|
}
|
|
|
|
creationExampleSyntax["go"] = modified
|
|
|
|
}
|
|
|
|
if example, found := dctx.constructorSyntaxData.java.resources[r.Token]; found {
|
|
|
|
creationExampleSyntax["java"] = example
|
|
|
|
}
|
2024-03-27 12:11:08 +00:00
|
|
|
if example, found := dctx.constructorSyntaxData.yaml.resources[collapseYAMLToken(r.Token)]; found {
|
2024-03-21 13:41:07 +00:00
|
|
|
creationExampleSyntax["yaml"] = example
|
|
|
|
}
|
|
|
|
}
|
2020-04-21 11:28:44 +00:00
|
|
|
|
Resource docs: emit supporting types beyond the 200 limit (#16185)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Originally motivated by uncontrolled pseudo-recurcive type expansion in
AWS WafV2, we've limited the number of types that we should in the docs
to 200: https://github.com/pulumi/pulumi/pull/12070
Our large customer that publishes their own packages and docs came back
to us and said they have legitimate use cases with more than 200 types:
#15507
I've grabbed stats about our current packages and still found a few
offenders:
```
"aws:lex/v2modelsIntent:V2modelsIntent" 920
"aws:wafv2/ruleGroup:RuleGroup" 310
"aws:wafv2/webAcl:WebAcl" 523
"azure-native:datafactory:Dataset" 256
"azure-native:datafactory:LinkedService" 299
"azure-native:datafactory:Pipeline" 618
"azure-native:datamigration:ServiceTask" 291
"azure-native:datamigration:Task" 291
"aws-native:quicksight:Analysis" 589
"aws-native:quicksight:Dashboard" 606
"aws-native:quicksight:Template" 590
```
Therefore, I'm not entirely removing the limit in this PR, but
a) bumping the default to 1000
b) applying 200 to the known offenders only
I don't love it's hard coded, but I haven't found a place to add simple
configuration nob. Anyway, it's slightly less hard-coded than it used to
be.
Fixes #15507
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
- Existing docs gen tests cover that I haven't broken anything
- I re-generated the AWS docs and they had no changes
<!---
User-facing changes require a CHANGELOG entry.
-->
- [x] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-05-13 14:58:33 +00:00
|
|
|
// Set a cap on how many auxiliary types the docs will include. We do that to limit the maximum size of
|
|
|
|
// a doc page. The default limit is rather high - we tried setting it to 200 for everyone but got
|
|
|
|
// pushback from third-party consumers who have legitimate use cases with more that 200 types.
|
|
|
|
// Therefore, we currently apply a smaller limit of 200 to packages that we know have some bloat in
|
|
|
|
// their types (AWS and AWS Native).
|
|
|
|
// See https://github.com/pulumi/pulumi/issues/15507#issuecomment-2064361317
|
|
|
|
//
|
|
|
|
// Schema Tools will print a warning every time a new resources gets an increase in number of types
|
|
|
|
// that is beyond 200. This should help us catch new instances and make decisions whether to include all
|
|
|
|
// types or add a limit. The default is including all types up to 1000.
|
|
|
|
maxNestedTypes := 1000
|
|
|
|
switch mod.pkg.Name() {
|
|
|
|
case "aws", "aws-native":
|
|
|
|
maxNestedTypes = 200
|
|
|
|
}
|
|
|
|
|
2024-07-09 14:54:50 +00:00
|
|
|
supportedSnippetLanguages := mod.docGenContext.getSupportedSnippetLanguages(r.IsOverlay, r.OverlaySupportedLanguages)
|
|
|
|
docInfo := dctx.decomposeDocstring(r.Comment, supportedSnippetLanguages)
|
2020-03-12 00:58:12 +00:00
|
|
|
data := resourceDocArgs{
|
2020-04-21 11:28:44 +00:00
|
|
|
Header: mod.genResourceHeader(r),
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-04-17 18:45:06 +00:00
|
|
|
Tool: mod.tool,
|
|
|
|
|
2024-07-09 14:54:50 +00:00
|
|
|
Comment: docInfo.description,
|
|
|
|
DeprecationMessage: r.DeprecationMessage,
|
|
|
|
ExamplesSection: examplesSection{
|
|
|
|
Examples: docInfo.examples,
|
|
|
|
LangChooserLanguages: supportedSnippetLanguages,
|
|
|
|
},
|
2024-03-21 13:41:07 +00:00
|
|
|
ImportDocs: docInfo.importDetails,
|
|
|
|
CreationExampleSyntax: creationExampleSyntax,
|
2020-04-17 18:46:02 +00:00
|
|
|
ConstructorParams: renderedCtorParams,
|
|
|
|
ConstructorParamsTyped: typedCtorParams,
|
|
|
|
|
2022-04-21 11:23:36 +00:00
|
|
|
ConstructorResource: mod.getConstructorResourceInfo(name, r.Token),
|
2020-03-09 17:35:20 +00:00
|
|
|
ArgsRequired: !allOptionalInputs,
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
InputProperties: inputProps,
|
|
|
|
OutputProperties: outputProps,
|
2020-03-17 20:37:40 +00:00
|
|
|
LookupParams: mod.genLookupParams(r, stateParam),
|
2020-03-09 17:35:20 +00:00
|
|
|
StateInputs: stateInputs,
|
2020-03-17 20:37:40 +00:00
|
|
|
StateParam: stateParam,
|
2020-03-12 00:58:12 +00:00
|
|
|
NestedTypes: mod.genNestedTypes(r, true /*resourceType*/),
|
Resource docs: emit supporting types beyond the 200 limit (#16185)
<!---
Thanks so much for your contribution! If this is your first time
contributing, please ensure that you have read the
[CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md)
documentation.
-->
# Description
Originally motivated by uncontrolled pseudo-recurcive type expansion in
AWS WafV2, we've limited the number of types that we should in the docs
to 200: https://github.com/pulumi/pulumi/pull/12070
Our large customer that publishes their own packages and docs came back
to us and said they have legitimate use cases with more than 200 types:
#15507
I've grabbed stats about our current packages and still found a few
offenders:
```
"aws:lex/v2modelsIntent:V2modelsIntent" 920
"aws:wafv2/ruleGroup:RuleGroup" 310
"aws:wafv2/webAcl:WebAcl" 523
"azure-native:datafactory:Dataset" 256
"azure-native:datafactory:LinkedService" 299
"azure-native:datafactory:Pipeline" 618
"azure-native:datamigration:ServiceTask" 291
"azure-native:datamigration:Task" 291
"aws-native:quicksight:Analysis" 589
"aws-native:quicksight:Dashboard" 606
"aws-native:quicksight:Template" 590
```
Therefore, I'm not entirely removing the limit in this PR, but
a) bumping the default to 1000
b) applying 200 to the known offenders only
I don't love it's hard coded, but I haven't found a place to add simple
configuration nob. Anyway, it's slightly less hard-coded than it used to
be.
Fixes #15507
## Checklist
- [x] I have run `make tidy` to update any new dependencies
- [x] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [x] I have added tests that prove my fix is effective or that my
feature works
- Existing docs gen tests cover that I haven't broken anything
- I re-generated the AWS docs and they had no changes
<!---
User-facing changes require a CHANGELOG entry.
-->
- [x] I have run `make changelog` and committed the
`changelog/pending/<file>` documenting my change
<!--
If the change(s) in this PR is a modification of an existing call to the
Pulumi Cloud,
then the service should honor older versions of the CLI where this
change would not exist.
You must then bump the API version in
/pkg/backend/httpstate/client/api.go, as well as add
it to the service.
-->
- [ ] Yes, there are changes in this PR that warrants bumping the Pulumi
Cloud API version
<!-- @Pulumi employees: If yes, you must submit corresponding changes in
the service repo. -->
2024-05-13 14:58:33 +00:00
|
|
|
MaxNestedTypes: maxNestedTypes,
|
2020-04-02 00:22:23 +00:00
|
|
|
|
2021-08-12 21:31:15 +00:00
|
|
|
Methods: mod.genMethods(r),
|
|
|
|
|
2024-07-09 14:54:50 +00:00
|
|
|
PackageDetails: packageDetails,
|
|
|
|
LangChooserLanguages: supportedSnippetLanguages,
|
2020-03-09 17:35:20 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-03-09 17:35:20 +00:00
|
|
|
return data
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:26:52 +00:00
|
|
|
func (mod *modContext) getNestedTypes(t schema.Type, types nestedTypeUsageInfo, input bool) {
|
2020-02-27 18:04:34 +00:00
|
|
|
switch t := t.(type) {
|
2021-06-24 16:17:55 +00:00
|
|
|
case *schema.InputType:
|
|
|
|
mod.getNestedTypes(t.ElementType, types, input)
|
|
|
|
case *schema.OptionalType:
|
|
|
|
mod.getNestedTypes(t.ElementType, types, input)
|
2020-02-27 18:04:34 +00:00
|
|
|
case *schema.ArrayType:
|
2021-06-24 16:17:55 +00:00
|
|
|
mod.getNestedTypes(t.ElementType, types, input)
|
2020-02-27 18:04:34 +00:00
|
|
|
case *schema.MapType:
|
2021-06-24 16:17:55 +00:00
|
|
|
mod.getNestedTypes(t.ElementType, types, input)
|
|
|
|
case *schema.ObjectType:
|
|
|
|
if types.contains(t.Token, input) {
|
|
|
|
break
|
2020-04-03 18:26:52 +00:00
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
types.add(t.Token, input)
|
|
|
|
for _, p := range t.Properties {
|
|
|
|
mod.getNestedTypes(p.Type, types, input)
|
|
|
|
}
|
2020-12-14 22:40:14 +00:00
|
|
|
case *schema.EnumType:
|
|
|
|
types.add(t.Token, false)
|
2020-02-27 18:04:34 +00:00
|
|
|
case *schema.UnionType:
|
|
|
|
for _, e := range t.ElementTypes {
|
2020-03-12 00:58:12 +00:00
|
|
|
mod.getNestedTypes(e, types, input)
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
func (mod *modContext) getTypes(member interface{}, types nestedTypeUsageInfo) {
|
2020-04-03 18:26:52 +00:00
|
|
|
glog.V(3).Infoln("getting nested types for module", mod.mod)
|
|
|
|
|
2020-03-12 00:58:12 +00:00
|
|
|
switch t := member.(type) {
|
2020-02-27 18:04:34 +00:00
|
|
|
case *schema.ObjectType:
|
2020-03-12 00:58:12 +00:00
|
|
|
for _, p := range t.Properties {
|
|
|
|
mod.getNestedTypes(p.Type, types, false)
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
case *schema.Resource:
|
2020-03-12 00:58:12 +00:00
|
|
|
for _, p := range t.Properties {
|
|
|
|
mod.getNestedTypes(p.Type, types, false)
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-03-12 00:58:12 +00:00
|
|
|
for _, p := range t.InputProperties {
|
|
|
|
mod.getNestedTypes(p.Type, types, true)
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2021-08-12 21:31:15 +00:00
|
|
|
for _, m := range t.Methods {
|
|
|
|
mod.getTypes(m.Function, types)
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
case *schema.Function:
|
2023-01-11 22:17:14 +00:00
|
|
|
if t.Inputs != nil && !t.MultiArgumentInputs {
|
2020-03-12 00:58:12 +00:00
|
|
|
mod.getNestedTypes(t.Inputs, types, true)
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2023-01-11 22:17:14 +00:00
|
|
|
|
|
|
|
if t.ReturnType != nil {
|
|
|
|
if objectType, ok := t.ReturnType.(*schema.ObjectType); ok && objectType != nil {
|
|
|
|
mod.getNestedTypes(objectType, types, false)
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-16 00:33:56 +00:00
|
|
|
// getModuleFileName returns the file name to use for a module.
|
2020-04-07 00:01:33 +00:00
|
|
|
func (mod *modContext) getModuleFileName() string {
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx := mod.docGenContext
|
2020-04-07 00:01:33 +00:00
|
|
|
if !isKubernetesPackage(mod.pkg) {
|
|
|
|
return mod.mod
|
|
|
|
}
|
|
|
|
|
2020-05-16 00:33:56 +00:00
|
|
|
// For k8s packages, use the Go-language info to get the file name
|
|
|
|
// for the module.
|
2021-10-06 15:03:21 +00:00
|
|
|
if override, ok := dctx.goPkgInfo.ModuleToPackage[mod.mod]; ok {
|
2020-04-07 00:01:33 +00:00
|
|
|
return override
|
|
|
|
}
|
|
|
|
return mod.mod
|
|
|
|
}
|
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
// moduleConflictResolver holds module-level information for resolving naming conflicts.
|
|
|
|
// It shares information with the top-level docGenContext
|
|
|
|
// to ensure the same name is used across modules that reference each other.
|
|
|
|
type moduleConflictResolver struct {
|
|
|
|
dctx *docGenContext
|
|
|
|
seen map[string]struct{}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
func (dctx *docGenContext) newModuleConflictResolver() moduleConflictResolver {
|
|
|
|
return moduleConflictResolver{
|
|
|
|
dctx: dctx,
|
|
|
|
seen: map[string]struct{}{},
|
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
// getSafeName returns a documentation name for an item
|
|
|
|
// that is unique within the module.
|
|
|
|
//
|
|
|
|
// if the item has already been resolved by any module,
|
|
|
|
// the previously-resolved name is returned.
|
|
|
|
func (r *moduleConflictResolver) getSafeName(name string, item interface{}) string {
|
|
|
|
if safeName, ok := r.dctx.moduleConflictLinkMap[item]; ok {
|
|
|
|
return safeName
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
var prefixes []string
|
|
|
|
switch item.(type) {
|
|
|
|
case *schema.Resource:
|
|
|
|
prefixes = []string{"", "res-"}
|
|
|
|
case *schema.Function:
|
|
|
|
prefixes = []string{"", "fn-"}
|
|
|
|
case *modContext:
|
|
|
|
prefixes = []string{"", "mod-"}
|
|
|
|
default:
|
|
|
|
prefixes = []string{""}
|
|
|
|
}
|
|
|
|
for _, prefix := range prefixes {
|
|
|
|
candidate := prefix + name
|
|
|
|
if _, exists := r.seen[candidate]; exists {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
r.seen[candidate] = struct{}{}
|
|
|
|
r.dctx.moduleConflictLinkMap[item] = candidate
|
|
|
|
return candidate
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
glog.Error("skipping unresolvable duplicate file name: ", name)
|
|
|
|
return ""
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
func (mod *modContext) gen(fs codegen.Fs) error {
|
2020-04-07 00:01:33 +00:00
|
|
|
glog.V(4).Infoln("genIndex for", mod.mod)
|
|
|
|
|
|
|
|
modName := mod.getModuleFileName()
|
2023-03-17 18:30:55 +00:00
|
|
|
conflictResolver := mod.docGenContext.newModuleConflictResolver()
|
2021-10-18 05:36:31 +00:00
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
def, err := mod.pkg.Definition()
|
2023-02-17 01:23:09 +00:00
|
|
|
contract.AssertNoErrorf(err, "failed to get definition for package %q", mod.pkg.Name())
|
2022-12-12 14:55:35 +00:00
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
modTitle := modName
|
|
|
|
if modTitle == "" {
|
|
|
|
// An empty string indicates that this is the root module.
|
2022-12-12 14:55:35 +00:00
|
|
|
if def.DisplayName != "" {
|
2023-03-17 18:30:55 +00:00
|
|
|
modTitle = def.DisplayName
|
2021-11-10 19:07:43 +00:00
|
|
|
} else {
|
2023-03-17 18:30:55 +00:00
|
|
|
modTitle = getPackageDisplayName(mod.pkg.Name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// addFileTemplated executes template tmpl with data,
|
|
|
|
// and adds a file $dirName/_index.md with the result.
|
|
|
|
addFileTemplated := func(dirName, tmpl string, data interface{}) error {
|
|
|
|
var buff bytes.Buffer
|
|
|
|
if err := mod.docGenContext.templates.ExecuteTemplate(&buff, tmpl, data); err != nil {
|
|
|
|
return err
|
2021-11-10 19:07:43 +00:00
|
|
|
}
|
2023-03-17 18:30:55 +00:00
|
|
|
p := path.Join(modName, dirName, "_index.md")
|
|
|
|
fs.Add(p, buff.Bytes())
|
|
|
|
return nil
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If there are submodules, list them.
|
2023-06-28 16:02:04 +00:00
|
|
|
modules := slice.Prealloc[indexEntry](len(mod.children))
|
2020-02-27 18:04:34 +00:00
|
|
|
for _, mod := range mod.children {
|
2020-04-07 00:01:33 +00:00
|
|
|
modName := mod.getModuleFileName()
|
2021-10-01 00:35:44 +00:00
|
|
|
displayName := modFilenameToDisplayName(modName)
|
2023-03-17 18:30:55 +00:00
|
|
|
safeName := conflictResolver.getSafeName(displayName, mod)
|
|
|
|
if safeName == "" {
|
|
|
|
continue // unresolved conflict
|
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
modules = append(modules, indexEntry{
|
2023-03-17 18:30:55 +00:00
|
|
|
Link: getModuleLink(safeName),
|
2021-10-01 00:35:44 +00:00
|
|
|
DisplayName: displayName,
|
2020-04-07 00:01:33 +00:00
|
|
|
})
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
sortIndexEntries(modules)
|
2020-02-27 18:04:34 +00:00
|
|
|
|
|
|
|
// If there are resources in the root, list them.
|
2023-06-28 16:02:04 +00:00
|
|
|
resources := slice.Prealloc[indexEntry](len(mod.resources))
|
2020-02-27 18:04:34 +00:00
|
|
|
for _, r := range mod.resources {
|
2023-03-17 18:30:55 +00:00
|
|
|
title := resourceName(r)
|
|
|
|
link := getResourceLink(title)
|
|
|
|
link = conflictResolver.getSafeName(link, r)
|
|
|
|
if link == "" {
|
|
|
|
continue // unresolved conflict
|
|
|
|
}
|
|
|
|
|
|
|
|
data := mod.genResource(r)
|
|
|
|
if err := addFileTemplated(link, "resource.tmpl", data); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-04-07 00:01:33 +00:00
|
|
|
resources = append(resources, indexEntry{
|
2023-03-17 18:30:55 +00:00
|
|
|
Link: link + "/",
|
|
|
|
DisplayName: title,
|
2020-04-07 00:01:33 +00:00
|
|
|
})
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
sortIndexEntries(resources)
|
2020-02-27 18:04:34 +00:00
|
|
|
|
|
|
|
// If there are functions in the root, list them.
|
2023-06-28 16:02:04 +00:00
|
|
|
functions := slice.Prealloc[indexEntry](len(mod.functions))
|
2020-02-27 18:04:34 +00:00
|
|
|
for _, f := range mod.functions {
|
2020-04-07 00:01:33 +00:00
|
|
|
name := tokenToName(f.Token)
|
2023-03-17 18:30:55 +00:00
|
|
|
link := getFunctionLink(name)
|
|
|
|
link = conflictResolver.getSafeName(link, f)
|
|
|
|
if link == "" {
|
|
|
|
continue // unresolved conflict
|
|
|
|
}
|
|
|
|
|
|
|
|
data := mod.genFunction(f)
|
|
|
|
if err := addFileTemplated(link, "function.tmpl", data); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-04-07 00:01:33 +00:00
|
|
|
functions = append(functions, indexEntry{
|
2023-03-17 18:30:55 +00:00
|
|
|
Link: link + "/",
|
2020-04-28 00:47:01 +00:00
|
|
|
DisplayName: strings.Title(name),
|
2020-04-07 00:01:33 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
sortIndexEntries(functions)
|
|
|
|
|
2021-06-24 16:17:55 +00:00
|
|
|
version := ""
|
2022-12-12 14:55:35 +00:00
|
|
|
if mod.pkg.Version() != nil {
|
|
|
|
version = mod.pkg.Version().String()
|
2021-06-24 16:17:55 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 00:01:33 +00:00
|
|
|
packageDetails := packageDetails{
|
2023-01-05 21:08:16 +00:00
|
|
|
DisplayName: getPackageDisplayName(def.Name),
|
|
|
|
Repository: def.Repository,
|
|
|
|
RepositoryName: getRepositoryName(def.Repository),
|
|
|
|
License: def.License,
|
|
|
|
Notes: def.Attribution,
|
|
|
|
Version: version,
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
var modTitleTag string
|
2020-04-21 11:28:44 +00:00
|
|
|
var packageDescription string
|
|
|
|
// The same index.tmpl template is used for both top level package and module pages, if modules not present,
|
|
|
|
// assume top level package index page when formatting title tags otherwise, if contains modules, assume modules
|
|
|
|
// top level page when generating title tags.
|
|
|
|
if len(modules) > 0 {
|
2023-12-12 12:19:42 +00:00
|
|
|
modTitleTag = getPackageDisplayName(modTitle) + " Package"
|
2020-04-21 11:28:44 +00:00
|
|
|
} else {
|
2023-03-17 18:30:55 +00:00
|
|
|
modTitleTag = fmt.Sprintf("%s.%s", mod.pkg.Name(), modTitle)
|
2022-12-12 14:55:35 +00:00
|
|
|
packageDescription = fmt.Sprintf("Explore the resources and functions of the %s.%s module.",
|
2023-03-17 18:30:55 +00:00
|
|
|
mod.pkg.Name(), modTitle)
|
2020-04-21 11:28:44 +00:00
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
// Generate the index file.
|
|
|
|
idxData := indexData{
|
2020-04-21 11:28:44 +00:00
|
|
|
Tool: mod.tool,
|
|
|
|
PackageDescription: packageDescription,
|
2023-03-17 18:30:55 +00:00
|
|
|
Title: modTitle,
|
|
|
|
TitleTag: modTitleTag,
|
2020-04-21 11:28:44 +00:00
|
|
|
Resources: resources,
|
|
|
|
Functions: functions,
|
|
|
|
Modules: modules,
|
|
|
|
PackageDetails: packageDetails,
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 00:01:33 +00:00
|
|
|
// If this is the root module, write out the package description.
|
|
|
|
if mod.mod == "" {
|
2023-03-17 18:30:55 +00:00
|
|
|
idxData.PackageDescription = mod.pkg.Description()
|
2020-04-02 18:26:11 +00:00
|
|
|
}
|
2020-04-02 00:22:23 +00:00
|
|
|
|
2023-03-17 18:30:55 +00:00
|
|
|
return addFileTemplated("", "index.tmpl", idxData)
|
|
|
|
}
|
|
|
|
|
|
|
|
// indexEntry represents an individual entry on an index page.
|
|
|
|
type indexEntry struct {
|
|
|
|
Link string
|
|
|
|
DisplayName string
|
|
|
|
}
|
|
|
|
|
|
|
|
// indexData represents the index file data to be rendered as _index.md.
|
|
|
|
type indexData struct {
|
|
|
|
Tool string
|
|
|
|
|
|
|
|
Title string
|
|
|
|
TitleTag string
|
|
|
|
PackageDescription string
|
|
|
|
|
|
|
|
Functions []indexEntry
|
|
|
|
Resources []indexEntry
|
|
|
|
Modules []indexEntry
|
|
|
|
PackageDetails packageDetails
|
|
|
|
}
|
|
|
|
|
|
|
|
func sortIndexEntries(entries []indexEntry) {
|
|
|
|
if len(entries) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Slice(entries, func(i, j int) bool {
|
|
|
|
return entries[i].DisplayName < entries[j].DisplayName
|
|
|
|
})
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-10 19:07:43 +00:00
|
|
|
// getPackageDisplayName uses the title lookup map to look for a
|
|
|
|
// display name for the given title.
|
|
|
|
func getPackageDisplayName(title string) string {
|
2020-04-21 11:28:44 +00:00
|
|
|
// If title not found in titleLookup map, default back to title given.
|
2021-10-06 15:03:21 +00:00
|
|
|
if val, ok := titleLookup(title); ok {
|
2020-04-21 11:28:44 +00:00
|
|
|
return val
|
|
|
|
}
|
|
|
|
return title
|
|
|
|
}
|
|
|
|
|
2023-01-05 21:08:16 +00:00
|
|
|
// getRepositoryName returns the repository name based on the repository's URL.
|
|
|
|
func getRepositoryName(repoURL string) string {
|
|
|
|
return strings.TrimPrefix(repoURL, "https://github.com/")
|
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
func (dctx *docGenContext) getMod(
|
2022-12-12 14:55:35 +00:00
|
|
|
pkg schema.PackageReference,
|
2021-10-06 15:03:21 +00:00
|
|
|
token string,
|
2022-12-12 14:55:35 +00:00
|
|
|
tokenPkg schema.PackageReference,
|
2021-10-06 15:03:21 +00:00
|
|
|
modules map[string]*modContext,
|
|
|
|
tool string,
|
2023-03-03 16:36:39 +00:00
|
|
|
add bool,
|
|
|
|
) *modContext {
|
2020-04-07 00:01:33 +00:00
|
|
|
modName := pkg.TokenToModule(token)
|
2024-02-20 15:44:37 +00:00
|
|
|
return dctx.getModByModName(pkg, tokens.ModuleName(modName), tokenPkg, modules, tool, add)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (dctx *docGenContext) getModByModName(
|
|
|
|
pkg schema.PackageReference,
|
|
|
|
modName tokens.ModuleName,
|
|
|
|
tokenPkg schema.PackageReference,
|
|
|
|
modules map[string]*modContext,
|
|
|
|
tool string,
|
|
|
|
add bool,
|
|
|
|
) *modContext {
|
|
|
|
mod, ok := modules[string(modName)]
|
2020-04-07 00:01:33 +00:00
|
|
|
if !ok {
|
|
|
|
mod = &modContext{
|
2021-10-06 15:03:21 +00:00
|
|
|
pkg: pkg,
|
2024-02-20 15:44:37 +00:00
|
|
|
mod: string(modName),
|
2021-10-06 15:03:21 +00:00
|
|
|
tool: tool,
|
|
|
|
docGenContext: dctx,
|
2020-04-07 00:01:33 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2022-12-12 14:55:35 +00:00
|
|
|
if modName != "" && codegen.PkgEquals(tokenPkg, pkg) {
|
2024-02-20 15:44:37 +00:00
|
|
|
parentName, hasParent := parentModule(modName)
|
|
|
|
if add && hasParent {
|
|
|
|
parent := dctx.getModByModName(pkg, parentName, tokenPkg, modules, tool, add)
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
parent.children = append(parent.children, mod)
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
// Save the module only if we're adding and it's for the current package.
|
|
|
|
// This way, modules for external packages are not saved.
|
|
|
|
if add && tokenPkg == pkg {
|
2024-02-20 15:44:37 +00:00
|
|
|
modules[string(modName)] = mod
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-04-07 00:01:33 +00:00
|
|
|
return mod
|
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
func (dctx *docGenContext) generateModulesFromSchemaPackage(tool string, pkg *schema.Package) map[string]*modContext {
|
2020-04-07 00:01:33 +00:00
|
|
|
// Group resources, types, and functions into modules.
|
|
|
|
modules := map[string]*modContext{}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2020-04-20 23:36:05 +00:00
|
|
|
// Decode language-specific info.
|
|
|
|
if err := pkg.ImportLanguages(map[string]schema.Language{
|
|
|
|
"go": go_gen.Importer,
|
|
|
|
"python": python.Importer,
|
|
|
|
"csharp": dotnet.Importer,
|
|
|
|
"nodejs": nodejs.Importer,
|
|
|
|
}); err != nil {
|
|
|
|
panic(err)
|
2020-03-20 15:17:58 +00:00
|
|
|
}
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx.goPkgInfo, _ = pkg.Language["go"].(go_gen.GoPackageInfo)
|
|
|
|
dctx.csharpPkgInfo, _ = pkg.Language["csharp"].(dotnet.CSharpPackageInfo)
|
|
|
|
dctx.nodePkgInfo, _ = pkg.Language["nodejs"].(nodejs.NodePackageInfo)
|
|
|
|
dctx.pythonPkgInfo, _ = pkg.Language["python"].(python.PackageInfo)
|
2020-04-20 23:36:05 +00:00
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
goLangHelper := dctx.getLanguageDocHelper("go").(*go_gen.DocLanguageHelper)
|
2020-03-20 15:17:58 +00:00
|
|
|
// Generate the Go package map info now, so we can use that to get the type string
|
|
|
|
// names later.
|
2021-10-06 15:03:21 +00:00
|
|
|
goLangHelper.GeneratePackagesMap(pkg, tool, dctx.goPkgInfo)
|
2020-03-20 15:17:58 +00:00
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
csharpLangHelper := dctx.getLanguageDocHelper("csharp").(*dotnet.DocLanguageHelper)
|
|
|
|
csharpLangHelper.Namespaces = dctx.csharpPkgInfo.Namespaces
|
2020-03-30 21:37:30 +00:00
|
|
|
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
visitObjects := func(r *schema.Resource) {
|
|
|
|
visitObjectTypes(r.InputProperties, func(t schema.Type) {
|
|
|
|
switch T := t.(type) {
|
|
|
|
case *schema.ObjectType:
|
2022-12-12 14:55:35 +00:00
|
|
|
dctx.getMod(pkg.Reference(), T.Token, T.PackageReference, modules, tool, true).details(T).inputType = true
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
if r.StateInputs != nil {
|
|
|
|
visitObjectTypes(r.StateInputs.Properties, func(t schema.Type) {
|
|
|
|
switch T := t.(type) {
|
|
|
|
case *schema.ObjectType:
|
2022-12-12 14:55:35 +00:00
|
|
|
dctx.getMod(pkg.Reference(), T.Token, T.PackageReference, modules, tool, true).details(T).inputType = true
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-27 18:04:34 +00:00
|
|
|
scanResource := func(r *schema.Resource) {
|
2022-12-12 14:55:35 +00:00
|
|
|
mod := dctx.getMod(pkg.Reference(), r.Token, r.PackageReference, modules, tool, true)
|
2020-02-27 18:04:34 +00:00
|
|
|
mod.resources = append(mod.resources, r)
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
visitObjects(r)
|
2020-04-03 18:26:52 +00:00
|
|
|
}
|
2020-03-19 19:18:18 +00:00
|
|
|
|
2020-04-03 18:26:52 +00:00
|
|
|
scanK8SResource := func(r *schema.Resource) {
|
2020-04-17 18:45:06 +00:00
|
|
|
mod := getKubernetesMod(pkg, r.Token, modules, tool)
|
2020-04-03 18:26:52 +00:00
|
|
|
mod.resources = append(mod.resources, r)
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
visitObjects(r)
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
|
|
|
|
2020-04-03 18:26:52 +00:00
|
|
|
glog.V(3).Infoln("scanning resources")
|
2022-12-12 14:55:35 +00:00
|
|
|
if isKubernetesPackage(pkg.Reference()) {
|
2020-04-03 18:26:52 +00:00
|
|
|
scanK8SResource(pkg.Provider)
|
|
|
|
for _, r := range pkg.Resources {
|
|
|
|
scanK8SResource(r)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
scanResource(pkg.Provider)
|
|
|
|
for _, r := range pkg.Resources {
|
|
|
|
scanResource(r)
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
2020-04-03 18:26:52 +00:00
|
|
|
glog.V(3).Infoln("done scanning resources")
|
2020-02-27 18:04:34 +00:00
|
|
|
|
|
|
|
for _, f := range pkg.Functions {
|
2021-08-12 21:31:15 +00:00
|
|
|
if !f.IsMethod {
|
2022-12-12 14:55:35 +00:00
|
|
|
mod := dctx.getMod(pkg.Reference(), f.Token, f.PackageReference, modules, tool, true)
|
2021-08-12 21:31:15 +00:00
|
|
|
mod.functions = append(mod.functions, f)
|
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
}
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
|
|
|
|
// Find nested types.
|
|
|
|
for _, t := range pkg.Types {
|
|
|
|
switch typ := t.(type) {
|
|
|
|
case *schema.ObjectType:
|
2022-12-12 14:55:35 +00:00
|
|
|
mod := dctx.getMod(pkg.Reference(), typ.Token, typ.PackageReference, modules, tool, false)
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
if mod.details(typ).inputType {
|
|
|
|
mod.inputTypes = append(mod.inputTypes, typ)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-20 15:17:58 +00:00
|
|
|
return modules
|
|
|
|
}
|
|
|
|
|
2024-03-21 13:41:07 +00:00
|
|
|
// generateModules generates constructor syntax examples for all resources of the input the package in the given
|
|
|
|
// input languages. We first generate a PCL program from the resource definitions, then for each language
|
|
|
|
// we call `GenerateProgram` to generate a language program that has all resources with their inputs being default
|
|
|
|
// values. After that, we extract the resource declarations from each program into a structured map.
|
|
|
|
//
|
|
|
|
// The reason we generate a full program a schema with all the resources is that if we did every resource separately,
|
|
|
|
// it would take too long to generate the programs and the rest of the docs. That is why we batch generate them and
|
|
|
|
// split the resource declarations by comment delimiters.
|
|
|
|
func generateConstructorSyntaxData(pkg *schema.Package, languages []string) *constructorSyntaxData {
|
|
|
|
loader := NewStaticSchemaLoader(pkg)
|
|
|
|
constructorGenerator := &constructorSyntaxGenerator{
|
|
|
|
indentSize: 0,
|
|
|
|
requiredPropertiesOnly: false,
|
|
|
|
}
|
|
|
|
|
|
|
|
schemaProgram := constructorGenerator.generateAll(pkg, generateAllOptions{
|
|
|
|
includeResources: true,
|
|
|
|
includeFunctions: false,
|
|
|
|
resourcesToSkip: []string{
|
|
|
|
// Skipping problematic resources which block example generation
|
|
|
|
"aws:wafv2/ruleGroup:RuleGroup",
|
|
|
|
"aws:wafv2/webAcl:WebAcl",
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
packagesToSkip := map[string]codegen.StringSet{
|
2024-03-28 00:03:58 +00:00
|
|
|
"aws-native": codegen.NewStringSet("python", "typescript", "go", "csharp", "yaml", "java"),
|
2024-03-21 13:41:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ProgramGenerator = func(program *pcl.Program) (files map[string][]byte, diags hcl.Diagnostics, err error)
|
|
|
|
|
|
|
|
constructorSyntax := newConstructorSyntaxData()
|
|
|
|
for _, lang := range languages {
|
|
|
|
if skippedLanguages, ok := packagesToSkip[pkg.Name]; ok && skippedLanguages.Has(lang) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
boundProgram, err := constructorGenerator.bindProgram(loader, schemaProgram)
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
safeExtract := func(generator ProgramGenerator) (files map[string][]byte, diags hcl.Diagnostics, err error) {
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
err = fmt.Errorf("panic: %v", r)
|
|
|
|
files = map[string][]byte{}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return generator(boundProgram)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch lang {
|
|
|
|
case "nodejs":
|
|
|
|
files, diags, err := safeExtract(nodejs.GenerateProgram)
|
|
|
|
if !diags.HasErrors() && err == nil {
|
|
|
|
program := string(files["index.ts"])
|
|
|
|
constructorSyntax.typescript = extractConstructorSyntaxExamples(
|
|
|
|
program, /* program */
|
|
|
|
"", /* indentation to trim */
|
|
|
|
"//", /* comment prefix */
|
|
|
|
func(line string) bool { return strings.HasSuffix(line, "});") })
|
|
|
|
}
|
|
|
|
case "python":
|
|
|
|
files, diags, err := safeExtract(python.GenerateProgram)
|
|
|
|
if !diags.HasErrors() && err == nil {
|
|
|
|
program := string(files["__main__.py"])
|
|
|
|
constructorSyntax.python = extractConstructorSyntaxExamples(
|
|
|
|
program, /* program */
|
|
|
|
"", /* indentation to trim */
|
|
|
|
"#", /* comment prefix */
|
|
|
|
func(line string) bool { return strings.HasSuffix(line, ")") })
|
|
|
|
}
|
|
|
|
case "csharp":
|
|
|
|
files, diags, err := safeExtract(dotnet.GenerateProgram)
|
|
|
|
if !diags.HasErrors() && err == nil {
|
|
|
|
exampleEnd := func(line string) bool {
|
|
|
|
return strings.HasSuffix(line, "});") || strings.HasSuffix(line, `");`)
|
|
|
|
}
|
|
|
|
program := string(files["Program.cs"])
|
|
|
|
constructorSyntax.csharp = extractConstructorSyntaxExamples(
|
|
|
|
program, /* program */
|
|
|
|
" ", /* indentation to trim */
|
|
|
|
"//", /* comment prefix */
|
|
|
|
exampleEnd)
|
|
|
|
}
|
|
|
|
case "go":
|
|
|
|
files, diags, err := safeExtract(go_gen.GenerateProgram)
|
|
|
|
if !diags.HasErrors() && err == nil {
|
|
|
|
var program string
|
|
|
|
content := files["main.go"]
|
|
|
|
if formatted, err := format.Source(content); err == nil {
|
|
|
|
program = string(formatted)
|
|
|
|
} else {
|
|
|
|
program = string(content)
|
|
|
|
}
|
|
|
|
|
|
|
|
constructorSyntax.golang = extractConstructorSyntaxExamples(
|
|
|
|
program, /* program */
|
|
|
|
"\t\t", /* indentation to trim */
|
|
|
|
"//", /* comment prefix */
|
|
|
|
func(line string) bool { return strings.HasSuffix(strings.TrimSpace(line), ")") })
|
|
|
|
}
|
2024-03-27 12:11:08 +00:00
|
|
|
case "yaml":
|
|
|
|
files, diags, err := safeExtract(yaml.GenerateProgram)
|
|
|
|
if !diags.HasErrors() && err == nil {
|
|
|
|
program := string(files["Main.yaml"])
|
|
|
|
constructorSyntax.yaml = extractConstructorSyntaxExamplesFromYAML(program)
|
|
|
|
}
|
2024-03-21 13:41:07 +00:00
|
|
|
case "java":
|
2024-03-28 00:03:58 +00:00
|
|
|
files, diags, err := safeExtract(java.GenerateProgram)
|
|
|
|
if !diags.HasErrors() && err == nil {
|
|
|
|
program := string(files["MyStack.java"])
|
|
|
|
constructorSyntax.java = extractConstructorSyntaxExamples(
|
|
|
|
program, /* program */
|
|
|
|
" ", /* indentation to trim */
|
|
|
|
"//", /* comment prefix */
|
|
|
|
func(line string) bool { return strings.HasSuffix(line, ");") })
|
|
|
|
}
|
2024-03-21 13:41:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return constructorSyntax
|
|
|
|
}
|
|
|
|
|
2024-03-27 12:11:08 +00:00
|
|
|
// collapseToken converts an exact token to a token more suitable for
|
|
|
|
// display. For example, it converts
|
|
|
|
//
|
|
|
|
// fizz:index/buzz:Buzz => fizz:Buzz
|
|
|
|
// fizz:mode/buzz:Buzz => fizz:mode:Buzz
|
|
|
|
// foo:index:Bar => foo:Bar
|
|
|
|
// foo::Bar => foo:Bar
|
|
|
|
// fizz:mod:buzz => fizz:mod:buzz
|
|
|
|
func collapseYAMLToken(token string) string {
|
|
|
|
tokenParts := strings.Split(token, ":")
|
|
|
|
|
|
|
|
if len(tokenParts) == 3 {
|
|
|
|
title := func(s string) string {
|
|
|
|
r := []rune(s)
|
|
|
|
if len(r) == 0 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return strings.ToTitle(string(r[0])) + string(r[1:])
|
|
|
|
}
|
|
|
|
if mod := strings.Split(tokenParts[1], "/"); len(mod) == 2 && title(mod[1]) == tokenParts[2] {
|
|
|
|
// aws:s3/bucket:Bucket => aws:s3:Bucket
|
|
|
|
// We handle the case foo:index/bar:Bar => foo:index:Bar
|
|
|
|
tokenParts = []string{tokenParts[0], mod[0], tokenParts[2]}
|
|
|
|
}
|
|
|
|
|
|
|
|
if tokenParts[1] == "index" || tokenParts[1] == "" {
|
|
|
|
// foo:index:Bar => foo:Bar
|
|
|
|
// or
|
|
|
|
// foo::Bar => foo:Bar
|
|
|
|
tokenParts = []string{tokenParts[0], tokenParts[2]}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(tokenParts, ":")
|
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
func (dctx *docGenContext) initialize(tool string, pkg *schema.Package) {
|
|
|
|
dctx.templates = template.New("").Funcs(template.FuncMap{
|
2020-03-20 15:17:58 +00:00
|
|
|
"htmlSafe": func(html string) template.HTML {
|
|
|
|
// Markdown fragments in the templates need to be rendered as-is,
|
|
|
|
// so that html/template package doesn't try to inject data into it,
|
|
|
|
// which will most certainly fail.
|
2023-01-06 01:10:56 +00:00
|
|
|
//nolint:gosec
|
2020-03-20 15:17:58 +00:00
|
|
|
return template.HTML(html)
|
|
|
|
},
|
2022-04-29 22:04:15 +00:00
|
|
|
"markdownify": func(html string) template.HTML {
|
|
|
|
// Convert a string of Markdown into HTML.
|
|
|
|
var buf bytes.Buffer
|
|
|
|
if err := goldmark.Convert([]byte(html), &buf); err != nil {
|
|
|
|
glog.Fatalf("rendering Markdown: %v", err)
|
|
|
|
}
|
2023-08-26 17:36:28 +00:00
|
|
|
rendered := buf.String()
|
|
|
|
|
|
|
|
// Trim surrounding <p></p> tags.
|
|
|
|
result := strings.TrimSpace(rendered)
|
|
|
|
result = strings.TrimPrefix(result, "<p>")
|
|
|
|
result = strings.TrimSuffix(result, "</p>")
|
|
|
|
|
|
|
|
// If there are still <p> tags, there are multiple paragraphs,
|
|
|
|
// in which case use the original rendered string (untrimmed).
|
|
|
|
if strings.Contains(result, "<p>") {
|
|
|
|
result = rendered
|
|
|
|
}
|
|
|
|
|
2023-01-06 01:10:56 +00:00
|
|
|
//nolint:gosec
|
2023-08-26 17:36:28 +00:00
|
|
|
return template.HTML(result)
|
2022-04-29 22:04:15 +00:00
|
|
|
},
|
2020-03-20 15:17:58 +00:00
|
|
|
})
|
|
|
|
|
2021-10-01 00:35:44 +00:00
|
|
|
defer glog.Flush()
|
|
|
|
|
2021-11-10 19:07:43 +00:00
|
|
|
if _, err := dctx.templates.ParseFS(packagedTemplates, "templates/*.tmpl"); err != nil {
|
|
|
|
glog.Fatalf("initializing templates: %v", err)
|
2020-03-20 15:17:58 +00:00
|
|
|
}
|
2020-02-27 18:04:34 +00:00
|
|
|
|
2024-03-21 13:41:07 +00:00
|
|
|
dctx.constructorSyntaxData = generateConstructorSyntaxData(pkg, dctx.supportedLanguages)
|
2020-03-20 15:17:58 +00:00
|
|
|
// Generate the modules from the schema, and for every module
|
|
|
|
// run the generator functions to generate markdown files.
|
2021-10-06 15:03:21 +00:00
|
|
|
dctx.setModules(dctx.generateModulesFromSchemaPackage(tool, pkg))
|
2021-10-01 00:35:44 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 15:03:21 +00:00
|
|
|
func (dctx *docGenContext) generatePackage(tool string, pkg *schema.Package) (map[string][]byte, error) {
|
|
|
|
if dctx.modules() == nil {
|
2021-10-01 00:35:44 +00:00
|
|
|
return nil, errors.New("must call Initialize before generating the docs package")
|
|
|
|
}
|
|
|
|
|
|
|
|
defer glog.Flush()
|
|
|
|
|
|
|
|
glog.V(3).Infoln("generating package docs now...")
|
2022-11-09 19:49:59 +00:00
|
|
|
files := codegen.Fs{}
|
2021-11-18 20:23:30 +00:00
|
|
|
modules := []string{}
|
|
|
|
modMap := dctx.modules()
|
|
|
|
for k := range modMap {
|
|
|
|
modules = append(modules, k)
|
|
|
|
}
|
|
|
|
sort.Strings(modules)
|
|
|
|
for _, mod := range modules {
|
|
|
|
if err := modMap[mod].gen(files); err != nil {
|
2020-02-27 18:04:34 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return files, nil
|
|
|
|
}
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
|
2024-02-20 15:44:37 +00:00
|
|
|
const (
|
|
|
|
// "" indicates the top-most module.
|
|
|
|
topMostModule tokens.ModuleName = ""
|
|
|
|
)
|
|
|
|
|
2021-10-01 00:35:44 +00:00
|
|
|
// GeneratePackageTree returns a navigable structure starting from the top-most module.
|
2021-10-06 15:03:21 +00:00
|
|
|
func (dctx *docGenContext) generatePackageTree() ([]PackageTreeItem, error) {
|
|
|
|
if dctx.modules() == nil {
|
2021-10-01 00:35:44 +00:00
|
|
|
return nil, errors.New("must call Initialize before generating the docs package")
|
|
|
|
}
|
|
|
|
|
|
|
|
defer glog.Flush()
|
|
|
|
|
|
|
|
var packageTree []PackageTreeItem
|
2024-02-20 15:44:37 +00:00
|
|
|
if rootMod, ok := dctx.modules()[string(topMostModule)]; ok {
|
2021-10-01 00:35:44 +00:00
|
|
|
tree, err := generatePackageTree(*rootMod)
|
|
|
|
if err != nil {
|
|
|
|
glog.Errorf("Error generating the package tree for package: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
packageTree = tree
|
|
|
|
} else {
|
|
|
|
glog.Error("A root module entry was not found for the package. Cannot generate the package tree...")
|
|
|
|
}
|
|
|
|
|
|
|
|
return packageTree, nil
|
|
|
|
}
|
|
|
|
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
func visitObjectTypes(properties []*schema.Property, visitor func(t schema.Type)) {
|
2021-06-24 16:17:55 +00:00
|
|
|
codegen.VisitTypeClosure(properties, func(t schema.Type) {
|
|
|
|
switch st := t.(type) {
|
[codegen/python] Rename conflicting ResourceArgs classes (#7171)
Python resource constructor overloads were recently added that accept a
`<Resource>Args` class for input properties, as an alternative to the
other constructor overload that accepts keyword arguments. The name of
the new args class is the name of the resource concatenated with an
`Args` suffix.
Some providers (e.g. Kubernetes, Azure Native, and Google Native) have
input types with the same name as resources in the same module, which
results in two different `<Resource>Args` classes in the same module.
When you try to use the new args class with the constructor, e.g.:
```python
pulumi_kubernetes.storage.v1.StorageClass(
resource_name='string',
args=pulumi_kubernetes.storage.v1.StorageClassArgs(...),
opts=pulumi.ResourceOptions(...),
)
```
You run into an error, because
`pulumi_kubernetes.storage.v1.StorageClassArgs` is actually referring to
the existing input type rather than the intended `StorageClassArgs`
class for the constructor arguments.
Having the duplicate classes hasn't broken existing usage of the input
type because we "export" all the input types for a module _after_ all
the resources and resource args classes are exported, so the input type
just ends up "overwriting" the duplicate resource args class.
Other languages don't have this problem because the input type is either
in it's own module/namespace (e.g. Node.js and .NET) or a different name
is used for the input type (Go). But with Python, the input types and
resources are all available in the same module.
To address this for Python, when there is an input type in the same
module with the same name as the resource, the args class for the
resource will be emitted as `<Resource>InitArgs` instead of
`<Resource>Args`.
2021-06-10 17:41:49 +00:00
|
|
|
case *schema.EnumType, *schema.ObjectType, *schema.ResourceType:
|
|
|
|
visitor(st)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2021-10-06 15:03:21 +00:00
|
|
|
|
|
|
|
// Export a default static context so as not to break external
|
|
|
|
// consumers of this API; prefer *WithContext API internally to ensure
|
|
|
|
// tests can run in parallel.
|
|
|
|
var defaultContext = newDocGenContext()
|
|
|
|
|
|
|
|
func Initialize(tool string, pkg *schema.Package) {
|
|
|
|
defaultContext.initialize(tool, pkg)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GeneratePackage generates docs for each resource given the Pulumi
|
|
|
|
// schema. The returned map contains the filename with path as the key
|
|
|
|
// and the contents as its value.
|
|
|
|
func GeneratePackage(tool string, pkg *schema.Package) (map[string][]byte, error) {
|
|
|
|
return defaultContext.generatePackage(tool, pkg)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GeneratePackageTree returns a navigable structure starting from the top-most module.
|
|
|
|
func GeneratePackageTree() ([]PackageTreeItem, error) {
|
|
|
|
return defaultContext.generatePackageTree()
|
|
|
|
}
|
2024-02-20 15:44:37 +00:00
|
|
|
|
|
|
|
// Returns the parent module, if available. For top-level modules the parent is a special
|
|
|
|
// topMostModule. For topMostModule itself there is no parent and this function returns false.
|
|
|
|
func parentModule(modName tokens.ModuleName) (tokens.ModuleName, bool) {
|
|
|
|
switch {
|
|
|
|
case modName == topMostModule:
|
|
|
|
return "", false
|
|
|
|
case strings.Contains(string(modName), tokens.QNameDelimiter):
|
|
|
|
return tokens.ModuleName(tokens.QName(modName).Namespace()), true
|
|
|
|
default:
|
|
|
|
return topMostModule, true
|
|
|
|
}
|
|
|
|
}
|