Hi! I’m getting started creating a dynamic resourc...
# getting-started
a
Hi! I’m getting started creating a dynamic resource provider in python and I have a couple of questions. • It seems that it isn't possible to access config secrets/values from within the dynamic resource provider. Is that correct? • For the id of the resource being made, is it better to use the name of the resource, something like a UUID created by the cloud provider, or is there some other best practice? Thank you!
l
Yes, the provider should work exclusively with its own constructor options, and the properties of resources it manages. It is up to the developer of the project to get values out of stack config and pass it to one of those two places. The main requirement of the ID is that resource type + ID is unique in the stack, as that combination is the primary lookup key. Where there is an ID available from the cloud provider that meets that requirement, you should use it. Otherwise, it looks like the name is the most common value used for the ID; e.g. for ComponentResources. Sometimes the ID is pretty much random, e.g. for Security Group Rules.
a
Thank you for the answers!
Quick follow-up question. Which method would you suggest I use to provide things like cloud provider url/secrets to the resources?
l
Can you provide a quick example? Presumably you're not passing passwords into resources...
a
Absolutely! A very general example would be a dynamic resource provider that will manage objects in the cloud provider's application via a REST API. What would be the best practice for the dynamic resource provider to obtain the base URL and an API token (ideally would be a secret in the stack config file) to make those requests?
l
The implementations of https://www.pulumi.com/registry/packages/aws/api-docs/secretsmanager/secretversion/ and https://www.pulumi.com/registry/packages/aws/api-docs/ssm/parameter/ both have secret parameters. They take Inputs, which can be plain strings, or Outputs<string>s that are or are not marked secret. Their outputs are always Output<string> marked secret. That seems reasonable, though the values are available unencrypted to the developer. Which might not be what you want.
Ah, that's different.
Since the resources never get those values.
a
where at the beginning of the code block there is
auth *=* "<auth token>"
l
Base URLs, API keys and similar are relevant only to the provider, never to the resoruces.
So my previous answer isn't relevant.
a
ah, I think I'm still getting used to the provider/resource terminology so I may be using them incorrectly, muddying things a bit (not helping matters)
l
Passing a token into a provider implementation is as simple as setting it in the normal way. Consider the AWS provider's aws:secretKey property: https://www.pulumi.com/registry/packages/aws/api-docs/provider/#secretkey_nodejs
It's just passed in. It's up to your implementation to retain it securely.
It would be reasonable to set it as a secret in the stack config, have the project use
requireSecret
to get it, and then just pass it to the provider constructor.
a
oooooh, I think this is what I was missing!
l
Theoretically, the project developer could mess up and store the API key in plain text in code, and check it into a public GitHub repo. But that's not your provider's problem.
a
right
so, to make sure I understand, I should write a new overarching provider that the other resourceproviders will utilize?
l
Just make sure that the property you put that value in in your provider is either encrypted or marked as a secret output. Pulumi stacks your provider's properties in the stack, and they can be read when the stack is exported.
No, no need for that.
You have one resource provider. You construct it, and it retains creds, addresses, etc. It is passed to the constructor of all the resources it manages.
The resources don't need that information.
a
ah right
l
Are you certain that you need a dynamic provider? Is this for an API that's not currently supported by Pulumi?
a
correct, this is not supported by pulumi, rolling my own manager for these resources
l
Ok that's right. In many cases, one provider should be enough for many resource types, assuming they share related APIs under a common root.
a
ooooh, interesting
so
okay, I think I need to noodle on this. I have enough to do some damage on the problem and can prooobably get there. I may be back, asking a follow-up clarification question or two :)
this has been very helpful. thank you!
l
I've been re-reading the examples on dynamic providers and I see that none of them use overloaded create()s. So it's probably best to use a single dynamic provider per resource type initially. So your idea of sharing creds via a "super-provider" isn't a bad idea, though that wouldn't be an actual provider, it'd just be an object storing those creds.
I've never tried a dynamic provider that has multiple create methods, so I don't know that it works, that's an assumption on my part.
a
ah, I would assume not, yeah
l
I wouldn't assume not.. I'd just avoid it while getting things working 🙂 I think overloads should work.. it'd be nice if they did!
a
At face value, how would you go about getting that data into the dynamic resource provider?
l
Well the API is yours to control 🙂 I'd probably export an interface of reusable values (baseUrl and apiKey), and define
pulumi.dynamic.ResourceProvider
classes which would would all have constructor arg interfaces that extend that one.
None of the examples have providers that have properties, which is so weird.
a
yeah, feels a little bit like a blind spot
has an example with
_MyResourceProviderInputs
l
Which language are you looking at?
a
python
l
I don't see an example in there that uses the input property of the provider.
a
ahhhh, yeah
l
The GitHub labels API example should but it doesn't, it uses a file constant.
Such a cheap dodge.
I can't read Python that well, but I'm guessing that if the auth value was passed into the provider constructor, then it would be available in the create() method via the self parameter?
If so, that's the way I'd go.
a
I would assume so, too
I'd imagine I'd need to do that for every resource
l
No, just for every provider.
So once per resource type, not resource.
a
oh interesting
l
And maybe you could rationalize that later, if overloaded create() methods do work.
a
I haven't seen any examples with constructing providers specifically in python
or rather constructing `ResourceProvider`s
l
Just put an init and some proerties in the GitHub Label example, hopefully that'd be it.
a
ooooh
I'll take a stab
thank you!