'How to use GCP's ResourceManager Python client library to get all child Projects under a Folder?

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?



Solution 1:[1]

I was facing the same problem as you. I ended up using the search_projects method. If you do not specify a filter, it will return all the projects for which you have the resourcemanager.projects.get permission on. You may filter on the state field to only retain the ACTIVE ones, avoiding the ones marked for deletion.

Solution 2:[2]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alssanro
Solution 2