Is it possible to affect the value of a variable in subsequent deployment steps?

Hi,
I’m trying to minimize the number of variable sets and variables that we are maintaining so this led me to wonder if I’m able to set the value of a variable in a variable set on an earlier step of a project so it can be used in latter steps of the same project when a web.config entry is patched. Let’s say this variable MQServer holds the machine name responsible for processing messages and I use it later to update values in web.config. This variable needs one value per environment and the value needed is exactly the machine name with the role of “QueueServer” for that environment. To accomplish, this is what I set out to do:

1). On the project, I referenced the variable set which contains MQServer variable.

2). I created a powershell function which obtains an array of machine names (not ids) that belong to an environment and filter the result when they match a given role and tenant id. This powershell function was saved as a script module which I referenced in the same projecct. In step 1 called “Calculate Prerequisite Variables”, I call this function and I’m able to echo the result of this function so I know it works. I then call Set-OctopusVariable -Name ‘MQServer’ -Value MyMessageMachine. The variable name is intentionally the same name as in the variable set.

The function looks like this:

function Get-OctopusMachineNamesInScope
{
[OutputType([string[]])]
param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Role
)

$OctopusAPIKey = $OctopusParameters["Octopus:Deployment:ApiKey"]
$OctopusUrl = $OctopusParameters["Octopus.Web.BaseUrl"]
$Header = @{ "X-Octopus-ApiKey" = $OctopusAPIKey }

$Machines = Invoke-Restmethod -Uri $OctopusUrl/api/environments/$EnvironmentId/machines -Headers $header -Method Get

return ($Machines.Items | Where-Object { $_.roles -Contains $Role -and $_.tenantids -contains $TenantId } | Select-Object -ExpandProperty Name)

}

I was hoping that in step 3 and 4 where I deploy two asp.net webpps, that the patching process works. I have a web.config entry with a key name equal to a variable in the same set as MQServer. In this example, le’ts call it MQPath where the value is composed from #{MQServer}\myqueuename. I purposely seeded MQServer variable in the variable set with the value “ReplaceMe” so I can tell if it’s being replaced or not. Unfortunately, it is not since the value I’m seeing in the web.config is not MyMessageMachine.

Steps 2 and 3 are using a custom step template I created for deploying iis webapps. It uses the built-in “Deploy to IIS” step template with the following features enabled: custom installation directory, custom deployment scripts, configuration variables, configuration transforms, and substitute variables in files. I’ve created parameters to this step template so I can pass the nugetpackageid, the webappname, parent website name, and 3 application pool settings related to timeouts and recycling. Inside the step template, I’m able to calculate the value of a CustomInstallationFolder in the pre-deploy step just in time for me to reference it as #{CustomInstallationFolder} in the Custom Install Directory “Install To” textbox. This part works due to the way features are ordered relative to another.

Since I intend this step template to be generic, is there a way for me to take the value I obtained in step 1 and pass it somehow to steps 2 and 3 either as parameters to their step template or by updating a variable that would be visible to steps 2 and 3? I thought about using output variables but that would couple this step template to the first step and thus, no longer generic.

Thanks in advance.

Hi Tristan,

Thanks for getting in touch! Your issue is intriguing, yet I think to better help you out I’ll need you to attach a deployment log with variable logging enabled to see exactly what Octopus is doing here.


Attaching the log with the above logging enabled will help me find a potential solution here or point you in the right direction. :slight_smile:

Looking forward to hearing from you.

Best regards,
Daniel

Hi Daniel,
Thanks for getting in touch. Incidentally, I actually was able to find an alternative, but I still feel it’s somewhat of a hack. In the custom step template which I mentioned above, I added a machineparameterlist string parameter which expects parameters in the form: machinevarname=octopusrolename;machinevarname2=octopusrolename2 etc. The parameters to the left of the equal sign must match a project variable of the same name for variable replacement to work as expected.
Within the pre-deploy script phase of that step template, I’ve added the powershell function Get-OctopusMachineNamesInScope. My intent is to call this function if machineparameterlist is not null and not empty. With the results from the function, I use Set-OctopusVariable with -Name matching machinevarname. This method works so far and I’m able to properly replace values in variables. I still need to handle scenarios that would result in multiple machine names (such as the mongodb connection string uri for a clustered configuration https://docs.mongodb.com/manual/reference/connection-string/), so a variation to the convention I use in machineparameterlist needs to be considered. When multiple values are expected, then I would like to be able to set a delimiter.

    I'll also try to repro the project in its prior state and provide the log. I feel it's a better solution than the hack I've temporarily put together just to be able to meet deadlines. Even better, if there was some kind of a built in function similar to Set-OctopusVariable but instead one that performs something similar to what I do in Get-OctopusMachineNamesInScope sans the rest api call, that'd be even better. I'm also realizing that none of the fields I have from Machine is giving me the FQDN. Instead, I'm having to use the Uri which includes https://<fqdn>:10933/ with the string replace method twice to strip out https:// and :10933/.