forked from ungleich-public/cdist
		
	
					parent
					
						
							
								4b2f23db62
							
						
					
				
			
			
				commit
				
					
						bdee7273af
					
				
			
		
					 11 changed files with 1800 additions and 136 deletions
				
			
		|  | @ -1,9 +1,9 @@ | |||
| import argparse | ||||
| import cdist | ||||
| import multiprocessing | ||||
| import os | ||||
| import logging | ||||
| import collections | ||||
| import cdist.configuration | ||||
| 
 | ||||
| 
 | ||||
| # set of beta sub-commands | ||||
|  | @ -115,7 +115,7 @@ def get_parsers(): | |||
|            '-b', '--beta', | ||||
|            help=('Enable beta functionality. '), | ||||
|            action='store_true', dest='beta', | ||||
|            default='CDIST_BETA' in os.environ) | ||||
|            default=False) | ||||
| 
 | ||||
|     # Main subcommand parser | ||||
|     parser['main'] = argparse.ArgumentParser( | ||||
|  | @ -136,12 +136,18 @@ def get_parsers(): | |||
|            '-I', '--inventory', | ||||
|            help=('Use specified custom inventory directory. ' | ||||
|                  'Inventory directory is set up by the following rules: ' | ||||
|                  'if this argument is set then specified directory is used, ' | ||||
|                  'if CDIST_INVENTORY_DIR env var is set then its value is ' | ||||
|                  'used, if HOME env var is set then ~/.cdist/inventory is ' | ||||
|                  'if cdist configuration resolves this value then specified ' | ||||
|                  'directory is used, ' | ||||
|                  'if HOME env var is set then ~/.cdist/inventory is ' | ||||
|                  'used, otherwise distribution inventory directory is used.'), | ||||
|            dest="inventory_dir", required=False) | ||||
| 
 | ||||
|     parser['common'] = argparse.ArgumentParser(add_help=False) | ||||
|     parser['common'].add_argument( | ||||
|            '-g', '--config-file', | ||||
|            help=('Use specified custom configuration file.'), | ||||
|            dest="config_file", required=False) | ||||
| 
 | ||||
|     # Config | ||||
|     parser['config_main'] = argparse.ArgumentParser(add_help=False) | ||||
|     parser['config_main'].add_argument( | ||||
|  | @ -149,7 +155,7 @@ def get_parsers(): | |||
|             help=('Specify custom cache path pattern. If ' | ||||
|                   'it is not set then default hostdir is used.'), | ||||
|             dest='cache_path_pattern', | ||||
|             default=os.environ.get('CDIST_CACHE_PATH_PATTERN')) | ||||
|             default=None) | ||||
|     parser['config_main'].add_argument( | ||||
|             '-c', '--conf-dir', | ||||
|             help=('Add configuration directory (can be repeated, ' | ||||
|  | @ -195,13 +201,13 @@ def get_parsers(): | |||
|            '--remote-copy', | ||||
|            help='Command to use for remote copy (should behave like scp).', | ||||
|            action='store', dest='remote_copy', | ||||
|            default=os.environ.get('CDIST_REMOTE_COPY')) | ||||
|            default=None) | ||||
|     parser['config_main'].add_argument( | ||||
|            '--remote-exec', | ||||
|            help=('Command to use for remote execution ' | ||||
|                  '(should behave like ssh).'), | ||||
|            action='store', dest='remote_exec', | ||||
|            default=os.environ.get('CDIST_REMOTE_EXEC')) | ||||
|            default=None) | ||||
| 
 | ||||
|     # Config | ||||
|     parser['config_args'] = argparse.ArgumentParser(add_help=False) | ||||
|  | @ -243,6 +249,7 @@ def get_parsers(): | |||
|              dest='tag', required=False, action="store_true", default=False) | ||||
|     parser['config'] = parser['sub'].add_parser( | ||||
|             'config', parents=[parser['loglevel'], parser['beta'], | ||||
|                                parser['common'], | ||||
|                                parser['config_main'], | ||||
|                                parser['inventory_common'], | ||||
|                                parser['config_args']]) | ||||
|  | @ -256,12 +263,14 @@ def get_parsers(): | |||
|     # Inventory | ||||
|     parser['inventory'] = parser['sub'].add_parser( | ||||
|            'inventory', parents=[parser['loglevel'], parser['beta'], | ||||
|                                  parser['common'], | ||||
|                                  parser['inventory_common']]) | ||||
|     parser['invsub'] = parser['inventory'].add_subparsers( | ||||
|             title="Inventory commands", dest="subcommand") | ||||
| 
 | ||||
|     parser['add-host'] = parser['invsub'].add_parser( | ||||
|             'add-host', parents=[parser['loglevel'], parser['beta'], | ||||
|                                  parser['common'], | ||||
|                                  parser['inventory_common']]) | ||||
|     parser['add-host'].add_argument( | ||||
|             'host', nargs='*', help='Host(s) to add.') | ||||
|  | @ -275,6 +284,7 @@ def get_parsers(): | |||
| 
 | ||||
