2014-02-19 19:35:51 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
'''
|
2014-05-22 00:59:02 +00:00
|
|
|
:codeauthor: :email:`Mike Place <mp@saltstack.com>`
|
2014-02-19 19:35:51 +00:00
|
|
|
'''
|
|
|
|
|
2014-11-21 19:05:13 +00:00
|
|
|
# Import python libs
|
|
|
|
from __future__ import absolute_import
|
|
|
|
|
2014-02-19 19:35:51 +00:00
|
|
|
# Import Salt Testing libs
|
2017-02-19 15:35:30 +00:00
|
|
|
from tests.support.mixins import LoaderModuleMockMixin
|
2017-02-27 13:58:07 +00:00
|
|
|
from tests.support.unit import TestCase, skipIf
|
|
|
|
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
|
2014-02-19 19:35:51 +00:00
|
|
|
|
2015-06-11 22:26:10 +00:00
|
|
|
from salt.ext.six.moves import StringIO
|
2017-03-21 17:15:36 +00:00
|
|
|
import salt.modules.cron as cronmod
|
|
|
|
import salt.states.cron as cron
|
2014-02-19 19:35:51 +00:00
|
|
|
|
|
|
|
STUB_USER = 'root'
|
|
|
|
STUB_PATH = '/tmp'
|
|
|
|
|
|
|
|
STUB_CRON_TIMESTAMP = {
|
|
|
|
'minute': '1',
|
|
|
|
'hour': '2',
|
|
|
|
'daymonth': '3',
|
|
|
|
'month': '4',
|
|
|
|
'dayweek': '5'}
|
|
|
|
|
|
|
|
STUB_SIMPLE_RAW_CRON = '5 0 * * * /tmp/no_script.sh'
|
|
|
|
STUB_SIMPLE_CRON_DICT = {
|
|
|
|
'pre': ['5 0 * * * /tmp/no_script.sh'],
|
|
|
|
'crons': [],
|
|
|
|
'env': [],
|
|
|
|
'special': []}
|
|
|
|
|
|
|
|
CRONTAB = StringIO()
|
|
|
|
|
|
|
|
|
|
|
|
def get_crontab(*args, **kw):
|
|
|
|
return CRONTAB.getvalue()
|
|
|
|
|
|
|
|
|
|
|
|
def set_crontab(val):
|
2015-06-11 22:26:10 +00:00
|
|
|
CRONTAB.seek(0)
|
2014-02-19 19:35:51 +00:00
|
|
|
CRONTAB.truncate(0)
|
|
|
|
CRONTAB.write(val)
|
|
|
|
|
|
|
|
|
|
|
|
def write_crontab(*args, **kw):
|
|
|
|
set_crontab('\n'.join(
|
|
|
|
[a.strip() for a in args[1]]))
|
2014-04-18 07:13:25 +00:00
|
|
|
return {
|
|
|
|
'retcode': False,
|
|
|
|
}
|
2014-02-19 19:35:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
2017-02-19 15:35:30 +00:00
|
|
|
class CronTestCase(TestCase, LoaderModuleMockMixin):
|
|
|
|
|
2017-03-22 12:12:36 +00:00
|
|
|
def setup_loader_modules(self):
|
|
|
|
loader_gloabals = {
|
2017-02-19 15:35:30 +00:00
|
|
|
'__low__': {'__id__': 'noo'},
|
|
|
|
'__grains__': {
|
|
|
|
'os': 'Debian',
|
|
|
|
'os_family': 'Debian',
|
|
|
|
},
|
|
|
|
'__opts__': {'test': False},
|
|
|
|
'__salt__': {
|
|
|
|
'cmd.run_all': MagicMock(return_value={
|
|
|
|
'pid': 5,
|
|
|
|
'retcode': 0,
|
|
|
|
'stderr': '',
|
|
|
|
'stdout': ''}),
|
|
|
|
'cron.list_tab': cronmod.list_tab,
|
|
|
|
'cron.rm_job': cronmod.rm_job,
|
|
|
|
'cron.set_job': cronmod.set_job,
|
|
|
|
}
|
|
|
|
}
|
2017-03-22 12:12:36 +00:00
|
|
|
return {cron: loader_gloabals, cronmod: loader_gloabals}
|
2014-02-19 19:35:51 +00:00
|
|
|
|
2014-02-25 19:52:47 +00:00
|
|
|
def setUp(self):
|
|
|
|
super(CronTestCase, self).setUp()
|
|
|
|
set_crontab('')
|
2017-04-10 13:00:57 +00:00
|
|
|
for mod, mock in (('salt.modules.cron.raw_cron', MagicMock(side_effect=get_crontab)),
|
|
|
|
('salt.modules.cron._write_cron_lines', MagicMock(side_effect=write_crontab))):
|
|
|
|
patcher = patch(mod, mock)
|
|
|
|
patcher.start()
|
|
|
|
self.addCleanup(patcher.stop)
|
|
|
|
self.addCleanup(set_crontab, '')
|
2014-02-25 19:52:47 +00:00
|
|
|
|
2014-02-19 19:35:51 +00:00
|
|
|
def test_present(self):
|
|
|
|
cron.present(
|
|
|
|
name='foo',
|
|
|
|
hour='1',
|
|
|
|
identifier='1',
|
|
|
|
user='root')
|
2015-11-23 14:51:32 +00:00
|
|
|
self.assertMultiLineEqual(
|
2014-02-19 19:35:51 +00:00
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 1 * * * foo')
|
|
|
|
cron.present(
|
|
|
|
name='foo',
|
|
|
|
hour='2',
|
|
|
|
identifier='1',
|
|
|
|
user='root')
|
2015-11-23 14:51:32 +00:00
|
|
|
self.assertMultiLineEqual(
|
2014-02-19 19:35:51 +00:00
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 2 * * * foo')
|
2015-11-23 14:51:32 +00:00
|
|
|
cron.present(
|
|
|
|
name='cmd1',
|
|
|
|
minute='0',
|
|
|
|
comment='Commented cron job',
|
|
|
|
commented=True,
|
|
|
|
identifier='commented_1',
|
|
|
|
user='root')
|
|
|
|
self.assertMultiLineEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 2 * * * foo\n'
|
|
|
|
'# Commented cron job SALT_CRON_IDENTIFIER:commented_1\n'
|
|
|
|
'#DISABLED#0 * * * * cmd1')
|
2014-02-19 19:35:51 +00:00
|
|
|
cron.present(
|
|
|
|
name='foo',
|
|
|
|
hour='2',
|
|
|
|
identifier='2',
|
|
|
|
user='root')
|
2015-11-23 14:51:32 +00:00
|
|
|
self.assertMultiLineEqual(
|
2014-02-19 19:35:51 +00:00
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 2 * * * foo\n'
|
2015-11-23 14:51:32 +00:00
|
|
|
'# Commented cron job SALT_CRON_IDENTIFIER:commented_1\n'
|
|
|
|
'#DISABLED#0 * * * * cmd1\n'
|
2014-02-19 19:35:51 +00:00
|
|
|
'# SALT_CRON_IDENTIFIER:2\n'
|
|
|
|
'* 2 * * * foo')
|
2015-11-23 14:51:32 +00:00
|
|
|
cron.present(
|
|
|
|
name='cmd2',
|
|
|
|
commented=True,
|
|
|
|
identifier='commented_2',
|
|
|
|
user='root')
|
|
|
|
self.assertMultiLineEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 2 * * * foo\n'
|
|
|
|
'# Commented cron job SALT_CRON_IDENTIFIER:commented_1\n'
|
|
|
|
'#DISABLED#0 * * * * cmd1\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:2\n'
|
|
|
|
'* 2 * * * foo\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:commented_2\n'
|
|
|
|
'#DISABLED#* * * * * cmd2')
|
2014-02-19 21:44:34 +00:00
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 2 * * * foo\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:2\n'
|
|
|
|
'* 2 * * * foo\n'
|
|
|
|
'* 2 * * * foo\n'
|
|
|
|
)
|
2014-02-19 19:35:51 +00:00
|
|
|
cron.present(
|
|
|
|
name='foo',
|
|
|
|
hour='2',
|
2015-08-12 07:13:06 +00:00
|
|
|
user='root',
|
|
|
|
identifier=None)
|
2014-02-19 19:35:51 +00:00
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
2014-03-11 18:13:06 +00:00
|
|
|
('# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 2 * * * foo\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:2\n'
|
|
|
|
'* 2 * * * foo\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'* 2 * * * foo'))
|
2014-02-19 19:35:51 +00:00
|
|
|
|
|
|
|
def test_remove(self):
|
2017-02-19 15:35:30 +00:00
|
|
|
with patch.dict(cron.__opts__, {'test': True}):
|
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 1 * * * foo')
|
|
|
|
result = cron.absent(name='bar', identifier='1')
|
|
|
|
self.assertEqual(
|
|
|
|
result,
|
|
|
|
{'changes': {},
|
|
|
|
'comment': 'Cron bar is set to be removed',
|
|
|
|
'name': 'bar',
|
|
|
|
'result': None}
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 1 * * * foo')
|
|
|
|
with patch.dict(cron.__opts__, {'test': False}):
|
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
|
|
|
'* 1 * * * foo')
|
|
|
|
cron.absent(name='bar', identifier='1')
|
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit'
|
|
|
|
)
|
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'* * * * * foo')
|
|
|
|
cron.absent(name='bar', identifier='1')
|
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'* * * * * foo'
|
|
|
|
)
|
|
|
|
# old behavior, do not remove with identifier set and
|
|
|
|
# even if command match !
|
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'* * * * * foo')
|
|
|
|
cron.absent(name='foo', identifier='1')
|
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit'
|
|
|
|
)
|
|
|
|
# old behavior, remove if no identifier and command match
|
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
|
|
|
'* * * * * foo')
|
|
|
|
cron.absent(name='foo')
|
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit'
|
|
|
|
)
|
2014-02-19 19:35:51 +00:00
|
|
|
|
2015-08-12 07:13:06 +00:00
|
|
|
def test_multiline_comments_are_updated(self):
|
2014-04-18 07:13:25 +00:00
|
|
|
set_crontab(
|
2014-02-25 19:52:47 +00:00
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'# First crontab - single line comment SALT_CRON_IDENTIFIER:1\n'
|
2014-02-25 19:52:47 +00:00
|
|
|
'* 1 * * * foo'
|
|
|
|
)
|
|
|
|
cron.present(
|
|
|
|
name='foo',
|
|
|
|
hour='1',
|
2015-08-12 07:13:06 +00:00
|
|
|
comment='First crontab\nfirst multi-line comment\n',
|
2014-02-25 19:52:47 +00:00
|
|
|
identifier='1',
|
|
|
|
user='root')
|
|
|
|
cron.present(
|
|
|
|
name='foo',
|
|
|
|
hour='1',
|
2015-08-12 07:13:06 +00:00
|
|
|
comment='First crontab\nsecond multi-line comment\n',
|
|
|
|
identifier='1',
|
2014-02-25 19:52:47 +00:00
|
|
|
user='root')
|
|
|
|
cron.present(
|
|
|
|
name='foo',
|
|
|
|
hour='1',
|
2015-08-12 08:08:43 +00:00
|
|
|
comment='Second crontab\nmulti-line comment\n',
|
2014-02-25 19:52:47 +00:00
|
|
|
identifier='2',
|
|
|
|
user='root')
|
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'# First crontab\n'
|
2017-06-08 22:15:49 +00:00
|
|
|
'# second multi-line comment\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:1\n'
|
2014-02-25 19:52:47 +00:00
|
|
|
'* 1 * * * foo\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'# Second crontab\n'
|
2017-06-08 22:15:49 +00:00
|
|
|
'# multi-line comment\n'
|
|
|
|
'# SALT_CRON_IDENTIFIER:2\n'
|
2014-02-25 19:52:47 +00:00
|
|
|
'* 1 * * * foo')
|
|
|
|
|
2015-08-12 07:13:06 +00:00
|
|
|
def test_existing_unmanaged_jobs_are_made_managed(self):
|
2014-04-18 07:13:25 +00:00
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'0 2 * * * foo'
|
2014-04-18 07:13:25 +00:00
|
|
|
)
|
2015-08-12 07:13:06 +00:00
|
|
|
ret = cron._check_cron('root', 'foo', hour='2', minute='0')
|
|
|
|
self.assertEqual(ret, 'present')
|
|
|
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
|
|
|
self.assertEqual(ret['changes'], {'root': 'foo'})
|
|
|
|
self.assertEqual(ret['comment'], 'Cron foo updated')
|
2014-04-18 07:13:25 +00:00
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'# SALT_CRON_IDENTIFIER:foo\n'
|
|
|
|
'0 2 * * * foo')
|
|
|
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
|
|
|
self.assertEqual(ret['changes'], {})
|
|
|
|
self.assertEqual(ret['comment'], 'Cron foo already present')
|
2014-04-18 07:13:25 +00:00
|
|
|
|
2015-08-12 07:13:06 +00:00
|
|
|
def test_existing_noid_jobs_are_updated_with_identifier(self):
|
2014-04-18 07:13:25 +00:00
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'# SALT_CRON_IDENTIFIER:NO ID SET\n'
|
|
|
|
'1 * * * * foo'
|
2014-04-18 07:13:25 +00:00
|
|
|
)
|
2015-08-12 07:13:06 +00:00
|
|
|
ret = cron._check_cron('root', 'foo', minute=1)
|
|
|
|
self.assertEqual(ret, 'present')
|
|
|
|
ret = cron.present('foo', 'root', minute=1)
|
|
|
|
self.assertEqual(ret['changes'], {'root': 'foo'})
|
|
|
|
self.assertEqual(ret['comment'], 'Cron foo updated')
|
2014-04-18 07:13:25 +00:00
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'# SALT_CRON_IDENTIFIER:foo\n'
|
|
|
|
'1 * * * * foo')
|
2014-04-18 07:13:25 +00:00
|
|
|
|
2015-08-12 07:13:06 +00:00
|
|
|
def test_existing_duplicate_unmanaged_jobs_are_merged_and_given_id(self):
|
2014-04-18 07:13:25 +00:00
|
|
|
set_crontab(
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'0 2 * * * foo\n'
|
|
|
|
'0 2 * * * foo'
|
2014-04-18 07:13:25 +00:00
|
|
|
)
|
2015-08-12 07:13:06 +00:00
|
|
|
ret = cron._check_cron('root', 'foo', hour='2', minute='0')
|
|
|
|
self.assertEqual(ret, 'present')
|
|
|
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
|
|
|
self.assertEqual(ret['changes'], {'root': 'foo'})
|
|
|
|
self.assertEqual(ret['comment'], 'Cron foo updated')
|
2014-04-18 07:13:25 +00:00
|
|
|
self.assertEqual(
|
|
|
|
get_crontab(),
|
|
|
|
'# Lines below here are managed by Salt, do not edit\n'
|
2015-08-12 07:13:06 +00:00
|
|
|
'# SALT_CRON_IDENTIFIER:foo\n'
|
|
|
|
'0 2 * * * foo')
|
|
|
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
|
|
|
self.assertEqual(ret['changes'], {})
|
|
|
|
self.assertEqual(ret['comment'], 'Cron foo already present')
|