How bad of an idea is this :smile:
f
How bad of an idea is this 😄
As our stacks have grown, someone said "Hey, let's group related resources together". This is a great idea - we already do this with functions that return objects - but pulumi doesn't know about this structure. We can parent resources to each other, but what if we want a "fake"/"virtual"/"container"/"empty" resource to act as a parent? As far as I can tell, the only way is with ComponentResources, and the only way to use those is to re-factor the entire codebase into classes.
l
You don't need classes for a resource to have a ComponentResource as a parent. Refactoring so that grouped resources are constructed in a component resources' constructor is a good idea for all sorts of reasons, but if you don't want to do it, then the empty resource like this is fine.
😲 1
If you're paying Pulumi per resource then this resource costs the same as every other resource. Which shouldn't be a reason not to do it, but it might be.
f
Mere seconds ago I learned you can call
new pulumi.ComponentResource()
directly, which is super cool. I was worried about the registerOutputs() call, that seems to be mandatory if you use
extends
l
Personally I'd take this opportunity to at least start the refactoring: have a policy of not creating an instance of a ComponentResource class, and instead create new subclasses. Initially, don't refactor anything into them, but doing it this way makes it clear that you'd like to refactor later...
There is no need to call registerOutputs in a "dummy" resource, since you have no outputs that need registering. id and urn are the only outputs, and they're already registered.
f
I've been trying to fully understand the benefits of full-blown component resources with classes, and it seems like the biggest one is being able to export a module/class and consume it in a different pulumi program in a different language. That's super cool, but it's not something we would use (We're tied to one language and would rather publish an internal npm module). I'm sold on parenting and the aliases benefits we get from that, but it looks like I can get that with functions. Is there anything else I'm missing? (Thank you so much for your help by the way)
l
The biggest benefits of component resources in my code base are 1. Unit testability -- prove that the stuff in 2 is there, report on partially-implemented resources, etc. 2. Policies -- code reviewers know that resources are being used in the correct ways, e.g. that buckets are public, versioned and encrypted, because the only way code creates buckets is via our bucket component resources, which contain all that logic (and which is unit tested thanks to 1 above).
Code in index.ts cannot be unit tested -- logically, because it's not a unit, and practically, because we use Pulumi APIs that don't behave the same in a unit testing context as they do normally. So we can keep all that sort of stuff in index.ts, and all unit-testable stuff goes into component resources.
f
That is extremely helpful, thank you!
👍 1
c
I have been meaning to open an issue in
pulumi/pulumi
for this very scenario. I, too, have an empty component resource that I just want to use as a common parent for some resources.
l
Does it not just work the way Ethan says? This seems like a good solution.
c
It does work and I use the same pattern too. I was thinking if Pulumi would want to introduce a first-class construct for this purpose. That way, it becomes a well-known pattern for devs to use. Right now, I think most people view component resources as only being useful when you have children to register in them or if you want to inherit a common provider passed to it etc.
l
I think a minor change to the docs could prevent creating (and maintaining, documenting, testing...) a new class 🙂
c
Maybe. Maybe both. I don't think this special parent needs to be a class. The workarounds call for a component resource class, which is still an option for those who might want a bit more control over this "empty parent". Having a first-class construct would mean I don't have to have such component resources declared in a bunch of projects or have a single project that exports this as a component (specifically for teams that are not equipped to publish internal packages and maintain them)