We have some custom sections in some of our Web.config files, like so:
@@@
@@@
What I would like is to have some of these be replaced with OD variables too. Of course it is complex because it is not a 1-to-1 any more.
I’ve looked into the “XML transformations” feature, but from what I understand I cannot use a OD variable anywhere in the XSLT code, and so I will not be able to get the OD variables that way.
I’ve also looked into creating a powershell that could apply XSLT from a OD variable, or replace OD variables into a static XSLT code before applying it to the config file. I’ve not been able to complete it and to be honest that way feels like reimplementing some stuff that OD is already doing.
I was just wondering if anyone else has experience around this?
…or how does OD recommend dealing with config values that need to be replaced but are nested into the config?
…f.ex. SOAP endpoints / URLs defined in Web.config that should be replaced by OD must be a common problem?
The best way to work with Octopus Deploy in this situation would be to do the substitutions in a transform file.
There are some examples and detail in the following blog post:
What if I need to replace/transform the config to contain a value from
Octopus Deploys variables?
If I understood correctly I will not be able to do this with the config
transforms. The best I could do was to create separate transforms with
the same names as my environments, right? That would mean I cannot keep
my config administrable in the OD webinterface any longer… I want that.
The trick to achieving this is to use the transform file as the target of variable substitution. This makes it possible to ‘for-each’ over a set of values, if I understand correctly that this is your goal.
(You can use your Web.config file itself as the target of variable substitution, but this will mean it is no longer valid XML, which is inconvenient during development.)
Assuming you have one or more transform files targeting the Web.config file, in the transform file you can use expressions like:
#{each server in Servers}
<Server Name="#{server.Name}" Host="#{server.Host}" ... />
#{/each}
Your Octopus variables can then contain entries like:
It took me some time to get this working. Here are some tips for people that read this:
In your example you use #{each server in Servers}. The variables then need to be called Servers[Cache].Name (plural) instead of Server[Cache].Name (singular).
Also, I wanted to have this substitution take place on my Web.config. However, I had setup my Web.Release.config to paste in the OD #{each...} statement. I found that the variable substitution runs before the config transformation, hence I had to perform the substitution on Web.Release.config instead of Web.config.
Yes, I see mr. Blumhardt had a small typo in his example, you are right,
it should have been said Servers in the config variables. It makes sense
when thinking of a foreach-loop that one is reading from a var Servers
into a local var server.
I can confirm my experience matches yours, substitution happens before
transformation. I will typical have Web.Release.config as the
substitution target. That way when transformation happens
Web.Release.config already has the desired substituted content.
Replacement would definitely be easier on this case, but if that’s not an option in your scenario:
You can add attributes to your configuration files. Now the configuration files cant be 100% empty, as they need to have at least the skeleton of a .config file (i.e it needs to have )
In your case you wont have a transform-config-file from which you will add the settings to you main config file. So you will need to add a step on your deployment process previous to the transformation/deployment, on which you will create this transform-config-file based on the values of your variables. The easiest way for this will be to use Powershell