Esempio n. 1
0
 def __init__(
     self,
     event_handler=None,
     popen=None,
     config_pm=None,
     fs_util=None,
     suite_engine_proc=None,
 ):
     if not self.CONF_NAME:
         self.CONF_NAME = self.NAME
     self.event_handler = event_handler
     if popen is None:
         popen = RosePopener(event_handler)
     self.popen = popen
     if fs_util is None:
         fs_util = FileSystemUtil(event_handler)
     self.fs_util = fs_util
     if config_pm is None:
         config_pm = ConfigProcessorsManager(event_handler, popen, fs_util)
     self.config_pm = config_pm
     if suite_engine_proc is None:
         suite_engine_proc = SuiteEngineProcessor.get_processor(
             event_handler=event_handler, popen=popen, fs_util=fs_util
         )
     self.suite_engine_proc = suite_engine_proc
     self.conf_tree_loader = ConfigTreeLoader()
Esempio n. 2
0
def rose_config_tree_loader(srcdir=None, opts=None):
    """Get a rose config tree from srcdir.

    Args:
        srcdir(string or Pathlib.path object):
            Search for a ``rose-suite.conf`` file in this location.
        opts:
            Options namespace: To be used to allow CLI
            specification of optional configuarations.
    Returns:
        A Rose ConfigTree object.
    """
    opt_conf_keys = []

    # get optional config key set as environment variable:
    opt_conf_keys_env = os.getenv("ROSE_SUITE_OPT_CONF_KEYS")
    if opt_conf_keys_env:
        opt_conf_keys += shlex.split(opt_conf_keys_env)

    # ... or as command line options
    if opts and 'opt_conf_keys' in dir(opts) and opts.opt_conf_keys:
        if isinstance(opts.opt_conf_keys, str):
            opt_conf_keys += opts.opt_conf_keys.split()
        elif isinstance(opts.opt_conf_keys, list):
            opt_conf_keys += opts.opt_conf_keys

    # Optional definitions
    redefinitions = []
    if opts and 'defines' in dir(opts) and opts.defines:
        redefinitions = opts.defines

    # Load the config tree
    from metomi.rose.config_tree import ConfigTreeLoader
    config_tree = ConfigTreeLoader().load(
        str(srcdir),
        'rose-suite.conf',
        opt_keys=opt_conf_keys,
        defines=redefinitions,
    )

    # Reload the Config using the suite_ variables.
    # (we can't do this first time around because we have no idea what the
    # templating section is.)
    if getattr(opts, 'rose_template_vars', None):
        template_section = identify_templating_section(config_tree.node)
        for template_var in opts.rose_template_vars:
            redefinitions.append(f'[{template_section}]{template_var}')
        # Reload the config
        config_tree = ConfigTreeLoader().load(
            str(srcdir),
            'rose-suite.conf',
            opt_keys=opt_conf_keys,
            defines=redefinitions,
        )

    return config_tree
Esempio n. 3
0
def rose_config_tree_loader(srcdir=None, opts=None):
    """Get a rose config tree from srcdir.

    Args:
        srcdir(string or Pathlib.path object):
            Search for a ``rose-suite.conf`` file in this location.
        opts:
            Options namespace: To be used to allow CLI
            specification of optional configuarations.
    Returns:
        A Rose ConfigTree object.
    """
    opt_conf_keys = []

    # get optional config key set as environment variable:
    opt_conf_keys_env = os.getenv("ROSE_SUITE_OPT_CONF_KEYS")
    if opt_conf_keys_env:
        opt_conf_keys += shlex.split(opt_conf_keys_env)

    # ... or as command line options
    if opts and 'opt_conf_keys' in dir(opts) and opts.opt_conf_keys:
        if isinstance(opts.opt_conf_keys, str):
            opt_conf_keys += opts.opt_conf_keys.split()
        elif isinstance(opts.opt_conf_keys, list):
            opt_conf_keys += opts.opt_conf_keys

    # Optional definitions
    redefinitions = []
    if opts and 'defines' in dir(opts) and opts.defines:
        redefinitions = opts.defines

    # Load the config tree
    from metomi.rose.config_tree import ConfigTreeLoader
    config_tree = ConfigTreeLoader().load(
        str(srcdir),
        'rose-suite.conf',
        opt_keys=opt_conf_keys,
        defines=redefinitions,
    )

    return config_tree
