Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,12 @@ asyncio.run(main())
API | Level | Access |
:-----------------------------------------------------------|:------------------:|:-------------------------------------|
Account Management - Account limits | :x: | |
Account Management - User management | :x: | |
Account Management - Group management | :x: | |
Account Management - Permission management | :x: | |
Account Management - Policy management | :x: | |
Account Management - Service user management | :x: | |
Account Management - Platform tokens | :x: | |
Account Management - User management | :heavy_check_mark: | `dt.account.iam_users` |
Account Management - Group management | :heavy_check_mark: | `dt.account.iam_groups` |
Account Management - Permission management | :heavy_check_mark: | `dt.account.iam_policies` |
Account Management - Policy management | :heavy_check_mark: | `dt.account.iam_policies` |
Account Management - Service user management | :heavy_check_mark: | `dt.account.iam_service_users` |
Account Management - Platform tokens | :heavy_check_mark: | `dt.account.iam_platform_tokens` |
Environment management API v1 | :heavy_check_mark: | `dt.account.env_v1` |
Environment management API v2 | :heavy_check_mark: | `dt.account.env_v2` |
Dynatrace Platform Subscription - Subscription management | :heavy_check_mark: | `dt.account.sub_v2` |
Expand Down
1 change: 1 addition & 0 deletions dynatrace/account/iam_v1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Account IAM v1 API wrappers."""
165 changes: 165 additions & 0 deletions dynatrace/account/iam_v1/groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"""Account group management API wrappers."""

import builtins
from typing import Any, Union

from httpx import Response

from dynatrace.dynatrace_object import DynatraceObject
from dynatrace.http_client import HttpClient


class AccountGroupsService:
"""
/iam/v1 Group management API

- GET /iam/v1/accounts/{accountUuid}/groups
- POST /iam/v1/accounts/{accountUuid}/groups
- GET /iam/v1/accounts/{accountUuid}/groups/{groupUuid}/users
- PUT /iam/v1/accounts/{accountUuid}/groups/{groupUuid}
- DELETE /iam/v1/accounts/{accountUuid}/groups/{groupUuid}
"""

def __init__(self, http_client: HttpClient) -> None:
self.__http_client = http_client

async def list(self, account_uuid: str) -> "GroupList":
"""List all user groups of an account."""
resp = (
await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/groups"
)
).json()
return GroupList(raw_element=resp)

async def create(
self, account_uuid: str, groups: builtins.list[dict[str, Any]]
) -> builtins.list["Group"]:
"""Create new user groups."""
resp = (
await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/groups",
method="POST",
json=groups,
)
).json()
return [Group(raw_element=e) for e in resp]

async def get_members(self, account_uuid: str, group_uuid: str) -> "GroupMembers":
"""List all members of a group."""
resp = (
await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/groups/{group_uuid}/users"
)
).json()
return GroupMembers(raw_element=resp)

async def update(
self,
account_uuid: str,
group_uuid: str,
group_config: Union["GroupUpdateRequest", dict[str, Any]],
) -> Response:
"""Edit a user group."""
if isinstance(group_config, GroupUpdateRequest):
body = group_config.to_json()
else:
body = group_config
return await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/groups/{group_uuid}",
method="PUT",
json=body,
)

async def delete(self, account_uuid: str, group_uuid: str) -> Response:
"""Delete a user group."""
return await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/groups/{group_uuid}",
method="DELETE",
)


# Response models
class Group(DynatraceObject):
"""Group object."""

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.uuid: str | None = raw_element.get("uuid")
self.name: str | None = raw_element.get("name")
self.description: str | None = raw_element.get("description")
self.federated_attribute_values: list[str] = raw_element.get(
"federatedAttributeValues", []
)
self.owner: str | None = raw_element.get("owner")
self.created_at: str | None = raw_element.get("createdAt")
self.updated_at: str | None = raw_element.get("updatedAt")

def to_json(self) -> dict[str, Any]:
return {
"uuid": self.uuid,
"name": self.name,
"description": self.description,
"federatedAttributeValues": self.federated_attribute_values,
}


class GroupList(DynatraceObject):
"""List of groups."""

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.count: int | None = raw_element.get("count")
self.items: list[Group] = [
Group(raw_element=e) for e in raw_element.get("items", [])
]


class GroupUser(DynatraceObject):
"""User in a group."""

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.uid: str | None = raw_element.get("uid")
self.email: str | None = raw_element.get("email")
self.name: str | None = raw_element.get("name")
self.surname: str | None = raw_element.get("surname")
self.user_status: str | None = raw_element.get("userStatus")
self.emergency_contact: bool | None = raw_element.get("emergencyContact")


class GroupMembers(DynatraceObject):
"""Members of a group."""

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.count: int | None = raw_element.get("count")
self.items: list[GroupUser] = [
GroupUser(raw_element=e) for e in raw_element.get("items", [])
]


class GroupUpdateRequest(DynatraceObject):
"""Request for updating a group."""

def __init__(
self,
name: str,
description: str | None = None,
federated_attribute_values: list[str] | None = None,
**kwargs: Any,
) -> None:
super().__init__(**kwargs)
self.name = name
self.description = description
self.federated_attribute_values = federated_attribute_values or []

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.name = raw_element.get("name")
self.description = raw_element.get("description")
self.federated_attribute_values = raw_element.get(
"federatedAttributeValues", []
)

def to_json(self) -> dict[str, Any]:
return {
"name": self.name,
"description": self.description,
"federatedAttributeValues": self.federated_attribute_values,
}
145 changes: 145 additions & 0 deletions dynatrace/account/iam_v1/platform_tokens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"""Account platform tokens management API wrappers."""

import builtins
from typing import Any

from httpx import Response

from dynatrace.dynatrace_object import DynatraceObject
from dynatrace.http_client import HttpClient


class AccountPlatformTokensService:
"""
/iam/v1 Platform tokens management API

