def load(self, filename=None, key=None, silent=True): """ Reads and loads in to `self.obj` a single key or all keys from source :param filename: Optional filename to load :param key: if provided load a single key :param silent: if load erros should be silenced """ filename = filename or self.obj.get(self.identifier.upper()) if not filename: return if not isinstance(filename, (list, tuple)): split_files = ensure_a_list(filename) if all([f.endswith(self.extensions) for f in split_files]): # noqa files = split_files # it is a ['file.ext', ...] else: # it is a single config as string files = [filename] else: # it is already a list/tuple files = filename self.obj._loaded_files.extend(files) env_list = build_env_list(self.obj, self.env) # load all envs self._read(files, env_list, silent, key)
def _load_all_envs(self, source_data, silent=True, key=None): """Load configs from files separating by each environment""" for file_data in source_data.values(): # env name is checked in lower file_data = {k.lower(): value for k, value in file_data.items()} # is there a `dynaconf_merge` on top level of file? file_merge = file_data.get("dynaconf_merge") for env in build_env_list(self.obj, self.env): env = env.lower() # lower for better comparison data = {} try: data = file_data[env] or {} except KeyError: if silent: continue raise if not data: continue if env != self.obj.get("DEFAULT_ENV_FOR_DYNACONF").lower(): identifier = f"{self.identifier}_{env}" else: identifier = self.identifier self._set_data_to_obj(data, identifier, file_merge, key)
def load(obj, env=None, silent=True, key=None): """Reads and loads in to "settings" a single key or all keys from redis :param obj: the settings instance :param env: settings env default='DYNACONF' :param silent: if errors should raise :param key: if defined load a single key, else load all in env :return: None """ redis = StrictRedis(**obj.get("REDIS_FOR_DYNACONF")) prefix = obj.get("ENVVAR_PREFIX_FOR_DYNACONF") # prefix is added to env_list to keep backwards compatibility env_list = [prefix] + build_env_list(obj, env or obj.current_env) for env_name in env_list: holder = f"{prefix.upper()}_{env_name.upper()}" try: if key: value = redis.hget(holder.upper(), key) if value: parsed_value = parse_conf_data(value, tomlfy=True, box_settings=obj) if parsed_value: obj.set(key, parsed_value) else: data = { key: parse_conf_data(value, tomlfy=True, box_settings=obj) for key, value in redis.hgetall(holder.upper()).items() } if data: obj.update(data, loader_identifier=IDENTIFIER) except Exception as e: if silent: return False raise
def _load_all_envs(self, source_data, silent=True, key=None): """Load configs from files separating by each environment""" for file_data in source_data.values(): # env name is checked in lower file_data = {k.lower(): value for k, value in file_data.items()} # is there a `dynaconf_merge` on top level of file? file_merge = file_data.get("dynaconf_merge") # is there a flag disabling dotted lookup on file? file_dotted_lookup = file_data.get("dynaconf_dotted_lookup") for env in build_env_list(self.obj, self.env): env = env.lower() # lower for better comparison try: data = file_data[env] or {} except KeyError: if silent: continue raise if not data: continue self._set_data_to_obj( data, f"{self.identifier}_{env}", file_merge, key, file_dotted_lookup=file_dotted_lookup, )
def test_env_list(): class Obj(dict): @property def current_env(self): return "other" assert build_env_list(Obj(), env="OTHER") == [ "default", "dynaconf", "other", "global", ]
def load(obj, env=None, silent=None, key=None): """Reads and loads in to "settings" a single key or all keys from vault :param obj: the settings instance :param env: settings env default='DYNACONF' :param silent: if errors should raise :param key: if defined load a single key, else load all in env :return: None """ client = get_client(obj) try: dirs = client.secrets.kv.list_secrets( path=obj.VAULT_PATH_FOR_DYNACONF, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF, )["data"]["keys"] except InvalidPath: # The given path is not a directory dirs = [] env_list = build_env_list(obj, env) + dirs for env in env_list: path = "/".join([obj.VAULT_PATH_FOR_DYNACONF, env]) try: if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2: data = client.secrets.kv.v2.read_secret_version( path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF) else: data = client.secrets.kv.read_secret( "data/" + path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF, ) except InvalidPath: # If the path doesn't exist, ignore it and set data to None data = None if data: # There seems to be a data dict within a data dict, # extract the inner data data = data.get("data", {}).get("data", {}) try: if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2 and data: data = data.get("data", {}) if data and key: value = parse_conf_data(data.get(key), tomlfy=True, box_settings=obj) if value: obj.set(key, value) elif data: obj.update(data, loader_identifier=IDENTIFIER, tomlfy=True) except Exception: if silent: return False raise
def _load_all_envs(self, source_data, silent=True, key=None): """Load configs from files separating by each environment""" for source_file, file_data in source_data.items(): # env name is checked in lower file_data = {k.lower(): value for k, value in file_data.items()} # is there a `dynaconf_merge` on top level of file? file_merge = file_data.get("dynaconf_merge") # all lower case for comparison base_envs = [ # DYNACONF or MYPROGRAM (self.obj.get("ENVVAR_PREFIX_FOR_DYNACONF") or "").lower(), # DEFAULT self.obj.get("DEFAULT_ENV_FOR_DYNACONF").lower(), # default active env unless ENV_FOR_DYNACONF is changed "development", # backwards compatibility for global "dynaconf", # global that rules all "global", ] for env in build_env_list(self.obj, self.env): env = env.lower() # lower for better comparison data = {} try: data = file_data[env] or {} except KeyError: if env not in base_envs: message = ( f"{self.identifier}_loader: {env} env not" f"defined in {source_file}" ) if silent: warnings.warn(message) else: raise KeyError(message) continue if env != self.obj.get("DEFAULT_ENV_FOR_DYNACONF").lower(): identifier = f"{self.identifier}_{env}" else: identifier = self.identifier self._set_data_to_obj( data, identifier, source_file, file_merge, key, env )
def load(obj, env=None, silent=None, key=None): """Reads and loads in to "settings" a single key or all keys from vault :param obj: the settings instance :param env: settings env default='DYNACONF' :param silent: if errors should raise :param key: if defined load a single key, else load all in env :return: None """ client = get_client(obj) env_list = build_env_list(obj, env) for env in env_list: path = "/".join([obj.VAULT_PATH_FOR_DYNACONF, env]) try: data = client.secrets.kv.read_secret_version(path) except InvalidPath: # If the path doesn't exist, ignore it and set data to None data = None if data: # There seems to be a data dict within a data dict, # extract the inner data data = data.get("data", {}).get("data", {}) try: if data and key: value = parse_conf_data(data.get(key), tomlfy=True) if value: obj.logger.debug( "vault_loader: loading by key: %s:%s (%s:%s)", key, "****", IDENTIFIER, path, ) obj.set(key, value) elif data: obj.logger.debug( "vault_loader: loading: %s (%s:%s)", list(data.keys()), IDENTIFIER, path, ) obj.update(data, loader_identifier=IDENTIFIER, tomlfy=True) except Exception as e: if silent: if hasattr(obj, "logger"): obj.logger.error(str(e)) return False raise
def load(obj, env=None, silent=None, key=None): """Reads and loads in to "settings" a single key or all keys from vault :param obj: the settings instance :param env: settings env default='DYNACONF' :param silent: if errors should raise :param key: if defined load a single key, else load all in env :return: None """ client = get_client(obj) try: if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2: dirs = client.secrets.kv.v2.list_secrets( path=obj.VAULT_PATH_FOR_DYNACONF, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF, )["data"]["keys"] else: dirs = client.secrets.kv.v1.list_secrets( path=obj.VAULT_PATH_FOR_DYNACONF, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF, )["data"]["keys"] except InvalidPath: # The given path is not a directory dirs = [] # First look for secrets into environments less store if not obj.ENVIRONMENTS_FOR_DYNACONF: # By adding '', dynaconf will now read secrets from environments-less # store which are not written by `dynaconf write` to Vault store env_list = [obj.MAIN_ENV_FOR_DYNACONF.lower(), ""] # Finally, look for secret into all the environments else: env_list = dirs + build_env_list(obj, env) for env in env_list: path = "/".join([obj.VAULT_PATH_FOR_DYNACONF, env]) try: if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2: data = client.secrets.kv.v2.read_secret_version( path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF) else: data = client.secrets.kv.read_secret( "data/" + path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF, ) except InvalidPath: # If the path doesn't exist, ignore it and set data to None data = None if data: # There seems to be a data dict within a data dict, # extract the inner data data = data.get("data", {}).get("data", {}) try: if (obj.VAULT_KV_VERSION_FOR_DYNACONF == 2 and obj.ENVIRONMENTS_FOR_DYNACONF and data): data = data.get("data", {}) if data and key: value = parse_conf_data(data.get(key), tomlfy=True, box_settings=obj) if value: obj.set(key, value) elif data: obj.update(data, loader_identifier=IDENTIFIER, tomlfy=True) except Exception: if silent: return False raise