mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2019.2.1' into failhard-batch-fix-2019.2.1
This commit is contained in:
commit
6684793bf1
10 changed files with 166 additions and 32 deletions
|
@ -1634,6 +1634,9 @@ def show_states(queue=False, **kwargs):
|
|||
raise Exception(result)
|
||||
|
||||
for s in result:
|
||||
if not isinstance(s, dict):
|
||||
_set_retcode(result)
|
||||
return result
|
||||
states[s['__sls__']] = True
|
||||
finally:
|
||||
st_.pop_active()
|
||||
|
|
|
@ -60,14 +60,35 @@ except ImportError:
|
|||
if sys_modules_pip is not None:
|
||||
del sys_modules_pip
|
||||
|
||||
|
||||
def pip_has_internal_exceptions_mod(ver):
|
||||
'''
|
||||
True when the pip version has the `pip._internal.exceptions` module
|
||||
'''
|
||||
return salt.utils.versions.compare(
|
||||
ver1=ver,
|
||||
oper='>=',
|
||||
ver2='10.0',
|
||||
)
|
||||
|
||||
|
||||
def pip_has_exceptions_mod(ver):
|
||||
'''
|
||||
True when the pip version has the `pip.exceptions` module
|
||||
'''
|
||||
if pip_has_internal_exceptions_mod(ver):
|
||||
return False
|
||||
return salt.utils.versions.compare(
|
||||
ver1=ver,
|
||||
oper='>=',
|
||||
ver2='1.0'
|
||||
)
|
||||
|
||||
|
||||
if HAS_PIP is True:
|
||||
if salt.utils.versions.compare(ver1=pip.__version__,
|
||||
oper='>=',
|
||||
ver2='18.1'):
|
||||
if pip_has_internal_exceptions_mod(pip.__version__):
|
||||
from pip._internal.exceptions import InstallationError # pylint: disable=E0611,E0401
|
||||
elif salt.utils.versions.compare(ver1=pip.__version__,
|
||||
oper='>=',
|
||||
ver2='1.0'):
|
||||
elif pip_has_exceptions_mod(pip.__version__):
|
||||
from pip.exceptions import InstallationError # pylint: disable=E0611,E0401
|
||||
else:
|
||||
InstallationError = ValueError
|
||||
|
|
|
@ -214,7 +214,7 @@ class Schedule(object):
|
|||
# dict we treat it like it was there and is True
|
||||
|
||||
# Check if we're able to run
|
||||
if not data['run']:
|
||||
if 'run' not in data or not data['run']:
|
||||
return data
|
||||
if 'jid_include' not in data or data['jid_include']:
|
||||
jobcount = 0
|
||||
|
@ -463,7 +463,10 @@ class Schedule(object):
|
|||
|
||||
if 'name' not in data:
|
||||
data['name'] = name
|
||||
log.info('Running Job: %s', name)
|
||||
|
||||
# Assume run should be True until we check max_running
|
||||
if 'run' not in data:
|
||||
data['run'] = True
|
||||
|
||||
if not self.standalone:
|
||||
data = self._check_max_running(func,
|
||||
|
@ -472,8 +475,8 @@ class Schedule(object):
|
|||
datetime.datetime.now())
|
||||
|
||||
# Grab run, assume True
|
||||
run = data.get('run', True)
|
||||
if run:
|
||||
if data.get('run'):
|
||||
log.info('Running Job: %s', name)
|
||||
self._run_job(func, data)
|
||||
|
||||
def enable_schedule(self):
|
||||
|
|
|
@ -890,10 +890,10 @@ class TestDaemon(object):
|
|||
}
|
||||
master_opts['file_roots'] = syndic_master_opts['file_roots'] = {
|
||||
'base': [
|
||||
os.path.join(FILES, 'file', 'base'),
|
||||
# Let's support runtime created files that can be used like:
|
||||
# salt://my-temp-file.txt
|
||||
RUNTIME_VARS.TMP_STATE_TREE
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(FILES, 'file', 'base'),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
'prod': [
|
||||
|
@ -903,10 +903,10 @@ class TestDaemon(object):
|
|||
}
|
||||
minion_opts['file_roots'] = {
|
||||
'base': [
|
||||
os.path.join(FILES, 'file', 'base'),
|
||||
# Let's support runtime created files that can be used like:
|
||||
# salt://my-temp-file.txt
|
||||
RUNTIME_VARS.TMP_STATE_TREE
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(FILES, 'file', 'base'),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
'prod': [
|
||||
|
|
|
@ -15,7 +15,7 @@ import time
|
|||
from tests.support.case import ModuleCase
|
||||
from tests.support.helpers import with_tempdir, flaky
|
||||
from tests.support.unit import skipIf
|
||||
from tests.support.paths import BASE_FILES, TMP, TMP_PILLAR_TREE
|
||||
from tests.support.paths import BASE_FILES, TMP, TMP_PILLAR_TREE, TMP_STATE_TREE
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
|
||||
# Import Salt libs
|
||||
|
@ -118,6 +118,21 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
self.assertTrue(isinstance(states, list))
|
||||
self.assertTrue(isinstance(states[0], six.string_types))
|
||||
|
||||
def test_show_states_missing_sls(self):
|
||||
'''
|
||||
Test state.show_states with a sls file
|
||||
defined in a top file is missing
|
||||
'''
|
||||
with salt.utils.files.fopen(os.path.join(TMP_STATE_TREE, 'top.sls'), 'w') as top_file:
|
||||
top_file.write(textwrap.dedent('''\
|
||||
base:
|
||||
'*':
|
||||
- doesnotexist
|
||||
'''))
|
||||
states = self.run_function('state.show_states')
|
||||
assert isinstance(states, list)
|
||||
assert states == ["No matching sls found for 'doesnotexist' in env 'base'"]
|
||||
|
||||
def test_catch_recurse(self):
|
||||
'''
|
||||
state.show_sls used to catch a recursive ref
|
||||
|
@ -2065,9 +2080,14 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
self.assertEqual(_expected, ret[key]['changes']['stdout'])
|
||||
|
||||
def tearDown(self):
|
||||
nonbase_file = os.path.join(TMP, 'nonbase_env')
|
||||
if os.path.isfile(nonbase_file):
|
||||
os.remove(nonbase_file)
|
||||
rm_files = [os.path.join(TMP, 'nonbase_env'),
|
||||
os.path.join(TMP, 'testfile'),
|
||||
os.path.join(TMP, 'test.txt'),
|
||||
os.path.join(TMP_STATE_TREE, 'top.sls')]
|
||||
|
||||
for file_ in rm_files:
|
||||
if os.path.isfile(file_):
|
||||
os.remove(file_)
|
||||
|
||||
# remove old pillar data
|
||||
for filename in os.listdir(TMP_PILLAR_TREE):
|
||||
|
@ -2075,16 +2095,6 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
self.run_function('saltutil.refresh_pillar')
|
||||
self.run_function('test.sleep', [5])
|
||||
|
||||
# remove testfile added in core.sls state file
|
||||
state_file = os.path.join(TMP, 'testfile')
|
||||
if os.path.isfile(state_file):
|
||||
os.remove(state_file)
|
||||
|
||||
# remove testfile added in issue-30161.sls state file
|
||||
state_file = os.path.join(TMP, 'test.txt')
|
||||
if os.path.isfile(state_file):
|
||||
os.remove(state_file)
|
||||
|
||||
def test_state_sls_integer_name(self):
|
||||
'''
|
||||
This tests the case where the state file is named
|
||||
|
|
73
tests/integration/scheduler/test_run_job.py
Normal file
73
tests/integration/scheduler/test_run_job.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import copy
|
||||
import logging
|
||||
import os
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from tests.support.mock import MagicMock, patch
|
||||
import tests.integration as integration
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils.schedule
|
||||
import salt.utils.platform
|
||||
|
||||
from salt.modules.test import ping as ping
|
||||
|
||||
try:
|
||||
import croniter # pylint: disable=W0611
|
||||
HAS_CRONITER = True
|
||||
except ImportError:
|
||||
HAS_CRONITER = False
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
ROOT_DIR = os.path.join(integration.TMP, 'schedule-unit-tests')
|
||||
SOCK_DIR = os.path.join(ROOT_DIR, 'test-socks')
|
||||
|
||||
DEFAULT_CONFIG = salt.config.minion_config(None)
|
||||
DEFAULT_CONFIG['conf_dir'] = ROOT_DIR
|
||||
DEFAULT_CONFIG['root_dir'] = ROOT_DIR
|
||||
DEFAULT_CONFIG['sock_dir'] = SOCK_DIR
|
||||
DEFAULT_CONFIG['pki_dir'] = os.path.join(ROOT_DIR, 'pki')
|
||||
DEFAULT_CONFIG['cachedir'] = os.path.join(ROOT_DIR, 'cache')
|
||||
|
||||
|
||||
class SchedulerRunJobTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
'''
|
||||
Validate the pkg module
|
||||
'''
|
||||
def setUp(self):
|
||||
with patch('salt.utils.schedule.clean_proc_dir', MagicMock(return_value=None)):
|
||||
functions = {'test.ping': ping}
|
||||
self.schedule = salt.utils.schedule.Schedule(copy.deepcopy(DEFAULT_CONFIG), functions, returners={})
|
||||
self.schedule.opts['loop_interval'] = 1
|
||||
|
||||
def tearDown(self):
|
||||
self.schedule.reset()
|
||||
|
||||
def test_run_job(self):
|
||||
'''
|
||||
verify that scheduled job runs
|
||||
'''
|
||||
job_name = 'test_run_job'
|
||||
job = {
|
||||
'schedule': {
|
||||
job_name: {
|
||||
'function': 'test.ping',
|
||||
}
|
||||
}
|
||||
}
|
||||
# Add the job to the scheduler
|
||||
self.schedule.opts.update(job)
|
||||
|
||||
# Run job
|
||||
self.schedule.run_job(job_name)
|
||||
ret = self.schedule.job_status(job_name)
|
||||
expected = {'function': 'test.ping', 'run': True, 'name': 'test_run_job'}
|
||||
self.assertEqual(ret, expected)
|
|
@ -150,14 +150,14 @@ class ScheduleTestCase(TestCase, LoaderModuleMockMixin):
|
|||
'''
|
||||
Test if it run a scheduled job on the minion immediately.
|
||||
'''
|
||||
with patch.dict(schedule.__opts__, {'schedule': {}, 'sock_dir': SOCK_DIR}):
|
||||
with patch.dict(schedule.__opts__, {'schedule': {'job1': JOB1}, 'sock_dir': SOCK_DIR}):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(schedule.__salt__, {'event.fire': mock}):
|
||||
_ret_value = {'complete': True, 'schedule': {}}
|
||||
_ret_value = {'complete': True, 'schedule': {'job1': JOB1}}
|
||||
with patch.object(SaltEvent, 'get_event', return_value=_ret_value):
|
||||
self.assertDictEqual(schedule.run_job('job1'),
|
||||
{'comment': 'Job job1 does not exist.',
|
||||
'result': False})
|
||||
{'comment': 'Scheduling Job job1 on minion.',
|
||||
'result': True})
|
||||
|
||||
# 'enable_job' function tests: 1
|
||||
|
||||
|
|
|
@ -632,6 +632,19 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||
self.assertEqual(state.show_low_sls("foo"), "A")
|
||||
self.assertListEqual(state.show_states("foo"), ['abc'])
|
||||
|
||||
def test_show_states_missing_sls(self):
|
||||
'''
|
||||
Test state.show_states when a sls file defined
|
||||
in a top.sls file is missing
|
||||
'''
|
||||
msg = ["No matching sls found for 'cloud' in evn 'base'"]
|
||||
chunks_mock = MagicMock(side_effect=[msg])
|
||||
mock = MagicMock(side_effect=["A", None])
|
||||
with patch.object(state, '_check_queue', mock),\
|
||||
patch('salt.state.HighState.compile_low_chunks', chunks_mock):
|
||||
self.assertEqual(state.show_low_sls("foo"), "A")
|
||||
self.assertListEqual(state.show_states("foo"), [msg[0]])
|
||||
|
||||
def test_sls_id(self):
|
||||
'''
|
||||
Test to call a single ID from the
|
||||
|
|
|
@ -282,3 +282,13 @@ class PipStateTest(TestCase, SaltReturnAssertsMixin, LoaderModuleMockMixin):
|
|||
'successfully installed',
|
||||
{'test': ret}
|
||||
)
|
||||
|
||||
def test_has_internal_exceptions_mod_function(self):
|
||||
assert pip_state.pip_has_internal_exceptions_mod('10.0')
|
||||
assert pip_state.pip_has_internal_exceptions_mod('18.1')
|
||||
assert not pip_state.pip_has_internal_exceptions_mod('9.99')
|
||||
|
||||
def test_has_exceptions_mod_function(self):
|
||||
assert pip_state.pip_has_exceptions_mod('1.0')
|
||||
assert not pip_state.pip_has_exceptions_mod('0.1')
|
||||
assert not pip_state.pip_has_exceptions_mod('10.0')
|
||||
|
|
|
@ -156,6 +156,7 @@ class BadTestModuleNamesTestCase(TestCase):
|
|||
'integration.scheduler.test_skip',
|
||||
'integration.scheduler.test_maxrunning',
|
||||
'integration.scheduler.test_helpers',
|
||||
'integration.scheduler.test_run_job',
|
||||
'integration.shell.test_spm',
|
||||
'integration.shell.test_cp',
|
||||
'integration.shell.test_syndic',
|
||||
|
|
Loading…
Add table
Reference in a new issue