示例#1
0
    def get_workflow(self, params: Dict) -> str:
        """Get the workflow identifier from the parameters or the environment.

        Attempts to get the workflow identifier from the list of parsed parameters.
        Assumes the the identifier is given by the parameter ``workflow``. If no
        workflow identifier is present in the given parameter dictionary an
        attempt is made to get the identifier from the environment variable that
        is defined for workflows in this context.

        Raises a missing configuration error if the value is not set.

        Parameters
        ----------
        params: dict
            Dictionary of parsed command-line parameters

        Returns
        -------
        string
        """
        # Get the parameter value for the workflow identifier. The value will
        # be set to None if the parameter is defined for a command but was not
        # provided by the user.
        workflow_id = params.get('workflow')
        # If the workflow value is None, attempt to get it from the environment.
        if not workflow_id:
            workflow_id = os.environ.get(self.vars['workflow'])
        # Raise an error if no workflow identifier was found.
        if not workflow_id:
            raise err.MissingConfigurationError('workflow identifier')
        return workflow_id
示例#2
0
def FS(env: Dict) -> FileStore:
    """Factory pattern to create file store instances for the service API. Uses
    the environment variables FLOWSERV_FILESTORE_MODULE and
    FLOWSERV_FILESTORE_CLASS to create an instance of the file store. If the
    environment variables are not set the FileSystemStore is returned as the
    default file store.

    Parameters
    ----------
    env: dict
        Configuration dictionary that provides access to configuration
        parameters from the environment.

    Returns
    -------
    flowserv.model.files.base.FileStore
    """
    module_name = env.get(FLOWSERV_FILESTORE_MODULE)
    class_name = env.get(FLOWSERV_FILESTORE_CLASS)
    # If both environment variables are None return the default file store.
    # Otherwise, import the specified module and return an instance of the
    # controller class. An error is raised if only one of the two environment
    # variables is set.
    if module_name is None and class_name is None:
        from flowserv.model.files.fs import FileSystemStore
        return FileSystemStore(env=env)
    elif module_name is not None and class_name is not None:
        from importlib import import_module
        module = import_module(module_name)
        return getattr(module, class_name)(env=env)
    raise err.MissingConfigurationError('file store')
示例#3
0
def APP() -> str:
    """Get the value for the FLOWSERV_APP variable from the environment. Raises
    a missing configuration error if the value is not set.
    Returns
    -------
    string
    """
    app_key = os.environ.get(FLOWSERV_APP)
    if not app_key:
        raise err.MissingConfigurationError('workflow identifier')
    return app_key
示例#4
0
def init(force=False):
    """Initialize database and base directories for the API."""
    if not force:
        click.echo('This will erase an existing database.')
        click.confirm('Continue?', default=True, abort=True)
    # Create a new instance of the database. Raise errors if the database URL
    # is not set.
    config = env()
    connect_url = config.get(FLOWSERV_DB)
    if connect_url is None:
        raise err.MissingConfigurationError('database Url')
    DB(connect_url=connect_url).init()
示例#5
0
    def __init__(self, env: Dict):
        """Initialize the base directory. The directory is created if it does
        not exist.

        Parameters
        ----------
        env: dict
            Configuration object that provides access to configuration
            parameters in the environment.
        """
        self.basedir = env.get(FLOWSERV_BASEDIR)
        if self.basedir is None:
            raise err.MissingConfigurationError('API base directory')
示例#6
0
    def access_token(self) -> str:
        """Get the value for the user access token from the environment.

        The environment variable that holds the token (*FLOWSERV_ACCESS_TOKEN*)
        is the same accross both applications.

         Raises a missing configuration error if the value is not set.

        Returns
        -------
        string
        """
        access_token = os.environ.get(self.vars['token'])
        if not access_token:
            raise err.MissingConfigurationError('access token')
        return access_token
