Beispiel #1
0
def test_storage_volume_config(tmpdir):
    """Test storage volume configuration objects."""
    # Default config.
    conf = config.env()
    assert isinstance(conf.get(config.FLOWSERV_FILESTORE), dict)
    doc = {'type': 'fs'}
    conf.volume(config=doc)
    assert conf.get(config.FLOWSERV_FILESTORE) == doc
    # Configure from file.
    filename = os.path.join(tmpdir, 'config.json')
    util.write_object(filename=filename, obj=doc)
    os.environ[config.FLOWSERV_FILESTORE] = filename
    conf = config.env()
    assert conf.get(config.FLOWSERV_FILESTORE) == doc
    del os.environ[config.FLOWSERV_FILESTORE]
Beispiel #2
0
def configuration():
    """Print configuration variables for flowServ."""
    envvar = 'export {}={}'
    click.echo('Configuration settings:\n')
    for var, value in env().items():
        click.echo(envvar.format(var, value))
    click.echo()
Beispiel #3
0
def ClientAPI(
    env: Optional[Dict] = None, basedir: Optional[str] = None,
    database: Optional[str] = None, open_access: Optional[bool] = None,
    run_async: Optional[bool] = None, user_id: Optional[str] = None
) -> APIFactory:
    """Create an instance of the API factory that is responsible for generating
    API instances for a flowserv client.

    The main distinction here is whether a connection is made to a local instance
    of the service or to a remote instance. This distinction is made based on
    the value of the FLOWSERV_CLIENT environment variable that takes the values
    'local' or 'remote'. The default is 'local'.

    Provides the option to alter the default settings of environment variables.

    Parameters
    ----------
    env: dict, default=None
        Dictionary with configuration parameter values.
    basedir: string, default=None
        Base directory for all workflow files. If no directory is given or
        specified in the environment a temporary directory will be created.
    database: string, default=None
        Optional database connect url.
    open_access: bool, default=None
        Use an open access policy if set to True.
    run_async: bool, default=False
        Run workflows in asynchronous mode.
    user_id: string, default=None
        Optional identifier for the authenticated API user.

    Returns
    -------
    flowserv.service.api.APIFactory
    """
    # Get the base configuration settings from the environment if not given.
    env = env if env is not None else config.env()
    if not isinstance(env, Config):
        env = Config(env)
    # Update configuration based on the given optional arguments.
    if basedir is not None:
        env.basedir(basedir)
    if database is not None:
        env.database(database)
    if open_access is not None and open_access:
        env.open_access()
    # By default, the client runs all workflows synchronously.
    if run_async is not None and run_async:
        env.run_async()
    elif env.get(config.FLOWSERV_ASYNC) is None:
        env.run_sync()
    # Create local or remote API factory depending on the FLOWSERV_CLIENT value.
    client = env.get(config.FLOWSERV_CLIENT, config.LOCAL_CLIENT)
    if client == config.LOCAL_CLIENT:
        return LocalAPIFactory(env=env, user_id=user_id)
    elif client == config.REMOTE_CLIENT:
        # Not implemented yet.
        pass
    raise ValueError("inalid client type '{}'".format(client))
Beispiel #4
0
def test_service_descriptor_urls():
    """Test getting Urls from the service descriptor."""
    service = ServiceDescriptor.from_config(env=config.env())
    doc = service.to_dict()
    doc['url'] = 'http://localhost//'
    service = ServiceDescriptor(doc=doc)
    assert service.urls(
        route.USERS_ACTIVATE) == 'http://localhost/users/activate'
    url = service.urls(route.FILES_DELETE, fileId='F1', userGroupId='G0')
    assert url == 'http://localhost/uploads/G0/files/F1'
Beispiel #5
0
def remote_service():
    """Get a test instance for the remote service API."""
    doc = ServiceDescriptor.from_config(env=config.env()).to_dict()
    doc['url'] = 'test'
    service = ServiceDescriptor(doc)
    return API(service=service,
               workflow_service=RemoteWorkflowService(descriptor=service),
               group_service=RemoteWorkflowGroupService(descriptor=service),
               upload_service=RemoteUploadFileService(descriptor=service),
               run_service=RemoteRunService(descriptor=service),
               user_service=RemoteUserService(descriptor=service))
Beispiel #6
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()
Beispiel #7
0
    def __init__(self,
                 env: Optional[Dict] = None,
                 basedir: Optional[str] = None,
                 database: Optional[str] = None,
                 open_access: Optional[bool] = None,
                 run_async: Optional[bool] = None,
                 clear: Optional[bool] = False,
                 user_id: Optional[str] = None):
        """Initialize the client API factory. Provides the option to alter the
        default settings of environment variables and for using custom instance
        of the database and workflow engine.

        Parameters
        ----------
        env: dict, default=None
            Dictionary with configuration parameter values.
        basedir: string, default=None
            Base directory for all workflow files. If no directory is given or
            specified in the environment a temporary directory will be created.
        database: str, default=None
            Databse connection Url.
        open_access: bool, default=None
            Use an open access policy if set to True.
        run_async: bool, default=False
            Run workflows in asynchronous mode.
        clear: bool, default=False
            Remove all existing files and folders in the base directory if the
            clear flag is True.
        user_id: string, default=None
            Identifier for an authenticated default user.
        """
        # Get the base configuration settings from the environment if not given.
        self.env = env if env is not None else config.env()
        # Set the base directory and ensure that it exists. Create a temporary
        # directory if no base directory is specified. If a base directory was
        # specified by the user it will override the settings from the global
        # environment.
        basedir = basedir if basedir is not None else self.env.get(
            config.FLOWSERV_BASEDIR)
        self.basedir = basedir if basedir is not None else tempfile.mkdtemp()
        self.env[config.FLOWSERV_BASEDIR] = self.basedir
        # Remove all existing files and folders in the base directory if the
        # clear flag is True.
        if clear:
            util.cleardir(self.basedir)
        self.service = ClientAPI(env=self.env,
                                 basedir=self.basedir,
                                 database=database,
                                 open_access=open_access,
                                 run_async=run_async,
                                 user_id=user_id)
