管理不同环境的配置

时间:2018-05-30 17:55:55

标签: python configuration continuous-integration configuration-files continuous-deployment

我与一些工作人员进行过讨论,但我们无法得出结论。
我们面临着两难的局面 - 您如何管理不同环境的不同配置值?

我们提出了一些选择,但似乎没有一个让我们满意:
- 单独的配置文件(即config.testconfig.prod等),并有一个指向所选文件的文件(例如~/env),或指向它的环境变量。登记/> - 使用单个DB存储所有配置(您可以使用您的环境查询并获取相应的配置值)
- 在部署时创建配置文件(使用像Atlassian Bamboo这样的CI / CD系统)

哪种选择更广泛?还有更好的方法吗?
配置文件应该与其余代码一起保存在git存储库中吗? 我们的系统是用python编写的(2.7和3)

5 个答案:

答案 0 :(得分:1)

您可以将所有这些配置放在单个配置文件config.py中。

class Base():
    DEBUG = False
    TESTING = False

class DevelopmentConfig(Base):
    DEBUG = True
    DEVELOPMENT = True
    DATABASE_URI = "mysql+mysqldb://root:root@localhost/demo"

class TestingConfig(Base):
    DEBUG = False
    TESTING = True
    DATABASE_URI = "mysql+mysqldb://root:root@test_server_host_name/demo_test"

class ProductionConfig(Base):
    DEBUG = False
    TESTING = False
    DATABASE_URI = "mysql+mysqldb://root:root@prod_host_name/demo_prod"

在shell设置环境变量上,如

  

APP_SETTINGS = config.DevelopmentConfig

在主应用程序app.py中,加载此环境变量(例如flask应用程序)

from flask import Flask
import os

app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])

我希望这可以提供帮助

答案 1 :(得分:1)

将配置设置提交到源代码管理通常是一个坏主意,尤其是当这些设置包含密码或其他机密时。我更喜欢使用环境变量将这些值传递给程序。我发现最灵活的方法是使用Certificate Nickname Trust Attributes SSL,S/MIME,JAR/XPI DigiCert SHA2 Secure Server CA ,, DigiCert SHA2 Extended Validation Server CA ,, Google Internet Authority G3 ,, 模块,并使用环境变量作为默认值。这样,您可以在命令行上覆盖环境变量。但是要小心将密码放在命令行上,因为其他用户可能会在进程列表中看到您的命令行参数。

此处使用argparse的{​​{3}}和环境变量:

argparse

设置这些环境变量可能有点混乱,特别是对于系统服务。如果您正在使用systemd,请查看an example,并谨慎使用def parse_args(argv=None): parser = ArgumentParser(description='Watch the raw data folder for new runs.', formatter_class=ArgumentDefaultsHelpFormatter) parser.add_argument( '--kive_server', default=os.environ.get('MICALL_KIVE_SERVER', 'http://localhost:8000'), help='server to send runs to') parser.add_argument( '--kive_user', default=os.environ.get('MICALL_KIVE_USER', 'kive'), help='user name for Kive server') parser.add_argument( '--kive_password', default=SUPPRESS, help='password for Kive server (default not shown)') args = parser.parse_args(argv) if not hasattr(args, 'kive_password'): args.kive_password = os.environ.get('MICALL_KIVE_PASSWORD', 'kive') return args 代替EnvironmentFile获取任何机密信息。任何Environment用户都可以查看Environment个值。

我通常会将默认值设置为在其工作站上运行的开发人员,因此他们可以在不更改任何配置的情况下开始开发。

另一种选择是将配置设置放在systemctl show文件中,并且注意不要将该文件提交给源代码控制。我经常提交一个用户可以复制的settings.py文件。

答案 2 :(得分:0)

一种方法是编写一个"模板"对于每种配置文件,其中模板主要包含纯文本,但有一些占位符。下面是一个示例模板配置文件,使用符号${foo}表示占位符。

serverName  = "${serverName}"
listenPort  = "${serverPort}"
logDir      = "/data/logs/${serverName}";
idleTimeout = "5 minutes";
workingDir  = "/tmp";

如果对应用程序使用的所有配置文件执行此操作,那么您可能会发现使用相对较少数量的占位符对模板配置文件执行全局搜索和替换将会产生准备运行特定部署的配置文件。如果您正在寻找一种简单的方法来对模板文件中的占位符执行全局搜索和替换,并且熟悉Java,那么您可能需要考虑Apache Velocity。但我想在Python中开发类似功能将是微不足道的。

答案 3 :(得分:0)

我们最终使用了类似于此one的方法。 我们有一个基本设置文件,以及特定于环境的文件,这些文件仅导入了基本文件中的所有内容 base.py:

SAMPLE_CONFIG_VARIABLE = SAMPLE_CONFIG_VALUE

prod.py:

from base.py import *

因此,当从配置访问值时,我们要做的就是读取一个环境变量并创建与之对应的文件。

答案 4 :(得分:0)

如果我们使用flask,那么我们可以像这样进行环境特定的配置管理:

-- project folder structure

config/
   default.py
   production.py
   development.py
instance/
  config.py
myapp/
  __init__.py

在应用初始化期间,

# app/__init__.py

app = Flask(__name__, instance_relative_config=True)

# Load the default configuration
app.config.from_object('config.default')

# Load the configuration from the instance folder
app.config.from_pyfile('config.py')

# Load the file specific to environment based on ENV environment variable
# Variables defined here will override those in the default configuration
app.config.from_object('config.'+os.getenv("ENV"))

在运行应用程序时:

# start.sh
# ENV should match the file name    
ENV=production python run.py

以上方法是我的首选方法。此方法基于best practices described here,并做了一些修改,例如基于环境变量的文件名。

但是还有其他选择