parent
					
						
							
								4b2f23db62
							
						
					
				
			
			
				commit
				
					
						bdee7273af
					
				
			
		
					 11 changed files with 1800 additions and 136 deletions
				
			
		|  | @ -1,9 +1,9 @@ | ||||||
| import argparse | import argparse | ||||||
| import cdist | import cdist | ||||||
| import multiprocessing | import multiprocessing | ||||||
| import os |  | ||||||
| import logging | import logging | ||||||
| import collections | import collections | ||||||
|  | import cdist.configuration | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # set of beta sub-commands | # set of beta sub-commands | ||||||
|  | @ -115,7 +115,7 @@ def get_parsers(): | ||||||
|            '-b', '--beta', |            '-b', '--beta', | ||||||
|            help=('Enable beta functionality. '), |            help=('Enable beta functionality. '), | ||||||
|            action='store_true', dest='beta', |            action='store_true', dest='beta', | ||||||
|            default='CDIST_BETA' in os.environ) |            default=False) | ||||||
| 
 | 
 | ||||||
|     # Main subcommand parser |     # Main subcommand parser | ||||||
|     parser['main'] = argparse.ArgumentParser( |     parser['main'] = argparse.ArgumentParser( | ||||||
|  | @ -136,12 +136,18 @@ def get_parsers(): | ||||||
|            '-I', '--inventory', |            '-I', '--inventory', | ||||||
|            help=('Use specified custom inventory directory. ' |            help=('Use specified custom inventory directory. ' | ||||||
|                  'Inventory directory is set up by the following rules: ' |                  'Inventory directory is set up by the following rules: ' | ||||||
|                  'if this argument is set then specified directory is used, ' |                  'if cdist configuration resolves this value then specified ' | ||||||
|                  'if CDIST_INVENTORY_DIR env var is set then its value is ' |                  'directory is used, ' | ||||||
|                  'used, if HOME env var is set then ~/.cdist/inventory is ' |                  'if HOME env var is set then ~/.cdist/inventory is ' | ||||||
|                  'used, otherwise distribution inventory directory is used.'), |                  'used, otherwise distribution inventory directory is used.'), | ||||||
|            dest="inventory_dir", required=False) |            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 |     # Config | ||||||
|     parser['config_main'] = argparse.ArgumentParser(add_help=False) |     parser['config_main'] = argparse.ArgumentParser(add_help=False) | ||||||
|     parser['config_main'].add_argument( |     parser['config_main'].add_argument( | ||||||
|  | @ -149,7 +155,7 @@ def get_parsers(): | ||||||
|             help=('Specify custom cache path pattern. If ' |             help=('Specify custom cache path pattern. If ' | ||||||
|                   'it is not set then default hostdir is used.'), |                   'it is not set then default hostdir is used.'), | ||||||
|             dest='cache_path_pattern', |             dest='cache_path_pattern', | ||||||
|             default=os.environ.get('CDIST_CACHE_PATH_PATTERN')) |             default=None) | ||||||
|     parser['config_main'].add_argument( |     parser['config_main'].add_argument( | ||||||
|             '-c', '--conf-dir', |             '-c', '--conf-dir', | ||||||
|             help=('Add configuration directory (can be repeated, ' |             help=('Add configuration directory (can be repeated, ' | ||||||
|  | @ -195,13 +201,13 @@ def get_parsers(): | ||||||
|            '--remote-copy', |            '--remote-copy', | ||||||
|            help='Command to use for remote copy (should behave like scp).', |            help='Command to use for remote copy (should behave like scp).', | ||||||
|            action='store', dest='remote_copy', |            action='store', dest='remote_copy', | ||||||
|            default=os.environ.get('CDIST_REMOTE_COPY')) |            default=None) | ||||||
|     parser['config_main'].add_argument( |     parser['config_main'].add_argument( | ||||||
|            '--remote-exec', |            '--remote-exec', | ||||||
|            help=('Command to use for remote execution ' |            help=('Command to use for remote execution ' | ||||||
|                  '(should behave like ssh).'), |                  '(should behave like ssh).'), | ||||||
|            action='store', dest='remote_exec', |            action='store', dest='remote_exec', | ||||||
|            default=os.environ.get('CDIST_REMOTE_EXEC')) |            default=None) | ||||||
| 
 | 
 | ||||||
|     # Config |     # Config | ||||||
|     parser['config_args'] = argparse.ArgumentParser(add_help=False) |     parser['config_args'] = argparse.ArgumentParser(add_help=False) | ||||||
|  | @ -243,6 +249,7 @@ def get_parsers(): | ||||||
|              dest='tag', required=False, action="store_true", default=False) |              dest='tag', required=False, action="store_true", default=False) | ||||||
|     parser['config'] = parser['sub'].add_parser( |     parser['config'] = parser['sub'].add_parser( | ||||||
|             'config', parents=[parser['loglevel'], parser['beta'], |             'config', parents=[parser['loglevel'], parser['beta'], | ||||||
|  |                                parser['common'], | ||||||
|                                parser['config_main'], |                                parser['config_main'], | ||||||
|                                parser['inventory_common'], |                                parser['inventory_common'], | ||||||
|                                parser['config_args']]) |                                parser['config_args']]) | ||||||
|  | @ -256,12 +263,14 @@ def get_parsers(): | ||||||
|     # Inventory |     # Inventory | ||||||
|     parser['inventory'] = parser['sub'].add_parser( |     parser['inventory'] = parser['sub'].add_parser( | ||||||
|            'inventory', parents=[parser['loglevel'], parser['beta'], |            'inventory', parents=[parser['loglevel'], parser['beta'], | ||||||
|  |                                  parser['common'], | ||||||
|                                  parser['inventory_common']]) |                                  parser['inventory_common']]) | ||||||
|     parser['invsub'] = parser['inventory'].add_subparsers( |     parser['invsub'] = parser['inventory'].add_subparsers( | ||||||
|             title="Inventory commands", dest="subcommand") |             title="Inventory commands", dest="subcommand") | ||||||
| 
 | 
 | ||||||
|     parser['add-host'] = parser['invsub'].add_parser( |     parser['add-host'] = parser['invsub'].add_parser( | ||||||
|             'add-host', parents=[parser['loglevel'], parser['beta'], |             'add-host', parents=[parser['loglevel'], parser['beta'], | ||||||
|  |                                  parser['common'], | ||||||
|                                  parser['inventory_common']]) |                                  parser['inventory_common']]) | ||||||
|     parser['add-host'].add_argument( |     parser['add-host'].add_argument( | ||||||
|             'host', nargs='*', help='Host(s) to add.') |             'host', nargs='*', help='Host(s) to add.') | ||||||
|  | @ -275,6 +284,7 @@ def get_parsers(): | ||||||
| 
 | 
 | ||||||
|     parser['add-tag'] = parser['invsub'].add_parser( |     parser['add-tag'] = parser['invsub'].add_parser( | ||||||
|             'add-tag', parents=[parser['loglevel'], parser['beta'], |             'add-tag', parents=[parser['loglevel'], parser['beta'], | ||||||
|  |                                 parser['common'], | ||||||
|                                 parser['inventory_common']]) |                                 parser['inventory_common']]) | ||||||
|     parser['add-tag'].add_argument( |     parser['add-tag'].add_argument( | ||||||
|            'host', nargs='*', |            'host', nargs='*', | ||||||
|  | @ -305,6 +315,7 @@ def get_parsers(): | ||||||
| 
 | 
 | ||||||
|     parser['del-host'] = parser['invsub'].add_parser( |     parser['del-host'] = parser['invsub'].add_parser( | ||||||
|             'del-host', parents=[parser['loglevel'], parser['beta'], |             'del-host', parents=[parser['loglevel'], parser['beta'], | ||||||
|  |                                  parser['common'], | ||||||
|                                  parser['inventory_common']]) |                                  parser['inventory_common']]) | ||||||
|     parser['del-host'].add_argument( |     parser['del-host'].add_argument( | ||||||
|             'host', nargs='*', help='Host(s) to delete.') |             'host', nargs='*', help='Host(s) to delete.') | ||||||
|  | @ -321,6 +332,7 @@ def get_parsers(): | ||||||
| 
 | 
 | ||||||
|     parser['del-tag'] = parser['invsub'].add_parser( |     parser['del-tag'] = parser['invsub'].add_parser( | ||||||
|             'del-tag', parents=[parser['loglevel'], parser['beta'], |             'del-tag', parents=[parser['loglevel'], parser['beta'], | ||||||
|  |                                 parser['common'], | ||||||
|                                 parser['inventory_common']]) |                                 parser['inventory_common']]) | ||||||
|     parser['del-tag'].add_argument( |     parser['del-tag'].add_argument( | ||||||
|             'host', nargs='*', |             'host', nargs='*', | ||||||
|  | @ -355,6 +367,7 @@ def get_parsers(): | ||||||
| 
 | 
 | ||||||
|     parser['list'] = parser['invsub'].add_parser( |     parser['list'] = parser['invsub'].add_parser( | ||||||
|             'list', parents=[parser['loglevel'], parser['beta'], |             'list', parents=[parser['loglevel'], parser['beta'], | ||||||
|  |                              parser['common'], | ||||||
|                              parser['inventory_common']]) |                              parser['inventory_common']]) | ||||||
|     parser['list'].add_argument( |     parser['list'].add_argument( | ||||||
|             'host', nargs='*', help='Host(s) to list.') |             'host', nargs='*', help='Host(s) to list.') | ||||||
|  | @ -401,3 +414,23 @@ def handle_loglevel(args): | ||||||
|         args.verbose = _verbosity_level_off |         args.verbose = _verbosity_level_off | ||||||
| 
 | 
 | ||||||
|     logging.root.setLevel(_verbosity_level[args.verbose]) |     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 | from cdist.mputil import mp_pool_run, mp_sig_handler | ||||||
| import atexit | import atexit | ||||||
| import shutil | import shutil | ||||||
| 
 |  | ||||||
| import cdist | import cdist | ||||||
| import cdist.hostsource | import cdist.hostsource | ||||||
| 
 |  | ||||||
| import cdist.exec.local | import cdist.exec.local | ||||||
| import cdist.exec.remote | import cdist.exec.remote | ||||||
| 
 |  | ||||||
| import cdist.util.ipaddr as ipaddr | import cdist.util.ipaddr as ipaddr | ||||||
| 
 | import cdist.configuration | ||||||
| from cdist import core, inventory | from cdist import core, inventory | ||||||
| from cdist.util.remoteutil import inspect_ssh_mux_opts | from cdist.util.remoteutil import inspect_ssh_mux_opts | ||||||
| 
 | 
 | ||||||
|  | @ -162,8 +159,11 @@ class Config(object): | ||||||
| 
 | 
 | ||||||
|         hostcnt = 0 |         hostcnt = 0 | ||||||
| 
 | 
 | ||||||
|  |         cfg = cdist.configuration.Configuration(args) | ||||||
|  |         configuration = cfg.get_config(section='GLOBAL') | ||||||
|  | 
 | ||||||
|         if args.tag or args.all_tagged_hosts: |         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: |             if args.all_tagged_hosts: | ||||||
|                 inv_list = inventory.InventoryList( |                 inv_list = inventory.InventoryList( | ||||||
|                     hosts=None, istag=True, hostfile=None, |                     hosts=None, istag=True, hostfile=None, | ||||||
|  | @ -191,7 +191,7 @@ class Config(object): | ||||||
|             else: |             else: | ||||||
|                 # if configuring by host then check inventory for tags |                 # if configuring by host then check inventory for tags | ||||||
|                 host = entry |                 host = entry | ||||||
|                 inventory.determine_default_inventory_dir(args) |                 inventory.determine_default_inventory_dir(args, configuration) | ||||||
|                 inv_list = inventory.InventoryList( |                 inv_list = inventory.InventoryList( | ||||||
|                     hosts=(host,), db_basedir=args.inventory_dir) |                     hosts=(host,), db_basedir=args.inventory_dir) | ||||||
|                 inv = tuple(inv_list.entries()) |                 inv = tuple(inv_list.entries()) | ||||||
|  | @ -208,14 +208,16 @@ class Config(object): | ||||||
| 
 | 
 | ||||||
|             hostcnt += 1 |             hostcnt += 1 | ||||||
|             if args.parallel: |             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 " |                 log.trace(("Args for multiprocessing operation " | ||||||
|                            "for host {}: {}".format(host, pargs))) |                            "for host {}: {}".format(host, pargs))) | ||||||
|                 process_args.append(pargs) |                 process_args.append(pargs) | ||||||
|             else: |             else: | ||||||
|                 try: |                 try: | ||||||
|                     cls.onehost(host, host_tags, host_base_path, hostdir, |                     cls.onehost(host, host_tags, host_base_path, hostdir, | ||||||
|                                 args, parallel=False) |                                 args, parallel=False, | ||||||
|  |                                 configuration=configuration) | ||||||
|                 except cdist.Error as e: |                 except cdist.Error as e: | ||||||
|                     failed_hosts.append(host) |                     failed_hosts.append(host) | ||||||
|         if args.parallel and len(process_args) == 1: |         if args.parallel and len(process_args) == 1: | ||||||
|  | @ -281,7 +283,7 @@ class Config(object): | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def onehost(cls, host, host_tags, host_base_path, host_dir_name, args, |     def onehost(cls, host, host_tags, host_base_path, host_dir_name, args, | ||||||
|                 parallel): |                 parallel, configuration): | ||||||
|         """Configure ONE system. |         """Configure ONE system. | ||||||
|            If operating in parallel then return tuple (host, True|False, ) |            If operating in parallel then return tuple (host, True|False, ) | ||||||
|            so that main process knows for which host function was successful. |            so that main process knows for which host function was successful. | ||||||
|  | @ -308,7 +310,8 @@ class Config(object): | ||||||
|                 initial_manifest=args.manifest, |                 initial_manifest=args.manifest, | ||||||
|                 add_conf_dirs=args.conf_dir, |                 add_conf_dirs=args.conf_dir, | ||||||
|                 cache_path_pattern=args.cache_path_pattern, |                 cache_path_pattern=args.cache_path_pattern, | ||||||
|                 quiet_mode=args.quiet) |                 quiet_mode=args.quiet, | ||||||
|  |                 configuration=configuration) | ||||||
| 
 | 
 | ||||||
|             remote = cdist.exec.remote.Remote( |             remote = cdist.exec.remote.Remote( | ||||||
|                 target_host=target_host, |                 target_host=target_host, | ||||||
|  | @ -316,7 +319,8 @@ class Config(object): | ||||||
|                 remote_copy=remote_copy, |                 remote_copy=remote_copy, | ||||||
|                 base_path=args.remote_out_path, |                 base_path=args.remote_out_path, | ||||||
|                 quiet_mode=args.quiet, |                 quiet_mode=args.quiet, | ||||||
|                 archiving_mode=args.use_archiving) |                 archiving_mode=args.use_archiving, | ||||||
|  |                 configuration=configuration) | ||||||
| 
 | 
 | ||||||
|             cleanup_cmds = [] |             cleanup_cmds = [] | ||||||
|             if cleanup_cmd: |             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, |                  initial_manifest=None, | ||||||
|                  add_conf_dirs=None, |                  add_conf_dirs=None, | ||||||
|                  cache_path_pattern=None, |                  cache_path_pattern=None, | ||||||
|                  quiet_mode=False): |                  quiet_mode=False, | ||||||
|  |                  configuration=None): | ||||||
| 
 | 
 | ||||||
