Nesting variable references

Is it possible to nest variable references? Something like this non-working example is desirable -

#{#{Octopus.Deployment.Tenant.Name | Replace "\W"}.SomeValue}

#{One.SomeValue}

The following was also considered, but also fails -

$OctopusParameters['#{Octopus.Deployment.Tenant.Name | Replace "\W"}.SomeValue']

System.Collections.Generic.Dictionary`2[System.String,System.String]['One.SomeValue']


The long story

This need is driven by the lack of tenant common environment variables, which means the following steps are required -

  • Create a library variable set per tenant (meaning that a variable can have different values per environment).
  • Create a additional library variable set and add a variable template for each variable in the sets created above.
  • Attach all of the above library sets to the relevant projects.

Now it is possible to reference the relevant set for tenant common variables. For example, a library variable set called Tenant One Variables contains the variable One.SomeValue. This means that in the tenant common variable template for that variable, #{One.SomeValue} can be specified.

To lessen the burden it would be great to specify a default value for tenant common variables, in the format of #{<Tenant>.SomeValue}. However, to do this a nested variable reference is required, and I’m unsure if this is possible.


As a bonus, is there any news on GitHub issue for variable unification? The ticket was created 3.5 years ago, but there has been no comments from Octopus from 2 years despite some people (including me :stuck_out_tongue:) asking for an update.

Greetings @dgard1981, thanks for reaching out! Yes, it is possible to nest variable references using the Replace filter. I tested this with the following,

#{Octopus.Project.Name | Replace "Test" #{One.SomeValue}}

I ran a script step with the following code

Write-Host "It is $($OctopusParameters['MyVariable'])"

image

Hope this helps!

Regards,

Shawn

Thanks for the reply, but I’m afraid that is not working.

Using the following (and assuming the same single environment for everything) -

  • A library variable set called “Test Set” with…
    • a variable where name is “One.SomeValue” and value is This is a test.
    • a variable template where name is “SomeValue” and default is #{#{Octopus.Deployment.Tenant.Name | Replace "\W"}.SomeValue}.
  • A project called “Test” with the ‘Test Set’ library variable set attached, containing a single script step…
    • Write-Host '#{SomeValue}'
  • A tenant called “One” with the ‘Test’ project attached.

Now when I deploy a release of the ‘Test’ project to the ‘One’ tenant, I would expect the script to write the value This is a test, but it doesn’t, it writes #{#{Octopus.Deployment.Tenant.Name | Replace "\W"}.SomeValue}.

If I make the default value for the template ‘SomeValue’ #{One.SomeValue}, then it works as expected. However, that defeats the object of being able to dynamically specify the variable to reference through the default, and instead would mean that I’d need to supply a value for every tenant variable template.

Ah, okay, I think I’m following what you’re attempting to do, thank you for providing clarification. If I may, what problem are you attempting to solve with the replacement in this way?

This is required because Tenant variables have not been implemented particularly well. As I’m sure you know, the only options we have are -

  • Common variables, which cannot be environment specific.
  • Project variables, which must be environment specific.

Project variables sound great in theory, but when you have many projects (16 in my case) that all require the same variable but with a different value for different environments it becomes a nightmare to manage.

My plan is to add tenant variables to a library variable set so that I can scope variables appropriately, add the set to every project, and then have tenant common variables reference the variables for the relevant tenant. To make things a bit simpler I was planning to set a default for all common template variables so that the relevant variable from a library variable set was automatically referenced.

This is why I’m wondering if the variable unification work is actually progressing, as I’m sure it isn’t just me that finds tenant variables inadequate.

I’m not sure if this helps or not, but it is possible to have Common variables be environment specific, you just have to get a little creative :stuck_out_tongue: You can have something like a Project variable where the value of the Project scoped variable is the variable in the Common template

image

Regarding the replacements that you were attempting to do, you could define it this way

then within your script, reference it this way

$VariableName = '#{SomeValue}'
$SomeValue = $OctopusParameters[$VariableName]
Write-Host "SomeValue: $SomeValue"

Hope this helps!

Regards,

Shawn

An interesting take, but I think not really tenable. Imagine you have 5 environments, you’d have to have 5x variable templates for every variable. It would be a monumental task to configure, and very easy to make a mistake. The complexity and chances of making a mistake would greatly increase for every environment that is added.

With regards to the replacements - the trouble is, I am not making replacements in scripts, so to not have proper values at runtime is a killer for me. For example, I want to replace a tenant variable in a YAML file, so I can’t your example above.

I’ll throw it out there one more time - this is why I’m very interested in the variable unification work, and whether or not it is actually progressing?

Also, I’ve come across another problem with tenant variables… I seems like it’s not possible to reference a special value from a library variable set. For example, if I set a variable to be either sensitive or an AWS account in a library variable set, then reference that variable in a Tenant, then finally reference the tenant variable in my project, it fails.

I’ve reached out internally to see if I can find out more information on that topic, I’ll keep you posted :slight_smile:

I forgot to mention that the engineers are Australian based so it may take some time to get a response.

I’ve heard back from the engineers, I’m sorry to say that variable unification isn’t something that is being worked at this time.