"""Config Vars.""" from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from distutils.util import strtobool import os from sqlalchemy.pool import QueuePool # Load env LOAD_ENV = strtobool(str(os.environ.get('LOAD_ENV', 'False'))) if LOAD_ENV: from dotenv import load_dotenv ENV_FILE = os.environ.get('ENV_FILE', None) if ENV_FILE: load_dotenv(ENV_FILE, override=True, verbose=True) elif os.path.exists(os.path.join(os.getcwd(), '.env')): load_dotenv(override=True, verbose=True) else: print('NOTICE: Environment file .env not found. Either create an ' 'environment (.env) file, or set LOAD_ENV=False in ' 'environment.') # Environment ---------------------------------------------------------------- PROD_ENVIRONMENT = 'prod' DEV_ENVIRONMENT = 'dev' QA_ENVIRONMENT = 'qa' TEST_ENVIRONMENT = 'test' ENVIRONMENT = os.environ.get('ENVIRONMENT', DEV_ENVIRONMENT).lower() APPLICATION_NAME = os.environ.get('APPLICATION_NAME', None) # Orchard-Specific ----------------------------------------------------------- # OA user id with creds to access Bulk Upload VAPI endpoint and insert rows OA_USER_LOGIN = str(os.environ.get('OA_USER_LOGIN', '')) # MySQL ---------------------------------------------------------------------- POOL_CLASS = QueuePool POOL_SIZE = 5 POOL_RECYCLE_MS = 3600 # Avoids connections going stale POOL_MAX_OVERFLOW = -1 POOL_PRE_PING = True POOL_RECYCLE = 3600 # Avoids connections going stale, recycle after 1 hour AR_MYSQL_USER = os.environ.get('AR_MYSQL_USER', None) AR_MYSQL_PASSWORD = os.environ.get('AR_MYSQL_PASSWORD', '') AR_MYSQL_HOST = os.environ.get('AR_MYSQL_HOST', None) AR_MYSQL_DB = os.environ.get('AR_MYSQL_DB', None) RDS_MYSQL_USER = os.environ.get('RDS_MYSQL_USER', None) RDS_MYSQL_PASSWORD = os.environ.get('RDS_MYSQL_PASSWORD', '') RDS_MYSQL_HOST = os.environ.get('RDS_MYSQL_HOST', None) RDS_MYSQL_DB = os.environ.get('RDS_MYSQL_DB', None) # Snowflake ------------------------------------------------------------------ SNOWFLAKE_ACCOUNT = os.environ.get('SNOWFLAKE_ACCOUNT', 'orchard') SNOWFLAKE_USER = os.environ.get('SNOWFLAKE_USER', '') SNOWFLAKE_ROLE = os.environ.get('SNOWFLAKE_ROLE', 'DEV_ENGINEERING') SNOWFLAKE_PASSWORD = os.environ.get('SNOWFLAKE_PASSWORD', '') SNOWFLAKE_WAREHOUSE = os.environ.get( 'SNOWFLAKE_WAREHOUSE', 'DEV_OWS_WAREHOUSE') SNOWFLAKE_DATABASE = os.environ.get('SNOWFLAKE_DATABASE', '') SNOWFLAKE_SCHEMA = os.environ.get('SNOWFLAKE_SCHEMA', '') SNOWFLAKE_KEY_PASSPHRASE = os.environ.get('SNOWFLAKE_KEY_PASSPHRASE', '') SNOWFLAKE_PRIVATE_KEY_PATH = os.environ.get('SNOWFLAKE_PRIVATE_KEY_PATH', '') # Defer private key loading until after interactive CLI prompts complete. # Initialize connect args empty; populated later via # load_snowflake_private_key(). SNOWFLAKE_CONNECT_ARGS: dict = {} def load_snowflake_private_key(force: bool = False) -> None: """Populate SNOWFLAKE_CONNECT_ARGS with private_key if passphrase present. Safe to call multiple times; subsequent calls are no-ops unless force=True. Reads updated environment variables to allow late injection via CLI. """ global SNOWFLAKE_CONNECT_ARGS global SNOWFLAKE_PRIVATE_KEY_PATH global SNOWFLAKE_KEY_PASSPHRASE if SNOWFLAKE_CONNECT_ARGS and not force: return passphrase = os.environ.get( 'SNOWFLAKE_KEY_PASSPHRASE', SNOWFLAKE_KEY_PASSPHRASE ) if not passphrase: return path = os.environ.get( 'SNOWFLAKE_PRIVATE_KEY_PATH', SNOWFLAKE_PRIVATE_KEY_PATH ) try: HOME = os.environ.get('HOME') or str( os.environ.get('HOMEDRIVE', '') + os.environ.get('HOMEPATH', '') ).replace('\\', '/') except Exception: # pragma: no cover HOME = '' if not path: path = f'{HOME}/.ssh/snowflake/rsa_key.p8' try: with open(path, 'rb') as key: p_key = serialization.load_pem_private_key( key.read(), password=passphrase.encode(), backend=default_backend() ) except FileNotFoundError: # Leave connect args empty; caller can detect and log later. return pkb = p_key.private_bytes( encoding=serialization.Encoding.DER, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() ) SNOWFLAKE_PRIVATE_KEY_PATH = path SNOWFLAKE_KEY_PASSPHRASE = passphrase SNOWFLAKE_CONNECT_ARGS = {'private_key': pkb} # AWS ------------------------------------------------------------------------ AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID', None) AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY', None) AWS_REGION = os.environ.get('AWS_REGION', 'us-east-1') # S3 ------------------------------------------------------------------------- S3_BUCKET = os.environ.get('S3_BUCKET', 'dev-orchdbucket') # S3_FOLDER_TEMPLATE = os.environ.get('S3_FOLDER_TEMPLATE', '') # Sentry --------------------------------------------------------------------- SENTRY = os.environ.get('SENTRY_DSN', None) SENTRY_TRACE_LEVEL = os.environ.get('SENTRY_TRACE_LEVEL', 1.0) # Files and Folders ---------------------------------------------------------- FILE_OUTPUT_PATH = os.environ.get('FILE_OUTPUT_PATH', 'tmp/output/{date}') # Enable Debug Logging ------------------------------------------------------- DEBUG_LOG = strtobool(str(os.environ.get('DEBUG_LOG', 'False'))) # Logger DSN (WIP) ----------------------------------------------------------- LOGGER_DSN = os.environ.get('LOGGER_DSN') or None LOGGER_NAME = os.environ.get('LOGGER_NAME') or None LOGGER_LEVEL = os.environ.get('LOGGER_LEVEL') or None # Log to Screen level CONSOLE_LOG_LEVEL = str(os.environ.get('CONSOLE_LOG_LEVEL', 'INFO')) # Logging Targets ------------------------------------------------------------ LOG_DIR = os.environ.get('LOG_DIR', str(os.getcwd() + '/logs')) MASTER_LOG = os.environ.get('MASTER_LOG', None) JSON_LOG = os.environ.get('JSON_LOG', None) CSV_LOG = os.environ.get('CSV_LOG', None) OTHER_LOG = os.environ.get('OTHER_LOG', None) # GraphQL -------------------------------------------------------------------- GRAPHQL_GATEWAY_URL = os.environ.get('GRAPHQL_GATEWAY_URL') OA_USER = os.environ.get('OA_USER') # Application Version APP_VERSION = os.environ.get('APP_VERSION', '1.0')