|         self.target_host = target_host |         self.target_host = target_host | ||||||
|         if target_host_tags is None: |         if target_host_tags is None: | ||||||
|  | @ -70,6 +71,10 @@ class Local(object): | ||||||
|         self._add_conf_dirs = add_conf_dirs |         self._add_conf_dirs = add_conf_dirs | ||||||
|         self.cache_path_pattern = cache_path_pattern |         self.cache_path_pattern = cache_path_pattern | ||||||
|         self.quiet_mode = quiet_mode |         self.quiet_mode = quiet_mode | ||||||
|  |         if configuration: | ||||||
|  |             self.configuration = configuration | ||||||
|  |         else: | ||||||
|  |             self.configuration = {} | ||||||
| 
 | 
 | ||||||
|         self._init_log() |         self._init_log() | ||||||
|         self._init_permissions() |         self._init_permissions() | ||||||
|  | @ -142,10 +147,12 @@ class Local(object): | ||||||
|             self.conf_dirs.append(self.home_dir) |             self.conf_dirs.append(self.home_dir) | ||||||
| 
 | 
 | ||||||
|         # Add directories defined in the CDIST_PATH environment variable |         # Add directories defined in the CDIST_PATH environment variable | ||||||
|         if 'CDIST_PATH' in os.environ: |         # if 'CDIST_PATH' in os.environ: | ||||||
|             cdist_path_dirs = re.split(r'(?<!\\):', os.environ['CDIST_PATH']) |         #     cdist_path_dirs = re.split(r'(?<!\\):', os.environ['CDIST_PATH']) | ||||||
|             cdist_path_dirs.reverse() |         #     cdist_path_dirs.reverse() | ||||||
|             self.conf_dirs.extend(cdist_path_dirs) |         #     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 |         # Add command line supplied directories | ||||||
|         if self._add_conf_dirs: |         if self._add_conf_dirs: | ||||||
|  | @ -175,12 +182,11 @@ class Local(object): | ||||||
|     def _init_cache_dir(self, cache_dir): |     def _init_cache_dir(self, cache_dir): | ||||||
|         if cache_dir: |         if cache_dir: | ||||||
|             self.cache_path = cache_dir |             self.cache_path = cache_dir | ||||||
|  |         elif self.home_dir: | ||||||
|  |             self.cache_path = os.path.join(self.home_dir, "cache") | ||||||
|         else: |         else: | ||||||
|             if self.home_dir: |             raise cdist.Error( | ||||||
|                 self.cache_path = os.path.join(self.home_dir, "cache") |                 "No homedir setup and no cache dir location given") | ||||||
|             else: |  | ||||||
|                 raise cdist.Error( |  | ||||||
|                         "No homedir setup and no cache dir location given") |  | ||||||
| 
 | 
 | ||||||
