diff --git a/scripts/export_systems_with_owners/README.md b/scripts/export_systems_with_owners/README.md new file mode 100644 index 0000000..bf3e9de --- /dev/null +++ b/scripts/export_systems_with_owners/README.md @@ -0,0 +1,23 @@ +# Export Systems with Owners to CSV + +This script is designed to fetch all Systems in your OpsLevel account, along with their owning Team, and export the results to a CSV file. + +Prerequisites: + +- Systems must exist in your OpsLevel account. +- Owner will be blank in the output for Systems with no Team assigned as owner, or with a non-Team owner. + +Requirements: + +- Python 3.10.10 or higher +- `requests` & `csv` libraries are installed + +To run this: + +1. Add your api token to an `OPSLEVEL_API_TOKEN` environment variable +2. Execute the command below +3. A `systems_with_owners.csv` file will be created in the same directory, containing one row per System with its name and owner. + +```bash +python ./export_systems_with_owners.py +``` diff --git a/scripts/export_systems_with_owners/export_systems_with_owners.py b/scripts/export_systems_with_owners/export_systems_with_owners.py new file mode 100644 index 0000000..753eab3 --- /dev/null +++ b/scripts/export_systems_with_owners/export_systems_with_owners.py @@ -0,0 +1,83 @@ +import os +import csv +import requests + +OPSLEVEL_API_TOKEN = os.environ["OPSLEVEL_API_TOKEN"] +OPSLEVEL_ENDPOINT = "https://app.opslevel.com/graphql" + +LIST_SYSTEMS_WITH_OWNERS_QUERY = """ + query systemsWithOwners($endCursor: String) { + account { + systems(after: $endCursor) { + nodes { + name + owner { + ... on Team { + name + } + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + } +""" + +def opslevel_graphql_query(query, variables=None): + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {OPSLEVEL_API_TOKEN}", + } + data = {"query": query, "variables": variables} + response = requests.post(OPSLEVEL_ENDPOINT, json=data, headers=headers) + if response.status_code != 200: + raise Exception(f"OpsLevel request failed: {response.content.decode()}") + return response.json() + + +def fetch_systems(): + """ + Fetches all systems and their owning team from OpsLevel. + Owner will be empty for systems with no Team owner set. + """ + cursor = None + has_next_page = True + systems = [] # Store fetched systems + while has_next_page: + response = opslevel_graphql_query( + LIST_SYSTEMS_WITH_OWNERS_QUERY, variables={"endCursor": cursor} + ) + nodes = response["data"]["account"]["systems"]["nodes"] + systems.extend(nodes) + page_info = response["data"]["account"]["systems"]["pageInfo"] + has_next_page = page_info["hasNextPage"] + cursor = page_info["endCursor"] + + return systems + + +def export_to_csv(systems, filename="systems_with_owners.csv"): + """ + Writes the collected systems list to a CSV file, one row per system. + """ + with open(filename, "w", newline="") as f: + writer = csv.writer(f) + writer.writerow(["name", "owner"]) + for system in systems: + owner_name = system["owner"]["name"] if system["owner"] else "" + writer.writerow([system["name"], owner_name]) + print(f"CSV file has been created at {filename}") + + +def main(): + systems = fetch_systems() + export_to_csv(systems) + + +if __name__ == "__main__": + if not OPSLEVEL_API_TOKEN: + raise ValueError("OPSLEVEL_API_TOKEN environment variable is not set.") + main()