Azure - transforming the csdef file
I adapted this idea from here: http://fabriccontroller.net/blog/posts/apply-xdt-transforms-to-your-servicedefinition-csdef-file/
Basically, we had a situation where we had an app hosted in Azure that was reliant on host headers to switch behavior. Now, host headers are defined within the .csdef as bindings - something like this:
<Site name="Web">
<Bindings>
<Binding name="HttpIn" endpointName="HttpIn" />
<Binding name="HttpIn_CO" endpointName="HttpIn_CO" hostHeader="www.xxx.co.uk" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="HttpIn" protocol="http" port="80" />
<InputEndpoint name="HttpIn_CO" protocol="http" port="82" />
</Endpoints>
We also had to deploy this app in more than one country, with both sites behaving the same (with some content changes). As we were deploying the same app twice, with different headers, we had 2 options - either have n Azure projects where n is the number of countries we deploy to; or we transform the csdef to change the bindings depending on cloud configuration.
We chose the second option. The first thing I did was read the article linked at the top of this post *hint*.
The basic steps from this article are:
Basically, we had a situation where we had an app hosted in Azure that was reliant on host headers to switch behavior. Now, host headers are defined within the .csdef as bindings - something like this:
<Site name="Web">
<Bindings>
<Binding name="HttpIn" endpointName="HttpIn" />
<Binding name="HttpIn_CO" endpointName="HttpIn_CO" hostHeader="www.xxx.co.uk" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="HttpIn" protocol="http" port="80" />
<InputEndpoint name="HttpIn_CO" protocol="http" port="82" />
</Endpoints>
We also had to deploy this app in more than one country, with both sites behaving the same (with some content changes). As we were deploying the same app twice, with different headers, we had 2 options - either have n Azure projects where n is the number of countries we deploy to; or we transform the csdef to change the bindings depending on cloud configuration.
We chose the second option. The first thing I did was read the article linked at the top of this post *hint*.
The basic steps from this article are:
- Add the web config transform runner package to your solution
PM> Install-Package WebConfigTransformRunner - In Windows Explorer, create new .csdef files for each .cscfg file.
- Manually edit the project file to add the new items as content
- Add a build target into the Azure project file
I followed these steps and got it all working. I was then immediately annoyed that I had two empty transform files... I had 3 .cscfg files Cloud, Cloud.AU and Local BUT I only wanted to transform Cloud.AU. So, I modified the build script to this:
<PropertyGroup>
<ServiceDefinitionTransform>ServiceDefinition.$(TargetProfile).csdef</ServiceDefinitionTransform>
<TransformRunnerExecutable>$(MSBuildProjectDirectory)\..\packages\WebConfigTransformRunner.1.0.0.1\Tools\WebConfigTransformRunner.exe</TransformRunnerExecutable>
</PropertyGroup>
<Target Name="AfterValidateServiceModel" Condition="Exists($(ServiceDefinitionTransform))">
<Exec Command=""$(TransformRunnerExecutable)" @(TargetServiceDefinition) $(ServiceDefinitionTransform) @(TargetServiceDefinition)" />
</Target>
All I did, was add a condition to the Target - "Exists($(ServiceDefinitionTransform))" which stops the target running if there's not a transform file for it.
I then deleted my 2 unused transform files and was left with one similar to this:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xdt:Locator="Condition(@name!='' and @schemaVersion!='')">
<WebRole name="POMvc.Web" vmsize="Small" xdt:Locator="Match(name)" xdt:Transform="SetAttributes" >
<Sites>
<Site name="Web" xdt:Locator="Match(name)" xdt:Transform="Replace">
<Bindings>
<Binding name="HttpIn" endpointName="HttpIn" />
<Binding name="HttpIn_CO" endpointName="HttpIn_CO" hostHeader="www.XXX.org.au" />
</Bindings>
</Site>
</Sites>
</WebRole>
</ServiceDefinition>
Notice that I'm also changing the VM size to reduce cost for the less used deployment :)
Is this still working for you? I can't seem to get it to work, and am wondering if an Azure SDK update or something would have prevented this approach from working any more
ReplyDeleteAs far as I'm aware it does... I'll double check on Monday and get back to you
DeleteI double checked this morning and it's still working for me on SDK v2.9
DeleteThanks for checking Rob, I must be doing something wrong. I'm on 2.9 too, so I'll have another look and try again
DeleteIn case it helps anybody else, I was able to get this working with a similar approach...
ReplyDeletehttp://stevekennaird.com/different-vm-sizes-per-environment-azure-cloud-service-roles-csdef-transform