Interactive Admin Tutorial
This walkthrough shows how to use the read-only and low-risk administration helpers in pdum.gcp. The snippets were executed with Application Default Credentials (ADC) and the outputs were manually sanitized so that organization names, project IDs, and email addresses are replaced with fictitious placeholders such as acme-research, org-123456789, or user@example.com.
⚠️ Dangerous territory: These tools assume you already have broad administrator access across multiple Google Cloud organizations. They are great for rapid exploration and teardown in tiny, high-trust circles. They are a terrible fit for larger companies or low-trust environments.
Prerequisites
- Application Default Credentials are configured (
gcloud auth application-default login). - The identity behind those credentials has the necessary organization- and project-level permissions.
- Mutating helpers (project creation, IAM changes, API enablement, etc.) are intentionally out of scope for this tutorial. Stick to the read-heavy snippets unless you are absolutely certain about the impact.
Step 1 – Run doctor()
doctor() performs a preflight check: it confirms your active identity, reports the quota project, compares enabled APIs against the package’s required baseline, and inspects organization-level role coverage.
from pdum.gcp.admin import doctor
doctor()
# Output (sanitized sample)
╭─ Identity ───────────────────────────────────────────╮
│ Active identity: user@example.com │
╰──────────────────────────────────────────────────────╯
╭─ Quota Project ──────────────────────────────────────╮
│ Quota project: acme-research │
╰──────────────────────────────────────────────────────╯
╭─ APIs ───────────────────────────────────────────────╮
│ Status Service │
│ OK cloudbilling.googleapis.com │
│ OK cloudresourcemanager.googleapis.com │
│ Missing serviceusage.googleapis.com │
╰──────────────────────────────────────────────────────╯
╭─ Grant Missing Roles ────────────────────────────────╮
│ gcloud organizations add-iam-policy-binding 123456789│
│ --member="user:user@example.com" │
│ --role="roles/resourcemanager.projectCreator" │
╰──────────────────────────────────────────────────────╯
Take action on any missing APIs or roles before continuing.
Step 2 – “Just Go” Quick Survey
Once the environment is healthy, run a minimal survey to understand the landscape you can touch.
from pdum.gcp import get_email, list_organizations, quota_project, walk_projects
email = get_email()
orgs = list_organizations()
qp = quota_project()
projects = list(walk_projects(active_only=True))
print("Identity:", email)
print("Containers:", [f"{o.display_name} ({o.resource_name})" for o in orgs])
print("Quota project:", qp.id, qp.lifecycle_state)
print("First three projects:", [p.id for p in projects[:3]])
# Output (sanitized sample)
Identity: user@example.com
Containers: ['Acme Research (organizations/123456789)', 'No Organization (NO_ORG)']
Quota project: acme-research ACTIVE
First three projects: ['acme-sandbox-001', 'acme-data-lab', 'personal-scratchpad']
Explore containers interactively
target = next(o for o in orgs if o.display_name == "Acme Research")
print("Folders:", [f.display_name for f in target.folders()])
print("Projects:", [p.id for p in target.projects()])
target.tree()
# Output (sanitized sample)
Folders: ['Platform', 'Experiments']
Projects: ['acme-research-admin']
🌺 Acme Research (organizations/123456789)
├── 🎸 Platform (folders/444444444444)
│ └── 🎵 platform-admin (ACTIVE)
└── 🎸 Experiments (folders/555555555555)
├── 🎵 acme-lab-001 (ACTIVE)
└── 🎵 acme-lab-archived (DELETE_REQUESTED)
Navigate folders explicitly
from pdum.gcp.types import Folder
platform = next(f for f in target.folders() if f.display_name == "Platform")
experiments = target.cd("Experiments")
print("Platform parent:", platform.parent_resource_name)
print("Experiments projects:", [p.id for p in experiments.projects()])
# Output (sanitized sample)
Platform parent: organizations/123456789
Experiments projects: ['acme-lab-001', 'acme-lab-archived']
Inspect IAM roles you personally hold
roles = target.list_roles(user_email=email)
print("Roles on organization:", [r.name for r in roles])
# Output (sanitized sample)
Roles on organization: [
'roles/resourcemanager.organizationAdmin',
'roles/iam.securityAdmin',
'roles/billing.user'
]
Check quota project APIs
enabled = qp.enabled_apis()
print(f"{qp.id} has {len(enabled)} APIs enabled.")
print("Sample:", sorted(enabled)[:5])
# Output (sanitized sample)
acme-research has 37 APIs enabled.
Sample: [
'bigquery.googleapis.com',
'cloudbilling.googleapis.com',
'cloudresourcemanager.googleapis.com',
'iam.googleapis.com',
'serviceusage.googleapis.com'
]
Resolve human-friendly API names
from pdum.gcp import lookup_api
print("Compute:", lookup_api("Compute Engine"))
print("Billing:", lookup_api("Cloud Billing API"))
# Output (sanitized sample)
Compute: compute.googleapis.com
Billing: cloudbilling.googleapis.com
Peek at billing accounts
billing_accounts = target.billing_accounts(open_only=True)
for account in billing_accounts:
print(account.display_name, account.id, account.status)
# Output (sanitized sample)
Acme Master Billing 000000-111111-222222 OPEN
Acme Sandbox Billing 333333-444444-555555 OPEN
Look up resources by ID
from pdum.gcp.types import Organization, Project
org_lookup = Organization.lookup("123456789")
project_lookup = Project.lookup("acme-research-admin")
print("Organization display name:", org_lookup.display_name)
print("Project parent:", project_lookup.parent.resource_name)
# Output (sanitized sample)
Organization display name: Acme Research
Project parent: organizations/123456789
Mutation Syntax Reference (Do Not Run Here)
The snippets below show the APIs for write operations. They are intentionally not executed in this tutorial. Review credentials, confirm the target resources, and double-check prerequisites before running them in your own session.
Most helpers grab credentials from the resource itself or fall back to Application Default Credentials automatically. If you ever need an explicit override, the pattern is:
from google.auth import default
creds, _ = default()
Create a Folder
new_folder = target.create_folder(
"Research Staging",
)
Create a Project
from pdum.gcp.types import NO_BILLING_ACCOUNT, Project
project_id = Project.suggest_name(prefix="acme-research")
# Use the first billing account visible to the organization; fall back to NO_BILLING_ACCOUNT if none.
billing_account = next(iter(target.billing_accounts()), NO_BILLING_ACCOUNT)
created = target.create_project(
project_id,
"Acme Research Sandbox",
billing_account=billing_account,
timeout=600.0,
polling_interval=5.0,
)
Update Project Billing
# Reuse an existing billing account from the parent organization
new_billing_account = next(iter(target.billing_accounts(open_only=True)), None)
if new_billing_account:
created.update_billing_account(new_billing_account)
# Or by ID without a Project instance
Project.update_billing_account_for_id(
project_id,
"000000-111111-222222",
)
Grant Owners on a Project
project = Project.lookup(project_id)
project.add_user_as_owner("trusted-human@example.com")
Grant Org-Level Owner Roles
target.add_user_as_owner("trusted-human@example.com")
# Fine-grained control:
target.add_user_roles(
"trusted-human@example.com",
roles_to_add=[
"roles/resourcemanager.organizationAdmin",
"roles/billing.admin",
],
)
Enable APIs on a Project
services = [
lookup_api("Compute Engine API"),
lookup_api("Cloud Resource Manager API"),
]
project.enable_apis(
services,
timeout=300.0,
verbose=True,
polling_interval=5.0,
)
Where to Go Next
- Need a refresher on every public class and helper? See the API Reference.
- Thinking about mutations (project creation, IAM changes)? Re-read the warnings, audit your permissions, and script cautiously.
- If anything in this tutorial drifts out of date, follow the tutorial rebuild guide to regenerate fresh snippets with anonymized outputs.