import logging import typing from decimal import Decimal from functools import wraps from time import time from analyst.libs.consts import * CLUSTER_ID_RE = re.compile('^\d+$') logger = logging.getLogger('cloud_insight') try: import uuid _use_uuid = True except ImportError: _use_uuid = False datetime_format = "%Y-%m-%d %H:%M:%S" date_format = "%Y-%m-%d" time_format = "%H:%M:%S" def set_datetime_format(fmt_string): datetime_format = fmt_string def set_date_format(fmt_string): date_format = fmt_string def set_time_format(fmt_string): time_format = fmt_string def more(obj): if isinstance(obj, Decimal): return str(obj) if isinstance(obj, datetime.datetime): return obj.strftime(datetime_format) if isinstance(obj, datetime.date): return obj.strftime(date_format) if isinstance(obj, datetime.time): return obj.strftime(time_format) if _use_uuid and isinstance(obj, uuid.UUID): return str(obj.db_value()) raise TypeError("%r is not JSON serializable" % obj) def timing(f): @wraps(f) def wrap(*args, **kw): ts = time() result = f(*args, **kw) te = time() logger.info('func:%r took: %2.4f sec' % \ (f.__name__, te - ts)) print('func:%r took: %2.4f sec' % \ (f.__name__, te - ts)) return result return wrap # get_infra_cr_namespace_prefix gets the prefix of namespace for infra Custom Resources. # For example, return 'nightly-ms' for dev environment. def get_infra_cr_namespace_prefix(env: str): prefix = env if env == Env.Dev: prefix = 'nightly-ms' return prefix def get_env_by_infra_cr_namespace(ns: str): if ns.startswith('nightly-ms-') or ns.startswith('dev-'): return Env.Dev elif ns.startswith('staging-'): return Env.Staging elif ns.startswith('prod-'): return Env.Prod else: return '' def get_member_name_from_pvc_name(pvc_name: str) -> str: result = MEMBER_NAME_IN_PVC_NAME_RE.match(pvc_name) if result: return result.groups()[0] return '' def set_member_name_from_pvc_name(resource: dict, pvc_name: str): member_name = get_member_name_from_pvc_name(pvc_name) if member_name: resource['member'] = member_name def get_component_from_pvc_name(pvc_name: str) -> str: result = COMPONENT_IN_PVC_NAME_RE.match(pvc_name) if result: return result.groups()[0] return '' def set_component_from_pvc_name(resource: dict, pvc_name: str): component = get_component_from_pvc_name(pvc_name) if component: set_if_empty(resource, 'component', component, extra_empty_values={'dbaas-control-plane-shoot', 'seed'}) def get_component_from_member_name(pvc_name: str) -> str: result = COMPONENT_IN_MEMBER_NAME_RE.match(pvc_name) if result: return result.groups()[0] return '' def set_component_from_member_name(resource: dict, member_name: str): component = get_component_from_member_name(member_name) if component: set_if_empty(resource, 'component', component, extra_empty_values={'shared', 'dbaas-control-plane-shoot'}) def get_cluster_id_from_tc_namespace(namespace: str) -> str: result = CLUSTER_ID_IN_TC_NS.match(namespace) if result: return result.groups()[0] elif namespace == TIDB_ADMIN_NS: return 'admin' else: return '' def set_cluster_id_from_tc_namespace(resource: dict, namespace: str): cluster_id = get_cluster_id_from_tc_namespace(namespace) if cluster_id: resource['cluster_id'] = cluster_id def set_if_empty(d: dict, key: str, value: str, empty_values: typing.Union[None, set] = None, extra_empty_values: typing.Union[None, set] = None): cur = d.get(key) if is_empty(cur, empty_values=empty_values, extra_empty_values=extra_empty_values): d[key] = value def is_empty(value: str, empty_values: typing.Union[None, set] = None, extra_empty_values: typing.Union[None, set] = None) -> bool: if empty_values is None: empty_values = {None, '', 'null'} if extra_empty_values is not None: empty_values.update(extra_empty_values) return value in empty_values def round_seconds(obj: datetime.datetime) -> datetime.datetime: if obj.microsecond >= 500_000: obj += datetime.timedelta(seconds=1) return obj.replace(microsecond=0)