Skip to content

Commit a1d0757

Browse files
authored
Merge pull request #342 from yjinjo/master
Add change_workspace_group api
2 parents f3aeaae + 1920e40 commit a1d0757

File tree

5 files changed

+143
-10
lines changed

5 files changed

+143
-10
lines changed

src/spaceone/identity/interface/grpc/workspace.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
from spaceone.core.pygrpc import BaseAPI
21
from spaceone.api.identity.v2 import workspace_pb2, workspace_pb2_grpc
2+
from spaceone.core.pygrpc import BaseAPI
3+
34
from spaceone.identity.service.workspace_service import WorkspaceService
45

56

@@ -19,6 +20,12 @@ def update(self, request, context):
1920
response: dict = workspace_svc.update(params)
2021
return self.dict_to_message(response)
2122

23+
def change_workspace_group(self, request, context):
24+
params, metadata = self.parse_request(request, context)
25+
workspace_svc = WorkspaceService(metadata)
26+
response: dict = workspace_svc.change_workspace_group(params)
27+
return self.dict_to_message(response)
28+
2229
def delete(self, request, context):
2330
params, metadata = self.parse_request(request, context)
2431
workspace_svc = WorkspaceService(metadata)

src/spaceone/identity/manager/workspace_manager.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ def delete_workspace_by_vo(workspace_vo: Workspace) -> None:
6060
_LOGGER.debug(
6161
f"[delete_workspace_by_vo] Delete role bindings count with {workspace_vo.workspace_id} : {rb_vos.count()}"
6262
)
63-
rb_vos.delete()
63+
for rb_vo in rb_vos:
64+
_LOGGER.debug(
65+
f"[delete_role_binding_by_vo] Delete role binding info: {rb_vo.to_dict()}"
66+
)
67+
rb_vo.delete()
6468

6569
workspace_vo.delete()
6670

src/spaceone/identity/model/workspace/request.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
from typing import Union, Literal
1+
from typing import Literal, Union
2+
23
from pydantic import BaseModel
34

