1

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?

KJH
  • 2,382
  • 16
  • 26

3 Answers3

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.

KJH
  • 2,382
  • 16
  • 26
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.

Alssanro
  • 145
  • 1
  • 10
  • A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted](/help/deleted-answers). –  May 11 '22 at 21:00
0

If you have folders under folders under folders in your organization, then search_projects is the easier option. list_projects will only return projects under specific org or folder but will not go further recursively.

resource_manager_client = resourcemanager_v3.ProjectsClient(credentials=credentials)
projects = resource_manager_client.search_projects()
    
# Iterate
for project in projects:
  print(project.project_id)
Maria
  • 33
  • 1
  • 7