v3 of the Cloud ResourceManager Python API has a list_projects
method, but it only returns Projects that are direct children of the given Folder.
For example, you could have sub-folders of that main folder with their own projects and sub-folders and so on.
How can one programmatically get all of the child projects underneath a given folder?
I believe I've solved this using a recursive function, but would appreciate any and all input to improve/refine this. Of course, this is just sample code, and is littered with print statements for verification & debugging, so you will need to modify to suit your needs.
It gets all of the project names and sticks them into a list. For a large organization, you will probably need a better data, file or other structure.
#!/usr/bin/env python3
from google.cloud.resourcemanager_v3 import ProjectsClient, FoldersClient
all_projects = []
def get_folders_and_projects(folder_id):
"""
Get a list of projects and folders, given a folder ID.
"""
client = ProjectsClient()
list_of_projects = client.list_projects(parent=f'folders/{folder_id}')
print(f"Projects in Folder `{folder_id}`:")
for project in list_of_projects:
print(project.project_id)
all_projects.append(project.project_id) # Add the project names to a list
print("")
client = FoldersClient()
list_of_folders = client.list_folders(parent=f'folders/{folder_id}')
for folder in list_of_folders:
print(f"Folder Name: {folder.display_name}, Folder ID: {folder.name}")
folder_id = folder.name.strip('folders/')
# Call the same f'n again to get child projects & folders:
get_folders_and_projects(folder_id)
get_folders_and_projects('123456789012')
print(all_projects)
One caveat: this code does not have the ability to start with an organization ID, since that requires a different format to the parent
argument, i.e. organizations/org_id
Addition, 25 May 2022: Inspired by @Alssanro's answer that I did not know about prior, I developed some code to use the Cloud Asset API to search for Active projects within a parent.
from google.cloud.asset_v1 import AssetServiceClient, SearchAllResourcesRequest
# The starting parent can be any of the following:
parent = "projects/123456789012"
# parent = "projects/project-name-id"
# parent = "folders/123456789012"
# parent = "organizations/123456789012"
client = AssetServiceClient()
# Construct the request argument
request = SearchAllResourcesRequest(
scope=parent,
asset_types=[
"cloudresourcemanager.googleapis.com/Project",
],
query="state:ACTIVE",
)
# Make the request
paged_results = client.search_all_resources(request=request)
# Handle the response
for response in paged_results:
project_id = response.name.split("/")[4]
print(
f"Project Name: {response.display_name}, Project ID: {project_id}, State: {response.state}, "
)
Note that I did not use the Resource Manager API as I could not find an easy way to search for/return projects that started at a specific parent AND are active.