harness-platform-sdk 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- harness_platform_sdk/__init__.py +56 -0
- harness_platform_sdk/authz/__init__.py +15 -0
- harness_platform_sdk/authz/resource_groups.py +274 -0
- harness_platform_sdk/authz/role_assignments.py +274 -0
- harness_platform_sdk/authz/roles.py +271 -0
- harness_platform_sdk/base_model.py +17 -0
- harness_platform_sdk/client.py +1540 -0
- harness_platform_sdk/config.py +63 -0
- harness_platform_sdk/exceptions.py +68 -0
- harness_platform_sdk/iacm_api/__init__.py +19 -0
- harness_platform_sdk/iacm_api/workspace_approvals.py +293 -0
- harness_platform_sdk/iacm_api/workspace_default_pipelines.py +300 -0
- harness_platform_sdk/iacm_api/workspace_states.py +205 -0
- harness_platform_sdk/iacm_api/workspace_variables.py +341 -0
- harness_platform_sdk/iacm_api/workspaces.py +301 -0
- harness_platform_sdk/idp_api/__init__.py +15 -0
- harness_platform_sdk/idp_api/catalog_custom_properties.py +389 -0
- harness_platform_sdk/idp_api/entities.py +332 -0
- harness_platform_sdk/idp_api/scores.py +359 -0
- harness_platform_sdk/models/authz/__init__.py +23 -0
- harness_platform_sdk/models/authz/resource_groups.py +47 -0
- harness_platform_sdk/models/authz/role_assignments.py +37 -0
- harness_platform_sdk/models/authz/roles.py +43 -0
- harness_platform_sdk/models/iacm_api/__init__.py +44 -0
- harness_platform_sdk/models/iacm_api/workspace_approvals.py +82 -0
- harness_platform_sdk/models/iacm_api/workspace_default_pipelines.py +104 -0
- harness_platform_sdk/models/iacm_api/workspace_states.py +37 -0
- harness_platform_sdk/models/iacm_api/workspace_variables.py +87 -0
- harness_platform_sdk/models/iacm_api/workspaces.py +107 -0
- harness_platform_sdk/models/idp_api/__init__.py +31 -0
- harness_platform_sdk/models/idp_api/catalog_custom_properties.py +56 -0
- harness_platform_sdk/models/idp_api/entities.py +80 -0
- harness_platform_sdk/models/idp_api/scores.py +64 -0
- harness_platform_sdk/models/ng_api/__init__.py +45 -0
- harness_platform_sdk/models/ng_api/connectors.py +44 -0
- harness_platform_sdk/models/ng_api/environments_v2.py +49 -0
- harness_platform_sdk/models/ng_api/infrastructures.py +63 -0
- harness_platform_sdk/models/ng_api/organizations.py +51 -0
- harness_platform_sdk/models/ng_api/projects.py +55 -0
- harness_platform_sdk/models/ng_api/secrets.py +45 -0
- harness_platform_sdk/models/ng_api/service_overrides.py +78 -0
- harness_platform_sdk/models/ng_api/services.py +55 -0
- harness_platform_sdk/models/ng_api/user_groups.py +61 -0
- harness_platform_sdk/models/ng_api/variables.py +53 -0
- harness_platform_sdk/models/pipeline_api/__init__.py +20 -0
- harness_platform_sdk/models/pipeline_api/input_sets_v0.py +67 -0
- harness_platform_sdk/models/pipeline_api/pipelines_v0.py +76 -0
- harness_platform_sdk/models/pipeline_api/triggers_v0.py +98 -0
- harness_platform_sdk/models/template_api/__init__.py +11 -0
- harness_platform_sdk/models/template_api/templates_v0.py +59 -0
- harness_platform_sdk/ng_api/__init__.py +29 -0
- harness_platform_sdk/ng_api/connectors.py +269 -0
- harness_platform_sdk/ng_api/environments_v2.py +314 -0
- harness_platform_sdk/ng_api/infrastructures.py +378 -0
- harness_platform_sdk/ng_api/organizations.py +269 -0
- harness_platform_sdk/ng_api/projects.py +265 -0
- harness_platform_sdk/ng_api/secrets.py +285 -0
- harness_platform_sdk/ng_api/service_overrides.py +342 -0
- harness_platform_sdk/ng_api/services.py +350 -0
- harness_platform_sdk/ng_api/user_groups.py +270 -0
- harness_platform_sdk/ng_api/variables.py +312 -0
- harness_platform_sdk/pagination.py +19 -0
- harness_platform_sdk/pipeline_api/__init__.py +15 -0
- harness_platform_sdk/pipeline_api/input_sets_v0.py +377 -0
- harness_platform_sdk/pipeline_api/pipelines_v0.py +324 -0
- harness_platform_sdk/pipeline_api/triggers_v0.py +372 -0
- harness_platform_sdk/py.typed +0 -0
- harness_platform_sdk/scope.py +28 -0
- harness_platform_sdk/template_api/__init__.py +10 -0
- harness_platform_sdk/template_api/templates_v0.py +576 -0
- harness_platform_sdk-1.0.0.dist-info/METADATA +209 -0
- harness_platform_sdk-1.0.0.dist-info/RECORD +74 -0
- harness_platform_sdk-1.0.0.dist-info/WHEEL +5 -0
- harness_platform_sdk-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Harness Platform SDK.
|
|
2
|
+
|
|
3
|
+
A Python SDK for interacting with the Harness Platform API.
|
|
4
|
+
Provides unified access to all Harness APIs (Organizations, Projects,
|
|
5
|
+
Pipelines, Connectors, Secrets, and more) with built-in authentication,
|
|
6
|
+
scope management, pagination, and retry handling.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .authz import *
|
|
10
|
+
from .client import HarnessClient
|
|
11
|
+
from .config import HarnessConfig
|
|
12
|
+
from .exceptions import ApiError, AuthError, HarnessSdkError, ScopeNotSetError
|
|
13
|
+
from .iacm_api import *
|
|
14
|
+
from .idp_api import *
|
|
15
|
+
from .ng_api import *
|
|
16
|
+
from .pipeline_api import *
|
|
17
|
+
from .scope import Scope
|
|
18
|
+
from .template_api import *
|
|
19
|
+
|
|
20
|
+
__version__ = "1.0.0"
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"HarnessClient",
|
|
24
|
+
"HarnessConfig",
|
|
25
|
+
"Scope",
|
|
26
|
+
"HarnessSdkError",
|
|
27
|
+
"ScopeNotSetError",
|
|
28
|
+
"ApiError",
|
|
29
|
+
"AuthError",
|
|
30
|
+
"OrganizationsApi",
|
|
31
|
+
"ProjectsApi",
|
|
32
|
+
"ServicesApi",
|
|
33
|
+
"RolesApi",
|
|
34
|
+
"ResourceGroupsApi",
|
|
35
|
+
"RoleAssignmentsApi",
|
|
36
|
+
"ConnectorsApi",
|
|
37
|
+
"SecretsApi",
|
|
38
|
+
"InfrastructuresApi",
|
|
39
|
+
"UserGroupsApi",
|
|
40
|
+
"PipelinesV0Api",
|
|
41
|
+
"InputSetsV0Api",
|
|
42
|
+
"TriggersV0Api",
|
|
43
|
+
"TemplatesV0Api",
|
|
44
|
+
"VariablesApi",
|
|
45
|
+
"ServiceOverridesApi",
|
|
46
|
+
# Infrastructure as Code
|
|
47
|
+
"WorkspacesApi",
|
|
48
|
+
"WorkspaceApprovalsApi",
|
|
49
|
+
"WorkspaceDefaultPipelinesApi",
|
|
50
|
+
"WorkspaceStatesApi",
|
|
51
|
+
"WorkspaceVariablesApi",
|
|
52
|
+
# Internal Developer Portal
|
|
53
|
+
"CatalogCustomPropertyApi",
|
|
54
|
+
"EntityApi",
|
|
55
|
+
"ScoreApi",
|
|
56
|
+
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Harness Authorization API resources.
|
|
2
|
+
|
|
3
|
+
Provides APIs for managing roles, resource groups, and role assignments
|
|
4
|
+
under the /authz/ path root.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .resource_groups import ResourceGroupsApi
|
|
8
|
+
from .role_assignments import RoleAssignmentsApi
|
|
9
|
+
from .roles import RolesApi
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"RolesApi",
|
|
13
|
+
"ResourceGroupsApi",
|
|
14
|
+
"RoleAssignmentsApi",
|
|
15
|
+
]
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"""ResourceGroups API client for Harness SDK.
|
|
2
|
+
|
|
3
|
+
Provides CRUD operations for resource_group resources.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections.abc import Iterator
|
|
9
|
+
|
|
10
|
+
from harness_platform_sdk.client import HarnessClient
|
|
11
|
+
from harness_platform_sdk.models.authz.resource_groups import (
|
|
12
|
+
ResourceGroupCreateRequest,
|
|
13
|
+
ResourceGroupResponse,
|
|
14
|
+
)
|
|
15
|
+
from harness_platform_sdk.pagination import PaginationStyle
|
|
16
|
+
from harness_platform_sdk.scope import Scope
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ResourceGroupsApi:
|
|
20
|
+
"""API client for resource_group operations."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, client: HarnessClient) -> None:
|
|
23
|
+
"""Initialize ResourceGroupsApi with HarnessClient.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
client: HarnessClient instance for making requests.
|
|
27
|
+
"""
|
|
28
|
+
self._client = client
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def root_api_path(self) -> str:
|
|
32
|
+
"""Get the root API path for resource group endpoints.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
str: The base API path for resource group operations.
|
|
36
|
+
"""
|
|
37
|
+
return "/authz/api/v2/resourcegroup"
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def unwrap_key(self) -> str:
|
|
41
|
+
"""Get the response unwrap key for resource group data.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
str: The key used to extract resource group data from API responses.
|
|
45
|
+
"""
|
|
46
|
+
return "resourceGroup"
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def should_wrap(self) -> bool:
|
|
50
|
+
"""Check if request bodies should be wrapped.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
bool: True if request bodies need to be wrapped before sending to API.
|
|
54
|
+
"""
|
|
55
|
+
return True
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def default_params(self):
|
|
59
|
+
"""Get the Default Request Parameters configuration."""
|
|
60
|
+
return getattr(self, "_default_params", None)
|
|
61
|
+
|
|
62
|
+
@default_params.setter
|
|
63
|
+
def default_params(self, resolved: Scope) -> dict:
|
|
64
|
+
"""Resolve Scope Variables and Set Default Params.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
resolved: Scope containing account/org/project context.
|
|
68
|
+
scope: Call-time scope (takes precedence).
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Dictionary of Parsed Querystrings from the scope
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
ScopeNotSetError: If required fields are missing.
|
|
75
|
+
"""
|
|
76
|
+
self._default_params = self._client._build_url(
|
|
77
|
+
"&".join(
|
|
78
|
+
[
|
|
79
|
+
"accountIdentifier={account_id}",
|
|
80
|
+
"orgIdentifier={org}",
|
|
81
|
+
"projectIdentifier={project}",
|
|
82
|
+
]
|
|
83
|
+
),
|
|
84
|
+
resolved,
|
|
85
|
+
is_params=True,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def resolved_scope(self):
|
|
90
|
+
"""Get the Resolved Scope configuration."""
|
|
91
|
+
return getattr(self, "_resolved_scope", None)
|
|
92
|
+
|
|
93
|
+
@resolved_scope.setter
|
|
94
|
+
def resolved_scope(self, scope: Scope) -> str:
|
|
95
|
+
"""Resolve Scope Variables and Set Default Params.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
scope: Call-time scope (takes precedence).
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Resolved Scope with all required fields.
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
ScopeNotSetError: If required fields are missing.
|
|
105
|
+
"""
|
|
106
|
+
self._resolved_scope = self._client._resolve_scope(scope)
|
|
107
|
+
# Call out to configure the default params
|
|
108
|
+
self.default_params = self._resolved_scope
|
|
109
|
+
|
|
110
|
+
def _wrapped_body(self, body: ResourceGroupCreateRequest) -> dict:
|
|
111
|
+
"""Resolve and wrap the body payload to additionally inject scope details into the payload."""
|
|
112
|
+
if not self.should_wrap:
|
|
113
|
+
return body
|
|
114
|
+
|
|
115
|
+
body = body.model_dump(exclude_none=True)
|
|
116
|
+
|
|
117
|
+
if "accountIdentifier" not in body or body["accountIdentifier"] is None:
|
|
118
|
+
body["accountIdentifier"] = self.resolved_scope.account_id
|
|
119
|
+
if "orgIdentifier" not in body or body["orgIdentifier"] is None:
|
|
120
|
+
body["orgIdentifier"] = self.resolved_scope.org
|
|
121
|
+
if "projectIdentifier" not in body or body["projectIdentifier"] is None:
|
|
122
|
+
body["projectIdentifier"] = self.resolved_scope.project
|
|
123
|
+
|
|
124
|
+
return {self.unwrap_key: body}
|
|
125
|
+
|
|
126
|
+
def list(self, scope: Scope | None = None, **kwargs) -> Iterator[ResourceGroupResponse]:
|
|
127
|
+
"""List resource_groups in the specified organization.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
scope: Scope containing org. If None, uses client default scope.
|
|
131
|
+
**kwargs: Additional query parameters (e.g., searchTerm).
|
|
132
|
+
|
|
133
|
+
Yields:
|
|
134
|
+
ResourceGroupResponse: Individual resource_group items across all pages.
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
138
|
+
"""
|
|
139
|
+
self.resolved_scope = scope
|
|
140
|
+
kwargs.update(self.default_params)
|
|
141
|
+
|
|
142
|
+
url = self._client._build_url(
|
|
143
|
+
"{root_api_path}",
|
|
144
|
+
self.resolved_scope,
|
|
145
|
+
root_api_path=self.root_api_path,
|
|
146
|
+
)
|
|
147
|
+
return self._client._paginate(
|
|
148
|
+
url,
|
|
149
|
+
params=kwargs,
|
|
150
|
+
response_model=ResourceGroupResponse,
|
|
151
|
+
pagination_style=PaginationStyle.OFFSET, # per pagination_inventory.md
|
|
152
|
+
scope=self.resolved_scope,
|
|
153
|
+
unwrap_field=self.unwrap_key, # API wraps each item in a "self.unwrap_key" field
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def get(self, identifier: str, scope: Scope | None = None) -> ResourceGroupResponse:
|
|
157
|
+
"""Get a single resource_group by ID.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
identifier: ResourceGroup identifier.
|
|
161
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
ResourceGroupResponse: The requested resource_group.
|
|
165
|
+
|
|
166
|
+
Raises:
|
|
167
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
168
|
+
ApiError: For non-2xx responses.
|
|
169
|
+
"""
|
|
170
|
+
self.resolved_scope = scope
|
|
171
|
+
url = self._client._build_url(
|
|
172
|
+
"{root_api_path}/{identifier}",
|
|
173
|
+
self.resolved_scope,
|
|
174
|
+
root_api_path=self.root_api_path,
|
|
175
|
+
identifier=identifier,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
response = self._client._get(url, params=self.default_params, response_model=None)
|
|
179
|
+
if not response:
|
|
180
|
+
return {}
|
|
181
|
+
|
|
182
|
+
unwrapped = self._client._unwrap_response(
|
|
183
|
+
key_type=self.unwrap_key, raw_data=response, scope=self.resolved_scope
|
|
184
|
+
)
|
|
185
|
+
return ResourceGroupResponse(**unwrapped)
|
|
186
|
+
|
|
187
|
+
def create(
|
|
188
|
+
self, body: ResourceGroupCreateRequest, scope: Scope | None = None
|
|
189
|
+
) -> ResourceGroupResponse:
|
|
190
|
+
"""Create a new resource_group.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
body: ResourceGroupCreateRequest request with required fields.
|
|
194
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
195
|
+
scope: Scope containing org. If None, uses client default scope.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
ResourceGroupResponse: The created resource_group.
|
|
199
|
+
|
|
200
|
+
Raises:
|
|
201
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
202
|
+
ApiError: For non-2xx responses.
|
|
203
|
+
"""
|
|
204
|
+
self.resolved_scope = scope
|
|
205
|
+
url = self._client._build_url(
|
|
206
|
+
"{root_api_path}",
|
|
207
|
+
self.resolved_scope,
|
|
208
|
+
root_api_path=self.root_api_path,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
response = self._client._post(
|
|
212
|
+
url, params=self.default_params, body=self._wrapped_body(body), response_model=None
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
unwrapped = self._client._unwrap_response(key_type=self.unwrap_key, raw_data=response)
|
|
216
|
+
return ResourceGroupResponse(**unwrapped)
|
|
217
|
+
|
|
218
|
+
def update(
|
|
219
|
+
self,
|
|
220
|
+
identifier: str,
|
|
221
|
+
body: ResourceGroupCreateRequest,
|
|
222
|
+
scope: Scope | None = None,
|
|
223
|
+
) -> ResourceGroupResponse:
|
|
224
|
+
"""Update an existing resource_group.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
identifier: resource_group identifier.
|
|
228
|
+
body: ResourceGroupCreateRequest request with updated fields.
|
|
229
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
ResourceGroupResponse: The updated resource_group.
|
|
233
|
+
|
|
234
|
+
Raises:
|
|
235
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
236
|
+
ApiError: For non-2xx responses.
|
|
237
|
+
"""
|
|
238
|
+
self.resolved_scope = scope
|
|
239
|
+
url = self._client._build_url(
|
|
240
|
+
"{root_api_path}/{identifier}",
|
|
241
|
+
self.resolved_scope,
|
|
242
|
+
root_api_path=self.root_api_path,
|
|
243
|
+
identifier=identifier,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
response = self._client._put(
|
|
247
|
+
url, params=self.default_params, body=self._wrapped_body(body), response_model=None
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
unwrapped = self._client._unwrap_response(key_type=self.unwrap_key, raw_data=response)
|
|
251
|
+
return ResourceGroupResponse(**unwrapped)
|
|
252
|
+
|
|
253
|
+
def delete(self, identifier: str, scope: Scope | None = None) -> dict | None:
|
|
254
|
+
"""Delete a resource_group.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
identifier: resource_group identifier.
|
|
258
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
dict | None: Response data (typically empty for DELETE).
|
|
262
|
+
|
|
263
|
+
Raises:
|
|
264
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
265
|
+
ApiError: For non-2xx responses.
|
|
266
|
+
"""
|
|
267
|
+
self.resolved_scope = scope
|
|
268
|
+
url = self._client._build_url(
|
|
269
|
+
"{root_api_path}/{identifier}",
|
|
270
|
+
self.resolved_scope,
|
|
271
|
+
root_api_path=self.root_api_path,
|
|
272
|
+
identifier=identifier,
|
|
273
|
+
)
|
|
274
|
+
return self._client._delete(url, params=self.default_params, response_model=None)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"""RoleAssignments API client for Harness SDK.
|
|
2
|
+
|
|
3
|
+
Provides CRUD operations for role_assignment resources.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections.abc import Iterator
|
|
9
|
+
|
|
10
|
+
from harness_platform_sdk.client import HarnessClient
|
|
11
|
+
from harness_platform_sdk.models.authz.role_assignments import (
|
|
12
|
+
RoleAssignmentCreateRequest,
|
|
13
|
+
RoleAssignmentResponse,
|
|
14
|
+
)
|
|
15
|
+
from harness_platform_sdk.pagination import PaginationStyle
|
|
16
|
+
from harness_platform_sdk.scope import Scope
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RoleAssignmentsApi:
|
|
20
|
+
"""API client for role_assignment operations."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, client: HarnessClient) -> None:
|
|
23
|
+
"""Initialize RoleAssignmentsApi with HarnessClient.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
client: HarnessClient instance for making requests.
|
|
27
|
+
"""
|
|
28
|
+
self._client = client
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def root_api_path(self) -> str:
|
|
32
|
+
"""Get the root API path for role assignment endpoints.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
str: The base API path for role assignment operations.
|
|
36
|
+
"""
|
|
37
|
+
return "/authz/api/roleassignments"
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def unwrap_key(self) -> str:
|
|
41
|
+
"""Get the response unwrap key for role assignment data.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
str: The key used to extract role assignment data from API responses.
|
|
45
|
+
"""
|
|
46
|
+
return "roleAssignment"
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def should_wrap(self) -> bool:
|
|
50
|
+
"""Check if request bodies should be wrapped.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
bool: False, as role assignment request bodies do not need wrapping.
|
|
54
|
+
"""
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def default_params(self):
|
|
59
|
+
"""Get the Default Request Parameters configuration."""
|
|
60
|
+
return getattr(self, "_default_params", None)
|
|
61
|
+
|
|
62
|
+
@default_params.setter
|
|
63
|
+
def default_params(self, resolved: Scope) -> dict:
|
|
64
|
+
"""Resolve Scope Variables and Set Default Params.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
resolved: Scope containing account/org/project context.
|
|
68
|
+
scope: Call-time scope (takes precedence).
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Dictionary of Parsed Querystrings from the scope
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
ScopeNotSetError: If required fields are missing.
|
|
75
|
+
"""
|
|
76
|
+
self._default_params = self._client._build_url(
|
|
77
|
+
"&".join(
|
|
78
|
+
[
|
|
79
|
+
"accountIdentifier={account_id}",
|
|
80
|
+
"orgIdentifier={org}",
|
|
81
|
+
"projectIdentifier={project}",
|
|
82
|
+
]
|
|
83
|
+
),
|
|
84
|
+
resolved,
|
|
85
|
+
is_params=True,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def resolved_scope(self):
|
|
90
|
+
"""Get the Resolved Scope configuration."""
|
|
91
|
+
return getattr(self, "_resolved_scope", None)
|
|
92
|
+
|
|
93
|
+
@resolved_scope.setter
|
|
94
|
+
def resolved_scope(self, scope: Scope) -> str:
|
|
95
|
+
"""Resolve Scope Variables and Set Default Params.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
scope: Call-time scope (takes precedence).
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Resolved Scope with all required fields.
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
ScopeNotSetError: If required fields are missing.
|
|
105
|
+
"""
|
|
106
|
+
self._resolved_scope = self._client._resolve_scope(scope)
|
|
107
|
+
# Call out to configure the default params
|
|
108
|
+
self.default_params = self._resolved_scope
|
|
109
|
+
|
|
110
|
+
def _wrapped_body(self, body: RoleAssignmentCreateRequest) -> dict:
|
|
111
|
+
"""Resolve and wrap the body payload to additionally inject scope details into the payload."""
|
|
112
|
+
if not self.should_wrap:
|
|
113
|
+
return body
|
|
114
|
+
|
|
115
|
+
body = body.model_dump(exclude_none=True)
|
|
116
|
+
|
|
117
|
+
if "accountIdentifier" not in body or body["accountIdentifier"] is None:
|
|
118
|
+
body["accountIdentifier"] = self.resolved_scope.account_id
|
|
119
|
+
if "orgIdentifier" not in body or body["orgIdentifier"] is None:
|
|
120
|
+
body["orgIdentifier"] = self.resolved_scope.org
|
|
121
|
+
if "projectIdentifier" not in body or body["projectIdentifier"] is None:
|
|
122
|
+
body["projectIdentifier"] = self.resolved_scope.project
|
|
123
|
+
|
|
124
|
+
return {self.unwrap_key: body}
|
|
125
|
+
|
|
126
|
+
def list(self, scope: Scope | None = None, **kwargs) -> Iterator[RoleAssignmentResponse]:
|
|
127
|
+
"""List role_assignments in the specified organization.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
scope: Scope containing org. If None, uses client default scope.
|
|
131
|
+
**kwargs: Additional query parameters (e.g., searchTerm).
|
|
132
|
+
|
|
133
|
+
Yields:
|
|
134
|
+
RoleAssignmentResponse: Individual role_assignment items across all pages.
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
138
|
+
"""
|
|
139
|
+
self.resolved_scope = scope
|
|
140
|
+
kwargs.update(self.default_params)
|
|
141
|
+
|
|
142
|
+
url = self._client._build_url(
|
|
143
|
+
"{root_api_path}",
|
|
144
|
+
self.resolved_scope,
|
|
145
|
+
root_api_path=self.root_api_path,
|
|
146
|
+
)
|
|
147
|
+
return self._client._paginate(
|
|
148
|
+
url,
|
|
149
|
+
params=kwargs,
|
|
150
|
+
response_model=RoleAssignmentResponse,
|
|
151
|
+
pagination_style=PaginationStyle.OFFSET, # per pagination_inventory.md
|
|
152
|
+
scope=self.resolved_scope,
|
|
153
|
+
unwrap_field=self.unwrap_key, # API wraps each item in a "self.unwrap_key" field
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def get(self, identifier: str, scope: Scope | None = None) -> RoleAssignmentResponse:
|
|
157
|
+
"""Get a single role_assignment by ID.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
identifier: RoleAssignment identifier.
|
|
161
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
RoleAssignmentResponse: The requested role_assignment.
|
|
165
|
+
|
|
166
|
+
Raises:
|
|
167
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
168
|
+
ApiError: For non-2xx responses.
|
|
169
|
+
"""
|
|
170
|
+
self.resolved_scope = scope
|
|
171
|
+
url = self._client._build_url(
|
|
172
|
+
"{root_api_path}/{identifier}",
|
|
173
|
+
self.resolved_scope,
|
|
174
|
+
root_api_path=self.root_api_path,
|
|
175
|
+
identifier=identifier,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
response = self._client._get(url, params=self.default_params, response_model=None)
|
|
179
|
+
if not response:
|
|
180
|
+
return {}
|
|
181
|
+
|
|
182
|
+
unwrapped = self._client._unwrap_response(
|
|
183
|
+
key_type=self.unwrap_key, raw_data=response, scope=self.resolved_scope
|
|
184
|
+
)
|
|
185
|
+
return RoleAssignmentResponse(**unwrapped)
|
|
186
|
+
|
|
187
|
+
def create(
|
|
188
|
+
self, body: RoleAssignmentCreateRequest, scope: Scope | None = None
|
|
189
|
+
) -> RoleAssignmentResponse:
|
|
190
|
+
"""Create a new role_assignment.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
body: RoleAssignmentCreateRequest request with required fields.
|
|
194
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
195
|
+
scope: Scope containing org. If None, uses client default scope.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
RoleAssignmentResponse: The created role_assignment.
|
|
199
|
+
|
|
200
|
+
Raises:
|
|
201
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
202
|
+
ApiError: For non-2xx responses.
|
|
203
|
+
"""
|
|
204
|
+
self.resolved_scope = scope
|
|
205
|
+
url = self._client._build_url(
|
|
206
|
+
"{root_api_path}",
|
|
207
|
+
self.resolved_scope,
|
|
208
|
+
root_api_path=self.root_api_path,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
response = self._client._post(
|
|
212
|
+
url, params=self.default_params, body=self._wrapped_body(body), response_model=None
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
unwrapped = self._client._unwrap_response(key_type=self.unwrap_key, raw_data=response)
|
|
216
|
+
return RoleAssignmentResponse(**unwrapped)
|
|
217
|
+
|
|
218
|
+
def update(
|
|
219
|
+
self,
|
|
220
|
+
identifier: str,
|
|
221
|
+
body: RoleAssignmentCreateRequest,
|
|
222
|
+
scope: Scope | None = None,
|
|
223
|
+
) -> RoleAssignmentResponse:
|
|
224
|
+
"""Update an existing role_assignment.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
identifier: role_assignment identifier.
|
|
228
|
+
body: RoleAssignmentCreateRequest request with updated fields.
|
|
229
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
RoleAssignmentResponse: The updated role_assignment.
|
|
233
|
+
|
|
234
|
+
Raises:
|
|
235
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
236
|
+
ApiError: For non-2xx responses.
|
|
237
|
+
"""
|
|
238
|
+
self.resolved_scope = scope
|
|
239
|
+
url = self._client._build_url(
|
|
240
|
+
"{root_api_path}/{identifier}",
|
|
241
|
+
self.resolved_scope,
|
|
242
|
+
root_api_path=self.root_api_path,
|
|
243
|
+
identifier=identifier,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
response = self._client._put(
|
|
247
|
+
url, params=self.default_params, body=self._wrapped_body(body), response_model=None
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
unwrapped = self._client._unwrap_response(key_type=self.unwrap_key, raw_data=response)
|
|
251
|
+
return RoleAssignmentResponse(**unwrapped)
|
|
252
|
+
|
|
253
|
+
def delete(self, identifier: str, scope: Scope | None = None) -> dict | None:
|
|
254
|
+
"""Delete a role_assignment.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
identifier: role_assignment identifier.
|
|
258
|
+
scope: Scope containing resource scope. If None, uses client default scope.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
dict | None: Response data (typically empty for DELETE).
|
|
262
|
+
|
|
263
|
+
Raises:
|
|
264
|
+
ScopeNotSetError: If scope cannot be resolved.
|
|
265
|
+
ApiError: For non-2xx responses.
|
|
266
|
+
"""
|
|
267
|
+
self.resolved_scope = scope
|
|
268
|
+
url = self._client._build_url(
|
|
269
|
+
"{root_api_path}/{identifier}",
|
|
270
|
+
self.resolved_scope,
|
|
271
|
+
root_api_path=self.root_api_path,
|
|
272
|
+
identifier=identifier,
|
|
273
|
+
)
|
|
274
|
+
return self._client._delete(url, params=self.default_params, response_model=None)
|