mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Refactor test_sudocmd_plugin
Reviewed-By: Ales 'alich' Marecek <amarecek@redhat.com>
This commit is contained in:
@@ -21,309 +21,173 @@
|
||||
Test the `ipalib/plugins/sudocmd.py` module.
|
||||
"""
|
||||
|
||||
from ipalib import errors
|
||||
from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, fuzzy_sudocmddn,
|
||||
fuzzy_uuid)
|
||||
from ipatests.test_xmlrpc import objectclasses
|
||||
from ipalib import api, errors
|
||||
from ipatests.util import assert_deepequal
|
||||
from ipatests.test_xmlrpc.xmlrpc_test import (XMLRPC_test, raises_exact)
|
||||
from ipatests.test_xmlrpc.tracker.sudocmd_plugin import SudoCmdTracker
|
||||
import pytest
|
||||
|
||||
sudocmd1 = u'/usr/bin/sudotestcmd1'
|
||||
sudocmd1_camelcase = u'/usr/bin/sudoTestCmd1'
|
||||
|
||||
sudorule1 = u'test_sudorule1'
|
||||
@pytest.fixture(scope='class')
|
||||
def sudocmd1(request):
|
||||
tracker = SudoCmdTracker(command=u'/usr/bin/sudotestcmd1',
|
||||
description=u'Test sudo command 1')
|
||||
return tracker.make_fixture(request)
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def sudocmd2(request):
|
||||
tracker = SudoCmdTracker(command=u'/usr/bin/sudoTestCmd1',
|
||||
description=u'Test sudo command 2')
|
||||
return tracker.make_fixture(request)
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def sudorule1(request):
|
||||
name = u'test_sudorule1'
|
||||
|
||||
def fin():
|
||||
api.Command['sudorule_del'](name)
|
||||
request.addfinalizer(fin)
|
||||
return name
|
||||
|
||||
|
||||
@pytest.mark.tier1
|
||||
class test_sudocmd(Declarative):
|
||||
class TestNonexistentSudoCmd(XMLRPC_test):
|
||||
def test_retrieve_nonexistent(self, sudocmd1):
|
||||
""" Try to retrieve non-existent sudocmd """
|
||||
command = sudocmd1.make_retrieve_command()
|
||||
with raises_exact(errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1.cmd)):
|
||||
command()
|
||||
|
||||
cleanup_commands = [
|
||||
('sudocmd_del', [sudocmd1], {}),
|
||||
('sudocmd_del', [sudocmd1_camelcase], {}),
|
||||
('sudorule_del', [sudorule1], {}),
|
||||
]
|
||||
def test_update_nonexistent(self, sudocmd1):
|
||||
""" Try to update non-existent sudocmd """
|
||||
command = sudocmd1.make_update_command(dict(description=u'Nope'))
|
||||
with raises_exact(errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1.cmd)):
|
||||
command()
|
||||
|
||||
tests = [
|
||||
|
||||
dict(
|
||||
desc='Try to retrieve non-existent %r' % sudocmd1,
|
||||
command=('sudocmd_show', [sudocmd1], {}),
|
||||
expected=errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1),
|
||||
),
|
||||
def test_delete_nonexistent(self, sudocmd1):
|
||||
""" Try to delete non-existent sudocmd """
|
||||
command = sudocmd1.make_delete_command()
|
||||
with raises_exact(errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1.cmd)):
|
||||
command()
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to update non-existent %r' % sudocmd1,
|
||||
command=('sudocmd_mod', [sudocmd1], dict(description=u'Nope')),
|
||||
expected=errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1),
|
||||
),
|
||||
@pytest.mark.tier1
|
||||
class TestSudoCmd(XMLRPC_test):
|
||||
def test_create(self, sudocmd1, sudocmd2):
|
||||
""" Create sudocmd and sudocmd with camelcase'd command """
|
||||
sudocmd1.ensure_exists()
|
||||
sudocmd2.ensure_exists()
|
||||
|
||||
def test_create_duplicates(self, sudocmd1, sudocmd2):
|
||||
""" Try to create duplicate sudocmds """
|
||||
sudocmd1.ensure_exists()
|
||||
sudocmd2.ensure_exists()
|
||||
command1 = sudocmd1.make_create_command()
|
||||
command2 = sudocmd2.make_create_command()
|
||||
|
||||
with raises_exact(errors.DuplicateEntry(
|
||||
message=u'sudo command with name "%s" already exists' %
|
||||
sudocmd1.cmd)):
|
||||
command1()
|
||||
with raises_exact(errors.DuplicateEntry(
|
||||
message=u'sudo command with name "%s" already exists' %
|
||||
sudocmd2.cmd)):
|
||||
command2()
|
||||
|
||||
def test_retrieve(self, sudocmd1):
|
||||
""" Retrieve sudocmd """
|
||||
sudocmd1.ensure_exists()
|
||||
sudocmd1.retrieve()
|
||||
|
||||
def test_search(self, sudocmd1, sudocmd2):
|
||||
""" Search for sudocmd """
|
||||
sudocmd1.find()
|
||||
sudocmd2.find()
|
||||
|
||||
def test_update_and_verify(self, sudocmd1):
|
||||
""" Update sudocmd description and verify by retrieve """
|
||||
sudocmd1_desc_new = u'Updated sudo command 1'
|
||||
sudocmd1.update(dict(description=sudocmd1_desc_new),
|
||||
dict(description=[sudocmd1_desc_new]))
|
||||
sudocmd1.retrieve()
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to delete non-existent %r' % sudocmd1,
|
||||
command=('sudocmd_del', [sudocmd1], {}),
|
||||
expected=errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1),
|
||||
),
|
||||
@pytest.mark.tier1
|
||||
class TestSudoCmdInSudoRuleLists(XMLRPC_test):
|
||||
def test_add_sudocmd_to_sudorule_allow_list(self, sudocmd1, sudorule1):
|
||||
""" Add sudocmd to sudorule allow list """
|
||||
sudocmd1.ensure_exists()
|
||||
api.Command['sudorule_add'](sudorule1)
|
||||
result = api.Command['sudorule_add_allow_command'](
|
||||
sudorule1, sudocmd=sudocmd1.cmd
|
||||
)
|
||||
assert_deepequal(dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberallowcmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True,
|
||||
), result)
|
||||
|
||||
def test_del_dependent_sudocmd_sudorule_allow(self, sudocmd1, sudorule1):
|
||||
""" Try to delete sudocmd that is in sudorule allow list """
|
||||
sudocmd1.ensure_exists()
|
||||
command = sudocmd1.make_delete_command()
|
||||
with raises_exact(errors.DependentEntry(
|
||||
key=sudocmd1.cmd,
|
||||
label='sudorule',
|
||||
dependent=sudorule1)):
|
||||
command()
|
||||
|
||||
dict(
|
||||
desc='Create %r' % sudocmd1,
|
||||
command=('sudocmd_add', [sudocmd1],
|
||||
dict(
|
||||
description=u'Test sudo command 1',
|
||||
),
|
||||
),
|
||||
expected=dict(
|
||||
value=sudocmd1,
|
||||
summary=u'Added Sudo Command "%s"' % sudocmd1,
|
||||
result=dict(
|
||||
dn=fuzzy_sudocmddn,
|
||||
sudocmd=[sudocmd1],
|
||||
description=[u'Test sudo command 1'],
|
||||
objectclass=objectclasses.sudocmd,
|
||||
ipauniqueid=[fuzzy_uuid],
|
||||
),
|
||||
),
|
||||
),
|
||||
def test_remove_sudocmd_from_sudorule_allow(self, sudocmd1, sudorule1):
|
||||
""" Remove sudocmd from sudorule allow list """
|
||||
sudocmd1.ensure_exists()
|
||||
result = api.Command['sudorule_remove_allow_command'](
|
||||
sudorule1, sudocmd=sudocmd1.cmd
|
||||
)
|
||||
assert_deepequal(dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberallowcmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True),
|
||||
result)
|
||||
|
||||
dict(
|
||||
desc='Create %r' % sudocmd1_camelcase,
|
||||
command=('sudocmd_add', [sudocmd1_camelcase],
|
||||
dict(
|
||||
description=u'Test sudo command 2',
|
||||
),
|
||||
),
|
||||
expected=dict(
|
||||
value=sudocmd1_camelcase,
|
||||
summary=u'Added Sudo Command "%s"' % sudocmd1_camelcase,
|
||||
result=dict(
|
||||
dn=fuzzy_sudocmddn,
|
||||
sudocmd=[sudocmd1_camelcase],
|
||||
description=[u'Test sudo command 2'],
|
||||
objectclass=objectclasses.sudocmd,
|
||||
ipauniqueid=[fuzzy_uuid],
|
||||
),
|
||||
),
|
||||
),
|
||||
def test_add_sudocmd_to_sudorule_deny_list(self, sudocmd1, sudorule1):
|
||||
""" Add sudocmd to sudorule deny list """
|
||||
sudocmd1.ensure_exists()
|
||||
result = api.Command['sudorule_add_deny_command'](
|
||||
sudorule1, sudocmd=sudocmd1.cmd
|
||||
)
|
||||
assert_deepequal(dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberdenycmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True),
|
||||
result)
|
||||
|
||||
def test_del_dependent_sudocmd_sudorule_deny(self, sudocmd1, sudorule1):
|
||||
""" Try to delete sudocmd that is in sudorule deny list """
|
||||
sudocmd1.ensure_exists()
|
||||
command = sudocmd1.make_delete_command()
|
||||
with raises_exact(errors.DependentEntry(
|
||||
key=sudocmd1.cmd,
|
||||
label='sudorule',
|
||||
dependent=sudorule1)):
|
||||
command()
|
||||
|
||||
dict(
|
||||
desc='Try to create duplicate %r' % sudocmd1,
|
||||
command=('sudocmd_add', [sudocmd1],
|
||||
dict(
|
||||
description=u'Test sudo command 1',
|
||||
),
|
||||
),
|
||||
expected=errors.DuplicateEntry(message=u'sudo command with ' +
|
||||
u'name "%s" already exists' % sudocmd1),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Try to create duplicate %r' % sudocmd1_camelcase,
|
||||
command=('sudocmd_add', [sudocmd1_camelcase],
|
||||
dict(
|
||||
description=u'Test sudo command 2',
|
||||
),
|
||||
),
|
||||
expected=errors.DuplicateEntry(message=u'sudo command with ' +
|
||||
u'name "%s" already exists' % sudocmd1_camelcase),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Retrieve %r' % sudocmd1,
|
||||
command=('sudocmd_show', [sudocmd1], {}),
|
||||
expected=dict(
|
||||
value=sudocmd1,
|
||||
summary=None,
|
||||
result=dict(
|
||||
dn=fuzzy_sudocmddn,
|
||||
sudocmd=[sudocmd1],
|
||||
description=[u'Test sudo command 1'],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Search for %r' % sudocmd1,
|
||||
command=('sudocmd_find', [sudocmd1], {}),
|
||||
expected=dict(
|
||||
count=1,
|
||||
truncated=False,
|
||||
summary=u'1 Sudo Command matched',
|
||||
result=[
|
||||
dict(
|
||||
dn=fuzzy_sudocmddn,
|
||||
sudocmd=[sudocmd1],
|
||||
description=[u'Test sudo command 1'],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Search for %r' % sudocmd1_camelcase,
|
||||
command=('sudocmd_find', [sudocmd1_camelcase], {}),
|
||||
expected=dict(
|
||||
count=1,
|
||||
truncated=False,
|
||||
summary=u'1 Sudo Command matched',
|
||||
result=[
|
||||
dict(
|
||||
dn=fuzzy_sudocmddn,
|
||||
sudocmd=[sudocmd1_camelcase],
|
||||
description=[u'Test sudo command 2'],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Update %r' % sudocmd1,
|
||||
command=('sudocmd_mod', [sudocmd1], dict(
|
||||
description=u'Updated sudo command 1')),
|
||||
expected=dict(
|
||||
value=sudocmd1,
|
||||
summary=u'Modified Sudo Command "%s"' % sudocmd1,
|
||||
result=dict(
|
||||
sudocmd=[sudocmd1],
|
||||
description=[u'Updated sudo command 1'],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Retrieve %r to verify update' % sudocmd1,
|
||||
command=('sudocmd_show', [sudocmd1], {}),
|
||||
expected=dict(
|
||||
value=sudocmd1,
|
||||
summary=None,
|
||||
result=dict(
|
||||
dn=fuzzy_sudocmddn,
|
||||
sudocmd=[sudocmd1],
|
||||
description=[u'Updated sudo command 1'],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Create %r' % sudorule1,
|
||||
command=('sudorule_add', [sudorule1], {}),
|
||||
expected=lambda e, result: True,
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Add %r to %r allow list' % (sudocmd1, sudorule1),
|
||||
command=('sudorule_add_allow_command', [sudorule1],
|
||||
dict(sudocmd=sudocmd1)),
|
||||
expected=dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberallowcmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True,
|
||||
),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc="Test %r can't be deleted when in %r" % (sudocmd1, sudorule1),
|
||||
command=('sudocmd_del', [sudocmd1], {}),
|
||||
expected=errors.DependentEntry(key=sudocmd1, label='sudorule',
|
||||
dependent=sudorule1),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Remove %r from %r' % (sudocmd1, sudorule1),
|
||||
command=('sudorule_remove_allow_command', [sudorule1],
|
||||
dict(sudocmd=sudocmd1)),
|
||||
expected=dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberallowcmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True,
|
||||
),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Add %r to %r deny list' % (sudocmd1, sudorule1),
|
||||
command=('sudorule_add_deny_command', [sudorule1],
|
||||
dict(sudocmd=sudocmd1)),
|
||||
expected=dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberdenycmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True,
|
||||
),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc="Test %r can't be deleted when in %r" % (sudocmd1, sudorule1),
|
||||
command=('sudocmd_del', [sudocmd1], {}),
|
||||
expected=errors.DependentEntry(key=sudocmd1, label='sudorule',
|
||||
dependent=sudorule1),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Remove %r from %r' % (sudocmd1, sudorule1),
|
||||
command=('sudorule_remove_deny_command', [sudorule1],
|
||||
dict(sudocmd=sudocmd1)),
|
||||
expected=dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberdenycmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True,
|
||||
),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Delete %r' % sudocmd1,
|
||||
command=('sudocmd_del', [sudocmd1], {}),
|
||||
expected=dict(
|
||||
value=[sudocmd1],
|
||||
summary=u'Deleted Sudo Command "%s"' % sudocmd1,
|
||||
result=dict(failed=[]),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to retrieve non-existent %r' % sudocmd1,
|
||||
command=('sudocmd_show', [sudocmd1], {}),
|
||||
expected=errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to update non-existent %r' % sudocmd1,
|
||||
command=('sudocmd_mod', [sudocmd1], dict(description=u'Nope')),
|
||||
expected=errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to delete non-existent %r' % sudocmd1,
|
||||
command=('sudocmd_del', [sudocmd1], {}),
|
||||
expected=errors.NotFound(
|
||||
reason=u'%s: sudo command not found' % sudocmd1),
|
||||
),
|
||||
|
||||
dict(
|
||||
desc='Retrieve %r' % sudocmd1_camelcase,
|
||||
command=('sudocmd_show', [sudocmd1_camelcase], {}),
|
||||
expected=dict(
|
||||
value=sudocmd1_camelcase,
|
||||
summary=None,
|
||||
result=dict(
|
||||
dn=fuzzy_sudocmddn,
|
||||
sudocmd=[sudocmd1_camelcase],
|
||||
description=[u'Test sudo command 2'],
|
||||
),
|
||||
),
|
||||
),
|
||||
]
|
||||
def test_remove_sudocmd_from_sudorule_deny(self, sudocmd1, sudorule1):
|
||||
""" Remove sudocmd from sudorule deny list """
|
||||
sudocmd1.ensure_exists()
|
||||
result = api.Command['sudorule_remove_deny_command'](
|
||||
sudorule1, sudocmd=sudocmd1.cmd
|
||||
)
|
||||
assert_deepequal(dict(
|
||||
completed=1,
|
||||
failed=dict(
|
||||
memberdenycmd=dict(sudocmdgroup=(), sudocmd=())),
|
||||
result=lambda result: True),
|
||||
result)
|
||||
|
||||
113
ipatests/test_xmlrpc/tracker/sudocmd_plugin.py
Normal file
113
ipatests/test_xmlrpc/tracker/sudocmd_plugin.py
Normal file
@@ -0,0 +1,113 @@
|
||||
#
|
||||
# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
from ipatests.test_xmlrpc import objectclasses
|
||||
from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_uuid, fuzzy_sudocmddn
|
||||
|
||||
from ipatests.test_xmlrpc.tracker.base import Tracker
|
||||
from ipatests.util import assert_deepequal
|
||||
|
||||
|
||||
class SudoCmdTracker(Tracker):
|
||||
""" Class for tracking sudo commands """
|
||||
retrieve_keys = {u'dn', u'sudocmd', u'description',
|
||||
u'memberof_sudocmdgroup'}
|
||||
retrieve_all_keys = retrieve_keys | {u'ipauniqueid', u'objectclass'}
|
||||
|
||||
create_keys = retrieve_all_keys
|
||||
update_keys = retrieve_keys - {u'dn'}
|
||||
|
||||
def __init__(self, command, description="Test sudo command"):
|
||||
super(SudoCmdTracker, self).__init__(default_version=None)
|
||||
self.cmd = command
|
||||
self.dn = fuzzy_sudocmddn
|
||||
self.description = description
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Property holding the name of the entry in LDAP """
|
||||
return self.cmd
|
||||
|
||||
def make_create_command(self, force=True):
|
||||
""" Make function that creates a sudocmd using 'sudocmd-add' """
|
||||
return self.make_command('sudocmd_add', self.cmd,
|
||||
description=self.description)
|
||||
|
||||
def make_delete_command(self):
|
||||
""" Make function that deletes a sudocmd using 'sudocmd-del' """
|
||||
return self.make_command('sudocmd_del', self.cmd)
|
||||
|
||||
def make_retrieve_command(self, all=False, raw=False):
|
||||
""" Make function that retrieves a sudocmd using 'sudocmd-show' """
|
||||
return self.make_command('sudocmd_show', self.cmd, all=all)
|
||||
|
||||
def make_find_command(self, *args, **kwargs):
|
||||
""" Make function that searches for a sudocmd using 'sudocmd-find' """
|
||||
return self.make_command('sudocmd_find', *args, **kwargs)
|
||||
|
||||
def make_update_command(self, updates):
|
||||
""" Make function that updates a sudocmd using 'sudocmd-mod' """
|
||||
return self.make_command('sudocmd_mod', self.cmd, **updates)
|
||||
|
||||
def track_create(self):
|
||||
""" Updates expected state for sudocmd creation"""
|
||||
self.attrs = dict(
|
||||
dn=self.dn,
|
||||
sudocmd=[self.cmd],
|
||||
description=[self.description],
|
||||
ipauniqueid=[fuzzy_uuid],
|
||||
objectclass=objectclasses.sudocmd,
|
||||
)
|
||||
self.exists = True
|
||||
|
||||
def check_create(self, result):
|
||||
""" Checks 'sudocmd_add' command result """
|
||||
assert_deepequal(dict(
|
||||
value=self.cmd,
|
||||
summary=u'Added Sudo Command "%s"' % self.cmd,
|
||||
result=self.filter_attrs(self.create_keys)
|
||||
), result)
|
||||
|
||||
def check_delete(self, result):
|
||||
""" Checks 'sudocmd_del' command result """
|
||||
assert_deepequal(dict(
|
||||
value=[self.cmd],
|
||||
summary=u'Deleted Sudo Command "%s"' % self.cmd,
|
||||
result=dict(failed=[]),
|
||||
), result)
|
||||
|
||||
def check_retrieve(self, result, all=False, raw=False):
|
||||
""" Checks 'sudocmd_show' command result """
|
||||
if all:
|
||||
expected = self.filter_attrs(self.retrieve_all_keys)
|
||||
else:
|
||||
expected = self.filter_attrs(self.retrieve_keys)
|
||||
|
||||
assert_deepequal(dict(
|
||||
value=self.cmd,
|
||||
summary=None,
|
||||
result=expected
|
||||
), result)
|
||||
|
||||
def check_find(self, result, all=False, raw=False):
|
||||
""" Checks 'sudocmd_find' command result """
|
||||
if all:
|
||||
expected = self.filter_attrs(self.retrieve_all_keys)
|
||||
else:
|
||||
expected = self.filter_attrs(self.retrieve_keys)
|
||||
|
||||
assert_deepequal(dict(
|
||||
count=1,
|
||||
truncated=False,
|
||||
summary=u'1 Sudo Command matched',
|
||||
result=[expected],
|
||||
), result)
|
||||
|
||||
def check_update(self, result, extra_keys={}):
|
||||
""" Checks 'sudocmd_mod' command result """
|
||||
assert_deepequal(dict(
|
||||
value=self.cmd,
|
||||
summary=u'Modified Sudo Command "%s"' % self.cmd,
|
||||
result=self.filter_attrs(self.update_keys | set(extra_keys))
|
||||
), result)
|
||||
Reference in New Issue
Block a user