|     parser['add-tag'] = parser['invsub'].add_parser( | ||||
|             'add-tag', parents=[parser['loglevel'], parser['beta'], | ||||
|                                 parser['common'], | ||||
|                                 parser['inventory_common']]) | ||||
|     parser['add-tag'].add_argument( | ||||
|            'host', nargs='*', | ||||
|  | @ -305,6 +315,7 @@ def get_parsers(): | |||
| 
 | ||||
|     parser['del-host'] = parser['invsub'].add_parser( | ||||
|             'del-host', parents=[parser['loglevel'], parser['beta'], | ||||
|                                  parser['common'], | ||||
|                                  parser['inventory_common']]) | ||||
|     parser['del-host'].add_argument( | ||||
|             'host', nargs='*', help='Host(s) to delete.') | ||||
|  | @ -321,6 +332,7 @@ def get_parsers(): | |||
| 
 | ||||
|     parser['del-tag'] = parser['invsub'].add_parser( | ||||
|             'del-tag', parents=[parser['loglevel'], parser['beta'], | ||||
|                                 parser['common'], | ||||
|                                 parser['inventory_common']]) | ||||
|     parser['del-tag'].add_argument( | ||||
|             'host', nargs='*', | ||||
|  | @ -355,6 +367,7 @@ def get_parsers(): | |||
| 
 | ||||
|     parser['list'] = parser['invsub'].add_parser( | ||||
|             'list', parents=[parser['loglevel'], parser['beta'], | ||||
|                              parser['common'], | ||||
|                              parser['inventory_common']]) | ||||
|     parser['list'].add_argument( | ||||
|             'host', nargs='*', help='Host(s) to list.') | ||||
|  | @ -401,3 +414,23 @@ def handle_loglevel(args): | |||
|         args.verbose = _verbosity_level_off | ||||
| 
 | ||||
|     logging.root.setLevel(_verbosity_level[args.verbose]) | ||||
| 
 | ||||
| 
 | ||||
| def parse_and_configure(argv): | ||||
|     parser = get_parsers() | ||||
|     parser_args = parser['main'].parse_args(argv) | ||||
|     cfg = cdist.configuration.Configuration(parser_args) | ||||
|     args = cfg.get_args() | ||||
|     # Loglevels are handled globally in here | ||||
|     handle_loglevel(args) | ||||
| 
 | ||||
|     log = logging.getLogger("cdist") | ||||
| 
 | ||||
|     log.verbose("version %s" % cdist.VERSION) | ||||
|     log.trace('command line args: {}'.format(cfg.command_line_args)) | ||||
|     log.trace('configuration: {}'.format(cfg.get_config())) | ||||
|     log.trace('configured args: {}'.format(args)) | ||||
| 
 | ||||
|     check_beta(vars(args)) | ||||
| 
 | ||||
|     return parser, cfg | ||||
|  |  | |||
|  | @ -31,15 +31,12 @@ import multiprocessing | |||
| from cdist.mputil import mp_pool_run, mp_sig_handler | ||||
| import atexit | ||||
| import shutil | ||||
| 
 | ||||
| import cdist | ||||
| import cdist.hostsource | ||||
| 
 | ||||
| import cdist.exec.local | ||||
| import cdist.exec.remote | ||||
| 
 | ||||
| import cdist.util.ipaddr as ipaddr | ||||
| 
 | ||||
| import cdist.configuration | ||||
| from cdist import core, inventory | ||||
| from cdist.util.remoteutil import inspect_ssh_mux_opts | ||||
| 
 | ||||
|  | @ -162,8 +159,11 @@ class Config(object): | |||
| 
 | ||||
|         hostcnt = 0 | ||||
| 
 | ||||
|         cfg = cdist.configuration.Configuration(args) | ||||
|         configuration = cfg.get_config(section='GLOBAL') | ||||
| 
 | ||||
|         if args.tag or args.all_tagged_hosts: | ||||
|             inventory.determine_default_inventory_dir(args) | ||||
|             inventory.determine_default_inventory_dir(args, configuration) | ||||
|             if args.all_tagged_hosts: | ||||
|                 inv_list = inventory.InventoryList( | ||||
|                     hosts=None, istag=True, hostfile=None, | ||||
|  | @ -191,7 +191,7 @@ class Config(object): | |||
|             else: | ||||
|                 # if configuring by host then check inventory for tags | ||||
|                 host = entry | ||||
|                 inventory.determine_default_inventory_dir(args) | ||||
|                 inventory.determine_default_inventory_dir(args, configuration) | ||||
|                 inv_list = inventory.InventoryList( | ||||
|                     hosts=(host,), db_basedir=args.inventory_dir) | ||||
|                 inv = tuple(inv_list.entries()) | ||||
|  | @ -208,14 +208,16 @@ class Config(object): | |||
| 
 | ||||
|             hostcnt += 1 | ||||
|             if args.parallel: | ||||
|                 pargs = (host, host_tags, host_base_path, hostdir, args, True) | ||||
|                 pargs = (host, host_tags, host_base_path, hostdir, args, True, | ||||
|                          configuration) | ||||
|                 log.trace(("Args for multiprocessing operation " | ||||
|                            "for host {}: {}".format(host, pargs))) | ||||
|                 process_args.append(pargs) | ||||
|             else: | ||||
|                 try: | ||||
|                     cls.onehost(host, host_tags, host_base_path, hostdir, | ||||
|                                 args, parallel=False) | ||||
|                                 args, parallel=False, | ||||
|                                 configuration=configuration) | ||||
|                 except cdist.Error as e: | ||||
|                     failed_hosts.append(host) | ||||
|         if args.parallel and len(process_args) == 1: | ||||
|  | @ -281,7 +283,7 @@ class Config(object): | |||
| 
 | ||||
|     @classmethod | ||||
|     def onehost(cls, host, host_tags, host_base_path, host_dir_name, args, | ||||
|                 parallel): | ||||
|                 parallel, configuration): | ||||
|         """Configure ONE system. | ||||
|            If operating in parallel then return tuple (host, True|False, ) | ||||
|            so that main process knows for which host function was successful. | ||||
|  | @ -308,7 +310,8 @@ class Config(object): | |||
|                 initial_manifest=args.manifest, | ||||
|                 add_conf_dirs=args.conf_dir, | ||||
|                 cache_path_pattern=args.cache_path_pattern, | ||||
|                 quiet_mode=args.quiet) | ||||
|                 quiet_mode=args.quiet, | ||||
|                 configuration=configuration) | ||||
| 
 | ||||
|             remote = cdist.exec.remote.Remote( | ||||
|                 target_host=target_host, | ||||
|  | @ -316,7 +319,8 @@ class Config(object): | |||
|                 remote_copy=remote_copy, | ||||
|                 base_path=args.remote_out_path, | ||||
|                 quiet_mode=args.quiet, | ||||
|                 archiving_mode=args.use_archiving) | ||||
|                 archiving_mode=args.use_archiving, | ||||
|                 configuration=configuration) | ||||
| 
 | ||||
|             cleanup_cmds = [] | ||||
|             if cleanup_cmd: | ||||
|  |  | |||
							
								
								
									
										421
									
								
								cdist/configuration.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								cdist/configuration.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,421 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # | ||||
| # 2017 Darko Poljak (darko.poljak at gmail.com) | ||||
| # | ||||
| # This file is part of cdist. | ||||
| # | ||||
| # cdist is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, either version 3 of the License, or | ||||
| # (at your option) any later version. | ||||
| # | ||||
| # cdist is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with cdist. If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| # | ||||
| 
 | ||||
| 
 | ||||
| import configparser | ||||
| import os | ||||
| import cdist | ||||
| import cdist.argparse | ||||
| import re | ||||
| import multiprocessing | ||||
| 
 | ||||
| 
 | ||||
| class Singleton(type): | ||||
|     instance = None | ||||
| 
 | ||||
|     def __call__(cls, *args, **kwargs): | ||||
|         if not cls.instance: | ||||
|             cls.instance = super(Singleton, cls).__call__(*args, **kwargs) | ||||
|         return cls.instance | ||||
| 
 | ||||
| 
 | ||||
| _VERBOSITY_VALUES = ( | ||||
|     'ERROR', 'WARNING', 'INFO', 'VERBOSE', 'DEBUG', 'TRACE', 'OFF', | ||||
| ) | ||||
| _ARCHIVING_VALUES = ( | ||||
|     'tar', 'tgz', 'tbz2', 'txz', 'none', | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| class OptionBase: | ||||
|     def __init__(self, name): | ||||
|         self.name = name | ||||
| 
 | ||||
|     def converter(self, *args, **kwargs): | ||||
|         raise NotImplementedError('Subclass should implement this method') | ||||
| 
 | ||||
|     def translate(self, val): | ||||
|         return val | ||||
| 
 | ||||
|     def update_value(self, currval, newval, update_appends=False): | ||||
|         '''Update current option value currval with new option value newval. | ||||
|         If update_appends is True and if currval and newval are lists then | ||||
|         resulting list contains all values in currval plus all values in | ||||
|         newval. Otherwise, newval is returned. | ||||
|         ''' | ||||
|         if (isinstance(currval, list) and isinstance(newval, list) and | ||||
|                 update_appends): | ||||
|             rv = [] | ||||
|             if currval: | ||||
|                 rv.extend(currval) | ||||
|             if newval: | ||||
|                 rv.extend(newval) | ||||
|             if not rv: | ||||
|                 rv = None | ||||
|             return rv | ||||
|         else: | ||||
|             return newval | ||||
| 
 | ||||
| 
 | ||||
| class StringOption(OptionBase): | ||||
|     def __init__(self, name): | ||||
|         super().__init__(name) | ||||
| 
 | ||||
|     def converter(self): | ||||
|         def string_converter(val): | ||||
|             return self.translate(str(val)) | ||||
|         return string_converter | ||||
| 
 | ||||
|     def translate(self, val): | ||||
|         if val: | ||||
|             return val | ||||
|         else: | ||||
|             return None | ||||
| 
 | ||||
| 
 | ||||
| class BooleanOption(OptionBase): | ||||
|     BOOLEAN_STATES = configparser.ConfigParser.BOOLEAN_STATES | ||||
| 
 | ||||
|     def __init__(self, name): | ||||
|         super().__init__(name) | ||||
| 
 | ||||
|     def converter(self): | ||||
|         def boolean_converter(val): | ||||
|             v = val.lower() | ||||
|             if v not in self.BOOLEAN_STATES: | ||||
|                 raise ValueError('Invalid {} boolean value: {}'.format( | ||||
|                     self.name, val)) | ||||
|             return self.translate(v) | ||||
|         return boolean_converter | ||||
| 
 | ||||
|     def translate(self, val): | ||||
|         return self.BOOLEAN_STATES[val] | ||||
| 
 | ||||
| 
 | ||||
| class IntOption(OptionBase): | ||||
|     def __init__(self, name): | ||||
|         super().__init__(name) | ||||
| 
 | ||||
|     def converter(self): | ||||
|         def int_converter(val): | ||||
|             return self.translate(int(val)) | ||||
|         return int_converter | ||||
| 
 | ||||
| 
 | ||||
| class LowerBoundIntOption(IntOption): | ||||
|     def __init__(self, name, lower_bound): | ||||
|         super().__init__(name) | ||||
|         self.lower_bound = lower_bound | ||||
| 
 | ||||
|     def converter(self): | ||||
|         def lower_bound_converter(val): | ||||
|             converted = super(LowerBoundIntOption, self).converter()(val) | ||||
|             if converted < self.lower_bound: | ||||
|                 raise ValueError("Invalid {} value: {} < {}".format( | ||||
|                     self.name, val, self.lower_bound)) | ||||
|             return converted | ||||
|         return lower_bound_converter | ||||
| 
 | ||||
| 
 | ||||
| class SpecialCasesLowerBoundIntOption(LowerBoundIntOption): | ||||
|     def __init__(self, name, lower_bound, special_cases_mapping): | ||||
|         super().__init__(name, lower_bound) | ||||
|         self.special_cases_mapping = special_cases_mapping | ||||
| 
 | ||||
|     def translate(self, val): | ||||
|         if val in self.special_cases_mapping: | ||||
|             return self.special_cases_mapping[val] | ||||
|         else: | ||||
|             return val | ||||
| 
 | ||||
| 
 | ||||
| class JobsOption(SpecialCasesLowerBoundIntOption): | ||||
|     def __init__(self, name): | ||||
|         super().__init__(name, -1, {-1: multiprocessing.cpu_count()}) | ||||
| 
 | ||||
| 
 | ||||
| class SelectOption(OptionBase): | ||||
|     def __init__(self, name, valid_values): | ||||
|         super().__init__(name) | ||||
|         self.valid_values = valid_values | ||||
| 
 | ||||
|     def converter(self): | ||||
|         def select_converter(val): | ||||
|             if val in self.valid_values: | ||||
|                 return self.translate(val) | ||||
|             else: | ||||
|                 raise ValueError("Invalid {} value: {}.".format( | ||||
|                     self.name, val)) | ||||
|         return select_converter | ||||
| 
 | ||||
| 
 | ||||
| class VerbosityOption(SelectOption): | ||||
|     def __init__(self): | ||||
|         super().__init__('verbosity', _VERBOSITY_VALUES) | ||||
| 
 | ||||
|     def translate(self, val): | ||||
|         name = 'VERBOSE_' + val | ||||
|         verbose = getattr(cdist.argparse, name) | ||||
|         return verbose | ||||
| 
 | ||||
| 
 | ||||
| class DelimitedValuesOption(OptionBase): | ||||
|     def __init__(self, name, delimiter): | ||||
|         super().__init__(name) | ||||
|         self.delimiter = delimiter | ||||
| 
 | ||||
|     def converter(self): | ||||
|         def delimited_values_converter(val): | ||||
|             vals = re.split(r'(?<!\\)' + self.delimiter, val) | ||||
|             vals = [x for x in vals if x] | ||||
|             return self.translate(vals) | ||||
|         return delimited_values_converter | ||||
| 
 | ||||
|     def translate(self, val): | ||||
|         if val: | ||||
|             return val | ||||
|         else: | ||||
|             return None | ||||
| 
 | ||||
| 
 | ||||
| class ConfDirOption(DelimitedValuesOption): | ||||
|     def __init__(self): | ||||
|         super().__init__('conf_dir', os.pathsep) | ||||
| 
 | ||||
| 
 | ||||
| class ArchivingOption(SelectOption): | ||||
|     def __init__(self): | ||||
|         super().__init__('archiving', _ARCHIVING_VALUES) | ||||
| 
 | ||||
|     def translate(self, val): | ||||
|         if val == 'none': | ||||
|             return None | ||||
|         else: | ||||
|             return val | ||||
| 
 | ||||
| 
 | ||||
| _ARG_OPTION_MAPPING = { | ||||
|     'beta': 'beta', | ||||
|     'cache_path_pattern': 'cache_path_pattern', | ||||
|     'conf_dir': 'conf_dir', | ||||
|     'manifest': 'init_manifest', | ||||
|     'out_path': 'out_path', | ||||
|     'remote_out_path': 'remote_out_path', | ||||
|     'remote_copy': 'remote_copy', | ||||
|     'remote_exec': 'remote_exec', | ||||
|     'inventory_dir': 'inventory_dir', | ||||
|     'jobs': 'jobs', | ||||
|     'parallel': 'parallel', | ||||
|     'verbose': 'verbosity', | ||||
|     'use_archiving': 'archiving', | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class Configuration(metaclass=Singleton): | ||||
|     _config_basename = 'cdist.cfg' | ||||
|     _global_config_file = os.path.join('/', 'etc', _config_basename, ) | ||||
|     _local_config_file = os.path.join(os.path.expanduser('~'), | ||||
|                                       '.' + _config_basename, ) | ||||
|     if (not (os.path.exists(_local_config_file) and | ||||
|              os.path.isfile(_local_config_file))): | ||||
|         _local_config_file = os.path.join( | ||||
|             os.environ.get('XDG_CONFIG_HOME', | ||||
|                            os.path.expanduser('~/.config/cdist')), | ||||
|             _config_basename) | ||||
|     default_config_files = (_global_config_file, _local_config_file, ) | ||||
|     ENV_VAR_CONFIG_FILE = 'CDIST_CONFIG_FILE' | ||||
| 
 | ||||
|     VERBOSITY_VALUES = _VERBOSITY_VALUES | ||||
|     ARCHIVING_VALUES = _ARCHIVING_VALUES | ||||
| 
 | ||||
|     CONFIG_FILE_OPTIONS = { | ||||
|         'GLOBAL': { | ||||
|             'beta': BooleanOption('beta'), | ||||
|             'local_shell': StringOption('local_shell'), | ||||
|             'remote_shell': StringOption('remote_shell'), | ||||
|             'cache_path_pattern': StringOption('cache_path_pattern'), | ||||
|             'conf_dir': ConfDirOption(), | ||||
|             'init_manifest': StringOption('init_manifest'), | ||||
|             'out_path': StringOption('out_path'), | ||||
|             'remote_out_path': StringOption('remote_out_path'), | ||||
|             'remote_copy': StringOption('remote_copy'), | ||||
|             'remote_exec': StringOption('remote_exec'), | ||||
|             'inventory_dir': StringOption('inventory_dir'), | ||||
|             'jobs': JobsOption('jobs'), | ||||
|             'parallel': JobsOption('parallel'), | ||||
|             'verbosity': VerbosityOption(), | ||||
|             'archiving': ArchivingOption(), | ||||
|         }, | ||||
|     } | ||||
| 
 | ||||
|     ENV_VAR_OPTION_MAPPING = { | ||||
|         'CDIST_BETA': 'beta', | ||||
|         'CDIST_PATH': 'conf_dir', | ||||
|         'CDIST_LOCAL_SHELL': 'local_shell', | ||||
|         'CDIST_REMOTE_SHELL': 'remote_shell', | ||||
|         'CDIST_REMOTE_EXEC': 'remote_exec', | ||||
|         'CDIST_REMOTE_COPY': 'remote_copy', | ||||
|         'CDIST_INVENTORY_DIR': 'inventory_dir', | ||||
|         'CDIST_CACHE_PATH_PATTERN': 'cache_path_pattern', | ||||
|     } | ||||
|     ENV_VAR_BOOLEAN_OPTIONS = ('CDIST_BETA', ) | ||||
| 
 | ||||
|     ARG_OPTION_MAPPING = _ARG_OPTION_MAPPING | ||||
|     ADJUST_ARG_OPTION_MAPPING = { | ||||
|        _ARG_OPTION_MAPPING[key]: key for key in _ARG_OPTION_MAPPING | ||||
|     } | ||||
| 
 | ||||
|     def _convert_args(self, args): | ||||
|         if args: | ||||
|             if hasattr(args, '__dict__'): | ||||
|                 return vars(args) | ||||
|             else: | ||||
|                 raise ValueError( | ||||
|                     'args parameter must be have __dict__ attribute') | ||||
|         else: | ||||
|             return None | ||||
| 
 | ||||
|     def __init__(self, command_line_args, env=os.environ, | ||||
|                  config_files=default_config_files): | ||||
|         self.command_line_args = command_line_args | ||||
|         self.args = self._convert_args(command_line_args) | ||||
|         self.env = env | ||||
|         self.config_files = config_files | ||||
|         self.config = self._get_config() | ||||
| 
 | ||||
|     def get_config(self, section=None): | ||||
|         if section is None: | ||||
|             return self.config | ||||
|         if section in self.config: | ||||
|             return self.config[section] | ||||
|         raise ValueError('Unknown section: {}'.format(section)) | ||||
| 
 | ||||
|     def _get_args_name_value(self, arg_name, val): | ||||
|         if arg_name == 'verbosity' and val == 'OFF': | ||||
|             name = 'quiet' | ||||
|             rv = True | ||||
|         else: | ||||
|             name = arg_name | ||||
|             rv = val | ||||
|         return (name, rv) | ||||
| 
 | ||||
|     def get_args(self, section='GLOBAL'): | ||||
|         args = self.command_line_args | ||||
|         cfg = self.get_config(section) | ||||
|         for option in self.ADJUST_ARG_OPTION_MAPPING: | ||||
|             if option in cfg: | ||||
|                 arg_name = self.ADJUST_ARG_OPTION_MAPPING[option] | ||||
|                 val = cfg[option] | ||||
|                 name, val = self._get_args_name_value(arg_name, val) | ||||
|                 setattr(args, name, val) | ||||
|         return args | ||||
| 
 | ||||
|     def _read_config_file(self, files): | ||||
|         config_parser = configparser.ConfigParser() | ||||
|         config_parser.read(files) | ||||
|         d = dict() | ||||
|         for section in config_parser.sections(): | ||||
|             if section not in self.CONFIG_FILE_OPTIONS: | ||||
|                 raise ValueError("Invalid section: {}.".format(section)) | ||||
|             if section not in d: | ||||
|                 d[section] = dict() | ||||
| 
 | ||||
|             for option in config_parser[section]: | ||||
|                 if option not in self.CONFIG_FILE_OPTIONS[section]: | ||||
|                     raise ValueError("Invalid option: {}.".format(option)) | ||||
| 
 | ||||
|                 option_object = self.CONFIG_FILE_OPTIONS[section][option] | ||||
|                 converter = option_object.converter() | ||||
|                 val = config_parser[section][option] | ||||
|                 newval = converter(val) | ||||
|                 d[section][option] = newval | ||||
|         return d | ||||
| 
 | ||||
|     def _read_env_var_config(self, env, section): | ||||
|         d = dict() | ||||
|         for option in self.ENV_VAR_OPTION_MAPPING: | ||||
|             if option in env: | ||||
|                 dst_opt = self.ENV_VAR_OPTION_MAPPING[option] | ||||
|                 if option in self.ENV_VAR_BOOLEAN_OPTIONS: | ||||
|                     d[dst_opt] = True | ||||
|                 else: | ||||
|                     option_object = self.CONFIG_FILE_OPTIONS[section][dst_opt] | ||||
|                     converter = option_object.converter() | ||||
|                     val = env[option] | ||||
|                     newval = converter(val) | ||||
|                     d[dst_opt] = newval | ||||
|         return d | ||||
| 
 | ||||
|     def _read_args_config(self, args): | ||||
|         d = dict() | ||||
|         for option in self.ARG_OPTION_MAPPING: | ||||
|             if option in args: | ||||
|                 dst_opt = self.ARG_OPTION_MAPPING[option] | ||||
|                 d[dst_opt] = args[option] | ||||
|         return d | ||||
| 
 | ||||
|     def _update_config_dict(self, config, newconfig, update_appends=False): | ||||
|         for section in newconfig: | ||||
|             self._update_config_dict_section( | ||||
|                 section, config, newconfig[section], update_appends) | ||||
| 
 | ||||
|     def _update_config_dict_section(self, section, config, newconfig, | ||||
|                                     update_appends=False): | ||||
|         if section not in config: | ||||
|             config[section] = dict() | ||||
|         for option in newconfig: | ||||
|             newval = newconfig[option] | ||||
|             if option in config[section]: | ||||
|                 currval = config[section][option] | ||||
|             else: | ||||
|                 currval = None | ||||
|             option_object = self.CONFIG_FILE_OPTIONS[section][option] | ||||
|             config[section][option] = option_object.update_value( | ||||
|                 currval, newval, update_appends) | ||||
| 
 | ||||
|     def _get_config(self): | ||||
|         # global config file | ||||
|         # local config file | ||||
|         config = self._read_config_file(self.config_files) | ||||
|         # default empty config if needed | ||||
|         if not config: | ||||
|             config['GLOBAL'] = dict() | ||||
|         # environment variables | ||||
|         newconfig = self._read_env_var_config(self.env, 'GLOBAL') | ||||
|         for section in config: | ||||
|             self._update_config_dict_section(section, config, newconfig) | ||||
|         # config file in CDIST_CONFIG_FILE env var | ||||
|         config_file = os.environ.get(self.ENV_VAR_CONFIG_FILE, None) | ||||
|         if config_file: | ||||
|             newconfig = self._read_config_file(config_file) | ||||
|             self._update_config_dict(config, newconfig) | ||||
|         # command line config file | ||||
|         if (self.args and 'config_file' in self.args and | ||||
|                 self.args['config_file']): | ||||
|             newconfig = self._read_config_file(self.args['config_file']) | ||||
|             self._update_config_dict(config, newconfig) | ||||
|         # command line | ||||
|         if self.args: | ||||
|             newconfig = self._read_args_config(self.args) | ||||
|             for section in config: | ||||
|                 self._update_config_dict_section(section, config, newconfig, | ||||
|                                                  update_appends=True) | ||||
|         return config | ||||
|  | @ -55,7 +55,8 @@ class Local(object): | |||
|                  initial_manifest=None, | ||||
|                  add_conf_dirs=None, | ||||
|                  cache_path_pattern=None, | ||||
|                  quiet_mode=False): | ||||
|                  quiet_mode=False, | ||||
|                  configuration=None): | ||||
| 
 | ||||
|         self.target_host = target_host | ||||
|         if target_host_tags is None: | ||||
|  | @ -70,6 +71,10 @@ class Local(object): | |||
|         self._add_conf_dirs = add_conf_dirs | ||||
|         self.cache_path_pattern = cache_path_pattern | ||||
|         self.quiet_mode = quiet_mode | ||||
|         if configuration: | ||||
|             self.configuration = configuration | ||||
|         else: | ||||
|             self.configuration = {} | ||||
| 
 | ||||
|         self._init_log() | ||||
|         self._init_permissions() | ||||
|  | @ -142,10 +147,12 @@ class Local(object): | |||
|             self.conf_dirs.append(self.home_dir) | ||||
| 
 | ||||
|         # Add directories defined in the CDIST_PATH environment variable | ||||
|         if 'CDIST_PATH' in os.environ: | ||||
|             cdist_path_dirs = re.split(r'(?<!\\):', os.environ['CDIST_PATH']) | ||||
|             cdist_path_dirs.reverse() | ||||
|             self.conf_dirs.extend(cdist_path_dirs) | ||||
|         # if 'CDIST_PATH' in os.environ: | ||||
|         #     cdist_path_dirs = re.split(r'(?<!\\):', os.environ['CDIST_PATH']) | ||||
|         #     cdist_path_dirs.reverse() | ||||
|         #     self.conf_dirs.extend(cdist_path_dirs) | ||||
|         if 'conf_dir' in self.configuration: | ||||
|             self.conf_dirs.extend(self.configuration['conf_dir']) | ||||
| 
 | ||||
|         # Add command line supplied directories | ||||
|         if self._add_conf_dirs: | ||||
|  | @ -175,12 +182,11 @@ class Local(object): | |||
|     def _init_cache_dir(self, cache_dir): | ||||
|         if cache_dir: | ||||
|             self.cache_path = cache_dir | ||||
|         elif self.home_dir: | ||||
|             self.cache_path = os.path.join(self.home_dir, "cache") | ||||
|         else: | ||||
|             if self.home_dir: | ||||
|                 self.cache_path = os.path.join(self.home_dir, "cache") | ||||
|             else: | ||||
|                 raise cdist.Error( | ||||
|                         "No homedir setup and no cache dir location given") | ||||
|             raise cdist.Error( | ||||
|                 "No homedir setup and no cache dir location given") | ||||
| 
 | ||||
|     def rmdir(self, path): | ||||
|         """Remove directory on the local side.""" | ||||
|  | @ -258,7 +264,7 @@ class Local(object): | |||
|             self.log.debug('%s is executable, running it', script) | ||||
|             command = [script] | ||||
|         else: | ||||
|             command = [os.environ.get('CDIST_LOCAL_SHELL', "/bin/sh"), "-e"] | ||||
|             command = [self.configuration.get('local_shell', "/bin/sh"), "-e"] | ||||
|             self.log.debug('%s is NOT executable, running it with %s', | ||||
|                            script, " ".join(command)) | ||||
|             command.append(script) | ||||
|  |  | |||
|  | @ -62,7 +62,8 @@ class Remote(object): | |||
|                  remote_copy, | ||||
|                  base_path=None, | ||||
|                  quiet_mode=None, | ||||
|                  archiving_mode=None): | ||||
|                  archiving_mode=None, | ||||
|                  configuration=None): | ||||
|         self.target_host = target_host | ||||
|         self._exec = remote_exec | ||||
|         self._copy = remote_copy | ||||
|  | @ -73,6 +74,10 @@ class Remote(object): | |||
|             self.base_path = "/var/lib/cdist" | ||||
|         self.quiet_mode = quiet_mode | ||||
|         self.archiving_mode = archiving_mode | ||||
|         if configuration: | ||||
|             self.configuration = configuration | ||||
|         else: | ||||
|             self.configuration = {} | ||||
| 
 | ||||
|         self.conf_path = os.path.join(self.base_path, "conf") | ||||
|         self.object_path = os.path.join(self.base_path, "object") | ||||
|  | @ -235,7 +240,10 @@ class Remote(object): | |||
| 
 | ||||
|         """ | ||||
| 
 | ||||
|         command = [os.environ.get('CDIST_REMOTE_SHELL', "/bin/sh"), "-e"] | ||||
|         command = [ | ||||
|             self.configuration.get('CDIST_REMOTE_SHELL', "/bin/sh"), | ||||
|             "-e" | ||||
|         ] | ||||
|         command.append(script) | ||||
| 
 | ||||
|         return self.run(command, env, return_output) | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ import os | |||
| import os.path | ||||
| import itertools | ||||
| import sys | ||||
| import cdist.configuration | ||||
| from cdist.hostsource import hostfile_process_line | ||||
| 
 | ||||
| DIST_INVENTORY_DB_NAME = "inventory" | ||||
|  | @ -34,21 +35,23 @@ dist_inventory_db = os.path.abspath(os.path.join( | |||
|     os.path.dirname(cdist.__file__), DIST_INVENTORY_DB_NAME)) | ||||
| 
 | ||||
| 
 | ||||
| def determine_default_inventory_dir(args): | ||||
| def determine_default_inventory_dir(args, configuration): | ||||
|     # The order of inventory dir setting by decreasing priority | ||||
|     # 1. inventory_dir argument | ||||
|     # 2. CDIST_INVENTORY_DIR env var if set | ||||
|     # 3. ~/.cdist/inventory if HOME env var is set | ||||
|     # 4. distribution inventory directory | ||||
|     if not args.inventory_dir: | ||||
|         if 'CDIST_INVENTORY_DIR' in os.environ: | ||||
|             args.inventory_dir = os.environ['CDIST_INVENTORY_DIR'] | ||||
|     # 1. inventory_dir from configuration | ||||
|     # 2. ~/.cdist/inventory if HOME env var is set | ||||
|     # 3. distribution inventory directory | ||||
|     inventory_dir_set = False | ||||
|     if 'inventory_dir' in configuration: | ||||
|         val = configuration['inventory_dir'] | ||||
|         if val: | ||||
|             args.inventory_dir = val | ||||
|             inventory_dir_set = True | ||||
|     if not inventory_dir_set: | ||||
|         home = cdist.home_dir() | ||||
|         if home: | ||||
|             args.inventory_dir = os.path.join(home, DIST_INVENTORY_DB_NAME) | ||||
|         else: | ||||
|             home = cdist.home_dir() | ||||
|             if home: | ||||
|                 args.inventory_dir = os.path.join(home, DIST_INVENTORY_DB_NAME) | ||||
|             else: | ||||
|                 args.inventory_dir = dist_inventory_db | ||||
|             args.inventory_dir = dist_inventory_db | ||||
| 
 | ||||
| 
 | ||||
| def contains_all(big, little): | ||||
|  | @ -80,8 +83,12 @@ def rstrip_nl(s): | |||
| class Inventory(object): | ||||
|     """Inventory main class""" | ||||
| 
 | ||||
|     def __init__(self, db_basedir=dist_inventory_db): | ||||
|     def __init__(self, db_basedir=dist_inventory_db, configuration=None): | ||||
|         self.db_basedir = db_basedir | ||||
|         if configuration: | ||||
|             self.configuration = configuration | ||||
|         else: | ||||
|             self.configuration = {} | ||||
|         self.log = logging.getLogger("inventory") | ||||
|         self.init_db() | ||||
| 
 | ||||
|  | @ -171,7 +178,10 @@ class Inventory(object): | |||
|         log = logging.getLogger("inventory") | ||||
|         if 'taglist' in args: | ||||
|             args.taglist = cls.strlist_to_list(args.taglist) | ||||
|         determine_default_inventory_dir(args) | ||||
| 
 | ||||
|         cfg = cdist.configuration.Configuration(args) | ||||
|         configuration = cfg.get_config(section='GLOBAL') | ||||
|         determine_default_inventory_dir(args, configuration) | ||||
| 
 | ||||
|         log.debug("Using inventory: {}".format(args.inventory_dir)) | ||||
|         log.trace("Inventory args: {}".format(vars(args))) | ||||
|  | @ -182,23 +192,26 @@ class Inventory(object): | |||
|                               hostfile=args.hostfile, | ||||
|                               db_basedir=args.inventory_dir, | ||||
|                               list_only_host=args.list_only_host, | ||||
|                               has_all_tags=args.has_all_tags) | ||||
|                               has_all_tags=args.has_all_tags, | ||||
|                               configuration=configuration) | ||||
|         elif args.subcommand == "add-host": | ||||
|             c = InventoryHost(hosts=args.host, hostfile=args.hostfile, | ||||
|                               db_basedir=args.inventory_dir) | ||||
|                               db_basedir=args.inventory_dir, | ||||
|                               configuration=configuration) | ||||
|         elif args.subcommand == "del-host": | ||||
|             c = InventoryHost(hosts=args.host, hostfile=args.hostfile, | ||||
|                               all=args.all, db_basedir=args.inventory_dir, | ||||
|                               action="del") | ||||
|                               action="del", configuration=configuration) | ||||
|         elif args.subcommand == "add-tag": | ||||
|             c = InventoryTag(hosts=args.host, tags=args.taglist, | ||||
|                              hostfile=args.hostfile, tagfile=args.tagfile, | ||||
|                              db_basedir=args.inventory_dir) | ||||
|                              db_basedir=args.inventory_dir, | ||||
|                              configuration=configuration) | ||||
|         elif args.subcommand == "del-tag": | ||||
|             c = InventoryTag(hosts=args.host, tags=args.taglist, | ||||
|                              hostfile=args.hostfile, tagfile=args.tagfile, | ||||
|                              all=args.all, db_basedir=args.inventory_dir, | ||||
|                              action="del") | ||||
|                              action="del", configuration=configuration) | ||||
|         else: | ||||
|             raise cdist.Error("Unknown inventory command \'{}\'".format( | ||||
|                         args.subcommand)) | ||||
|  | @ -208,8 +221,8 @@ class Inventory(object): | |||
| class InventoryList(Inventory): | ||||
|     def __init__(self, hosts=None, istag=False, hostfile=None, | ||||
|                  list_only_host=False, has_all_tags=False, | ||||
|                  db_basedir=dist_inventory_db): | ||||
|         super().__init__(db_basedir) | ||||
|                  db_basedir=dist_inventory_db, configuration=None): | ||||
|         super().__init__(db_basedir, configuration) | ||||
|         self.hosts = hosts | ||||
|         self.istag = istag | ||||
|         self.hostfile = hostfile | ||||
|  | @ -274,8 +287,9 @@ class InventoryList(Inventory): | |||
| 
 | ||||
