Skip to content

Commit

Permalink
Address review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
lblackstone committed May 25, 2021
1 parent 3b86125 commit 7d2f6e3
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 73 deletions.
67 changes: 33 additions & 34 deletions pkg/codegen/dotnet/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,10 +448,19 @@ func (pt *plainType) genInputProperty(w io.Writer, prop *schema.Property, indent

indent = strings.Repeat(indent, 2)

// Next generate the input property itself. The way this is generated depends on the type of the property:
// complex types like lists and maps need a backing field.
needsBackingField := false
switch prop.Type.(type) {
case *schema.ArrayType, *schema.MapType:
needsBackingField = true
default:
if prop.Secret {
needsBackingField = true
}
}

// Next generate the input property itself. The way this is generated depends on the type of the property:
// complex types like lists and maps need a backing field. Secret properties also require a backing field.
if needsBackingField {
backingFieldName := "_" + prop.Name
requireInitializers := !pt.args
backingFieldType := pt.mod.typeString(prop.Type, pt.propertyTypeQualifier, true, pt.state, argsType, argsType, requireInitializers, false)
Expand All @@ -465,59 +474,49 @@ func (pt *plainType) genInputProperty(w io.Writer, prop *schema.Property, indent
}
printObsoleteAttribute(w, prop.DeprecationMessage, indent)

// Note that we use the backing field type--which is just the property type without any nullable annotation--to
// ensure that the user does not see warnings when initializing these properties using object or collection
// initializers.
fmt.Fprintf(w, "%spublic %s %s\n", indent, backingFieldType, propertyName)
fmt.Fprintf(w, "%s{\n", indent)
fmt.Fprintf(w, "%s get => %[2]s ?? (%[2]s = new %[3]s());\n", indent, backingFieldName, backingFieldType)
switch prop.Type.(type) {
case *schema.ArrayType, *schema.MapType:
// Note that we use the backing field type--which is just the property type without any nullable annotation--to
// ensure that the user does not see warnings when initializing these properties using object or collection
// initializers.
fmt.Fprintf(w, "%spublic %s %s\n", indent, backingFieldType, propertyName)
fmt.Fprintf(w, "%s{\n", indent)
fmt.Fprintf(w, "%s get => %[2]s ?? (%[2]s = new %[3]s());\n", indent, backingFieldName, backingFieldType)
default:
fmt.Fprintf(w, "%spublic %s? %s\n", indent, backingFieldType, propertyName)
fmt.Fprintf(w, "%s{\n", indent)
fmt.Fprintf(w, "%s get => %s;\n", indent, backingFieldName)
}
if prop.Secret {
fmt.Fprintf(w, "%s set\n", indent)
fmt.Fprintf(w, "%s {\n", indent)
fmt.Fprintf(w, "%s // Always mark this field as secret to avoid leaking sensitive values into the state.\n", indent)
fmt.Fprintf(w, "%s // Since we can't directly assign the Output from CreateSecret to the property, use an\n", indent)
fmt.Fprintf(w, "%s // Output.all to enable the secret flag on the data.\n", indent)
// Since we can't directly assign the Output from CreateSecret to the property, use an Output.All or
// Output.Tuple to enable the secret flag on the data.
switch t := prop.Type.(type) {
case *schema.ArrayType:
fmt.Fprintf(w, "%s var emptySecret = Output.CreateSecret(ImmutableArray.Create<%s>());\n", indent, t.ElementType.String())
fmt.Fprintf(w, "%s %s = Output.All(value, emptySecret).Apply(v => v[0]);\n", indent, backingFieldName)
case *schema.MapType:
fmt.Fprintf(w, "%s var emptySecret = Output.CreateSecret(ImmutableDictionary.Create<string, %s>());\n", indent, t.ElementType.String())
fmt.Fprintf(w, "%s %s = Output.All(value, emptySecret).Apply(v => v[0]);\n", indent, backingFieldName)
default:
fmt.Fprintf(w, "%s var emptySecret = Output.CreateSecret(0);\n", indent)
fmt.Fprintf(w, "%s %s = Output.Tuple<%s?, int>(value, emptySecret).Apply(t => t.Item1);\n", indent, backingFieldName, backingFieldType)
}
fmt.Fprintf(w, "%s %s = Output.All(value, emptySecret).Apply(v => v[0]);\n", indent, backingFieldName)
fmt.Fprintf(w, "%s }\n", indent)
} else {
fmt.Fprintf(w, "%s set => %s = value;\n", indent, backingFieldName)
}
fmt.Fprintf(w, "%s}\n", indent)
default:
} else {
initializer := ""
if prop.IsRequired && (!isValueType(prop.Type) || pt.args) {
initializer = " = null!;"
}

printComment(w, prop.Comment, indent)
fmt.Fprintf(w, "%s[Input(\"%s\"%s)]\n", indent, wireName, attributeArgs)
if prop.Secret {
fmt.Fprintf(w, "%spublic %s %s\n", indent, propertyType, propertyName)
fmt.Fprintf(w, "%s{\n", indent)
fmt.Fprintf(w, "%s get => %s;\n", indent, propertyName)
fmt.Fprintf(w, "%s set\n", indent)
fmt.Fprintf(w, "%s {\n", indent)
fmt.Fprintf(w, "%s if (value != null)\n", indent)
fmt.Fprintf(w, "%s {\n", indent)
fmt.Fprintf(w, "%s // Always mark this field as secret to avoid leaking sensitive values into the state.\n", indent)
fmt.Fprintf(w, "%s // Since we can't directly assign the Output from CreateSecret to the property, use an\n", indent)
fmt.Fprintf(w, "%s // Output.Tuple to enable the secret flag on the data.\n", indent)
fmt.Fprintf(w, "%s var emptySecret = Output.CreateSecret(0);\n", indent)
fmt.Fprintf(w, "%s %s = Output.Tuple<%s, int>(value, emptySecret).Apply(t => t.Item1);\n", indent, propertyName, propertyType)
fmt.Fprintf(w, "%s }\n", indent)
fmt.Fprintf(w, "%s else\n", indent)
fmt.Fprintf(w, "%s %s = null;\n", indent, propertyName)
fmt.Fprintf(w, "%s }\n", indent)
fmt.Fprintf(w, "%s}\n", indent)
} else {
fmt.Fprintf(w, "%spublic %s %s { get; set; }%s\n", indent, propertyType, propertyName, initializer)
}
fmt.Fprintf(w, "%spublic %s %s { get; set; }%s\n", indent, propertyType, propertyName, initializer)
}
}

