Skip to content

Commit

Permalink
Merge pull request #44 from newscorp-ghfb/Story/PE-7553-Revise-gcppro…
Browse files Browse the repository at this point in the history
…jects

Story/pe 7553 revise gcpprojects
  • Loading branch information
WCierkowski authored Oct 29, 2024
2 parents ec077b9 + c166787 commit 347abb8
Showing 1 changed file with 57 additions and 38 deletions.
95 changes: 57 additions & 38 deletions tools/c7n_org/scripts/gcpprojects.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# Copyright The Cloud Custodian Authors.
# SPDX-License-Identifier: Apache-2.0

from c7n_gcp.client import Session
import click
import yaml

from c7n_gcp.client import Session


@click.command()
@click.option(
"-f",
Expand All @@ -19,66 +17,87 @@
"-e",
"--exclude",
multiple=True,
help="list of folders that won't be added to the config file",
help="List of folders that won't be added to the config file",
)
@click.option(
"-b",
"--buid",
required=False,
multiple=True,
help="List folders the will be added to the config file",
help="List of folder IDs that will be added to the config file",
)
@click.option(
"-ap",
"--appscript",
default=False,
is_flag=True,
help="list of app script projects to account files",
help="Exclude App Script projects from the account files",
)
def main(output, exclude, appscript, buid):
"""
Generate a c7n-org gcp projects config file
Generate a c7n-org GCP projects config file.
"""
client = Session().client("cloudresourcemanager", "v1", "projects")
session = Session()
client = session.client("cloudresourcemanager", "v1", "projects")
folder_client = session.client("cloudresourcemanager", "v2", "folders")

# Helper function to retrieve all subfolders for each buid
def get_all_subfolders(folder_id):
subfolders = set()
request = folder_client.execute_query("list", {"parent": f"folders/{folder_id}"})
for folder in request.get("folders", []):
subfolders.add(folder["name"].split("/")[-1])
subfolders.update(get_all_subfolders(folder["name"].split("/")[-1])) # Recursive call
return subfolders

# Check if buid is empty; if so, assume flat structure and set organization ID
results = []
organization_id = "161588151302" # Replace with your actual organization ID
all_folders = set(buid) if buid else set()

if not buid:
print("No BUID specified; assuming flat organization. Listing all projects under organization.")

else:
# Hierarchical structure: gather all folders and subfolders for each buid
for folder_id in buid:
all_folders.update(get_all_subfolders(folder_id))

# Retrieve all projects and apply filtering in Python
for page in client.execute_paged_query("list", {}):
for project in page.get("projects", []):
# Exclude App Script GCP Projects
if appscript == False:
if "sys-" in project["projectId"]:
continue

if (
project["lifecycleState"] != "ACTIVE"
or project["projectNumber"] in exclude
):
# Exclude App Script projects if the flag is set
if not appscript and "sys-" in project["projectId"]:
continue

if buid != ():
if project["parent"]["type"] != "folder":
continue
for fold in buid:
if project["parent"]["id"] != fold:
continue

project_info = {
"project_id": project["projectId"],
"project_number": project["projectNumber"],
"name": project["name"],
}
# Exclude projects in inactive states or those in excluded folders
if project["lifecycleState"] != "ACTIVE" or project["projectNumber"] in exclude:
continue

if "labels" in project:
project_info["tags"] = [
"%s:%s" % (k, v) for k, v in project.get("labels", {}).items()
]
project_info["vars"] = {
k: v for k, v in project.get("labels", {}).items()
# Filtering logic for flat and hierarchical organization structures
if (not buid and project["parent"].get("type") == "organization" and project["parent"].get("id") == organization_id) or \
(buid and project["parent"].get("type") == "folder" and project["parent"].get("id") in all_folders):

# Collect project details
project_info = {
"project_id": project["projectId"],
"project_number": project["projectNumber"],
"name": project["name"],
}
results.append(project_info)

output.write(yaml.safe_dump({"projects": results}, default_flow_style=False))
# Include labels if they exist
if "labels" in project:
project_info["tags"] = [
f"{k}:{v}" for k, v in project.get("labels", {}).items()
]
project_info["vars"] = {
k: v for k, v in project.get("labels", {}).items()
}

results.append(project_info)

# Output project information to YAML
output.write(yaml.safe_dump({"projects": results}, default_flow_style=False))

if __name__ == "__main__":
main()
main()

0 comments on commit 347abb8

Please sign in to comment.