2009-09-10 5 views
23

Je cherchais une meilleure façon de traiter les paramètres spécifiques au site (dans ce cas, le fichier django settings.py). La structure et les champs settings.py sont relativement cohérents, mais les valeurs diffèrent entre les zones du développeur, l'intégration, le contrôle qualité, les tests et les environnements de production.Gérez élégamment les paramètres/configurations spécifiques au site dans svn/hg/git/etc?

Quelle est la manière élégante de contrôler la source des paramètres tout en permettant des changements entre les différentes boîtes? Je suis également préoccupé par les données sensibles (par exemple, les mots de passe de base de données) dans le contrôle de la source, mais je veux des déploiements automatisés.

Des exemples de ce que nous avons utilisé:

  • settings.py définit les valeurs communes charge alors un fichier de paramètres secondaires en fonction du nom d'hôte ou le nom d'utilisateur.

  • d'injecter des valeurs dans le fichier settings.py à l'aide d'un script de déploiement. Mais cela déplace simplement le problème vers la gestion des scripts de déploiement au lieu du script settings.py.

Quelqu'un a une approche particulièrement élégante?

+0

Voyez aussi cette bonne réponse ici qui utilise les identifiants de connexion actuels pour différencier les paramètres spécifiques (mais les a tous dans le contrôle de version): http://stackoverflow.com/questions/6009/how-do-you-deal- avec-configuration-files-in-source-control/65226 # 65226 –

Répondre

18

Créer un fichier principal settings.py, qui devrait comprendre ceci:

# 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 

Maintenant, vous créez un nouveau fichier de paramètres pour chaque nom d'hôte que vous aimez. Mais ceux-ci sont vraiment petits. Chacun de votre dossier de serveur de production ne contient que:

from myproject.settings.production import * 

et vos serveurs de stockage intermédiaire ont:

from myproject.settings.staging import * 

Maintenant, vous pouvez créer un fichier production.py avec des remplacements de production pour les réglages, un staging.py et bientôt. Vous pouvez créer de nouveaux fichiers pour chaque rôle joué par un serveur.

Enfin, vous pouvez créer un fichier local.py sur une machine (y compris les machines des développeurs) avec les remplacements locaux et marquer ce fichier comme ignoré par le contrôle de la source, de sorte que les changements ne sont pas vérifiées dans.

Nous utilisons cette structure depuis des années, cela fonctionne très bien.

+0

Merci Ned. Mettez-vous les fichiers de paramètres spécifiques au site dans le contrôle de la source? Je suis inquiet d'avoir des mots de passe dans les fichiers de paramètres dans le contrôle de la source. – Parand

+0

Nous mettons tout sauf local.py dans le contrôle de la source. Je n'ai pas de solution pour le problème de mot de passe. –

+3

Cela semble être une bonne approche, mais j'ai du mal à comprendre la structure de votre répertoire. Avez-vous un settings.py ainsi qu'un répertoire/package de paramètres? Si oui, comment évitez-vous de nommer les conflits? (Désolé si c'est vraiment évident). – donturner

4

+1 pour la réponse de Ned, mais je veux mentionner une légère variation.

Je vois les paramètres de Django comme relevant de 2 zones: projet et instance.

Les paramètres de projet sont communs à toutes les instances (développement, test, production, plusieurs sites en production) et les paramètres d'instance sont locaux uniquement pour cette instance de serveur spécifique.

paramètres du projet sont des choses comme INSTALLED_APPS (bien que les paramètres locaux peuvent également inclure cette option pour ajouter des choses comme la barre d'outils de débogage pour les développeurs django), MIDDLEWARE_CLASSES et TEMPLATE_LOADERS. Les paramètres d'instance sont des éléments tels que les paramètres de la base de données, les paramètres MEDIA_URL, etc.

Les paramètres du projet vont dans settings.py et les paramètres d'instance dans local_settings.py, qui est importé dans settings.py. local_settings.py est répertorié dans .gitignore et les paramètres du projet sont stockés dans git.

J'ai essayé plusieurs autres variantes à ce sujet mais cela s'est terminé ici parce que c'est tellement plus simple.

La seule fois que je n'aime pas cette configuration est pour plusieurs sites (en utilisant des sites Django cadre), qui finissent par proliférer dans des choses comme sitename_settings.py qui importe sitename_local_settings.py etc.

Enfin, je garde un local_settings_template.py en git, à utiliser comme point de départ pour de nouvelles instances et pour que les développeurs puissent suivre les modifications qu'ils pourraient avoir besoin de leurs propres paramètres locaux.

0

La façon dont je gère cela est d'avoir un fichier settings.py de base, puis un fichier de paramètres pour chaque environnement (par exemple dev_settings.py, live_settings.py)

En haut de chaque environnement fichier spécifique je

from settings import * 

Je peux alors remplacer simplement les paramètres que je dois changer sur un environnement de base spécifique

pour assurer que chaque environnement utilise les paramètres corrects je modifie simplement la variable d'environnement DJANGO_SETTINGS_MODULE. Comment vous faites cela dépend comment vous déployez django (mod_wsgi, mod_python et ainsi de suite ...)

3

Permet de séparer ces deux problèmes distincts: 1) la gestion des paramètres spécifiques au site et 2) la gestion des secrets.

