I want to maintain a staging as well as a production environment in azure. Each should have it\'s own blob storage and sql storage. What wod be the best way to achive this? setu
Not really an answer, but I needed more characters than allowed in comments :)
I'm also dealing with the same problem. Having separate storage accounts and database server is the way to go however the challenge is to pick appropriate storage account/database from your configuration file as you could be deploying your code in either staging or production environment. The RoleInstance class does not have a way to distinguish between staging and production.
Only option you're left with is to invoke the Service Management API and figure out which storage account/database to pick. Add one more complication to this equation is when you do VIP Swap and all of a sudden your staging slot becomes production slot (and vice versa) and now you have to switch your storage account/database connection strings based on the new environment.
I would be very interested in hearing what other folks are doing.
Here is a step by step guide.
1) You need the library: Microsoft.Samples.WindowsAzure.ServiceManagement There is a nuGet package entitled "Windows Azure Service Management Library" which contains this.
2) You need create a X509Certificate2 and follow the instructions laid out here. Make sure you upload the .CER file you create to the Subscription Certificate store. Make sure you upload a copy of the .PFX with the PRIVATE KEY to the actual cloud service certificate store.
Create and upload a certificate for Windows Azure Management
http://blogs.msdn.com/b/clouddeployments/archive/2010/05/12/making-calls-to-the-service-management-api-from-a-service-running-in-windows-azure.aspx
3) These tutorials also gloss over this: you need to have the service endpoint defined. I did that in my app.config file with the following
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="WindowsAzureServiceManagement_WebHttpBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
<readerQuotas maxStringContentLength="1048576" maxBytesPerRead="131072" />
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</webHttpBinding>
</bindings>
<client>
<endpoint name="WindowsAzureEndPoint"
address="https://management.core.windows.net"
binding="webHttpBinding" bindingConfiguration="WindowsAzureServiceManagement_WebHttpBinding" contract="Microsoft.Samples.WindowsAzure.ServiceManagement.IServiceManagement" />
</client>
</system.serviceModel>
4) Once that is done, I created a static class named "GetServerInstance". Here is the code:
public static class GetServerInstance
{
const string SubId = "your azuresubscriptionid";
public static bool IsProductionEnvironment()
{
//get the current deploymentId
var currentInstance = RoleEnvironment.DeploymentId;
var mgmtChannnel = ServiceManagementHelper.CreateServiceManagementChannel("WindowsAzureEndPoint",GetCertifcate()); //make the endpoint.
var serviceDetails = mgmtChannnel.GetHostedServiceWithDetails(SubId, "your-cloud-service-name", true);
var currentDeploymentSlot = serviceDetails.Deployments.First(p => p.PrivateID == currentInstance).DeploymentSlot;
if (currentDeploymentSlot == DeploymentSlotType.Staging)
return false; //staging server
if (currentDeploymentSlot == DeploymentSlotType.Production)
return true; //production server
}
private static X509Certificate2 GetCertifcate()
{
string certificateThumbprint = RoleEnvironment.GetConfigurationSettingValue("CertificateThumbprint");
if (String.IsNullOrEmpty(certificateThumbprint))
{
return null; //I'd throw an exception here and log the error
}
var certificateStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certificateStore.Open(OpenFlags.ReadOnly);
var certs = certificateStore.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);
if (certs.Count != 1)
{
return null; //I'd throw an exception here and log the error
}
return certs[0];
}
}
5) Now in my worker role, which I never want to run on Staging, because it will charge people twice. I call this:
if (GetServerInstance.IsProductionEnvironment())
{
//Do work! I'm in production
};
This is how I manage my production/acceptance/test environments (note that I'm not using the word staging). For each environment, I create the following (depending on the project):
So let's assume I have an app called myapp, then my environments would look like this:
So all environments have a version of the app running in the production deployment slot. I only use the staging deployment slot whenever I want to do a VIP swap for my production environment (note the difference between production deployment slot and production environment).
There are a few advantages to this approach where you have dedicated components (like storage accounts) per environment: