Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip staging db and aws on missing credentials #243

Merged
merged 9 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,12 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for information related to developing the

### Firebase Firestore
1. Step-by-step Guide
* Create a Firebase project in test mode with your google account, select `firebase_admin` as the SDK. [Firebase Firestore tutorial](https://firebase.google.com/docs/firestore)
* Generate a new private key by navigating to "Project settings">"Service account" in the project's dashboard.
* For dev database:
* Create a Firebase project in test mode with your google account, select `firebase_admin` as the SDK. [Firebase Firestore tutorial](https://firebase.google.com/docs/firestore)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very useful!

* Generate a new private key by navigating to "Project settings">"Service account" in the project's dashboard.
* For staging database:
* Reach out to the code owner for the necessary credentials.
* Set up an `.env` file as instructed.

**MIT license**

28 changes: 22 additions & 6 deletions cellpack/autopack/AWSHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from urllib.parse import parse_qs, urlparse, urlunparse

import boto3
from botocore.exceptions import ClientError
from botocore.exceptions import ClientError, NoCredentialsError


class AWSHandler(object):
Expand Down Expand Up @@ -115,8 +115,24 @@ def save_file_and_get_url(self, file_path):
"""
Uploads a file to S3 and returns the base url
"""
file_name = self.upload_file(file_path)
base_url = self.create_presigned_url(file_name)
if file_name and base_url:
if self.is_url_valid(base_url):
return file_name, base_url
try:
file_name = self.upload_file(file_path)
base_url = self.create_presigned_url(file_name)
if file_name and base_url:
if self.is_url_valid(base_url):
return file_name, base_url
except NoCredentialsError as e:
print(self.skip_aws_credentials(e))
return None, None
return None, None

@staticmethod
def skip_aws_credentials(e):
"""
Handles the case when AWS credentials are not configured.
Provides a detailed error message and instruction.
"""
aws_readme_url = (
"https://github.com/mesoscope/cellpack/blob/main/README.md#aws-s3"
)
return f"AWS credentials are not configured, details:{e}. If needed, refer to the instructions at {aws_readme_url}. \nSkipping the opening of new browser tabs -------------"
29 changes: 20 additions & 9 deletions cellpack/autopack/FirebaseHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ def __init__(self, default_db=None):
# check if firebase is already initialized
if not FirebaseHandler._initialized:
db_choice = FirebaseHandler.which_db(default_db=default_db)
if db_choice == "staging":
cred = FirebaseHandler.get_staging_creds()
else:
cred = FirebaseHandler.get_dev_creds()
login = credentials.Certificate(cred)
firebase_admin.initialize_app(login)
FirebaseHandler._initialized = True
FirebaseHandler._db = firestore.client()
cred = FirebaseHandler.get_creds(db_choice)
if cred:
login = credentials.Certificate(cred)
firebase_admin.initialize_app(login)
FirebaseHandler._db = firestore.client()
FirebaseHandler._initialized = True

self.db = FirebaseHandler._db
self.name = "firebase"
Expand All @@ -49,6 +47,14 @@ def which_db(default_db=None):
print(f"Using {options.get(choice, 'dev')} database -------------")
return options.get(choice, "dev") # default to dev db for recipe uploads

@staticmethod
def get_creds(db_choice):
if db_choice == "staging":
cred = FirebaseHandler.get_staging_creds()
else:
cred = FirebaseHandler.get_dev_creds()
return cred

@staticmethod
def doc_to_dict(doc):
return doc.to_dict()
Expand Down Expand Up @@ -115,8 +121,13 @@ def get_staging_creds():
# set override=True to refresh the .env file if softwares or tokens updated
load_dotenv(dotenv_path="./.env", override=False)
FIREBASE_TOKEN = os.getenv("FIREBASE_TOKEN")
firebase_key = FIREBASE_TOKEN.replace("\\n", "\n")
FIREBASE_EMAIL = os.getenv("FIREBASE_EMAIL")
if not FIREBASE_TOKEN or not FIREBASE_EMAIL:
print(
"Firebase credentials are not found. If needed, please contact the code owner for assistance. \nSkipping firebase staging database -------------"
)
return
firebase_key = FIREBASE_TOKEN.replace("\\n", "\n")
return {
"type": "service_account",
"project_id": "cell-pack-database",
Expand Down
4 changes: 4 additions & 0 deletions cellpack/autopack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,10 @@ def load_file(filename, destination="", cache="geometries", force=None):
if database_name == "firebase":
db = DATABASE_IDS.handlers().get(database_name)
initialize_db = db()
if not initialize_db._initialized:
sys.exit(
"The selected database is not initialized. Please set up Firebase credentials to pack remote recipes."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could link to the readme/instructions here similar to how we do for missing AWS credentials

)
db_handler = DBRecipeLoader(initialize_db)
recipe_id = file_path.split("/")[-1]
db_doc, _ = db_handler.collect_docs_by_id(
Expand Down
33 changes: 12 additions & 21 deletions cellpack/autopack/upy/simularium/simularium_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import matplotlib
import numpy as np
import trimesh
from botocore.exceptions import NoCredentialsError

from simulariumio import (
TrajectoryConverter,
Expand Down Expand Up @@ -1390,22 +1389,13 @@ def raycast_test(self, obj, start, end, length, **kw):
def post_and_open_file(self, file_name, open_results_in_browser=True):
simularium_file = Path(f"{file_name}.simularium")
url = None
try:
_, url = simulariumHelper.store_result_file(simularium_file, storage="aws")
except Exception as e:
aws_readme_url = (
"https://github.com/mesoscope/cellpack/blob/main/README.md#aws-s3"
)
if isinstance(e, NoCredentialsError):
print(
f"need to configure your aws account, find instructions here: {aws_readme_url}"
)
else:
print(
f"An error occurred while storing the file {simularium_file} to S3: {e}"
)
if url is not None and open_results_in_browser:
simulariumHelper.open_in_simularium(url)
file_name, url = simulariumHelper.store_result_file(
simularium_file, storage="aws"
)
if file_name and url:
simulariumHelper.store_metadata(file_name, url, db="firebase")
if open_results_in_browser:
simulariumHelper.open_in_simularium(url)

@staticmethod
def store_result_file(file_path, storage=None):
Expand All @@ -1416,8 +1406,7 @@ def store_result_file(file_path, storage=None):
sub_folder_name="simularium",
region_name="us-west-2",
)
file_name, url = initialized_handler.save_file_and_get_url(file_path)
simulariumHelper.store_metadata(file_name, url, db="firebase")
file_name, url = initialized_handler.save_file_and_get_url(file_path)
return file_name, url

@staticmethod
Expand All @@ -1427,8 +1416,10 @@ def store_metadata(file_name, url, db=None):
initialized_db = handler(
default_db="staging"
) # default to staging for metadata uploads
db_uploader = DBUploader(initialized_db)
db_uploader.upload_result_metadata(file_name, url)
if initialized_db._initialized:
db_uploader = DBUploader(initialized_db)
db_uploader.upload_result_metadata(file_name, url)
return

@staticmethod
def open_in_simularium(aws_url):
Expand Down
17 changes: 12 additions & 5 deletions cellpack/bin/upload.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import sys
import fire

from cellpack.autopack.FirebaseHandler import FirebaseHandler
from cellpack.autopack.DBRecipeHandler import DBUploader

Expand All @@ -18,11 +20,16 @@ def upload(
if db_id == DATABASE_IDS.FIREBASE:
# fetch the service key json file
db_handler = FirebaseHandler()
recipe_loader = RecipeLoader(recipe_path)
recipe_full_data = recipe_loader._read(resolve_inheritance=False)
recipe_meta_data = recipe_loader.get_only_recipe_metadata()
recipe_db_handler = DBUploader(db_handler)
recipe_db_handler.upload_recipe(recipe_meta_data, recipe_full_data)
if FirebaseHandler._initialized:
recipe_loader = RecipeLoader(recipe_path)
recipe_full_data = recipe_loader._read(resolve_inheritance=False)
recipe_meta_data = recipe_loader.get_only_recipe_metadata()
recipe_db_handler = DBUploader(db_handler)
recipe_db_handler.upload_recipe(recipe_meta_data, recipe_full_data)
else:
sys.exit(
"The selected database is not initialized. Please set up Firebase credentials to upload recipes."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could link to the readme/instructions here similar to AWS

)


def main():
Expand Down
Loading