I have been using LXD on Ubuntu 16.04 for a year or so and it has been very convenient.
I have been using (trivial) LXD templates on image launch for inserting some string into some configuration file based on an environment variable (environment.*) set in a profile.
There’s really not much documentation on templates, so it’s a lot of trial and error (which is really hard as you have to change, publish and launch over and over again without any hints on why the image couldn’t be launched – at least to my knowledge).
What I’ve done is this, which is working:
{{ config_get("environment.db-library", "") }}
to prepend some DB libraries in the JDBC connection string depending on environment.
Now I would like to include one complete file when in test, another when in production.
I was self-confident and tried this in a template (based on Django/Pongo2 docs):
{% if config_get("environment.env", "") == "prod" %} {% include "prod.txt" %} {% else %} {% include "test.txt" %} {% endif %}
It did not work and I have no clue as to why.
Is there anything I could do the make my template testing easier?
Does anybody have any tip on what I should do with my specific including problem?
To be honest I never really understood the cloud-init thing. I thought it was for cloud environments in some way – I run my stuff on local servers…
My problem can probably be solved using cloud-init, it appears, but how are you supposed to run conditional statements depending on variables/settings set in the profile (runcmd seems really suitable to run only simple, single commands)?
Wouldn’t it be cleaner to use templates to include only the correct file in the container filesystem instead of having all alternative files in the container and during launch/runcmd choose the correct one?
It seems to me (with my very limited knowledge) that templates are suitable for including specific files in the container during launch while cloud-init is convenient for taking simple actions during launch.
Anyway, how should if-then-else be done in the template? Even if that wouldn’t be the recommended way, it should be possible as there is such a template (cloud-init-user.tpl) in the Ubuntu image (in my at least):
For testing, it’s usually easiest to make sure that the template triggers on start so that you can just restart the container and have it re-applied.
Your syntax does look valid to me but I’ve never played with the include tag and I do wonder relative to what any of those paths would be… We may need to tweak LXD’s behavior in this regard as we’d want that to be relative to the container’s rootfs which I’m not sure it is today.
For testing, it’s usually easiest to make sure that the template triggers on start so that you can just restart the container and have it re-applied.
Cool, that makes the process at least 3 times faster. Thanks!
Your syntax does look valid to me but I’ve never played with the include tag and I do wonder relative to what any of those paths would be…
I thought I would try a path relative to the template path. The location didn’t become a problem yet, but the problem is the script tags (as you can see in my previous reply) – even an empty script tag ({% %}) breaks it.
EROR[01-30|15:30:39] start hook failed container=c1 err="[Error (where: fromfile) in test | Line 1 Col 89 near 'test'] open test: no such file or directory"
DBUG[01-30|15:30:39]
{
"error": "[Error (where: fromfile) in test | Line 1 Col 89 near 'test'] open test: no such file or directory",
"error_code": 500,
"type": "error"
}
EROR[01-30|15:30:39] Failed starting container action=start created=2018-01-30T15:43:26+0000 ephemeral=false name=c1 stateful=false used=2018-01-30T20:28:49+0000
So include seems to be working here, though it’s relative to the host rather than the container.
I think we should treat that as a bug and find some way to tell pongo to make includes relative to the container instead.
Actually, in my example above, I just print the string “include prod.txt”, but with the if-statement that fails (I have not even really included anything yet). I have to look closer at your “experiment” and I’ll report back.
Very strange. Now that I tested this with the if-statement you provided above, it suddenly is working!
In other words:
{% if config_get("environment.env", "") == "prod" %} {% include "/var/lib/lxd/containers/testcontainer/templates/test/prod.txt" %} {% else %} {% include "/var/lib/lxd/containers/testcontainer/templates/test/test.txt" %} {% endif %}
… is all fine. If the setting is “prod”, then it includes the corresponding file all right, the same goes for test.
Hard-coded paths are bad, so I tried giving the path to the files as a setting (environment.templatepath), but I couldn’t make that working. I’m sure it must be possible to create the argument to “include” from a variable and a hardcoded string?
I tried something like this:
{% if config_get("environment.templatepath", "") == "prod" %} {% include config_get("environment.templatepath", "")+"/prod.txt" %} {% endif %}
… but that was incorrect. Anybody knows the correct syntax?