def get_rose_vars(srcdir=None, opts=None): """Load template variables from Rose suite configuration. Loads the Rose suite configuration tree from the filesystem using the shell environment. Args: srcdir(pathlib.Path): Path to the Rose suite configuration (the directory containing the ``rose-suite.conf`` file). opts: Options object containing specification of optional configuarations set by the CLI. Returns: dict - A dictionary of sections of rose-suite.conf. For each section either a dictionary or None is returned. E.g. { 'env': {'MYVAR': 42}, 'empy:suite.rc': None, 'jinja2:suite.rc': { 'myJinja2Var': {'yes': 'it is a dictionary!'} } } """ # Set up blank page for returns. config = { 'env': {}, 'template_variables': {}, 'templating_detected': None } # Return a blank config dict if srcdir does not exist if not rose_config_exists(srcdir, opts): if ( getattr(opts, "opt_conf_keys", None) or getattr(opts, "defines", None) or getattr(opts, "rose_template_vars", None) ): raise NotARoseSuiteException() return config # Load the raw config tree config_tree = rose_config_tree_loader(srcdir, opts) deprecation_warnings(config_tree) # Extract templatevars from the configuration get_rose_vars_from_config_node( config, config_tree.node, os.environ ) # Export environment vars for key, val in config['env'].items(): os.environ[key] = val return config
def test_rose_config_tree_loader_CLI_handling(tmp_path, expect, file, opts): """Test interaction of config tree loader with -S and -D. """ source = tmp_path (source / 'rose-suite.conf').write_text(file) opts = SimpleNamespace(**opts) tree = rose_config_tree_loader(source, opts) assert node_stripper(tree.node) == expect
def rose_fileinstall(srcdir=None, opts=None, rundir=None): """Call Rose Fileinstall. Args: srcdir(pathlib.Path): Search for a ``rose-suite.conf`` file in this location. rundir (pathlib.Path) """ if not rose_config_exists(rundir, opts): return False # Load the config tree config_tree = rose_config_tree_loader(rundir, opts) if any(i.startswith('file') for i in config_tree.node.value): try: startpoint = os.getcwd() os.chdir(rundir) except FileNotFoundError as exc: raise exc else: # Carry out imports. import asyncio from metomi.rose.config_processor import ConfigProcessorsManager from metomi.rose.popen import RosePopener from metomi.rose.reporter import Reporter from metomi.rose.fs_util import FileSystemUtil # Update config tree with install location # NOTE-TO-SELF: value=os.environ["CYLC_WORKFLOW_RUN_DIR"] config_tree.node = config_tree.node.set( keys=["file-install-root"], value=str(rundir) ) # Artificially set rose to verbose. event_handler = Reporter(3) fs_util = FileSystemUtil(event_handler) popen = RosePopener(event_handler) # Get an Asyncio loop if one doesn't exist: # Rose may need an event loop to invoke async interfaces, # doing this here incase we want to go async in cylc-rose. # See https://github.com/cylc/cylc-rose/pull/130/files try: asyncio.get_event_loop() except RuntimeError: asyncio.set_event_loop(asyncio.new_event_loop()) # Process fileinstall. config_pm = ConfigProcessorsManager(event_handler, popen, fs_util) config_pm(config_tree, "file") finally: os.chdir(startpoint) return config_tree.node
def get_rose_vars(srcdir=None, opts=None): """Load template variables from Rose suite configuration. Loads the Rose suite configuration tree from the filesystem using the shell environment. Args: srcdir(pathlib.Path): Path to the Rose suite configuration (the directory containing the ``rose-suite.conf`` file). opts: Options object containing specification of optional configuarations set by the CLI. Returns: dict - A dictionary of sections of rose-suite.conf. For each section either a dictionary or None is returned. E.g. { 'env': {'MYVAR': 42}, 'empy:suite.rc': None, 'jinja2:suite.rc': { 'myJinja2Var': {'yes': 'it is a dictionary!'} } } """ # Set up blank page for returns. config = {'env': {}, 'template_variables': {}, 'templating_detected': None} # Return a blank config dict if srcdir does not exist if not rose_config_exists(srcdir, opts): return config # Load the raw config tree config_tree = rose_config_tree_loader(srcdir, opts) # Warn if root-dir set in config: if 'root-dir' in config_tree.node: LOG.warning('You have set "root-dir", which at Cylc 8 does nothing. ' 'See Cylc Install documentation.') # Extract templatevars from the configuration get_rose_vars_from_config_node(config, config_tree.node, os.environ) # Export environment vars for key, val in config['env'].items(): os.environ[key] = val return config
def test_rose_config_tree_loader( rose_config_template, override, section, exp_ANOTHER_JINJA2_ENV, exp_JINJA2_VAR, opts_format ): """Test reading of empy or jinja2 vars Scenarios tested: - Read in a basic rose-suite.conf file. Ensure we don't return env, just jinja2/empy. - Get optional config name from an environment variable. - Get optional config name from command line option. - Get optional config name from an explicit over-ride string. """ options = None if override == 'environment': os.environ['ROSE_SUITE_OPT_CONF_KEYS'] = "gravy" else: # Prevent externally set environment var breaking tests. os.environ['ROSE_SUITE_OPT_CONF_KEYS'] = "" if opts_format == 'list': conf_keys = ['chips'] else: conf_keys = 'chips' if override == 'CLI': options = SimpleNamespace() options.opt_conf_keys = conf_keys if override == 'override': options = SimpleNamespace() options.opt_conf_keys = conf_keys options.defines = [ f"[{section}:suite.rc]Another_Jinja2_var=Variable overridden" ] result = rose_config_tree_loader( rose_config_template(section), options ).node.value[section + ':suite.rc'].value results = { 'Another_Jinja2_var': result['Another_Jinja2_var'].value, 'JINJA2_VAR': result['JINJA2_VAR'].value } expected = { 'Another_Jinja2_var': f'{exp_ANOTHER_JINJA2_ENV}', 'JINJA2_VAR': f'{exp_JINJA2_VAR}' } assert results == expected
def rose_fileinstall(srcdir=None, opts=None, rundir=None): """Call Rose Fileinstall. Args: srcdir(pathlib.Path): Search for a ``rose-suite.conf`` file in this location. rundir (pathlib.Path) """ if not rose_config_exists(rundir, opts): return False # Load the config tree config_tree = rose_config_tree_loader(rundir, opts) if any(i.startswith('file') for i in config_tree.node.value): try: startpoint = os.getcwd() os.chdir(rundir) except FileNotFoundError as exc: raise exc else: # Carry out imports. from metomi.rose.config_processor import ConfigProcessorsManager from metomi.rose.popen import RosePopener from metomi.rose.reporter import Reporter from metomi.rose.fs_util import FileSystemUtil # Update config tree with install location # NOTE-TO-SELF: value=os.environ["CYLC_WORKFLOW_RUN_DIR"] config_tree.node = config_tree.node.set( keys=["file-install-root"], value=str(rundir) ) # Artificially set rose to verbose. event_handler = Reporter(3) fs_util = FileSystemUtil(event_handler) popen = RosePopener(event_handler) # Process files config_pm = ConfigProcessorsManager(event_handler, popen, fs_util) config_pm(config_tree, "file") finally: os.chdir(startpoint) return config_tree.node