salt/tests/unit/states/test_augeas.py
rallytime c0f16dae74
Merge branch '2017.7' into 'develop'
Conflicts:
  - doc/topics/tutorials/index.rst
  - salt/crypt.py
  - salt/modules/cmdmod.py
  - salt/modules/grains.py
  - salt/pillar/git_pillar.py
  - salt/roster/clustershell.py
  - tests/unit/states/test_augeas.py
  - tests/unit/utils/test_utils.py
2017-10-16 15:26:19 -04:00

247 lines
10 KiB
Python

# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
:codeauthor: :email:`Andrew Colin Kissa <andrew@topdog.za.net>`
'''
# Import Python libs
from __future__ import absolute_import
import os
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import skipIf, TestCase
from tests.support.mock import (
mock_open,
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch
)
# Import Salt Libs
import salt.states.augeas as augeas
@skipIf(NO_MOCK, NO_MOCK_REASON)
class AugeasTestCase(TestCase, LoaderModuleMockMixin):
'''
Test cases for salt.states.augeas
'''
def setup_loader_modules(self):
return {augeas: {}}
# 'change' function tests: 1
def setUp(self):
self.name = 'zabbix'
self.context = '/files/etc/services'
self.changes = ['ins service-name after service-name[last()]',
'set service-name[last()] zabbix-agent']
self.fp_changes = [
'ins service-name after /files/etc/services/service-name[last()]',
'set /files/etc/services/service-name[last()] zabbix-agent']
self.ret = {'name': self.name,
'result': False,
'changes': {},
'comment': ''}
method_map = {
'set': 'set',
'setm': 'setm',
'mv': 'move',
'move': 'move',
'ins': 'insert',
'insert': 'insert',
'rm': 'remove',
'remove': 'remove',
}
self.mock_method_map = MagicMock(return_value=method_map)
def tearDown(self):
del self.ret
del self.changes
del self.fp_changes
del self.mock_method_map
def test_change_non_list_changes(self):
'''
Test if none list changes handled correctly
'''
comt = ('\'changes\' must be specified as a list')
self.ret.update({'comment': comt})
self.assertDictEqual(augeas.change(self.name), self.ret)
def test_change_non_list_load_path(self):
'''
Test if none list load_path is handled correctly
'''
comt = ('\'load_path\' must be specified as a list')
self.ret.update({'comment': comt})
self.assertDictEqual(augeas.change(
self.name, self.context, self.changes, load_path='x'), self.ret)
def test_change_in_test_mode(self):
'''
Test test mode handling
'''
comt = ('Executing commands in file "/files/etc/services":\n'
'ins service-name after service-name[last()]'
'\nset service-name[last()] zabbix-agent')
self.ret.update({'comment': comt, 'result': True})
with patch.dict(augeas.__opts__, {'test': True}):
self.assertDictEqual(
augeas.change(self.name, self.context, self.changes),
self.ret)
def test_change_no_context_without_full_path(self):
'''
Test handling of no context without full path
'''
comt = 'Error: Changes should be prefixed with /files if no ' \
'context is provided, change: {0}'\
.format(self.changes[0])
self.ret.update({'comment': comt, 'result': False})
with patch.dict(augeas.__opts__, {'test': False}):
mock_dict_ = {'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
self.assertDictEqual(
augeas.change(self.name, changes=self.changes),
self.ret)
def test_change_no_context_with_full_path_fail(self):
'''
Test handling of no context with full path with execute fail
'''
self.ret.update({'comment': 'Error: error', 'result': False})
with patch.dict(augeas.__opts__, {'test': False}):
mock_execute = MagicMock(
return_value=dict(retval=False, error='error'))
mock_dict_ = {'augeas.execute': mock_execute,
'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
self.assertDictEqual(
augeas.change(self.name, changes=self.fp_changes),
self.ret)
def test_change_no_context_with_full_path_pass(self):
'''
Test handling of no context with full path with execute pass
'''
self.ret.update(dict(comment='Changes have been saved',
result=True,
changes={'diff': '+ zabbix-agent'}))
with patch.dict(augeas.__opts__, {'test': False}):
mock_execute = MagicMock(return_value=dict(retval=True))
mock_dict_ = {'augeas.execute': mock_execute,
'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
mock_filename = MagicMock(return_value='/etc/services')
with patch.object(augeas, '_workout_filename', mock_filename), \
patch('os.path.isfile', MagicMock(return_value=True)):
with patch('salt.utils.files.fopen', MagicMock(mock_open)):
mock_diff = MagicMock(return_value=['+ zabbix-agent'])
with patch('difflib.unified_diff', mock_diff):
self.assertDictEqual(augeas.change(self.name,
changes=self.fp_changes),
self.ret)
def test_change_no_context_without_full_path_invalid_cmd(self):
'''
Test handling of invalid commands when no context supplied
'''
self.ret.update(dict(comment='Error: Command det is not supported (yet)',
result=False))
with patch.dict(augeas.__opts__, {'test': False}):
mock_execute = MagicMock(return_value=dict(retval=True))
mock_dict_ = {'augeas.execute': mock_execute,
'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
changes = ['det service-name[last()] zabbix-agent']
self.assertDictEqual(augeas.change(self.name,
changes=changes),
self.ret)
def test_change_no_context_without_full_path_invalid_change(self):
'''
Test handling of invalid change when no context supplied
'''
comt = ('Error: Invalid formatted command, see '
'debug log for details: require')
self.ret.update(dict(comment=comt,
result=False))
changes = ['require']
with patch.dict(augeas.__opts__, {'test': False}):
mock_execute = MagicMock(return_value=dict(retval=True))
mock_dict_ = {'augeas.execute': mock_execute,
'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
self.assertDictEqual(augeas.change(self.name,
changes=changes),
self.ret)
def test_change_no_context_with_full_path_multiple_files(self):
'''
Test handling of different paths with no context supplied
'''
changes = ['set /files/etc/hosts/service-name test',
'set /files/etc/services/service-name test']
filename = '/etc/hosts/service-name'
filename_ = '/etc/services/service-name'
comt = 'Error: Changes should be made to one file at a time, ' \
'detected changes to {0} and {1}'.format(filename, filename_)
self.ret.update(dict(comment=comt,
result=False))
with patch.dict(augeas.__opts__, {'test': False}):
mock_execute = MagicMock(return_value=dict(retval=True))
mock_dict_ = {'augeas.execute': mock_execute,
'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
self.assertDictEqual(augeas.change(self.name,
changes=changes),
self.ret)
def test_change_with_context_without_full_path_fail(self):
'''
Test handling of context without full path fails
'''
self.ret.update(dict(comment='Error: error', result=False))
with patch.dict(augeas.__opts__, {'test': False}):
mock_execute = MagicMock(
return_value=dict(retval=False, error='error'))
mock_dict_ = {'augeas.execute': mock_execute,
'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
with patch('salt.utils.files.fopen', MagicMock(mock_open)):
self.assertDictEqual(augeas.change(self.name,
context=self.context,
changes=self.changes),
self.ret)
def test_change_with_context_without_old_file(self):
'''
Test handling of context without oldfile pass
'''
self.ret.update(dict(comment='Changes have been saved',
result=True,
changes={'updates': self.changes}))
with patch.dict(augeas.__opts__, {'test': False}):
mock_execute = MagicMock(return_value=dict(retval=True))
mock_dict_ = {'augeas.execute': mock_execute,
'augeas.method_map': self.mock_method_map}
with patch.dict(augeas.__salt__, mock_dict_):
mock_isfile = MagicMock(return_value=False)
with patch.object(os.path, 'isfile', mock_isfile):
self.assertDictEqual(augeas.change(self.name,
context=self.context,
changes=self.changes),
self.ret)