how do I get the string representation of a stack ...
# general
s
how do I get the string representation of a stack output? e.g. https://gist.github.com/ohlol/90cdf58e5a2ea49976470c06d8fb4afd
f
bucket.apply(print)
s
thanks, what if I want to say use string formatting?
f'{bucket.apply(str)}-bucket'
didn’t work
g
bucket.apply(lambda b: print(f'{b}-bucket'))
Outputs are essentially promises/futures, so any manipulation you need to do them must happen with the
.apply()
.
The pulumi type system allows you to pass an output as an input without
.apply()
ing it as long as you don't need to manipulate or transform the value.
s
hmm,
bucket.apply(print)
doesn’t send anything to diagnostics like a normal
print()
does - should it?
though, i’m not as concerned with print as just being able to interpolate the value of an output
f
Note that the returned type is still an
Output[str]
and not a str
but you can then pass that in to other resources
s
so i’ve finally gotten time to revisit this, it’s still not working for me
according to the docs, this should be possible: https://www.pulumi.com/docs/intro/concepts/programming-model/#lifting
i’m pretty bewildered by the fact that such a simple thing is not so simple
to be clear, I want to pass
vpc.cidr_block
to something that is not a Pulumi resource. so if the CIDR block is
10.0.0.0/16
then I want to pass that string
no incantation of apply, all, or anything else is working
how does this not raise
IndexError
?
Copy code
vpc_network = ip_network(vpc.cidr_block[0][1][500][6])
      File "/Users/scott/.pyenv/versions/3.8.2/lib/python3.8/ipaddress.py", line 83, in ip_network
        raise ValueError('%r does not appear to be an IPv4 or IPv6 network' %
    ValueError: <pulumi.output.Output object at 0x108333af0> does not appear to be an IPv4 or IPv6 network
    error: an unhandled error occurred: Program exited with non-zero exit code: 1
that’s wild
str(vpc.tags.apply(lambda x: f'{x.get("Name")}-{subnet_config.get("name")}_{availability_zone}'))
this does not return a string
I use that to generate a subnet name
and pulumi tries to create this resource:
+ └─ awsec2Subnet <pulumi.output.Output object at 0x10c0c7be0> create
in that case the string would be
util-private_us-west-1b
f
apply
returns an
Output
the concept of lifting is to simplify getting an
Output
value
you work with the actual type, e.g.
str
within the
apply
but you’ll never get back a
str
from the
apply
itself
assuming
do_thing
wants to take a
str
— you should be doing something like
vpc.cidr_block.apply(lambda cidr: do_thing(cidr))
note that this itself returns an
Output[T]
where
T
is the return type of
do_thing
s
thanks, so i think I get it now but it just isn’t working as I expect/desire. I gave up on that but have another instance where this is not working. I’m passing
vpc.id.apply(lambda x: x)
to EC2 user data which writes the value to a file, but the object repr is getting written
it’s done through jinja2:
Copy code
return template.render(
            kops_name=kops_name,
            kops_state_store=f"s3://{kops_name}",
            vpc_cidr=self.vpc_cidr,
            vpc_id=self.vpc_id.apply(lambda f: f),
            vpc_name=self.vpc_name,
        )
that writes to a file on the host:
Copy code
cat > /etc/profile.d/envs.sh <<EOF
export KOPS_NAME="{{ kops_name }}" \
  KOPS_STATE_STORE="{{ kops_state_store }}" \
  VPC_CIDR="{{ vpc_cidr }}" \
  VPC_ID="{{ vpc_id }}" \
  VPC_NAME="{{ vpc_name }}"
EOF
and the file:
Copy code
root@ip-10-2-0-17:/etc/profile.d# cat envs.sh
export KOPS_NAME="foo.k8s.local"   KOPS_STATE_STORE="s3://<bucket>"   VPC_CIDR="10.2.0.0/20"   VPC_ID="<pulumi.output.Output object at 0x10f621e80>"   VPC_NAME="foo"
f
The way to think about outputs is that you’ll never get back the underlying type - you’ll always get back an output. Outputs are like promises or futures, you always get another promise/future — which makes sense, b/c you don’t know when the value will be known, so everything is done asynchronously. So in the case of rendering a template, you want the render to happen within your apply.
s
oh, okay, so if I wanted to pass multiple outputs would I want to use
Output.all([x,y]).apply(fn: template.render(whatever))
i’ll try that
f
Exactly
That will in return give you back an
Output
which you can then pass to the constructor of a resource
(or stack output)
s
that worked! thank you, finally I think it makes sense