Sunday, 4 August 2013

Type safe configuration mapper

Almost every project needs some sort of configuration, that is external of the source code. Sometimes we spend time to find the best library that fits our needs and sometimes we give up and write something in-house. I would like to save your time in both these tasks and suggest what I have found and I use in my projects.

I was looking for a library that would allow me to represent all parameters as an interface or class. The parameters would be strongly typed with minimum overhead in mapping parameter to property. Providing default values would be also nice, but not necessarily. The best library that exactly fits these needs is ConfigReader. Here are a few simple steps how to use it in your project:

1. Put your configuration parameters in the regular app.config or web.config file. Parameters may be of any primitive data types:
 

 <appsettings>
    <add key="ApplicationConfiguration.Duration" value="30" />
    <add key="ApplicationConfiguration.Distance" value="3" />
    <add key="ApplicationConfiguration.Author" value="Boris Modylevsky" />
 </appsettings>

2. Create an interface with properties to represent the configuration in code. Give properties the same names as parameters names. Properties may be read-only - having only getter without setter. We don't need to specify no special mapping attributes, nothing. Just an interface with properties. Here is a corresponding interface:
 

public interface IApplicationConfiguration
{
    int Duration { get; }
    double Distance { get; }
    string Author { get; }
}
3. Next step we need to initialize our configuration interface from the configuration file. If you are using Inversion of Control (IoC) containers, it is better to to in the bootstrapper - where all the classes are registered in the container. I will show how this could be done in Autofac. First of all we create a ConfigurationModule class, which defines configuration registration in Autofac:
 
using System.Diagnostics.Contracts;
using Autofac;
using ConfigReader;

public class ConfigurationModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        Contract.Assert(builder != null, "Builder container is null");

        var configReader = new ConfigurationReader().SetupConfigOf<IApplicationConfiguration>();
        var configuration = configReader.ConfigBrowser.Get<IApplicationConfiguration>();
        builder.RegisterInstance(configuration).As<IApplicationConfiguration>();
    }
}
4. Then we just register the ConfigurationModule in our container builder and that's all!
 

using Autofac;

public static class Bootstrapper
{
    public static IContainer Container { get; private set; }

    public static IContainer Initialize()
    {
        var containerBuilder = new ContainerBuilder();
        containerBuilder.RegisterModule<ConfigurationModule>();
        Container = containerBuilder.Build();
        return Container;
    }
}
5. Use it by defining as constructor parameter. IoC container will take care to transfer the correct instance into your constructor:
 
public class SomeClassThatUsesConfiguration
{
    private readonly IApplicationConfiguration _configuration;

    public SomeClassThatUsesConfiguration(IApplicationConfiguration configuration)
    {
        _configuration = configuration;
    }

    public double GetVelocity()
    {
        return _configuration.Distance/_configuration.Duration;
    }
}
If you like the above and would like to use it in your project, download it from nuget.org:

PM> Install-Package ConfigReader




Friday, 26 July 2013

How to add grammar and spelling check on your website

I've just noticed that I have posted my previous post with a minor typo. I will immediately correct it. But you may wonder how to add grammar and spelling checks on your website with minimal integration required.
1. Copy and paste the below on on your webpage
2. Add any textarea control and it will be automatically checked by Ginger spelling and grammar checker


<script type="text/javascript" src="http://cdn.gingersoftware.com/webWidget/gingerEditor.min.js"></script>
<script type="text/javascript">var init = GS_WEB_WIDGET.namespace("initParams");if (init && init.hasOwnProperty("init")) { init.init({apiKey:"03243e85-a1a7-4383-8338-2f1db1cb9b46"});}</script>
For more integration options see: http://www.gingersoftware.com/self_service

Thursday, 25 July 2013

Automatic Deployment :: The final solution

In my previous post I lited tools used for automatic deployment. Although all of them have significant advantages, they did not fit for our needs. Or if they did, they seem to be too complex for such simple deployment process. So let's start with what we needed. We needed a script/tool that:
1. Downloads binaries 
2. Updates configuration files
3. Stops a windows service
4. Copies rellevant files 
5. Starts a windows service
6. Checks that the service is started and responding properly
7. Iterates the above steps for several servers in several data centers