| class InventoryHost(Inventory): | ||||
|     def __init__(self, hosts=None, hostfile=None, | ||||
|                  db_basedir=dist_inventory_db, all=False, action="add"): | ||||
|         super().__init__(db_basedir) | ||||
|                  db_basedir=dist_inventory_db, all=False, action="add", | ||||
|                  configuration=None): | ||||
|         super().__init__(db_basedir, configuration) | ||||
|         self.actions = ("add", "del") | ||||
|         if action not in self.actions: | ||||
|             raise cdist.Error("Invalid action \'{}\', valid actions are:" | ||||
|  | @ -323,8 +337,9 @@ class InventoryHost(Inventory): | |||
| 
 | ||||
| class InventoryTag(Inventory): | ||||
|     def __init__(self, hosts=None, tags=None, hostfile=None, tagfile=None, | ||||
|                  db_basedir=dist_inventory_db, all=False, action="add"): | ||||
|         super().__init__(db_basedir) | ||||
|                  db_basedir=dist_inventory_db, all=False, action="add", | ||||
|                  configuration=None): | ||||
|         super().__init__(db_basedir, configuration) | ||||
|         self.actions = ("add", "del") | ||||
|         if action not in self.actions: | ||||
|             raise cdist.Error("Invalid action \'{}\', valid actions are:" | ||||
|  |  | |||
							
								
								
									
										1076
									
								
								cdist/test/configuration/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1076
									
								
								cdist/test/configuration/__init__.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										0
									
								
								cdist/test/configuration/fixtures/.nonempty
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								cdist/test/configuration/fixtures/.nonempty
									
										
									
									
									
										Normal file
									
								
							|  | @ -28,8 +28,10 @@ import string | |||
| import random | ||||
| import time | ||||
| import datetime | ||||
| import argparse | ||||
| 
 | ||||
| import cdist | ||||
| import cdist.configuration as cc | ||||
| from cdist import test | ||||
| from cdist.exec import local | ||||
| 
 | ||||
|  | @ -165,6 +167,9 @@ class LocalTestCase(test.CdistTestCase): | |||
| 
 | ||||
|         os.environ['CDIST_PATH'] = conf_dir | ||||
| 
 | ||||
|         configuration = cc.Configuration(argparse.Namespace(), | ||||
|                                          env=os.environ) | ||||
| 
 | ||||
|         link_test_local = local.Local( | ||||
|             target_host=( | ||||
|                 'localhost', | ||||
|  | @ -174,6 +179,7 @@ class LocalTestCase(test.CdistTestCase): | |||
|             base_root_path=self.host_base_path, | ||||
|             host_dir_name=self.hostdir, | ||||
|             exec_path=test.cdist_exec_path, | ||||
|             configuration=configuration | ||||
|         ) | ||||
| 
 | ||||
|         link_test_local._create_conf_path_and_link_conf_dirs() | ||||
|  |  | |||
|  | @ -15,43 +15,45 @@ SYNOPSIS | |||
| 
 | ||||
|     cdist banner [-h] [-q] [-v] | ||||
| 
 | ||||
|     cdist config [-h] [-q] [-v] [-b] [-C CACHE_PATH_PATTERN] [-c CONF_DIR] | ||||
|                  [-i MANIFEST] [-j [JOBS]] [-n] [-o OUT_PATH] | ||||
|                  [-R [{tar,tgz,tbz2,txz}]] [-r REMOTE_OUT_DIR] | ||||
|                  [--remote-copy REMOTE_COPY] [--remote-exec REMOTE_EXEC] | ||||
|                  [-I INVENTORY_DIR] [-A] [-a] [-f HOSTFILE] [-p [HOST_MAX]] | ||||
|                  [-s] [-t] | ||||
|     cdist config [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||
|                  [-C CACHE_PATH_PATTERN] [-c CONF_DIR] [-i MANIFEST] | ||||
|                  [-j [JOBS]] [-n] [-o OUT_PATH] [-R [{tar,tgz,tbz2,txz}]] | ||||
|                  [-r REMOTE_OUT_DIR] [--remote-copy REMOTE_COPY] | ||||
|                  [--remote-exec REMOTE_EXEC] [-I INVENTORY_DIR] [-A] [-a] | ||||
|                  [-f HOSTFILE] [-p [HOST_MAX]] [-s] [-t] | ||||
|                  [host [host ...]]  | ||||
| 
 | ||||
|     cdist install [-h] [-q] [-v] [-b] [-C CACHE_PATH_PATTERN] [-c CONF_DIR] | ||||
|                   [-i MANIFEST] [-j [JOBS]] [-n] [-o OUT_PATH] | ||||
|                   [-R [{tar,tgz,tbz2,txz}]] [-r REMOTE_OUT_DIR] | ||||
|                   [--remote-copy REMOTE_COPY] [--remote-exec REMOTE_EXEC] | ||||
|                   [-I INVENTORY_DIR] [-A] [-a] [-f HOSTFILE] [-p [HOST_MAX]] | ||||
|                   [-s] [-t] | ||||
|     cdist install [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||
|                   [-C CACHE_PATH_PATTERN] [-c CONF_DIR] [-i MANIFEST] | ||||
|                   [-j [JOBS]] [-n] [-o OUT_PATH] [-R [{tar,tgz,tbz2,txz}]] | ||||
|                   [-r REMOTE_OUT_DIR] [--remote-copy REMOTE_COPY] | ||||
|                   [--remote-exec REMOTE_EXEC] [-I INVENTORY_DIR] [-A] [-a] | ||||
|                   [-f HOSTFILE] [-p [HOST_MAX]] [-s] [-t] | ||||
|                   [host [host ...]]  | ||||
| 
 | ||||
|     cdist inventory [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] | ||||
|     cdist inventory [-h] [-q] [-v] [-b] [-g CONFIG_FILE] [-I INVENTORY_DIR] | ||||
|                     {add-host,add-tag,del-host,del-tag,list} ... | ||||
| 
 | ||||
|     cdist inventory add-host [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] | ||||
|                              [-f HOSTFILE] | ||||
|     cdist inventory add-host [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||
|                              [-I INVENTORY_DIR] [-f HOSTFILE] | ||||
|                              [host [host ...]] | ||||
| 
 | ||||
|     cdist inventory add-tag [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] | ||||
|                             [-f HOSTFILE] [-T TAGFILE] [-t TAGLIST] | ||||
|     cdist inventory add-tag [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||
|                             [-I INVENTORY_DIR] [-f HOSTFILE] [-T TAGFILE] | ||||
|                             [-t TAGLIST] | ||||
|                             [host [host ...]] | ||||
| 
 | ||||
|     cdist inventory del-host [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] [-a] | ||||
|                              [-f HOSTFILE] | ||||
|     cdist inventory del-host [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||
|                              [-I INVENTORY_DIR] [-a] [-f HOSTFILE] | ||||
|                              [host [host ...]] | ||||
| 
 | ||||
|     cdist inventory del-tag [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] [-a] | ||||
|                             [-f HOSTFILE] [-T TAGFILE] [-t TAGLIST] | ||||
|     cdist inventory del-tag [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||
|                             [-I INVENTORY_DIR] [-a] [-f HOSTFILE] | ||||
|                             [-T TAGFILE] [-t TAGLIST] | ||||
|                             [host [host ...]] | ||||
| 
 | ||||
|     cdist inventory list [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] [-a] | ||||
|                          [-f HOSTFILE] [-H] [-t] | ||||
|     cdist inventory list [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||
|                          [-I INVENTORY_DIR] [-a] [-f HOSTFILE] [-H] [-t] | ||||
|                          [host [host ...]] | ||||
| 
 | ||||
|     cdist shell [-h] [-q] [-v] [-s SHELL] | ||||
|  | @ -112,7 +114,7 @@ Install command is currently in beta. | |||
| .. option:: -b, --beta | ||||
| 
 | ||||
|     Enable beta functionality. | ||||
| 
 | ||||
|      | ||||
| .. option:: -C CACHE_PATH_PATTERN, --cache-path-pattern CACHE_PATH_PATTERN | ||||
| 
 | ||||
|     Sepcify custom cache path pattern. If it is not set then | ||||
|  | @ -133,15 +135,18 @@ Install command is currently in beta. | |||
|     read hosts from stdin. For the file format see | ||||
|     :strong:`HOSTFILE FORMAT` below. | ||||
| 
 | ||||
| .. option:: -g CONFIG_FILE, --config-file CONFIG_FILE | ||||
| 
 | ||||
|     Use specified custom configuration file. | ||||
| 
 | ||||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||
| 
 | ||||
|     Use specified custom inventory directory. Inventory | ||||
|     directory is set up by the following rules: if this | ||||
|     argument is set then specified directory is used, if | ||||
|     CDIST_INVENTORY_DIR env var is set then its value is | ||||
|     used, if HOME env var is set then ~/.cdit/inventory is | ||||
|     used, otherwise distribution inventory directory is | ||||
|     used. | ||||
|     directory is set up by the following rules: if cdist  | ||||
|     configuration resolves this value then specified | ||||
|     directory is used, if HOME env var is set then | ||||
|     ~/.cdit/inventory is used, otherwise distribution | ||||
|     inventory directory is used. | ||||
| 
 | ||||
| .. option:: -i MANIFEST, --initial-manifest MANIFEST | ||||
| 
 | ||||
|  | @ -254,16 +259,18 @@ Add host(s) to inventory database. | |||
|     host or host file is specified then, by default, read | ||||
|     from stdin. Hostfile format is the same as config hostfile format. | ||||
| 
 | ||||
| .. option:: -g CONFIG_FILE, --config-file CONFIG_FILE | ||||
| 
 | ||||
|     Use specified custom configuration file. | ||||
| 
 | ||||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||
| 
 | ||||
|     Use specified custom inventory directory. Inventory | ||||
|     directory is set up by the following rules: if this | ||||
|     argument is set then specified directory is used, if | ||||
|     CDIST_INVENTORY_DIR env var is set then its value is | ||||
|     used, if HOME env var is set then ~/.cdist/inventory is | ||||
|     used, otherwise distribution inventory directory is | ||||
|     used. | ||||
|     directory is set up by the following rules: if cdist  | ||||
|     configuration resolves this value then specified | ||||
|     directory is used, if HOME env var is set then | ||||
|     ~/.cdit/inventory is used, otherwise distribution | ||||
|     inventory directory is used. | ||||
| 
 | ||||
| 
 | ||||
| INVENTORY ADD-TAG | ||||
|  | @ -287,15 +294,18 @@ Add tag(s) to inventory database. | |||
|     are specified then tags are read from stdin and are | ||||
|     added to all hosts. Hostfile format is the same as config hostfile format. | ||||
| 
 | ||||
| .. option:: -g CONFIG_FILE, --config-file CONFIG_FILE | ||||
| 
 | ||||
|     Use specified custom configuration file. | ||||
| 
 | ||||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||
| 
 | ||||
|     Use specified custom inventory directory. Inventory | ||||
|     directory is set up by the following rules: if this | ||||
|     argument is set then specified directory is used, if | ||||
|     CDIST_INVENTORY_DIR env var is set then its value is | ||||
|     used, if HOME env var is set then ~/.cdist/inventory is | ||||
|     used, otherwise distribution inventory directory is | ||||
|     used. | ||||
|     directory is set up by the following rules: if cdist  | ||||
|     configuration resolves this value then specified | ||||
|     directory is used, if HOME env var is set then | ||||
|     ~/.cdit/inventory is used, otherwise distribution | ||||
|     inventory directory is used. | ||||
| 
 | ||||
| .. option:: -T TAGFILE, --tag-file TAGFILE | ||||
| 
 | ||||
|  | @ -335,15 +345,18 @@ Delete host(s) from inventory database. | |||
|     host or host file is specified then, by default, read | ||||
|     from stdin. Hostfile format is the same as config hostfile format. | ||||
| 
 | ||||
| .. option:: -g CONFIG_FILE, --config-file CONFIG_FILE | ||||
| 
 | ||||
|     Use specified custom configuration file. | ||||
| 
 | ||||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||
| 
 | ||||
|     Use specified custom inventory directory. Inventory | ||||
|     directory is set up by the following rules: if this | ||||
|     argument is set then specified directory is used, if | ||||
|     CDIST_INVENTORY_DIR env var is set then its value is | ||||
|     used, if HOME env var is set then ~/.cdist/inventory is | ||||
|     used, otherwise distribution inventory directory is | ||||
|     used. | ||||
|     directory is set up by the following rules: if cdist  | ||||
|     configuration resolves this value then specified | ||||
|     directory is used, if HOME env var is set then | ||||
|     ~/.cdit/inventory is used, otherwise distribution | ||||
|     inventory directory is used. | ||||
| 
 | ||||
| 
 | ||||
| INVENTORY DEL-TAG | ||||
|  | @ -372,15 +385,18 @@ Delete tag(s) from inventory database. | |||
|     from stdin and are deleted from all hosts. Hostfile | ||||
|     format is the same as config hostfile format. | ||||
| 
 | ||||
| .. option:: -g CONFIG_FILE, --config-file CONFIG_FILE | ||||
| 
 | ||||
|     Use specified custom configuration file. | ||||
| 
 | ||||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||
| 
 | ||||
|     Use specified custom inventory directory. Inventory | ||||
|     directory is set up by the following rules: if this | ||||
|     argument is set then specified directory is used, if | ||||
|     CDIST_INVENTORY_DIR env var is set then its value is | ||||
|     used, if HOME env var is set then ~/.cdist/inventory is | ||||
|     used, otherwise distribution inventory directory is | ||||
|     used. | ||||
|     directory is set up by the following rules: if cdist  | ||||
|     configuration resolves this value then specified | ||||
|     directory is used, if HOME env var is set then | ||||
|     ~/.cdit/inventory is used, otherwise distribution | ||||
|     inventory directory is used. | ||||
| 
 | ||||
| .. option:: -T TAGFILE, --tag-file TAGFILE | ||||
| 
 | ||||
|  | @ -421,6 +437,10 @@ List inventory database. | |||
|     host or host file is specified then, by default, list | ||||
|     all. Hostfile format is the same as config hostfile format. | ||||
| 
 | ||||
| .. option:: -g CONFIG_FILE, --config-file CONFIG_FILE | ||||
| 
 | ||||
|     Use specified custom configuration file. | ||||
| 
 | ||||
| .. option:: -H, --host-only | ||||
| 
 | ||||
|     Suppress tags listing. | ||||
|  | @ -428,12 +448,11 @@ List inventory database. | |||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||
| 
 | ||||
|     Use specified custom inventory directory. Inventory | ||||
|     directory is set up by the following rules: if this | ||||
|     argument is set then specified directory is used, if | ||||
|     CDIST_INVENTORY_DIR env var is set then its value is | ||||
|     used, if HOME env var is set then ~/.cdist/inventory is | ||||
|     used, otherwise distribution inventory directory is | ||||
|     used. | ||||
|     directory is set up by the following rules: if cdist  | ||||
|     configuration resolves this value then specified | ||||
|     directory is used, if HOME env var is set then | ||||
|     ~/.cdit/inventory is used, otherwise distribution | ||||
|     inventory directory is used. | ||||
| 
 | ||||
| .. option:: -t, --tag | ||||
| 
 | ||||
|  | @ -454,6 +473,82 @@ usage. Its primary use is for debugging type parameters. | |||
|     be POSIX compatible shell. | ||||
| 
 | ||||
| 
 | ||||
| CONFIGURATION FILE | ||||
| ------------------ | ||||
| cdist obtains configuration data from the following sources in the following | ||||
| order: | ||||
| 
 | ||||
|     #. command-line options | ||||
|     #. configuration file specified at command-line | ||||
|     #. configuration file specified in CDIST_CONFIG_FILE environment variable | ||||
|     #. environment variables | ||||
|     #. user's configuration file (first one found of ~/.cdist.cfg, | ||||
|            $XDG_CONFIG_HOME/cdist/cdist.cfg, in specified order) | ||||
|     #. system-wide configuration file (/etc/cdist.cfg) | ||||
| 
 | ||||
| if one exists. | ||||
| 
 | ||||
| cdist configuration file is in the INI file format. Currently it supports | ||||
| only [GLOBAL] section. | ||||
| The possible keywords and their meanings are as follows: | ||||
| 
 | ||||
| :strong:`archiving` | ||||
|     Use specified archiving. Valid values include: | ||||
|     'none', 'tar', 'tgz', 'tbz2' and 'txz'. | ||||
| 
 | ||||
| :strong:`beta` | ||||
|     Enable beta functionality. It recognizes boolean values from | ||||
|     'yes'/'no', 'on'/'off', 'true'/'false' and '1'/'0' | ||||
| 
 | ||||
| :strong:`cache_path_pattern` | ||||
|     Specify cache path pattern. | ||||
| 
 | ||||
| :strong:`conf_dir` | ||||
|     Comma separated list of configuration directories. | ||||
|     If also specified at command line then values from command line are | ||||
|     appended to this value. | ||||
| 
 | ||||
| :strong:`init_manifest` | ||||
|     Specify default initial manifest. | ||||
| 
 | ||||
| :strong:`inventory_dir` | ||||
|     Specify inventory directory. | ||||
| 
 | ||||
| :strong:`jobs` | ||||
|     Specify number of jobs for parallel processing. If -1 then the default, | ||||
|     number of CPU's in the system is used. If 0 then parallel processing in | ||||
|     jobs is disabled. If set to positive number then specified maximum | ||||
|     number of processes will be used. | ||||
| 
 | ||||
| :strong:`local_shell` | ||||
|     Shell command used for local execution. | ||||
| 
 | ||||
| :strong:`out_path` | ||||
|     Directory to save cdist output in. | ||||
| 
 | ||||
| :strong:`parallel` | ||||
|     Process hosts in parallel. If -1 then the default, number of CPU's in | ||||
|     the system is used. If 0 then parallel processing of hosts is disabled. | ||||
|     If set to positive number then specified maximum number of processes | ||||
|     will be used. | ||||
| 
 | ||||
| :strong:`remote_copy` | ||||
|     Command to use for remote copy (should behave like scp). | ||||
| 
 | ||||
| :strong:`remote_exec` | ||||
|     Command to use for remote execution (should behave like ssh). | ||||
| 
 | ||||
| :strong:`remote_out_path` | ||||
|     Directory to save cdist output in on the target host. | ||||
| 
 | ||||
| :strong:`remote_shell` | ||||
|     Shell command at remote host used for remote execution. | ||||
| 
 | ||||
| :strong:`verbosity` | ||||
|     Set verbosity level. Valid values are:  | ||||
|     'ERROR', 'WARNING', 'INFO', 'VERBOSE', 'DEBUG', 'TRACE' and 'OFF'. | ||||
| 
 | ||||
| 
 | ||||
| FILES | ||||
| ----- | ||||
| ~/.cdist | ||||
|  | @ -468,6 +563,10 @@ cdist/conf | |||
| cdist/inventory | ||||
|     The distribution inventory directory. | ||||
|     This path is relative to cdist installation directory. | ||||
| /etc/cdist.cfg | ||||
|     Global cdist configuration file, if exists. | ||||
| ~/.cdist/cdist.cfg | ||||
|     Local cdist configuration file, if exists. | ||||
| 
 | ||||
| NOTES | ||||
| ----- | ||||
|  | @ -592,6 +691,10 @@ CDIST_BETA | |||
| CDIST_CACHE_PATH_PATTERN | ||||
|     Custom cache path pattern. | ||||
| 
 | ||||
| CDIST_CONFIG_FILE | ||||
|     Custom configuration file. | ||||
| 
 | ||||
| 
 | ||||
| EXIT STATUS | ||||
| ----------- | ||||
| The following exit values shall be returned: | ||||
|  |  | |||
|  | @ -22,26 +22,20 @@ | |||
| # | ||||
| 
 | ||||
| import logging | ||||
| import cdist | ||||
| import cdist.argparse | ||||
| import cdist.banner | ||||
| import cdist.config | ||||
| import cdist.install | ||||
| import cdist.shell | ||||
| import cdist.inventory | ||||
| 
 | ||||
| 
 | ||||
| def commandline(): | ||||
|     """Parse command line""" | ||||
| 
 | ||||
|     import cdist.argparse | ||||
|     import cdist.banner | ||||
|     import cdist.config | ||||
|     import cdist.install | ||||
|     import cdist.shell | ||||
|     import cdist.inventory | ||||
| 
 | ||||
|     parser = cdist.argparse.get_parsers() | ||||
|     args = parser['main'].parse_args(sys.argv[1:]) | ||||
| 
 | ||||
|     # Loglevels are handled globally in here | ||||
|     cdist.argparse.handle_loglevel(args) | ||||
| 
 | ||||
|     log.verbose("version %s" % cdist.VERSION) | ||||
|     log.trace(args) | ||||
|     parser, cfg = cdist.argparse.parse_and_configure(sys.argv[1:]) | ||||
|     args = cfg.get_args() | ||||
| 
 | ||||
|     # Work around python 3.3 bug: | ||||
|     # http://bugs.python.org/issue16308 | ||||
|  | @ -58,7 +52,6 @@ def commandline(): | |||
|         parser['main'].print_help() | ||||
|         sys.exit(0) | ||||
| 
 | ||||
|     cdist.argparse.check_beta(vars(args)) | ||||
|     args.func(args) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -74,9 +67,8 @@ if __name__ == "__main__": | |||
|     exit_code = 0 | ||||
| 
 | ||||
|     try: | ||||
|         import os | ||||
|         import re | ||||
|         import cdist | ||||
|         import os | ||||
| 
 | ||||
|         log = logging.getLogger("cdist") | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue