def _read_config_files(paths): """ Read configuration data from INI-style file(s). Data loaded from the given files is aggregated into a nested 2-level Python mapping, where 1st-level keys are config section names (as read from the files), and corresponding items are again key/value mappings (configuration item name and value). :param paths: list of filesystem paths of files to read """ # read given config files configparser = SafeConfigParser() configparser.read(paths) # temporarily modify environment to allow both `${...}` and `%(...)s` # variable substitution in config values defaults = _make_defaults_dict() config = {} with environment(**defaults): for section in configparser.sections(): config[section] = {} for key in configparser.options(section): # `configparser.get()` performs the `%(...)s` substitutions value = configparser.get(section, key, vars=defaults) # `expandvars()` performs the `${...}` substitutions config[section][key] = expandvars(value) return config
def _run_elasticluster_cmd(argv): """ Run the `elasticluster` command with additional arguments. Return STDOUT, STDERR, and the process exit status. """ with temporary_dir() as tmpdir: with environment( HOME=os.getcwd(), PYTHONWARNINGS=( # as support for Py2 wanes, we must silence warnings that # Python 2.7 will no longer be supported, as they make the # tests fail unnecessarily (functionality is OK, we just get # some extra lines into STDERR). However, # `cryptography.utils.CryptographyDeprecationWarning` is a # subclass of `UserWarning` exactly because # `DeprecationWarnings` are ignored by default, so we need to # ignore all `UserWarnings` as well (cannot ignore a non-builtin # exception class via an environmental variable) 'ignore::DeprecationWarning,ignore::UserWarning' if sys.version_info < (3, 6) # display all warnings on Py3.6+ else ''), ) as env: proc = subprocess.Popen( ['elasticluster'] + argv, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, shell=False) stdout, stderr = proc.communicate() return stdout, stderr, proc.returncode
def _read_config_files(paths): """ Read configuration data from INI-style file(s). Data loaded from the given files is aggregated into a nested 2-level Python mapping, where 1st-level keys are config section names (as read from the files), and corresponding items are again key/value mappings (configuration item name and value). :param paths: list of filesystem paths of files to read """ # read given config files configparser = make_config_parser() # Preventing automatic lowercase of config keys # see: https://stackoverflow.com/questions/19359556/configparser-reads-capital-keys-and-make-them-lower-case configparser.optionxform = str configparser.read(paths) # temporarily modify environment to allow both `${...}` and `%(...)s` # variable substitution in config values defaults = _make_defaults_dict() config = {} with environment(**defaults): for section in configparser.sections(): config[section] = {} for key in configparser.options(section): # `configparser.get()` performs the `%(...)s` substitutions value = configparser.get(section, key, vars=defaults) # `expandvars()` performs the `${...}` substitutions config[section][key] = expandvars(value) return config
def _run_command(argv): """ Run the `elasticluster` command with additional arguments. Return STDOUT, STDERR, and the process exit status. """ with temporary_dir() as tmpdir: with environment(HOME=os.getcwd()) as env: proc = subprocess.Popen(['elasticluster'] + argv, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, shell=False) stdout, stderr = proc.communicate() return stdout, stderr, proc.returncode
def _run_command(argv): """ Run the `elasticluster` command with additional arguments. Return STDOUT, STDERR, and the process exit status. """ with temporary_dir() as tmpdir: with environment(HOME=os.getcwd()) as env: proc = subprocess.Popen( ['elasticluster'] + argv, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, shell=False) stdout, stderr = proc.communicate() return stdout, stderr, proc.returncode