One of the most important decisions we've made before and during the tools selection, was the following. Use the same deployment tool/script for deployment to test/staging environment as for production deployment. This rule seems to be pretty obvious and maybe irrelevant, but it saves a lot of times and script fixing during produciton debug. When the product is deployed to test machines on a frwquently basis it tested each time. If there is some new configuration parameter that needs to be updated. If we forget to update the deployment script it fails in deploy to test machine. Then we fix it in deploy to test machine and produciton deployment works smoothly.

So let's go back to tool seleciton: we use TeamCity as our continious integration system for builds automated tests etc. And it seemed so natural to use TeamCity for automatic deployment as well. We wrote, or actually, reused Powershell script previously written in order to extend Puppet. These scripts do the steps described above. 

So the winners are TeamCity and Powershell


Tuesday, 16 July 2013

Automatic Deployment :: Choosing the magic tool

About a year ago I was asked to automate the deployment process. Actually it has some level of automation, but it should be significantly improved. When my boss says "significantly improve", he means "completely rewrite". In the beginning I was looking for that magic tool, that click-and-relax solutions that will do the work. Polling at StackOverflow and googling around resulted with a list of tools. This post will focus on advantages and disadvantages of these tools. In the next post I will try to explain what solution was chosen and why.

eyeShare by Ayehu http://www.ayehu.com/

eyeShare is a descent UI based tool for deployment automation and monitoring. I was interested only in the automation part. It provides and drag and drop user interface with different kinds of actions: Copy, Stop Service, Start Service etc. It has many cool features, such as email and SMS notifications and listeners. The listeners allow the user to respond to some failure in some action. For example, deployment of the database failed, eyeShare will send email/SMS with notification and will wait for reply: proceed or rollback database changes. This might be extremely useful. However it has some major drawbacks for our basic scenario:

  1. deployment processes stored by eyeShare are not version controlled, they are stored in SQL Server database with no history tracking; 
  2. it requires installation of the UI management on each machine and there is no web UI accessible from all the machines; 
  3. something that took me sometime to understand and I had to talk to their support: let say I have action A and then action B. I assume that until action A is finished, action B does not start. Basic serial processing. However eyeShare executes action in parallel, even of they are organized serially in the deployment workflow. There are some workaround that need to be done using timers and timeout in order to overcome this behavior. 
Octopus Deploy http://octopusdeploy.com/

Octopus Deploy is a cool deployment project for ASP.NET and Windows Service projects. Actually I did not dive too much into it, since it requires any software component will be delivered as a nuget package. Since our product has many dependent components, it was decided that it would be too much work to package every component as nuget package.


Puppet http://puppetlabs.com/

Puppet, puppet, puppet! Everybody in the DevOps world talk about Puppet. If your want automatic deployment you have to use Puppet. 

I was curious when starting to learn about Puppet. I have to admit, that the learning curve was steep, but at the end we had automatic deployment POC using Puppet. After the POC was completed it was decided not to proceed with it. Here are some of the reasons. My feeling was that Puppet it more Linux/Unix oriented, that Windows. Since our main product is developed in .NET and should be deployed to Windows servers, the whole overhead with Linux style paths and Linux style commands is ridiculous. Some of the operations are not supported in Puppet agent on Windows and I had to write scripts in Powershell. At the end it resulted that most of the things are written in Powershell, so there was no reason to use Puppet as a manager of these scripts.

For the actual selected and working solution wait for the next post:
http://borismod.blogspot.co.il/2013/07/automatic-deployment-final-solution.html





Monday, 24 September 2012

The service did not respond to the start or control request in a timely fashion.

If your Windows Service does not start and there is the following error under System folder in the Event Viewer:


The ServiceName service failed to start due to the following error:
The service did not respond to the start or control request in a timely fashion.

It might occur if the .NET Framework, the service uses, is not installed on the machine.

Run your service in command line mode (if it's supported) and you'll see the error saying .NET Framework X.X is not installed.

Then you will know what version you need to download and install

Hope it saved you time, that I spent on finding this out