Exemple #1
0
    def update_group(self, group_id, name=None, members=None):
        """Update the name and/or list of members for a workflow group.

        Parameters
        ----------
        group_id: string
            Unique group identifier
        name: string, optional
            Unique user identifier
        members: list(string), optional
            List of user identifier for group members

        Returns
        -------
        flowserv.model.base.GroupObject

        Raises
        ------
        flowserv.error.ConstraintViolationError
        flowserv.error.UnknownUserError
        flowserv.error.UnknownWorkflowGroupError
        """
        # Get group handle. This will raise an error if the group is unknown.
        group = self.get_group(group_id)
        # If name and members are None we simply return the group handle.
        if name is None and members is None:
            return group
        if name is not None and name is not group.name:
            constraint.validate_name(name)
            group.name = name
        if members is not None:
            group.members = list()
            for user_id in members:
                group.members.append(self.users.get_user(user_id, active=True))
        return group
Exemple #2
0
def unique_name(name, existing_names):
    """Ensure that the workflow name in the project metadata is not empty, not
    longer than 512 character, and unique.

    Parameters
    ----------
    name: string
        Workflow name in manifest or given by user.
    existing_names: set
        Set of names for existing projects.

    Raises
    ------
    flowserv.error.ConstraintViolationError
    """
    # Validate that the name is not empty and not too long.
    constraint.validate_name(name)
    # Ensure that the name is unique.
    if name in existing_names:
        # Find a a unique name that matches the template name (int)
        name_templ = name + ' ({})'
        count = 1
        while name_templ.format(count) in existing_names:
            count += 1
        name = name_templ.format(count)
        # Re-validate that the name is not too long.
        constraint.validate_name(name)
    return name
Exemple #3
0
    def upload_file(self, group_id: str, file: IOHandle, name: str):
        """Upload a new file for a workflow group. This will create a copy of
        the given file in the file store that is associated with the group. The
        file will be places in a unique folder inside the groups upload folder.

        Raises an error if the given file name is invalid.

        Parameters
        ----------
        group_id: string
            Unique group identifier
        file: flowserv.model.files.base.IOHandle
            File object (e.g., uploaded via HTTP request)
        name: string
            Name of the file

        Returns
        -------
        flowserv.model.base.UploadFile

        Raises
        ------
        flowserv.error.ConstraintViolationError
        flowserv.error.UnknownWorkflowGroupError
        """
        # Get the group object to ensure that the group exists.
        group = self.get_group(group_id)
        # Ensure that the given file name is valid
        constraint.validate_name(name)
        # Create a new unique identifier for the file and save the file object
        # to the new file path.
        file_id = util.get_unique_identifier()
        uploaddir = self.fs.group_uploaddir(
            workflow_id=group.workflow_id,
            group_id=group.group_id
        )
        # Get file size.
        file_size = file.size()
        # Attempt to guess the Mime type for the uploaded file from the file
        # name.
        mime_type, _ = mimetypes.guess_type(url=name)
        self.fs.store_files(files=[(file, file_id)], dst=uploaddir)
        # Insert information into database and return handle for uploaded file.
        fileobj = UploadFile(
            file_id=file_id,
            created_at=util.utc_now(),
            key=os.path.join(uploaddir, file_id),
            name=name,
            mime_type=mime_type,
            size=file_size
        )
        group.uploads.append(fileobj)
        return fileobj
