Merge ~vultaire/charm-sudo-pair:focal into charm-sudo-pair:master

Proposed by Paul Goins
Status: Merged
Approved by: Paul Goins
Approved revision: dd7e04f18d182066d08b1a532513b202c246eda2
Merged at revision: dd7e04f18d182066d08b1a532513b202c246eda2
Proposed branch: ~vultaire/charm-sudo-pair:focal
Merge into: charm-sudo-pair:master
Diff against target: 188 lines (+51/-65)
1 file modified
tests/functional/test_deploy.py (+51/-65)
Reviewer Review Type Date Requested Status
Alvaro Uria (community) Approve
Review via email: mp+384398@code.launchpad.net

Description of the change

This is a resubmit of Wouter's MR (https://code.launchpad.net/~woutervb/charm-sudo-pair/+git/sudo-pair-charm/+merge/378781), updated to apply on top of the current top-level launchpad project's trunk.

To post a comment you must log in.
Revision history for this message
Paul Goins (vultaire) wrote :

Note: the first commit is the real change, the second commit is purely black's work.

Revision history for this message
Alvaro Uria (aluria) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/tests/functional/test_deploy.py b/tests/functional/test_deploy.py
index cdb5ae4..2f0f272 100644
--- a/tests/functional/test_deploy.py
+++ b/tests/functional/test_deploy.py
@@ -6,14 +6,16 @@ import pytest
66
7pytestmark = pytest.mark.asyncio7pytestmark = pytest.mark.asyncio
88
9charm_build_dir = os.getenv('CHARM_BUILD_DIR', '..').rstrip('/')9charm_build_dir = os.getenv("CHARM_BUILD_DIR", "..").rstrip("/")
1010
1111
12sources = [('local', '{}/builds/sudo-pair'.format(charm_build_dir))]12sources = [("local", "{}/builds/sudo-pair".format(charm_build_dir))]
1313
14series = ['xenial',14series = [
15 'bionic',15 "xenial",
16 ]16 "bionic",
17 "focal",
18]
1719
1820
19############21############
@@ -36,8 +38,8 @@ def source(request):
36@pytest.fixture38@pytest.fixture
37async def app(model, series, source):39async def app(model, series, source):
38 """Return application of the charm under test."""40 """Return application of the charm under test."""
39 app_name = 'sudo-pair-{}'.format(series)41 app_name = "sudo-pair-{}".format(series)
40 return await model._wait_for_new('application', app_name)42 return await model._wait_for_new("application", app_name)
4143
4244
43@pytest.fixture45@pytest.fixture
@@ -50,108 +52,92 @@ async def unit(app):
50# TESTS #52# TESTS #
51#########53#########
5254
55
53async def test_deploy_app(model, series, source):56async def test_deploy_app(model, series, source):
54 """Deploy the sudo_pair app as a subordinate of ubuntu."""57 """Deploy the sudo_pair app as a subordinate of ubuntu."""
55 await model.deploy(58 await model.deploy(
56 'ubuntu',59 "ubuntu", application_name="ubuntu-" + series, series=series, channel="stable"
57 application_name='ubuntu-' + series,
58 series=series,
59 channel='stable'
60 )60 )
61 sudo_pair_app = await model.deploy(61 sudo_pair_app = await model.deploy(
62 source[1],62 source[1],
63 application_name='sudo-pair-' + series,63 application_name="sudo-pair-" + series,
64 series=series,64 series=series,
65 num_units=0,65 num_units=0,
66 config={66 config={
67 'bypass_cmds': '/bin/ls',67 "bypass_cmds": "/bin/ls",
68 'groups_enforced': 'ubuntu',68 "groups_enforced": "ubuntu",
69 'bypass_group': 'warthogs',69 "bypass_group": "warthogs",
70 }70 },
71 )71 )
72 await model.add_relation(72 await model.add_relation(
73 'ubuntu-{}:juju-info'.format(series),73 "ubuntu-{}:juju-info".format(series), "sudo-pair-{}:juju-info".format(series)
74 'sudo-pair-{}:juju-info'.format(series))74 )
7575
76 await model.block_until(lambda: sudo_pair_app.status == 'active')76 await model.block_until(lambda: sudo_pair_app.status == "active")
77 # no need to cleanup since the model will be be torn down at the end of the77 # no need to cleanup since the model will be be torn down at the end of the
78 # testing78 # testing
7979
8080
81async def test_status(app):81async def test_status(app):
82 """Check that the app is in active state."""82 """Check that the app is in active state."""
83 assert app.status == 'active'83 assert app.status == "active"
8484
8585
86@pytest.mark.parametrize("path,expected_stat", [86@pytest.mark.parametrize(
87 ('/usr/lib/sudo/sudo_pair.so', {87 "path,expected_stat",
88 'gid': 0,88 [
89 'uid': 0,89 ("/usr/lib/sudo/sudo_pair.so", {"gid": 0, "uid": 0, "mode": "0o100644"}),
90 'mode': '0o100644'}),90 ("/usr/bin/sudo_approve", {"gid": 0, "uid": 0, "mode": "0o100755"}),
91 ('/usr/bin/sudo_approve', {91 ("/etc/sudo_pair.prompt.user", {"gid": 0, "uid": 0, "mode": "0o100644"}),
92 'gid': 0,92 ("/etc/sudo_pair.prompt.pair", {"gid": 0, "uid": 0, "mode": "0o100644"}),
93 'uid': 0,93 ("/var/run/sudo_pair", {"gid": 0, "uid": 0, "mode": "0o40644"}),
94 'mode': '0o100755'}),94 ],
95 ('/etc/sudo_pair.prompt.user', {95)
96 'gid': 0,
97 'uid': 0,
98 'mode': '0o100644'}),
99 ('/etc/sudo_pair.prompt.pair', {
100 'gid': 0,
101 'uid': 0,
102 'mode': '0o100644'}),
103 ('/var/run/sudo_pair', {
104 'gid': 0,
105 'uid': 0,
106 'mode': '0o40644'})])
107async def test_stats(path, expected_stat, unit, file_stat):96async def test_stats(path, expected_stat, unit, file_stat):
108 """Check that created files have the correct permissions."""97 """Check that created files have the correct permissions."""
109 test_stat = await file_stat(path, unit)98 test_stat = await file_stat(path, unit)
110 assert test_stat['size'] > 099 assert test_stat["size"] > 0
111 assert test_stat['gid'] == expected_stat['gid']100 assert test_stat["gid"] == expected_stat["gid"]
112 assert test_stat['uid'] == expected_stat['uid']101 assert test_stat["uid"] == expected_stat["uid"]
113 assert test_stat['mode'] == expected_stat['mode']102 assert test_stat["mode"] == expected_stat["mode"]
114103
115104
116async def test_sudoers(file_contents, unit):105async def test_sudoers(file_contents, unit):
117 """Check the content of sudoers file."""106 """Check the content of sudoers file."""
118 sudoers_content = await file_contents("/etc/sudoers", unit)107 sudoers_content = await file_contents("/etc/sudoers", unit)
119 assert 'Defaults log_output' in sudoers_content108 assert "Defaults log_output" in sudoers_content
120109
121110
122async def test_sudoers_bypass_conf(file_contents, unit):111async def test_sudoers_bypass_conf(file_contents, unit):
123 """Check the content of sudoers bypass command file."""112 """Check the content of sudoers bypass command file."""
124 path = "/etc/sudoers.d/91-bypass-sudopair-cmds"113 path = "/etc/sudoers.d/91-bypass-sudopair-cmds"
125 sudoers_bypass_content = await file_contents(path=path,114 sudoers_bypass_content = await file_contents(path=path, target=unit)
126 target=unit)115 content = "%warthogs ALL = (ALL) NOLOG_OUTPUT: /bin/ls"
127 content = '%warthogs ALL = (ALL) NOLOG_OUTPUT: /bin/ls'
128 assert content in sudoers_bypass_content116 assert content in sudoers_bypass_content
129117
130118
131async def test_reconfigure(reconfigure_app, file_contents, unit, app):119async def test_reconfigure(reconfigure_app, file_contents, unit, app):
132 """Change a charm config parameter and verify that it has been propagated to the unit."""120 """Change a charm config parameter and verify that it has been propagated to the unit."""
133 sudo_approve_path = '/usr/bin/sudo_approve'121 sudo_approve_path = "/usr/bin/sudo_approve"
134 await reconfigure_app(cfg={'auto_approve': 'false'},122 await reconfigure_app(cfg={"auto_approve": "false"}, target=app)
135 target=app)123 sudo_approve_content = await file_contents(path=sudo_approve_path, target=unit)
136 sudo_approve_content = await file_contents(path=sudo_approve_path,
137 target=unit)
138 new_content = 'echo "You can\'t approve your own session."'124 new_content = 'echo "You can\'t approve your own session."'
139 assert new_content in sudo_approve_content125 assert new_content in sudo_approve_content
140126
141127
142async def test_remove_relation(app, model, run_command):128async def test_remove_relation(app, model, run_command):
143 """Check that the relation is removed."""129 """Check that the relation is removed."""
144 series = app.units[0].data['series']130 series = app.units[0].data["series"]
145 app_name = 'sudo-pair-{}'.format(series)131 app_name = "sudo-pair-{}".format(series)
146 principalname = 'ubuntu-{}'.format(series)132 principalname = "ubuntu-{}".format(series)
147 await app.remove_relation(133 await app.remove_relation(
148 '{}:juju-info'.format(app_name),134 "{}:juju-info".format(app_name), "{}:juju-info".format(principalname)
149 '{}:juju-info'.format(principalname))135 )
150 await model.block_until(lambda: not app.relations)136 await model.block_until(lambda: not app.relations)
151 principal = model.applications[principalname].units[0]137 principal = model.applications[principalname].units[0]
152 res = await run_command('test -f /etc/sudo.conf || echo gone', target=principal)138 res = await run_command("test -f /etc/sudo.conf || echo gone", target=principal)
153 assert res['Stdout'].strip() == 'gone'139 assert res["Stdout"].strip() == "gone"
154 await model.add_relation(140 await model.add_relation(
155 '{}:juju-info'.format(principalname),141 "{}:juju-info".format(principalname), "{}:juju-info".format(app_name)
156 '{}:juju-info'.format(app_name))142 )
157 await model.block_until(lambda: app.relations)143 await model.block_until(lambda: app.relations)

Subscribers

People subscribed via source and target branches