1) paramètres spécifiques au site

tout version (à l'exception des secrets), les paramètres spécifiques au même développeur. Avec Django et beaucoup d'autres logiciels, le fichier de configuration est un morceau de code exécutable, ce qui facilite le chargement des paramètres de configuration courants et remplace tout ce qui doit être surchargé. De cette façon, vous pouvez rester DRY.

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

Alors maintenant, vous avez settings_base.py, settings_prod.py, settings_dev.py, settings_developper_john.py, etc. Comment pouvez-vous dire que l'on Django à utiliser? Le déploiement du fichier de paramètres approprié sur le serveur est une tâche pour le script de déploiement, je crois. Le script de déploiement saura que vous déployez pour héberger prod17 qui est un serveur de production, de sorte qu'il générerait à la volée un fichier settings.py qui ressemblerait à ceci:

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

Une autre solution est d'avoir cette logique dans un générique settings.py: il pourrait lire une variable d'environnement ou d'obtenir le nom d'hôte (ou appliquer toute autre logique) et charger le module de paramètres appropriés:

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

Ma solution préférée pour les paramètres Django est described here.Pour tout autre logiciel moins flexible avec son fichier de configuration, la meilleure option est probablement de faire en sorte que le script de déploiement génère le fichier de configuration, éventuellement en utilisant des modèles (des outils comme Chef ou Puppet facilitent cela). Cela vous permet de rester DRY: par exemple, un logiciel nécessite un fichier config.ini plat, puis le script de déploiement peut lire un fichier common.ini et un fichier production.ini, les mélanger ensemble de manière appropriée et produire un config.ini prêt à être déployé en production.

secrets Gestion

Tout d'abord, ne pas stocker vos mots de passe dans un système de contrôle de version. :-)

Une solution pour gérer les secrets est de faire en sorte que le script de déploiement transfère les secrets. Par exemple, Bob est responsable du déploiement des applications Web, il connaît le mot de passe de la base de données, donc quand il lance le script de déploiement, il est invité à entrer le mot de passe de la base de données et le script le transfère au serveur. Ou le script de déploiement lit simplement le mot de passe dans un fichier sur l'ordinateur de Bob et le transfère. C'est probablement la solution la plus courante. C'est bien dans la plupart des cas.

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

Si vous avez besoin d'automatiser la création de machines virtuelles et que vous ne voulez pas le deployer automatisé de connaître un secret, vous pouvez inclure les secrets de la VM-image. Bien sûr, quelqu'un doit inclure les secrets dans l'image VM en premier lieu. Le problème avec cette solution est que vous avez besoin de générer une nouvelle image de VM chaque fois qu'un secret change. Si vous voulez éviter cela, alors vous pourriez vouloir un "serveur secret": un serveur pour gérer les secrets de tous les autres serveurs. Ensuite, le seul secret que vous devez inclure dans l'image VM est le secret bootstrap nécessaire pour se connecter au "serveur secret".

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 

Par exemple, le serveur secret, pourrait être un serveur chef, les secrets pourraient être stocker dans des sacs de données cryptées, et le secret d'amorçage serait la clé pour déchiffrer ces sacs.

Questions connexes