https://pulumi.com logo
Title
p

purple-minister-96588

11/04/2022, 2:29 PM
Serious question. How on earth do I take an output and make it into a string? I have lost an entire day to this and a team of 5 people and none of us can make this work. I create a redis cache on gcp which I return as an object called cache which I would expect to have a cache.host value, which I think I do have. Only that the output type of that is string according to the documentation. When I try to use it as a string to create a dns entry I get told it is an Output and not a string. So I want to cast to a string? I have this
host = cache.host.apply(lambda k: k)
Which from what I can tell is meant to be right, but host remains an output.
p

polite-ocean-13631

11/04/2022, 2:41 PM
cache.host
will only be available as a string within the function being run by
Output.apply
, so instead of trying to get a string out of it, you'll need to move the assignment (and whatever you wanted to do with the assignment) into it. If you have multiple
Output
-wrapped values that you need at the same time, you can use
Output.all
.
p

purple-minister-96588

11/04/2022, 2:44 PM
cache = redis_factory.create_redis(resource_name=name,
      project=base_project,
      tier=tier,
      memory_size_gb=memory_size_gb,
      region=region,
      authorized_network=authorized_network,
      display_name=name,
      read_replicas_mode=read_replicas_mode,
      connect_mode=connect_mode,
      replica_count=replica_count,
      redis_version=redis_version
    )

    host = cache.host.apply(lambda k: k)
    dns_records.append(DnsRecord(name,
      managed_zone=zone,
      dns_type="A",
      ttl=300,
      routing_policy="simple",
      data=host,
      name=name))
So on this do I do
host = cache.host.Output.apply(lambda k: k)
Sorry this is basically my first week with Pulumi so I am obviously missing something.
My factory runs
cache = gcp.redis.Instance(...)
return cache
I see in the docs
url = Output.all(hostname, port).apply(lambda l: f"http://{l[0]}:{l[1]}/")
So is that an Output.all(host).apply(lambda k: k) rather than try and tie it to the cache object?
p

polite-ocean-13631

11/04/2022, 2:47 PM
def create_dns_record(host: str):
    DnsRecord(
        name,
        managed_zone=zone,
        dns_type="A",
        ttl=300,
        routing_policy="simple",
        data=host,
        name=name,
    )

cache.host.apply(create_dns_record)
Maybe something like this would work? I assume this
DnsRecord
class doesn't accept
Output
-wrapped objects as arguments.
Output.all
is only useful when you want to do an
Output.apply
on multiple
Output
-wrapped values at once. so in the above code block if you also needed to pass in an output wrapped
routing_policy
in addition to
host
you could do something like:
Output.all(cache.host, routing_policy).apply(create_dns_record)
With
create_dns_record
updated to take a list of strings instead of a single one.
p

purple-minister-96588

11/04/2022, 2:55 PM
So I'm going to try
def create_dns_record(host: str, dns_record: DnsRecord, shared_project: str):
    dns_factory = DnsFactory()
    dns_factory.create_a_record(shared_project,
    resource_name=dns_record.resource_name,
    managed_zone=dns_record.managed_zone,
    dns_type=dns_record.dns_type,
    ttl=dns_record.ttl,
    routing_policy=dns_record.routing_policy,
    data=host,
    name=dns_record.name
  )
for dns_record in dns_records:
      cache.host.apply(create_dns_record(cache.host,dns_record, shared_project))
Does this sound right?
p

polite-ocean-13631

11/04/2022, 2:57 PM
The argument to
cache.host.apply
must be a function with a single
str
parameter. You'll need to use
cache.host.apply(lambda host: create_dns_record(host, dns_record, shared_project))
Or
functools.partial
p

purple-minister-96588

11/04/2022, 3:07 PM
cache.host.apply(lambda host: create_dns_records(host, dns_records, shared_project))

def create_dns_records(host: str, dns_records: list, shared_project: str):
    for dns_record in dns_records:
      dns_factory = DnsFactory()
      dns_factory.create_a_record(shared_project,
        resource_name=dns_record.resource_name,
        managed_zone=dns_record.managed_zone,
        dns_type=dns_record.dns_type,
        ttl=dns_record.ttl,
        routing_policy=dns_record.routing_policy,
        data=host,
        name=dns_record.name
    )
Thank you so much! This appears to be working
p

polite-ocean-13631

11/04/2022, 3:07 PM
Glad I could help 🙂
p

purple-minister-96588

11/04/2022, 3:08 PM
I've worked with terraform for about 8 years. So this is quite different.
e

echoing-dinner-19531

11/04/2022, 3:48 PM
Outputs are probably the biggest stumbling block people hit with Pulumi, but they are pretty much just fancy promises. They're a bit like Futures, except you can only ask for the result in a on_done_callback (i.e. apply). As such
output.apply(x: x)
is basically a no op, so if you ever find yourself with that you can simplify to just
output
. One of our architects wrote a pretty good blog post about it a while ago: https://leebriggs.co.uk/blog/2021/05/09/pulumi-apply Might help get your head around it.