Esempio n. 4
0
def rose_config_tree_loader(dir_=None, opts=None):
    """Get a rose config tree from a given dir

    Args:
        dir_(string or Pathlib.path object):
            Search for a ``rose-suite.conf`` file in this location.
        opts:
            Some sort of options object or string - To be used to allow CLI
            specification of optional configuaration.
    Returns:
        A Rose ConfigTree object.
    """
    from metomi.rose.config_tree import ConfigTreeLoader

    opt_conf_keys = []
    # get optional config key set as environment variable:
    opt_conf_keys_env = os.getenv("ROSE_SUITE_OPT_CONF_KEYS")
    if opt_conf_keys_env:
        opt_conf_keys += shlex.split(opt_conf_keys_env)
    # ... or as command line options
    if 'opt_conf_keys' in dir(opts) and opts.opt_conf_keys:
        opt_conf_keys += opts.opt_conf_keys

    # Optional definitions
    redefinitions = []
    if 'defines' in dir(opts) and opts.defines:
        redefinitions = opts.defines

    # Load the actual config tree
    config_tree = ConfigTreeLoader().load(
        str(dir_),
        'rose-suite.conf',
        opt_keys=opt_conf_keys,
        defines=redefinitions
    )

    return config_tree
Esempio n. 5
0
class Runner:

    """Invoke a Rose application."""

    CONF_NAME = None
    NAME = None
    OPTIONS = []

    def __init__(self, event_handler=None, popen=None, config_pm=None,
                 fs_util=None, suite_engine_proc=None):
        if not self.CONF_NAME:
            self.CONF_NAME = self.NAME
        self.event_handler = event_handler
        if popen is None:
            popen = RosePopener(event_handler)
        self.popen = popen
        if fs_util is None:
            fs_util = FileSystemUtil(event_handler)
        self.fs_util = fs_util
        if config_pm is None:
            config_pm = ConfigProcessorsManager(event_handler, popen, fs_util)
        self.config_pm = config_pm
        if suite_engine_proc is None:
            suite_engine_proc = SuiteEngineProcessor.get_processor(
                event_handler=event_handler, popen=popen, fs_util=fs_util)
        self.suite_engine_proc = suite_engine_proc
        self.conf_tree_loader = ConfigTreeLoader()

    def handle_event(self, *args, **kwargs):
        """Handle an event using the runner's event handler."""

        if callable(self.event_handler):
            return self.event_handler(*args, **kwargs)

    def config_load(self, opts):
        """Combine main config file with optional ones and defined ones.

        Return an instance of metomi.rose.config_tree.ConfigTree.

        """

        # Main configuration file
        conf_dir = opts.conf_dir
        if conf_dir is None:
            conf_dir = os.getcwd()
        conf_dir_orig = conf_dir
        conf_name = "rose-" + self.CONF_NAME + ".conf"
        while not os.access(os.path.join(conf_dir, conf_name),
                            os.F_OK | os.R_OK):
            conf_dir = self.fs_util.dirname(conf_dir)
            if conf_dir == self.fs_util.dirname(conf_dir):  # is root
                raise ConfigNotFoundError(conf_dir_orig, conf_name)

        # Optional configuration files
        opt_conf_keys = []
        opt_conf_keys_env = os.getenv("ROSE_%s_OPT_CONF_KEYS" %
                                      self.CONF_NAME.upper())
        if opt_conf_keys_env:
            opt_conf_keys += shlex.split(opt_conf_keys_env)
        if opts.opt_conf_keys:
            opt_conf_keys += opts.opt_conf_keys

        self.handle_event(RunConfigLoadEvent(
            conf_dir, conf_name, opt_conf_keys, opts.defines,
            getattr(opts, 'defines_suite', [])))

        conf_tree = self.conf_tree_loader.load(conf_dir, conf_name,
                                               opt_keys=opt_conf_keys,
                                               defines=opts.defines)
        return conf_tree

    def run(self, opts, args):

        """Initiates a run with this runner, using the options and arguments.

        opts is a dict or object with relevant flags
        args is a list of strings.

        """

        if isinstance(opts, dict):
            opts = Dummy(**opts)
        cwd = os.getcwd()
        environ = dict(os.environ)
        uuid = str(uuid4())
        work_files = []
        try:
            return self.run_impl(opts, args, uuid, work_files)
        finally:
            # Close handle on specific log file
            try:
                self.event_handler.contexts[uuid].handle.close()
            except (KeyError, IOError, AttributeError):
                pass
            # Remove work files
            for work_file in work_files:
                try:
                    if os.path.isfile(work_file) or os.path.islink(work_file):
                        os.unlink(work_file)
                    elif os.path.isdir(work_file):
                        shutil.rmtree(work_file)
                except OSError:
                    pass
            # Change back to original working directory
            try:
                os.chdir(cwd)
            except OSError:
                pass
            # Reset os.environ
            os.environ = dict(environ)

    __call__ = run

    def run_impl(self, opts, args, uuid, work_files):

        """Sub-class should implement the actual logic for a run.
        uuid is a unique identifier for a run.
        work_files is a list of files, which are removed at the end of a run.
        """

        raise NotImplementedError()