Archive for the ‘Azure’ Category.

Windows Azure and Object-Oriented Testable Code

I am currently working on an Azure application that makes heavy use of blob storage (think raw data storage), table storage (think object database) and queues (think queues). From a high level point of view, these are constructs that could be useful to many enterprise applications being built today.

With that said, I’ve had to do a little work to make Azure more friendly to my way of building software. Let me deviate for a moment…

Lately, I have tried to distill everything that I know about object-oriented programming down to one statement: If I can test it, it’s good enough for now. There’s code readability and things like that which must be considered, but when I say this I am really referring to the structural elements of the application. Good enough for now means that everything is in a state that can be easily refactored later (if need be) and it means that the code is testable in an automated way (NUnit). My designs tend to rely on dependency injection, inversion of control and make heavy use of abstractions.

The Azure Storage API (what I’m mostly familiar with in the world of Azure) seems to be a throwback to older MS designs: sealed classes based on no abstractions (interfaces, abstract base classes). In other words, it’s an all or nothing black box approach. So forget about mocking. Granted, MS makes stuff easy to use but at the same time doesn’t seem to understand that that how I connect everything together is important, too.

Fortunately, it has been trivial to get around this using Bridge/Adapter-ish patterns.

My approach to blob storage has been something along these lines (THIS IS NOT PRODUCTION READY CODE – EXAMPLE ONLY):

public interface IBlob
{
    void UploadFile(string fileName);
    // just a few more methods here
    // not exposing every method on CloudBlob
}

public interface IBlobContainer
{
    IBlob GetBlobReference(string blobAddress);
}

public interface IBlobStorage
{
    IBlobContainer GetContainer(string name);
}

public class BlobStorage : IBlobStorage
{
    private readonly CloudBlobClient _client;

    public BlobStorage()
    {
        var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
        _client = account.CreateCloudBlobClient();
    }

    public IBlobContainer GetContainer(string name)
    {
        return new BlobContainer(_client, name);
    }
}

public class BlobContainer : IBlobContainer
{
    private readonly CloudBlobClient _client;
    private readonly string _containerName;

    public BlobContainer(CloudBlobClient client, string containerName)
    {
        _client = client;
        _containerName = containerName;
    }

    public IBlob GetBlobReference(string blobAddress)
    {
        var container = _client.GetContainerReference(_containerName);
        container.CreateIfNotExist();
        var blob = container.GetBlobReference(blobAddress);
        return new Blob(blob);
    }
}

public class Blob : IBlob
{
    private readonly CloudBlob _cloudBlob;

    public Blob(CloudBlob cloudBlob)
    {
        _cloudBlob = cloudBlob;
    }

    public void UploadFile(string fileName)
    {
        _cloudBlob.UploadFile(fileName);
    }
}

This gives me IBlob, IBlobContainer and IBlobStorage….my own interfaces, which can easily be mocked and improves my testability.

I am doing something similar with queues. Again, this is an example only (I say this over and over in an attempt to keep “nitpicking” type comments to a minimum). Rest assured, my production code is a little more rich than this.

public interface IQueueMessage
{
    object Content { get; }
    string AsString { get; }
}

public interface IQueue
{
    void AddMessage(IQueueMessage message);
    IQueueMessage GetMessage();
    void DeleteMessage(IQueueMessage message);
}

public interface IQueueLocator
{
    IQueue GetQueue(string queueName);
}

public class QueueMessage : IQueueMessage
{
    internal CloudQueueMessage CloudQueueMessage { get; private set; }

    public QueueMessage(CloudQueueMessage cloudQueueMessage)
    {
        CloudQueueMessage = cloudQueueMessage;
    }

    public QueueMessage(byte[] content)
    {
        CloudQueueMessage = new CloudQueueMessage(content);
    }

    public QueueMessage(string content)
    {
        CloudQueueMessage = new CloudQueueMessage(content);
    }

    public object Content
    {
        get { return CloudQueueMessage; }
    }

    public string AsString
    {
        get { return CloudQueueMessage.AsString; }
    }
}

public class Queue : IQueue
{
    private readonly CloudQueue _cloudQueue;

    public Queue(CloudQueue cloudQueue)
    {
        _cloudQueue = cloudQueue;
    }

