pythongoogle-cloud-platformgoogle-cloud-python

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

  • 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.