Target switching

Als ik start met het werken aan een website ga ik natuurlijk niet meteen aan de slag op de productie-server. Ik zet eerst een lokale omgeving op, met o.a. een nieuwe database en een nieuwe virtual host in het geval van een Apache server. Op het moment dat de site stabiel genoeg is om het daglicht te zien, zit ik dan altijd te knoeien met het aanpassen van de configuratie, zoals de locatie en login-gegevens van de database.

Om lokaal verder te kunnen ontwikkelen moet ik alles weer opnieuw aanpassen. Een mogelijke optie is om in een centrale file een variabele bij te houden, ENVIRONMENT, die dan kan gebruikt worden om, afhankelijk van de omgeving, de juiste code uit te voeren. Veel geprul en een hoopje if blocks die de code niet overzichtelijker maken.

Pants illustratie

Om m’n Python-skills wat te oefenen heb ik besloten om dit probleem op te lossen met een eenvoudig script: Pants.

Hoe Pants werkt

De websites waaraan ik werk, plaats ik steevast in de C:\web directory. Deze website vind ik dan terug onder C:\web\el73.be. Om mijn Wordpress-installatie ook op mijn computer te kunnen gebruiken heb ik een aparte database aangemaakt. Die database komt echter totaal niet overeen met de database op de echte el73.be server. De configuratie van Wordpress, in C:\web\el73.be\weblog\wp-config.php, moet dus worden aangepast naargelang de omgeving. De inhoud van wp-config.php ziet er standaard als volgt uit:


define('DB_NAME', 'wordpress');    // The name of the database
define('DB_USER', 'username');     // Your MySQL username
define('DB_PASSWORD', 'password'); // ...and password
define('DB_HOST', 'localhost');    // 99% chance you won't need to change this value

// Meer...

Stap 1: templates

Ik kopieer de configuratie naar C:\web\el73.be_template\weblog\wp-config.php en vervang de database gegevens:


define('DB_NAME', '@db.name@');    // The name of the database
define('DB_USER', '@db.user@');     // Your MySQL username
define('DB_PASSWORD', '@db.password@'); // ...and password
define('DB_HOST', '@db.host@');    // 99% chance you won't need to change this value

// Meer...

Stap 2: de waarden van de parameters

In C:\web\el73.be_params maak ik vervolgens 2 files, local.properties en prod.properties, eentje voor elke omgeving.

De lokale zou er als volgt kunnen uitzien:


db.name=el73
db.user=root
db.password=rootpassword
db.host=localhost

De andere zou er als volgt kunnen uitzien:


db.name=prod_el73
db.user=prod_el73_user
db.password=prod_el73_password
db.host=mysql.el73.be

Stap 3: target switching

Als ik lokaal wil werken run ik dan het script met als parameters C:\web\el73.be en local. Pants zal de files uit de template directory gaan kopiëren naar de gegeven directory en de waarden uit de C:\web\el73.be_params\local.properties file gaan gebruiken om de parameters in de template te vervangen.

De template en parameters directories moeten op hetzelfde niveau staan als de target directory en eindigen in _template, respectievelijk _params. De properties file mag eender welke naam krijgen, zolang die maar eindigt in .properties. ammehoela.properties is dus perfect mogelijk, je moet het script dan enkel aanroepen met als parameters je target directory en ammehoela.

Om te switchen naar de productie-omgeving van el73.be, moet ik gewoon het volgende doen:

C:\>pants.py C:\web\el73.be prod

En zo worden de database-gegevens voor de productie-omgeving ingevuld in C:\web\el73.be\weblog\wp-config.php.

Voor de geïnteresseerden: Pants is beschikbaar voor download (4 KB). No warranty, doe ermee wat je wilt, etc.

Dit artikel werd opgenomen in ontwikkeling, software.


6 reacties

  1. Avatar van Bart Bart 27 Mar 2007 08:46

    Ik ontwikkel altijd op een live omgeving. Bespaart tijd en configwerk. Lokaal een gelijkaardige config installeren is nagenoeg onmogelijk.

  2. Avatar van Bramus! Bramus! 27 Mar 2007 22:53

    hier gebeurt het met een simpele php check (op voorwaarde dat het PHP sites zijn uiteraard) op de $_SERVER[’SERVER_NAME’] variabele:

    $localArray = Array("localhost","testserv.foo");

    if (in_array($_SERVER['SERVER_NAME'], $localArray)) {
    // defines voor test-omgeving hier
    } else {
    // defines voor live-omgeving hier
    }

    Site zal zelf zo slim genoeg zijn (op mijn aangeven dan) om op de live omgeving naar de live db te connecten en mailserver X te gebruiken en op de testomgeving naar de testdb te connecten en mailserver Y te gebruiken … works like a charm :)

  3. Avatar van Kevin Kevin 28 Mar 2007 09:37

    Bart: fair enough, voor el73.be. Maar ik zou enkele mensen ernstige nachtmerries bezorgen als ik dat op een echte productie-omgeving zou gaan doen. ;)

    Bramus!: het zijn net die if-testen die ik wil vermijden met dit script (hoewel het meer ging om het uitproberen van Python dan het maken van iets nuttigs).

  4. Avatar van Jeroen Jeroen 06 Apr 2007 14:48

    JAmmer dat ik het niet werkend kreeg onder ubuntu en op m’n mac :(

  5. Avatar van Jeroen Jeroen 11 Apr 2007 18:44

    Ik vermoed dat het bij mij te maken had met “verouderde” versie van python.
    Als ik op regel 97 de code

    (property, x, value) = param.partition(’=')

    aanpas naar

    (property, value) = param.split(’=')

    dan werkt het wel :)

    Python gaf voorheen met .partition deze foutmelding: AttributeError: ’str’ object has no attribute ‘partition’

  6. Avatar van Kevin Kevin 11 Apr 2007 18:56

    Dat zou best kunnen. Ik gebruik Python 2.5 en heb het nog niet getest op m’n Linux-installatie. Bedankt om het te laten weten :)