Skip to content

Commit

Permalink
Feature/eng 131 allow changing user roles in cluster organization pro…
Browse files Browse the repository at this point in the history
…ject (#3009)
  • Loading branch information
mikeoz32 authored Jun 14, 2024
1 parent 1b0c52f commit 939d9f8
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ neuro-sdk/build
neuro-sdk/dist
neuro-sdk/docs/_build
pip-wheel-metadata
venv
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ repos:
- id: pyupgrade
args: ['--py37-plus']
- repo: https://github.com/PyCQA/flake8
rev: '4.0.1'
rev: '7.0.0'
hooks:
- id: flake8
exclude: "^neuro-sdk/docs/"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.D/3009.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add update-cluster-user command.
20 changes: 20 additions & 0 deletions CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
* [neuro admin set-user-quota](#neuro-admin-set-user-quota)
* [neuro admin show-cluster-options](#neuro-admin-show-cluster-options)
* [neuro admin update-cluster](#neuro-admin-update-cluster)
* [neuro admin update-cluster-user](#neuro-admin-update-cluster-user)
* [neuro admin update-node-pool](#neuro-admin-update-node-pool)
* [neuro admin update-org-cluster](#neuro-admin-update-org-cluster)
* [neuro admin update-project](#neuro-admin-update-project)
Expand Down Expand Up @@ -486,6 +487,7 @@ Name | Description|
| _[neuro admin set\-user-quota](#neuro-admin-set-user-quota)_| Set user quota to given values |
| _[neuro admin show\-cluster-options](#neuro-admin-show-cluster-options)_| Show available cluster options |
| _[neuro admin update-cluster](#neuro-admin-update-cluster)_| Update a cluster |
| _[neuro admin update\-cluster-user](#neuro-admin-update-cluster-user)_| |
| _[neuro admin update\-node-pool](#neuro-admin-update-node-pool)_| Update cluster node pool |
| _[neuro admin update\-org-cluster](#neuro-admin-update-org-cluster)_| Update org cluster quotas |
| _[neuro admin update-project](#neuro-admin-update-project)_| Update project settings |
Expand Down Expand Up @@ -1218,6 +1220,24 @@ Name | Description|



### neuro admin update-cluster-user

**Usage:**

```bash
neuro admin update-cluster-user [OPTIONS] CLUSTER_NAME USER_NAME [ROLE]
```

**Options:**

Name | Description|
|----|------------|
|_--help_|Show this message and exit.|
|_--org ORG_|org name for org-cluster users|




### neuro admin update-node-pool

Update cluster node pool.
Expand Down
23 changes: 23 additions & 0 deletions neuro-cli/docs/admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Cluster administration commands.
| [_set-user-quota_](admin.md#set-user-quota) | Set user quota to given values |
| [_show-cluster-options_](admin.md#show-cluster-options) | Show available cluster options |
| [_update-cluster_](admin.md#update-cluster) | Update a cluster |
| [_update-cluster-user_](admin.md#update-cluster-user) | |
| [_update-node-pool_](admin.md#update-node-pool) | Update cluster node pool |
| [_update-org-cluster_](admin.md#update-org-cluster) | Update org cluster quotas |
| [_update-project_](admin.md#update-project) | Update project settings |
Expand Down Expand Up @@ -867,6 +868,28 @@ Update a cluster.



### update-cluster-user




#### Usage

```bash
neuro admin update-cluster-user [OPTIONS] CLUSTER_NAME USER_NAME [ROLE]
```



#### Options

| Name | Description |
| :--- | :--- |
| _--help_ | Show this message and exit. |
| _--org ORG_ | org name for org-cluster users |



### update-node-pool

Update cluster node pool
Expand Down
53 changes: 50 additions & 3 deletions neuro-cli/src/neuro_cli/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,50 @@ async def add_cluster_user(
root.print(balance_fmt(user.balance))


@command()
@argument("cluster_name", required=True, type=str)
@argument("user_name", required=True, type=str)
@argument(
"role",
required=True,
metavar="[ROLE]",
type=click.Choice([str(role) for role in list(_ClusterUserRoleType)]),
)
@option(
"--org",
metavar="ORG",
default=None,
type=str,
help="org name for org-cluster users",
)
async def update_cluster_user(
root: Root,
cluster_name: str,
user_name: str,
role: str,
org: Optional[str],
) -> None:
cluster_user = await root.client._admin.get_cluster_user(
cluster_name, user_name, org_name=org
)
cluster_user = replace(cluster_user, role=_ClusterUserRoleType(role))
await root.client._admin.update_cluster_user(cluster_user)

if not root.quiet:
root.print(
f"New role for user [bold]{rich_escape(cluster_user.user_name)}[/bold] "
+ (
f"as member of org [bold]{rich_escape(org)}[/bold] "
if org is not None
else ""
)
+ f"on cluster [u]{rich_escape(cluster_name)}[/u]:",
markup=True,
end=" ",
)
root.print(str(cluster_user.role))


def _parse_finite_decimal(value: str) -> Decimal:
try:
result = Decimal(value)
Expand Down Expand Up @@ -1148,9 +1192,11 @@ async def update_resource_preset(
raise ValueError(f"Preset '{preset_name}' does not exists")

kwargs: Dict[str, Any] = {
"credits_per_hour": _parse_finite_decimal(credits_per_hour)
if credits_per_hour is not None
else None,
"credits_per_hour": (
_parse_finite_decimal(credits_per_hour)
if credits_per_hour is not None
else None
),
"cpu": cpu,
"memory": memory,
"nvidia_gpu": nvidia_gpu,
Expand Down Expand Up @@ -2079,6 +2125,7 @@ async def remove_project_user(

admin.add_command(get_cluster_users)
admin.add_command(add_cluster_user)
admin.add_command(update_cluster_user)
admin.add_command(remove_cluster_user)

admin.add_command(get_user_quota)
Expand Down
60 changes: 60 additions & 0 deletions neuro-cli/tests/unit/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
_CloudProviderOptions,
_CloudProviderType,
_Clusters,
_ClusterUser,
_ClusterUserRoleType,
_ClusterUserWithInfo,
_EFSPerformanceMode,
Expand Down Expand Up @@ -147,6 +148,65 @@ def test_add_cluster_user_with_jobs(run_cli: _RunCli) -> None:
assert capture.code == 2


def test_update_cluster_user(run_cli: _RunCli) -> None:
with ExitStack() as exit_stack:

async def get_cluster_user(
cluster_name: str,
user_name: str,
org_name: Optional[str] = None,
) -> _ClusterUserWithInfo:
return _ClusterUserWithInfo(
cluster_name=cluster_name,
user_name=user_name,
role=_ClusterUserRoleType.USER,
quota=_Quota(),
balance=_Balance(),
org_name=org_name,
user_info=_UserInfo(email=f"{user_name}@example.org"),
)

mocked_get = exit_stack.enter_context(
mock.patch.object(_Admin, "get_cluster_user")
)
mocked_get.side_effect = get_cluster_user

async def update_cluster_user(
cluster_user: _ClusterUser, with_user_info: bool = False
) -> _ClusterUser:
return cluster_user

mocked_update = exit_stack.enter_context(
mock.patch.object(_Admin, "update_cluster_user")
)
mocked_update.side_effect = update_cluster_user

capture = run_cli(
["admin", "update-cluster-user", "default", "test-user", "manager"]
)

assert capture.code == 0
assert capture.out == "New role for user test-user on cluster default: manager"

capture = run_cli(
[
"admin",
"update-cluster-user",
"default",
"test-user",
"manager",
"--org",
"test-org",
]
)

assert capture.code == 0
assert capture.out == (
"New role for user test-user as member of org test-org "
"on cluster default: manager"
)


def test_set_user_credits(run_cli: _RunCli) -> None:
with mock.patch.object(_Admin, "update_cluster_user_balance") as mocked:

Expand Down
4 changes: 2 additions & 2 deletions neuro-sdk/src/neuro_sdk/_gcs_bucket_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def __init__(self, key_data_json_b64: str, request: Request) -> None:

async def _do_refresh(self) -> None:
await self._credential.refresh(self._request)
self._token = self._credential.token
self._token = self._credential.token # type: ignore

def _refresh_required(self) -> bool:
return not self._token or not self._credential.valid
Expand Down Expand Up @@ -276,7 +276,7 @@ async def _upload_chunk(*, final: bool = False) -> None:
if size == 0:
data_range = "*"
else:
data_range = f"{uploaded_bytes}-{uploaded_bytes+size-1}"
data_range = f"{uploaded_bytes}-{uploaded_bytes + size - 1}"
async with self._request(
"PUT",
url=str(session_url),
Expand Down
4 changes: 2 additions & 2 deletions neuro-sdk/tests/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ async def handler(request: web.Request) -> web.StreamResponse:
response.set_status(web.HTTPPartialContent.status_code)
response.headers[
"Content-Range"
] = f"bytes {start}-{stop-1}/{len(content)}"
] = f"bytes {start}-{stop - 1}/{len(content)}"
response.content_length = stop - start
await response.prepare(request)
chunk_size = 200
Expand Down Expand Up @@ -1408,7 +1408,7 @@ async def handler(request: web.Request) -> web.StreamResponse:
start, stop, _ = rng.indices(len(data))
return web.Response(
status=web.HTTPPartialContent.status_code,
headers={"Content-Range": f"bytes {start}-{stop-1}/{len(data)}"},
headers={"Content-Range": f"bytes {start}-{stop - 1}/{len(data)}"},
body=data[start:stop],
)
else:
Expand Down

0 comments on commit 939d9f8

Please sign in to comment.