-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dialogs: Create audit entries for dialog answers
Previously dialog answers have not been tracked in the audit. This patch introduces a new event type dialog-answer that will be emitted every time a dialog answer is requested or received. This will report any answers that are provided through answerfile or interactive reply. Signed-off-by: Vinzenz Feenstra <[email protected]>
- Loading branch information
Showing
2 changed files
with
322 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,314 @@ | ||
import pytest | ||
|
||
import leapp.messaging.answerstore | ||
from leapp.messaging.answerstore import AnswerStore, multiprocessing | ||
|
||
|
||
class MockManager(object): | ||
def __call__(self): | ||
return self | ||
|
||
@staticmethod | ||
def dict(*args): | ||
return dict(*args) | ||
|
||
|
||
class MockComponentKey1(object): | ||
value_type = str | ||
key = 'key1' | ||
label = 'label key1' | ||
description = 'description key1' | ||
default = False | ||
value = None | ||
|
||
|
||
class MockComponentKey2(object): | ||
value_type = str | ||
key = 'key2' | ||
label = 'label key2' | ||
description = 'description key2' | ||
default = 'Default' | ||
value = None | ||
|
||
|
||
class MockComponentKey1Bool(object): | ||
value_type = bool | ||
key = 'key1' | ||
label = 'label bool key1' | ||
description = 'description bool key1' | ||
default = True | ||
value = None | ||
|
||
|
||
class MockComponentKey2Bool(object): | ||
value_type = bool | ||
key = 'key2' | ||
label = 'label bool key2' | ||
description = 'description bool key2' | ||
default = False | ||
value = None | ||
|
||
|
||
class MockDialogScope1(object): | ||
scope = 'scope1' | ||
title = 'Mock Dialog scope1' | ||
reason = 'Mock Test Data for scope1' | ||
components = (MockComponentKey1, MockComponentKey2) | ||
|
||
|
||
class MockDialogScope2(object): | ||
scope = 'scope2' | ||
title = 'Mock Dialog scope2' | ||
reason = 'Mock Test Data for scope2' | ||
components = (MockComponentKey1, MockComponentKey2) | ||
|
||
|
||
class MockDialogBoolScope(object): | ||
scope = 'boolscope' | ||
title = 'Mock Dialog boolscope' | ||
reason = 'Mock Test Data for boolscope' | ||
components = (MockComponentKey1Bool, MockComponentKey2Bool) | ||
|
||
|
||
class MockWorkflow(object): | ||
dialogs = (MockDialogScope1, MockDialogScope2, MockDialogBoolScope) | ||
|
||
|
||
@pytest.fixture(scope='function') | ||
def answerfile_data(): | ||
yield ''' | ||
[scope1] | ||
key1=scope1.key1 | ||
key2=scope1.key2 | ||
[scope2] | ||
key1=scope2.key1 | ||
key2=scope2.key2 | ||
[boolscope] | ||
key1=True | ||
Key2=False | ||
''' | ||
|
||
|
||
@pytest.fixture(scope='function', name='answerfile') | ||
def answerfile_file(tmpdir, answerfile_data): | ||
d = tmpdir.join('answerfile') | ||
d.mkdir() | ||
f = d.join('data.ini') | ||
f.write(answerfile_data) | ||
yield str(f) | ||
|
||
|
||
def test_answerstore_init(monkeypatch): | ||
manager = MockManager() | ||
assert type(AnswerStore()._storage) is multiprocessing.managers.DictProxy | ||
monkeypatch.setattr(multiprocessing, 'Manager', MockManager()) | ||
assert type(AnswerStore(manager=manager)._storage) is dict | ||
assert type(AnswerStore()._storage) is dict | ||
|
||
|
||
def test_answerstore_answer(): | ||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.answer(scope='scope1', key='key1', value='scope1.key1') | ||
a.answer(scope='scope1', key='key2', value='scope1.key2') | ||
a.answer(scope='scope2', key='key1', value='scope2.key1') | ||
a.answer(scope='scope2', key='key2', value='scope2.key2') | ||
assert 'scope1' in store.keys() | ||
assert 'scope2' in store.keys() | ||
assert 'key1' in store['scope1'].keys() | ||
assert 'key1' in store['scope1'].keys() | ||
assert 'key1' in store['scope2'] | ||
assert 'key2' in store['scope2'] | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
|
||
|
||
def test_answerstore_update(answerfile, answerfile_data, tmpdir): | ||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.load(answerfile) | ||
assert store['boolscope']['key1'] == 'True' | ||
assert store['boolscope']['key2'] == 'False' | ||
a.answer('boolscope', 'key1', False) | ||
a.answer('boolscope', 'key2', True) | ||
assert store['boolscope']['key1'] is False | ||
assert store['boolscope']['key2'] is True | ||
f = tmpdir.join('test_answerstore_update') | ||
f.write(answerfile_data) | ||
a.update(str(f)) | ||
a2 = AnswerStore(manager=m) | ||
store2 = a2._storage | ||
a2.load(str(f)) | ||
assert store2['boolscope']['key1'] == 'False' | ||
assert store2['boolscope']['key2'] == 'True' | ||
assert store2['scope1']['key1'] == 'scope1.key1' | ||
assert store2['scope1']['key2'] == 'scope1.key2' | ||
assert store2['scope2']['key1'] == 'scope2.key1' | ||
assert store2['scope2']['key2'] == 'scope2.key2' | ||
|
||
|
||
def test_answerstore_load(answerfile): | ||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.load(answerfile) | ||
assert 'scope1' in store.keys() | ||
assert 'scope2' in store.keys() | ||
assert 'boolscope' in store.keys() | ||
assert 'key1' in store['scope1'].keys() | ||
assert 'key1' in store['scope1'].keys() | ||
assert 'key1' in store['scope2'] | ||
assert 'key2' in store['scope2'] | ||
assert 'key1' in store['boolscope'] | ||
assert 'key2' in store['boolscope'] | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
assert store['boolscope']['key1'] == 'True' | ||
assert store['boolscope']['key2'] == 'False' | ||
|
||
|
||
def test_answerstore_load_and_translate_for_workflow(answerfile): | ||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.load_and_translate_for_workflow(answerfile, MockWorkflow) | ||
assert store['boolscope']['key1'] is True | ||
assert store['boolscope']['key2'] is False | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
|
||
|
||
def test_answerfile_get(monkeypatch, answerfile): | ||
entries_created = [] | ||
|
||
def mocked_create_audit_entry(event, data, message=None): | ||
entries_created.append((event, data, message)) | ||
|
||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.load(answerfile) | ||
monkeypatch.setattr(leapp.messaging.answerstore, 'create_audit_entry', mocked_create_audit_entry) | ||
|
||
# Testing boolscope | ||
assert store['boolscope']['key1'] == 'True' | ||
assert store['boolscope']['key2'] == 'False' | ||
result = a.get(scope='boolscope', fallback='boolscope') | ||
assert result != 'boolscope' | ||
assert result['key1'] == 'True' | ||
assert result['key2'] == 'False' | ||
assert entries_created | ||
assert entries_created[0][1]['scope'] == 'boolscope' | ||
assert entries_created[0][1]['fallback'] == 'boolscope' | ||
assert entries_created[0][1]['answer']['key1'] == 'True' | ||
assert entries_created[0][1]['answer']['key2'] == 'False' | ||
entries_created.pop() | ||
|
||
# Testing scope1 | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
result = a.get(scope='scope1', fallback='scope1') | ||
assert result | ||
assert result['key1'] == 'scope1.key1' | ||
assert result['key2'] == 'scope1.key2' | ||
assert entries_created | ||
assert entries_created[0][1]['scope'] == 'scope1' | ||
assert entries_created[0][1]['fallback'] == 'scope1' | ||
assert entries_created[0][1]['answer']['key1'] == 'scope1.key1' | ||
assert entries_created[0][1]['answer']['key2'] == 'scope1.key2' | ||
entries_created.pop() | ||
|
||
# Testing scope2 | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
|
||
result = a.get(scope='scope2', fallback='scope2') | ||
assert result | ||
assert result['key1'] == 'scope2.key1' | ||
assert result['key2'] == 'scope2.key2' | ||
assert entries_created | ||
assert entries_created[0][1]['scope'] == 'scope2' | ||
assert entries_created[0][1]['fallback'] == 'scope2' | ||
assert entries_created[0][1]['answer']['key1'] == 'scope2.key1' | ||
assert entries_created[0][1]['answer']['key2'] == 'scope2.key2' | ||
entries_created.pop() | ||
|
||
|
||
def test_answerfile_translate_for_workflow(answerfile): | ||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.load(answerfile) | ||
assert store['boolscope']['key1'] == 'True' | ||
assert store['boolscope']['key2'] == 'False' | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
a.translate_for_workflow(MockWorkflow) | ||
assert store['boolscope']['key1'] is True | ||
assert store['boolscope']['key2'] is False | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
|
||
|
||
def test_answerfile_translate(answerfile): | ||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.load(answerfile) | ||
assert store['boolscope']['key1'] == 'True' | ||
assert store['boolscope']['key2'] == 'False' | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
a.translate(MockDialogBoolScope) | ||
assert store['boolscope']['key1'] is True | ||
assert store['boolscope']['key2'] is False | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
|
||
|
||
def test_answerfile_generate(tmpdir, answerfile): | ||
f = tmpdir.join('test_answerfile_generate') | ||
m = MockManager() | ||
a = AnswerStore(manager=m) | ||
store = a._storage | ||
a.load_and_translate_for_workflow(answerfile, MockWorkflow) | ||
assert store['scope1']['key1'] == 'scope1.key1' | ||
assert store['scope1']['key2'] == 'scope1.key2' | ||
assert store['scope2']['key1'] == 'scope2.key1' | ||
assert store['scope2']['key2'] == 'scope2.key2' | ||
assert store['boolscope']['key1'] is True | ||
assert store['boolscope']['key2'] is False | ||
a.answer('scope1', 'key1', 'generate.scope1.key1') | ||
a.answer('scope1', 'key2', 'generate.scope1.key2') | ||
a.answer('scope2', 'key1', 'generate.scope2.key1') | ||
a.answer('scope2', 'key2', 'generate.scope2.key2') | ||
a.answer('boolscope', 'key1', False) | ||
a.answer('boolscope', 'key2', True) | ||
a.generate(MockWorkflow.dialogs, str(f)) | ||
a = AnswerStore(manager=m) | ||
store2 = a._storage | ||
a.load_and_translate_for_workflow(str(f), MockWorkflow) | ||
assert store2['scope1']['key1'] == 'generate.scope1.key1' | ||
assert store2['scope1']['key2'] == 'generate.scope1.key2' | ||
assert store2['scope2']['key1'] == 'generate.scope2.key1' | ||
assert store2['scope2']['key2'] == 'generate.scope2.key2' | ||
assert store2['boolscope']['key1'] is False | ||
assert store2['boolscope']['key2'] is True |