IAM & Service Accounts¶
- Client:
google-cloud-iam(iam_admin_v1.IAMClient) - Transport: gRPC only. The client ships no REST transport and honors no emulator env var, so drongo runs an in-process gRPC server and injects a transport pointing the default client at it.
- Backend: per-project.
Use the normal client with no transport argument. Scoped to service
accounts and their keys.
A third interception mode
Most gRPC-first GCP services are handled by forcing the client onto its REST
transport (Secret Manager, Cloud Tasks, ...) or by an emulator env var
(Pub/Sub, Firestore). IAM Admin has neither, so drongo introduces a third
mode: it starts the in-process gRPC server and injects a transport built
on an insecure channel to it during the mock scope. Your code still just
calls IAMClient().
Service accounts¶
from drongo import mock_gcp
@mock_gcp
def test_service_accounts():
from google.cloud import iam_admin_v1 as iam
client = iam.IAMClient()
parent = "projects/my-project"
sa = client.create_service_account(
request={
"name": parent,
"account_id": "worker",
"service_account": {"display_name": "Worker"},
}
)
assert sa.email == "worker@my-project.iam.gserviceaccount.com"
# Addressable by email or by unique id.
assert (
client.get_service_account(request={"name": sa.name}).display_name == "Worker"
)
by_uid = client.get_service_account(
request={"name": f"{parent}/serviceAccounts/{sa.unique_id}"}
)
assert by_uid.email == sa.email
list_service_accounts, delete_service_account, and
enable_service_account / disable_service_account all work as expected;
duplicates raise AlreadyExists, missing accounts raise NotFound.
Keys¶
create_service_account_key returns key material (a fake but non-empty blob, as
the real API does):
@mock_gcp
def test_keys():
from google.cloud import iam_admin_v1 as iam
client = iam.IAMClient()
sa = client.create_service_account(
request={"name": "projects/p", "account_id": "svc", "service_account": {}}
)
key = client.create_service_account_key(request={"name": sa.name})
assert key.private_key_data
assert [
k.name for k in client.list_service_account_keys(request={"name": sa.name}).keys
] == [key.name]
client.delete_service_account_key(request={"name": key.name})
Coverage¶
| Operation | Status |
|---|---|
| Create / get / list / delete service account | Supported |
| Get by email or unique id | Supported |
| Enable / disable service account | Supported |
| Create / list / get / delete key | Supported |
| Update (display name / description) | Planned |
Roles (custom roles, QueryGrantableRoles) |
Planned |
IAM policy get/set (getIamPolicy/setIamPolicy) |
Planned |
SignBlob / SignJwt (IAM Credentials API) |
Planned |