14

我想保留development.iniproduction.ini接受版本控制,但出于安全原因,不希望sqlalchemy.url存储连接字符串,因为这将包含用于数据库连接的用户名和密码。

在 Pyramid 中,从其他外部文件获取此设置的规范方式是什么?

编辑 除了使用环境变量的解决方案之外,我在#pyramid 上询问后提出了这个解决方案:

def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
# Read db password from config file outside of version control
secret_cfg = ConfigParser()
secret_cfg.read(settings['secrets'])
dbpass = secret_cfg.get("secrets", "dbpass")
settings['sqlalchemy.url'] = settings['connstr'] % (dbpass,)
4

3 回答 3

26

我对此进行了很多研究,并尝试了很多不同的方法。但是,Pyramid 非常灵活,.ini配置解析器为您做的事情是如此之少,以至于似乎没有一个事实上的答案。

在我的场景中,我production.example.ini首先尝试在生产服务器上复制并填写详细信息的版本控制,但这很麻烦,因为示例的更新没有被翻译成副本,所以副本有随时更改时重新创建。另外,我开始使用 Heroku,所以不在版本控制中的文件永远不会进入部署。

然后是加密配置方法。其中,我不喜欢范式。想象一个系统管理员负责维护生产环境,但是如果不通过版本控制将其运行回来,他或她就无法更改数据库的位置或特定于环境的设置。尽可能多地将环境和代码分开真的很好,这样这些更改就可以在没有版本控制修订的情况下即时进行。

我的最终解决方案是有一些看起来像这样的值:

[app:main]

sqlalchemy.url = ${SQLALCHEMY_URL}

然后,在生产服务器上,我将环境变量设置SQLALCHEMY_URL为指向数据库。这甚至允许我使用相同的配置文件进行登台和生产,这很好。

在我的 Pyramid init 中,我只是使用以下方法扩展了环境变量值os.path.expandvars

sqlalchemy_url = os.path.expandvars(settings.get('sqlalchemy.url'))
engine = create_engine(sqlalchemy_url)

而且,如果您想使用它并自动替换设置字典中的所有环境变量,我为我的项目制作了这个小助手方法:

def expandvars_dict(settings):
    """Expands all environment variables in a settings dictionary."""
    return dict((key, os.path.expandvars(value)) for
                key, value in settings.iteritems())

main在您的应用入口点中像这样使用它:

settings = expandvars_dict(settings)
于 2013-05-08T17:17:33.237 回答
1

Pyramid 中单独的 ini 文件的全部意义在于您不必对所有这些文件进行版本控制,并且它们可以包含针对不同场景(开发/生产/测试)的不同设置。您的 production.ini 几乎总是不应该与您的源代码在同一个 VCS 中。

于 2013-05-08T14:54:38.327 回答
0

我发现这种方式可以从额外的配置和环境中加载秘密。

from pyramid.config import Configurator
from paste.deploy import appconfig
from os import path

__all__ = [ "main" ]


def _load_secrets(global_config, settings):
    """ Helper to load secrets from a secrets config and
        from env (in that order).
    """
    if "drawstack.secrets" in settings:
        secrets_config = appconfig('config:' + settings["drawstack.secrets"],
                                    relative_to=path.dirname(global_config['__file__']))

        for k, v in secrets_config.items():
            if k == "here" or k == "__file__":
                continue
            settings[k] = v

    if "ENV_DB_URL" in global_config:
        settings["sqlalchemy.url"] = global_config["ENV_DB_URL"]


def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """

    _load_secrets(global_config, settings)

    config = Configurator(settings=settings)
    config.include('pyramid_jinja2')
    config.include('.models')
    config.include('.routes')
    config.scan()
    return config.make_wsgi_app()

上面的代码将从配置键的值加载任何变量drawstack.secrets,然后尝试DB_URL从环境加载。

drawstack.secrets可以相对于原始配置文件或绝对。

于 2018-02-14T00:52:12.257 回答