A while back I discussed the approach we use on some projects to configuration management and how we solve the problem of configuring binding and configuration (and any other) files for different environments. I had originally written the linked article on my blog. While it was fairly successful the main project I've been working on has a number of BizTalk projects within it and I felt that the configuration dictionary approach we were using was becoming a bit of a pain as the XML dictionaries were awkward to maintain and you couldn't get a clear view of your configuration.
To help tackle this problem I wanted to create a tool to help with this, the aims of the tool were:
- Provide a nice simple to use UI which would allow me to manage configuration settings for multiple code bases on large projects
- Provide an easy way to integrate a build process into the use of this configuration store
- Try to enhance the previous approach by allowing you to import configuration as the XML files which people may already be using.
The tool is available on codeplex: http://www.codeplex.com/ConfigSettingsTool
Here are a few points to describe the model for the configuration data:
- The system will store information for multiple projects
- Each project can have multiple environments associated within
- Each project will have multiple solutions (code bases) associated with it
- Each solution will have a list of settings which can have default values
- For each solution within a project you can specify setting values for each environment, or inherit the default setting
In the rest of this article I will describe the use of the tool, and how we implemented it for our BizTalk projects. Note that nothing about this tool is BizTalk specific so you could easily use it for .net projects etc. Also in this article I have used screen shots from a real project but have had to censor some information from the screen shot.
In order to run the tool the prerequisites are as follows:
- The database should be setup on a SQL Server 2005 database (ensure you configure backups for your database)
- The client application requires .net 3.5
- The MsBuild tasks need to run on a machine which has .net 3.5
To set up the application you should take the following steps:
Setting up the database
In the zip file you will download there is a folder containing the database script. You will first need to create a database (which I'm assuming you can do already) and then use the CreateDatabaseObjects.sql script to setup all of the database objects by running it in query analyser.
Setting up the application
In the zip file there is an application folder. In this folder the ConfigurationManagement.Administration.exe.config file contains settings for the application. You will need to edit the connection string to ensure it points to your new database.
Once you have done this and saved the file you can now run the application by double clicking the ConfigurationManagement.Administration.exe file.
Using the Application
Now you are setup if you open the application you can begin setting up your configuration. If you open the Tools à Management menu you will see options for managing the different aspects described above.
In the picture below you can see the screen for managing your projects. This is pretty simple, you can add/update/delete projects in the grid. Note any changes are not saved until you close the form.
I normally use 1 project per customer or major project of work. In this project you can configure multiple solutions and I normally relate each configuration solution to a visual studio solution.
Within a project you can also configure multiple environments. As you can see in the below picture I have configured only a couple of environments. Examples of environments you might configure include (System Test, UAT, Production). The environments screen again is fairly simple in that it allows you to add/update and delete environments. Note again changes aren't saved until you close the form.
Within the Project you can also define the details of multiple solutions. The solutions form allows you to add/update and delete solutions. The changes are not saved until you close the form. The below picture shows an example of the solutions within this project.
Manage the Solution Dictionary
Once your solution is configured you can now set up its dictionary. The below picture shows an example of this. Within the solution you will create a list of setting tags. These tags are things you will put in files to indicate a special key that you will replace. We typically use the format $(-------) to indicate a key. For each setting you can define a default value which will be used if no specific setting for that environment is configured.
In the below picture if we ran this solution dictionary over a file we would look for each setting and replace it with the environment specific or default value. If a setting key could not be found then we will move onto the next tag.
Again the form follows the usual format for adding/updating and deleting settings and as before the settings are only saved when the form is closed.
Manage Environment Settings
Now we come to managing the settings for each environment. We use the below form which allows you to choose a project and solution. This will then execute a cross tab query to create a grid listing the solutions configuration tags in the first column and then create additional columns for each environment as shown in the picture below.
The first column is read-only, but the other columns allow you to define a specific value for each environment. If you leave a cell empty then the default value is used instead.
This form is different to the others by the nature of what it does. You can not add of remove rows, only edit existing cells. Also when you make a change the details are saved when you finish editing the cell.
At this point you have now configured your solution and are well under way to effectively managing your configuration for your development effort.
Template Files to Configure
As mentioned previously you will typically have a template file which you will run the configuration dictionary over to produce the correctly configured file for a given environment. Some examples of files we typically configure on our BizTalk projects are:
- A template of BizTalk Binding Files
- A template of Web.config and policy cache files for published web services
- A template of BTSNTSVC.exe.config
In the below picture which is a snippet of a BizTalk Binding File Template you can see that I have circled in red the setting tags which are in the $(------) format (note that I have had to censor the tag named). We maintain this template as an artefact within the solution and then during our build process we will run the dictionary over this template file to produce the real correctly configured files for each environment.
Integrating the Build Tasks into Your Script
Along with the Configuration Management application you will also find a folder with a dll containing some MsBuild tasks. There are 3 tasks:
This task will look up the configuration settings from the database and configure a template file.
This task will use the old dictionary file format to configure the template file. This will be discussed later.
This task will produce an HTML report for the configuration. We use this task to deliver a report of the settings we want them to use to our deployment team.
The below picture shows the MsBuild UsingTask statements you would need to use to reference the Configuration Management build tasks. You should also see a ConfigurationManagement.tasks file in the folder containing the MsBuild tasks assembly. You can import this .tasks file into your build script using the Import MsBuild statement.
In the next picture you can see a snippet from our build script. In this case we are configuring two files (a web.config and a policycache file) based on information in the Configuration Management database. You need to tell the task the Project, Solution and Environment which you want information from and also the connection string to your database.
In the bottom part of the above snippet you can see how we use the ProduceSettingsReport task to produce the HTML report I discussed earlier. A sample of this report is below:
Working with the old Dictionary File Based Model
While the new application is very useful and we are able to access configuration directly from the database, some teams may still prefer to store the configuration as a dictionary file like in my original blog post. This has the benefit that you can easily keep the dictionary in a source control system and have a full version history for it. Based on this I wanted to allow teams to make this choice and if they still wanted to use the file based approach then could still take advantage of the tool anyway. This is described below.
Importing Configuration from File
You can begin by importing your dictionary file into the Configuration Management application. The below picture shows how you can choose the Project, Solution and path to the dictionary file. When you import this information any existing setting information is updated, and any new data is added.
Exporting Configuration to File
When you have edited your configuration you may wish to export it again to a file to update the file in your solution. Like with the import you can choose the Solution, Project and path then just export it.
Hopefully you will find this tool very useful and time saving. There are a couple of limitations and future enhancements you may wish to be aware of if you are considering using this.
At present there is no additional security other than if you can access the database. In future releases I plan to add the ability to configure reader and editor roles for each solution/environment/project so this can be locked down more. This will make the tool more usable for bigger projects when you want multiple teams to work on this.
At present I do not audit any changes made to the configuration. This would be a useful enhancement.
- Any changes made to configuration will not trigger a build in your Continuous Integration environment. This is one reason why a team may wish to combine using the tool with the old file based dictionary approach because when the updated dictionary file is checked in a build would be triggered. If you do scheduled nightly builds this may mitigate this.