little-market-63455
07/22/2021, 12:41 PMaws:someProperty: 'a'
aws:somethingElse: 'b'
vs.
aws:
someProperty: 'a'
somethingElse: 'b'
I feel this helps clear the confusion, at least mine, around reading nested configs and allows you to fold/unfold related options
Something also related to this, why isn't the configuration key types inferred from the config file rather than specified explicitly. As in why requireString()
and requireObject()
and so on instead of just require()
and get
. I feel the config file already all has the type and secret semantics that you need for that?bored-oyster-3147
07/22/2021, 9:36 PMrequire()
and get()
, how would that work in strongly typed languages? what would those methods return?getBoolean()
and know that a boolean
is returned?
or would you rather have a generic result returned from a get()
method and then have to do your own type checking to ensure that the result is the boolean
you expect?getX
and requireX
methods results in a much cleaner API + much more intuitive usage for the consumeraws:someProperty: 'a'
is equivalent to this:
aws:
someProperty: 'a'
So you very well could write your file like that if you wanted, that just happens to not be the way that Pulumi writes the config when it writes to that file, so it would probably get overwritten the next time Pulumi serialized your config.
I'm not 100% certain on those being equivalent though, YAML is weirdhandsome-state-59775
07/23/2021, 5:47 AMgreat-sunset-355
07/23/2021, 8:43 AMproject
eg:
config:
project:key: value
project:another:
nested: value
project:different:
nested_different:
- 1
- 2
- 3
# returns value
value = cfg.require('key')
# returns {"nested": value"}
another = cfg.require_object('another')
# fails to find `project:another.nested: value
another_value = cfg.require('another.nested')
I'd recommend playing around with config but in general, if you want nested config you'll have to do with get_object
little-market-63455
07/23/2021, 8:50 AMgreat-sunset-355
07/23/2021, 9:32 AMlittle-market-63455
07/23/2021, 10:01 AMnamespace:some-service-config:
normalProperty: a
anotherNormalProperty: b
secretProperty:
AdminEmail:
secure: some-encrypted-value
AdminPassword:
secure: another-encrypted-value
There is no way to read the secretProperty without reading the entire service-config
as secret
So you would be forced to do this:
namespace:some-service-config:
normalProperty: a
anotherNormalProperty: b
namespace:someSecretProperty:
AdminEmail:
secure: some-encrypted-value
AdminPassword:
secure: another-encrypted-value
bored-oyster-3147
07/23/2021, 12:39 PMlittle-market-63455
07/23/2021, 1:10 PMbored-oyster-3147
07/23/2021, 1:21 PMaws:
someProperty: 'a'
somethingElse: 'b'
I have called config.Get("aws")
What is the method signature of config.Get(...)
? You can't have a dynamic return type in .NET. So it must be some generic type ConfigResult
. This object would need to look something like:
class ConfigResult
{
ConfigType Type,
object? Value
}
Where ConfigType
is an enum that looks something like:
enum ConfigType
{
String,
Int16,
Int32,
Int64,
Boolean,
Object,
etc..
}
Ok so let's say we did our config.Get("aws")
call. This is an object. You're suggesting that they return a strong type.
AFAIK YAML has types so they could still give you type safety in typed languages by inferring the type from YAMLIn .NET that means they would have to use reflection to search all the available types that: • Matches the properties • Is accessible • Is constructible That is a really big ask and reflection has very poor performance, but let's say they accomplish it. Now your code looks like:
var config = new Pulumi.Config();
var awsConfigResult = config.Get("aws");
if (awsConfigResult.Type != ConfigType.Object)
throw SomeException();
if (awsConfigResult.Value is not AwsConfig awsConfig)
throw SomeException();
// now do work with awsConfig instance that is proper type
When if you had just provided the type to begin with, your code would remain:
var config = new Pulumi.Config();
var awsConfig = config.GetObject<AwsConfig>("aws");
No type searching required, no inference required, and cleaner consumer code.little-market-63455
07/23/2021, 1:35 PMrequireString()
and family of functions aren't really annoying me. It's mainly the namespace thing that does
My config file is just growing larger and larger and being able to fold/unfold and read the configuration for a specific component in one go is what makes it attractive for me. Mainly the secrets part
It's been a while that I have done some .NET but cannot you use generics to solve the problem. I am not saying it's easy but again I don't work for them and I don't know if this is the biggest deal.
So a normal get()
or require()
could return indeed a generic object
type by default and if you are interested in a typed option then you can provide the type as a generic parameter and Pulumi would just cast it as it is doing now with requireObject<T>
So basically:
• If you are interested in types then it's your responsibility as a consumer to specify that type and Pulumi does is cast
• If you are not interested in the type then you get a generic object
or any
in TypeScriptbored-oyster-3147
07/23/2021, 1:37 PMobject
you're still doing the defensive checking in your infra code when it could've been done in Pulumi. Meaning you would only use that overload for config that can be more than one type.Dictionary<string, string>
that has the keys someProperty
and somethingElse
great-sunset-355
07/26/2021, 9:24 AMsecretProperty:
AdminEmail:
secure: some-encrypted-value
AdminPassword:
secure: another-encrypted-value
but you must use get_secret_object
and then deal with the Output type or it is possible to get plain text values by get_object
.
IMO easiest way is to pass this responsibility from pulumi to pydantic and instantiate pydantic object instead
In another language I'd use the same approach and created my own config object instead of relying on pulumi.