- GET /iam/v1/accounts/{accountUuid}/platform-tokens
- POST /iam/v1/accounts/{accountUuid}/platform-tokens
- DELETE /iam/v1/accounts/{accountUuid}/platform-tokens/{platformTokenId}
- PUT /iam/v1/accounts/{accountUuid}/platform-tokens/{platformTokenId}/expiration-date
- PUT /iam/v1/accounts/{accountUuid}/platform-tokens/{platformTokenId}/status
"""

def __init__(self, http_client: HttpClient) -> None:
self.__http_client = http_client

async def list(
self,
account_uuid: str,
search_term: str | None = None,
status: str | None = None,
page: int | None = None,
size: int | None = None,
) -> "PlatformTokenPage":
"""List all platform tokens within account."""
params = {}
if search_term is not None:
params["searchTerm"] = search_term
if status is not None:
params["status"] = status
if page is not None:
params["page"] = page
if size is not None:
params["size"] = size

resp = (
await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/platform-tokens",
params=params,
)
).json()
return PlatformTokenPage(raw_element=resp)

async def create(
self,
account_uuid: str,
name: str,
scopes: builtins.list[str],
expiration_date: str | None = None,
) -> "PlatformTokenSecret":
"""Create a new platform token for user."""
body = {"name": name, "scopes": scopes}
if expiration_date:
body["expirationDate"] = expiration_date

resp = (
await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/platform-tokens",
method="POST",
json=body,
)
).json()
return PlatformTokenSecret(raw_element=resp)

async def delete(self, account_uuid: str, platform_token_id: str) -> Response:
"""Delete a platform token."""
return await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/platform-tokens/{platform_token_id}",
method="DELETE",
)

async def set_expiration_date(
self,
account_uuid: str,
platform_token_id: str,
expiration_date: str,
) -> Response:
"""Update platform token expiration date."""
body = {"expirationDate": expiration_date}
return await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/platform-tokens/{platform_token_id}/expiration-date",
method="PUT",
json=body,
)

async def set_status(
self,
account_uuid: str,
platform_token_id: str,
status: str,
) -> Response:
"""Update platform token status."""
body = {"status": status}
return await self.__http_client.make_request(
f"/iam/v1/accounts/{account_uuid}/platform-tokens/{platform_token_id}/status",
method="PUT",
json=body,
)


# Response models
class PlatformToken(DynatraceObject):
"""Platform token object."""

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.token_id: str | None = raw_element.get("tokenId")
self.name: str | None = raw_element.get("name")
self.status: str | None = raw_element.get("status")
self.created_by: str | None = raw_element.get("createdBy")
self.created_at: str | None = raw_element.get("createdAt")
self.last_used_at: str | None = raw_element.get("lastUsedAt")
self.expiration_date: str | None = raw_element.get("expirationDate")
self.scopes: list[str] = raw_element.get("scopes", [])


class PlatformTokenPage(DynatraceObject):
"""Page of platform tokens."""

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.items: list[PlatformToken] = [
PlatformToken(raw_element=e) for e in raw_element.get("items", [])
]
self.page_size: int | None = raw_element.get("pageSize")
self.total_items: int | None = raw_element.get("totalItems")


class PlatformTokenSecret(DynatraceObject):
"""Platform token secret (returned on creation)."""

def _create_from_raw_data(self, raw_element: dict[str, Any]):
self.token_id: str | None = raw_element.get("tokenId")
self.secret: str | None = raw_element.get("secret")
self.name: str | None = raw_element.get("name")
self.scopes: list[str] = raw_element.get("scopes", [])
self.expiration_date: str | None = raw_element.get("expirationDate")
self.created_at: str | None = raw_element.get("createdAt")
Loading
Loading