Changing Service Configuration (cscfg) during Azure Cloud Service Deployment

Good day

How does one go about changing the Service Configuration settings during a deployment in Octopus Deploy 2.6?

More specifically, I need to update the ReservedIP value based on the deployment targed (Production/Test).

It seems that the normal config setting substitution won’t do as this isn’t a Key/Value setting.

One can’t use the #{variable} substitution as this causes compilation errors.

Is the only way by means of a PowerShell script? If so, which script should one use? PreDeploy/Deploy/PostDeploy? What would be the path to the cscfg file? A sample would be really great.

Hi,

Thanks for reaching out. As the compiler doesn’t accept #{} syntax variables, the only way right now is to use Powershell for the substitution.

The Octopus variable #{Octopus.Action.Azure.PackageExtractionPath} holds the path where the cscfg file will be extracted. With that in mind, see my example cscfg file and the powershell script to modify one of its nodes

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="AzureCloudService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="4" osVersion="*" schemaVersion="2015-04.2.6">
  <Role name="WebRole1">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
  </Role>
  <Role name="WorkerRole1">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

changing the node [ServiceConfiguration.Role[0].Instances.count]

#Path where Octopus will unpack the cscfg file. The file needs to be at the root of the NuGet package for this to work
$fileroot = "#{Octopus.Action.Azure.PackageExtractionPath}"

#Name of your cscfg
$filename = "ServiceConfiguration.Cloud.cscfg" 

$cscfgfile = Get-Item $fileroot\$filename
[xml]$cscfgcontent = get-content $cscfgfile

#changing the node [ServiceConfiguration.Role[0].Instances.count]
$cscfgcontent.ServiceConfiguration.Role[0].Instances.count = "3"

#saving the changes
$cscfgcontent.Save($cscfgfile.FullName)

Hope that helps

Dalmiro

Hi Dalmiro

The post was a great help, thank you.

I declared the following PreDeploy.ps1 inside the process step (not as a PreDeploy.ps1 file in the package).

I couldn’t get the #{Octopus.Action.Azure.PackageExtractionPath} variable to work inside my script, but I found that it worked without it as well.

Here’s the script I ended up writing. Because I have only one web role I didn’t have to use the array indexer ([0]) to specify the element.

$ServiceConfigFileName = "ServiceConfiguration.Cloud.cscfg" 
$CscfgFile = Get-Item $ServiceConfigFileName
[xml]$CscfgContent = Get-Content $CscfgFile

# Update Service Configuration File
$CscfgContent.ServiceConfiguration.Role.Instances.count = "$RoleInstances"
$CscfgContent.ServiceConfiguration.NetworkConfiguration.AddressAssignments.ReservedIPs.ReservedIP.name = "$ReservedIP"
$CscfgContent.Save($CscfgFile.FullName)
Write-Output "Applied config changes to $($CscfgFile.FullName)"

At the moment I’m stuck trying to update the VM Size in the Service Definition file. We’re using Octopus 2.6, so the csdef file is not extracted in order to make any sort of changes to it.

Is there a way to extract the file from the package, update it, and package it again in order to edit the VM Size?

Hi,

I’m afraid the extract feature is only available in 3.0, so this approach wont work in 2.6. Perhaps you could add that powershell script to your build process before the app gets packaged into the cspkg?

Dalmiro

Hi Dalmiro

Thank you. We’ll prioritize the move to 3.0 or 3.1.

Hey Jeanpaul,

If you are willing to do some work to get it working in 2.6, you can follow my example here:

I’ve been doing this for about a year now and it works perfectly. The trick is to use build-time transforms to inject the tokens and then deploy-time transforms to inject the proper values. See the above repo for a fully working example.