Esempio n. 1
0
def environment():
    workspace = os.getenv("WORKSPACE_NAME")
    admin_token = os.getenv("ADMIN_NEPTUNE_API_TOKEN")
    user = os.getenv("USER_USERNAME")

    project_name, project_key = a_project_name(project_slug=fake.slug())
    project_identifier = normalize_project_name(name=project_name, workspace=workspace)
    created_project_identifier = create_project(
        name=project_name,
        key=project_key,
        visibility="priv",
        workspace=workspace,
        api_token=admin_token,
    )

    add_project_member(
        name=created_project_identifier,
        username=user,
        # pylint: disable=no-member
        role="contributor",
        api_token=admin_token,
    )

    yield Environment(
        workspace=workspace,
        project=project_identifier,
        user_token=os.getenv("NEPTUNE_API_TOKEN"),
        admin_token=admin_token,
        admin=os.getenv("ADMIN_USERNAME"),
        user=user,
    )
Esempio n. 2
0
def get_project_list(api_token: Optional[str] = None) -> List[str]:
    """Get a list of projects you have access to.
    Args:
        api_token(str, optional): User’s API token. Defaults to `None`.
            If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken.
            .. note::
                It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your
                API token in plain text in your source code.
    Returns:
        ``List[str]``: list of project names of a format 'WORKSPACE/PROJECT'
    Examples:
        >>> from neptune import management
        >>> management.get_project_list()
    You may also want to check `management API reference`_.
    .. _management API reference:
       https://docs.neptune.ai/api-reference/management
    """
    verify_type("api_token", api_token, (str, type(None)))

    backend_client = _get_backend_client(api_token=api_token)

    params = {
        "userRelation": "viewerOrHigher",
        "sortBy": ["lastViewed"],
        **DEFAULT_REQUEST_KWARGS,
    }

    projects = backend_client.api.listProjects(
        **params).response().result.entries

    return [
        normalize_project_name(name=project.name,
                               workspace=project.organizationName)
        for project in projects
    ]
Esempio n. 3
0
    def test_standard_scenario(self, environment: "Environment"):
        project_name, project_key = a_project_name(
            project_slug=f"{fake.slug()}-mgmt")
        project_identifier = normalize_project_name(
            name=project_name, workspace=environment.workspace)

        assert project_identifier not in get_project_list(
            api_token=environment.admin_token)
        assert environment.user in get_workspace_member_list(
            name=environment.workspace, api_token=environment.admin_token)
        assert (get_workspace_member_list(
            name=environment.workspace, api_token=environment.admin_token).get(
                environment.user) == "member")

        created_project_identifier = create_project(
            name=project_name,
            key=project_key,
            visibility="priv",
            workspace=environment.workspace,
            api_token=environment.admin_token,
        )

        assert created_project_identifier == project_identifier
        assert created_project_identifier in get_project_list(
            api_token=environment.admin_token)
        assert environment.user not in get_project_member_list(
            name=created_project_identifier, api_token=environment.admin_token)

        add_project_member(
            name=created_project_identifier,
            username=environment.user,
            role="contributor",
            api_token=environment.admin_token,
        )

        assert environment.user in get_project_member_list(
            name=created_project_identifier, api_token=environment.admin_token)
        assert (get_project_member_list(name=created_project_identifier,
                                        api_token=environment.admin_token).get(
                                            environment.user) == "contributor")
        assert created_project_identifier in get_project_list(
            api_token=environment.user_token)

        remove_project_member(
            name=created_project_identifier,
            username=environment.user,
            api_token=environment.admin_token,
        )

        assert environment.user not in get_project_member_list(
            name=created_project_identifier, api_token=environment.admin_token)

        delete_project(name=created_project_identifier,
                       api_token=environment.admin_token)

        assert project_identifier not in get_project_list(
            api_token=environment.admin_token)
