kinto icon indicating copy to clipboard operation
kinto copied to clipboard

Kinto plugins settings can't be loaded using ENV variable

Open Natim opened this issue 7 years ago • 10 comments

During the initialization phase, we are checking for each Kinto default settings if any env variable are defined.

https://github.com/Kinto/kinto/blob/master/kinto/core/initialization.py#L512-L514

However it only works for kinto default settings, I believe it doesn't for plugin's settings.

Natim avatar Mar 21 '18 08:03 Natim

We iterate on the settings defined in the .ini + the defaults:

https://github.com/Kinto/kinto/blob/86a9943b428b8e7fab53190bf840222f5c833225/kinto/core/initialization.py#L480-L497

What would we be your suggestion?

Note that the plugin include happens after the initialization phase:

https://github.com/Kinto/kinto/blob/86a9943b428b8e7fab53190bf840222f5c833225/kinto/core/init.py#L202-L205

leplatrem avatar Mar 21 '18 09:03 leplatrem

Does it means that if we want to override a value with ENV variables we need to define it with a wrong value in the ini file?

Natim avatar Mar 21 '18 09:03 Natim

According to my understanding of the code, it seems like a workaround yes

leplatrem avatar Mar 21 '18 23:03 leplatrem

Unless we add a helper like request.get_setting("key", 128) and use it instead of request.registry.settings.get() I don't see how we could fix this.

leplatrem avatar Mar 24 '18 20:03 leplatrem

This might be a stupid question, but why? Can't we just iterate over everything in sys.env and look for things that seem like they could be settings?

glasserc avatar Apr 06 '18 02:04 glasserc

Ok, we can add an additional initialization step that does that.

But I think the input list should be settings names because I'm not sure we can reverse (SIGNER_CID_PATH should be signer.cid.path or signer_cid.path?)

leplatrem avatar Apr 06 '18 07:04 leplatrem

I like the idea of a helper like request.config() with options similar to python-decouple

leplatrem avatar Apr 20 '18 08:04 leplatrem

config.kinto_setting("mail.host", default="localhost")
config.kinto_setting("mail.port", cast=int, default=25)
config.kinto_setting("mail.password", env="PASSWD")

See an example of how to add a config method.

See loading of default settings

leplatrem avatar Nov 30 '20 22:11 leplatrem

In core/__init__.py, add a kinto_setting directive with something like that:

def kinto_setting(config, name, default=None, cast=None, env=None):
    config.registry.kinto_settings[name] = {
        "default": default,
        "cast": cast,
        "env": env or name.upper(),
    }

config.add_directive("kinto_setting", kinto_setting)

And then in load_default_settings(config, default_settings), read these info from config.registry.kinto_settings to enhance/process the config.settings values that come from the .ini file.

leplatrem avatar Dec 11 '20 14:12 leplatrem

Depending on the order of things at startup (whether load_default_settings() or config.kinto_setting("mail.host") is called first), it could be relevant to enhance the config.settings from the kinto_setting() directive.

def kinto_setting(config, name, default=None, cast=None, env=None):
    enhanced = {}
    from_env = os.getenv(env or name.upper(), default)
    value = config.settings.get(name, from_env) 
    if cast:
        value = cast(value)
    enhanced[name] = value
    config.add_settings(enhanced)

leplatrem avatar Dec 11 '20 15:12 leplatrem