salt/tests/unit/states/test_cron.py
rallytime 3273bbdab7
Merge branch '2017.7' into '2018.3'
Conflicts:
  - doc/ref/configuration/master.rst
  - doc/ref/modules/all/index.rst
  - doc/topics/grains/index.rst
  - doc/topics/releases/2016.3.4.rst
  - doc/topics/spm/spm_formula.rst
  - doc/topics/tutorials/cron.rst
  - doc/topics/tutorials/index.rst
  - doc/topics/tutorials/stormpath.rst
  - salt/engines/slack.py
  - salt/log/handlers/fluent_mod.py
  - salt/modules/cyg.py
  - salt/modules/junos.py
  - salt/modules/namecheap_dns.py
  - salt/modules/namecheap_domains.py
  - salt/modules/namecheap_ns.py
  - salt/modules/namecheap_ssl.py
  - salt/modules/namecheap_users.py
  - salt/modules/reg.py
  - salt/modules/tomcat.py
  - salt/modules/vault.py
  - salt/modules/win_file.py
  - salt/modules/zpool.py
  - salt/output/highstate.py
  - salt/renderers/pass.py
  - salt/runners/cache.py
  - salt/states/boto_apigateway.py
  - salt/states/boto_iam.py
  - salt/states/boto_route53.py
  - salt/states/msteams.py
  - salt/states/reg.py
  - salt/states/win_iis.py
  - tests/integration/modules/test_cmdmod.py
  - tests/integration/states/test_user.py
  - tests/support/helpers.py
  - tests/unit/cloud/clouds/test_openstack.py
  - tests/unit/fileserver/test_gitfs.py
  - tests/unit/modules/test_junos.py
  - tests/unit/pillar/test_git.py
  - tests/unit/states/test_win_path.py
  - tests/unit/test_pillar.py
  - tests/unit/utils/test_format_call.py
  - tests/unit/utils/test_utils.py
  - tests/unit/utils/test_warnings.py
2018-06-01 14:54:12 -04:00

326 lines
11 KiB
Python

# -*- coding: utf-8 -*-
'''
:codeauthor: Mike Place <mp@saltstack.com>
'''
# Import python libs
from __future__ import absolute_import, unicode_literals, print_function
# Import Salt Testing libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase, skipIf
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
from salt.ext.six.moves import StringIO
import salt.modules.cron as cronmod
import salt.states.cron as cron
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):
CRONTAB.seek(0)
CRONTAB.truncate(0)
CRONTAB.write(val)
def write_crontab(*args, **kw):
set_crontab('\n'.join(
[a.strip() for a in args[1]]))
return {
'retcode': False,
}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class CronTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
loader_gloabals = {
'__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,
}
}
return {cron: loader_gloabals, cronmod: loader_gloabals}
def setUp(self):
super(CronTestCase, self).setUp()
set_crontab('')
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, '')
def test_present(self):
cron.present(
name='foo',
hour='1',
identifier='1',
user='root')
self.assertMultiLineEqual(
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')
self.assertMultiLineEqual(
get_crontab(),
'# Lines below here are managed by Salt, do not edit\n'
'# SALT_CRON_IDENTIFIER:1\n'
'* 2 * * * foo')
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')
cron.present(
name='foo',
hour='2',
identifier='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')
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')
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'
)
cron.present(
name='foo',
hour='2',
user='root',
identifier=None)
self.assertEqual(
get_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'))
def test_remove(self):
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'
)
def test_multiline_comments_are_updated(self):
set_crontab(
'# Lines below here are managed by Salt, do not edit\n'
'# First crontab - single line comment SALT_CRON_IDENTIFIER:1\n'
'* 1 * * * foo'
)
cron.present(
name='foo',
hour='1',
comment='First crontab\nfirst multi-line comment\n',
identifier='1',
user='root')
cron.present(
name='foo',
hour='1',
comment='First crontab\nsecond multi-line comment\n',
identifier='1',
user='root')
cron.present(
name='foo',
hour='1',
comment='Second crontab\nmulti-line comment\n',
identifier='2',
user='root')
self.assertEqual(
get_crontab(),
'# Lines below here are managed by Salt, do not edit\n'
'# First crontab\n'
'# second multi-line comment\n'
'# SALT_CRON_IDENTIFIER:1\n'
'* 1 * * * foo\n'
'# Second crontab\n'
'# multi-line comment\n'
'# SALT_CRON_IDENTIFIER:2\n'
'* 1 * * * foo')
def test_existing_unmanaged_jobs_are_made_managed(self):
set_crontab(
'# Lines below here are managed by Salt, do not edit\n'
'0 2 * * * foo'
)
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')
self.assertEqual(
get_crontab(),
'# Lines below here are managed by Salt, do not edit\n'
'# 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')
def test_existing_noid_jobs_are_updated_with_identifier(self):
set_crontab(
'# Lines below here are managed by Salt, do not edit\n'
'# SALT_CRON_IDENTIFIER:NO ID SET\n'
'1 * * * * foo'
)
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')
self.assertEqual(
get_crontab(),
'# Lines below here are managed by Salt, do not edit\n'
'# SALT_CRON_IDENTIFIER:foo\n'
'1 * * * * foo')
def test_existing_duplicate_unmanaged_jobs_are_merged_and_given_id(self):
set_crontab(
'# Lines below here are managed by Salt, do not edit\n'
'0 2 * * * foo\n'
'0 2 * * * foo'
)
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')
self.assertEqual(
get_crontab(),
'# Lines below here are managed by Salt, do not edit\n'
'# 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')