I'm obviously doing something wrong here with my i...
# typescript
b
I'm obviously doing something wrong here with my inputs and outputs, but I'm not really sure what. I'm trying to define a dynamic Resource that will check the status of a series of virtual machines. I have an interface for what a virtual machine 'looks like':
Copy code
export interface IP {
  ...
  address: string;
  ...
}

export interface IVirtualMachine {
  ...
  primaryIp: IP;
  ...
}
Elsewhere I'm passing objects defined as IVirtualMachine around between ComponentResource objects, and accessing
vm.primaryIp.address
without issue, but this is the first time I've tried to use one within a dynamic provider. My resource constructor has this interface for `args`:
Copy code
interface GetReadyInputs {
  clientConfiguration: pulumi.Input<ClientConfiguration>;
  nodes: pulumi.Input<IVirtualMachine[]>;
}
and the provider
async create
function expects this:
Copy code
interface GetReadyProviderInputs {
  clientConfiguration: ClientConfiguration;
  nodes: IVirtualMachine[];
}
But if I try and access the properties of an
IVirtualMachine
within the provider I get errors for
Cannot read properties of undefined
. Some judicious
console.log
output tells me it's because the value of each item in the
nodes
list at that point seems to be a Pulumi string URN, not an object satisfying
IVirtualMachine
. So how am I supposed to be passing these objects around so that I can correctly access the properties of them within my provider. For what it's worth the values I'm trying to access are known at compile time, not looked up at run time, but if they could be that would be amazing and future-proof my code.
l
Are you returning the full objects from
check()
? Or just their URNs?
b
I've not actually written a custom
check()
function. All the other objects I'd passed, including ones that were nested structures, were available fully without it, so I was expecting the same to be true in this case. From your pointer I get that if I wanted my values to be resolvable at runtime I'd probably need
check()
to do a lookup to fill them in, but given that currently they're available compile-time I was expecting it to Just Work (tm).
Those VMs are actually a
ComponentResource
object as well, but treating them as such wasn't something I thought was important here. That may be an incorrect assumption. We had problems with CDK where we ended up with deeply nested class hierarchies because TypeScript only does single-inheritance and we were using full classes everywhere. As we try to do a greenfield project in Pulumi we're really trying to avoid the same thing happening, so we wanted to be able to define interfaces which each class may implement multiple of, and each other class only references the interfaces that are relevant to it rather than a concrete class.
e
If the object implementing IVirtualMachine is a resource it will be serialsied across the wire to the dynamic provider as a resource reference, and because dynamic providers don't support full style references it translates to just a URN.
b
So what's the 'correct' thing to do here? Pull out the child property I actually want and pass just that to the dynamic provider?
That definitely seem to be working
e
yeh that'll work, or write a wrapper function to just copy out all the interface fields into a new plain object
b
Hmm. Is my definition of the input as
pulumi.Input<IVirtualMachine[]>
correct, or should it be
pulumi.Input<IVirtualMachine>[]
? Is it an input which contains a list, or a list of inputs? I don't seem to be able to unwrap the former to get at the properties of individual
IVirtualMachine
objects, so I'm guessing I want the latter. I'm keen to get this right because it's greenfield. So anything which I get wrong/have as a bad pattern will probably end up replicated all over the place for other components and then become massively hard to unpick. Also, I know properties in Pulumi can be marked as secret so they are encrypted in state. I don't see a way to do that with dynamic providers?
e
inputs depends on your use case, I can't comment to what's correct there. But where ever the input layer is you can unwrap and change it to something else via an output.apply. dynamic providers don't currently support secrets, we're looking at whole new provider sdks to replace them probably but just not had the time to push those over the line to finished yet