When having multiple environments in Azure for WebRoles or WorkerRoles, it might not be neccesary to have the same performance everywhere. A testing environment, for example, usually has to handle a lot less work than an acceptance or production environment. Scaling this down can save a lot of money. One way to scale down is decreasing the amount of instances or undeploying the services outside of office hours. An additional method would be to lower the instance size. Whereas the number of instances can easily be modified in the .cscfg
file for a cloud service, the instance size cannot be easily changed per environment as it is stored in the .csdef
file.
Whatever your reason to change the .csdef
per environment, the default Azure SDK does not facilitate this behavior. It’s pretty easy though.
ServiceDefinitionLocator.targets
Create a new textfile in the root of your solution and call it ServiceDefinitionLocator.targets
. Its content should be:
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- Martijn Stolk - ICT Automatisering Use 'ServiceDefinition.[PROFILE].csdef' if it exists. Otherwise fall back to the default 'ServiceDefinition.csdef'. Note that this does not use the @ServiceDefinition entries. The file only needs to exist on the file system. --> <Target Name="ResolveServiceDefinition"> <Message Text="[ICT] Target Profile: $(TargetProfile)" /> <Message Text="[ICT] Service Definition: @(ServiceDefinition)" /> <Message Condition="Exists('ServiceDefinition.$(TargetProfile).csdef')" Text="[ICT] Found ServiceDefinition for profile $(TargetProfile)" /> <Message Condition="!Exists('ServiceDefinition.$(TargetProfile).csdef')" Text="[ICT] Could not find ServiceDefinition for profile $(TargetProfile)" /> <ItemGroup> <SourceServiceDefinition Condition="Exists('ServiceDefinition.$(TargetProfile).csdef')" Include="ServiceDefinition.$(TargetProfile).csdef" /> <SourceServiceDefinition Condition="!Exists('ServiceDefinition.$(TargetProfile).csdef')" Include="ServiceDefinition.csdef" /> <!-- The target service definition is in the output directory. --> <TargetServiceDefinition Include="@(SourceServiceDefinition->'$(OutDir)%(Filename)%(Extension)')" /> </ItemGroup> <Message Text="[ICT] Source Service Definition: @(SourceServiceDefinition)" /> <Message Text="[ICT] Target Service Definition: @(TargetServiceDefinition)" /> </Target> </Project>
Environment-specific ServiceDefinition files
Use the Manage Configuration
option to create the configurations for which you also want different .csdef
files. Don’t worry if you have more configurations than the amount of .csdef
files you want. There’ll be a fallback to the default ServiceDefinintion.csdef
.
Now we’ll need to create the ServiceDefinition files we want.
The Azure SDK doesn’t like multiple .csdef files, so you can’t copy/paste them in VS2015 itself. Open your project folder with explorer and make the neccesary copies of your ServiceDefinition file. In our example we’ll create three: ServiceDefinition.T.csdef
, ServiceDefinition.A.csdef
and ServiceDefinition.P.csdef
.
We’ll add those files to the project in the next step.
Cloud project file
Unload and edit the cloud project file (.ccproj
) and add the following line at the bottom, just above the “ end tag.
<Import Project="$(SolutionDir)\ServiceDefinitionLocator.targets" />
While you’re here, add the copies of the ServiceDefinition to the project. There can only be one ServiceDefinition, so the copies will have to be created as Content
type.
<ItemGroup> <ServiceDefinition Include="ServiceDefinition.csdef" /> <Content Include="ServiceDefinition.T.csdef" /> <Content Include="ServiceDefinition.A.csdef" /> <Content Include="ServiceDefinition.P.csdef" /> <ServiceConfiguration Include="ServiceConfiguration.T.cscfg" /> <ServiceConfiguration Include="ServiceConfiguration.A.cscfg" /> <ServiceConfiguration Include="ServiceConfiguration.P.cscfg" /> <ServiceConfiguration Include="ServiceConfiguration.Local.cscfg" /> <ServiceConfiguration Include="ServiceConfiguration.Cloud.cscfg" /> </ItemGroup>
Reload the project file. You’ll see the ServiceDefinition files there.
Modify csdef files
You can now customize the csdef files for each environment. Take note that:
- you’ll need to manually keep the environment-specific copies of the
.csdef
files up to date. Adding new configuration settings won’t automatically update your copies. The same counts for tasks, endpoints, etc. - you’ll need to create a package, or publish the project, while the correct Service Configuration is selected.
Or, from the msbuild
command line, you’ll have to add the /p:TargetProfile=T
parameter to your publish/package command.
Recent Comments