Esempio n. 4
0
def remove_project_member(
    name: str,
    username: str,
    workspace: Optional[str] = None,
    api_token: Optional[str] = None,
):
    """Removes member from the Neptune project.
    Args:
        name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'.
            If workspace argument was set, it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'.
        username(str): name of the user you want to remove from the project.
        workspace(str, optional): Name of your Neptune workspace.
            If you specify change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'.
            If 'None' it will be parsed from the name argument.
        api_token(str, optional): User’s API token. Defaults to `None`.
            If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken.
            .. note::
                It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your
                API token in plain text in your source code.
    Examples:
        >>> from neptune import management
        >>> management.remove_project_member(name="awesome-team/amazing-project",
        ...                                  username="******")
    You may also want to check `management API reference`_.
    .. _management API reference:
       https://docs.neptune.ai/api-reference/management
    """
    verify_type("name", name, str)
    verify_type("username", username, str)
    verify_type("workspace", workspace, (str, type(None)))
    verify_type("api_token", api_token, (str, type(None)))

    backend_client = _get_backend_client(api_token=api_token)
    project_identifier = normalize_project_name(name=name, workspace=workspace)

    params = {
        "projectIdentifier": project_identifier,
        "userId": username,
        **DEFAULT_REQUEST_KWARGS,
    }

    try:
        backend_client.api.deleteProjectMember(**params).response()
    except HTTPNotFound as e:
        raise ProjectNotFound(name=project_identifier) from e
    except HTTPUnprocessableEntity as e:
        raise UserNotExistsOrWithoutAccess(user=username,
                                           project=project_identifier) from e
    except HTTPForbidden as e:
        raise AccessRevokedOnMemberRemoval(user=username,
                                           project=project_identifier) from e
Esempio n. 5
0
    def test_normalize_project_name(self):
        self.assertEqual("jackie/sandbox",
                         normalize_project_name(name="jackie/sandbox"))
        self.assertEqual(
            "jackie/sandbox",
            normalize_project_name(name="sandbox", workspace="jackie"))
        self.assertEqual(
            "jackie/sandbox",
            normalize_project_name(name="jackie/sandbox", workspace="jackie"),
        )

        with self.assertRaises(InvalidProjectName):
            normalize_project_name(name="nothing/else/matters")

        with self.assertRaises(MissingWorkspaceName):
            normalize_project_name(name="sandbox")

        with self.assertRaises(ConflictingWorkspaceName):
            normalize_project_name(name="jackie/sandbox", workspace="john")
Esempio n. 6
0
def get_project_member_list(name: str,
                            workspace: Optional[str] = None,
                            api_token: Optional[str] = None) -> Dict[str, str]:
    """Get a list of members for a project.
    Args:
        name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'.
            If workspace argument was set it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'.
        workspace(str, optional): Name of your Neptune workspace.
            If you specify change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'.
            If 'None' it will be parsed from the name argument.
        api_token(str, optional): User’s API token. Defaults to `None`.
            If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken.
            .. note::
                It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your
                API token in plain text in your source code.
    Returns:
        ``Dict[str, str]``: Dictionary with usernames as keys and ProjectMemberRoles
        ('owner', 'contributor', 'viewer') as values.
    Examples:
        >>> from neptune import management
        >>> management.get_project_member_list(name="awesome-team/amazing-project")
    You may also want to check `management API reference`_.
    .. _management API reference:
       https://docs.neptune.ai/api-reference/management
    """
    verify_type("name", name, str)
    verify_type("workspace", workspace, (str, type(None)))
    verify_type("api_token", api_token, (str, type(None)))

    backend_client = _get_backend_client(api_token=api_token)
    project_identifier = normalize_project_name(name=name, workspace=workspace)

    params = {
        "projectIdentifier": project_identifier,
        **DEFAULT_REQUEST_KWARGS
    }

    try:
        result = backend_client.api.listProjectMembers(
            **params).response().result
        return {
            f"{m.registeredMemberInfo.username}":
            ProjectMemberRoleDTO.to_domain(m.role)
            for m in result
        }
    except HTTPNotFound as e:
        raise ProjectNotFound(name=project_identifier) from e