Beispiel #8
0
def test_service_descriptor():
    """Test the service descriptor object."""
    schema = validator('ServiceDescriptor')
    # Local service descriptor (no arguments).
    service = ServiceDescriptor.from_config(env=config.env())
    schema.validate(service.to_dict())
    assert service.routes().get(SERVICE_DESCRIPTOR) is not None
    assert service.routes().get('foo') is None
    # Remote service descriptor (init from local serialization).
    service = ServiceDescriptor(doc=service.to_dict(), routes={'foo': 'bar'})
    schema.validate(service.to_dict())
    assert service.routes().get(SERVICE_DESCRIPTOR) is not None
    schema.validate(service.to_dict())
    assert service.routes().get('foo') == 'bar'
Beispiel #9
0
def get_app(app_key: Optional[str] = None) -> Workflow:
    """Get the application handle for the specified application identifier. If
    no application identifier is given it is expected in the environment
    variable FLOWSERV_APP.

    Parameters
    ----------
    app_key: string
        Unique identifier referencing the workflow that defines the application
        that is being run.

    Returns
    -------
    flowserv.client.app.workflow.Workflow
    """
    return open_app(env=config.env().open_access(), identifier=app_key)
Beispiel #10
0
    def __init__(self,
                 env: Optional[Dict] = None,
                 db: Optional[DB] = None,
                 engine: Optional[WorkflowController] = None,
                 user_id: Optional[str] = None):
        """Initialize the API factory from a given set of configuration
        parameters and their values. If the configuration dictionary is not
        provided the current values from the respective environment variables
        are used.

        The option to initialize the associated database and workflow engine is
        promarily intended for test purposes.

        Parameters
        ----------
        env: dict, default=None
            Dictionary that provides access to configuration parameter values.
        db: flowserv.model.database.DB, default=None
            Optional default database.
        engine: flowserv.controller.base.WorkflowController, default=None
            Optional workflow controller (for test purposes).
        user_id: string, default=None
            Optional identifier for the authenticated API user.
        """
        # Use the current environment settings if the configuration dictionary
        # is not given.
        env = env if env is not None else config.env()
        super(LocalAPIFactory, self).__init__(env)
        # Ensure that the base directory is set and exists.
        self[BASEDIR] = self.get(BASEDIR, config.API_DEFAULTDIR())
        os.makedirs(self[BASEDIR], exist_ok=True)
        # Initialize that database.
        self._db = db if db is not None else init_db(self)
        # Initialize the workflow engine.
        self._engine = engine if engine is not None else init_backend(self)
        # Initialize the file store.
        self._fs = FS(self)
        # Ensure that the authentication policy identifier is set.
        self[AUTH] = self.get(AUTH, config.AUTH_OPEN)
        # Authenticated default user. The initial value depends on the given
        # value for the user_id or authentication policy.
        self._user_id = config.DEFAULT_USER if not user_id and self[
            AUTH] == config.AUTH_OPEN else user_id
Beispiel #11
0
def init_service(basedir: Optional[str] = None, database: Optional[str] = None) -> APIFactory:
    """Configure the API factory that is used by the Flask application.

    Parameters
    ----------
    basedir: string, default=None
        Base directory for all workflow files. If no directory is given or
        specified in the environment a temporary directory will be created.
    database: string, default=None
        Optional database connect url.

    Returns
    -------
    flowserv.service.api.APIFactory
    """
    global service
    service = ClientAPI(
        env=env().auth().run_async().webapp(),
        basedir=basedir,
        database=database
    )
    return service
Beispiel #12
0
def open_app(env: Optional[Dict] = None,
             identifier: Optional[str] = None) -> Workflow:
    """Shortcut to open an instance for a workflow application from the
    environment configuration settings.

    Parameters
    ----------
    env: dict, default=None
        Dictionary with configuration parameters to use instaed of the values
        in the global environment.
    identifier: string, default=None
        Identifier of the workflow application.

    Returns
    -------
    flowserv.client.app.workflow.Workflow
    """
    # Get the base configuration settings from the environment if not given.
    env = env if env is not None else config.env()
    # Return an instance of the specified application workflow. Get the
    # application identifier from the app if not given.
    return Flowserv(env=env).open(
        identifier=env.get(config.FLOWSERV_APP, identifier))
Beispiel #13
0
def test_config_env(var, value, result):
    """Test getting configuration values from environment variables."""
    os.environ[var] = value
    conf = config.env()
    assert conf[var] == result
    del os.environ[var]