diff --git a/chassis/config.py b/chassis/config.py new file mode 100644 index 0000000..cbddbc7 --- /dev/null +++ b/chassis/config.py @@ -0,0 +1,27 @@ +import os + +from chassis.consts import const + + +class Config: + """ + 基础配置 + """ + + # 先读 env 环境变量中的配置 + + # 指定加密KEY + SECRET_KEY = os.getenv('SECRET_KEY') + + # 指定数据库 + DEFAULT_DATABASE_URI = os.getenv('DEFAULT_DATABASE_URI') + READONLY_DATABASE_URI = os.getenv('READONLY_DATABASE_URI') + const.DB_CONFIG_ITEM = { + const.DEFAULT_DB_KEY: DEFAULT_DATABASE_URI, + const.READONLY_DB_KEY: READONLY_DATABASE_URI, + } + + STATSD_PREFIX = os.getenv('STATSD_PREFIX') + STATSD_HOST = os.getenv('STATSD_HOST') + STATSD_PORT = os.getenv('STATSD_PORT') + diff --git a/chassis/consts.py b/chassis/consts.py new file mode 100644 index 0000000..0abb517 --- /dev/null +++ b/chassis/consts.py @@ -0,0 +1,133 @@ +class ConstError(TypeError): + pass + + +class _const: + def __setattr__(self, name, value): + if name in self.__dict__: + raise ConstError("Can't rebind const (%s)" % name) + if not name.isupper(): + raise ConstError("Const must be upper.") + self.__dict__[name] = value + + +const = _const() + +const.DB_CONFIG_ITEM = 'databases' +const.DEFAULT_DB_KEY = 'default' +const.READONLY_DB_KEY = 'readonly' + +const.REDIS_CONFIG_ITEM = 'redises' +const.RD_HOST_KEY = 'host' +const.RD_PORT_KEY = 'port' +const.RD_DB_KEY = 'db' +const.RD_AUTH_KEY = 'auth' +const.RD_CHARSET_KEY = 'charset' +const.RD_DECODE_RESPONSES = 'decode_responses' +const.RD_PASSWORD_KEY = 'password' +const.DEFAULT_RD_KEY = 'default' + +const.MQ_CONFIG_ITEM = 'mqs' +const.MQ_ADDR = 'MQ_ADDR' +const.MQ_PORT = 'MQ_PORT' +const.MQ_VHOST = 'MQ_VHOST' +const.MQ_USER = 'MQ_USER' +const.MQ_PWD = 'MQ_PWD' +const.DEFAULT_MQ_KEY = 'default' +const.AGENT_MQ_KEY = 'agent' + +const.APP_NAME = 'app_name' +const.LOG_PATH = 'log_path' +const.LOG_BACKUP_COUNT = 'log_backup_count' +const.LOG_MAX_FILE_SIZE = 'log_max_filesize' + +const.REQUEST_START_SIGNAL = 'request_start' +const.REQUEST_FINISHED_SIGNAL = 'request_finished' + +const.NW_SALT = 'nw' +const.ALY_SALT = 'aly' +const.TX_SALT = 'tx' +const.SG_SALT = 'sg' +const.DEFAULT_SALT = 'default' +const.SALT_API = 'salt_api' +const.SALT_USER = 'salt_username' +const.SALT_PW = 'salt_password' +const.SALT_OUT = 'salt_timeout' + +const.NW_INCEPTION = 'nw' +const.ALY_INCEPTION = 'aly' +const.TX_INCEPTION = 'tx' +const.DEFAULT_INCEPTION = 'default' + +const.REGION = "cn-hangzhou" +const.PRODUCT_NAME = "Dysmsapi" +const.DOMAIN = "dysmsapi.aliyuncs.com" + +# app settings +const.APP_SETTINGS = 'APP_SETTINGS' +# all user info +const.USERS_INFO = 'USERS_INFO' +# API GW +const.WEBSITE_API_GW_URL = 'api_gw' +const.API_AUTH_KEY = 'settings_auth_key' +const.EMAILLOGIN_DOMAIN = 'EMAILLOGIN_DOMAIN' +const.EMAILLOGIN_SERVER = 'EMAILLOGIN_SERVER' +# e-mail +const.EMAIL_SUBJECT_PREFIX = "EMAIL_SUBJECT_PREFIX" +const.EMAIL_HOST = "EMAIL_HOST" +const.EMAIL_PORT = "EMAIL_PORT" +const.EMAIL_HOST_USER = "EMAIL_HOST_USER" +const.EMAIL_HOST_PASSWORD = "EMAIL_HOST_PASSWORD" +const.EMAIL_USE_SSL = "EMAIL_USE_SSL" +const.EMAIL_USE_TLS = "EMAIL_USE_TLS" + +# 短信配置 +const.SMS_REGION = "SMS_REGION" +const.SMS_PRODUCT_NAME = "SMS_PRODUCT_NAME" +const.SMS_DOMAIN = "SMS_DOMAIN" + +const.SMS_ACCESS_KEY_ID = 'SMS_ACCESS_KEY_ID' +const.SMS_ACCESS_KEY_SECRET = 'SMS_ACCESS_KEY_SECRET' +# 钉钉 +const.DING_TALK_WEBHOOK = "DING_TALK_WEBHOOK" +# 存储 +const.STORAGE_REGION = "STORAGE_REGION" +const.STORAGE_NAME = "STORAGE_NAME" +const.STORAGE_PATH = "STORAGE_PATH" +const.STORAGE_KEY_ID = "STORAGE_KEY_ID" +const.STORAGE_KEY_SECRET = "STORAGE_KEY_SECRET" + +# LDAP +const.LDAP_SERVER_HOST = "LDAP_SERVER_HOST" +const.LDAP_SERVER_PORT = "LDAP_SERVER_PORT" +const.LDAP_ADMIN_DN = "LDAP_ADMIN_DN" +const.LDAP_ADMIN_PASSWORD = "LDAP_ADMIN_PASSWORD" +const.LDAP_SEARCH_BASE = "LDAP_SEARCH_BASE" +const.LDAP_SEARCH_FILTER = "LDAP_SEARCH_FILTER" +const.LDAP_ATTRIBUTES = "LDAP_ATTRIBUTES" +const.LDAP_USE_SSL = "LDAP_USE_SSL" +const.LDAP_ENABLE = "LDAP_ENABLE" + +# token 超时时间 +const.TOKEN_EXP_TIME = "TOKEN_EXP_TIME" + +# 全局 二次认证 +const.MFA_GLOBAL = 'MFA_GLOBAL' + +# 任务状态 +const.STATE_NEW = '0' +const.STATE_WAIT = '1' +const.STATE_RUNNING = '2' +const.STATE_SUCCESS = '3' +const.STATE_ERROR = '4' +const.STATE_MANUAL = '5' +const.STATE_BREAK = '6' +const.STATE_TIMING = '7' +const.STATE_UNKNOWN = '8' +const.STATE_FAIL = '9' +const.STATE_IGNORE = '10' ## 忽略 +const.EXEC_TIMEOUT = 1800 + +# 节点地址 +const.NODE_ADDRESS = 'NODE_ADDRESS' +const.EXEC_NODE_MAP_KEY = 'EXEC_NODE_MAP_KEY' diff --git a/chassis/db_context.py b/chassis/db_context.py new file mode 100644 index 0000000..b2be323 --- /dev/null +++ b/chassis/db_context.py @@ -0,0 +1,61 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +from chassis.config import Config +from chassis.consts import const + +engines = {} + + +def init_engine(config): + if config: + databases = getattr(config, const.DB_CONFIG_ITEM) + else: + databases = getattr(Config, const.DB_CONFIG_ITEM) + for db_key, db_url in databases.items(): + engine = create_engine(db_url, + logging_name=db_key, poolclass=None, pool_size=5, max_overflow=20, pool_recycle=3600, + pool_pre_ping=True) + engines[db_key] = engine + + +class DBContext(object): + def __init__(self, rw='r', db_key=None, need_commit=False, **settings): + self.__db_key = db_key + if not self.__db_key: + if rw == 'w': + self.__db_key = const.DEFAULT_DB_KEY + elif rw == 'r': + self.__db_key = const.READONLY_DB_KEY + engine = self.__get_db_engine(self.__db_key, **settings) + self.__engine = engine + self.need_commit = need_commit + + # @property + # def db_key(self): + # return self.__db_key + + @staticmethod + def __get_db_engine(db_key, **settings): + if len(engines) == 0: + init_engine(**settings) + return engines[db_key] + + @property + def session(self): + return self.__session + + def __enter__(self): + self.__session = sessionmaker(bind=self.__engine)() + return self.__session + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.need_commit: + if exc_type: + self.__session.rollback() + else: + self.__session.commit() + self.__session.close() + + def get_session(self): + return self.__session \ No newline at end of file