Merge pull request #177 from ChrisMacNaughton/glob-permissions
Allow file assertions to include globs
This commit is contained in:
64
unit_tests/utilities/test_zaza_utilities_file_assertions.py
Normal file
64
unit_tests/utilities/test_zaza_utilities_file_assertions.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# Copyright 2018 Canonical Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
import unit_tests.utils as ut_utils
|
||||
import zaza.utilities.file_assertions as file_assertions
|
||||
|
||||
|
||||
class TestFileAssertionUtils(ut_utils.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestFileAssertionUtils, self).setUp()
|
||||
# Patch all run_on_unit calls
|
||||
self.patch(
|
||||
'zaza.utilities.file_assertions.model.run_on_unit',
|
||||
new_callable=mock.MagicMock(),
|
||||
name='run_on_unit'
|
||||
)
|
||||
self._assert = mock.MagicMock()
|
||||
self._assert.assertEqual = mock.MagicMock()
|
||||
|
||||
def test_path_glob(self):
|
||||
self.run_on_unit.return_value = {
|
||||
'Stdout': 'file-name root root 600'
|
||||
}
|
||||
file_details = {'path': '*'}
|
||||
file_assertions.assert_path_glob(
|
||||
self._assert, 'test/0', file_details)
|
||||
self.run_on_unit.assert_called_once_with(
|
||||
'test/0', 'bash -c "shopt -s -q globstar;'
|
||||
' stat -c "%n %U %G %a" *"')
|
||||
|
||||
def test_single_path(self):
|
||||
self.run_on_unit.return_value = {
|
||||
'Stdout': 'root root 600'
|
||||
}
|
||||
file_details = {'path': 'test'}
|
||||
file_assertions.assert_single_file(
|
||||
self._assert, 'test/0', file_details)
|
||||
self.run_on_unit.assert_called_once_with(
|
||||
'test/0', 'stat -c "%U %G %a" test')
|
||||
|
||||
def test_error_message_glob(self):
|
||||
message = file_assertions._error_message(
|
||||
"Owner", "test/0", "root", "/path/to/something")
|
||||
self.assertEqual(
|
||||
message,
|
||||
"Owner is incorrect for /path/to/something on test/0: root")
|
||||
|
||||
def test_error_message_single(self):
|
||||
|
||||
message = file_assertions._error_message(
|
||||
"Owner", "test/0", "root")
|
||||
self.assertEqual(message, "Owner is incorrect on test/0: root")
|
||||
@@ -20,31 +20,20 @@ import unittest
|
||||
|
||||
import zaza.model as model
|
||||
import zaza.charm_lifecycle.utils as utils
|
||||
from zaza.utilities.file_assertions import (
|
||||
assert_path_glob,
|
||||
assert_single_file,
|
||||
)
|
||||
|
||||
|
||||
def _make_test_function(application, file_details):
|
||||
def _make_test_function(application, file_details, paths=None):
|
||||
def test(self):
|
||||
expected_owner = file_details.get("owner", "root")
|
||||
expected_group = file_details.get("group", "root")
|
||||
expected_mode = file_details.get("mode", "600")
|
||||
for unit in model.get_units(application):
|
||||
unit = unit.entity_id
|
||||
result = model.run_on_unit(
|
||||
unit, 'stat -c "%U %G %a" {}'.format(file_details['path']))
|
||||
ownership = result['Stdout']
|
||||
owner, group, mode = ownership.split()
|
||||
self.assertEqual(expected_owner,
|
||||
owner,
|
||||
"Owner is incorrect for {}: {}"
|
||||
.format(unit, owner))
|
||||
self.assertEqual(expected_group,
|
||||
group,
|
||||
"Group is incorrect for {}: {}"
|
||||
.format(unit, group))
|
||||
self.assertEqual(expected_mode,
|
||||
mode,
|
||||
"Mode is incorrect for {}: {}"
|
||||
.format(unit, mode))
|
||||
if '*' in file_details['path']:
|
||||
assert_path_glob(self, unit, file_details, paths)
|
||||
else:
|
||||
assert_single_file(self, unit, file_details)
|
||||
return test
|
||||
|
||||
|
||||
@@ -56,8 +45,13 @@ def _add_tests():
|
||||
for name, attributes in files.items():
|
||||
# Lets make sure to only add tests for deployed applications
|
||||
if name in deployed_applications:
|
||||
paths = [
|
||||
file['path'] for
|
||||
file in attributes['files']
|
||||
if "*" not in file["path"]
|
||||
]
|
||||
for file in attributes['files']:
|
||||
test_func = _make_test_function(name, file)
|
||||
test_func = _make_test_function(name, file, paths=paths)
|
||||
setattr(
|
||||
cls,
|
||||
'test_{}_{}'.format(name, file['path']),
|
||||
|
||||
72
zaza/utilities/file_assertions.py
Normal file
72
zaza/utilities/file_assertions.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# Copyright 2018 Canonical Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Module of helpers for Zaza file assertions."""
|
||||
|
||||
import zaza.model as model
|
||||
|
||||
|
||||
def assert_path_glob(test_case, unit, file_details, paths=None):
|
||||
"""Verify all files in a given directory."""
|
||||
if not paths:
|
||||
paths = []
|
||||
result = model.run_on_unit(
|
||||
unit, 'bash -c "'
|
||||
'shopt -s -q globstar; '
|
||||
'stat -c "%n %U %G %a" {}"'.format(file_details['path']))
|
||||
files = result['Stdout']
|
||||
for file in files.splitlines():
|
||||
file, owner, group, mode = file.split()
|
||||
if file not in paths and file not in ['.', '..']:
|
||||
verify_file(test_case,
|
||||
unit,
|
||||
file_details,
|
||||
owner,
|
||||
group,
|
||||
mode,
|
||||
path=file)
|
||||
|
||||
|
||||
def assert_single_file(test_case, unit, file_details):
|
||||
"""Verify ownership of a single file."""
|
||||
result = model.run_on_unit(
|
||||
unit, 'stat -c "%U %G %a" {}'.format(file_details['path']))
|
||||
ownership = result['Stdout']
|
||||
owner, group, mode = ownership.split()
|
||||
verify_file(test_case, unit, file_details, owner, group, mode)
|
||||
|
||||
|
||||
def verify_file(test_case, unit, file_details,
|
||||
actual_owner, actual_group, actual_mode, path=None):
|
||||
"""Assert file has correct permissions."""
|
||||
expected_owner = file_details.get("owner", "root")
|
||||
expected_group = file_details.get("group", "root")
|
||||
expected_mode = file_details.get("mode", "600")
|
||||
test_case.assertEqual(expected_owner,
|
||||
actual_owner,
|
||||
_error_message("Owner", unit, actual_owner, path))
|
||||
test_case.assertEqual(expected_group,
|
||||
actual_group,
|
||||
_error_message("Group", unit, actual_group, path))
|
||||
test_case.assertEqual(expected_mode,
|
||||
actual_mode,
|
||||
_error_message("Mode", unit, actual_mode, path))
|
||||
|
||||
|
||||
def _error_message(thing, unit, value, path=None):
|
||||
if path:
|
||||
return "{} is incorrect for {} on {}: {}".format(
|
||||
thing, path, unit, value)
|
||||
else:
|
||||
return "{} is incorrect on {}: {}".format(thing, unit, value)
|
||||
Reference in New Issue
Block a user