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]
|
||||
|
@ -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…
Reference in a new issue