Esempio n. 7
0
def add_project_member(
    name: str,
    username: str,
    role: str,
    workspace: Optional[str] = None,
    api_token: Optional[str] = None,
):
    """Adds member to the Neptune project.
    Args:
        name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'.
            If workspace argument was set, it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'.
        username(str): Name of the user you want to add to the project.
        role(str): level of permissions the user should have in a project.
            Can be set to:
             - 'viewer': can only view project content and members
             - 'contributor': can view and edit project content and only view members
             - 'owner': can view and edit project content and members
            For more information, see `user roles in a project docs`_.
        workspace(str, optional): Name of your Neptune workspace.
            If you specify it, change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'.
            If 'None' it will be parsed from the name argument.
        api_token(str, optional): User’s API token. Defaults to `None`.
            If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken.
            .. note::
                It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your
                API token in plain text in your source code.
    Examples:
        >>> from neptune import management
        >>> management.add_project_member(name="awesome-team/amazing-project",
        ...                               username="******",
        ...                               role="contributor")
    You may also want to check `management API reference`_.
    .. _management API reference:
       https://docs.neptune.ai/api-reference/management
    .. _user roles in a project docs:
       https://docs.neptune.ai/administration/user-management#roles-in-a-project
    """
    verify_type("name", name, str)
    verify_type("username", username, str)
    verify_type("role", role, str)
    verify_type("workspace", workspace, (str, type(None)))
    verify_type("api_token", api_token, (str, type(None)))

    backend_client = _get_backend_client(api_token=api_token)
    project_identifier = normalize_project_name(name=name, workspace=workspace)

    params = {
        "projectIdentifier": project_identifier,
        "member": {
            "userId": username,
            "role": ProjectMemberRoleDTO.from_str(role).value,
        },
        **DEFAULT_REQUEST_KWARGS,
    }

    try:
        backend_client.api.addProjectMember(**params).response()
    except HTTPNotFound as e:
        raise ProjectNotFound(name=project_identifier) from e
    except HTTPConflict as e:
        raise UserAlreadyHasAccess(user=username,
                                   project=project_identifier) from e
Esempio n. 8
0
def create_project(
    name: str,
    key: str,
    workspace: Optional[str] = None,
    visibility: str = ProjectVisibility.PRIVATE,
    description: Optional[str] = None,
    api_token: Optional[str] = None,
) -> str:
    """Creates a new project in your Neptune workspace.
    Args:
        name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'.
            If workspace argument was set, it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'.
        key(str): Project identifier. It has to be contain 1-10 upper case letters or numbers.
            For example, 'GOOD5'
        workspace(str, optional): Name of your Neptune workspace.
            If you specify it, change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'.
            If 'None' it will be parsed from the `name` argument.
        visibility(str, optional): level of visibility you want your project to have.
            Can be set to:
             - 'pub' for public projects
             - 'priv' for private projects
            If 'None' it will be set to 'priv'
        description(str, optional): Project description.
            If 'None', it will be left empty.
        api_token(str, optional): User’s API token. Defaults to `None`.
            If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken.
            .. note::
                It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your
                API token in plain text in your source code.
    Returns:
        ``str``: name of the new project you created.
    Examples:
        >>> from neptune import management
        >>> management.create_project(name="awesome-team/amazing-project",
        ...                           key="AMA",
        ...                           visibility="pub")
    You may also want to check `management API reference`_.
    .. _management API reference:
       https://docs.neptune.ai/api-reference/management
    """
    verify_type("name", name, str)
    verify_type("key", key, str)
    verify_type("workspace", workspace, (str, type(None)))
    verify_type("visibility", visibility, str)
    verify_type("description", description, (str, type(None)))
    verify_type("api_token", api_token, (str, type(None)))

    backend_client = _get_backend_client(api_token=api_token)
    project_identifier = normalize_project_name(name=name, workspace=workspace)

    project_spec = re.search(PROJECT_QUALIFIED_NAME_PATTERN,
                             project_identifier)
    workspace, name = project_spec["workspace"], project_spec["project"]

    try:
        workspaces = (backend_client.api.listOrganizations(
            **DEFAULT_REQUEST_KWARGS).response().result)
        workspace_name_to_id = {f"{f.name}": f.id for f in workspaces}
    except HTTPNotFound:
        raise WorkspaceNotFound(workspace=workspace)

    if workspace not in workspace_name_to_id:
        raise WorkspaceNotFound(workspace=workspace)

    params = {
        "projectToCreate": {
            "name": name,
            "description": description,
            "projectKey": key,
            "organizationId": workspace_name_to_id[workspace],
            "visibility": ProjectVisibilityDTO.from_str(visibility).value,
        },
        **DEFAULT_REQUEST_KWARGS,
    }

    try:
        response = backend_client.api.createProject(**params).response()
        return normalize_project_name(
            name=response.result.name,
            workspace=response.result.organizationName)
    except HTTPBadRequest as e:
        validation_errors = parse_validation_errors(error=e)
        if "ERR_NOT_UNIQUE" in validation_errors:
            raise ProjectAlreadyExists(name=project_identifier) from e
        raise BadRequestException(validation_errors=validation_errors)
    except HTTPUnprocessableEntity as e:
        raise ProjectsLimitReached() from e