[codegen/nodejs] - Fix provider enum with env var (#8051)

* Add failing test

* Fix

* PR feedback
This commit is contained in:
Komal 2021-09-24 15:02:56 -07:00 committed by GitHub
parent e14f74fbe7
commit 74dfa83de5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 441 additions and 13 deletions

View file

@ -14,8 +14,11 @@
- [codegen/nodejs] Correctly determine imports for functions.
[#8038](https://github.com/pulumi/pulumi/pull/8038)
- [codegen/go] - Fix resolution of enum naming collisions
- [codegen/go] - Fix resolution of enum naming collisions.
[#7985](https://github.com/pulumi/pulumi/pull/7985)
- [sdk/{nodejs,python}] - Fix errors when testing remote components with mocks.
[#8053](https://github.com/pulumi/pulumi/pull/8053)
- [codegen/nodejs] - Fix generation of provider enum with environment variables.
[#8051](https://github.com/pulumi/pulumi/pull/8051)

View file

@ -24,7 +24,8 @@ meta_desc: "Documentation for the configstation.Provider resource with examples,
{{% 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="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="nx">favorite_color</span><span class="p">:</span> <span class="nx">Optional[Union[str, Color]]</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>
@ -152,19 +153,51 @@ The Provider resource accepts the following [input]({{< relref "/docs/intro/conc
{{% choosable language csharp %}}
<dl class="resources-properties"></dl>
<dl class="resources-properties"><dt class="property-optional"
title="Optional">
<span id="favoritecolor_csharp">
<a href="#favoritecolor_csharp" style="color: inherit; text-decoration: inherit;">Favorite<wbr>Color</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">string | <a href="#color">Pulumi.<wbr>Configstation.<wbr>Color</a></span>
</dt>
<dd>{{% md %}}this is a relaxed string enum which can also be set via env var It can also be sourced from the following environment variable: `FAVE_COLOR`{{% /md %}}</dd></dl>
{{% /choosable %}}
{{% choosable language go %}}
<dl class="resources-properties"></dl>
<dl class="resources-properties"><dt class="property-optional"
title="Optional">
<span id="favoritecolor_go">
<a href="#favoritecolor_go" style="color: inherit; text-decoration: inherit;">Favorite<wbr>Color</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">string | <a href="#color">Color</a></span>
</dt>
<dd>{{% md %}}this is a relaxed string enum which can also be set via env var It can also be sourced from the following environment variable: `FAVE_COLOR`{{% /md %}}</dd></dl>
{{% /choosable %}}
{{% choosable language nodejs %}}
<dl class="resources-properties"></dl>
<dl class="resources-properties"><dt class="property-optional"
title="Optional">
<span id="favoritecolor_nodejs">
<a href="#favoritecolor_nodejs" style="color: inherit; text-decoration: inherit;">favorite<wbr>Color</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">string | <a href="#color">Color</a></span>
</dt>
<dd>{{% md %}}this is a relaxed string enum which can also be set via env var It can also be sourced from the following environment variable: `FAVE_COLOR`{{% /md %}}</dd></dl>
{{% /choosable %}}
{{% choosable language python %}}
<dl class="resources-properties"></dl>
<dl class="resources-properties"><dt class="property-optional"
title="Optional">
<span id="favorite_color_python">
<a href="#favorite_color_python" style="color: inherit; text-decoration: inherit;">favorite_<wbr>color</a>
</span>
<span class="property-indicator"></span>
<span class="property-type">str | <a href="#color">Color</a></span>
</dt>
<dd>{{% md %}}this is a relaxed string enum which can also be set via env var It can also be sourced from the following environment variable: `FAVE_COLOR`{{% /md %}}</dd></dl>
{{% /choosable %}}
@ -228,6 +261,36 @@ All [input](#inputs) properties are implicitly available as output properties. A
## Supporting Types
<h4 id="color">Color</h4>
{{% choosable language csharp %}}
<dl class="tabular"><dt>Blue</dt>
<dd>blue</dd><dt>Red</dt>
<dd>red</dd></dl>
{{% /choosable %}}
{{% choosable language go %}}
<dl class="tabular"><dt>Color<wbr>Blue</dt>
<dd>blue</dd><dt>Color<wbr>Red</dt>
<dd>red</dd></dl>
{{% /choosable %}}
{{% choosable language nodejs %}}
<dl class="tabular"><dt>Blue</dt>
<dd>blue</dd><dt>Red</dt>
<dd>red</dd></dl>
{{% /choosable %}}
{{% choosable language python %}}
<dl class="tabular"><dt>BLUE</dt>
<dd>blue</dd><dt>RED</dt>
<dd>red</dd></dl>
{{% /choosable %}}
<h2 id="package-details">Package Details</h2>
<dl class="package-details">

View file

@ -0,0 +1,37 @@
// *** 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.ComponentModel;
using Pulumi;
namespace Pulumi.Configstation
{
[EnumType]
public readonly struct Color : IEquatable<Color>
{
private readonly string _value;
private Color(string value)
{
_value = value ?? throw new ArgumentNullException(nameof(value));
}
public static Color Blue { get; } = new Color("blue");
public static Color Red { get; } = new Color("red");
public static bool operator ==(Color left, Color right) => left.Equals(right);
public static bool operator !=(Color left, Color right) => !left.Equals(right);
public static explicit operator string(Color value) => value._value;
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object? obj) => obj is Color other && Equals(other);
public bool Equals(Color other) => string.Equals(_value, other._value, StringComparison.Ordinal);
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => _value?.GetHashCode() ?? 0;
public override string ToString() => _value;
}
}

View file

@ -39,8 +39,15 @@ namespace Pulumi.Configstation
public sealed class ProviderArgs : Pulumi.ResourceArgs
{
/// <summary>
/// this is a relaxed string enum which can also be set via env var
/// </summary>
[Input("favoriteColor", json: true)]
public InputUnion<string, Pulumi.Configstation.Color>? FavoriteColor { get; set; }
public ProviderArgs()
{
FavoriteColor = Utilities.GetEnv("FAVE_COLOR");
}
}
}

View file

@ -2,6 +2,7 @@
"emittedFiles": [
"Config/Config.cs",
"Config/README.md",
"Enums.cs",
"Outputs/Child.cs",
"Provider.cs",
"Pulumi.Configstation.csproj",

View file

@ -6,6 +6,7 @@
"configstation/doc.go",
"configstation/init.go",
"configstation/provider.go",
"configstation/pulumiEnums.go",
"configstation/pulumiTypes.go",
"configstation/pulumiUtilities.go"
]

View file

@ -21,6 +21,9 @@ func NewProvider(ctx *pulumi.Context,
args = &ProviderArgs{}
}
if args.FavoriteColor == nil {
args.FavoriteColor = pulumi.StringPtr(getEnvOrDefault("", nil, "FAVE_COLOR").(string))
}
var resource Provider
err := ctx.RegisterResource("pulumi:providers:configstation", name, args, &resource, opts...)
if err != nil {
@ -30,10 +33,14 @@ func NewProvider(ctx *pulumi.Context,
}
type providerArgs struct {
// this is a relaxed string enum which can also be set via env var
FavoriteColor *string `pulumi:"favoriteColor"`
}
// The set of arguments for constructing a Provider resource.
type ProviderArgs struct {
// this is a relaxed string enum which can also be set via env var
FavoriteColor pulumi.StringPtrInput
}
func (ProviderArgs) ElementType() reflect.Type {

View file

@ -0,0 +1,180 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
package configstation
import (
"context"
"reflect"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
type Color string
const (
ColorBlue = Color("blue")
ColorRed = Color("red")
)
func (Color) ElementType() reflect.Type {
return reflect.TypeOf((*Color)(nil)).Elem()
}
func (e Color) ToColorOutput() ColorOutput {
return pulumi.ToOutput(e).(ColorOutput)
}
func (e Color) ToColorOutputWithContext(ctx context.Context) ColorOutput {
return pulumi.ToOutputWithContext(ctx, e).(ColorOutput)
}
func (e Color) ToColorPtrOutput() ColorPtrOutput {
return e.ToColorPtrOutputWithContext(context.Background())
}
func (e Color) ToColorPtrOutputWithContext(ctx context.Context) ColorPtrOutput {
return Color(e).ToColorOutputWithContext(ctx).ToColorPtrOutputWithContext(ctx)
}
func (e Color) ToStringOutput() pulumi.StringOutput {
return pulumi.ToOutput(pulumi.String(e)).(pulumi.StringOutput)
}
func (e Color) ToStringOutputWithContext(ctx context.Context) pulumi.StringOutput {
return pulumi.ToOutputWithContext(ctx, pulumi.String(e)).(pulumi.StringOutput)
}
func (e Color) ToStringPtrOutput() pulumi.StringPtrOutput {
return pulumi.String(e).ToStringPtrOutputWithContext(context.Background())
}
func (e Color) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput {
return pulumi.String(e).ToStringOutputWithContext(ctx).ToStringPtrOutputWithContext(ctx)
}
type ColorOutput struct{ *pulumi.OutputState }
func (ColorOutput) ElementType() reflect.Type {
return reflect.TypeOf((*Color)(nil)).Elem()
}
func (o ColorOutput) ToColorOutput() ColorOutput {
return o
}
func (o ColorOutput) ToColorOutputWithContext(ctx context.Context) ColorOutput {
return o
}
func (o ColorOutput) ToColorPtrOutput() ColorPtrOutput {
return o.ToColorPtrOutputWithContext(context.Background())
}
func (o ColorOutput) ToColorPtrOutputWithContext(ctx context.Context) ColorPtrOutput {
return o.ApplyTWithContext(ctx, func(_ context.Context, v Color) *Color {
return &v
}).(ColorPtrOutput)
}
func (o ColorOutput) ToStringOutput() pulumi.StringOutput {
return o.ToStringOutputWithContext(context.Background())
}
func (o ColorOutput) ToStringOutputWithContext(ctx context.Context) pulumi.StringOutput {
return o.ApplyTWithContext(ctx, func(_ context.Context, e Color) string {
return string(e)
}).(pulumi.StringOutput)
}
func (o ColorOutput) ToStringPtrOutput() pulumi.StringPtrOutput {
return o.ToStringPtrOutputWithContext(context.Background())
}
func (o ColorOutput) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput {
return o.ApplyTWithContext(ctx, func(_ context.Context, e Color) *string {
v := string(e)
return &v
}).(pulumi.StringPtrOutput)
}
type ColorPtrOutput struct{ *pulumi.OutputState }
func (ColorPtrOutput) ElementType() reflect.Type {
return reflect.TypeOf((**Color)(nil)).Elem()
}
func (o ColorPtrOutput) ToColorPtrOutput() ColorPtrOutput {
return o
}
func (o ColorPtrOutput) ToColorPtrOutputWithContext(ctx context.Context) ColorPtrOutput {
return o
}
func (o ColorPtrOutput) Elem() ColorOutput {
return o.ApplyT(func(v *Color) Color {
if v != nil {
return *v
}
var ret Color
return ret
}).(ColorOutput)
}
func (o ColorPtrOutput) ToStringPtrOutput() pulumi.StringPtrOutput {
return o.ToStringPtrOutputWithContext(context.Background())
}
func (o ColorPtrOutput) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput {
return o.ApplyTWithContext(ctx, func(_ context.Context, e *Color) *string {
if e == nil {
return nil
}
v := string(*e)
return &v
}).(pulumi.StringPtrOutput)
}
// ColorInput is an input type that accepts ColorArgs and ColorOutput values.
// You can construct a concrete instance of `ColorInput` via:
//
// ColorArgs{...}
type ColorInput interface {
pulumi.Input
ToColorOutput() ColorOutput
ToColorOutputWithContext(context.Context) ColorOutput
}
var colorPtrType = reflect.TypeOf((**Color)(nil)).Elem()
type ColorPtrInput interface {
pulumi.Input
ToColorPtrOutput() ColorPtrOutput
ToColorPtrOutputWithContext(context.Context) ColorPtrOutput
}
type colorPtr string
func ColorPtr(v string) ColorPtrInput {
return (*colorPtr)(&v)
}
func (*colorPtr) ElementType() reflect.Type {
return colorPtrType
}
func (in *colorPtr) ToColorPtrOutput() ColorPtrOutput {
return pulumi.ToOutput(in).(ColorPtrOutput)
}
func (in *colorPtr) ToColorPtrOutputWithContext(ctx context.Context) ColorPtrOutput {
return pulumi.ToOutputWithContext(ctx, in).(ColorPtrOutput)
}
func init() {
pulumi.RegisterOutputType(ColorOutput{})
pulumi.RegisterOutputType(ColorPtrOutput{})
}

View file

@ -7,6 +7,7 @@
"package.json",
"provider.ts",
"tsconfig.json",
"types/enums/index.ts",
"types/index.ts",
"types/input.ts",
"types/output.ts",

View file

@ -2,7 +2,7 @@
// *** 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";
import { input as inputs, output as outputs, enums } from "../types";
import * as utilities from "../utilities";
declare var exports: any;

View file

@ -7,6 +7,9 @@ import * as utilities from "./utilities";
// Export members:
export * from "./provider";
// Export enums:
export * from "./types/enums";
// Export sub-modules:
import * as config from "./config";
import * as types from "./types";

View file

@ -2,6 +2,7 @@
// *** 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, enums } from "./types";
import * as utilities from "./utilities";
export class Provider extends pulumi.ProviderResource {
@ -31,6 +32,7 @@ export class Provider extends pulumi.ProviderResource {
let inputs: pulumi.Inputs = {};
opts = opts || {};
{
inputs["favoriteColor"] = (args ? args.favoriteColor : undefined) ?? <any>utilities.getEnv("FAVE_COLOR");
}
if (!opts.version) {
opts = pulumi.mergeOptions(opts, { version: utilities.getVersion()});
@ -43,4 +45,8 @@ export class Provider extends pulumi.ProviderResource {
* The set of arguments for constructing a Provider resource.
*/
export interface ProviderArgs {
/**
* this is a relaxed string enum which can also be set via env var
*/
favoriteColor?: pulumi.Input<string | enums.Color>;
}

View file

@ -17,6 +17,7 @@
"config/vars.ts",
"index.ts",
"provider.ts",
"types/enums/index.ts",
"types/index.ts",
"types/input.ts",
"types/output.ts",

View file

@ -0,0 +1,10 @@
// *** WARNING: this file was generated by test. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***
export const Color = {
Blue: "blue",
Red: "red",
} as const;
export type Color = (typeof Color)[keyof typeof Color];

View file

@ -2,10 +2,12 @@
// *** Do not edit by hand unless you're certain you know what you are doing! ***
// Export sub-modules:
import * as enums from "./enums";
import * as input from "./input";
import * as output from "./output";
export {
enums,
input,
output,
};

View file

@ -2,7 +2,7 @@
// *** 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";
import { input as inputs, output as outputs, enums } from "../types";
export namespace config {
}

View file

@ -2,7 +2,7 @@
// *** 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";
import { input as inputs, output as outputs, enums } from "../types";
export interface Child {
age?: number;

View file

@ -2,6 +2,7 @@
"emittedFiles": [
"pulumi_configstation/README.md",
"pulumi_configstation/__init__.py",
"pulumi_configstation/_enums.py",
"pulumi_configstation/_utilities.py",
"pulumi_configstation/config/__init__.py",
"pulumi_configstation/config/__init__.pyi",

View file

@ -5,6 +5,7 @@
from . import _utilities
import typing
# Export this package's modules as members:
from ._enums import *
from .provider import *
from . import outputs

View file

@ -0,0 +1,14 @@
# 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 enum import Enum
__all__ = [
'Color',
]
class Color(str, Enum):
BLUE = "blue"
RED = "red"

View file

@ -7,6 +7,7 @@ import pulumi
import pulumi.runtime
from typing import Any, Mapping, Optional, Sequence, Union, overload
from . import _utilities
from ._enums import *
__all__ = [
'Child',

View file

@ -7,16 +7,34 @@ import pulumi
import pulumi.runtime
from typing import Any, Mapping, Optional, Sequence, Union, overload
from . import _utilities
from ._enums import *
__all__ = ['ProviderArgs', 'Provider']
@pulumi.input_type
class ProviderArgs:
def __init__(__self__):
def __init__(__self__, *,
favorite_color: Optional[pulumi.Input[Union[str, 'Color']]] = None):
"""
The set of arguments for constructing a Provider resource.
:param pulumi.Input[Union[str, 'Color']] favorite_color: this is a relaxed string enum which can also be set via env var
"""
pass
if favorite_color is None:
favorite_color = _utilities.get_env('FAVE_COLOR')
if favorite_color is not None:
pulumi.set(__self__, "favorite_color", favorite_color)
@property
@pulumi.getter(name="favoriteColor")
def favorite_color(self) -> Optional[pulumi.Input[Union[str, 'Color']]]:
"""
this is a relaxed string enum which can also be set via env var
"""
return pulumi.get(self, "favorite_color")
@favorite_color.setter
def favorite_color(self, value: Optional[pulumi.Input[Union[str, 'Color']]]):
pulumi.set(self, "favorite_color", value)
class Provider(pulumi.ProviderResource):
@ -24,11 +42,13 @@ class Provider(pulumi.ProviderResource):
def __init__(__self__,
resource_name: str,
opts: Optional[pulumi.ResourceOptions] = None,
favorite_color: Optional[pulumi.Input[Union[str, 'Color']]] = None,
__props__=None):
"""
Create a Configstation 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.
:param pulumi.Input[Union[str, 'Color']] favorite_color: this is a relaxed string enum which can also be set via env var
"""
...
@overload
@ -53,6 +73,7 @@ class Provider(pulumi.ProviderResource):
def _internal_init(__self__,
resource_name: str,
opts: Optional[pulumi.ResourceOptions] = None,
favorite_color: Optional[pulumi.Input[Union[str, 'Color']]] = None,
__props__=None):
if opts is None:
opts = pulumi.ResourceOptions()
@ -65,6 +86,9 @@ class Provider(pulumi.ProviderResource):
raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource')
__props__ = ProviderArgs.__new__(ProviderArgs)
if favorite_color is None:
favorite_color = _utilities.get_env('FAVE_COLOR')
__props__.__dict__["favorite_color"] = pulumi.Output.from_input(favorite_color).apply(pulumi.runtime.to_json) if favorite_color is not None else None
super(Provider, __self__).__init__(
'configstation',
resource_name,

View file

@ -1,6 +1,24 @@
{
"version": "0.0.1",
"name": "configstation",
"provider": {
"inputProperties": {
"favoriteColor": {
"description": "this is a relaxed string enum which can also be set via env var",
"oneOf": [
{
"type": "string"
},
{
"$ref": "#/types/configstation:index:color"
}
],
"defaultInfo": {
"environment": ["FAVE_COLOR"]
}
}
}
},
"config": {
"variables": {
"name": {
@ -61,6 +79,13 @@
}
},
"type": "object"
},
"configstation:index:color": {
"enum": [
{"value": "blue"},
{"value": "red"}
],
"type": "string"
}
},
"language": {

View file

@ -327,8 +327,20 @@ func (mod *modContext) typeString(t schema.Type, input bool, constValue interfac
func isStringType(t schema.Type) bool {
t = codegen.UnwrapType(t)
for tt, ok := t.(*schema.TokenType); ok; tt, ok = t.(*schema.TokenType) {
t = tt.UnderlyingType
switch typ := t.(type) {
case *schema.TokenType:
t = typ.UnderlyingType
case *schema.EnumType:
t = typ.ElementType
case *schema.UnionType:
// The following case detects for relaxed string enums. If it's a Union, check if one ElementType is an EnumType.
// If yes, t is the ElementType of the EnumType.
for _, tt := range typ.ElementTypes {
t = codegen.UnwrapType(tt)
if typ, ok := t.(*schema.EnumType); ok {
t = typ.ElementType
}
}
}
return t == schema.StringType

View file

@ -126,3 +126,31 @@ func TestPascalCases(t *testing.T) {
require.Equal(t, tt.expected, result)
}
}
func Test_isStringType(t *testing.T) {
tests := []struct {
name string
input schema.Type
expected bool
}{
{"string", schema.StringType, true},
{"int", schema.IntType, false},
{"Input[string]", &schema.InputType{ElementType: schema.StringType}, true},
{"Input[int]", &schema.InputType{ElementType: schema.IntType}, false},
{"StrictStringEnum", &schema.EnumType{ElementType: schema.StringType}, true},
{"StrictIntEnum", &schema.EnumType{ElementType: schema.IntType}, false},
{"RelaxedStringEnum", &schema.UnionType{
ElementTypes: []schema.Type{&schema.EnumType{ElementType: schema.StringType}, schema.StringType},
}, true},
{"RelaxedIntEnum", &schema.UnionType{
ElementTypes: []schema.Type{&schema.EnumType{ElementType: schema.IntType}, schema.IntType},
}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := isStringType(tt.input); got != tt.expected {
t.Errorf("isStringType() = %v, want %v", got, tt.expected)
}
})
}
}