[codegen/go] Rewrite cyclic types. (#8049)

When computing the type name for a field of an object type, we must
ensure that we do not generate invalid recursive struct types. A struct
type T contains invalid recursion if the closure of its fields and its
struct-typed fields' fields includes a field of type T. A few examples:

Directly invalid:

    type T struct { Invalid T }

Indirectly invalid:

    type T struct { Invalid S }

    type S struct { Invalid T }

In order to avoid generating invalid struct types, we replace all
references to types involved in a cyclical definition with *T. The
examples above therefore become:

(1) type T struct { Valid *T }

(2) type T struct { Valid *S }

    type S struct { Valid *T }

We do this using a rewriter that turns all fields involved in reference
cycles into optional fields.

These changes also include an enhancement to the SDK codegen test
driver in the interest of making iterating and debugging more convenient:  if the -sdk.no-checks flag is passed, the driver will not run post-generation checks.
This commit is contained in:
Pat Gavlin 2021-09-28 07:33:14 -07:00 committed by GitHub
parent a182f103cf
commit 0a45f8d3ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 2057 additions and 9 deletions

View file

@ -24,3 +24,6 @@
- [codegen/nodejs] - Fix generation of provider enum with environment variables.
[#8051](https://github.com/pulumi/pulumi/pull/8051)
- [codegen/go] - Fix generation of cyclic struct types.
[#8049](https://github.com/pulumi/pulumi/pull/8049)

View file

@ -94,10 +94,12 @@ type pkgContext struct {
types []*schema.ObjectType
resources []*schema.Resource
functions []*schema.Function
// schemaNames tracks the names of types/resources as specified in the schema
schemaNames codegen.StringSet
names codegen.StringSet
renamed map[string]string
// duplicateTokens tracks tokens that exist for both types and resources
duplicateTokens map[string]bool
functionNames map[*schema.Function]string
@ -1878,6 +1880,111 @@ func init() {
fmt.Fprintf(w, initCode)
}
type objectProperty struct {
object *schema.ObjectType
property *schema.Property
}
// When computing the type name for a field of an object type, we must ensure that we do not generate invalid recursive
// struct types. A struct type T contains invalid recursion if the closure of its fields and its struct-typed fields'
// fields includes a field of type T. A few examples:
//
// Directly invalid:
//
// type T struct {
// Invalid T
// }
//
// Indirectly invalid:
//
// type T struct {
// Invalid S
// }
//
// type S struct {
// Invalid T
// }
//
// In order to avoid generating invalid struct types, we replace all references to types involved in a cyclical
// definition with *T. The examples above therefore become:
//
// (1)
// type T struct {
// Valid *T
// }
//
// (2)
// type T struct {
// Valid *S
// }
//
// type S struct {
// Valid *T
// }
//
// We do this using a rewriter that turns all fields involved in reference cycles into optional fields.
func rewriteCyclicField(rewritten codegen.Set, path []objectProperty, op objectProperty) {
// If this property refers to an Input<> type, unwrap the type. This ensures that the plain and input shapes of an
// object type remain identical.
t := op.property.Type
if inputType, isInputType := op.property.Type.(*schema.InputType); isInputType {
t = inputType.ElementType
}
// If this property does not refer to an object type, it cannot be involved in a cycle. Skip it.
objectType, isObjectType := t.(*schema.ObjectType)
if !isObjectType {
return
}
path = append(path, op)
// Check the current path for cycles by crawling backwards until reaching the start of the path
// or finding a property that is a member of the current object type.
var cycle []objectProperty
for i := len(path) - 1; i > 0; i-- {
if path[i].object == objectType {
cycle = path[i:]
break
}
}
// If the current path does not involve a cycle, recur into the current object type.
if len(cycle) == 0 {
rewriteCyclicFields(rewritten, path, objectType)
return
}
// If we've found a cycle, mark each property involved in the cycle as optional.
//
// NOTE: this overestimates the set of properties that must be marked as optional. For example, in case (2) above,
// only one of T.Invalid or S.Invalid needs to be marked as optional in order to break the cycle. However, choosing
// a minimal set of properties that is also deterministic and resilient to changes in visit order is difficult and
// seems to add little value.
for _, p := range cycle {
p.property.Type = codegen.OptionalType(p.property)
}
}
func rewriteCyclicFields(rewritten codegen.Set, path []objectProperty, obj *schema.ObjectType) {
if !rewritten.Has(obj) {
rewritten.Add(obj)
for _, property := range obj.Properties {
rewriteCyclicField(rewritten, path, objectProperty{obj, property})
}
}
}
func rewriteCyclicObjectFields(pkg *schema.Package) {
rewritten := codegen.Set{}
for _, t := range pkg.Types {
if obj, ok := t.(*schema.ObjectType); ok && !obj.IsInputShape() {
rewriteCyclicFields(rewritten, nil, obj)
rewriteCyclicFields(rewritten, nil, obj.InputShape)
}
}
}
func (pkg *pkgContext) genType(w io.Writer, obj *schema.ObjectType) {
contract.Assert(!obj.IsInputShape())
@ -2479,6 +2586,9 @@ func generatePackageContextMap(tool string, pkg *schema.Package, goInfo GoPackag
}
}
// Rewrite cyclic types. See the docs on rewriteCyclicFields for the motivation.
rewriteCyclicObjectFields(pkg)
// Use a string set to track object types that have already been processed.
// This avoids recursively processing the same type. For example, in the
// Kubernetes package, JSONSchemaProps have properties whose type is itself.

View file

@ -1,6 +1,7 @@
package test
import (
"flag"
"fmt"
"os"
"path/filepath"
@ -134,13 +135,13 @@ var sdkTests = []sdkTest{
},
{
Directory: "resource-property-overlap",
Description: "A resource with the same name as it's property",
Description: "A resource with the same name as its property",
SkipCompileCheck: codegen.NewStringSet(dotnet, nodejs),
Skip: codegen.NewStringSet("python/test"),
},
{
Directory: "hyphen-url",
Description: "A resource url with a hyphen in it's path",
Description: "A resource url with a hyphen in its path",
Skip: codegen.NewStringSet("python/test"),
},
{
@ -148,6 +149,22 @@ var sdkTests = []sdkTest{
Description: "Tests targeting the $fn_output helper code generation feature",
SkipCompileCheck: codegen.NewStringSet(dotnet),
},
{
Directory: "cyclic-types",
Description: "Cyclic object types",
Skip: codegen.NewStringSet("python/test"),
},
}
var genSDKOnly bool
func NoSDKCodegenChecks() bool {
return genSDKOnly
}
func init() {
flag.BoolVar(&genSDKOnly, "sdk.no-checks", false, "when set, skips all post-SDK-generation checks")
// NOTE: the testing package will call flag.Parse.
}
type SDKCodegenOptions struct {
@ -253,6 +270,10 @@ func TestSDKCodegen(t *testing.T, opts *SDKCodegenOptions) { // revive:disable-l
}
}
if genSDKOnly {
return
}
CopyExtraFiles(t, dirPath, opts.Language)
// Merge language-specific global and

View file

@ -0,0 +1,29 @@
---
title: "example"
title_tag: "example.example"
meta_desc: ""
menu:
reference:
parent: API Reference
---
<!-- WARNING: this file was generated by test. -->
<!-- Do not edit by hand unless you're certain you know what you are doing! -->
<h2 id="resources">Resources</h2>
<ul class="api">
<li><a href="provider" title="Provider"><span class="symbol resource"></span>Provider</a></li>
</ul>
<h2 id="package-details">Package Details</h2>
<dl class="package-details">
<dt>Repository</dt>
<dd><a href=""></a></dd>
<dt>License</dt>
<dd></dd>
<dt>Version</dt>
<dd>0.0.1</dd>
</dl>

View file

@ -0,0 +1,6 @@
{
"emittedFiles": [
"_index.md",
"provider/_index.md"
]
}

View file

@ -0,0 +1,239 @@
---
title: "Provider"
title_tag: "example.Provider"
meta_desc: "Documentation for the example.Provider resource with examples, input properties, output properties, lookup functions, and supporting types."
---
<!-- WARNING: this file was generated by test. -->
<!-- Do not edit by hand unless you're certain you know what you are doing! -->
## Create a Provider Resource {#create}
{{< chooser language "typescript,python,go,csharp" / >}}
{{% choosable language nodejs %}}
<div class="highlight"><pre class="chroma"><code class="language-typescript" data-lang="typescript"><span class="k">new </span><span class="nx">Provider</span><span class="p">(</span><span class="nx">name</span><span class="p">:</span> <span class="nx">string</span><span class="p">,</span> <span class="nx">args</span><span class="p">?:</span> <span class="nx"><a href="#inputs">ProviderArgs</a></span><span class="p">,</span> <span class="nx">opts</span><span class="p">?:</span> <span class="nx"><a href="/docs/reference/pkg/nodejs/pulumi/pulumi/#CustomResourceOptions">CustomResourceOptions</a></span><span class="p">);</span></code></pre></div>
{{% /choosable %}}
{{% choosable language python %}}
<div class="highlight"><pre class="chroma"><code class="language-python" data-lang="python"><span class=nd>@overload</span>
<span class="k">def </span><span class="nx">Provider</span><span class="p">(</span><span class="nx">resource_name</span><span class="p">:</span> <span class="nx">str</span><span class="p">,</span>
<span class="nx">opts</span><span class="p">:</span> <span class="nx"><a href="/docs/reference/pkg/python/pulumi/#pulumi.ResourceOptions">Optional[ResourceOptions]</a></span> = None<span class="p">)</span>
<span class=nd>@overload</span>
<span class="k">def </span><span class="nx">Provider</span><span class="p">(</span><span class="nx">resource_name</span><span class="p">:</span> <span class="nx">str</span><span class="p">,</span>
<span class="nx">args</span><span class="p">:</span> <span class="nx"><a href="#inputs">Optional[ProviderArgs]</a></span> = None<span class="p">,</span>
<span class="nx">opts</span><span class="p">:</span> <span class="nx"><a href="/docs/reference/pkg/python/pulumi/#pulumi.ResourceOptions">Optional[ResourceOptions]</a></span> = None<span class="p">)</span></code></pre></div>
{{% /choosable %}}
{{% choosable language go %}}
<div class="highlight"><pre class="chroma"><code class="language-go" data-lang="go"><span class="k">func </span><span class="nx">NewProvider</span><span class="p">(</span><span class="nx">ctx</span><span class="p"> *</span><span class="nx"><a href="https://pkg.go.dev/github.com/pulumi/pulumi/sdk/v3/go/pulumi?tab=doc#Context">Context</a></span><span class="p">,</span> <span class="nx">name</span><span class="p"> </span><span class="nx">string</span><span class="p">,</span> <span class="nx">args</span><span class="p"> *</span><span class="nx"><a href="#inputs">ProviderArgs</a></span><span class="p">,</span> <span class="nx">opts</span><span class="p"> ...</span><span class="nx"><a href="https://pkg.go.dev/github.com/pulumi/pulumi/sdk/v3/go/pulumi?tab=doc#ResourceOption">ResourceOption</a></span><span class="p">) (*<span class="nx">Provider</span>, error)</span></code></pre></div>
{{% /choosable %}}
{{% choosable language csharp %}}
<div class="highlight"><pre class="chroma"><code class="language-csharp" data-lang="csharp"><span class="k">public </span><span class="nx">Provider</span><span class="p">(</span><span class="nx">string</span><span class="p"> </span><span class="nx">name<span class="p">,</span> <span class="nx"><a href="#inputs">ProviderArgs</a></span><span class="p">? </span><span class="nx">args = null<span class="p">,</span> <span class="nx"><a href="/docs/reference/pkg/dotnet/Pulumi/Pulumi.CustomResourceOptions.html">CustomResourceOptions</a></span><span class="p">? </span><span class="nx">opts = null<span class="p">)</span></code></pre></div>
{{% /choosable %}}
{{% choosable language nodejs %}}
<dl class="resources-properties"><dt
class="property-required" title="Required">
<span>name</span>
<span class="property-indicator"></span>
<span class="property-type">string</span>
</dt>
<dd>The unique name of the resource.</dd><dt
class="property-optional" title="Optional">
<span>args</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="#inputs">ProviderArgs</a></span>
</dt>
<dd>The arguments to resource properties.</dd><dt
class="property-optional" title="Optional">
<span>opts</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="/docs/reference/pkg/nodejs/pulumi/pulumi/#CustomResourceOptions">CustomResourceOptions</a></span>
</dt>
<dd>Bag of options to control resource&#39;s behavior.</dd></dl>
{{% /choosable %}}
{{% choosable language python %}}
<dl class="resources-properties"><dt
class="property-required" title="Required">
<span>resource_name</span>
<span class="property-indicator"></span>
<span class="property-type">str</span>
</dt>
<dd>The unique name of the resource.</dd><dt
class="property-optional" title="Optional">
<span>args</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="#inputs">ProviderArgs</a></span>
</dt>
<dd>The arguments to resource properties.</dd><dt
class="property-optional" title="Optional">
<span>opts</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="/docs/reference/pkg/python/pulumi/#pulumi.ResourceOptions">ResourceOptions</a></span>
</dt>
<dd>Bag of options to control resource&#39;s behavior.</dd></dl>
{{% /choosable %}}
{{% choosable language go %}}
<dl class="resources-properties"><dt
class="property-optional" title="Optional">
<span>ctx</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="https://pkg.go.dev/github.com/pulumi/pulumi/sdk/v3/go/pulumi?tab=doc#Context">Context</a></span>
</dt>
<dd>Context object for the current deployment.</dd><dt
class="property-required" title="Required">
<span>name</span>
<span class="property-indicator"></span>
<span class="property-type">string</span>
</dt>
<dd>The unique name of the resource.</dd><dt
class="property-optional" title="Optional">
<span>args</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="#inputs">ProviderArgs</a></span>
</dt>
<dd>The arguments to resource properties.</dd><dt
class="property-optional" title="Optional">
<span>opts</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="https://pkg.go.dev/github.com/pulumi/pulumi/sdk/v3/go/pulumi?tab=doc#ResourceOption">ResourceOption</a></span>
</dt>
<dd>Bag of options to control resource&#39;s behavior.</dd></dl>
{{% /choosable %}}
{{% choosable language csharp %}}
<dl class="resources-properties"><dt
class="property-required" title="Required">
<span>name</span>
<span class="property-indicator"></span>
<span class="property-type">string</span>
</dt>
<dd>The unique name of the resource.</dd><dt
class="property-optional" title="Optional">
<span>args</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="#inputs">ProviderArgs</a></span>
</dt>
<dd>The arguments to resource properties.</dd><dt
class="property-optional" title="Optional">
<span>opts</span>
<span class="property-indicator"></span>
<span class="property-type"><a href="/docs/reference/pkg/dotnet/Pulumi/Pulumi.CustomResourceOptions.html">CustomResourceOptions</a></span>
</dt>
<dd>Bag of options to control resource&#39;s behavior.</dd></dl>
{{% /choosable %}}
## Provider Resource Properties {#properties}
To learn more about resource properties and how to use them, see [Inputs and Outputs]({{< relref "/docs/intro/concepts/inputs-outputs" >}}) in the Architecture and Concepts docs.
### Inputs
The Provider resource accepts the following [input]({{< relref "/docs/intro/concepts/inputs-outputs" >}}) properties:
{{% choosable language csharp %}}
<dl class="resources-properties"></dl>
{{% /choosable %}}
{{% choosable language go %}}
<dl class="resources-properties"></dl>
{{% /choosable %}}
{{% choosable language nodejs %}}
<dl class="resources-properties"></dl>
{{% /choosable %}}
{{% choosable language python %}}
<dl class="resources-properties"></dl>
{{% /choosable %}}
### Outputs
All [input](#inputs) properties are implicitly available as output properties. Additionally, the Provider resource produces the following output properties:
{{% choosable language csharp %}}
<dl class="resources-properties"><dt class="property-"
title="">
<span id="id_csharp">
<a href="#id_csharp" style="color: inherit; text-decoration: inherit;">Id</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">string</span>
</dt>
<dd>{{% md %}}The provider-assigned unique ID for this managed resource.{{% /md %}}</dd></dl>
{{% /choosable %}}
{{% choosable language go %}}
<dl class="resources-properties"><dt class="property-"
title="">
<span id="id_go">
<a href="#id_go" style="color: inherit; text-decoration: inherit;">Id</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">string</span>
</dt>
<dd>{{% md %}}The provider-assigned unique ID for this managed resource.{{% /md %}}</dd></dl>
{{% /choosable %}}
{{% choosable language nodejs %}}
<dl class="resources-properties"><dt class="property-"
title="">
<span id="id_nodejs">
<a href="#id_nodejs" style="color: inherit; text-decoration: inherit;">id</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">string</span>
</dt>
<dd>{{% md %}}The provider-assigned unique ID for this managed resource.{{% /md %}}</dd></dl>
{{% /choosable %}}
{{% choosable language python %}}
<dl class="resources-properties"><dt class="property-"
title="">
<span id="id_python">
<a href="#id_python" style="color: inherit; text-decoration: inherit;">id</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">str</span>
</dt>
<dd>{{% md %}}The provider-assigned unique ID for this managed resource.{{% /md %}}</dd></dl>
{{% /choosable %}}
<h2 id="package-details">Package Details</h2>
<dl class="package-details">
<dt>Repository</dt>
<dd><a href=""></a></dd>
<dt>License</dt>
<dd></dd>
</dl>

View file

@ -0,0 +1,46 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Pulumi.Serialization;
namespace Pulumi.Example
{
[ExampleResourceType("pulumi:providers:example")]
public partial class Provider : Pulumi.ProviderResource
{
/// <summary>
/// Create a Provider resource with the given unique name, arguments, and options.
/// </summary>
///
/// <param name="name">The unique name of the resource</param>
/// <param name="args">The arguments used to populate this resource's properties</param>
/// <param name="options">A bag of options that control this resource's behavior</param>
public Provider(string name, ProviderArgs? args = null, CustomResourceOptions? options = null)
: base("example", name, args ?? new ProviderArgs(), MakeResourceOptions(options, ""))
{
}
private static CustomResourceOptions MakeResourceOptions(CustomResourceOptions? options, Input<string>? id)
{
var defaultOptions = new CustomResourceOptions
{
Version = Utilities.Version,
};
var merged = CustomResourceOptions.Merge(defaultOptions, options);
// Override the ID if one was specified for consistency with other language SDKs.
merged.Id = id ?? merged.Id;
return merged;
}
}
public sealed class ProviderArgs : Pulumi.ResourceArgs
{
public ProviderArgs()
{
}
}
}

View file

@ -0,0 +1,53 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Pulumi Corp.</Authors>
<Company>Pulumi Corp.</Company>
<Description></Description>
<PackageLicenseExpression></PackageLicenseExpression>
<PackageProjectUrl></PackageProjectUrl>
<RepositoryUrl></RepositoryUrl>
<PackageIcon>logo.png</PackageIcon>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Nullable>enable</Nullable>
<UseSharedCompilation>false</UseSharedCompilation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
</PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="version.txt" />
<None Include="version.txt" Pack="True" PackagePath="content" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Pulumi" Version="3.12" />
</ItemGroup>
<ItemGroup>
<None Include="logo.png">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,87 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
using System;
using System.IO;
using System.Reflection;
using Pulumi;
namespace Pulumi.Example
{
static class Utilities
{
public static string? GetEnv(params string[] names)
{
foreach (var n in names)
{
var value = Environment.GetEnvironmentVariable(n);
if (value != null)
{
return value;
}
}
return null;
}
static string[] trueValues = { "1", "t", "T", "true", "TRUE", "True" };
static string[] falseValues = { "0", "f", "F", "false", "FALSE", "False" };
public static bool? GetEnvBoolean(params string[] names)
{
var s = GetEnv(names);
if (s != null)
{
if (Array.IndexOf(trueValues, s) != -1)
{
return true;
}
if (Array.IndexOf(falseValues, s) != -1)
{
return false;
}
}
return null;
}
public static int? GetEnvInt32(params string[] names) => int.TryParse(GetEnv(names), out int v) ? (int?)v : null;
public static double? GetEnvDouble(params string[] names) => double.TryParse(GetEnv(names), out double v) ? (double?)v : null;
public static InvokeOptions WithVersion(this InvokeOptions? options)
{
if (options?.Version != null)
{
return options;
}
return new InvokeOptions
{
Parent = options?.Parent,
Provider = options?.Provider,
Version = Version,
};
}
private readonly static string version;
public static string Version => version;
static Utilities()
{
var assembly = typeof(Utilities).GetTypeInfo().Assembly;
using var stream = assembly.GetManifestResourceStream("Pulumi.Example.version.txt");
using var reader = new StreamReader(stream ?? throw new NotSupportedException("Missing embedded version.txt file"));
version = reader.ReadToEnd().Trim();
var parts = version.Split("\n");
if (parts.Length == 2)
{
// The first part is the provider name.
version = parts[1].Trim();
}
}
}
internal sealed class ExampleResourceTypeAttribute : Pulumi.ResourceTypeAttribute
{
public ExampleResourceTypeAttribute(string type) : base(type, Utilities.Version)
{
}
}
}

View file

@ -0,0 +1,9 @@
{
"emittedFiles": [
"Provider.cs",
"Pulumi.Example.csproj",
"README.md",
"Utilities.cs",
"logo.png"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View file

@ -0,0 +1,9 @@
{
"emittedFiles": [
"example/doc.go",
"example/init.go",
"example/provider.go",
"example/pulumiTypes.go",
"example/pulumiUtilities.go"
]
}

View file

@ -0,0 +1,3 @@
// Package example exports types, functions, subpackages for provisioning example resources.
//
package example

View file

@ -0,0 +1,40 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
package example
import (
"fmt"
"github.com/blang/semver"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
type pkg struct {
version semver.Version
}
func (p *pkg) Version() semver.Version {
return p.version
}
func (p *pkg) ConstructProvider(ctx *pulumi.Context, name, typ, urn string) (pulumi.ProviderResource, error) {
if typ != "pulumi:providers:example" {
return nil, fmt.Errorf("unknown provider type: %s", typ)
}
r := &Provider{}
err := ctx.RegisterResource(typ, name, nil, r, pulumi.URN_(urn))
return r, err
}
func init() {
version, err := PkgVersion()
if err != nil {
fmt.Printf("failed to determine package version. defaulting to v1: %v\n", err)
}
pulumi.RegisterResourcePackage(
"example",
&pkg{version},
)
}

View file

@ -0,0 +1,78 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
package example
import (
"context"
"reflect"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
type Provider struct {
pulumi.ProviderResourceState
}
// NewProvider registers a new resource with the given unique name, arguments, and options.
func NewProvider(ctx *pulumi.Context,
name string, args *ProviderArgs, opts ...pulumi.ResourceOption) (*Provider, error) {
if args == nil {
args = &ProviderArgs{}
}
var resource Provider
err := ctx.RegisterResource("pulumi:providers:example", name, args, &resource, opts...)
if err != nil {
return nil, err
}
return &resource, nil
}
type providerArgs struct {
}
// The set of arguments for constructing a Provider resource.
type ProviderArgs struct {
}
func (ProviderArgs) ElementType() reflect.Type {
return reflect.TypeOf((*providerArgs)(nil)).Elem()
}
type ProviderInput interface {
pulumi.Input
ToProviderOutput() ProviderOutput
ToProviderOutputWithContext(ctx context.Context) ProviderOutput
}
func (*Provider) ElementType() reflect.Type {
return reflect.TypeOf((*Provider)(nil))
}
func (i *Provider) ToProviderOutput() ProviderOutput {
return i.ToProviderOutputWithContext(context.Background())
}
func (i *Provider) ToProviderOutputWithContext(ctx context.Context) ProviderOutput {
return pulumi.ToOutputWithContext(ctx, i).(ProviderOutput)
}
type ProviderOutput struct{ *pulumi.OutputState }
func (ProviderOutput) ElementType() reflect.Type {
return reflect.TypeOf((*Provider)(nil))
}
func (o ProviderOutput) ToProviderOutput() ProviderOutput {
return o
}
func (o ProviderOutput) ToProviderOutputWithContext(ctx context.Context) ProviderOutput {
return o
}
func init() {
pulumi.RegisterOutputType(ProviderOutput{})
}

View file

@ -0,0 +1,581 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
package example
import (
"context"
"reflect"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
type AcyclicReferent struct {
Bar IndirectCycleS `pulumi:"bar"`
Baz IndirectCycleT `pulumi:"baz"`
Foo4 DirectCycle `pulumi:"foo4"`
}
// AcyclicReferentInput is an input type that accepts AcyclicReferentArgs and AcyclicReferentOutput values.
// You can construct a concrete instance of `AcyclicReferentInput` via:
//
// AcyclicReferentArgs{...}
type AcyclicReferentInput interface {
pulumi.Input
ToAcyclicReferentOutput() AcyclicReferentOutput
ToAcyclicReferentOutputWithContext(context.Context) AcyclicReferentOutput
}
type AcyclicReferentArgs struct {
Bar IndirectCycleSInput `pulumi:"bar"`
Baz IndirectCycleTInput `pulumi:"baz"`
Foo4 DirectCycleInput `pulumi:"foo4"`
}
func (AcyclicReferentArgs) ElementType() reflect.Type {
return reflect.TypeOf((*AcyclicReferent)(nil)).Elem()
}
func (i AcyclicReferentArgs) ToAcyclicReferentOutput() AcyclicReferentOutput {
return i.ToAcyclicReferentOutputWithContext(context.Background())
}
func (i AcyclicReferentArgs) ToAcyclicReferentOutputWithContext(ctx context.Context) AcyclicReferentOutput {
return pulumi.ToOutputWithContext(ctx, i).(AcyclicReferentOutput)
}
type AcyclicReferentOutput struct{ *pulumi.OutputState }
func (AcyclicReferentOutput) ElementType() reflect.Type {
return reflect.TypeOf((*AcyclicReferent)(nil)).Elem()
}
func (o AcyclicReferentOutput) ToAcyclicReferentOutput() AcyclicReferentOutput {
return o
}
func (o AcyclicReferentOutput) ToAcyclicReferentOutputWithContext(ctx context.Context) AcyclicReferentOutput {
return o
}
func (o AcyclicReferentOutput) Bar() IndirectCycleSOutput {
return o.ApplyT(func(v AcyclicReferent) IndirectCycleS { return v.Bar }).(IndirectCycleSOutput)
}
func (o AcyclicReferentOutput) Baz() IndirectCycleTOutput {
return o.ApplyT(func(v AcyclicReferent) IndirectCycleT { return v.Baz }).(IndirectCycleTOutput)
}
func (o AcyclicReferentOutput) Foo4() DirectCycleOutput {
return o.ApplyT(func(v AcyclicReferent) DirectCycle { return v.Foo4 }).(DirectCycleOutput)
}
type AcyclicS struct {
Foo5 string `pulumi:"foo5"`
}
// AcyclicSInput is an input type that accepts AcyclicSArgs and AcyclicSOutput values.
// You can construct a concrete instance of `AcyclicSInput` via:
//
// AcyclicSArgs{...}
type AcyclicSInput interface {
pulumi.Input
ToAcyclicSOutput() AcyclicSOutput
ToAcyclicSOutputWithContext(context.Context) AcyclicSOutput
}
type AcyclicSArgs struct {
Foo5 pulumi.StringInput `pulumi:"foo5"`
}
func (AcyclicSArgs) ElementType() reflect.Type {
return reflect.TypeOf((*AcyclicS)(nil)).Elem()
}
func (i AcyclicSArgs) ToAcyclicSOutput() AcyclicSOutput {
return i.ToAcyclicSOutputWithContext(context.Background())
}
func (i AcyclicSArgs) ToAcyclicSOutputWithContext(ctx context.Context) AcyclicSOutput {
return pulumi.ToOutputWithContext(ctx, i).(AcyclicSOutput)
}
type AcyclicSOutput struct{ *pulumi.OutputState }
func (AcyclicSOutput) ElementType() reflect.Type {
return reflect.TypeOf((*AcyclicS)(nil)).Elem()
}
func (o AcyclicSOutput) ToAcyclicSOutput() AcyclicSOutput {
return o
}
func (o AcyclicSOutput) ToAcyclicSOutputWithContext(ctx context.Context) AcyclicSOutput {
return o
}
func (o AcyclicSOutput) Foo5() pulumi.StringOutput {
return o.ApplyT(func(v AcyclicS) string { return v.Foo5 }).(pulumi.StringOutput)
}
type AcyclicT struct {
Foo6 AcyclicS `pulumi:"foo6"`
}
// AcyclicTInput is an input type that accepts AcyclicTArgs and AcyclicTOutput values.
// You can construct a concrete instance of `AcyclicTInput` via:
//
// AcyclicTArgs{...}
type AcyclicTInput interface {
pulumi.Input
ToAcyclicTOutput() AcyclicTOutput
ToAcyclicTOutputWithContext(context.Context) AcyclicTOutput
}
type AcyclicTArgs struct {
Foo6 AcyclicSInput `pulumi:"foo6"`
}
func (AcyclicTArgs) ElementType() reflect.Type {
return reflect.TypeOf((*AcyclicT)(nil)).Elem()
}
func (i AcyclicTArgs) ToAcyclicTOutput() AcyclicTOutput {
return i.ToAcyclicTOutputWithContext(context.Background())
}
func (i AcyclicTArgs) ToAcyclicTOutputWithContext(ctx context.Context) AcyclicTOutput {
return pulumi.ToOutputWithContext(ctx, i).(AcyclicTOutput)
}
type AcyclicTOutput struct{ *pulumi.OutputState }
func (AcyclicTOutput) ElementType() reflect.Type {
return reflect.TypeOf((*AcyclicT)(nil)).Elem()
}
func (o AcyclicTOutput) ToAcyclicTOutput() AcyclicTOutput {
return o
}
func (o AcyclicTOutput) ToAcyclicTOutputWithContext(ctx context.Context) AcyclicTOutput {
return o
}
func (o AcyclicTOutput) Foo6() AcyclicSOutput {
return o.ApplyT(func(v AcyclicT) AcyclicS { return v.Foo6 }).(AcyclicSOutput)
}
type DirectCycle struct {
Foo *DirectCycle `pulumi:"foo"`
}
// DirectCycleInput is an input type that accepts DirectCycleArgs and DirectCycleOutput values.
// You can construct a concrete instance of `DirectCycleInput` via:
//
// DirectCycleArgs{...}
type DirectCycleInput interface {
pulumi.Input
ToDirectCycleOutput() DirectCycleOutput
ToDirectCycleOutputWithContext(context.Context) DirectCycleOutput
}
type DirectCycleArgs struct {
Foo DirectCyclePtrInput `pulumi:"foo"`
}
func (DirectCycleArgs) ElementType() reflect.Type {
return reflect.TypeOf((*DirectCycle)(nil)).Elem()
}
func (i DirectCycleArgs) ToDirectCycleOutput() DirectCycleOutput {
return i.ToDirectCycleOutputWithContext(context.Background())
}
func (i DirectCycleArgs) ToDirectCycleOutputWithContext(ctx context.Context) DirectCycleOutput {
return pulumi.ToOutputWithContext(ctx, i).(DirectCycleOutput)
}
func (i DirectCycleArgs) ToDirectCyclePtrOutput() DirectCyclePtrOutput {
return i.ToDirectCyclePtrOutputWithContext(context.Background())
}
func (i DirectCycleArgs) ToDirectCyclePtrOutputWithContext(ctx context.Context) DirectCyclePtrOutput {
return pulumi.ToOutputWithContext(ctx, i).(DirectCycleOutput).ToDirectCyclePtrOutputWithContext(ctx)
}
// DirectCyclePtrInput is an input type that accepts DirectCycleArgs, DirectCyclePtr and DirectCyclePtrOutput values.
// You can construct a concrete instance of `DirectCyclePtrInput` via:
//
// DirectCycleArgs{...}
//
// or:
//
// nil
type DirectCyclePtrInput interface {
pulumi.Input
ToDirectCyclePtrOutput() DirectCyclePtrOutput
ToDirectCyclePtrOutputWithContext(context.Context) DirectCyclePtrOutput
}
type directCyclePtrType DirectCycleArgs
func DirectCyclePtr(v *DirectCycleArgs) DirectCyclePtrInput {
return (*directCyclePtrType)(v)
}
func (*directCyclePtrType) ElementType() reflect.Type {
return reflect.TypeOf((**DirectCycle)(nil)).Elem()
}
func (i *directCyclePtrType) ToDirectCyclePtrOutput() DirectCyclePtrOutput {
return i.ToDirectCyclePtrOutputWithContext(context.Background())
}
func (i *directCyclePtrType) ToDirectCyclePtrOutputWithContext(ctx context.Context) DirectCyclePtrOutput {
return pulumi.ToOutputWithContext(ctx, i).(DirectCyclePtrOutput)
}
type DirectCycleOutput struct{ *pulumi.OutputState }
func (DirectCycleOutput) ElementType() reflect.Type {
return reflect.TypeOf((*DirectCycle)(nil)).Elem()
}
func (o DirectCycleOutput) ToDirectCycleOutput() DirectCycleOutput {
return o
}
func (o DirectCycleOutput) ToDirectCycleOutputWithContext(ctx context.Context) DirectCycleOutput {
return o
}
func (o DirectCycleOutput) ToDirectCyclePtrOutput() DirectCyclePtrOutput {
return o.ToDirectCyclePtrOutputWithContext(context.Background())
}
func (o DirectCycleOutput) ToDirectCyclePtrOutputWithContext(ctx context.Context) DirectCyclePtrOutput {
return o.ApplyTWithContext(ctx, func(_ context.Context, v DirectCycle) *DirectCycle {
return &v
}).(DirectCyclePtrOutput)
}
func (o DirectCycleOutput) Foo() DirectCyclePtrOutput {
return o.ApplyT(func(v DirectCycle) *DirectCycle { return v.Foo }).(DirectCyclePtrOutput)
}
type DirectCyclePtrOutput struct{ *pulumi.OutputState }
func (DirectCyclePtrOutput) ElementType() reflect.Type {
return reflect.TypeOf((**DirectCycle)(nil)).Elem()
}
func (o DirectCyclePtrOutput) ToDirectCyclePtrOutput() DirectCyclePtrOutput {
return o
}
func (o DirectCyclePtrOutput) ToDirectCyclePtrOutputWithContext(ctx context.Context) DirectCyclePtrOutput {
return o
}
func (o DirectCyclePtrOutput) Elem() DirectCycleOutput {
return o.ApplyT(func(v *DirectCycle) DirectCycle {
if v != nil {
return *v
}
var ret DirectCycle
return ret
}).(DirectCycleOutput)
}
func (o DirectCyclePtrOutput) Foo() DirectCyclePtrOutput {
return o.ApplyT(func(v *DirectCycle) *DirectCycle {
if v == nil {
return nil
}
return v.Foo
}).(DirectCyclePtrOutput)
}
type IndirectCycleS struct {
Foo2 *IndirectCycleT `pulumi:"foo2"`
}
// IndirectCycleSInput is an input type that accepts IndirectCycleSArgs and IndirectCycleSOutput values.
// You can construct a concrete instance of `IndirectCycleSInput` via:
//
// IndirectCycleSArgs{...}
type IndirectCycleSInput interface {
pulumi.Input
ToIndirectCycleSOutput() IndirectCycleSOutput
ToIndirectCycleSOutputWithContext(context.Context) IndirectCycleSOutput
}
type IndirectCycleSArgs struct {
Foo2 IndirectCycleTPtrInput `pulumi:"foo2"`
}
func (IndirectCycleSArgs) ElementType() reflect.Type {
return reflect.TypeOf((*IndirectCycleS)(nil)).Elem()
}
func (i IndirectCycleSArgs) ToIndirectCycleSOutput() IndirectCycleSOutput {
return i.ToIndirectCycleSOutputWithContext(context.Background())
}
func (i IndirectCycleSArgs) ToIndirectCycleSOutputWithContext(ctx context.Context) IndirectCycleSOutput {
return pulumi.ToOutputWithContext(ctx, i).(IndirectCycleSOutput)
}
func (i IndirectCycleSArgs) ToIndirectCycleSPtrOutput() IndirectCycleSPtrOutput {
return i.ToIndirectCycleSPtrOutputWithContext(context.Background())
}
func (i IndirectCycleSArgs) ToIndirectCycleSPtrOutputWithContext(ctx context.Context) IndirectCycleSPtrOutput {
return pulumi.ToOutputWithContext(ctx, i).(IndirectCycleSOutput).ToIndirectCycleSPtrOutputWithContext(ctx)
}
// IndirectCycleSPtrInput is an input type that accepts IndirectCycleSArgs, IndirectCycleSPtr and IndirectCycleSPtrOutput values.
// You can construct a concrete instance of `IndirectCycleSPtrInput` via:
//
// IndirectCycleSArgs{...}
//
// or:
//
// nil
type IndirectCycleSPtrInput interface {
pulumi.Input
ToIndirectCycleSPtrOutput() IndirectCycleSPtrOutput
ToIndirectCycleSPtrOutputWithContext(context.Context) IndirectCycleSPtrOutput
}
type indirectCycleSPtrType IndirectCycleSArgs
func IndirectCycleSPtr(v *IndirectCycleSArgs) IndirectCycleSPtrInput {
return (*indirectCycleSPtrType)(v)
}
func (*indirectCycleSPtrType) ElementType() reflect.Type {
return reflect.TypeOf((**IndirectCycleS)(nil)).Elem()
}
func (i *indirectCycleSPtrType) ToIndirectCycleSPtrOutput() IndirectCycleSPtrOutput {
return i.ToIndirectCycleSPtrOutputWithContext(context.Background())
}
func (i *indirectCycleSPtrType) ToIndirectCycleSPtrOutputWithContext(ctx context.Context) IndirectCycleSPtrOutput {
return pulumi.ToOutputWithContext(ctx, i).(IndirectCycleSPtrOutput)
}
type IndirectCycleSOutput struct{ *pulumi.OutputState }
func (IndirectCycleSOutput) ElementType() reflect.Type {
return reflect.TypeOf((*IndirectCycleS)(nil)).Elem()
}
func (o IndirectCycleSOutput) ToIndirectCycleSOutput() IndirectCycleSOutput {
return o
}
func (o IndirectCycleSOutput) ToIndirectCycleSOutputWithContext(ctx context.Context) IndirectCycleSOutput {
return o
}
func (o IndirectCycleSOutput) ToIndirectCycleSPtrOutput() IndirectCycleSPtrOutput {
return o.ToIndirectCycleSPtrOutputWithContext(context.Background())
}
func (o IndirectCycleSOutput) ToIndirectCycleSPtrOutputWithContext(ctx context.Context) IndirectCycleSPtrOutput {
return o.ApplyTWithContext(ctx, func(_ context.Context, v IndirectCycleS) *IndirectCycleS {
return &v
}).(IndirectCycleSPtrOutput)
}
func (o IndirectCycleSOutput) Foo2() IndirectCycleTPtrOutput {
return o.ApplyT(func(v IndirectCycleS) *IndirectCycleT { return v.Foo2 }).(IndirectCycleTPtrOutput)
}
type IndirectCycleSPtrOutput struct{ *pulumi.OutputState }
func (IndirectCycleSPtrOutput) ElementType() reflect.Type {
return reflect.TypeOf((**IndirectCycleS)(nil)).Elem()
}
func (o IndirectCycleSPtrOutput) ToIndirectCycleSPtrOutput() IndirectCycleSPtrOutput {
return o
}
func (o IndirectCycleSPtrOutput) ToIndirectCycleSPtrOutputWithContext(ctx context.Context) IndirectCycleSPtrOutput {
return o
}
func (o IndirectCycleSPtrOutput) Elem() IndirectCycleSOutput {
return o.ApplyT(func(v *IndirectCycleS) IndirectCycleS {
if v != nil {
return *v
}
var ret IndirectCycleS
return ret
}).(IndirectCycleSOutput)
}
func (o IndirectCycleSPtrOutput) Foo2() IndirectCycleTPtrOutput {
return o.ApplyT(func(v *IndirectCycleS) *IndirectCycleT {
if v == nil {
return nil
}
return v.Foo2
}).(IndirectCycleTPtrOutput)
}
type IndirectCycleT struct {
Foo3 *IndirectCycleS `pulumi:"foo3"`
}
// IndirectCycleTInput is an input type that accepts IndirectCycleTArgs and IndirectCycleTOutput values.
// You can construct a concrete instance of `IndirectCycleTInput` via:
//
// IndirectCycleTArgs{...}
type IndirectCycleTInput interface {
pulumi.Input
ToIndirectCycleTOutput() IndirectCycleTOutput
ToIndirectCycleTOutputWithContext(context.Context) IndirectCycleTOutput
}
type IndirectCycleTArgs struct {
Foo3 IndirectCycleSPtrInput `pulumi:"foo3"`
}
func (IndirectCycleTArgs) ElementType() reflect.Type {
return reflect.TypeOf((*IndirectCycleT)(nil)).Elem()
}
func (i IndirectCycleTArgs) ToIndirectCycleTOutput() IndirectCycleTOutput {
return i.ToIndirectCycleTOutputWithContext(context.Background())
}
func (i IndirectCycleTArgs) ToIndirectCycleTOutputWithContext(ctx context.Context) IndirectCycleTOutput {
return pulumi.ToOutputWithContext(ctx, i).(IndirectCycleTOutput)
}
func (i IndirectCycleTArgs) ToIndirectCycleTPtrOutput() IndirectCycleTPtrOutput {
return i.ToIndirectCycleTPtrOutputWithContext(context.Background())
}
func (i IndirectCycleTArgs) ToIndirectCycleTPtrOutputWithContext(ctx context.Context) IndirectCycleTPtrOutput {
return pulumi.ToOutputWithContext(ctx, i).(IndirectCycleTOutput).ToIndirectCycleTPtrOutputWithContext(ctx)
}
// IndirectCycleTPtrInput is an input type that accepts IndirectCycleTArgs, IndirectCycleTPtr and IndirectCycleTPtrOutput values.
// You can construct a concrete instance of `IndirectCycleTPtrInput` via:
//
// IndirectCycleTArgs{...}
//
// or:
//
// nil
type IndirectCycleTPtrInput interface {
pulumi.Input
ToIndirectCycleTPtrOutput() IndirectCycleTPtrOutput
ToIndirectCycleTPtrOutputWithContext(context.Context) IndirectCycleTPtrOutput
}
type indirectCycleTPtrType IndirectCycleTArgs
func IndirectCycleTPtr(v *IndirectCycleTArgs) IndirectCycleTPtrInput {
return (*indirectCycleTPtrType)(v)
}
func (*indirectCycleTPtrType) ElementType() reflect.Type {
return reflect.TypeOf((**IndirectCycleT)(nil)).Elem()
}
func (i *indirectCycleTPtrType) ToIndirectCycleTPtrOutput() IndirectCycleTPtrOutput {
return i.ToIndirectCycleTPtrOutputWithContext(context.Background())
}
func (i *indirectCycleTPtrType) ToIndirectCycleTPtrOutputWithContext(ctx context.Context) IndirectCycleTPtrOutput {
return pulumi.ToOutputWithContext(ctx, i).(IndirectCycleTPtrOutput)
}
type IndirectCycleTOutput struct{ *pulumi.OutputState }
func (IndirectCycleTOutput) ElementType() reflect.Type {
return reflect.TypeOf((*IndirectCycleT)(nil)).Elem()
}
func (o IndirectCycleTOutput) ToIndirectCycleTOutput() IndirectCycleTOutput {
return o
}
func (o IndirectCycleTOutput) ToIndirectCycleTOutputWithContext(ctx context.Context) IndirectCycleTOutput {
return o
}
func (o IndirectCycleTOutput) ToIndirectCycleTPtrOutput() IndirectCycleTPtrOutput {
return o.ToIndirectCycleTPtrOutputWithContext(context.Background())
}
func (o IndirectCycleTOutput) ToIndirectCycleTPtrOutputWithContext(ctx context.Context) IndirectCycleTPtrOutput {
return o.ApplyTWithContext(ctx, func(_ context.Context, v IndirectCycleT) *IndirectCycleT {
return &v
}).(IndirectCycleTPtrOutput)
}
func (o IndirectCycleTOutput) Foo3() IndirectCycleSPtrOutput {
return o.ApplyT(func(v IndirectCycleT) *IndirectCycleS { return v.Foo3 }).(IndirectCycleSPtrOutput)
}
type IndirectCycleTPtrOutput struct{ *pulumi.OutputState }
func (IndirectCycleTPtrOutput) ElementType() reflect.Type {
return reflect.TypeOf((**IndirectCycleT)(nil)).Elem()
}
func (o IndirectCycleTPtrOutput) ToIndirectCycleTPtrOutput() IndirectCycleTPtrOutput {
return o
}
func (o IndirectCycleTPtrOutput) ToIndirectCycleTPtrOutputWithContext(ctx context.Context) IndirectCycleTPtrOutput {
return o
}
func (o IndirectCycleTPtrOutput) Elem() IndirectCycleTOutput {
return o.ApplyT(func(v *IndirectCycleT) IndirectCycleT {
if v != nil {
return *v
}
var ret IndirectCycleT
return ret
}).(IndirectCycleTOutput)
}
func (o IndirectCycleTPtrOutput) Foo3() IndirectCycleSPtrOutput {
return o.ApplyT(func(v *IndirectCycleT) *IndirectCycleS {
if v == nil {
return nil
}
return v.Foo3
}).(IndirectCycleSPtrOutput)
}
func init() {
pulumi.RegisterOutputType(AcyclicReferentOutput{})
pulumi.RegisterOutputType(AcyclicSOutput{})
pulumi.RegisterOutputType(AcyclicTOutput{})
pulumi.RegisterOutputType(DirectCycleOutput{})
pulumi.RegisterOutputType(DirectCyclePtrOutput{})
pulumi.RegisterOutputType(IndirectCycleSOutput{})
pulumi.RegisterOutputType(IndirectCycleSPtrOutput{})
pulumi.RegisterOutputType(IndirectCycleTOutput{})
pulumi.RegisterOutputType(IndirectCycleTPtrOutput{})
}

View file

@ -0,0 +1,77 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
package example
import (
"fmt"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"github.com/blang/semver"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
type envParser func(v string) interface{}
func parseEnvBool(v string) interface{} {
b, err := strconv.ParseBool(v)
if err != nil {
return nil
}
return b
}
func parseEnvInt(v string) interface{} {
i, err := strconv.ParseInt(v, 0, 0)
if err != nil {
return nil
}
return int(i)
}
func parseEnvFloat(v string) interface{} {
f, err := strconv.ParseFloat(v, 64)
if err != nil {
return nil
}
return f
}
func parseEnvStringArray(v string) interface{} {
var result pulumi.StringArray
for _, item := range strings.Split(v, ";") {
result = append(result, pulumi.String(item))
}
return result
}
func getEnvOrDefault(def interface{}, parser envParser, vars ...string) interface{} {
for _, v := range vars {
if value := os.Getenv(v); value != "" {
if parser != nil {
return parser(value)
}
return value
}
}
return def
}
// PkgVersion uses reflection to determine the version of the current package.
func PkgVersion() (semver.Version, error) {
type sentinal struct{}
pkgPath := reflect.TypeOf(sentinal{}).PkgPath()
re := regexp.MustCompile("^.*/pulumi-example/sdk(/v\\d+)?")
if match := re.FindStringSubmatch(pkgPath); match != nil {
vStr := match[1]
if len(vStr) == 0 { // If the version capture group was empty, default to v1.
return semver.Version{Major: 1}, nil
}
return semver.MustParse(fmt.Sprintf("%s.0.0", vStr[2:])), nil
}
return semver.Version{}, fmt.Errorf("failed to determine the package version from %s", pkgPath)
}

View file

@ -0,0 +1,13 @@
{
"emittedFiles": [
"README.md",
"index.ts",
"package.json",
"provider.ts",
"tsconfig.json",
"types/index.ts",
"types/input.ts",
"types/output.ts",
"utilities.ts"
]
}

View file

@ -0,0 +1,27 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
import * as pulumi from "@pulumi/pulumi";
import * as utilities from "./utilities";
// Export members:
export * from "./provider";
// Export sub-modules:
import * as types from "./types";
export {
types,
};
import { Provider } from "./provider";
pulumi.runtime.registerResourcePackage("example", {
version: utilities.getVersion(),
constructProvider: (name: string, type: string, urn: string): pulumi.ProviderResource => {
if (type !== "pulumi:providers:example") {
throw new Error(`unknown provider type ${type}`);
}
return new Provider(name, <any>undefined, { urn });
},
});

View file

@ -0,0 +1,16 @@
{
"name": "@pulumi/example",
"version": "${VERSION}",
"scripts": {
"build": "tsc"
},
"dependencies": {
"@pulumi/pulumi": "^3.12"
},
"devDependencies": {
"typescript": "^3.7.0"
},
"pulumi": {
"resource": true
}
}

View file

@ -0,0 +1,46 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
import * as pulumi from "@pulumi/pulumi";
import * as utilities from "./utilities";
export class Provider extends pulumi.ProviderResource {
/** @internal */
public static readonly __pulumiType = 'example';
/**
* Returns true if the given object is an instance of Provider. This is designed to work even
* when multiple copies of the Pulumi SDK have been loaded into the same process.
*/
public static isInstance(obj: any): obj is Provider {
if (obj === undefined || obj === null) {
return false;
}
return obj['__pulumiType'] === Provider.__pulumiType;
}
/**
* Create a Provider resource with the given unique name, arguments, and options.
*
* @param name The _unique_ name of the resource.
* @param args The arguments to use to populate this resource's properties.
* @param opts A bag of options that control this resource's behavior.
*/
constructor(name: string, args?: ProviderArgs, opts?: pulumi.ResourceOptions) {
let inputs: pulumi.Inputs = {};
opts = opts || {};
{
}
if (!opts.version) {
opts = pulumi.mergeOptions(opts, { version: utilities.getVersion()});
}
super(Provider.__pulumiType, name, inputs, opts);
}
}
/**
* The set of arguments for constructing a Provider resource.
*/
export interface ProviderArgs {
}

View file

@ -0,0 +1,23 @@
{
"compilerOptions": {
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"stripInternal": true,
"experimentalDecorators": true,
"noFallthroughCasesInSwitch": true,
"forceConsistentCasingInFileNames": true,
"strict": true
},
"files": [
"index.ts",
"provider.ts",
"types/index.ts",
"types/input.ts",
"types/output.ts",
"utilities.ts"
]
}

View file

@ -0,0 +1,11 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
// Export sub-modules:
import * as input from "./input";
import * as output from "./output";
export {
input,
output,
};

View file

@ -0,0 +1,6 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
import * as pulumi from "@pulumi/pulumi";
import { input as inputs, output as outputs } from "../types";

View file

@ -0,0 +1,6 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
import * as pulumi from "@pulumi/pulumi";
import { input as inputs, output as outputs } from "../types";

View file

@ -0,0 +1,49 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
export function getEnv(...vars: string[]): string | undefined {
for (const v of vars) {
const value = process.env[v];
if (value) {
return value;
}
}
return undefined;
}
export function getEnvBoolean(...vars: string[]): boolean | undefined {
const s = getEnv(...vars);
if (s !== undefined) {
// NOTE: these values are taken from https://golang.org/src/strconv/atob.go?s=351:391#L1, which is what
// Terraform uses internally when parsing boolean values.
if (["1", "t", "T", "true", "TRUE", "True"].find(v => v === s) !== undefined) {
return true;
}
if (["0", "f", "F", "false", "FALSE", "False"].find(v => v === s) !== undefined) {
return false;
}
}
return undefined;
}
export function getEnvNumber(...vars: string[]): number | undefined {
const s = getEnv(...vars);
if (s !== undefined) {
const f = parseFloat(s);
if (!isNaN(f)) {
return f;
}
}
return undefined;
}
export function getVersion(): string {
let version = require('./package.json').version;
// Node allows for the version to be prefixed by a "v", while semver doesn't.
// If there is a v, strip it off.
if (version.indexOf('v') === 0) {
version = version.slice(1);
}
return version;
}

View file

@ -0,0 +1,10 @@
{
"emittedFiles": [
"pulumi_example/README.md",
"pulumi_example/__init__.py",
"pulumi_example/_utilities.py",
"pulumi_example/provider.py",
"pulumi_example/py.typed",
"setup.py"
]
}

View file

@ -0,0 +1,23 @@
# coding=utf-8
# *** WARNING: this file was generated by test. ***
# *** Do not edit by hand unless you're certain you know what you are doing! ***
from . import _utilities
import typing
# Export this package's modules as members:
from .provider import *
_utilities.register(
resource_modules="""
[]
""",
resource_packages="""
[
{
"pkg": "example",
"token": "pulumi:providers:example",
"fqn": "pulumi_example",
"class": "Provider"
}
]
"""
)

View file

@ -0,0 +1,235 @@
# coding=utf-8
# *** WARNING: this file was generated by test. ***
# *** Do not edit by hand unless you're certain you know what you are doing! ***
import importlib.util
import inspect
import json
import os
import pkg_resources
import sys
import typing
import pulumi
import pulumi.runtime
from semver import VersionInfo as SemverVersion
from parver import Version as PEP440Version
def get_env(*args):
for v in args:
value = os.getenv(v)
if value is not None:
return value
return None
def get_env_bool(*args):
str = get_env(*args)
if str is not None:
# NOTE: these values are taken from https://golang.org/src/strconv/atob.go?s=351:391#L1, which is what
# Terraform uses internally when parsing boolean values.
if str in ["1", "t", "T", "true", "TRUE", "True"]:
return True
if str in ["0", "f", "F", "false", "FALSE", "False"]:
return False
return None
def get_env_int(*args):
str = get_env(*args)
if str is not None:
try:
return int(str)
except:
return None
return None
def get_env_float(*args):
str = get_env(*args)
if str is not None:
try:
return float(str)
except:
return None
return None
def _get_semver_version():
# __name__ is set to the fully-qualified name of the current module, In our case, it will be
# <some module>._utilities. <some module> is the module we want to query the version for.
root_package, *rest = __name__.split('.')
# pkg_resources uses setuptools to inspect the set of installed packages. We use it here to ask
# for the currently installed version of the root package (i.e. us) and get its version.
# Unfortunately, PEP440 and semver differ slightly in incompatible ways. The Pulumi engine expects
# to receive a valid semver string when receiving requests from the language host, so it's our
# responsibility as the library to convert our own PEP440 version into a valid semver string.
pep440_version_string = pkg_resources.require(root_package)[0].version
pep440_version = PEP440Version.parse(pep440_version_string)
(major, minor, patch) = pep440_version.release
prerelease = None
if pep440_version.pre_tag == 'a':
prerelease = f"alpha.{pep440_version.pre}"
elif pep440_version.pre_tag == 'b':
prerelease = f"beta.{pep440_version.pre}"
elif pep440_version.pre_tag == 'rc':
prerelease = f"rc.{pep440_version.pre}"
elif pep440_version.dev is not None:
prerelease = f"dev.{pep440_version.dev}"
# The only significant difference between PEP440 and semver as it pertains to us is that PEP440 has explicit support
# for dev builds, while semver encodes them as "prerelease" versions. In order to bridge between the two, we convert
# our dev build version into a prerelease tag. This matches what all of our other packages do when constructing
# their own semver string.
return SemverVersion(major=major, minor=minor, patch=patch, prerelease=prerelease)
# Determine the version once and cache the value, which measurably improves program performance.
_version = _get_semver_version()
_version_str = str(_version)
def get_version():
return _version_str
def get_resource_args_opts(resource_args_type, resource_options_type, *args, **kwargs):
"""
Return the resource args and options given the *args and **kwargs of a resource's
__init__ method.
"""
resource_args, opts = None, None
# If the first item is the resource args type, save it and remove it from the args list.
if args and isinstance(args[0], resource_args_type):
resource_args, args = args[0], args[1:]
# Now look at the first item in the args list again.
# If the first item is the resource options class, save it.
if args and isinstance(args[0], resource_options_type):
opts = args[0]
# If resource_args is None, see if "args" is in kwargs, and, if so, if it's typed as the
# the resource args type.
if resource_args is None:
a = kwargs.get("args")
if isinstance(a, resource_args_type):
resource_args = a
# If opts is None, look it up in kwargs.
if opts is None:
opts = kwargs.get("opts")
return resource_args, opts
# Temporary: just use pulumi._utils.lazy_import once everyone upgrades.
def lazy_import(fullname):
import pulumi._utils as u
f = getattr(u, 'lazy_import', None)
if f is None:
f = _lazy_import_temp
return f(fullname)
# Copied from pulumi._utils.lazy_import, see comments there.
def _lazy_import_temp(fullname):
m = sys.modules.get(fullname, None)
if m is not None:
return m
spec = importlib.util.find_spec(fullname)
m = sys.modules.get(fullname, None)
if m is not None:
return m
loader = importlib.util.LazyLoader(spec.loader)
spec.loader = loader
module = importlib.util.module_from_spec(spec)
m = sys.modules.get(fullname, None)
if m is not None:
return m
sys.modules[fullname] = module
loader.exec_module(module)
return module
class Package(pulumi.runtime.ResourcePackage):
def __init__(self, pkg_info):
super().__init__()
self.pkg_info = pkg_info
def version(self):
return _version
def construct_provider(self, name: str, typ: str, urn: str) -> pulumi.ProviderResource:
if typ != self.pkg_info['token']:
raise Exception(f"unknown provider type {typ}")
Provider = getattr(lazy_import(self.pkg_info['fqn']), self.pkg_info['class'])
return Provider(name, pulumi.ResourceOptions(urn=urn))
class Module(pulumi.runtime.ResourceModule):
def __init__(self, mod_info):
super().__init__()
self.mod_info = mod_info
def version(self):
return _version
def construct(self, name: str, typ: str, urn: str) -> pulumi.Resource:
class_name = self.mod_info['classes'].get(typ, None)
if class_name is None:
raise Exception(f"unknown resource type {typ}")
TheClass = getattr(lazy_import(self.mod_info['fqn']), class_name)
return TheClass(name, pulumi.ResourceOptions(urn=urn))
def register(resource_modules, resource_packages):
resource_modules = json.loads(resource_modules)
resource_packages = json.loads(resource_packages)
for pkg_info in resource_packages:
pulumi.runtime.register_resource_package(pkg_info['pkg'], Package(pkg_info))
for mod_info in resource_modules:
pulumi.runtime.register_resource_module(
mod_info['pkg'],
mod_info['mod'],
Module(mod_info))
_F = typing.TypeVar('_F', bound=typing.Callable[..., typing.Any])
def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
"""Decorator internally used on {fn}_output lifted function versions
to implement them automatically from the un-lifted function."""
func_sig = inspect.signature(func)
def lifted_func(*args, opts=None, **kwargs):
bound_args = func_sig.bind(*args, **kwargs)
return pulumi.Output.from_input({
'args': bound_args.args,
'kwargs': bound_args.kwargs
}).apply(lambda resolved_args: func(*resolved_args['args'],
opts=opts,
**resolved_args['kwargs']))
return (lambda _: lifted_func)

View file

@ -0,0 +1,73 @@
# coding=utf-8
# *** WARNING: this file was generated by test. ***
# *** Do not edit by hand unless you're certain you know what you are doing! ***
import warnings
import pulumi
import pulumi.runtime
from typing import Any, Mapping, Optional, Sequence, Union, overload
from . import _utilities
__all__ = ['ProviderArgs', 'Provider']
@pulumi.input_type
class ProviderArgs:
def __init__(__self__):
"""
The set of arguments for constructing a Provider resource.
"""
pass
class Provider(pulumi.ProviderResource):
@overload
def __init__(__self__,
resource_name: str,
opts: Optional[pulumi.ResourceOptions] = None,
__props__=None):
"""
Create a Example resource with the given unique name, props, and options.
:param str resource_name: The name of the resource.
:param pulumi.ResourceOptions opts: Options for the resource.
"""
...
@overload
def __init__(__self__,
resource_name: str,
args: Optional[ProviderArgs] = None,
opts: Optional[pulumi.ResourceOptions] = None):
"""
Create a Example resource with the given unique name, props, and options.
:param str resource_name: The name of the resource.
:param ProviderArgs args: The arguments to use to populate this resource's properties.
:param pulumi.ResourceOptions opts: Options for the resource.
"""
...
def __init__(__self__, resource_name: str, *args, **kwargs):
resource_args, opts = _utilities.get_resource_args_opts(ProviderArgs, pulumi.ResourceOptions, *args, **kwargs)
if resource_args is not None:
__self__._internal_init(resource_name, opts, **resource_args.__dict__)
else:
__self__._internal_init(resource_name, *args, **kwargs)
def _internal_init(__self__,
resource_name: str,
opts: Optional[pulumi.ResourceOptions] = None,
__props__=None):
if opts is None:
opts = pulumi.ResourceOptions()
if not isinstance(opts, pulumi.ResourceOptions):
raise TypeError('Expected resource options to be a ResourceOptions instance')
if opts.version is None:
opts.version = _utilities.get_version()
if opts.id is None:
if __props__ is not None:
raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource')
__props__ = ProviderArgs.__new__(ProviderArgs)
super(Provider, __self__).__init__(
'example',
resource_name,
__props__,
opts)

View file

@ -0,0 +1,58 @@
# coding=utf-8
# *** WARNING: this file was generated by test. ***
# *** Do not edit by hand unless you're certain you know what you are doing! ***
import errno
from setuptools import setup, find_packages
from setuptools.command.install import install
from subprocess import check_call
VERSION = "0.0.0"
PLUGIN_VERSION = "0.0.0"
class InstallPluginCommand(install):
def run(self):
install.run(self)
try:
check_call(['pulumi', 'plugin', 'install', 'resource', 'example', PLUGIN_VERSION])
except OSError as error:
if error.errno == errno.ENOENT:
print(f"""
There was an error installing the example resource provider plugin.
It looks like `pulumi` is not installed on your system.
Please visit https://pulumi.com/ to install the Pulumi CLI.
You may try manually installing the plugin by running
`pulumi plugin install resource example {PLUGIN_VERSION}`
""")
else:
raise
def readme():
try:
with open('README.md', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
return "example Pulumi Package - Development Version"
setup(name='pulumi_example',
version=VERSION,
long_description=readme(),
long_description_content_type='text/markdown',
cmdclass={
'install': InstallPluginCommand,
},
packages=find_packages(),
package_data={
'pulumi_example': [
'py.typed',
]
},
install_requires=[
'parver>=0.2.1',
'pulumi',
'semver>=2.8.1'
],
zip_safe=False)

View file

@ -0,0 +1,55 @@
version: "0.0.1"
name: example
types:
example::DirectCycle:
type: object
properties:
foo:
$ref: "#/types/example::DirectCycle"
required: [ foo ]
example::IndirectCycleS:
type: object
properties:
foo2:
$ref: "#/types/example::IndirectCycleT"
required: [ foo2 ]
example::IndirectCycleT:
type: object
properties:
foo3:
$ref: "#/types/example::IndirectCycleS"
required: [ foo3 ]
example::AcyclicReferent:
type: object
properties:
foo4:
$ref: "#/types/example::DirectCycle"
bar:
$ref: "#/types/example::IndirectCycleS"
baz:
$ref: "#/types/example::IndirectCycleT"
required: [ foo4, bar, baz ]
example::AcyclicS:
type: object
properties:
foo5:
type: string
required: [ foo5 ]
example::AcyclicT:
type: object
properties:
foo6:
$ref: "#/types/example::AcyclicS"
required: [ foo6 ]
language:
csharp: { "packageReferences": { "Pulumi": "3.12" } }
go:
{
"importBasePath": "github.com/pulumi/pulumi/pkg/v3/codegen/internal/test/testdata/cyclic-types/go/example",
}
nodejs:
{
"dependencies": { "@pulumi/pulumi": "^3.12" },
"devDependencies": { "typescript": "^3.7.0" },
}
python: {}

View file

@ -56,13 +56,15 @@ func TestRelPathToRelImport(t *testing.T) {
}
func TestGeneratePackage(t *testing.T) {
// To speed up these tests, we will generate one common
// virtual environment for all of them to run in, rather than
// having one per test.
err := buildVirtualEnv()
if err != nil {
t.Error(err)
return
if !test.NoSDKCodegenChecks() {
// To speed up these tests, we will generate one common
// virtual environment for all of them to run in, rather than
// having one per test.
err := buildVirtualEnv()
if err != nil {
t.Error(err)
return
}
}
test.TestSDKCodegen(t, &test.SDKCodegenOptions{

View file

@ -88,6 +88,10 @@ func (s Set) Add(v interface{}) {
s[v] = struct{}{}
}
func (s Set) Delete(v interface{}) {
delete(s, v)
}
func (s Set) Has(v interface{}) bool {
_, ok := s[v]
return ok