2 followers Follow

Deploying to Microsoft Azure Deployment Slots

This scenario is hard to explain, but here goes.

We are leveraging XL Deploy to perform deployments to Microsoft Azure Deployment Slots. Each environment has 2 slots; staging and production. Here is a cool article on slots for anyone who is reading this and wondering what they are --

The solution we're implementing is to create to types of infrastructure; azure.stagingGateway and azure.productionGateway. We're treating the staging slot as it's own environment that will contain the Infrastructure CI of type azure.stagingGateway. Similarly, the production slot is an environment that contains an azure.productionGateway CI.

When deploying to staging, the plug-in we've created will leverage the Azure Powershell cmdlets to perform the azure deployment if the target container type is azure.stagingGateway. When deploying to production, the plug-in will again leverage the Azure Powershell cmdlets, but this time rather than deploy anything, we're just swapping the 2 slots. We can get the different behavior again by checking the container type we're targeting and ensuring it is azure.productionGateway.

Because it is a swap, we will need to bake in some checks to ensure that the version being deployed to the production slot matches the version currently deployed to the associated staging slot.

Here is the challenge: after we swap as a result of deploying to the production slot, we would like to reflect that the staging environment now has whatever version was previously deployed to production, which could include no version upon initial deployment to production.

It's not immediately obvious to me how we might accomplish this, and I'm looking for suggestions.

Also, I'm curious... for anyone who has made it this far and understands what we're doing, does this approach seem reasonable and like it should work? Is there a better way we could be doing this?

Any input would be greatly appreciated.

Josh Figler

Please sign in to leave a comment.



Does anyone have any input on how I might update an environment that I am NOT deploying to in order to reflect the swap that occurs in Microsoft Azure?

I'm referring to the section of the original post where I say "Here is the challenge"...

Josh Figler 0 votes

Side note: Does freemarker work in in synthetic properties in XLD 5.0.1? I thought it used to anyway...

For example, I have a property like this:

<property name="createVerb" hidden="true" default="&lt;#if deployed.container.type == &quot;azure.ProductionGateway&quot;&gt;Swap&lt;#else&gt;Deploy&lt;/#if&gt;" />

I'm trying to dynamically set the verb for CREATE in the synthetic depending on the target container type. However, it does not process the freemarker when viewing the deployment plan -- it just spits out the freemarker unprocessed.

I got this idea from the old cmd2 plug-in on the community plug-in site -- it used to have freemarker in the synthetic for the alwaysRun property.

Josh Figler 0 votes

Hi Josh

Thanks for posting! Sorry for the delayed response - this has just bubbled up. To answer your second question first:

Does freemarker work in in synthetic properties in XLD 5.0.1? I thought it used to anyway

From what I recall, FreeMarker is not supported in properties in general. The wrinkle here is that, in some plugins, some properties happened to be passed through FreeMarker before being used, so in a few places this works. But that's a plugin-specific implementation decision, really.

With rules, every attribute of a step can be an expression (more specifically, a Jython expression), which should allow you to create the kind of dynamic step description you're after.

And now on to the bigger question... ;-) The first part of my response would be that, in general, every deployment in XLD takes one (or more, as per 5.x) deployment packages to one environment, so there's unfortunately no obvious way to have two environments updated at the same time using steps or processors.

The most "realistic" way to model what's happening would probably be to model the slot as a container and simply move the container from the staging to the prod environment, and vice-versa. But of course that won't work well from a reporting perspective because it won't update the versions of the deployed applications.

The most workable solution that comes to mind at this point would be to configure a trigger or step in the deployment to the prod environment that would "skip'n'commit" a downgrade deployment to the staging enviornment, too.

That would result in every production deployment effectively creating two entries in the deployment log (the upgrade in prod and downgrade in staging), but that's not too far away from what's actually happening.

Does that make some kind of sense?



Andrew Phillips 0 votes

Thanks for the response on both fronts, Andrew.

I have been working on implementing an Azure solution, and the one I came up with so far was to leverage the CLI to "patch up" the repository to represent that the swap took place when performing a deployment to the production slot. By "patch up" I mean to copy the udm.DeployedApplication that is currently in deployed to the production slot (if any), and all of it's properties (deployeds, version, orchestrators, etc), and apply that udm.DeployedApplication back to the associated Staging environment.

I'm thinking I'll use an xl-rule to just add a step at the end to do all this work.

The down side that I see here is that it won't show up in the reports for the Staging environment. It'll just be different with no indication of what happened. Is there a way to remediate that?

The upside that I see here is that it more accurately represents the swap because of things like manually changed dictionary values, partial deployments, etc.