    public void AddMessage(IQueueMessage message)
    {
        if (_cloudQueue == null)
            return;
        _cloudQueue.AddMessage((CloudQueueMessage)message.Content);
    }

    public IQueueMessage GetMessage()
    {
        if (_cloudQueue != null)
        {
            var content = _cloudQueue.GetMessage();
            return new QueueMessage(content);
        }

        return null;
    }

    public void DeleteMessage(IQueueMessage message)
    {
        if (_cloudQueue != null)
        {
            var content = (CloudQueueMessage)message.Content;
            _cloudQueue.DeleteMessage(content);
        }
    }
}

public class QueueLocator : IQueueLocator
{
    private static CloudQueueClient _queueStorage;

    public IQueue GetQueue(string queueName)
    {
        if (_queueStorage == null)
        {
            CreateQueueStorage();
        }

        if (_queueStorage != null)
        {
            var cloudQueue = _queueStorage.GetQueueReference(queueName);
            cloudQueue.CreateIfNotExist();
            return new Queue(cloudQueue);
        }

        return null;
    }

    private static void CreateQueueStorage()
    {
        var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
        _queueStorage = storageAccount.CreateCloudQueueClient();
    }
}

Conclusion

Not perfect, I know, but it’s good enough for now. I have hidden the fact that there are CloudStorageAccount’s and CloudBlobClient’s and CloudQueueClient’s. This may or may not work for you. My main concern is that I have something that I can mock. I can use dependency injection and inversion of control and I am able to see how my application interacts with Azure in my unit tests.

Installing Java into an Azure Worker Role

1. Download Java.

2. Add a reference to the installation package (e.g. jre-6u26-windows-x64.exe) to your worker role. In the properties, set Copy to Output Directory = Copy always.

3. Create and add a Startup.bat to your worker role. Set Copy to Output Directory = Copy always. This batch file is one line long:

jre-6u26-windows-x64.exe /s /L %RoleRoot%/approot/java-install.log

This will silently install Java and create a log in your root directory (which has been E:\approot every time I have ever remoted in to any instance).

4. Add a startup task to ServiceDefinition.csdef that will run the batch file during deployment:

<WorkerRole name="WorkerRole1">

<Startup>
    <Task commandLine="Startup.bat" executionContext="elevated" taskType="background" />
</Startup>

</WorkerRole>

5. Before you publish, you need to make sure you have an x.509 certificate added to your worker role. Upload the certificate to your hosted service via the Azure Management Portal. Also, add the certificate to your configuration settings.

6. Now it’s time to publish. Make sure you select Configure Remote Desktop connections. You will want to log into your role remotely (at least once) to verify that Java was installed).

7. After the worker role has been deployed, you should be able to remote into the machine. Once you are in, navigate to E:\approot. The installation log should be there if you need to look at it. If you just need to verify that Java is installed, try D:\Program Files\Java.

Running NUnit in the Windows Azure Emulator

Download Test Project Here

If there is an easier way to do what I am about to describe, someone please me. I am guessing there is some clever way to use cspack and csrun to allow me to run NUnit in the Azure emulator, but for the life of me I can’t get it to work. Therefore, I am using this admittedly goofy approach.

Disclaimer: The approach is tailored to a web role. The sample code is really a proof of concept.

"I think I have NUnit running"

Basic Approach

My basic approach is to copy the output from my test project into a subdirectory beneath the bin folder of my main web role (bin/test). Instead of using a test runner – in my case TestDriven .NET – I run my web role. There is a page on my site that will run NUnit and output the test results to the browser. If I need to, I can put break points in my tests and the debugger will let me step into the code.

Initial Setup

1. In the bin directory of your web role, create a sub-directory called test. In my case this is /TestSiteWebRole/bin/test.

2. Add a post-build event to your test project (replacing TestSiteWebRole with your project):

copy “$(TargetDir)*.*” “$(SolutionDir)TestSiteWebRole\bin\test”

3. In your web role add references to nunit.core.dll and nunit.core.interfaces.dll.

Adding a Test Runner Page (or Running NUnit from Code)

4. Add a page to your web role. In the example code, this is NUnit.aspx. There are several horrors to behold here. One, my example code is using WebForms. Two, there are a bunch of hardcoded references in it. I’m leaving it up to you to take this code beyond a POC.