Exemple #4
0
    def update_workflow(self,
                        workflow_id,
                        name=None,
                        description=None,
                        instructions=None):
        """Update name, description, and instructions for a given workflow.

        Raises an error if the given workflow does not exist or if the name is
        not unique.

        Parameters
        ----------
        workflow_id: string
            Unique workflow identifier
        name: string, optional
            Unique workflow name
        description: string, optional
            Optional short description for display in workflow listings
        instructions: string, optional
            Text containing detailed instructions for workflow execution

        Returns
        -------
        flowserv.model.base.WorkflowObject

        Raises
        ------
        flowserv.error.ConstraintViolationError
        flowserv.error.UnknownWorkflowError
        """
        # Get the workflow from the database. This will raise an error if the
        # workflow does not exist.
        workflow = self.get_workflow(workflow_id)
        # Update workflow properties.
        if name is not None:
            # Ensure that the name is a valid name.
            constraint.validate_name(name)
            # Ensure that the name is unique.
            wf = self.session\
                .query(WorkflowObject)\
                .filter(WorkflowObject.name == name)\
                .one_or_none()
            if wf is not None and wf.workflow_id != workflow_id:
                msg = "workflow '{}' exists".format(name)
                raise err.ConstraintViolationError(msg)
            workflow.name = name
        if description is not None:
            workflow.description = description
        if instructions is not None:
            workflow.instructions = instructions
        return workflow
Exemple #5
0
    def create_group(self,
                     workflow_id: str,
                     name: str,
                     parameters: List[Parameter],
                     workflow_spec: Dict,
                     user_id: Optional[str] = None,
                     members: List[str] = None,
                     engine_config: Optional[Dict] = None,
                     identifier: Optional[str] = None):
        """Create a new group for a given workflow. Within each workflow,
        the names of groups are expected to be unique.

        The workflow group may define additional parameters for the template.
        The full (modifued or original) parameter list is stored with the group
        together with the workflow specification.

        A group may have a list of users that are members. Membership can be
        used to control which users are allowed to execute the associated
        workflow and to upload/view files. The user that creates the group,
        identified by user_id parameter, is always part of the initial list of
        group members.

        If a list of members is given it is ensured that each identifier in the
        list references an existing user.

        Parameters
        ----------
        workflow_id: string
            Unique workflow identifier
        name: string
            Group name
        user_id: string
            Unique identifier of the user that created the group
        parameters: list(flowserv.model.parameter.base.Parameter)
            List of workflow template parameter declarations that may be
            specific to the group
        workflow_spec: dict
            Workflow specification
        members: list(string), optional
            Optional list of user identifiers for other group members
        engine_config: dict, default=None
            Optional configuration settings that will be used as the default
            when running a workflow.
        identifier: string, default=None
            Optional user-provided group identifier.

        Returns
        -------
        flowserv.model.base.GroupObject

        Raises
        ------
        flowserv.error.ConstraintViolationError
        flowserv.error.UnknownUserError
        """
        # Validate the given group identifier. This will raise a ValueError
        # if the identifier is invalid.
        validate_identifier(identifier)
        # Ensure that the given name is valid and unique for the workflow
        constraint.validate_name(name)
        # Ensure that the user identifier is not None.
        if user_id is None:
            raise err.UnknownUserError('none')
        group = self.session.query(GroupObject)\
            .filter(GroupObject.name == name)\
            .filter(GroupObject.workflow_id == workflow_id)\
            .one_or_none()
        if group is not None:
            msg = "group '{}' exists".format(name)
            raise err.ConstraintViolationError(msg)
        # Create the group object
        identifier = identifier if identifier else unique_identifier()
        group = GroupObject(group_id=identifier,
                            name=name,
                            workflow_id=workflow_id,
                            owner_id=user_id,
                            parameters=parameters,
                            workflow_spec=workflow_spec,
                            engine_config=engine_config)
        # Create a set of member identifier that contains the identifier of
        # the group owner. Ensure that all group members exist. This will also
        # ensure that the group owner exists.
        member_set = set() if members is None else set(members)
        if user_id is not None and user_id not in member_set:
            member_set.add(user_id)
        for member_id in member_set:
            group.members.append(self.users.get_user(member_id, active=True))
        # Enter group information into the database.
        self.session.add(group)
        return group
def test_valid_names(name):
    """Test no exception for valid names."""
    validate_name(name)
def test_invalid_names(name):
    """Test exception for invalid names."""
    with pytest.raises(err.ConstraintViolationError):
        validate_name(name)