Triggers to deploy multiple octopus but share a common website

Hey Guys,

We are looking to using Azure Virtual Machine Scaling Sets in Azure… But have hit a little bit of configuration issue where we have multiple octopus projects using a common IIS website.

So the issue, we have 5 individual octopus projects that deploy a web application to the same IIS website (api.website.com) on the same server . None of the projects has a create IIS website step at this time. In its current state it fails because the “api.website.com” iis site doesn’t exist (as expected)

When a new server comes online, the triggers kick off on a first come first serve, so we would need to put the “Create IIS website” step under each of the 5 octopus projects. This would mean that each project would share duplicate variables, binding information etc. If we need to add an additional bindings we would need to do it 5 times to each project. Not ideal.

What is the best way to manage or handle this?

My current thinking is create a new octopus project that contains the “Create IIS website” step for "api.website.com which contains all the bindings etc. Then the next steps uses Octo.exe deploy-release to deploy the web applications to the new server. In this scenario the only application which has a trigger is the new octopus project.

Love to hear some different theories.

Ta

-Chris

Hi Chris,

Thanks for getting in touch! Your solution sounds great and it should work. I have two other ideas that you might want to consider.

The first one is based on Custom Step Templates. You could create a custom step template with either all relevant data already hard-coded or provided via variables. If the data is provided via variables then you could put them into a shared Library Variable Set. In this way you need to set it up once per WebSite but the updates should not take much time. This will be especially true with a new feature that we are working on right now that will allow you to update all steps at once.

The second idea would require you to change your deployment process and host each application in its own IIS WebSite. In this way both code and infrastructure for each site is completely independent and the order of deployments doesn’t matter. This more than likely would require some kind of reverse proxy in front of your websites so the change is not visible to the outside world.

Please, let me know what you think.

Regards,

Pawel

Hey Pawel,

I think I might have over thought this.

What I might do is write a small script on the web app deployment step to check if the site exists, if it doesn’t then wait x seconds (in this wait, the trigger for website creation should be running), recheck and progress or wait. Least this way I am using Octopus and its triggers to work.

Thoughts?

-Chris

Hi Chris,

This might work but then in your script you will have to distinguish between a failed WebSite Creation deployment and a WebSite Creation deployment that simply takes a longer than usually. Otherwise you might end up with with bunch of deployments that never finish.

Regards,

Pawel

Hey Pawel,

Yup I think I have covered that off… if after x amount of checking if the site exists the web app deployment fails. Which is what I want.

I do have one final step! After all the steps finish in the website creation project, I have a step that starts IIS itself. I want to check if all the deployments on the server are finished. What is the easiest way check if something is running on that box via Powershell or Octopus.Client? I seem to find it quite difficult to work out if there is an action on going on a machine or not. What I am trying below. Is there anything more direct as below feels quite dirty.

var tasks = repository.Tasks.GetAllActive();

            foreach (var task in tasks.Where(r => r.Id != thisDeploymentTaskId))
            {
                var deploymentId = task.Arguments.FirstOrDefault().Value;
                var deploymentStatus = repository.Deployments.Get(deploymentId.ToString()).SpecificMachineIds.Contains(ThisOctopusMachineId);
            }

Ta

-Chris

Hi Chris,

Not sure whether this is what you are looking for but you might want to have a look at repository.Client.List<TaskResource>("/api/machines/{MACHINE_ID}/tasks").

Regards,

Pawel

Hey Pawel,

Had a look, it appears that method doesn’t return tasks that are currently executing on the server. Only completed tasks… Any other recommendations?

Ta

-Chris

Hi Chris,

Unfortunately this API doesn’t return tasks in progress. It looks like you will have to go back to your previous solution as I don’t see any cleaner way of implementing your idea.

Please, let me know if this doesn’t solve your problem.

Pawel

Dammit, I do think I am making progress.

Maybe a simple question then, how can I get a list of machines used in a deployment? (if the machine hasn’t been specifically specified). It looks like when it’s a deployment via trigger then specificmachine ids is a null field.

I am looking at generating it via the operation below and filtering through the tree but that has potential edge cases where a machine id could be missed.

Using the TaskDetailsResource method (and some advise looking for the deployment package step http://help.octopusdeploy.com/discussions/questions/5624-machine-names-involved-in-deployment-through-api)

This will let me work out if that machine has been used. But it feels a little “meh”, for example if Octopus changes the label it could break it.

var taskDetail = repository.Tasks.GetDetails(task);
                    var machines = taskDetail.ActivityLogs.FirstOrDefault().Children.
                        First(c => c.Name.Equals("Acquire packages", StringComparison.OrdinalIgnoreCase)).
                        Children.SelectMany(x => x.Children).
                        Select(x => new Uri(x.Name.Replace("Upload package to ", null)).Host);

I can see that this information is available under a system variable of a deployment: Octopus.Deployment.Machines, is that available via an API?

Hi Chris,

Your idea with using Octopus.Deployment.Machines might be the cleanest solution. I was able to retrieve the information you are looking for using our API.

Please, let me know if this doesn’t solve your problem.

Regards,

Pawel

Hi Pawel,

Awesome… Looks like I can use that perfectly in my code… One question, what is the Octopus.Client object that API is returning? It doesn’t seem to like VariableSetResource or LibraryVariableSetResource?

Ignore me, went to use the variableSets method to get the values correctly :slight_smile:

-Chris

Hi Chris,

I’m glad you have a working solution.

Regards,

Pawel