Merge lp:~gnuoy/charm-helpers/service-framework-loader into lp:charm-helpers

Proposed by Liam Young
Status: Merged
Merged at revision: 477
Proposed branch: lp:~gnuoy/charm-helpers/service-framework-loader
Merge into: lp:charm-helpers
Diff against target: 219 lines (+89/-11)
6 files modified
charmhelpers/contrib/openstack/utils.py (+18/-0)
charmhelpers/core/services/helpers.py (+5/-2)
charmhelpers/core/templating.py (+8/-5)
tests/contrib/openstack/test_os_utils.py (+15/-0)
tests/core/test_services.py (+20/-4)
tests/core/test_templating.py (+23/-0)
To merge this branch: bzr merge lp:~gnuoy/charm-helpers/service-framework-loader
Reviewer Review Type Date Requested Status
charmers Pending
Review via email: mp+276519@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charmhelpers/contrib/openstack/utils.py'
2--- charmhelpers/contrib/openstack/utils.py 2015-10-14 21:29:40 +0000
3+++ charmhelpers/contrib/openstack/utils.py 2015-11-03 12:21:04 +0000
4@@ -26,6 +26,7 @@
5
6 import six
7 import traceback
8+import uuid
9 import yaml
10
11 from charmhelpers.contrib.network import ip
12@@ -41,6 +42,7 @@
13 log as juju_log,
14 charm_dir,
15 INFO,
16+ related_units,
17 relation_ids,
18 relation_set,
19 status_set,
20@@ -978,3 +980,19 @@
21 action_set({'outcome': 'no upgrade available.'})
22
23 return ret
24+
25+
26+def remote_restart(rel_name, remote_service=None):
27+ trigger = {
28+ 'restart-trigger': str(uuid.uuid4()),
29+ }
30+ if remote_service:
31+ trigger['remote-service'] = remote_service
32+ for rid in relation_ids(rel_name):
33+ # This subordinate can be related to two seperate services using
34+ # different subordinate relations so only issue the restart if
35+ # the principle is conencted down the relation we think it is
36+ if related_units(relid=rid):
37+ relation_set(relation_id=rid,
38+ relation_settings=trigger,
39+ )
40
41=== modified file 'charmhelpers/core/services/helpers.py'
42--- charmhelpers/core/services/helpers.py 2015-08-17 11:03:07 +0000
43+++ charmhelpers/core/services/helpers.py 2015-11-03 12:21:04 +0000
44@@ -249,16 +249,18 @@
45 :param int perms: The permissions of the rendered file
46 :param partial on_change_action: functools partial to be executed when
47 rendered file changes
48+ :param jinja2 loader template_loader: A jinja2 template loader
49 """
50 def __init__(self, source, target,
51 owner='root', group='root', perms=0o444,
52- on_change_action=None):
53+ on_change_action=None, template_loader=None):
54 self.source = source
55 self.target = target
56 self.owner = owner
57 self.group = group
58 self.perms = perms
59 self.on_change_action = on_change_action
60+ self.template_loader = template_loader
61
62 def __call__(self, manager, service_name, event_name):
63 pre_checksum = ''
64@@ -269,7 +271,8 @@
65 for ctx in service.get('required_data', []):
66 context.update(ctx)
67 templating.render(self.source, self.target, context,
68- self.owner, self.group, self.perms)
69+ self.owner, self.group, self.perms,
70+ template_loader=self.template_loader)
71 if self.on_change_action:
72 if pre_checksum == host.file_hash(self.target):
73 hookenv.log(
74
75=== modified file 'charmhelpers/core/templating.py'
76--- charmhelpers/core/templating.py 2015-07-28 12:52:17 +0000
77+++ charmhelpers/core/templating.py 2015-11-03 12:21:04 +0000
78@@ -21,7 +21,7 @@
79
80
81 def render(source, target, context, owner='root', group='root',
82- perms=0o444, templates_dir=None, encoding='UTF-8'):
83+ perms=0o444, templates_dir=None, encoding='UTF-8', template_loader=None):
84 """
85 Render a template.
86
87@@ -52,12 +52,15 @@
88 apt_install('python-jinja2', fatal=True)
89 from jinja2 import FileSystemLoader, Environment, exceptions
90
91- if templates_dir is None:
92- templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
93- loader = Environment(loader=FileSystemLoader(templates_dir))
94+ if template_loader:
95+ template_env = Environment(loader=template_loader)
96+ else:
97+ if templates_dir is None:
98+ templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
99+ template_env = Environment(loader=FileSystemLoader(templates_dir))
100 try:
101 source = source
102- template = loader.get_template(source)
103+ template = template_env.get_template(source)
104 except exceptions.TemplateNotFound as e:
105 hookenv.log('Could not load template %s from %s.' %
106 (source, templates_dir),
107
108=== modified file 'tests/contrib/openstack/test_os_utils.py'
109--- tests/contrib/openstack/test_os_utils.py 2015-09-25 14:23:31 +0000
110+++ tests/contrib/openstack/test_os_utils.py 2015-11-03 12:21:04 +0000
111@@ -95,3 +95,18 @@
112 database='testdb',
113 username='testdbuser',
114 hostname=hosts)
115+
116+ @mock.patch('uuid.uuid4')
117+ @mock.patch('charmhelpers.contrib.openstack.utils.related_units')
118+ @mock.patch('charmhelpers.contrib.openstack.utils.relation_set')
119+ @mock.patch('charmhelpers.contrib.openstack.utils.relation_ids')
120+ def test_remote_restart(self, mock_relation_ids, mock_relation_set,
121+ mock_related_units, mock_uuid4):
122+ mock_relation_ids.return_value = ['neutron-plugin-api-subordinate:8']
123+ mock_related_units.return_value = ['neutron-api/0']
124+ mock_uuid4.return_value = 'uuid4'
125+ utils.remote_restart('neutron-plugin-api-subordinate')
126+ mock_relation_set.assert_called_with(
127+ relation_id='neutron-plugin-api-subordinate:8',
128+ relation_settings={'restart-trigger': 'uuid4'}
129+ )
130
131=== modified file 'tests/core/test_services.py'
132--- tests/core/test_services.py 2015-08-17 11:03:07 +0000
133+++ tests/core/test_services.py 2015-11-03 12:21:04 +0000
134@@ -739,7 +739,7 @@
135 callback(manager, 'test', 'event')
136 mtemplating.render.assert_called_once_with(
137 'foo.yml', 'bar.yml', {'foo': 'bar'},
138- 'root', 'root', 0o444)
139+ 'root', 'root', 0o444, template_loader=None)
140
141 @mock.patch.object(services.helpers, 'templating')
142 def test_template_explicit(self, mtemplating):
143@@ -754,7 +754,23 @@
144 callback(manager, 'test', 'event')
145 mtemplating.render.assert_called_once_with(
146 'foo.yml', 'bar.yml', {'foo': 'bar'},
147- 'user', 'group', 0o555)
148+ 'user', 'group', 0o555, template_loader=None)
149+
150+ @mock.patch.object(services.helpers, 'templating')
151+ def test_template_loader(self, mtemplating):
152+ manager = mock.Mock(**{'get_service.return_value': {
153+ 'required_data': [{'foo': 'bar'}]}})
154+ callback = services.template(
155+ source='foo.yml', target='bar.yml',
156+ owner='user', group='group', perms=0o555,
157+ template_loader='myloader'
158+ )
159+ assert isinstance(callback, services.ManagerCallback)
160+ assert not mtemplating.render.called
161+ callback(manager, 'test', 'event')
162+ mtemplating.render.assert_called_once_with(
163+ 'foo.yml', 'bar.yml', {'foo': 'bar'},
164+ 'user', 'group', 0o555, template_loader='myloader')
165
166 @mock.patch.object(os.path, 'isfile')
167 @mock.patch.object(host, 'file_hash')
168@@ -777,7 +793,7 @@
169 callback(manager, 'test', 'event')
170 mtemplating.render.assert_called_once_with(
171 'foo.yml', 'bar.yml', {'foo': 'bar'},
172- 'user', 'group', 0o555)
173+ 'user', 'group', 0o555, template_loader=None)
174 mrestart.assert_called_with('mysuperservice')
175
176 @mock.patch.object(hookenv, 'log')
177@@ -801,7 +817,7 @@
178 callback(manager, 'test', 'event')
179 mtemplating.render.assert_called_once_with(
180 'foo.yml', 'bar.yml', {'foo': 'bar'},
181- 'user', 'group', 0o555)
182+ 'user', 'group', 0o555, template_loader=None)
183 self.assertEqual(mrestart.call_args_list, [])
184
185
186
187=== modified file 'tests/core/test_templating.py'
188--- tests/core/test_templating.py 2015-07-28 12:52:17 +0000
189+++ tests/core/test_templating.py 2015-11-03 12:21:04 +0000
190@@ -58,6 +58,29 @@
191 # expose your secrets (!).
192 self.assertEqual(mkdir.call_count, 0)
193
194+ @mock.patch.object(templating.host.os, 'fchown')
195+ @mock.patch.object(templating.host, 'mkdir')
196+ @mock.patch.object(templating.host, 'log')
197+ def test_render_loader(self, log, mkdir, fchown):
198+ with tempfile.NamedTemporaryFile() as fn1:
199+ context = {
200+ 'nats': {
201+ 'port': '1234',
202+ 'host': 'example.com',
203+ },
204+ 'router': {
205+ 'domain': 'api.foo.com'
206+ },
207+ 'nginx_port': 80,
208+ }
209+ template_loader = jinja2.ChoiceLoader([jinja2.FileSystemLoader(TEMPLATES_DIR)])
210+ templating.render('fake_cc.yml', fn1.name,
211+ context, template_loader=template_loader)
212+ contents = open(fn1.name).read()
213+ self.assertRegexpMatches(contents, 'port: 1234')
214+ self.assertRegexpMatches(contents, 'host: example.com')
215+ self.assertRegexpMatches(contents, 'domain: api.foo.com')
216+
217 @mock.patch.object(templating.os.path, 'exists')
218 @mock.patch.object(templating.host.os, 'fchown')
219 @mock.patch.object(templating.host, 'mkdir')

Subscribers

People subscribed via source and target branches