Hello, how does `dependsOn` inheritance work (if a...
# general
c
Hello, how does
dependsOn
inheritance work (if at all) for component resources? The docs (https://www.pulumi.com/docs/concepts/options/parent/) say that “Child resources inherit default values for many other resource options from their parent…” but don’t mentioned dependencies. I would assume that they should inherit these, but in my tests they don’t seem to, so I have to pipe them through to children manually as part of the parent component resource “wrapper” code. Is that expected? Thanks!
b
are you parenting your resources inside your component to the component itself?
if so, passing
dependsOn
to the component when it’s instantiated should created a dependency on the component itself
some code would help
c
Thanks @billowy-army-68599.
Basically, if I don’t explicitly pass the
dependsOn
through to each child (there’s one child in the code snippet above), then the child does not appear to have any dependency, direct or transient, on the
dependsOn
used to instantiate the component resource (in this case,
dbClusterInstances
).
Without the extra
dependsOn
plumbing, a
state export
shows the parent relationship but doesn’t show anything in dependencies — not to the
dbClusterInstances
or to the parent class. Is this parent-class dependency implicit? I put the plumbing in there originally because I noticed these child resources being created before
dbClusterInstances
was completed, but I thought that having a parent dependent on a resource should have been enough. So I must be missing something here. Thanks again!
b
yes, you’re not setting the
parent
on the child resources
Copy code
this.admin = new postgresql.Role(
      `${dbName}-postgres-admin-role`,
      {
        login: true,
        name: adminUserName,
        password: adminUserPassword,
      },
      { parent, this },
    );
c
Thanks @billowy-army-68599 — I must be missing something, is line 24 not doing just that? The docs say it should be sent in the
opts
as the named param
parent
, which is happening in line 24 (I thought — note that line 13 is what sets the local
parent
to
this
). It seems like your example
{parent, this}
would instead send
this
as a named param
this
, which doesn’t exist from what I can see in the
CustomResourceOptions
interface. Thanks for your help, here.
b
Ah sorry, that’s a typos. You need parent:this (not a comma)
c
In JS if
parent
is a local you do not need to do
parent: parent
parent
alone will suffice (so-called “shorthand property names”). So I believe the code above is equivalent to
{ parent: this }
.
b
I’m not really following that, what I am trying to say is this particular resource:
Copy code
this.admin = new postgresql.Role(
      `${dbName}-postgres-admin-role`,
      {
        login: true,
        name: adminUserName,
        password: adminUserPassword,
      },
      { dependsOn, parent },
    );
Does not know it is a member of a component at all. It just knows that it
dependsOn
the component. Parenting a resource in Pulumi is a specific thing. It tells Pulumi to let all resources inherit the resource options from the thing it’s parenting to, including
dependsOn
Copy code
// Component class
export class PostgresDb extends pulumi.ComponentResource {
  db: postgresql.Database;
  admin: postgresql.Role;

  constructor(
    name: string,
    args: PostgresDbArgs,
    opts?: pulumi.ComponentResourceOptions,
  ) {
    super('mynamespace:aws:PostgresDb', name, args, opts);

	const parent = this;
    const dependsOn = opts?.dependsOn;
    const { dbName, adminUserName, adminUserPassword } = args;
		
    this.admin = new postgresql.Role(
      `${dbName}-postgres-admin-role`,
      {
        login: true,
        name: adminUserName,
        password: adminUserPassword,
      },
      { parent: this },
    );
    
	// ...
  }
}

const MySvcDb = new PostgresDb(
  'my-svc-postgres-db',
  {
    dbName: 'my-svc',
    adminUserName: '...',
    adminUserPassword: '...',
  },
  {
    parent: this
  },
It’ll likely solve your issue
c
Thank you @billowy-army-68599 — I think the code is functionally equivalent (JS syntax is the difference). I will rewrite it though and try it that same way. One clarification — you added
parent: this
to the
opts
for the component resource initializer as well (i.e. also to
new PostgresDb()
, not just the children of the component like
new postgresql.Role()
) — presumably that would make the component’s parent the…. stack? I haven’t seen this use of
parent
before.
b
ah sorry, I didn’t realise that was a component, you don’t need parent there
just inside the resources in the component
my mistake
c
Good to know! 🙂 I tried with the different syntax, same result. This results in the expected
parent
associated with its state, but no
dependencies
at all:
Copy code
"parent": "urn:pulumi:(stack)::cda::mynamespace:PostgresDb::my-svc-postgres-db",
b
did you make the component instantiation depend on the role?
c
Sorry, no, the role is part of the component.
b
sorry let me regrok this
c
I’m happy to present it in a different way (e.g. change names to be more obvious).
When I change the child’s
opts
to the following the state is updated with the dependencies passed into the component resource
opts
:
Copy code
"dependencies": [
    "urn:pulumi:(stack)::cda::aws:rds/clusterInstance:ClusterInstance::rdsClusterPostgresInstance-0"
],
b
okay, I think I understand now. Let’s say you have a component like this
Copy code
// Component class
export class PostgresDb extends pulumi.ComponentResource {
  db: postgresql.Database;
  admin: postgresql.Role;

  constructor(
    name: string,
    args: PostgresDbArgs,
    opts?: pulumi.ComponentResourceOptions,
  ) {
    super('mynamespace:aws:PostgresDb', name, args, opts);

	const parent = this;
    const dependsOn = opts?.dependsOn;
    const { dbName, adminUserName, adminUserPassword } = args;
		
    this.admin = new postgresql.Role(
      `${dbName}-postgres-admin-role`,
      {
        login: true,
        name: adminUserName,
        password: adminUserPassword,
      },
      { parent: this },
    );
    
	// ...
  }
}
And you instantate it like this
Copy code
const MySvcDb = new PostgresDb(
  'my-svc-postgres-db',
  {
    dbName: 'my-svc',
    adminUserName: '...',
    adminUserPassword: '...',
  },
  {
    dependsOn: someOtherResources
  },
Everything in the
PostgresDb
class should depend on
someOtherResources
is there somrthing else you need?
c
That is what I assume — but that’s not what I’m observing.
None of the children have dependencies on
someOtherResources
.
b
how are you observing that?
c
I’m deploying, doing a
pulumi stack export
, and finding the resource in the file, looking at its
dependencies
property. It’s not present on children; when I explicitly plumb through the
opts.dependsOn
to the children it shows up.
b
It won’t be set on anythjng other than the parent. The logic happens in the engine
You don’t get that explicit dependency on the children in the state
c
Hmmm… I guess that’s the answer then, and good to know. I introduced it because I saw the children being created before the
dependsOn
resources that were provided to the parent. That’s a hard thing to reproduce quickly (it involves spinning up new RDSes). I can revert the explicit piping then and see if it reintroduces the problem or not! 🙂 Thanks for sticking with this thread, much appreciated. I’m not sure if the documentation can be improved in this respect — it’s a little vague on that parent page what should happen and how the state doesn’t show this implicit dependency. I appreciate your help in clarifying!