45
__all__ = [
56
"WorkspaceCreateRequest",
67
"WorkspaceUpdateRequest",
8+
"WorkspaceChangeWorkspaceGroupRequest",
79
"WorkspaceDeleteRequest",
810
"WorkspaceEnableRequest",
911
"WorkspaceDisableRequest",
@@ -30,6 +32,12 @@ class WorkspaceUpdateRequest(BaseModel):
3032
domain_id: str
3133

3234

35+
class WorkspaceChangeWorkspaceGroupRequest(BaseModel):
36+
workspace_id: str
37+
workspace_group_id: Union[str, None] = None
38+
domain_id: str
39+
40+
3341
class WorkspaceDeleteRequest(BaseModel):
3442
force: Union[bool, None] = False
3543
workspace_id: str
@@ -64,6 +72,7 @@ class WorkspaceSearchQueryRequest(BaseModel):
6472
created_by: Union[str, None] = None
6573
is_managed: Union[bool, None] = None
6674
is_dormant: Union[bool, None] = None
75+
workspace_group_id: Union[str, None] = None
6776
domain_id: str
6877

6978

src/spaceone/identity/model/workspace/response.py

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class WorkspaceResponse(BaseModel):
2323
user_count: Union[int, None] = None
2424
cost_info: Union[dict, None] = None
2525
trusted_account_id: Union[str, None] = None
26+
workspace_group_id: Union[str, None] = None
2627
domain_id: Union[str, None] = None
2728
created_at: Union[datetime, None] = None
2829
last_synced_at: Union[datetime, None] = None

src/spaceone/identity/service/workspace_service.py

+119-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Union
2+
from typing import Dict, List, Union
33

44
from spaceone.core.error import *
55
from spaceone.core.service import *
@@ -11,16 +11,14 @@
1111
from spaceone.identity.manager.project_manager import ProjectManager
1212
from spaceone.identity.manager.resource_manager import ResourceManager
1313
from spaceone.identity.manager.role_binding_manager import RoleBindingManager
14-
from spaceone.identity.manager.service_account_manager import \
15-
ServiceAccountManager
16-
from spaceone.identity.manager.trusted_account_manager import \
17-
TrustedAccountManager
18-
from spaceone.identity.manager.workspace_group_manager import \
19-
WorkspaceGroupManager
14+
from spaceone.identity.manager.service_account_manager import ServiceAccountManager
15+
from spaceone.identity.manager.trusted_account_manager import TrustedAccountManager
16+
from spaceone.identity.manager.workspace_group_manager import WorkspaceGroupManager
2017
from spaceone.identity.manager.workspace_manager import WorkspaceManager
2118
from spaceone.identity.model import Workspace
2219
from spaceone.identity.model.workspace.request import *
2320
from spaceone.identity.model.workspace.response import *
21+
from spaceone.identity.service.role_binding_service import RoleBindingService
2422

2523
_LOGGER = logging.getLogger(__name__)
2624

@@ -86,6 +84,45 @@ def update(self, params: WorkspaceUpdateRequest) -> Union[WorkspaceResponse, dic
8684
)
8785
return WorkspaceResponse(**workspace_vo.to_dict())
8886

87+
@transaction(permission="identity:Workspace.write", role_types=["DOMAIN_ADMIN"])
88+
@convert_model
89+
def change_workspace_group(
90+
self, params: WorkspaceChangeWorkspaceGroupRequest
91+
) -> Union[WorkspaceResponse, dict]:
92+
"""Change workspace group
93+
Args:
94+
params (WorkspaceChangeWorkspaceGroupRequest): {
95+
'workspace_id': 'str', # required
96+
'workspace_group_id': 'str',
97+
'domain_id': 'str' # injected from auth (required)
98+
}
99+
Returns:
100+
WorkspaceResponse:
101+
"""
102+
workspace_id = params.workspace_id
103+
workspace_group_id = params.workspace_group_id
104+
domain_id = params.domain_id
105+
106+
workspace_vo = self.workspace_mgr.get_workspace(
107+
workspace_id=params.workspace_id, domain_id=domain_id
108+
)
109+
110+
previous_workspace_group_id = workspace_vo.workspace_group_id
111+
is_updatable = True
112+
if workspace_group_id:
113+
self._add_workspace_to_group(workspace_id, workspace_group_id, domain_id)
114+
elif previous_workspace_group_id:
115+
self._remove_workspace_from_group(
116+
previous_workspace_group_id, workspace_group_id, domain_id
117+
)
118+
119+
if is_updatable:
120+
workspace_vo = self.workspace_mgr.update_workspace_by_vo(
121+
params.dict(exclude_unset=False), workspace_vo
122+
)
123+
124+
return WorkspaceResponse(**workspace_vo.to_dict())
125+
89126
@transaction(permission="identity:Workspace.write", role_types=["DOMAIN_ADMIN"])
90127
@convert_model
91128
def delete(self, params: WorkspaceDeleteRequest) -> None:
@@ -230,6 +267,7 @@ def list(
230267
'created_by': 'str',
231268
'is_managed': 'bool',
232269
'is_dormant': 'bool',
270+
'workspace_group_id': 'str',
233271
'domain_id': 'str', # injected from auth (required)
234272
}
235273
Returns:
@@ -335,3 +373,77 @@ def _delete_related_resources_in_workspace(workspace_vo: Workspace):
335373
_LOGGER.debug(
336374
f"[_delete_related_resources_in_workspace] Delete workspace group: {workspace_group_vo.name} ({workspace_group_vo.workspace_group_id})"
337375
)
376+
377+
def _add_workspace_to_group(
378+
self, workspace_id: str, workspace_group_id: str, domain_id: str
379+
) -> bool:
380+
workspace_vo = self.workspace_mgr.get_workspace(
381+
workspace_id=workspace_id, domain_id=domain_id
382+
)
383+
workspace_group_mgr = WorkspaceGroupManager()
384+
existing_workspace_group_id = workspace_vo.workspace_group_id
385+
is_updatable = True
386+
387+
workspace_group_vo = workspace_group_mgr.get_workspace_group(
388+
workspace_group_id=workspace_group_id, domain_id=domain_id
389+
)
390+
391+
if existing_workspace_group_id:
392+
if existing_workspace_group_id != workspace_group_id:
393+
self._delete_role_bindings(existing_workspace_group_id, domain_id)
394+
395+
self._create_role_bindings(
396+
workspace_group_vo.users,
397+
workspace_id,
398+
workspace_group_id,
399+
domain_id,
400+
)
401+
else:
402+
is_updatable = False
403+
else:
404+
self._create_role_bindings(
405+
workspace_group_vo.users,
406+
workspace_id,
407+
workspace_group_id,
408+
domain_id,
409+
)
410+
411+
return is_updatable
412+
413+
def _remove_workspace_from_group(
414+
self, previous_workspace_group_id: str, workspace_group_id: str, domain_id: str
415+
) -> None:
416+
self._delete_role_bindings(previous_workspace_group_id, domain_id)
417+
418+
@staticmethod
419+
def _delete_role_bindings(existing_workspace_group_id: str, domain_id: str):
420+
rb_mgr = RoleBindingManager()
421+
rb_vos = rb_mgr.filter_role_bindings(
422+
workspace_group_id=existing_workspace_group_id,
423+
domain_id=domain_id,
424+
)
425+
for rb_vo in rb_vos:
426+
_LOGGER.debug(
427+
f"[_delete_role_bindings] Delete role binding info: {rb_vo.to_dict()}"
428+
)
429+
rb_vo.delete()
430+
431+
@staticmethod
432+
def _create_role_bindings(
433+
workspace_group_users: List[Dict[str, str]],
434+
workspace_id: str,
435+
workspace_group_id: str,
436+
domain_id: str,
437+
):
438+
rb_svc = RoleBindingService()
439+
for user_info in workspace_group_users or []:
440+
rb_svc.create_role_binding(
441+
{
442+
"user_id": user_info["user_id"],
443+
"role_id": user_info["role_id"],
444+
"resource_group": "WORKSPACE",
445+
"domain_id": domain_id,
446+
"workspace_group_id": workspace_group_id,
447+
"workspace_id": workspace_id,
448+
}
449+
)

0 commit comments

Comments
 (0)