123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158 |
- # -*- coding: utf-8 -*-
- '''
- :codeauthor: Denys Havrysh <denys.gavrysh@gmail.com>
- '''
- # Import python libs
- from __future__ import absolute_import, print_function, unicode_literals
- import os
- import shutil
- import tempfile
- # Import Salt Testing Libs
- from tests.support.unit import skipIf, TestCase
- from tests.support.runtests import RUNTIME_VARS
- from tests.support.mock import (
- MagicMock,
- patch,
- )
- # Import Salt Libs
- import salt.log.setup as log
- import salt.config
- import salt.syspaths
- import salt.utils.parsers
- import salt.utils.platform
- import pytest
- class ErrorMock(object): # pylint: disable=too-few-public-methods
- '''
- Error handling
- '''
- def __init__(self):
- '''
- init
- '''
- self.msg = None
- def error(self, msg):
- '''
- Capture error message
- '''
- self.msg = msg
- class LogSetupMock(object):
- '''
- Logger setup
- '''
- def __init__(self):
- '''
- init
- '''
- self.log_level = None
- self.log_file = None
- self.log_level_logfile = None
- self.config = {}
- self.temp_log_level = None
- def setup_console_logger(self, log_level='error', **kwargs): # pylint: disable=unused-argument
- '''
- Set console loglevel
- '''
- self.log_level = log_level
- def setup_extended_logging(self, opts):
- '''
- Set opts
- '''
- self.config = opts
- def setup_logfile_logger(self, logfile, loglevel, **kwargs): # pylint: disable=unused-argument
- '''
- Set logfile and loglevel
- '''
- self.log_file = logfile
- self.log_level_logfile = loglevel
- @staticmethod
- def get_multiprocessing_logging_queue(): # pylint: disable=invalid-name
- '''
- Mock
- '''
- import multiprocessing
- return multiprocessing.Queue()
- def setup_multiprocessing_logging_listener(self, opts, *args): # pylint: disable=invalid-name,unused-argument
- '''
- Set opts
- '''
- self.config = opts
- def setup_temp_logger(self, log_level='error'):
- '''
- Set temp loglevel
- '''
- self.temp_log_level = log_level
- class ObjectView(object): # pylint: disable=too-few-public-methods
- '''
- Dict object view
- '''
- def __init__(self, d):
- self.__dict__ = d
- @pytest.mark.destructive_test
- @pytest.mark.skip_if_not_root
- class ParserBase(object):
- '''
- Unit Tests for Log Level Mixin with Salt parsers
- '''
- args = []
- skip_console_logging_config = False
- log_setup = None
- # Set config option names
- loglevel_config_setting_name = 'log_level'
- logfile_config_setting_name = 'log_file'
- logfile_loglevel_config_setting_name = 'log_level_logfile' # pylint: disable=invalid-name
- @classmethod
- def setUpClass(cls):
- cls.root_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
- @classmethod
- def tearDownClass(cls):
- shutil.rmtree(cls.root_dir, ignore_errors=True)
- def setup_log(self):
- '''
- Mock logger functions
- '''
- testing_config = self.default_config.copy()
- testing_config['root_dir'] = self.root_dir
- for name in ('pki_dir', 'cachedir'):
- testing_config[name] = name
- testing_config[self.logfile_config_setting_name] = getattr(self, self.logfile_config_setting_name, self.log_file)
- self.testing_config = testing_config
- self.addCleanup(setattr, self, 'testing_config', None)
- self.log_setup = LogSetupMock()
- patcher = patch.multiple(
- log,
- setup_console_logger=self.log_setup.setup_console_logger,
- setup_extended_logging=self.log_setup.setup_extended_logging,
- setup_logfile_logger=self.log_setup.setup_logfile_logger,
- get_multiprocessing_logging_queue=self.log_setup.get_multiprocessing_logging_queue,
- setup_multiprocessing_logging_listener=self.log_setup.setup_multiprocessing_logging_listener,
- setup_temp_logger=self.log_setup.setup_temp_logger
- )
- patcher.start()
- self.addCleanup(patcher.stop)
- self.addCleanup(setattr, self, 'log_setup', None)
- # log level configuration tests
- def test_get_log_level_cli(self):
- '''
- Tests that log level match command-line specified value
- '''
- # Set defaults
- default_log_level = self.testing_config[self.loglevel_config_setting_name]
- # Set log level in CLI
- log_level = 'critical'
- args = ['--log-level', log_level] + self.args
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=self.testing_config)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- console_log_level = getattr(parser.options, self.loglevel_config_setting_name)
- # Check console log level setting
- self.assertEqual(console_log_level, log_level)
- # Check console loggger log level
- self.assertEqual(self.log_setup.log_level, log_level)
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.temp_log_level, log_level)
- # Check log file logger log level
- self.assertEqual(self.log_setup.log_level_logfile, default_log_level)
- def test_get_log_level_config(self):
- '''
- Tests that log level match the configured value
- '''
- args = self.args
- # Set log level in config
- log_level = 'info'
- opts = self.testing_config.copy()
- opts.update({self.loglevel_config_setting_name: log_level})
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=opts)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- console_log_level = getattr(parser.options, self.loglevel_config_setting_name)
- # Check console log level setting
- self.assertEqual(console_log_level, log_level)
- # Check console loggger log level
- self.assertEqual(self.log_setup.log_level, log_level)
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file logger log level
- self.assertEqual(self.log_setup.log_level_logfile, log_level)
- def test_get_log_level_default(self):
- '''
- Tests that log level match the default value
- '''
- # Set defaults
- log_level = default_log_level = self.testing_config[self.loglevel_config_setting_name]
- args = self.args
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=self.testing_config)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- console_log_level = getattr(parser.options, self.loglevel_config_setting_name)
- # Check log level setting
- self.assertEqual(console_log_level, log_level)
- # Check console loggger log level
- self.assertEqual(self.log_setup.log_level, log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file logger
- self.assertEqual(self.log_setup.log_level_logfile, default_log_level)
- # Check help message
- self.assertIn('Default: \'{0}\'.'.format(default_log_level),
- parser.get_option('--log-level').help)
- # log file configuration tests
- def test_get_log_file_cli(self):
- '''
- Tests that log file match command-line specified value
- '''
- # Set defaults
- log_level = self.testing_config[self.loglevel_config_setting_name]
- # Set log file in CLI
- log_file = '{0}_cli.log'.format(self.log_file)
- args = ['--log-file', log_file] + self.args
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=self.testing_config)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- log_file_option = getattr(parser.options, self.logfile_config_setting_name)
- if not self.skip_console_logging_config:
- # Check console loggger
- self.assertEqual(self.log_setup.log_level, log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.config[self.logfile_config_setting_name],
- log_file)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file setting
- self.assertEqual(log_file_option, log_file)
- # Check log file logger
- self.assertEqual(self.log_setup.log_file, log_file)
- def test_get_log_file_config(self):
- '''
- Tests that log file match the configured value
- '''
- # Set defaults
- log_level = self.testing_config[self.loglevel_config_setting_name]
- args = self.args
- # Set log file in config
- log_file = '{0}_config.log'.format(self.log_file)
- opts = self.testing_config.copy()
- opts.update({self.logfile_config_setting_name: log_file})
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=opts)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- log_file_option = getattr(parser.options, self.logfile_config_setting_name)
- if not self.skip_console_logging_config:
- # Check console loggger
- self.assertEqual(self.log_setup.log_level, log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.config[self.logfile_config_setting_name],
- log_file)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file setting
- self.assertEqual(log_file_option, log_file)
- # Check log file logger
- self.assertEqual(self.log_setup.log_file, log_file)
- def test_get_log_file_default(self):
- '''
- Tests that log file match the default value
- '''
- # Set defaults
- log_level = self.testing_config[self.loglevel_config_setting_name]
- log_file = self.testing_config[self.logfile_config_setting_name]
- default_log_file = self.default_config[self.logfile_config_setting_name]
- args = self.args
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=self.testing_config)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- log_file_option = getattr(parser.options, self.logfile_config_setting_name)
- if not self.skip_console_logging_config:
- # Check console loggger
- self.assertEqual(self.log_setup.log_level, log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.config[self.logfile_config_setting_name],
- log_file)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file setting
- self.assertEqual(log_file_option, log_file)
- # Check log file logger
- self.assertEqual(self.log_setup.log_file, log_file)
- # Check help message
- self.assertIn('Default: \'{0}\'.'.format(default_log_file),
- parser.get_option('--log-file').help)
- # log file log level configuration tests
- def test_get_log_file_level_cli(self):
- '''
- Tests that file log level match command-line specified value
- '''
- # Set defaults
- default_log_level = self.testing_config[self.loglevel_config_setting_name]
- # Set log file level in CLI
- log_level_logfile = 'error'
- args = ['--log-file-level', log_level_logfile] + self.args
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=self.testing_config)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- log_level_logfile_option = getattr(parser.options,
- self.logfile_loglevel_config_setting_name)
- if not self.skip_console_logging_config:
- # Check console loggger
- self.assertEqual(self.log_setup.log_level, default_log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- default_log_level)
- self.assertEqual(self.log_setup.config[self.logfile_loglevel_config_setting_name],
- log_level_logfile)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file level setting
- self.assertEqual(log_level_logfile_option, log_level_logfile)
- # Check log file logger
- self.assertEqual(self.log_setup.log_level_logfile, log_level_logfile)
- def test_get_log_file_level_config(self):
- '''
- Tests that log file level match the configured value
- '''
- # Set defaults
- log_level = self.testing_config[self.loglevel_config_setting_name]
- args = self.args
- # Set log file level in config
- log_level_logfile = 'info'
- opts = self.testing_config.copy()
- opts.update({self.logfile_loglevel_config_setting_name: log_level_logfile})
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=opts)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- log_level_logfile_option = getattr(parser.options,
- self.logfile_loglevel_config_setting_name)
- if not self.skip_console_logging_config:
- # Check console loggger
- self.assertEqual(self.log_setup.log_level, log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.config[self.logfile_loglevel_config_setting_name],
- log_level_logfile)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file level setting
- self.assertEqual(log_level_logfile_option, log_level_logfile)
- # Check log file logger
- self.assertEqual(self.log_setup.log_level_logfile, log_level_logfile)
- def test_get_log_file_level_default(self):
- '''
- Tests that log file level match the default value
- '''
- # Set defaults
- default_log_level = self.testing_config[self.loglevel_config_setting_name]
- log_level = default_log_level
- log_level_logfile = default_log_level
- args = self.args
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=self.testing_config)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- log_level_logfile_option = getattr(parser.options,
- self.logfile_loglevel_config_setting_name)
- if not self.skip_console_logging_config:
- # Check console loggger
- self.assertEqual(self.log_setup.log_level, log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.config[self.logfile_loglevel_config_setting_name],
- log_level_logfile)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file level setting
- self.assertEqual(log_level_logfile_option, log_level_logfile)
- # Check log file logger
- self.assertEqual(self.log_setup.log_level_logfile, log_level_logfile)
- # Check help message
- self.assertIn('Default: \'{0}\'.'.format(default_log_level),
- parser.get_option('--log-file-level').help)
- def test_get_console_log_level_with_file_log_level(self): # pylint: disable=invalid-name
- '''
- Tests that both console log level and log file level setting are working together
- '''
- log_level = 'critical'
- log_level_logfile = 'debug'
- args = ['--log-file-level', log_level_logfile] + self.args
- opts = self.testing_config.copy()
- opts.update({self.loglevel_config_setting_name: log_level})
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=opts)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- log_level_logfile_option = getattr(parser.options,
- self.logfile_loglevel_config_setting_name)
- if not self.skip_console_logging_config:
- # Check console loggger
- self.assertEqual(self.log_setup.log_level, log_level)
- # Check extended logger
- self.assertEqual(self.log_setup.config[self.loglevel_config_setting_name],
- log_level)
- self.assertEqual(self.log_setup.config[self.logfile_loglevel_config_setting_name],
- log_level_logfile)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file level setting
- self.assertEqual(log_level_logfile_option, log_level_logfile)
- # Check log file logger
- self.assertEqual(self.log_setup.log_level_logfile, log_level_logfile)
- @skipIf(salt.utils.platform.is_windows(), 'Windows uses a logging listener')
- def test_log_created(self):
- '''
- Tests that log file is created
- '''
- args = self.args
- log_file = self.log_file
- log_file_name = self.logfile_config_setting_name
- opts = self.testing_config.copy()
- opts.update({'log_file': log_file})
- if log_file_name != 'log_file':
- opts.update({log_file_name: getattr(self, log_file_name)})
- if log_file_name == 'key_logfile':
- self.skipTest('salt-key creates log file outside of parse_args.')
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=opts)):
- parser.parse_args(args)
- if log_file_name == 'log_file':
- self.assertEqual(os.path.getsize(log_file), 0)
- else:
- self.assertEqual(os.path.getsize(getattr(self, log_file_name)), 0)
- def test_callbacks_uniqueness(self):
- '''
- Test that the callbacks are only added once, no matter
- how many instances of the parser we create
- '''
- mixin_container_names = ('_mixin_setup_funcs',
- '_mixin_process_funcs',
- '_mixin_after_parsed_funcs',
- '_mixin_before_exit_funcs')
- parser = self.parser()
- nums_1 = {}
- for cb_container in mixin_container_names:
- obj = getattr(parser, cb_container)
- nums_1[cb_container] = len(obj)
- # The next time we instantiate the parser, the counts should be equal
- parser = self.parser()
- nums_2 = {}
- for cb_container in mixin_container_names:
- obj = getattr(parser, cb_container)
- nums_2[cb_container] = len(obj)
- self.assertDictEqual(nums_1, nums_2)
- @skipIf(salt.utils.platform.is_windows(), 'Windows uses a logging listener')
- class MasterOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Master options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_master_parser_test'
- # Function to patch
- self.config_func = 'salt.config.master_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.MasterOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- @skipIf(salt.utils.platform.is_windows(), 'Windows uses a logging listener')
- class MinionOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Minion options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set defaults
- self.default_config = salt.config.DEFAULT_MINION_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_minion_parser_test'
- # Function to patch
- self.config_func = 'salt.config.minion_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.MinionOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- class ProxyMinionOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Proxy Minion options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set defaults
- self.default_config = salt.config.DEFAULT_MINION_OPTS.copy()
- self.default_config.update(salt.config.DEFAULT_PROXY_MINION_OPTS)
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_proxy_minion_parser_test'
- # Function to patch
- self.config_func = 'salt.config.proxy_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.ProxyMinionOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- @skipIf(salt.utils.platform.is_windows(), 'Windows uses a logging listener')
- class SyndicOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Syndic options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set config option names
- self.logfile_config_setting_name = 'syndic_log_file'
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_syndic_parser_test'
- self.syndic_log_file = '/tmp/salt_syndic_log'
- # Function to patch
- self.config_func = 'salt.config.syndic_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SyndicOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- if os.path.exists(self.syndic_log_file):
- os.unlink(self.syndic_log_file)
- class SaltCMDOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt CLI options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = ['foo', 'bar.baz']
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_cmd_parser_test'
- # Function to patch
- self.config_func = 'salt.config.client_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltCMDOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- class SaltCPOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing salt-cp options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = ['foo', 'bar', 'baz']
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_cp_parser_test'
- # Function to patch
- self.config_func = 'salt.config.master_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltCPOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- class SaltKeyOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing salt-key options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- self.skip_console_logging_config = True
- # Set config option names
- self.logfile_config_setting_name = 'key_logfile'
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_key_parser_test'
- self.key_logfile = '/tmp/key_logfile'
- # Function to patch
- self.config_func = 'salt.config.client_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltKeyOptionParser
- self.addCleanup(delattr, self, 'parser')
- # log level configuration tests
- def test_get_log_level_cli(self):
- '''
- Tests that console log level option is not recognized
- '''
- # No console log level will be actually set
- log_level = default_log_level = None
- option = '--log-level'
- args = self.args + [option, 'error']
- parser = self.parser()
- mock_err = ErrorMock()
- with patch('salt.utils.parsers.OptionParser.error', mock_err.error):
- parser.parse_args(args)
- # Check error msg
- self.assertEqual(mock_err.msg, 'no such option: {0}'.format(option))
- # Check console loggger has not been set
- self.assertEqual(self.log_setup.log_level, log_level)
- self.assertNotIn(self.loglevel_config_setting_name, self.log_setup.config)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file logger log level
- self.assertEqual(self.log_setup.log_level_logfile, default_log_level)
- def test_get_log_level_config(self):
- '''
- Tests that log level set in config is ignored
- '''
- log_level = 'info'
- args = self.args
- # Set log level in config and set additional mocked opts keys
- opts = {self.loglevel_config_setting_name: log_level,
- self.logfile_config_setting_name: 'key_logfile',
- 'log_fmt_logfile': None,
- 'log_datefmt_logfile': None,
- 'log_rotate_max_bytes': None,
- 'log_rotate_backup_count': None}
- parser = self.parser()
- with patch(self.config_func, MagicMock(return_value=opts)):
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- # Check config name absence in options
- self.assertNotIn(self.loglevel_config_setting_name, parser.options.__dict__)
- # Check console loggger has not been set
- self.assertEqual(self.log_setup.log_level, None)
- self.assertNotIn(self.loglevel_config_setting_name, self.log_setup.config)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file logger log level
- self.assertEqual(self.log_setup.log_level_logfile, log_level)
- def test_get_log_level_default(self):
- '''
- Tests that log level default value is ignored
- '''
- # Set defaults
- default_log_level = self.testing_config[self.loglevel_config_setting_name]
- log_level = None
- args = self.args
- parser = self.parser()
- parser.parse_args(args)
- with patch('salt.utils.parsers.is_writeable', MagicMock(return_value=True)):
- parser.setup_logfile_logger()
- # Check config name absence in options
- self.assertNotIn(self.loglevel_config_setting_name, parser.options.__dict__)
- # Check console loggger has not been set
- self.assertEqual(self.log_setup.log_level, log_level)
- self.assertNotIn(self.loglevel_config_setting_name, self.log_setup.config)
- # Check temp logger
- self.assertEqual(self.log_setup.temp_log_level, 'error')
- # Check log file logger log level
- self.assertEqual(self.log_setup.log_level_logfile, default_log_level)
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- if os.path.exists(self.key_logfile):
- os.unlink(self.key_logfile)
- class SaltCallOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Minion options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = ['foo.bar']
- # Set defaults
- self.default_config = salt.config.DEFAULT_MINION_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_call_parser_test'
- # Function to patch
- self.config_func = 'salt.config.minion_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltCallOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- class SaltRunOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Master options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = ['foo.bar']
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_run_parser_test'
- # Function to patch
- self.config_func = 'salt.config.master_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltRunOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- class SaltSSHOptionParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Master options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = ['foo', 'bar.baz']
- # Set config option names
- self.logfile_config_setting_name = 'ssh_log_file'
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_ssh_parser_test'
- self.ssh_log_file = '/tmp/ssh_logfile'
- # Function to patch
- self.config_func = 'salt.config.master_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltSSHOptionParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- if os.path.exists(self.ssh_log_file):
- os.unlink(self.ssh_log_file)
- class SaltCloudParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Cloud options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = ['-p', 'foo', 'bar']
- # Set default configs
- # Cloud configs are merged with master configs in
- # config/__init__.py, so we'll do that here as well
- # As we need the 'user' key later on.
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.default_config.update(salt.config.DEFAULT_CLOUD_OPTS)
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_cloud_parser_test'
- # Function to patch
- self.config_func = 'salt.config.cloud_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltCloudParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- class SPMParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Cloud options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = ['foo', 'bar']
- # Set config option names
- self.logfile_config_setting_name = 'spm_logfile'
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.default_config.update(salt.config.DEFAULT_SPM_OPTS)
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/spm_parser_test'
- self.spm_logfile = '/tmp/spm_logfile'
- # Function to patch
- self.config_func = 'salt.config.spm_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SPMParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- if os.path.exists(self.spm_logfile):
- os.unlink(self.spm_logfile)
- class SaltAPIParserTestCase(ParserBase, TestCase):
- '''
- Tests parsing Salt Cloud options
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Set mandatory CLI options
- self.args = []
- # Set config option names
- self.logfile_config_setting_name = 'api_logfile'
- # Set defaults
- self.default_config = salt.config.DEFAULT_MASTER_OPTS.copy()
- self.default_config.update(salt.config.DEFAULT_API_OPTS)
- self.addCleanup(delattr, self, 'default_config')
- # Log file
- self.log_file = '/tmp/salt_api_parser_test'
- self.api_logfile = '/tmp/api_logfile'
- # Function to patch
- self.config_func = 'salt.config.api_config'
- # Mock log setup
- self.setup_log()
- # Assign parser
- self.parser = salt.utils.parsers.SaltAPIParser
- self.addCleanup(delattr, self, 'parser')
- def tearDown(self):
- if os.path.exists(self.log_file):
- os.unlink(self.log_file)
- if os.path.exists(self.api_logfile):
- os.unlink(self.api_logfile)
- class DaemonMixInTestCase(TestCase):
- '''
- Tests the PIDfile deletion in the DaemonMixIn.
- '''
- def setUp(self):
- '''
- Setting up
- '''
- # Setup mixin
- self.daemon_mixin = salt.utils.parsers.DaemonMixIn()
- self.daemon_mixin.config = {}
- self.daemon_mixin.config['pidfile'] = '/some/fake.pid'
- def tearDown(self):
- '''
- Tear down test
- :return:
- '''
- del self.daemon_mixin
- @patch('os.unlink', MagicMock())
- @patch('os.path.isfile', MagicMock(return_value=True))
- @patch('salt.utils.parsers.logger', MagicMock())
- def test_pid_file_deletion(self):
- '''
- PIDfile deletion without exception.
- '''
- self.daemon_mixin._mixin_before_exit()
- assert salt.utils.parsers.os.unlink.call_count == 1
- salt.utils.parsers.logger.info.assert_not_called()
- salt.utils.parsers.logger.debug.assert_not_called()
- @patch('os.unlink', MagicMock(side_effect=OSError()))
- @patch('os.path.isfile', MagicMock(return_value=True))
- @patch('salt.utils.parsers.logger', MagicMock())
- def test_pid_deleted_oserror_as_root(self):
- '''
- PIDfile deletion with exception, running as root.
- '''
- if salt.utils.platform.is_windows():
- patch_args = ('salt.utils.win_functions.is_admin',
- MagicMock(return_value=True))
- else:
- patch_args = ('os.getuid', MagicMock(return_value=0))
- with patch(*patch_args):
- self.daemon_mixin._mixin_before_exit()
- assert salt.utils.parsers.os.unlink.call_count == 1
- salt.utils.parsers.logger.info.assert_called_with(
- 'PIDfile could not be deleted: %s',
- format(self.daemon_mixin.config['pidfile'])
- )
- salt.utils.parsers.logger.debug.assert_called()
- @patch('os.unlink', MagicMock(side_effect=OSError()))
- @patch('os.path.isfile', MagicMock(return_value=True))
- @patch('salt.utils.parsers.logger', MagicMock())
- def test_pid_deleted_oserror_as_non_root(self):
- '''
- PIDfile deletion with exception, running as non-root.
- '''
- if salt.utils.platform.is_windows():
- patch_args = ('salt.utils.win_functions.is_admin',
- MagicMock(return_value=False))
- else:
- patch_args = ('os.getuid', MagicMock(return_value=1000))
- with patch(*patch_args):
- self.daemon_mixin._mixin_before_exit()
- assert salt.utils.parsers.os.unlink.call_count == 1
- salt.utils.parsers.logger.info.assert_not_called()
- salt.utils.parsers.logger.debug.assert_not_called()
|