Using envionment modules with cylc

I am using Modules (https://lmod.readthedocs.io) to load an environment that I would like to have available to the cylc suite.
Can I do this in jinja2? or otherwise load the module in a way that the suite would use those values when run?

I figured out how to set what I need in jinja2. But it leads to another question:

Or maybe I need to turn this on it’s head - can I register a cylc suite from a Module?

I’m not sure I understand your last question (“can I register a cylc suite from a Module?”). As I understand it, Modules are put in place by system admins, to configure user environments by setting environment variables to provide access to particular software packages. Which doesn’t sound like an appropriate place to register Cylc suites.

Anyhow, do you want the environment modules to affect the behavior of your Cylc schedulers, or of the jobs that they execute? If the latter, you can use module load etc. in job scripting, just as you would in the terminal.

Modules are not just for sys-admin types, you can write and use them as a user and they can be quite handy. We have several suites set up to use the same suite.rc file and just accept different inputs.
Currently I have that set of inputs at the top of the suite.rc file as jinja variables but I would like to
move them out of the suite file into there own file so that instead of editing the suite file the user can just load the module associated with the suite they want to run. So I want the Modules to affect both the scheduler and the jobs they execute. I just found the --set-file argument to cylc run which may be what I need.

1 Like

Sounds like the problem is providing multiple alternative configurations of a workflow and an easy way of switching between them.

Having multiple “configurations” or “modes” for a single workflow is a common requirements and Cylc has some built-in ways of achieving this:

  1. Cylc “set files”

    Place all of your Jinja2 variables in a “set file”, specify the required file when running the workflow.

    $ cylc run <workflow> --set-file=<file>
    

    Cylc8 Note: In Cylc7 setfile variables can only be strings, in Cylc8 they can be any Python literal (e.g. string, int, boolean). This is a change in behaviour as strings must be explicitly quoted.

  2. Dynamic imports.

    You can use Jinja2 to {% import %} other files. You can derive the name of the file that is loaded from another variable. This approach is often used to load site specific settings or toggle between different modes:

    # suite.rc
    {% import "suite." + SITE" + ".rc" as site %}
    {% set xyz = site.xyz | default('123') %}
    
    # suite.mysitename.rc
    {% set xyz = "abc" %}
    
    $ cylc run <workflow> -s SITE=mysitename
    

    Note: You may want to add with context after the as site in the import. This allows any variables set in the lines above to flow through into the imported file.

  3. Rose optional configurations.

    Rose configurations can be used to set Jinja2 and environment variables as well as configuring files to install.

    The “base” configuration could look something like this:

    # rose-suite.conf
    [jinja2:suite.rc]
    xyz="default value"
    

    Optional configurations (which are appended to the base only apply when activated):

    # opt/rose-suite-operational.conf
    [jinja2:suite.rc]
    xyz="operational value"
    
    $ rose suite-run -O operational  # use the operational optional configuration
    
1 Like

Thank you - I am trying to use method 2 but it only seems to use the default values. I get an error if I include a non-existent file so I think that the file is being read, but only the default values get set.

Whoops, sorry, I made a mistake in my code above, I meant imports not includes, fixed now.

  • Includes bring through the text (i.e. the Cylc configuration) from another file.

    # suite.rc
    {% include "suite.runtime.rc" %}
    
    # suite.runtime.rc
    [runtime]
        [[foo]]
            script = true
    
  • Imports bring through the Jinja2 things from another file.

    # suite.rc
    {% from "suite.settings.rc" import foo, bar, baz %}
    
    # suite.settings.rc
    {% set foo = 1 %}
    {% set bar = 2 %}
    {% set baz = 3 %}
    

There’s one other quirk to Jinja2 includes/imports to be aware of:

  • “with context” lets variables pass into the other file.

    # suite.rc
    {% set answer = 42 %}
    {% import "suite.other.rc" as whatever with context %}
    
    # suite.other.rc
    {% set foo = answer * 2 %}
    
    $ cylc view --process two --stdout
    # 84
    
  • “without context” (default) doesn’t.

    # suite.rc
    {% set answer = 42 %}
    {% import "suite.other.rc" as whatever %}
    
    # suite.other.rc
    {% set foo = answer * 2 %}
    
    $ cylc view --process two --stdout
    Jinja2Error: 'answer' is undefined
    
    Context lines:
    
    {% set answer = 42 %}
    
    {% import "other.cylc" as site %} <-- UndefinedError