Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transform ServiceDefinition.csdef

I have tried every possible example I can come across yet have not been able to make a single one of these work. Has anyone managed to get a ServiceDefinition.csdef transform to actually work?

During each of the below attempts, I have used the ServiceDefinition.csdef in the Bin folder (after build) and then looked at the csdef in the package file. I was setting vmsize in the 'base' or original file to 'Other' (I know this is not a real size) and then uses a transform that should have changed it to 'Large' but the final file always showed 'Other'.

Fabriccontroller.net's Example

SkyLineTechnologies' Example

MSDN Blogger's Example

And about 3 or 4 others...

We build Umbraco based websites and host them on Azure. We setup 3 environments (QA, UAT, and LIVE) and on each environment we have 2 Web Roles (Front End and Back Office). The goal of transforming the ServiceDefinition.csdef is so that the following vmsizes are reached:

QA-FE: Small
QA-BO: Small
UAT-FE: Small
UAT-BO: Small
LIVE-FE: Large
LIVE-BO: Small

I also want to point out that I tried creating multiple Cloud Service Projects but as you can see by the requirements above, this makes it a bit 'odd'

Finally, the transform must be able to happen on our TFS Build Server (vNext).

like image 280
Jason H Avatar asked Mar 11 '23 12:03

Jason H


1 Answers

I came up with my solution after reviewing a lot of different suggestions I found that parts of them worked but others did not. I ended up combining and simplifying what I found to work into this.

For this example, we have the following requirements:

  • We need the Build Configuration to match our environments
  • Since the latest version of Azure Cloud Services supports multiple Service Configurations we can set that up via the build in options, in our case we make it match our Build Configurations as well.
  • We need to be able to publish via local (VS) and TFS Release Manager (via a Build Agent).
  • We will have 3 Environments with different size VMs
    • QA (small)
    • UAT (Large)
    • LIVE (XLarge)

Go to the Project Folder for the Azure Cloud Services Make a copy of the ServiceDefinition.csdef and name it ServiceDefinition.Base.csdef Add 3 files, ServiceDefinition.QA.csdef | ServiceDefinition.UAT.csdef | ServiceDefinition.LIVE.csdef Unload your Project in Visual Studio and edit the ccprog file Find the ItemGroup that contains the ServiceDefinition.csdef, which will look like this:

<ItemGroup>
    <ServiceDefinition Include="ServiceDefinition.csdef" />
    <ServiceConfiguration Include="ServiceConfiguration.QA.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.UAT.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.LIVE.cscfg" />
</ItemGroup>

Make it look like this:

<ItemGroup>
    <ServiceDefinition Include="ServiceDefinition.csdef" />
    <ServiceConfiguration Include="ServiceConfiguration.QA.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.UAT.cscfg" />
    <ServiceConfiguration Include="ServiceConfiguration.LIVE.cscfg" />
    <None Include="ServiceDefinition.Base.csdef" />
    <None Include="ServiceDefinition.QA.csdef">
       <DependentUpon>ServiceDefinition.csdef</DependentUpon>
    </None>
    <None Include="ServiceDefinition.UAT.csdef">
       <DependentUpon>ServiceDefinition.csdef</DependentUpon>
    </None>
    <None Include="ServiceDefinition.LIVE.csdef">
       <DependentUpon>ServiceDefinition.csdef</DependentUpon>
    </None>
</ItemGroup>

Now go to the bottom of the ccprog file and between the Import

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets" />

and the closing Project Tag

</Project>

Add the following:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets" />
<Target Name="BeforeBuild" Condition=" '$(Configuration)' != 'Debug' ">
    <Message Text="Removing Read-Only Attribute from ServiceDefinition.csdef" />
    <Exec Command="attrib -r $(ProjectDir)ServiceDefinition.csdef" />
    <Message Text="Transforming ServiceDefinition.Base.csdef with ServiceDefinition.$(Configuration).csdef to create ServiceDefinition.csdef" />
    <TransformXml Source="ServiceDefinition.Base.csdef" Transform="ServiceDefinition.$(Configuration).csdef" Destination="ServiceDefinition.csdef" />
</Target>

Save and Reload the project, if any error messages come up, correct the issue. Upon reload, your project file should look like this:

enter image description here

Open the ServiceDefinition.QA.csdef and add this:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="AzureCloudTransform" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" schemaVersion="2015-04.2.6">
  <WebRole name="WebApplication" vmsize="Small" xdt:Transform="SetAttributes" xdt:Locator="Match(name)">
  </WebRole>
</ServiceDefinition>

Save

Open the ServiceDefinition.UAT.csdef and add this:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="AzureCloudTransform" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" schemaVersion="2015-04.2.6">
  <WebRole name="WebApplication" vmsize="Large" xdt:Transform="SetAttributes" xdt:Locator="Match(name)">
  </WebRole>
</ServiceDefinition>

Save

Open the ServiceDefinition.LIVE.csdef and add this:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="AzureCloudTransform" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" schemaVersion="2015-04.2.6">
  <WebRole name="WebApplication" vmsize="XLarge" xdt:Transform="SetAttributes" xdt:Locator="Match(name)">
  </WebRole>
</ServiceDefinition>

Save

Done.

Now when you build in one of the Build Configurations, the transform will happen before the build which then allows VS to just run normally for the packaging of the files. The ServiceDefinition.csdef file will change prior to the build and be included in the package correct. The biggest reason I chose to do this transform this way is because it work on our Build Servers which are using vNext Build Definitions.

like image 63
Jason H Avatar answered Mar 16 '23 21:03

Jason H