Configuration Management is a requisite for medium or large projects, since you want to externalize all the config so that changes do not ripple when you modify any value. What does that mean? Let me break it down with an example of using Python with MongoDB.
Let’s take an example of connecting to MongoDB and getting 2 collections, let’s call it the Student collection and Teacher Collection. We shall have three types of config. One for the Mongo collection itself, and one each for the field names and collection names of the collection.
So what happens if we don’t/do have configuration Management? Well, a few things:
Suppose you decide to change the host name – since you are moving from testing to production onto a real server. You have to make the change of this host name in multiple locations. Suppose now you move it back into local for testing. Changes again.
If you externalize your config to a single location, you have to make changes only in a single place. It’s quick, and easy.
You won’t have to worry where you have to make the changes to make your app work in local. If you don’t have it centralized, your life will be hell if you want to make changes.
This means other naive people can use it, just by changing the config. So a non-programmer can set up your system by just changing the values relevant to his requirements. It also helps testing teams (if you have one).
I can list more, but you’ve got the idea (I hope).
So let’s get to the actual config values. (If you don’t know Mongo, don’t worry, these are just configurable values.)
Let’s take a brief look at existing solutions to store config files (from 1): 1) YAML: YAML is a human friendly data serialization standard for all programming languages. PyYAML is a YAML parser, that can load and read YAML files. You can see 1 for a concrete example 2) ConfigParser: This is python’s built in module for, well, parsing config files in .ini format. All good 3) Python dict: This is the simplest format, with just a python dict specifying key-value pairs like so:
config = { 'MONGO_DB_NAME' : 'Database' , 'MONGO_HOST' : localhost ,.. }
These approaches handle config well, and at the end transform the config file into a python dictionary. I argue that this isn’t sufficient for Config Management, and go a step further : Creation of Classes that serves these properties in a clean way.
Let’s assume you chose one of the 3 ways to store the configuration, and you’ve put it into a dict named ‘conf’. Create a class called Config (or Configuration), with a method get_property, which takes in a arg that is a key into the conf dictionary. Like so:
# loaded config
conf = {
key1: val1,
key2: val2,
...
keyn : valn
}
class Config(object):
def __init__(self):
self._config = conf # set it to conf
def get_property(self, property_name):
if property_name not in self._config.keys(): # we don't want KeyError
return None # just return None if not found
return self._config[property_name]
We can now do something like this:
configuration = Config()
mongo_client = pymongo.MongoClient(host=configuration.get_property('MONGO_HOST'), port=configuration.get_property('MONGO_PORT'))
...
This just doesn’t cut it, since we have to remember MONGO_HOST, blah blah. So we go to step 2
Self Explanatory!
class MongoConfig(Config):
pass
class StudentConfig(Config):
pass
class TeacherConfig(Config):
pass
If you don’t know what python properties are, just google them around a bit. I’m gonna explain one class only here, the other classes can be similarly built.
class MongoConfig(Config):
@property
def host(self):
return self.get_property('MONGO_HOST')
@property
def port(self):
return self.get_property('MONGO_PORT')
@property
def username(self):
return self.get_property('MONGO_USERNAME')
@property
def db_name(self):
return self.get_property('MONGO_DB_NAME')
@property
def password(self):
return self.get_property('MONGO_PASSWORD')
Since MongoConfig is extended from Config, it has full access to the Config class methods, so it can use get_property to get the relevant properties.
To illustrate how it can be used, here’s a method to get a collection using pymongo:
def get_collection(collection_name):
configuration = config.MongoConfig()
mongo_client = pymongo.MongoClient(host=configuration.host, port=configuration.port)
db = mongo_client[configuration.db_name]
if configuration.username is not None:
db.authenticate(configuration.username, password=configuration.password)
return db[collection_name]
You can see this code in the following gist: https://gist.github.com/samarthbhargav/e491a6ab5a83d05eb833
Feel free to comment, etc. Refrences: