johnkors

John Korsnes

Varying Azure Instances Between Environments When Deploying With Octopus Deploy

| Comments

Octopus Deploy is a great tool for doing release management for .NET platforms. If you’re doing any kind of .NET-apps I really recommend you do try it out. Lately I’ve been using it at work for deployments to Azure Cloud Services. Octopus handles both deploying your app to your server, but also setting the correct configuration parameters for the environment you are deploying to. In Azure Cloud Services the relevant config file is by default ServiceConfiguration.Cloud.cscfg as well as the usual web.config.

Our setup

We have the usual 4 environments linked to 4 different Azure Cloud Services - Test, Stage, Preprod and Production. We build a single deployment package using our CI server (Team City) and let Octopus execute our deployment process. In Octopus 2.0 (current version) it’s possible to vary any configuration setting specified in the <ConfigurationSettings> section.

Example fetched from the Octopus Azure documentation page link:

ServiceConfiguration.Cloud.cscfg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ServiceConfiguration serviceName="Humpty" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*" schemaVersion="2012-10.1.8">
  <Role name="Humpty.Web">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
      <Setting name="HelloMessage" value="Hello world! This is a web role!" />
    </ConfigurationSettings>
  </Role>
  <Role name="Humpty.Worker">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
      <Setting name="HelloMessage" value="Hello world! This is a worker!" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

This works perfectly, but has a limitation on only varying values with <ConfigurationSettings> . In our scenario, we also need to vary two other values in the ServiceConfiguration.Cloud.csfg - namely the Instance count and also Certificate thumbprints. We use fewer instances in our test environments than in production, and also we have a different certificate for our production environment.

Instance count
1
2
3
<Role name="Humpty.Web">
    <Instances count="1" />
    ...
Certificate thumbprint
1
2
3
4
5
  <Role name="Humpty.Web">
    <Certificates>
      <Certificate name="MyCertificate" thumbprint="MyThumbprint">
    </Certificates>
  </Role>

Even though Octopus does not support transforming these values out of the box, it is still possible by taking advantage of the PreDeploy.ps1 extensibility feature of Octopus.

Using Powershells rich XML API, I’ve written a PreDeploy.ps1 that searches the Octopus variables for variables on the format Azure.Role[rolename].Instances and updates the ServiceConfiguration.Cloud.cscfg accordingly before executing the deployment to Azure. For the Octopus example mentioned, if you define a variable in the Octopus portal named Azure.Role[Humpty.Worker].Instances, it will update ServiceConfiguration.Cloud.cscfg file with the instance count defined by the Octopus variable value. The script similarly supports transforming the Certificate thumbprint by variables on format Azure.Role[rolename].Certificate .

Snippet of PreDeploy.ps1 Link to full script on github gist
1
2
3
4
5
6
$configFile = "ServiceConfiguration.Cloud.cscfg";
$roleInfo = GetCustomRoleInfoFromOctopusParameters
$xml = ParseAzureConfigToXml
$xmlWithNewCertificate = UpdateFirstCertificateEntriesForEveryRole $xml $roleInfo.Certificates
$xmlWithNewInstanceCounts = UpdateInstanceCounts $xmlWithNewCertificate $roleInfo.Instances
$xmlWithNewInstanceCounts.Save($configFile);

Hopefully Octopus will support this natively in coming versions. As of Octopus 2.0, it still only lets you do instance count from the ServiceConfig-value or the instance count from the current deployment - but not vary it between environments.

Comments