hi, <https://pulumi.io/reference/pkg/nodejs/@pulum...
# general
c
hi, https://pulumi.io/reference/pkg/nodejs/@pulumi/pulumi/index.html#Output-apply "‘func’ is not allowed to make resources." Is this still stands? If so, how can you do this with an Output like this: https://pulumi.io/reference/pkg/nodejs/@pulumi/aws/route53/#Zone-nameServers Possibly not the way the example shows, getting the array elements with fix indexes, without a loop.
w
"‘func’ is not allowed to make resources."
That's actually technically not true - it is possible and will generally work for the callback to create new resources. But it is discouraged, as it can lead to the results of
pulumi preview
being wrong, as the
apply
callback will not get run during a preview (because the real outputs values aren't yet known until the resources are deployed), and therefore any resources created in the callback will not be seen during the
preview
. I'm not sure I fully follow the second part of your question about
nameServers
. In general, it should be very very rare to have to create resources inside an
apply
- instead you should be able to create the resource and pass in the output value as an input to the resource. If you share an example of where you are needing to do this we could suggest an alternative.
c
The nameservers property returns a
pulumi.Output<string[]>
not a
pulumi.Output<string>[]
, latter is iterable without apply, but the former not, so if I want to create a resource for every nameserver, I can only do that in inside apply, e.g.:
Copy code
let pubZone = new aws.route53.Zone(`${stackName}-r53-pub-zone`, {
  name: pubDomain,
  forceDestroy: true
})

pubZone.nameServers.apply(nameservers => {
  nameservers.forEach((nameserver, index) => {
    new cloudflare.DNSRecord(`${stackName}-r53-pub-zone-ns-${index}`, {
      domain: mainDomain,
      type: 'NS',
      name: pubDomain.substring(0, pubDomain.indexOf(mainDomain) - 1),
      content: nameserver,
      ttl: dnsTTL,
      proxied: false
    })
  })
})
where
content
is a
pulumi.Input<string>
. I can't see a way to do this outside of apply without modifying our custom resource or is it possible to transform the nameserver output to a
pulumi.Output<string>[]
?
Another example, we have a subnetIds array as an output from one stack, read that in another stack with StackRef, so we got a pulumi.Output<any> which is a pulumi.Output<string[]> under the hood, how can we iterate through that and create some resource for each subnet, outside of apply?
w
Great - so that use case is indeed the class of case where it is necessary to create resources inside the
apply
. The fact that
preview
can not accurately predict what will get created is fairly clear here - you do not in fact know how many of these (if any) you will end up needing to create until part of the deployment has happened (enough to return the actual array of
nameServers
. So Pulumi lets you express this, but the preview may not include any changes to resources that are created (or later removed) from within the
apply
.
c
ok, thanks, any plan to make this kind of Outputs iterable and avoid this problem? maybe a new helper method to the pulumi.iterable module?
o
did you import or write your own cloudflare provider??
@cold-coat-35200
c
we wrote our own, but only for handling DNSRecords, let me know if you need that code
c
@cold-coat-35200 It would great if you can share some of the code!! I work along with @orange-tailor-85423
o
👍
c
3 things you should know. First, 2 env variable has to be set, you can see them in the getClient() code, we chose this solution to avoid saving sensitive data in the state . Second, setting
deleteBeforeReplace
on DNSRecord resources is recommended, because Cloudflare does not allow to create the same record twice. Third, cloudflare library using a very old
got
library (6.x, newest is 9.x) which does not pass back the error text, returned from Cloudflare api, so if any problem happens, you will see a 400 error and nothing else. I can't do anything about it.