Skip to content

Commit 6e3dbf2

Browse files
author
Corey Bryant
committed
Fix exception in set-temp-url-secret action
There are two issues fixed in this bug. The first is that the keystone_session exception block does not return on failure. The second, and the reason that create_keystone_session is failing, is due to the use of setuptools 60.9.0+ with the importlib-metadata in wheelhouse.txt that is pinned to <3.0.0. For more details see: pypa/setuptools#3452 Closes-Bug: #2018018 Change-Id: I266c1fb92d531aded2f3253766de0a79accd9577 (cherry picked from commit 9f221f1)
1 parent 128cd8a commit 6e3dbf2

File tree

5 files changed

+152
-1
lines changed

5 files changed

+152
-1
lines changed

src/actions/actions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def set_temp_url_secret(*args):
5656
except Exception as e:
5757
ch_core.hookenv.action_fail('Failed to create keystone session ("{}")'
5858
.format(e))
59+
return
5960

6061
os_cli = api_utils.OSClients(keystone_session)
6162
if os_cli.has_swift() is False:

src/wheelhouse.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ cryptography
2121
pyrsistent<0.18.0
2222
iso8601<1.0.0
2323

24-
importlib-metadata<3.0.0
24+
importlib-metadata==4.3.0
2525
importlib-resources<3.0.0
26+
setuptools<60.9.0
2627

2728
git+https://github.com/openstack/charms.openstack.git#egg=charms.openstack
2829

unit_tests/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
sys.modules['charmhelpers.core.decorators'] = (
1111
charms_openstack.test_mocks.charmhelpers.core.decorators)
1212

13+
global snap
14+
snap = mock.MagicMock()
15+
sys.modules['charms.layer'] = snap
16+
1317

1418
class _fake_decorator(object):
1519

unit_tests/test_actions.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import src.actions.actions as actions
2+
import unit_tests.test_utils
3+
import reactive.ironic_handlers as handlers
4+
import charm.openstack.ironic.api_utils as api_utils
5+
import charmhelpers.core as ch_core
6+
import charms.leadership as leadership
7+
8+
import mock
9+
10+
11+
class TestActions(unit_tests.test_utils.CharmTestCase):
12+
13+
def setUp(self):
14+
super(TestActions, self).setUp()
15+
self.patches = []
16+
self.patch_all()
17+
self.ironic_charm = mock.MagicMock()
18+
self.patch_object(handlers.charm, 'provide_charm_instance',
19+
new=mock.MagicMock())
20+
self.provide_charm_instance().__enter__.return_value = \
21+
self.ironic_charm
22+
self.provide_charm_instance().__exit__.return_value = None
23+
24+
def test_set_temp_url_secret_keystone_session_successful(self):
25+
self.patch_object(ch_core.hookenv, 'action_fail')
26+
self.patch_object(leadership, 'leader_get')
27+
28+
actions.set_temp_url_secret()
29+
30+
self.leader_get.assert_called_with('temp_url_secret')
31+
32+
def test_set_temp_url_secret_keystone_session_exception(self):
33+
self.patch_object(api_utils, 'create_keystone_session')
34+
self.patch_object(ch_core.hookenv, 'action_fail')
35+
self.patch_object(leadership, 'leader_get')
36+
37+
def raise_exception(*args):
38+
raise Exception("doh!")
39+
40+
self.create_keystone_session.side_effect = raise_exception
41+
42+
actions.set_temp_url_secret()
43+
44+
self.action_fail.assert_called_with(
45+
'Failed to create keystone session ("doh!")')
46+
self.leader_get.assert_not_called()

unit_tests/test_utils.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from unittest import mock
2+
import unittest
3+
4+
5+
class CharmTestCase(unittest.TestCase):
6+
7+
def setUp(self):
8+
self._patches = {}
9+
self._patches_start = {}
10+
11+
def tearDown(self):
12+
for k, v in self._patches.items():
13+
v.stop()
14+
setattr(self, k, None)
15+
self._patches = None
16+
self._patches_start = None
17+
18+
def _patch(self, method):
19+
_m = unittest.mock.patch.object(self.obj, method)
20+
mock = _m.start()
21+
self.addCleanup(_m.stop)
22+
return mock
23+
24+
def patch_all(self):
25+
for method in self.patches:
26+
setattr(self, method, self._patch(method))
27+
28+
def patch_object(self, obj, attr, return_value=None, name=None, new=None,
29+
**kwargs):
30+
if name is None:
31+
name = attr
32+
if new is not None:
33+
mocked = mock.patch.object(obj, attr, new=new, **kwargs)
34+
else:
35+
mocked = mock.patch.object(obj, attr, **kwargs)
36+
self._patches[name] = mocked
37+
started = mocked.start()
38+
if new is None:
39+
started.return_value = return_value
40+
self._patches_start[name] = started
41+
setattr(self, name, started)
42+
43+
def patch(self, item, return_value=None, name=None, new=None, **kwargs):
44+
if name is None:
45+
raise RuntimeError("Must pass 'name' to .patch()")
46+
if new is not None:
47+
mocked = mock.patch(item, new=new, **kwargs)
48+
else:
49+
mocked = mock.patch(item, **kwargs)
50+
self._patches[name] = mocked
51+
started = mocked.start()
52+
if new is None:
53+
started.return_value = return_value
54+
self._patches_start[name] = started
55+
56+
57+
class TestConfig(object):
58+
59+
def __init__(self):
60+
self.config = {}
61+
self.config_prev = {}
62+
63+
def __call__(self, key=None):
64+
if key:
65+
return self.get(key)
66+
else:
67+
return self
68+
69+
def previous(self, k):
70+
return self.config_prev[k] if k in self.config_prev else self.config[k]
71+
72+
def set_previous(self, k, v):
73+
self.config_prev[k] = v
74+
75+
def unset_previous(self, k):
76+
if k in self.config_prev:
77+
self.config_prev.pop(k)
78+
79+
def changed(self, k):
80+
if not self.config_prev:
81+
return True
82+
return self.get(k) != self.previous(k)
83+
84+
def get(self, attr=None):
85+
if not attr:
86+
return self
87+
try:
88+
return self.config[attr]
89+
except KeyError:
90+
return None
91+
92+
def get_all(self):
93+
return self.config
94+
95+
def set(self, attr, value):
96+
self.config[attr] = value
97+
98+
def __getitem__(self, k):
99+
return self.get(k)

0 commit comments

Comments
 (0)