Skip to content

Instantly share code, notes, and snippets.

@mingliangguo
Created July 1, 2025 15:25
Show Gist options
  • Save mingliangguo/1cfe4155901aabb6d7f18d04d886474d to your computer and use it in GitHub Desktop.
Save mingliangguo/1cfe4155901aabb6d7f18d04d886474d to your computer and use it in GitHub Desktop.

Revisions

  1. mingliangguo created this gist Jul 1, 2025.
    102 changes: 102 additions & 0 deletions list-gcp-projects.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    import json
    import time

    from google.auth import default
    from googleapiclient.discovery import build


    def search_all_projects(scope: str):
    credentials, _ = default()
    service = build("cloudasset", "v1", credentials=credentials)

    # scope = f"organizations/{org_id}"
    asset_types = ["cloudresourcemanager.googleapis.com/Project"]

    # filter out prod projects and sys generated (start with sys-)
    request = service.v1().searchAllResources(
    scope=scope,
    assetTypes=asset_types,
    query="state:ACTIVE AND NOT labels.environment:prod AND NOT name:sys-",
    )
    all_projects = []

    while request is not None:
    response = request.execute()
    all_projects.extend(response.get("results", []))
    request = service.v1().searchAllResources_next(
    previous_request=request, previous_response=response
    )
    write_file = f"{scope}.json"
    with open(write_file, "w", encoding="utf-8") as f:
    json.dump(all_projects, f, indent=2, ensure_ascii=False)

    return all_projects


    def list_gcp_projects(org_id: str):
    credentials, _ = default()
    service = build("cloudresourcemanager", "v1", credentials=credentials)

    # request = service.projects().list(filter=f"parent.type:organization parent.id:{org_id}")
    request = service.projects().list(
    filter=f"parent.type:folder parent.id:{org_id} AND state:ACTIVE AND NOT labels.cflt_environment:prod"
    )
    projects = []

    while request is not None:
    response = request.execute()
    projects.extend(response.get("projects", []))
    request = service.projects().list_next(
    previous_request=request, previous_response=response
    )

    return projects


    def check_name(project_name: str):
    """
    Check if the project name contains 'prod', 'non-prod', 'nonprod', or 'preprod'.
    """
    return (
    "prod" not in project_name.lower()
    or "non-prod" in project_name.lower()
    or "nonprod" in project_name.lower()
    or "preprod" in project_name.lower()
    )


    if __name__ == "__main__":
    # Replace with your actual org ID (numbers only)
    # confluent org id
    ORG_ID = "123"

    FOLDER_ID = "456"

    org_scope = f"organizations/{ORG_ID}"
    folder_scope = f"folders/{FOLDER_ID}"
    start_time = time.time()
    print(f"Start searching for projects in org {FOLDER_ID}")
    projects = search_all_projects(org_scope)
    elapsed = time.time() - start_time

    print(f"Execution time: {elapsed:.2f} seconds")
    print(f"Found {len(projects)} projects:")

    non_sys_projects = [
    p
    for p in projects
    if not (p["name"].split("/"))[-1].startswith("sys-")
    and (
    not "prod" in (p["name"].split("/"))[-1]
    or (
    "non-prod" in (p["name"].split("/"))[-1]
    or "nonprod" in (p["name"].split("/"))[-1]
    or "preprod" in (p["name"].split("/"))[-1]
    )
    )
    ]

    print(f"Found {len(non_sys_projects)} non system generated projects:")

    for project in non_sys_projects:
    print(f"- {project['project']} ({project['name']})")