Couple of questions around the <new> `StackReferen...
# python
d
Couple of questions around the new
StackReference.get_output_details
• How do we call it in our stacks? The method is async. • How come our code needs to care if an output is secret or not? (interface has both
value
and
secret_value
e
• How do we call it in our stacks? The method is async.
Ah 🤦 I'll raise an issue about that, all the other SDKs support async calls in the program but I don't think we have a great way to do this in python yet (short of the user nesting the whole program in an asyncio.run call)
How come our code needs to care if an output is secret or not?
Because you may want to change behaviour based on it being secret or not, more importantly we didn't want people to inadvertently leak secret values because they just didn't think about that the values could be secrets.
d
It's rare I see actual code referencing config/stackreferences directly; aliasing them to globals or a config namespace instead. Them being Stackreferences complicates it, too, as Stack B now needs to know whether Stack A is exporting a secret. The Stacks may not be part of the same package, or codebase, meaning co-ordinated updates are needed.
I see this becoming common practice:
Copy code
# config.py
def get_output_details(stack, name):
  from pulumi.runtime.sync_await import _sync_await
  d = _sync_await(
    stack.get_output_details(name)
  )
  return d.value if d.value is not None else d.secret_value
e
Yes, I suspect your right there. It's tricky trying to build something "just does the right thing" and "is easy to use". People want "plain" values, just str or int so they can work with them easier. But they also want secrets correctly tracked so they don't get leaked, but plain values can't track that.
d
It's a tough one, yeah. Heard a few people say they use (or consider using) Pulumi purely for the Secrets support
regarding async; Jupyter (bits anyway) is moving toward being async-first, and wrapping sync functions up. example. Could be a nice pattern to adopt for the public API:
Copy code
def async_get_output_details(self, ...): ...
get_output_details = run_sync(async_get_output_details)
e
Yeh that sounds reasonable