Expand Down
4 changes: 1 addition & 3 deletions pkg/codegen/go/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,12 +1181,10 @@ func (pkg *pkgContext) genResource(w io.Writer, r *schema.Resource, generateReso
fmt.Fprintf(w, "\t})\n")
fmt.Fprintf(w, "\topts = append(opts, aliases)\n")
}
// Set any defined additionalSecretOutputs.
if len(secretProps) > 0 {
fmt.Fprintf(w, "\t// Always mark these fields as secret to avoid leaking sensitive values into the state.\n")
for _, p := range secretProps {
fmt.Fprintf(w, "\tif args.%s != nil {\n", Title(p.Name))
fmt.Fprintf(w, "\t\targs.%[1]s = pulumi.ToSecret(args.%[1]s).(%[2]s)\n", Title(p.Name), pkg.inputType(p.Type, false))
fmt.Fprintf(w, "\t\targs.%[1]s = pulumi.ToSecret(args.%[1]s).(%[2]s)\n", Title(p.Name), pkg.outputType(p.Type, false))
fmt.Fprintf(w, "\t}\n")
}
fmt.Fprintf(w, "\tsecrets := pulumi.AdditionalSecretOutputs([]string{\n")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,14 @@ public static Resource Get(string name, Input<string> id, CustomResourceOptions?
public sealed class ResourceArgs : Pulumi.ResourceArgs
{
[Input("bar")]
private Input<string>? _bar;
public Input<string>? Bar
{
get => Bar;
get => _bar;
set
{
if (value != null)
{
// Always mark this field as secret to avoid leaking sensitive values into the state.
// Since we can't directly assign the Output from CreateSecret to the property, use an
// Output.Tuple to enable the secret flag on the data.
var emptySecret = Output.CreateSecret(0);
Bar = Output.Tuple<Input<string>?, int>(value, emptySecret).Apply(t => t.Item1);
}
else
Bar = null;
var emptySecret = Output.CreateSecret(0);
_bar = Output.Tuple<Input<string>?, int>(value, emptySecret).Apply(t => t.Item1);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ func NewResource(ctx *pulumi.Context,
args = &ResourceArgs{}
}

// Always mark these fields as secret to avoid leaking sensitive values into the state.
if args.Bar != nil {
args.Bar = pulumi.ToSecret(args.Bar).(pulumi.StringInput)
args.Bar = pulumi.ToSecret(args.Bar).(pulumi.StringOutput)
}
secrets := pulumi.AdditionalSecretOutputs([]string{
"bar",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,13 @@ export class Resource extends pulumi.CustomResource {
let inputs: pulumi.Inputs = {};
opts = opts || {};
if (!opts.id) {
inputs["bar"] = args ? args.bar : undefined;
inputs["bar"] = args?.bar ? pulumi.secret(args.bar) : undefined;
} else {
inputs["bar"] = undefined /*out*/;
}
if (!opts.version) {
opts = pulumi.mergeOptions(opts, { version: utilities.getVersion()});
}
// Always mark these fields as secret to avoid leaking sensitive values into the state.
for (const key of ["bar"]) {
if (key in inputs && inputs[key] !== undefined) inputs[key] = pulumi.secret(inputs[key]);
}

const secretOpts = { additionalSecretOutputs: ["bar"] };
opts = pulumi.mergeOptions(opts, secretOpts);
super(Resource.__pulumiType, name, inputs, opts);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,7 @@ def _internal_init(__self__,
raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource')
__props__ = ResourceArgs.__new__(ResourceArgs)

__props__.__dict__["bar"] = bar
# Always mark these fields as secret to avoid leaking sensitive values into the state.
for key in ["bar"]:
if __props__.__dict__.get(key):
__props__.__dict__[key] = pulumi.Output.secret(__props__.__dict__[key])
__props__.__dict__["bar"] = None if bar is None else pulumi.Output.secret(bar)
secret_opts = pulumi.ResourceOptions(additional_secret_outputs=["bar"])
opts = pulumi.ResourceOptions.merge(opts, secret_opts)
super(Resource, __self__).__init__(
Expand Down
11 changes: 6 additions & 5 deletions pkg/codegen/nodejs/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,12 @@ func (mod *modContext) genResource(w io.Writer, r *schema.Resource) error {
}
}
for _, prop := range r.InputProperties {
arg := fmt.Sprintf("args ? args.%[1]s : undefined", prop.Name)
var arg string
if prop.Secret {
arg = fmt.Sprintf("args?.%[1]s ? pulumi.secret(args.%[1]s) : undefined", prop.Name)
} else {
arg = fmt.Sprintf("args ? args.%[1]s : undefined", prop.Name)
}

prefix := " "
if prop.ConstValue != nil {
Expand Down Expand Up @@ -691,10 +696,6 @@ func (mod *modContext) genResource(w io.Writer, r *schema.Resource) error {
}

if len(secretProps) > 0 {
fmt.Fprintf(w, " // Always mark these fields as secret to avoid leaking sensitive values into the state.\n")
fmt.Fprintf(w, ` for (const key of ["%s"]) {`, strings.Join(secretProps, `", "`))
fmt.Fprintf(w, "\n if (key in inputs && inputs[key] !== undefined) inputs[key] = pulumi.secret(inputs[key]);\n")
fmt.Fprintf(w, " }\n\n")
fmt.Fprintf(w, ` const secretOpts = { additionalSecretOutputs: ["%s"] };`, strings.Join(secretProps, `", "`))
fmt.Fprintf(w, "\n opts = pulumi.mergeOptions(opts, secretOpts);\n")
}
Expand Down
14 changes: 7 additions & 7 deletions pkg/codegen/python/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (

"github.com/blang/semver"
"github.com/pkg/errors"

"github.com/pulumi/pulumi/pkg/v3/codegen"
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
Expand Down Expand Up @@ -1099,13 +1100,17 @@ func (mod *modContext) genResource(res *schema.Resource) (string, error) {
if res.IsProvider && !isStringType(prop.Type) {
arg = fmt.Sprintf("pulumi.Output.from_input(%s).apply(pulumi.runtime.to_json) if %s is not None else None", arg, arg)
}
fmt.Fprintf(w, " __props__.__dict__[%q] = %s\n", PyName(prop.Name), arg)
name := PyName(prop.Name)
if prop.Secret {
fmt.Fprintf(w, " __props__.__dict__[%[1]q] = None if %[2]s is None else pulumi.Output.secret(%[2]s)\n", name, arg)
} else {
fmt.Fprintf(w, " __props__.__dict__[%q] = %s\n", name, arg)
}

ins.Add(prop.Name)
}

var secretProps []string
var secretPropsPyName []string
for _, prop := range res.Properties {
// Default any pure output properties to None. This ensures they are available as properties, even if
// they don't ever get assigned a real value, and get documentation if available.
Expand All @@ -1115,7 +1120,6 @@ func (mod *modContext) genResource(res *schema.Resource) (string, error) {

if prop.Secret {
secretProps = append(secretProps, prop.Name)
secretPropsPyName = append(secretPropsPyName, PyName(prop.Name))
}
}

Expand All @@ -1134,10 +1138,6 @@ func (mod *modContext) genResource(res *schema.Resource) (string, error) {
}

if len(secretProps) > 0 {
fmt.Fprintf(w, " # Always mark these fields as secret to avoid leaking sensitive values into the state.\n")
fmt.Fprintf(w, ` for key in ["%s"]:`, strings.Join(secretPropsPyName, `", "`))
fmt.Fprintf(w, "\n if __props__.__dict__.get(key):\n")
fmt.Fprintf(w, " __props__.__dict__[key] = pulumi.Output.secret(__props__.__dict__[key])\n")
fmt.Fprintf(w, ` secret_opts = pulumi.ResourceOptions(additional_secret_outputs=["%s"])`, strings.Join(secretProps, `", "`))
fmt.Fprintf(w, "\n opts = pulumi.ResourceOptions.merge(opts, secret_opts)\n")
}
Expand Down

0 comments on commit 7d2f6e3

Please sign in to comment.