Update variables in $OctopusParameters dictionary with custom powershell step

Hi everyone.
I want to update Octopus.Deployment.ExcludedMachines (which is in $OctopusParameters) in my custom (Run a script) powershell step and use it in the next steps of the deployment. I use some prompted variables to specify which machines should be excluded.

Is there a way to directly update the value of Octopus.Deployment.ExcludedMachines in $OctopusParameters dictionary during deployment process?

Hi @ant261089,

Thanks for getting in touch, and welcome! Great question, though unfortunately it won’t be possible to modify this variable mid-deployment in this way. The best long-term solution might be to remodel your target roles. E.g. which roles are assigned to each machine, and the deployment steps to run on each applicable role. This would control which machines each step run on in a predictable manner.

Otherwise, I think the approach to get closest to the desired outcome via variables would be the following.

I’ve created two variable values, one scoped to each step (we can’t use a prompted variable for this case unfortunately, as prompted variables can only be scoped to environments or processes). Each contains the value of a machine’s ID, scoped to the step you want it to not be run on.

Then I created the following variable run condition and applied it as-is to each step.

#{unless Octopus.Machine.Id | Match #{ExcludedMachines}}True#{/unless}

The step will evaluate the condition for each machine the step is running on, and skip the step on the machine that is defined in the variable scoped on each step.

Unfortunately this would then mean you would need to modify the project variable pre-release creation in order to apply the changes.

I’m sorry it’s not the most elegant solution! Let me know what you think, or if you have any further questions or concerns going forward.

Best regards,

Kenny

Hi @Kenneth_Bates.
Thank you for the response. This doesn’t seem to be a working solution. We have >5000 projects with different processes and roles. Also we use another run condition variables for steps. It’s quite difficult to update all processes for those projects. I played around with Output variables but no luck. For example I set
Set-OctopusVariable -name “ExcludedMachines” -value “list of machine ids” in custom step
Octopus.Deployment.ExcludedMachines = #{Octopus.Action[MyStep].Output.ExcludedMachines} in project.
So I need a variable that I can define in custom step and push it to Octopus.Deployment.ExcludedMachines for all other steps. It will be much easier to add a step using API script rather than update all kind of processes. Do you have any ideas how it can be done?

Hi @ant261089,

As mentioned by Kenny, it isn’t possible to update the Octopus.Deployment.ExcludedMachines system variable during a deployment.

Can you provide some additional details on the scenario leading to the requirement to exclude machines during a deployment? It may be that we have other options available.

For example, changing the transient deployment setting may work for you if these are targets that will be unavailable during the deployment.

Regards,
Paul

Hi @paul.calvert.
It’s not about unavailable targets. We need to manually control which “server set” is used for deployment.
I use prompted variables to specify which servers are going to be used in the deployment. Like Deploy.1st.set = true. I get the value of this variable in the custom step $OctopusParameters[“Deploy.1st.set”] and use some conditionals to specify excluded targets. We have many complicated deployment processes and it’s almost impossible to change them all. The only thing I can do is adding a new custom step (with API script that I wrote) or play around with variables (in project or library sets).

If this is to control which servers the deployment should target, then the best way would be to configure this outside of the deployment process.

A couple of ideas come to mind.

When deploying a release, you can include or exclude targets. You could either manually set these or use the CLI, script or orchestration project to set the desired server set programmatically.
e.g.

The other option would be to use Tenants and Tenant Tags to group your targets into these “server sets” and then you can simply deploy to the relevant Tenant/set as needed.

Thanks for the reply, but it’s different. I know that servers can be excluded manually before deployment but imaging if you have to select 10-50 servers. I can filter them with powershell logic by name and put to one variable but I can’t use it in the deployment. Not sure why this is not working Output variables | Documentation and Support
I set Octopus.Deployment.ExcludedMachines = #{Octopus.Action[MyStep].Output.ExcludedMachines} in project and I see the same value (#{Octopus.Action[MyStep].Output.ExcludedMachines}) in deployment log file in the next steps. Do I have to do smth to have the value from custom step in the following steps?

Hi @ant261089,

Thanks for keeping in touch! This is proving to be a bit of a tricky situation to approach. The Octopus.Deployment.ExcludedMachines system variable is applied to the deployment as a whole, and isn’t able to be changed mid-deployment for certain steps, so I don’t think this will be able to contribute to the solution.

The only alternative that seems possible to what I mentioned earlier would be what Paul mentioned. E.g. grouping your targets into logical sets and using scoping on each step to control what is run where. Though I can imagine that would probably create a lot of overhead to re-architect these projects. I’ve brought this up internally to see if we can think of any other ideas that might be easier via any variables, and I’ll let you know any ideas that might arise from that.

Best regards,

Kenny