-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better typing for Go SDK #248
Comments
@johanbrandhorst thank you for filing this. As the guy who put this together, I can't agree more. One of the challenges we have, which I would love feedback on since I ran out of ideas, is that it's tough to type these things. I'm not sure if you noticed all the specialized /cc @pgavlin also, since he is our resident Go idioms guy. |
I wonder if we should consider functions like This would be a lot like It would be rather verbose, but in a way that is fairly idiomatic for Go. |
@joeduffy @lukehoban thanks for your replies! I'm personally not a huge fan of the stuff the AWS SDK does (afaik it's just a helper for creating a pointer to a string literal). For discriminated unions I think the best you can do at the moment is using an unexported interface like the Go protobuf implementation:
Unfortunately this does not work with native strings of course... so you'd still need a |
Go support is out of scope for M21. |
Part of pulumi/pulumi#3506? |
The redesign is focused around providing better static typings and improved ease-of-use for the Go SDK. Most of the redesign revolves around three pivots: - Strongly-typed inputs, especially for nested types - Struct-based resource and invoke APIs - Ease-of-use of Apply 1. Strongly-typed inputs Input is the type of a generic input value for a Pulumi resource. This type is used in conjunction with Output to provide polymorphism over strongly-typed input values. The intended pattern for nested Pulumi value types is to define an input interface and a plain, input, and output variant of the value type that implement the input interface. For example, given a nested Pulumi value type with the following shape: ``` type Nested struct { Foo int Bar string } ``` We would define the following: ``` var nestedType = reflect.TypeOf((*Nested)(nil)).Elem() type NestedInput interface { pulumi.Input ToNestedOutput() NestedOutput ToNestedOutputWithContext(context.Context) NestedOutput } type Nested struct { Foo int `pulumi:"foo"` Bar string `pulumi:"bar"` } type NestedInputValue struct { Foo pulumi.IntInput `pulumi:"foo"` Bar pulumi.StringInput `pulumi:"bar"` } func (NestedInputValue) ElementType() reflect.Type { return nestedType } func (v NestedInputValue) ToNestedOutput() NestedOutput { return pulumi.ToOutput(v).(NestedOutput) } func (v NestedInputValue) ToNestedOutputWithContext(ctx context.Context) NestedOutput { return pulumi.ToOutputWithContext(ctx, v).(NestedOutput) } type NestedOutput struct { *pulumi.OutputState } func (NestedOutput) ElementType() reflect.Type { return nestedType } func (o NestedOutput) ToNestedOutput() NestedOutput { return o } func (o NestedOutput) ToNestedOutputWithContext(ctx context.Context) NestedOutput { return o } func (o NestedOutput) Foo() pulumi.IntOutput { return o.Apply(func (v Nested) int { return v.Foo }).(pulumi.IntOutput) } func (o NestedOutput) Bar() pulumi.StringOutput { return o.Apply(func (v Nested) string { return v.Bar }).(pulumi.StringOutput) } ``` The SDK provides input and output types for primitives, arrays, and maps. 2. Struct-based APIs Instead of providing expected output properties in the input map passed to {Read,Register}Resource and returning the outputs as a map, the user now passes a pointer to a struct that implements one of the Resource interfaces and has appropriately typed and tagged fields that represent its output properties. For example, given a custom resource with an int-typed output "foo" and a string-typed output "bar", we would define the following CustomResource type: ``` type MyResource struct { pulumi.CustomResourceState Foo pulumi.IntOutput `pulumi:"foo"` Bar pulumi.StringOutput `pulumi:"bar"` } ``` And invoke RegisterResource like so: ``` var resource MyResource err := ctx.RegisterResource(tok, name, props, &resource, opts...) ``` Invoke arguments and results are also provided via structs, but use plain-old Go types for their fields: ``` type MyInvokeArgs struct { Foo int `pulumi:"foo"` } type MyInvokeResult struct { Bar string `pulumi:"bar"` } var result MyInvokeResult err := ctx.Invoke(tok, MyInvokeArgs{Foo: 42}, &result, opts...) ``` 3. Ease-of-use of Apply All `Apply` methods now accept an interface{} as the callback type. The provided callback value must have one of the following signatures: func (v T) U func (v T) (U, error) func (ctx context.Context, v T) U func (ctx context.Context, v T) (U, error) T must be assignable from the ElementType of the Output. If U is a type that has a registered Output type, the result of the Apply will be the corresponding Output type. Otherwise, the result of the Apply will be AnyOutput. Fixes #2149. Fixes #3488. Fixes #3487. Fixes pulumi/pulumi-aws#248. Fixes #3492. Fixes #3491. Fixes #3562.
Hi!
I'm really excited by this project, but I was immediately disappointed by the SDK types. Here's the first one I found:
I understand this was probably a compromise to get things ready for GA, but I'd like this issue to track the work on typing this stuff up, otherwise it's little better than the JS SDK (:scream:).
Thanks
The text was updated successfully, but these errors were encountered: