How can I share tenant variables between projects?

The Tenants feature is a great way to deploy different versions and configurations of the same application to different customers, regions, etc at different times.

One question that comes up every now and then is how to share tenant variables across projects. Perhaps you need to use the same environment scoped database passwords, API keys, or hostnames for the same tenant across multiple projects.

There is not an easy way to do this with tenant variables in Octopus today, but I have created a work around that will accomplish this.

Note: Like with any example, please review and test before adding to your process.

Tenant Common Variables

This work around centers around Tenant Common Variables. These are variable templates that are configured in a libarary variable set and can be shared across projects.

A detail of the common variable templates that makes them not the obvious choice in the scenario is that they are not automatically scoped to environments like the project variable templates are. But we can use a clever trick to simulate this.

I’ve created a libary variable set named “Shared Tenant Variables”. In that set, I navigated to the Variable Templates tab and added the following templates.

As you can see in the screenshot above, I’ve created environment specific templates for a database connection string. Let’s look at the first one.

I set the label to “Dev Database Name” but it can be more specific if you want to put your product name or team name in the label. I set the variable name to “Financial.Tenant.Database.Name.Dev”. That’s a bit of a mouthful but each part means something. Financial is my imagined product suite. Tenant means that this is a tenant variable. Database means that it is a database setting for the tenant. Name signifies that this is the database name value. The Dev on the end means that this is for the development environment. I also gave it a default value that will substitue in the tenant name. If you have values that will follow a format like this, the variable substitution can save you a lot of time.

I’ve created one of these for each environment, Dev, Test, and Production. I’ve also created templates for the rest of a connection string, Database Server, Database User, and Database Password.

In all, I have 12 variable templates. If you have a lot of shared variables. This will be tedious to set up because you have to create a template for each environment. On the other hand, you don’t have to create project variable templates in each project and duplicate the values. I highly recommend taking a look at our API and scripting out the creation of these variable templates.

Note: Because these templates are not tied to environments and projects like the project templates, a tenant that is only tied to the production environment will still be able to have values for Dev and Test even though they are never used.

Variables

Once I have my templates set up, I go to the Variables tab and add in the piece that makes environment scoping work.

In the screenshot above, you can see that I’ve created a variable named “Financial.Tenant.Database.Name”. This is the same name as the variable templates but without the environment prefix. I then set up three values corresponding to the environment specific templates and then scope those to the appropriate environment. I have configured this for each of variables I’m using for the connection string.

And finally I have an unscoped variable named “Financial.Database.ConnectionString” with a value of “Server=#{Financial.Tenant.Database.Server};Database=#{Financial.Tenant.Database.Name};User ID=#{Financial.Tenant.Database.User};Password=#{Financial.Tenant.Database.Password};”.

This variable will be used in the projects and references the environmentally scoped variables that in turn reference the common tenant variables.

Project Settings

After configuring the library, I go to my tenanted project and include the “Shared Tenant Variables” set in its variables. Once that’s done, we can go to our tenants and configure the common variable values. But first, we’ll add a step that prints the variable value.

The step is a Run a Script step with the following inline script.

Write-Highlight $OctopusParameters[“Financial.Database.ConnectionString”]

Tenants

Then I go to one of my tenants and access the variables section. There I choose the “Common Variables Tab” and expand the “Shared Tenant Variables” section. Here I can change any of the default values and add the passwords for the tenant database user.

Deploy It

Now that we’ve configured this, let’s go back to the project and deploy a release for our tenant “Internal”.

And there it is. We have a tenant and environment specific variable that we can share across multiple projects.

If you’ve used this method to share tenant variables or have found another solution, share your experience in the comments.

1 Like