示例#7
0
    def __init__(self,
                 service: APIFactory,
                 worker_config: Optional[Dict] = None):
        """Initialize the function that is used to execute individual workflow
        steps. The run workflow function in this module executes all steps
        within sub-processes in the same environment as the workflow
        controller.

        NOTE: Using the provided execution function is intended for development
        and private use only. It is not recommended (and very dangerous) to
        use this function in a public setting.

        Parameters
        ----------
        service: flowserv.service.api.APIFactory, default=None
            API factory for service callbach during asynchronous workflow
            execution.
        worker_config: dict, default=None
            Mapping of container image identifier to worker specifications that
            are used to create an instance of a
            :class:`flowserv.controller.worker.base.ContainerStep` worker.
        """
        self.fs = FS(env=service)
        self.service = service
        self.worker_config = worker_config if worker_config else service.worker_config(
        )
        logging.info("workers {}".format(self.worker_config))
        # The is_async flag controlls the default setting for asynchronous
        # execution. If the flag is False all workflow steps will be executed
        # in a sequentiall (blocking) manner.
        self.is_async = service.get(FLOWSERV_ASYNC)
        # Directory for temporary run files.
        basedir = service.get(FLOWSERV_BASEDIR)
        if basedir is None:
            raise err.MissingConfigurationError('API base directory')
        logging.info('base dir {}'.format(basedir))
        self.runsdir = service.get(FLOWSERV_RUNSDIR,
                                   os.path.join(basedir, DEFAULT_RUNSDIR))
        # Dictionary of all running tasks
        self.tasks = dict()
        # Lock to manage asynchronous access to the task dictionary
        self.lock = Lock()
示例#8
0
    def get_group(self, params: Dict) -> str:
        """Get the user group (submission) identifier from the parameters or
        the environment.

        Attempts to get the group identifier from the list of parsed parameters.
        Assumes the the identifier is given by the parameter ``group``. If no
        group identifier is present in the given parameter dictionary an
        attempt is made to get the identifier from the environment variable that
        is defined for user groups in this context. If that environment variable
        is not set an attempt is made to get the value from the environment
        variable for the workflow identifier. The latter is done since flowserv
        applications are installed with identical workflow and group identifier.

        Raises a missing configuration error if the value is not set.

        Parameters
        ----------
        params: dict
            Dictionary of parsed command-line parameters

        Returns
        -------
        string
        """
        # Get the parameter value for the group identifier. The value will
        # be set to None if the parameter is defined for a command but was not
        # provided by the user.
        group_id = params.get('group')
        # If the group value is None, attempt to get it from the environment.
        if not group_id:
            group_id = os.environ.get(self.vars['group'])
        # If the group value is still None, attempt to get it from the
        # workflow environment variable.
        if not group_id:
            group_id = os.environ.get(self.vars['workflow'])
        # Raise an error if no group identifier was found.
        if not group_id:
            raise err.MissingConfigurationError(
                'submission (group) identifier')
        return group_id
示例#9
0
def init_backend(api: APIFactory) -> WorkflowController:
    """Create an instance of the workflow engine based on the given configuration
    settings. The workflow engine receives a reference to the API factory for
    callback operations that modify the global database state.

    Parameters
    ----------
    env: dict, default=None
        Dictionary that provides access to configuration parameter values.
    api: flowserv.service.api.APIFactory
        Reference to tha API factory for callbacks that modify the global
        database state.

    Returns
    -------
    flowserv.controller.base.WorkflowController
    """
    # Create a new instance of the file store based on the configuration in the
    # respective environment variables.
    module_name = api.get(config.FLOWSERV_BACKEND_MODULE)
    class_name = api.get(config.FLOWSERV_BACKEND_CLASS)
    # If both environment variables are None return the default controller.
    # Otherwise, import the specified module and return an instance of the
    # controller class. An error is raised if only one of the two environment
    # variables is set.
    if module_name is None and class_name is None:
        engine = 'flowserv.controller.serial.engine.base.SerialWorkflowEngine'
        logging.info('API backend {}'.format(engine))
        from flowserv.controller.serial.engine.base import SerialWorkflowEngine
        return SerialWorkflowEngine(service=api)
    elif module_name is not None and class_name is not None:
        logging.info('API backend {}.{}'.format(module_name, class_name))
        from importlib import import_module
        module = import_module(module_name)
        return getattr(module, class_name)(service=api)
    raise err.MissingConfigurationError('workflow backend')