|     def rmdir(self, path): |     def rmdir(self, path): | ||||||
|         """Remove directory on the local side.""" |         """Remove directory on the local side.""" | ||||||
|  | @ -258,7 +264,7 @@ class Local(object): | ||||||
|             self.log.debug('%s is executable, running it', script) |             self.log.debug('%s is executable, running it', script) | ||||||
|             command = [script] |             command = [script] | ||||||
|         else: |         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', |             self.log.debug('%s is NOT executable, running it with %s', | ||||||
|                            script, " ".join(command)) |                            script, " ".join(command)) | ||||||
|             command.append(script) |             command.append(script) | ||||||
|  |  | ||||||
|  | @ -62,7 +62,8 @@ class Remote(object): | ||||||
|                  remote_copy, |                  remote_copy, | ||||||
|                  base_path=None, |                  base_path=None, | ||||||
|                  quiet_mode=None, |                  quiet_mode=None, | ||||||
|                  archiving_mode=None): |                  archiving_mode=None, | ||||||
|  |                  configuration=None): | ||||||
|         self.target_host = target_host |         self.target_host = target_host | ||||||
|         self._exec = remote_exec |         self._exec = remote_exec | ||||||
|         self._copy = remote_copy |         self._copy = remote_copy | ||||||
|  | @ -73,6 +74,10 @@ class Remote(object): | ||||||
|             self.base_path = "/var/lib/cdist" |             self.base_path = "/var/lib/cdist" | ||||||
|         self.quiet_mode = quiet_mode |         self.quiet_mode = quiet_mode | ||||||
|         self.archiving_mode = archiving_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.conf_path = os.path.join(self.base_path, "conf") | ||||||
|         self.object_path = os.path.join(self.base_path, "object") |         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) |         command.append(script) | ||||||
| 
 | 
 | ||||||
