Управление конфигурациями для разных сред

Я поговорил с несколькими людьми на работе, и мы не смогли прийти к какому-то выводу.
Мы столкнулись с дилеммой: как управлять разными значениями конфигурации для разных сред?

Мы придумали несколько вариантов, но ни один из них нас не удовлетворил:
- Отдельные файлы конфигурации (например, config.test, config.prod и т. д.) и наличие файла, указывающего на выбранный (например, в ~/env), или переменная среды, указывающая на нее.
 – Использование одной БД для хранения всех конфигураций (вы запрашиваете ее в своей среде и получаете соответствующие значения конфигурации)
 – Создание файлов конфигурации при развертывании (с использованием системы CI/CD, например Атласский бамбук)

Какой вариант используется чаще? Есть ли лучший способ?
Следует ли хранить файл конфигурации в репозитории git вместе с остальным кодом? Наши системы написаны на питоне (как 2.7, так и 3).




Ответы (5)


Вы можете поместить всю эту конфигурацию в один файл конфигурации 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"

в переменной окружения набора оболочек, например

APP_SETTINGS = config.DevelopmentConfig

В вашем основном приложении app.py загрузите эту переменную среды (например, приложение flask)

from flask import Flask
import os

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

Я надеюсь, что это может помочь

person PKD    schedule 30.05.2018

Обычно не рекомендуется передавать параметры конфигурации в систему управления версиями, особенно если эти параметры включают пароли или другие секреты. Я предпочитаю использовать переменные среды для передачи этих значений в программу. Самый гибкий способ, который я нашел, - это использовать модуль argparse и использовать переменные среды в качестве значений по умолчанию. Таким образом, вы можете переопределить переменные среды в командной строке. Однако будьте осторожны с вводом паролей в командную строку, потому что другие пользователи, вероятно, увидят ваши аргументы командной строки в списке процессов.

Вот пример, в котором используются argparse и среда переменные:

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

Установка этих переменных среды может быть немного запутанной, особенно для системных служб. Если вы используете systemd, загляните в службу. , и будьте осторожны, чтобы использовать EnvironmentFile вместо Environment для любых секретов. Environment значений может просматривать любой пользователь с systemctl show.

Обычно я делаю значения по умолчанию полезными для разработчика, работающего на своей рабочей станции, чтобы он мог начать разработку без изменения какой-либо конфигурации.

Другой вариант — поместить параметры конфигурации в файл settings.py и просто быть осторожным, чтобы не зафиксировать этот файл в системе управления версиями. Я часто коммитил файл settings_template.py, который пользователи могут копировать.

person Don Kirkby    schedule 13.06.2018

Один из подходов состоит в том, чтобы написать «шаблон» для каждого типа файла конфигурации, где шаблон содержит в основном простой текст, но с несколькими заполнителями. Вот пример файла конфигурации шаблона с использованием нотации ${foo} для обозначения заполнителя.

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

Если вы сделаете это для всех файлов конфигурации, используемых вашим приложением, то вы, вероятно, обнаружите, что выполнение глобального поиска и замены в файлах конфигурации шаблона со значениями для относительно небольшого числа заполнителей даст готовый к использованию файл. запускать файлы конфигурации для конкретного развертывания. Если вы ищете простой способ выполнения глобального поиска и замены заполнителей в файлах шаблонов и хорошо разбираетесь в Java, возможно, вам стоит рассмотреть Скорость Apache. Но я полагаю, что было бы тривиально разработать аналогичную функциональность в Python.

person Ciaran McHale    schedule 31.05.2018

В итоге мы использовали метод, аналогичный этому one. У нас был базовый файл настроек и специфичные для среды файлы, которые просто импортировали все из базового файла base.py:

SAMPLE_CONFIG_VARIABLE = SAMPLE_CONFIG_VALUE

прод.py:

from base.py import *

Итак, все, что нам нужно было сделать при доступе к значениям из конфигурации, — это прочитать переменную среды и создать соответствующий ей файл.

person Dor Shinar    schedule 19.01.2019

Если мы используем 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

Вышеупомянутый метод является моим предпочтительным способом. Этот метод основан на рекомендациях, описанных здесь с небольшими изменениями, такими как имя файла на основе переменной среды.

Но есть и другие варианты

person Sairam Krish    schedule 03.02.2020