Skip to content

Commit

Permalink
Add expansion feature
Browse files Browse the repository at this point in the history
Read dotenv file and expand based on env and system env
  • Loading branch information
damoncro committed Nov 30, 2021
1 parent a127111 commit ee589d2
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
21 changes: 21 additions & 0 deletions pystarport/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
import tomlkit
import yaml
from dateutil.parser import isoparse
from dotenv import dotenv_values, load_dotenv
from supervisor import xmlrpc
from supervisor.compat import xmlrpclib

from . import ports
from .app import CHAIN, IMAGE, SUPERVISOR_CONFIG_FILE
from .cosmoscli import ChainCommand, CosmosCLI, ModuleAccount, module_address
from .expansion import expand_posix_vars
from .ledger import ZEMU_BUTTON_PORT, ZEMU_HOST
from .utils import format_doc_string, interact, write_ini

Expand Down Expand Up @@ -906,6 +908,20 @@ def init_cluster(
):
config = yaml.safe_load(open(config_path))

if "dotenv" in config:
dotenv = config.pop("dotenv", {})
if not isinstance(dotenv, str):
raise ValueError(f"Invalid value passed to dotenv: {dotenv}")
config_vars = load_system_envvars()
env_path = Path(config_path).parent.joinpath(dotenv)
if not env_path.is_file():
raise ValueError(
f"Dotenv specified in config but not found at path: {env_path}"
)
config_vars.update(dotenv_values(dotenv_path=env_path)) # type: ignore
load_dotenv(dotenv_path=env_path)
config = expand_posix_vars(config, config_vars)

relayer_config = config.pop("relayer", {})
for chain_id, cfg in config.items():
cfg["path"] = str(config_path)
Expand Down Expand Up @@ -1101,3 +1117,8 @@ def format_value(v, ctx):
supervisord.wait()
t.stop()
t.join()


def load_system_envvars():
config_vars = dict(os.environ)
return config_vars
58 changes: 58 additions & 0 deletions pystarport/expansion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import re
from typing import Any, Mapping, Optional, Text

from dotenv.variables import parse_variables


def expand_posix_vars(obj: Any, variables: Mapping[Text, Optional[Any]]) -> Any:
"""expand_posix_vars recursively expands POSIX values in an object.
Args:
obj (any): object in which to interpolate variables.
variables (dict): dictionary that maps variable names to their value
"""
if isinstance(obj, (dict,)):
for key, val in obj.items():
obj[key] = expand_posix_vars(val, variables)
elif isinstance(obj, (list,)):
for index in range(len(obj)):
obj[index] = expand_posix_vars(obj[index], variables)
elif isinstance(obj, (str,)):
obj = _str_to_python_value(_expand(obj, variables))
return obj


def _expand(value, variables={}):
"""_expand does POSIX-style variable expansion
This is adapted from python-dotenv, specifically here:
https://github.com/theskumar/python-dotenv/commit/17dba65244c1d4d10f591fe37c924bd2c6fd1cfc
We need this layer here so we can explicitly pass in variables;
python-dotenv assumes you want to use os.environ.
"""

if not isinstance(value, (str,)):
return value
atoms = parse_variables(value)
return "".join([str(atom.resolve(variables)) for atom in atoms])


INT_REGEX = re.compile(r"^[-+]?[0-9]+$")


def _str_to_python_value(val):
"""_str_to_python_value infers the data type from a string.
This could eventually use PyYAML's parsing logic.
"""
if not isinstance(val, (str,)):
return val
elif val == "true" or val == "True" or val == "on":
return True
elif val == "false" or val == "False" or val == "off":
return False
# elif INT_REGEX.match(val):
# return int(val)
return val

0 comments on commit ee589d2

Please sign in to comment.