https://pulumi.com logo
#getting-started
Title
# getting-started
c

cuddly-jewelry-42389

12/29/2023, 9:14 AM
Hi team, On the documentation page for apply, it says to not have side-effects - like creating new resources - in the callback passed to apply, which makes absolute sense based on the explanation. Yet, in the Crosswalk for AWS documentation that's exactly what's being done in one of the examples. So, what IS the recommended best practice?
d

dry-keyboard-94795

12/29/2023, 9:57 AM
In this case, DefaultVpc is just a wrapped invoke, which will still run during preview. Awsx is using
pulumi.output
to wrap promises, so it's a different lifecycle that can be treated as "sync" before a stack is constructed. If it's an output from a resource, you should still avoid using
.apply
to create other resources
c

cuddly-jewelry-42389

12/29/2023, 10:02 AM
Thanks for the swift answer. So, do I need to know implementation details to understand when I can create resources inside apply and when not? Or am I missing something?
d

dry-keyboard-94795

12/29/2023, 10:10 AM
Only that an invoke (provider function) runs before the stack is constructed unless it depends on a resource output. This goes for if you're wrapping your own async code with
pulumi.output
too. You shouldn't need to dive further into implementation details than that
c

cuddly-jewelry-42389

12/29/2023, 10:22 AM
I don't think I understand your reference to "invoke (provider function)". When I create an instance of
awsx.ec2.DefaultVpc
it has a property
publicSubnetIds
. The type of that property is
pulumi.Output<string[]>
. An instance of type
aws.acm.Certificate
has a property
domainValidationOptions
of type
pulumi.Output<CertificateDomainValidationOptions[]>
. How do I know on which of these properties I'm allowed to create new resources inside the
apply
callback and on which not? I see no way except looking into the code of the corresponding package implementations.
d

dry-keyboard-94795

12/29/2023, 10:42 AM
If the docs provide an example, it'll be safe. But yes, without that example you'd need to check the code
This gives the basics of provider functions: https://www.pulumi.com/docs/concepts/resources/functions/
c

cuddly-jewelry-42389

12/29/2023, 10:45 AM
Got it, thanks!
But yes, without that example you'd need to check the code
This does sound like a bit of a design flaw to me.
d

dry-keyboard-94795

12/29/2023, 10:48 AM
Yes, perhaps Invokes should have a new type of
KnownOutput
to make it clearer when it's always safe to use. I don't think it'd help much though, as there wouldn't be a way to warn about resource creation inside the function body
c

cuddly-jewelry-42389

12/29/2023, 10:51 AM
Right. It would require a complete redesign of how resources are being created...
d

dry-keyboard-94795

12/29/2023, 10:52 AM
I meant in terms of static type analysis. It'd be easy enough to warn at runtime
c

cuddly-jewelry-42389

12/29/2023, 10:54 AM
Yes, that's what I meant as well. To be able to prevent people from writing code that creates new resources inside the apply function, the way resources are created would need to be changed, e.g. to using a factory class instead of `new`ing them up. And then, an instance of this factory class is being passed - by pulumi - only to places where resources may be created.
b

billowy-army-68599

12/29/2023, 12:57 PM
There’s some nuance here. It’s not best practice to create resources inside an apply, but due to the design of some cloud provider APIs, there really isn’t much choice in some situations. It’s really API dependent. The domain validation one for ACM certificates is a great example of that - you need to create DNS records for the cert but can’t do it until the API has returned values. You can use lifting, but that often means not doing it idiomatically.
d

dry-keyboard-94795

12/29/2023, 1:05 PM
Given it's a common question, going to look at doing some articles on life cycles within within pulumi
c

cuddly-jewelry-42389

12/29/2023, 2:35 PM
Thanks for the additional insight!