public partial class NUnit : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        RunTests();

    }

    private void RunTests()
    {
        CoreExtensions.Host.InitializeService();

        string testPath = Server.MapPath("bin/test");
        string testAssemblyPath = Path.Combine(testPath, "TestSite.Tests.dll");
        var package = new TestPackage(testAssemblyPath);
        var builder = new TestSuiteBuilder();
        var suite = builder.Build(package);
        var result = suite.Run(new MyListener(Response), TestFilter.Empty);
    }

5. The NUnit page uses another class called MyListener. This is just a class that implements NUnit.Core.EventListener (which is an interface). My implementation is about as simple as you can get. I am sure you can do much better.

public class MyListener : EventListener
{
    private readonly HttpResponse _response;

    public MyListener(HttpResponse response)
    {
        _response = response;
    }

    public void RunStarted(string name, int testCount)
    {
        _response.Write(name);
    }

    public void RunFinished(TestResult result)
    {
    }

    public void RunFinished(Exception exception)
    {
    }

    public void TestStarted(TestName testName)
    {
        Print("<p/>");
        Print("{0}", testName.Name);
    }

    public void TestFinished(TestResult result)
    {
        if (result.ResultState == ResultState.Failure)
        {
            Print("FAILED");
            Print(result.StackTrace);
        }
        else if (result.ResultState == ResultState.Success)
        {
            Print("SUCCESS");
        }
        else
        {
            // do something phenomenal here
        }
        Print(result.Message);
    }

    public void SuiteStarted(TestName testName)
    {
    }

    public void SuiteFinished(TestResult result)
    {
    }

    public void UnhandledException(Exception exception)
    {
    }

    public void TestOutput(TestOutput testOutput)
    {
    }

    private void Print(string msg)
    {
        _response.Write(msg);
        _response.Write("<br />");
    }

    private void Print(string msg, params string[] args)
    {
        _response.Write(string.Format(msg, args));
        _response.Write("<br />");
    }
}

The test project contains one test:

[Test]
public void role_environment_is_available()
{
    Assert.IsTrue(RoleEnvironment.IsAvailable);
}

If everything is set up correctly. You should get the following output when you run the NUnit page:

role_environment_is_available
SUCCESS

Managing Azure Configuration Settings

I thought I would share a simple class that I am using to manage configuration settings in Azure. The class provides access to configuration settings much like the traditional ConfigurationManager class:

string connectionString = AzureSettings.GetValue(“DataConnectionString”);

However, this will return a different value depending upon where I am running (emulator vs. actual cloud).


I accomplish this with a little convention.

For emulator settings, I prefix the setting name with dev_. If I am running in the emulator and I ask for “DataConnectionString”, AzureSettings will look for “dev_DataConnectionString” instead. If it can’t find that setting it will try “DataConnectionString”. If it still can’t find it, it will try to pull it from appSettings in the web/app.config.

In order to determine whether or not I am running in the emulator I am resorting to a hack (gasp!). RoleEnvironment.DeploymentId will be something like “deployment(42)” in the emulator but in the cloud it’s a Guid. Yeah, it’s not official, but I can live with it. MS doesn’t provide a way to check for the existence of configuration settings so I already have to potentially swallow two exceptions just to get a setting. So, the whole thing is filthier than toilet seat anyway.

using System;
using System.Configuration;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace SoftwareCraftsman
{
    public static class AzureSettings
    {
        public static bool InEmulator { get; private set; }

        static AzureSettings()
        {
            if (RoleEnvironment.IsAvailable)
            {
                Guid deploymentId;
                InEmulator = !Guid.TryParse(RoleEnvironment.DeploymentId, out deploymentId);
            }

        }

        public static string GetValue(string key)
        {
            if (RoleEnvironment.IsAvailable)
            {
                if (InEmulator)
                {
                    try
                    {
                        return RoleEnvironment.GetConfigurationSettingValue("dev_" + key);
                    }
                    catch
                    {
                         /* swallow */
                    }

                }

                try
                {
                    return RoleEnvironment.GetConfigurationSettingValue(key);
                }
                catch
                {
                     /* swallow */
                }
            }

            return ConfigurationManager.AppSettings[key];
        }

    }
}