From 66d49b1d2c5984985b1766b6113534ef327c3bac Mon Sep 17 00:00:00 2001 From: Venkat Date: Thu, 21 Nov 2024 16:35:45 +0000 Subject: [PATCH 1/2] feat: adding getoutline library --- glueops/getoutline.py | 165 ++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 2 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 glueops/getoutline.py diff --git a/glueops/getoutline.py b/glueops/getoutline.py new file mode 100644 index 0000000..4a1512b --- /dev/null +++ b/glueops/getoutline.py @@ -0,0 +1,165 @@ +import requests +import os +from glueops import setup_logging +import traceback + +LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") +logger = setup_logging.configure(level=LOG_LEVEL) + +class GetOutlineClient: + """ + A client to interact with the Outline API for managing documents. + """ + + def __init__(self, api_url, document_id, api_token): + """ + Initializes the GetOutlineClient with the necessary API credentials. + + :param api_url: The base URL for the Outline API. + :param document_id: The ID of the document to manage. + :param api_token: The API token for authentication. + """ + self.api_url = api_url.rstrip('/') # Ensure no trailing slash + self.document_id = document_id + self.api_token = api_token + self.headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {self.api_token}" + } + + def update_document(self, markdown_text): + """ + Updates the content of the specified document with new markdown text. + + :param markdown_text: The new markdown text to update the document with. + """ + logger.debug("Updating document on Outline.") + url = f"{self.api_url}/api/documents.update" + payload = { + "id": self.document_id, + "text": markdown_text + } + + try: + response = requests.post(url, json=payload, headers=self.headers) + response.raise_for_status() + logger.info(f"Updated document with ID: {self.document_id}") + except requests.exceptions.RequestException as e: + logger.error(f"Error updating document: {e}") + logger.error(traceback.format_exc()) + raise + + def get_document_uuid(self): + """ + Retrieves the UUID of the parent document. + + :return: The UUID of the parent document or None if an error occurs. + """ + url = f"{self.api_url}/api/documents.info" + payload = { + "id": self.document_id + } + + try: + response = requests.post(url, json=payload, headers=self.headers) + response.raise_for_status() + parent_id = response.json().get("data", {}).get("id") + logger.debug(f"Parent document UUID: {parent_id}") + return parent_id + except requests.exceptions.RequestException as e: + logger.error(f"Error getting parent document UUID: {e}") + logger.error(traceback.format_exc()) + raise + + + def get_children_documents_to_delete(self, parent_document_id): + """ + Retrieves a list of child document IDs under the specified parent document. + + :param parent_document_id: The UUID of the parent document. + :return: A list of child document IDs. + """ + url = f"{self.api_url}/api/documents.list" + payload = { + "parentDocumentId": parent_document_id, + "limit": 100, + "offset": 0 + } + all_ids = [] + + try: + while True: + response = requests.post(url, json=payload, headers=self.headers) + response.raise_for_status() + data = response.json() + child_docs = data.get("data", []) + new_ids = [doc.get("id") for doc in child_docs if "id" in doc] + all_ids.extend(new_ids) + + # Check if there is a next page + pagination = data.get("pagination", {}) + next_path = pagination.get("nextPath") + if len(new_ids) == 0 or not next_path: + break + + # Update the payload for the next request + payload["offset"] += payload["limit"] + + logger.debug(f"Child document IDs to delete: {all_ids}") + return all_ids + except requests.exceptions.RequestException as e: + logger.error(f"Error getting children documents: {e}") + logger.error(traceback.format_exc()) + raise + + + def delete_document(self, document_id): + """ + Deletes a document with the specified document ID. + + :param document_id: The ID of the document to delete. + :return: True if deletion was successful, False otherwise. + """ + url = f"{self.api_url}/api/documents.delete" + payload = { + "id": document_id + } + + try: + response = requests.post(url, json=payload, headers=self.headers) + response.raise_for_status() + logger.debug(f"Successfully deleted document with ID: {document_id}") + return True + except requests.exceptions.RequestException as e: + logger.error(f"Error deleting document {document_id}: {e}") + logger.error(traceback.format_exc()) + raise + + + def create_document(self, parent_document_id, title, text): + """ + Creates a new document under the specified parent document. + + :param parent_document_id: The UUID of the parent document. + :param title: The title of the new document. + :param text: The markdown text content of the new document. + :return: True if creation was successful, False otherwise. + """ + url = f"{self.api_url}/api/documents.create" + payload = { + "parentDocumentId": parent_document_id, + "title": title, + "text": text, + "publish": True + } + + try: + response = requests.post(url, json=payload, headers=self.headers) + response.raise_for_status() + logger.info(f"Successfully created document with title: {title}") + return True + except requests.exceptions.RequestException as e: + logger.error(f"Error creating document '{title}': {e}") + logger.error(traceback.format_exc()) + raise + diff --git a/setup.py b/setup.py index a606918..98493b0 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='glueops-helpers', - version='0.4.1', + version='0.6.0', packages=find_packages(), install_requires=[ 'requests', From b969c95fbfdcee69810f878a983c9263715aff54 Mon Sep 17 00:00:00 2001 From: Venkat Date: Thu, 21 Nov 2024 18:28:25 +0000 Subject: [PATCH 2/2] chore: update README.md --- README.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7f75fc5..ef49650 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,98 @@ -# glueops-helper-library +# GlueOps Helpers Library +The GlueOps Helpers Library is a collection of utility functions and classes designed to simplify common tasks in Python projects. This library includes helpers for logging, AWS interactions, Kubernetes configuration, and more. -The following does an install against tag: v0.0.11 +## Installation + +To install the GlueOps Helpers Library, you can use pip with the following command: ```bash -pip install https://github.com/GlueOps/python-glueops-helpers-library/archive/refs/tags/v0.0.11.zip +pip install https://github.com/GlueOps/python-glueops-helpers-library/archive/refs/tags/v0.6.0.zip +``` + +# Usage + +## Logging + +The library provides a logging configuration utility that sets up a JSON formatter for structured logging. + +```python +import os +from glueops import setup_logging + +LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") +logger = setup_logging.configure(level=LOG_LEVEL) + +logger.info("This is an info message") +logger.error("This is an error message") +``` + +## AWS +The library includes helpers for creating AWS clients and retrieving resources based on tags. + +```python +from glueops.aws import create_aws_client, get_resource_arns_using_tags + +# Create an AWS client +s3_client = create_aws_client('s3') + +# Get resource ARNs using tags +tags = [{'Key': 'Environment', 'Value': 'Production'}] +resource_arns = get_resource_arns_using_tags(tags, ['s3']) +print(resource_arns) +``` + +## Kubernetes + +```python +import os +from glueops.setup_kubernetes import load_kubernetes_config + +logger = setup_logging.configure(level="INFO") +v1, custom_api = load_kubernetes_config(logger) + +# Example: List all pods in the default namespace +pods = v1.list_namespaced_pod(namespace='default') +for pod in pods.items: + print(pod.metadata.name) ``` + +## Vault + +The library includes a client for interacting with HashiCorp Vault, supporting both Kubernetes and Pomerium authentication. + +```python +from glueops.vault_client import VaultClient + +vault_url = "https://vault.example.com" +kubernetes_role = "my-role" +vault_client = VaultClient(vault_url, kubernetes_role) + +# Get data from Vault +secret_path = "secret/data/my-secret" +data = vault_client.get_data_from_vault(secret_path) +print(data) + +# Write data to Vault +data_to_write = {"key": "value"} +vault_client.write_data_to_vault(secret_path, data_to_write) +``` + +## GetOutline + +The library provides a client for interacting with the GetOutline API for managing documents. + +```python +from glueops.getoutline import GetOutlineClient + +api_url = "https://api.getoutline.com" +document_id = "your_document_id" +api_token = "your_api_token" +outline_client = GetOutlineClient(api_url, document_id, api_token) + +# Create a new document +parent_document_id = "parent_document_id" +title = "New Document" +text = "This is the content of the new document." +outline_client.create_document(parent_document_id, title, text) +``` \ No newline at end of file