For example, when deploying to the production slot (swapping), if I copy the deployeds from production to staging, I'm guaranteed to capture all that information. With the "skip'n'commit" approach, I don't know how I'd do that? Or it might be a bit more difficult to do so anyway?

I have the actual swap working in Azure, but I am still at the beginning stages of figuring out how to get the repository up to snuff as a result of the swap, so I could still change gears here if you think the way I'm heading is not optimal.

Thanks for the input -- I find it very valuable.


Josh Figler 0 votes

Hi Josh

Watch out, small essay to come... ;-)

I have been working on implementing an Azure solution, and the one I came up
with so far was to leverage the CLI to "patch up" the repository to represent
that the swap took place when performing a deployment to the production slot.

That's the approach I was originally also going to suggest, but didn't due to the reporting issue. Thinking it over a little more, I suspect the best approach will depend on the following questions:

  1. Do we consider a "slot update" a full deployment?
  2. How much else is happening during these deployments?

I'm basing these on the following model (which may be quite different from how you've actually set things up):

  1. The "slot deployment" part is represented by a deployed (azure.CodeDeployedToSlot or whatever), going to an azure.Endpoint or similar container
  2. A deployment package may consist of not just the Azure deployable (of type azure.CodeToBeDeployedToSlot, or whatever), but also of other components

For simplicity's sake, I started out with the following assumptions:

  - code-v1 (azure.CodeToBeDeployedToSlot)
  - db-v1 (sql.SqlScripts)

  - code-v2 (azure.CodeToBeDeployedToSlot)
  - db-v2 (sql.SqlScripts)

Then, I considered what happens if we have App/v2 deployed to the QA slot, and App/v1 in the Prod slot. Then we'd also have db-v2 in the QA environment and db-v1 in Prod. If we now carry out a deployment of App/v2 to Prod with a slot swap, would we would end up with is:

In QA:

  • deployed-code-v1 (swapped out from the Prod slot)
  • executed-db-v2 (from the App/v2 version previously deployed)

In Prod:

  • deployed-code-v2 (because we just deployed App/v2)
  • executed-db-v2 (because we deployed the DB alongwith the app)

In other words, in the general case the state in QA after the slot swap is neither "v1 is deployed" or "v2 is deployed" - it's actually an "in between" state that, in the above case at least, is probably broken.

To fix the above case in general, the theory would be to carry out the following two steps:

  1. Update the DeployedApplication in QA (whether by a direct call or through e.g. discovery) to reflect the "in between" state. In the example, we would only be modifying one of the deployed items, though.
  2. Deploy App/v1 to the QA environment, which would downgrade the database to match the app code. Because the repository has already been updated (in the previous step) to reflect that fact that deployed-code-v1 is already in place, XL Deploy should only trigger a NOOP action and not try to deploy the code again.

A slightly less "theoretically pure", but perhaps more convenient approach would be to skip the first step, but implement the MODIFY action to do nothing if the desired version is already in place (which is how provisioning tools tend to handle this issue). XL Deploy would try to downgrade the code to deployed-code-v1, thinking that deployed-code-v2 is still in place, but the implementation wouldn't actually do anything. Or we could programmatically skip the appropriate step(s) as "not required".

The end result in both cases would be a hopefully functioning App/v1 in QA, where all components of the app are back at v1, and an entry in the deployment log to record the (true) fact that an update deployment in QA was also carried out.

So much for the general case. If the deployment package only contains the code, we don't really need the update deployment in QA to get all the components back to the correct version. Then the question becomes whether we consider what happened in QA as part of slot swap a deployment at all.

Based on the above reasoning, I'd be tempted to consider it more of "side effect" of the Prod deployment, to be recorded - as you suggest - by an update to the repository, rather than an entry in the deployment log. If we want to carry out an actual deployment in QA - which we probably should, since otherwise things like the Release Dashboard will be out-of-sync, we should probably consider adding the "downgrade deployment" as a second step.

Hope that makes some kind of sense!



Andrew Phillips 0 votes

Hi Andrew -- thank you for this response.

We decided to go the approach of the skip'n'commit deployment because:

  • We are considering a staging/production slot update a full deployment
  • Not much else is happening during these deployments.

The implementation is going wall, and I'd say we're about 70% complete. We're using a jython step to do the skip'n'commit deployment back to the staging slot environment when we are deploying to the production slot environment.

Thanks again for the help.


Josh Figler 0 votes

Hi Josh

The implementation is going wall, and I'd say we're about 70% complete.

Thanks for the update! Glad to hear things are moving along. Looking forward to finding out how it all works out in the end!



Andrew Phillips 0 votes