|         return self.run(command, env, return_output) |         return self.run(command, env, return_output) | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ import os | ||||||
| import os.path | import os.path | ||||||
| import itertools | import itertools | ||||||
| import sys | import sys | ||||||
|  | import cdist.configuration | ||||||
| from cdist.hostsource import hostfile_process_line | from cdist.hostsource import hostfile_process_line | ||||||
| 
 | 
 | ||||||
| DIST_INVENTORY_DB_NAME = "inventory" | 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)) |     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 |     # The order of inventory dir setting by decreasing priority | ||||||
|     # 1. inventory_dir argument |     # 1. inventory_dir from configuration | ||||||
|     # 2. CDIST_INVENTORY_DIR env var if set |     # 2. ~/.cdist/inventory if HOME env var is set | ||||||
|     # 3. ~/.cdist/inventory if HOME env var is set |     # 3. distribution inventory directory | ||||||
|     # 4. distribution inventory directory |     inventory_dir_set = False | ||||||
|     if not args.inventory_dir: |     if 'inventory_dir' in configuration: | ||||||
|         if 'CDIST_INVENTORY_DIR' in os.environ: |         val = configuration['inventory_dir'] | ||||||
|             args.inventory_dir = os.environ['CDIST_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: |         else: | ||||||
|             home = cdist.home_dir() |             args.inventory_dir = dist_inventory_db | ||||||
|             if home: |  | ||||||
|                 args.inventory_dir = os.path.join(home, DIST_INVENTORY_DB_NAME) |  | ||||||
|             else: |  | ||||||
|                 args.inventory_dir = dist_inventory_db |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def contains_all(big, little): | def contains_all(big, little): | ||||||
|  | @ -80,8 +83,12 @@ def rstrip_nl(s): | ||||||
| class Inventory(object): | class Inventory(object): | ||||||
|     """Inventory main class""" |     """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 |         self.db_basedir = db_basedir | ||||||
|  |         if configuration: | ||||||
|  |             self.configuration = configuration | ||||||
|  |         else: | ||||||
|  |             self.configuration = {} | ||||||
|         self.log = logging.getLogger("inventory") |         self.log = logging.getLogger("inventory") | ||||||
|         self.init_db() |         self.init_db() | ||||||
| 
 | 
 | ||||||
|  | @ -171,7 +178,10 @@ class Inventory(object): | ||||||
|         log = logging.getLogger("inventory") |         log = logging.getLogger("inventory") | ||||||
|         if 'taglist' in args: |         if 'taglist' in args: | ||||||
|             args.taglist = cls.strlist_to_list(args.taglist) |             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.debug("Using inventory: {}".format(args.inventory_dir)) | ||||||
|         log.trace("Inventory args: {}".format(vars(args))) |         log.trace("Inventory args: {}".format(vars(args))) | ||||||
|  | @ -182,23 +192,26 @@ class Inventory(object): | ||||||
|                               hostfile=args.hostfile, |                               hostfile=args.hostfile, | ||||||
|                               db_basedir=args.inventory_dir, |                               db_basedir=args.inventory_dir, | ||||||
|                               list_only_host=args.list_only_host, |                               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": |         elif args.subcommand == "add-host": | ||||||
|             c = InventoryHost(hosts=args.host, hostfile=args.hostfile, |             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": |         elif args.subcommand == "del-host": | ||||||
|             c = InventoryHost(hosts=args.host, hostfile=args.hostfile, |             c = InventoryHost(hosts=args.host, hostfile=args.hostfile, | ||||||
|                               all=args.all, db_basedir=args.inventory_dir, |                               all=args.all, db_basedir=args.inventory_dir, | ||||||
|                               action="del") |                               action="del", configuration=configuration) | ||||||
|         elif args.subcommand == "add-tag": |         elif args.subcommand == "add-tag": | ||||||
|             c = InventoryTag(hosts=args.host, tags=args.taglist, |             c = InventoryTag(hosts=args.host, tags=args.taglist, | ||||||
|                              hostfile=args.hostfile, tagfile=args.tagfile, |                              hostfile=args.hostfile, tagfile=args.tagfile, | ||||||
|                              db_basedir=args.inventory_dir) |                              db_basedir=args.inventory_dir, | ||||||
|  |                              configuration=configuration) | ||||||
|         elif args.subcommand == "del-tag": |         elif args.subcommand == "del-tag": | ||||||
|             c = InventoryTag(hosts=args.host, tags=args.taglist, |             c = InventoryTag(hosts=args.host, tags=args.taglist, | ||||||
|                              hostfile=args.hostfile, tagfile=args.tagfile, |                              hostfile=args.hostfile, tagfile=args.tagfile, | ||||||
|                              all=args.all, db_basedir=args.inventory_dir, |                              all=args.all, db_basedir=args.inventory_dir, | ||||||
|                              action="del") |                              action="del", configuration=configuration) | ||||||
|         else: |         else: | ||||||
|             raise cdist.Error("Unknown inventory command \'{}\'".format( |             raise cdist.Error("Unknown inventory command \'{}\'".format( | ||||||
|                         args.subcommand)) |                         args.subcommand)) | ||||||
|  | @ -208,8 +221,8 @@ class Inventory(object): | ||||||
| class InventoryList(Inventory): | class InventoryList(Inventory): | ||||||
|     def __init__(self, hosts=None, istag=False, hostfile=None, |     def __init__(self, hosts=None, istag=False, hostfile=None, | ||||||
|                  list_only_host=False, has_all_tags=False, |                  list_only_host=False, has_all_tags=False, | ||||||
|                  db_basedir=dist_inventory_db): |                  db_basedir=dist_inventory_db, configuration=None): | ||||||
|         super().__init__(db_basedir) |         super().__init__(db_basedir, configuration) | ||||||
|         self.hosts = hosts |         self.hosts = hosts | ||||||
|         self.istag = istag |         self.istag = istag | ||||||
|         self.hostfile = hostfile |         self.hostfile = hostfile | ||||||
|  | @ -274,8 +287,9 @@ class InventoryList(Inventory): | ||||||
| 
 | 
 | ||||||
| class InventoryHost(Inventory): | class InventoryHost(Inventory): | ||||||
|     def __init__(self, hosts=None, hostfile=None, |     def __init__(self, hosts=None, hostfile=None, | ||||||
|                  db_basedir=dist_inventory_db, all=False, action="add"): |                  db_basedir=dist_inventory_db, all=False, action="add", | ||||||
|         super().__init__(db_basedir) |                  configuration=None): | ||||||
|  |         super().__init__(db_basedir, configuration) | ||||||
|         self.actions = ("add", "del") |         self.actions = ("add", "del") | ||||||
|         if action not in self.actions: |         if action not in self.actions: | ||||||
|             raise cdist.Error("Invalid action \'{}\', valid actions are:" |             raise cdist.Error("Invalid action \'{}\', valid actions are:" | ||||||
|  | @ -323,8 +337,9 @@ class InventoryHost(Inventory): | ||||||
| 
 | 
 | ||||||
| class InventoryTag(Inventory): | class InventoryTag(Inventory): | ||||||
|     def __init__(self, hosts=None, tags=None, hostfile=None, tagfile=None, |     def __init__(self, hosts=None, tags=None, hostfile=None, tagfile=None, | ||||||
|                  db_basedir=dist_inventory_db, all=False, action="add"): |                  db_basedir=dist_inventory_db, all=False, action="add", | ||||||
|         super().__init__(db_basedir) |                  configuration=None): | ||||||
|  |         super().__init__(db_basedir, configuration) | ||||||
|         self.actions = ("add", "del") |         self.actions = ("add", "del") | ||||||
|         if action not in self.actions: |         if action not in self.actions: | ||||||
|             raise cdist.Error("Invalid action \'{}\', valid actions are:" |             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 random | ||||||
| import time | import time | ||||||
| import datetime | import datetime | ||||||
|  | import argparse | ||||||
| 
 | 
 | ||||||
| import cdist | import cdist | ||||||
|  | import cdist.configuration as cc | ||||||
| from cdist import test | from cdist import test | ||||||
| from cdist.exec import local | from cdist.exec import local | ||||||
| 
 | 
 | ||||||
|  | @ -165,6 +167,9 @@ class LocalTestCase(test.CdistTestCase): | ||||||
| 
 | 
 | ||||||
|         os.environ['CDIST_PATH'] = conf_dir |         os.environ['CDIST_PATH'] = conf_dir | ||||||
| 
 | 
 | ||||||
|  |         configuration = cc.Configuration(argparse.Namespace(), | ||||||
|  |                                          env=os.environ) | ||||||
|  | 
 | ||||||
|         link_test_local = local.Local( |         link_test_local = local.Local( | ||||||
|             target_host=( |             target_host=( | ||||||
|                 'localhost', |                 'localhost', | ||||||
|  | @ -174,6 +179,7 @@ class LocalTestCase(test.CdistTestCase): | ||||||
|             base_root_path=self.host_base_path, |             base_root_path=self.host_base_path, | ||||||
|             host_dir_name=self.hostdir, |             host_dir_name=self.hostdir, | ||||||
|             exec_path=test.cdist_exec_path, |             exec_path=test.cdist_exec_path, | ||||||
|  |             configuration=configuration | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         link_test_local._create_conf_path_and_link_conf_dirs() |         link_test_local._create_conf_path_and_link_conf_dirs() | ||||||
|  |  | ||||||
|  | @ -15,43 +15,45 @@ SYNOPSIS | ||||||
| 
 | 
 | ||||||
|     cdist banner [-h] [-q] [-v] |     cdist banner [-h] [-q] [-v] | ||||||
| 
 | 
 | ||||||
|     cdist config [-h] [-q] [-v] [-b] [-C CACHE_PATH_PATTERN] [-c CONF_DIR] |     cdist config [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||||
|                  [-i MANIFEST] [-j [JOBS]] [-n] [-o OUT_PATH] |                  [-C CACHE_PATH_PATTERN] [-c CONF_DIR] [-i MANIFEST] | ||||||
|                  [-R [{tar,tgz,tbz2,txz}]] [-r REMOTE_OUT_DIR] |                  [-j [JOBS]] [-n] [-o OUT_PATH] [-R [{tar,tgz,tbz2,txz}]] | ||||||
|                  [--remote-copy REMOTE_COPY] [--remote-exec REMOTE_EXEC] |                  [-r REMOTE_OUT_DIR] [--remote-copy REMOTE_COPY] | ||||||
|                  [-I INVENTORY_DIR] [-A] [-a] [-f HOSTFILE] [-p [HOST_MAX]] |                  [--remote-exec REMOTE_EXEC] [-I INVENTORY_DIR] [-A] [-a] | ||||||
|                  [-s] [-t] |                  [-f HOSTFILE] [-p [HOST_MAX]] [-s] [-t] | ||||||
|                  [host [host ...]]  |                  [host [host ...]]  | ||||||
| 
 | 
 | ||||||
|     cdist install [-h] [-q] [-v] [-b] [-C CACHE_PATH_PATTERN] [-c CONF_DIR] |     cdist install [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||||
|                   [-i MANIFEST] [-j [JOBS]] [-n] [-o OUT_PATH] |                   [-C CACHE_PATH_PATTERN] [-c CONF_DIR] [-i MANIFEST] | ||||||
|                   [-R [{tar,tgz,tbz2,txz}]] [-r REMOTE_OUT_DIR] |                   [-j [JOBS]] [-n] [-o OUT_PATH] [-R [{tar,tgz,tbz2,txz}]] | ||||||
|                   [--remote-copy REMOTE_COPY] [--remote-exec REMOTE_EXEC] |                   [-r REMOTE_OUT_DIR] [--remote-copy REMOTE_COPY] | ||||||
|                   [-I INVENTORY_DIR] [-A] [-a] [-f HOSTFILE] [-p [HOST_MAX]] |                   [--remote-exec REMOTE_EXEC] [-I INVENTORY_DIR] [-A] [-a] | ||||||
|                   [-s] [-t] |                   [-f HOSTFILE] [-p [HOST_MAX]] [-s] [-t] | ||||||
|                   [host [host ...]]  |                   [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} ... |                     {add-host,add-tag,del-host,del-tag,list} ... | ||||||
| 
 | 
 | ||||||
|     cdist inventory add-host [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] |     cdist inventory add-host [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||||
|                              [-f HOSTFILE] |                              [-I INVENTORY_DIR] [-f HOSTFILE] | ||||||
|                              [host [host ...]] |                              [host [host ...]] | ||||||
| 
 | 
 | ||||||
|     cdist inventory add-tag [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] |     cdist inventory add-tag [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||||
|                             [-f HOSTFILE] [-T TAGFILE] [-t TAGLIST] |                             [-I INVENTORY_DIR] [-f HOSTFILE] [-T TAGFILE] | ||||||
|  |                             [-t TAGLIST] | ||||||
|                             [host [host ...]] |                             [host [host ...]] | ||||||
| 
 | 
 | ||||||
|     cdist inventory del-host [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] [-a] |     cdist inventory del-host [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||||
|                              [-f HOSTFILE] |                              [-I INVENTORY_DIR] [-a] [-f HOSTFILE] | ||||||
|                              [host [host ...]] |                              [host [host ...]] | ||||||
| 
 | 
 | ||||||
|     cdist inventory del-tag [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] [-a] |     cdist inventory del-tag [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||||
|                             [-f HOSTFILE] [-T TAGFILE] [-t TAGLIST] |                             [-I INVENTORY_DIR] [-a] [-f HOSTFILE] | ||||||
|  |                             [-T TAGFILE] [-t TAGLIST] | ||||||
|                             [host [host ...]] |                             [host [host ...]] | ||||||
| 
 | 
 | ||||||
|     cdist inventory list [-h] [-q] [-v] [-b] [-I INVENTORY_DIR] [-a] |     cdist inventory list [-h] [-q] [-v] [-b] [-g CONFIG_FILE] | ||||||
|                          [-f HOSTFILE] [-H] [-t] |                          [-I INVENTORY_DIR] [-a] [-f HOSTFILE] [-H] [-t] | ||||||
|                          [host [host ...]] |                          [host [host ...]] | ||||||
| 
 | 
 | ||||||
|     cdist shell [-h] [-q] [-v] [-s SHELL] |     cdist shell [-h] [-q] [-v] [-s SHELL] | ||||||
|  | @ -133,15 +135,18 @@ Install command is currently in beta. | ||||||
|     read hosts from stdin. For the file format see |     read hosts from stdin. For the file format see | ||||||
|     :strong:`HOSTFILE FORMAT` below. |     :strong:`HOSTFILE FORMAT` below. | ||||||
| 
 | 
 | ||||||
|  | .. option:: -g CONFIG_FILE, --config-file CONFIG_FILE | ||||||
|  | 
 | ||||||
|  |     Use specified custom configuration file. | ||||||
|  | 
 | ||||||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||||
| 
 | 
 | ||||||
|     Use specified custom inventory directory. Inventory |     Use specified custom inventory directory. Inventory | ||||||
|     directory is set up by the following rules: if this |     directory is set up by the following rules: if cdist  | ||||||
|     argument is set then specified directory is used, if |     configuration resolves this value then specified | ||||||
|     CDIST_INVENTORY_DIR env var is set then its value is |     directory is used, if HOME env var is set then | ||||||
|     used, if HOME env var is set then ~/.cdit/inventory is |     ~/.cdit/inventory is used, otherwise distribution | ||||||
|     used, otherwise distribution inventory directory is |     inventory directory is used. | ||||||
|     used. |  | ||||||
| 
 | 
 | ||||||
| .. option:: -i MANIFEST, --initial-manifest MANIFEST | .. 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 |     host or host file is specified then, by default, read | ||||||
|     from stdin. Hostfile format is the same as config hostfile format. |     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 | .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||||
| 
 | 
 | ||||||
|     Use specified custom inventory directory. Inventory |     Use specified custom inventory directory. Inventory | ||||||
|     directory is set up by the following rules: if this |     directory is set up by the following rules: if cdist  | ||||||
|     argument is set then specified directory is used, if |     configuration resolves this value then specified | ||||||
|     CDIST_INVENTORY_DIR env var is set then its value is |     directory is used, if HOME env var is set then | ||||||
|     used, if HOME env var is set then ~/.cdist/inventory is |     ~/.cdit/inventory is used, otherwise distribution | ||||||
|     used, otherwise distribution inventory directory is |     inventory directory is used. | ||||||
|     used. |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| INVENTORY ADD-TAG | INVENTORY ADD-TAG | ||||||
|  | @ -287,15 +294,18 @@ Add tag(s) to inventory database. | ||||||
|     are specified then tags are read from stdin and are |     are specified then tags are read from stdin and are | ||||||
|     added to all hosts. Hostfile format is the same as config hostfile format. |     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 | .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||||
| 
 | 
 | ||||||
|     Use specified custom inventory directory. Inventory |     Use specified custom inventory directory. Inventory | ||||||
|     directory is set up by the following rules: if this |     directory is set up by the following rules: if cdist  | ||||||
|     argument is set then specified directory is used, if |     configuration resolves this value then specified | ||||||
|     CDIST_INVENTORY_DIR env var is set then its value is |     directory is used, if HOME env var is set then | ||||||
|     used, if HOME env var is set then ~/.cdist/inventory is |     ~/.cdit/inventory is used, otherwise distribution | ||||||
|     used, otherwise distribution inventory directory is |     inventory directory is used. | ||||||
|     used. |  | ||||||
| 
 | 
 | ||||||
| .. option:: -T TAGFILE, --tag-file TAGFILE | .. 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 |     host or host file is specified then, by default, read | ||||||
|     from stdin. Hostfile format is the same as config hostfile format. |     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 | .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||||
| 
 | 
 | ||||||
|     Use specified custom inventory directory. Inventory |     Use specified custom inventory directory. Inventory | ||||||
|     directory is set up by the following rules: if this |     directory is set up by the following rules: if cdist  | ||||||
|     argument is set then specified directory is used, if |     configuration resolves this value then specified | ||||||
|     CDIST_INVENTORY_DIR env var is set then its value is |     directory is used, if HOME env var is set then | ||||||
|     used, if HOME env var is set then ~/.cdist/inventory is |     ~/.cdit/inventory is used, otherwise distribution | ||||||
|     used, otherwise distribution inventory directory is |     inventory directory is used. | ||||||
|     used. |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| INVENTORY DEL-TAG | INVENTORY DEL-TAG | ||||||
|  | @ -372,15 +385,18 @@ Delete tag(s) from inventory database. | ||||||
|     from stdin and are deleted from all hosts. Hostfile |     from stdin and are deleted from all hosts. Hostfile | ||||||
|     format is the same as config hostfile format. |     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 | .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||||
| 
 | 
 | ||||||
|     Use specified custom inventory directory. Inventory |     Use specified custom inventory directory. Inventory | ||||||
|     directory is set up by the following rules: if this |     directory is set up by the following rules: if cdist  | ||||||
|     argument is set then specified directory is used, if |     configuration resolves this value then specified | ||||||
|     CDIST_INVENTORY_DIR env var is set then its value is |     directory is used, if HOME env var is set then | ||||||
|     used, if HOME env var is set then ~/.cdist/inventory is |     ~/.cdit/inventory is used, otherwise distribution | ||||||
|     used, otherwise distribution inventory directory is |     inventory directory is used. | ||||||
|     used. |  | ||||||
| 
 | 
 | ||||||
| .. option:: -T TAGFILE, --tag-file TAGFILE | .. option:: -T TAGFILE, --tag-file TAGFILE | ||||||
| 
 | 
 | ||||||
|  | @ -421,6 +437,10 @@ List inventory database. | ||||||
|     host or host file is specified then, by default, list |     host or host file is specified then, by default, list | ||||||
|     all. Hostfile format is the same as config hostfile format. |     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 | .. option:: -H, --host-only | ||||||
| 
 | 
 | ||||||
|     Suppress tags listing. |     Suppress tags listing. | ||||||
|  | @ -428,12 +448,11 @@ List inventory database. | ||||||
| .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | .. option:: -I INVENTORY_DIR, --inventory INVENTORY_DIR | ||||||
| 
 | 
 | ||||||
|     Use specified custom inventory directory. Inventory |     Use specified custom inventory directory. Inventory | ||||||
|     directory is set up by the following rules: if this |     directory is set up by the following rules: if cdist  | ||||||
|     argument is set then specified directory is used, if |     configuration resolves this value then specified | ||||||
|     CDIST_INVENTORY_DIR env var is set then its value is |     directory is used, if HOME env var is set then | ||||||
|     used, if HOME env var is set then ~/.cdist/inventory is |     ~/.cdit/inventory is used, otherwise distribution | ||||||
|     used, otherwise distribution inventory directory is |     inventory directory is used. | ||||||
|     used. |  | ||||||
| 
 | 
 | ||||||
| .. option:: -t, --tag | .. option:: -t, --tag | ||||||
| 
 | 
 | ||||||
|  | @ -454,6 +473,82 @@ usage. Its primary use is for debugging type parameters. | ||||||
|     be POSIX compatible shell. |     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 | FILES | ||||||
| ----- | ----- | ||||||
| ~/.cdist | ~/.cdist | ||||||
|  | @ -468,6 +563,10 @@ cdist/conf | ||||||
| cdist/inventory | cdist/inventory | ||||||
|     The distribution inventory directory. |     The distribution inventory directory. | ||||||
|     This path is relative to cdist installation 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 | NOTES | ||||||
| ----- | ----- | ||||||
|  | @ -592,6 +691,10 @@ CDIST_BETA | ||||||
| CDIST_CACHE_PATH_PATTERN | CDIST_CACHE_PATH_PATTERN | ||||||
|     Custom cache path pattern. |     Custom cache path pattern. | ||||||
| 
 | 
 | ||||||
|  | CDIST_CONFIG_FILE | ||||||
|  |     Custom configuration file. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| EXIT STATUS | EXIT STATUS | ||||||
| ----------- | ----------- | ||||||
| The following exit values shall be returned: | The following exit values shall be returned: | ||||||
|  |  | ||||||
|  | @ -22,26 +22,20 @@ | ||||||
| # | # | ||||||
| 
 | 
 | ||||||
| import logging | import logging | ||||||
|  | import cdist | ||||||
|  | import cdist.argparse | ||||||
|  | import cdist.banner | ||||||
|  | import cdist.config | ||||||
|  | import cdist.install | ||||||
|  | import cdist.shell | ||||||
|  | import cdist.inventory | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def commandline(): | def commandline(): | ||||||
|     """Parse command line""" |     """Parse command line""" | ||||||
| 
 | 
 | ||||||
|     import cdist.argparse |     parser, cfg = cdist.argparse.parse_and_configure(sys.argv[1:]) | ||||||
|     import cdist.banner |     args = cfg.get_args() | ||||||
|     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) |  | ||||||
| 
 | 
 | ||||||
|     # Work around python 3.3 bug: |     # Work around python 3.3 bug: | ||||||
|     # http://bugs.python.org/issue16308 |     # http://bugs.python.org/issue16308 | ||||||
|  | @ -58,7 +52,6 @@ def commandline(): | ||||||
|         parser['main'].print_help() |         parser['main'].print_help() | ||||||
|         sys.exit(0) |         sys.exit(0) | ||||||
| 
 | 
 | ||||||
|     cdist.argparse.check_beta(vars(args)) |  | ||||||
|     args.func(args) |     args.func(args) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -74,9 +67,8 @@ if __name__ == "__main__": | ||||||
|     exit_code = 0 |     exit_code = 0 | ||||||
| 
 | 
 | ||||||
|     try: |     try: | ||||||
|         import os |  | ||||||
|         import re |         import re | ||||||
|         import cdist |         import os | ||||||
| 
 | 
 | ||||||
|         log = logging.getLogger("cdist") |         log = logging.getLogger("cdist") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue