# Path: slo_generator/utils.py
#     GCS_ENABLED = True
#     GCS_ENABLED = False
# LOGGER = logging.getLogger(__name__)
# def load_configs(path, ctx=os.environ, kind=None):
# def load_config(path, ctx=os.environ, kind=None):
# def parse_config(path=None, content=None, ctx=os.environ):
#     def replace_env_vars(content, ctx):
# def setup_logging():
# def get_human_time(timestamp, timezone=None):
# def get_exporters(config, spec):
# def get_backend(config, spec):
# def get_error_budget_policy(config, spec):
# def get_backend_cls(backend):
# def get_exporter_cls(exporter):
# def import_cls(cls_name, expected_type):
# def import_dynamic(package, name, prefix="class"):
# def capitalize(word):
# def snake_to_caml(word):
# def caml_to_snake(word):
# def dict_snake_to_caml(data):
# def apply_func_dict(data, func):
# def str2bool(string):
# def download_gcs_file(url):
# def decode_gcs_url(url):
# def get_files(source, extensions=['yaml', 'yml', 'json']):
# def get_target_path(source_dir, target_dir, relative_path, mkdir=True):
# def fmt_traceback(exc):
# 
# Path: slo_generator/constants.py
# METRIC_LABELS_COMPAT = {
#     'goal': 'slo_target',
#     'description': 'slo_description',
#     'error_budget_burn_rate_threshold': 'alerting_burn_rate_threshold'
# }
# 
# METRIC_METADATA_LABELS_TOP_COMPAT = ['service_name', 'feature_name', 'slo_name']
# 
# PROVIDERS_COMPAT = {
#     'Stackdriver': 'CloudMonitoring',
#     'StackdriverServiceMonitoring': 'CloudServiceMonitoring'
# }
# 
# CONFIG_SCHEMA = {
#     'backends': {},
#     'exporters': {},
#     'error_budget_policies': {},
# }
# 
# SLO_CONFIG_SCHEMA = {
#     'apiVersion': '',
#     'kind': '',
#     'metadata': {},
#     'spec': {
#         'description': '',
#         'backend': '',
#         'method': '',
#         'exporters': [],
#         'service_level_indicator': {}
#     }
# }
# 
# GREEN = Colors.OKGREEN
# 
# RED = Colors.FAIL
# 
# BOLD = '\033[1m'
# 
# WARNING = '\033[93m'
# 
# ENDC = '\033[0m'
# 
# SUCCESS = '✅'
# 
# FAIL = '\033[91m'
# 
# RIGHT_ARROW = '➞'


import copy
import itertools
import pprint
import random
import string
import sys
import click
from collections import OrderedDict
from pathlib import Path
from ruamel import yaml
from slo_generator import utils
from slo_generator.constants import (METRIC_LABELS_COMPAT,
                                     METRIC_METADATA_LABELS_TOP_COMPAT,
                                     PROVIDERS_COMPAT, CONFIG_SCHEMA,
                                     SLO_CONFIG_SCHEMA, GREEN, RED, BOLD,
                                     WARNING, ENDC, SUCCESS, FAIL, RIGHT_ARROW)
    """
    shared_obj = shared_config[section]
    key = key or new_obj.pop('class', None)
    if not key:
        raise ValueError("Object key is undefined.")
    if '.' not in key:
        key = utils.caml_to_snake(PROVIDERS_COMPAT.get(key, key))

    existing_obj = {
        k: v
        for k, v in shared_obj.items()
        if k.startswith(key.split('/')[0]) and str(v) == str(dict(new_obj))
    }
    if existing_obj:
        key = next(iter(existing_obj))
        # click.secho(f'Found existing {section} {key}')
    else:
        if key in shared_obj.keys():  # key conflicts
            if quiet:
                key += '/' + get_random_suffix()
            else:
                name = section.rstrip('s')
                cfg = pprint.pformat({key: dict(new_obj)})
                valid = False
                while not valid:
                    click.secho(
                        f'\nNew {name} found with the following config:\n{cfg}',
                        fg='cyan',
                        blink=True)
                    user_input = click.prompt(

# Path: slo_generator/utils.py
#     GCS_ENABLED = True
#     GCS_ENABLED = False
# LOGGER = logging.getLogger(__name__)
# def load_configs(path, ctx=os.environ, kind=None):
# def load_config(path, ctx=os.environ, kind=None):
# def parse_config(path=None, content=None, ctx=os.environ):
#     def replace_env_vars(content, ctx):
# def setup_logging():
# def get_human_time(timestamp, timezone=None):
# def get_exporters(config, spec):
# def get_backend(config, spec):
# def get_error_budget_policy(config, spec):
# def get_backend_cls(backend):
# def get_exporter_cls(exporter):
# def import_cls(cls_name, expected_type):
# def import_dynamic(package, name, prefix="class"):
# def capitalize(word):
# def snake_to_caml(word):
# def caml_to_snake(word):
# def dict_snake_to_caml(data):
# def apply_func_dict(data, func):
# def str2bool(string):
# def download_gcs_file(url):
# def decode_gcs_url(url):
# def get_files(source, extensions=['yaml', 'yml', 'json']):
# def get_target_path(source_dir, target_dir, relative_path, mkdir=True):
# def fmt_traceback(exc):
# 
# Path: slo_generator/constants.py
# METRIC_LABELS_COMPAT = {
#     'goal': 'slo_target',
#     'description': 'slo_description',
#     'error_budget_burn_rate_threshold': 'alerting_burn_rate_threshold'
# }
# 
# METRIC_METADATA_LABELS_TOP_COMPAT = ['service_name', 'feature_name', 'slo_name']
# 
# PROVIDERS_COMPAT = {
#     'Stackdriver': 'CloudMonitoring',
#     'StackdriverServiceMonitoring': 'CloudServiceMonitoring'
# }
# 
# CONFIG_SCHEMA = {
#     'backends': {},
#     'exporters': {},
#     'error_budget_policies': {},
# }
# 
# SLO_CONFIG_SCHEMA = {
#     'apiVersion': '',
#     'kind': '',
#     'metadata': {},
#     'spec': {
#         'description': '',
#         'backend': '',
#         'method': '',
#         'exporters': [],
#         'service_level_indicator': {}
#     }
# }
# 
# GREEN = Colors.OKGREEN
# 
# RED = Colors.FAIL
# 
# BOLD = '\033[1m'
# 
# WARNING = '\033[93m'
# 
# ENDC = '\033[0m'
# 
# SUCCESS = '✅'
# 
# FAIL = '\033[91m'
# 
# RIGHT_ARROW = '➞'


# Path: slo_generator/migrations/migrator.py
import copy
import itertools
import pprint
import random
import string
import sys
import click
from collections import OrderedDict
from pathlib import Path
from ruamel import yaml
from slo_generator import utils
from slo_generator.constants import (METRIC_LABELS_COMPAT,
                                     METRIC_METADATA_LABELS_TOP_COMPAT,
                                     PROVIDERS_COMPAT, CONFIG_SCHEMA,
                                     SLO_CONFIG_SCHEMA, GREEN, RED, BOLD,
                                     WARNING, ENDC, SUCCESS, FAIL, RIGHT_ARROW)

    """
    shared_obj = shared_config[section]
    key = key or new_obj.pop('class', None)
    if not key:
        raise ValueError("Object key is undefined.")
    if '.' not in key:
        key = utils.caml_to_snake(PROVIDERS_COMPAT.get(key, key))

    existing_obj = {
        k: v
        for k, v in shared_obj.items()
        if k.startswith(key.split('/')[0]) and str(v) == str(dict(new_obj))
    }
    if existing_obj:
        key = next(iter(existing_obj))
        # click.secho(f'Found existing {section} {key}')
    else:
        if key in shared_obj.keys():  # key conflicts
            if quiet:
                key += '/' + get_random_suffix()
            else:
                name = section.rstrip('s')
                cfg = pprint.pformat({key: dict(new_obj)})
                valid = False
                while not valid:
                    click.secho(
                        f'\nNew {name} found with the following config:\n{cfg}',
                        fg='cyan',
                        blink=True)
                    user_input = click.prompt(

                        f'\n{RED}{BOLD}Please give this {name} a name{ENDC}',