Подтвердить что ты не робот

Элегантно обрабатывать настройки/настройки сайта в svn/hg/git/etc?

Я искал лучший способ справиться с настройками для сайта (в данном случае, файл django settings.py).

Структура и поля settings.py довольно согласованы, но значения различаются между полями разработчика, интеграцией, QA, тестированием и производственными средами.

Каков элегантный способ управления параметрами, сохраняя при этом изменения между разными полями?

Я также обеспокоен наличием конфиденциальных данных (например, паролей базы данных) в исходном управлении, но мне нужны автоматические развертывания.

Примеры того, что мы использовали:

  • settings.py устанавливает общие значения, затем загружает дополнительный файл настроек на основе имени хоста или имени пользователя.

  • ввод значений в файл settings.py с помощью развертывания script. Но это просто переносит проблему на управление сценариями развертывания вместо параметров settings.py script.

Кто-нибудь имеет особенно элегантный подход?

4b9b3361

Ответ 1

Создайте основной файл settings.py, который должен включать следующее:

# Pull in hostname-based changes.
import socket
HOSTNAME = socket.gethostname().lower().split('.')[0].replace('-','')

try:
    exec "from myproject.settings.host_%s import *" % HOSTNAME
except ImportError:
    pass

# Pull in the local changes.
try:
    from myproject.settings.local import *
except ImportError:
    pass

Теперь вы создаете новый файл настроек для каждого интересующего вас имени хоста. Но они очень маленькие. Каждый из файлов вашего рабочего сервера содержит:

from myproject.settings.production import *

а на ваших промежуточных серверах:

from myproject.settings.staging import *

Теперь вы можете создать файл production.py с производственными переопределениями для настроек, staging.py и т.д. Вы можете создавать новые файлы для каждой роли, которую играет сервер.

Наконец, вы можете создать файл local.py на любом компьютере (включая машины разработчиков) с локальными переопределениями и пометить этот файл как проигнорированный исходным элементом управления, чтобы изменения не попадали в него.

Мы использовали эту структуру в течение многих лет, она работает очень хорошо.

Ответ 2

+1 для ответа Ned, но хочу указать небольшое изменение.

Я вижу настройки Django как падающие на 2 области: проект и экземпляр.

Параметры проекта являются общими для всех экземпляров (dev, testing, production, multiple sites in production), а настройки экземпляра являются локальными только для определенного экземпляра сервера.

Настройки проекта такие, как INSTALLED_APPS (хотя локальные настройки также могут включать это, чтобы добавить такие вещи, как панель инструментов отладки django для разработчиков), MIDDLEWARE_CLASSES и TEMPLATE_LOADERS. Настройки экземпляра - это такие, как настройки базы данных, настройки MEDIA_URL и т.д.

Настройки проекта входят settings.py и параметры экземпляра в local_settings.py, которые импортируются в settings.py. local_settings.py указан в .gitignore, а настройки проекта хранятся в git.

Я попробовал несколько других вариантов этого, но закончился здесь, потому что это намного проще.

Единственный раз, когда мне не нравится эта настройка, - это несколько сайтов (с использованием платформы Django sites), которые в конечном итоге распространяются на такие вещи, как sitename_settings.py, который импортирует sitename_local_settings.py и т.д.

Наконец, я сохраняю local_settings_template.py в git, чтобы использовать в качестве отправной точки для новых экземпляров, а для разработчиков - отслеживать изменения, которые могут потребоваться для их локальных настроек.

Ответ 3

Позволяет разделить эти две различные проблемы: 1) управление настройками для сайта и 2) управление секретами.

1) Настройки для сайта

Версия все (кроме секретов), даже настройки для конкретного разработчика.

С Django и множеством других программных файлов конфигурационный файл представляет собой часть исполняемого кода, что упрощает загрузку общих параметров конфигурации и отменяет все, что необходимо переопределить. Таким образом, вы можете оставаться DRY.

# settings_prod.py
from settings_base import *
... # override whatever needs to be overridden for production environment

Итак, теперь у вас есть settings_base.py, settings_prod.py, settings_dev.py, settings_developper_john.py и т.д. Как вы скажете Django, какой из них использовать?

Развертывание соответствующего файла настроек на сервере является задачей для развертывания script, я считаю. Развертывание script будет знать, что вы развертываете для размещения prod17, который является производственным сервером, поэтому он будет генерировать на лету файл settings.py, который будет выглядеть следующим образом:

# settings.py (generated by deployment script)
from settings_prod import *

Другое решение состоит в том, чтобы иметь эту логику в общем settings.py: он мог читать переменную окружения или получать имя хоста (или применять любую другую логику) и загружать соответствующий модуль настроек:

# settings.py
import os
if os.environ["MY_APP_ENV"] == "prod":
    from settings_prod import *
elif ...

Мое любимое решение для настроек Django описано здесь.

Для любого другого программного обеспечения, которое не так гибко с ним связано с конфигурационным файлом, лучшим вариантом является, вероятно, развертывание script генерации файла конфигурации, возможно, с использованием шаблонов (такие инструменты, как Chef или Puppet, делают это проще). Это позволяет вам оставаться сухим: например, скажем, для программного обеспечения требуется плоский файл config.ini, тогда развертывание script может читать файл common.ini и production.ini, смешать их вместе и создать config.ini готовые к развертыванию в производство.

Управление секретами

Прежде всего, не храните свои пароли в системе управления версиями.: -)

Одним из решений для управления секретами является развертывание script передачи секретов. Например, bob отвечает за развертывание веб-приложений, он знает пароль для базы данных, поэтому, когда он запускает развертывание script, ему предлагается ввести пароль базы данных, а script передает его на сервер. Или развертывание script просто читает пароль в файле на компьютере bob и передает его. Это, вероятно, наиболее распространенное решение. Это нормально в большинстве случаев.

              secrets
deployer ================> server

Если вам нужно автоматизировать создание виртуальных машин, и вы не хотите, чтобы автоматизированный разработчик знал какой-либо секрет, вы можете включить секреты в VM-образ. Конечно, во-первых, кто-то должен включать секреты в образ VM.

                  VM image including secrets
human deployer -------------------------------+
                                              |
                                              |
                    image_name                v
automated deployer ==============> Cloud Service ========> VM including secrets

Проблема с этим решением заключается в том, что вам нужно генерировать новый образ VM каждый раз, когда какие-либо секретные изменения. Если вы хотите этого избежать, тогда вам может понадобиться "секретный сервер": сервер для управления всеми другими секретами сервера. Тогда единственный секрет, который вам нужно включить в образ VM, - это секрет бутстрапа, необходимый для подключения к "секретному серверу".

step 1:

               VM image including bootstrap secret
human deployer -----------------------------------+
                                                  |
                                                  |
                    image_name                    v
automated deployer ==================> Cloud Service ========> VM including secrets


step 2:

    bootstrap secret
   ==================>
VM                     Secret Server
   <==================
         secrets

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

Ответ 4

То, как я обрабатываю это, - это иметь базовый файл settings.py, а затем файл настроек для каждой среды (например, dev_settings.py, live_settings.py)

В верхней части каждого конкретного файла среды у меня есть

from settings import *

Я могу просто переопределить любые настройки, которые мне нужно изменить на основе среды

Чтобы каждая среда использовала правильные настройки, я просто изменяю переменную среды DJANGO_SETTINGS_MODULE. Как вы это делаете, зависит от того, как вы развертываете django (mod_wsgi, mod_python и т.д.)