Merge lp:~gnuoy/charm-helpers/peerstorage-updates into lp:charm-helpers

Proposed by Liam Young
Status: Merged
Merged at revision: 195
Proposed branch: lp:~gnuoy/charm-helpers/peerstorage-updates
Merge into: lp:charm-helpers
Diff against target: 208 lines (+157/-3)
3 files modified
charmhelpers/contrib/peerstorage/__init__.py (+47/-0)
charmhelpers/core/hookenv.py (+2/-1)
tests/contrib/peerstorage/test_peerstorage.py (+108/-2)
To merge this branch: bzr merge lp:~gnuoy/charm-helpers/peerstorage-updates
Reviewer Review Type Date Requested Status
Chris Glass (community) Approve
Liam Young (community) Needs Resubmitting
Review via email: mp+231201@code.launchpad.net

Description of the change

Add helper to perform relation set and store the dict in the peer db. This function will be used address Bug #1355848

To post a comment you must log in.
199. By Liam Young

Added peer_retrieve_by_prefix function to return all k/v pairs from the peer db given a prefix and filter using {inc,exc}_list.

Revision history for this message
Chris Glass (tribaal) wrote :

A couple of comments inline. The default to mutable argument is a showstopper as far as I'm concerned, but is an easy fix :)

review: Needs Fixing
Revision history for this message
Chris Glass (tribaal) :
Revision history for this message
Liam Young (gnuoy) wrote :

Thanks for the feedback and the link to the article, very interesting! I'll update the mp accordingly

200. By Liam Young

* Remove mutable defaults from new peer functions and from core.hookenv.relation_set
* Improve peer_store_and_set doc string

Revision history for this message
Liam Young (gnuoy) :
review: Needs Resubmitting
Revision history for this message
Chris Glass (tribaal) wrote :

Looks good! +1, with a small inline nitpick :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmhelpers/contrib/peerstorage/__init__.py'
--- charmhelpers/contrib/peerstorage/__init__.py 2014-03-07 11:57:28 +0000
+++ charmhelpers/contrib/peerstorage/__init__.py 2014-08-19 14:05:21 +0000
@@ -1,4 +1,6 @@
1from charmhelpers.core.hookenv import relation_id as current_relation_id
1from charmhelpers.core.hookenv import (2from charmhelpers.core.hookenv import (
3 is_relation_made,
2 relation_ids,4 relation_ids,
3 relation_get,5 relation_get,
4 local_unit,6 local_unit,
@@ -49,6 +51,24 @@
49 'peer relation {}'.format(relation_name))51 'peer relation {}'.format(relation_name))
5052
5153
54def peer_retrieve_by_prefix(prefix, relation_name='cluster', delimiter='_',
55 inc_list=None, exc_list=None):
56 """ Retrieve k/v pairs given a prefix and filter using {inc,exc}_list """
57 inc_list = inc_list if inc_list else []
58 exc_list = exc_list if exc_list else []
59 peerdb_settings = peer_retrieve('-', relation_name=relation_name)
60 matched = {}
61 for k, v in peerdb_settings.items():
62 full_prefix = prefix + delimiter
63 if k.startswith(full_prefix):
64 new_key = k.replace(full_prefix, '')
65 if new_key in exc_list:
66 continue
67 if new_key in inc_list or len(inc_list) == 0:
68 matched[new_key] = v
69 return matched
70
71
52def peer_store(key, value, relation_name='cluster'):72def peer_store(key, value, relation_name='cluster'):
53 """ Store the key/value pair on the named peer relation relation_name """73 """ Store the key/value pair on the named peer relation relation_name """
54 cluster_rels = relation_ids(relation_name)74 cluster_rels = relation_ids(relation_name)
@@ -81,3 +101,30 @@
81 echo_data[attribute] = value101 echo_data[attribute] = value
82 if len(echo_data) > 0:102 if len(echo_data) > 0:
83 relation_set(relation_settings=echo_data)103 relation_set(relation_settings=echo_data)
104
105
106def peer_store_and_set(relation_id=None, peer_relation_name='cluster',
107 peer_store_fatal=False, relation_settings=None,
108 delimiter='_', **kwargs):
109 """Store the passed-in arguments both in the argument relation and in peer storage.
110
111 It functions like doing relation_set() and peer_store() at the same time, with the same data.
112
113 @param relation_id: the id of the relation to store the data on. Defaults to the current relation.
114 @param peer_store_fatal: Set to True, the function will raise an exception should the peer sotrage not be avialable."""
115
116 relation_settings = relation_settings if relation_settings else {}
117 relation_set(relation_id=relation_id,
118 relation_settings=relation_settings,
119 **kwargs)
120 if is_relation_made(peer_relation_name):
121 for key, value in dict(kwargs.items() +
122 relation_settings.items()).iteritems():
123 key_prefix = relation_id or current_relation_id()
124 peer_store(key_prefix + delimiter + key,
125 value,
126 relation_name=peer_relation_name)
127 else:
128 if peer_store_fatal:
129 raise ValueError('Unable to detect '
130 'peer relation {}'.format(peer_relation_name))
84131
=== modified file 'charmhelpers/core/hookenv.py'
--- charmhelpers/core/hookenv.py 2014-06-09 17:10:38 +0000
+++ charmhelpers/core/hookenv.py 2014-08-19 14:05:21 +0000
@@ -285,8 +285,9 @@
285 raise285 raise
286286
287287
288def relation_set(relation_id=None, relation_settings={}, **kwargs):288def relation_set(relation_id=None, relation_settings=None, **kwargs):
289 """Set relation information for the current unit"""289 """Set relation information for the current unit"""
290 relation_settings = relation_settings if relation_settings else {}
290 relation_cmd_line = ['relation-set']291 relation_cmd_line = ['relation-set']
291 if relation_id is not None:292 if relation_id is not None:
292 relation_cmd_line.extend(('-r', relation_id))293 relation_cmd_line.extend(('-r', relation_id))
293294
=== modified file 'tests/contrib/peerstorage/test_peerstorage.py'
--- tests/contrib/peerstorage/test_peerstorage.py 2014-03-05 10:32:49 +0000
+++ tests/contrib/peerstorage/test_peerstorage.py 2014-08-19 14:05:21 +0000
@@ -1,10 +1,17 @@
1from tests.helpers import FakeRelation1from tests.helpers import FakeRelation
2from testtools import TestCase2from testtools import TestCase
3from mock import patch3from mock import patch, call
4from charmhelpers.contrib import peerstorage4from charmhelpers.contrib import peerstorage
55
66
7TO_PATCH = ['relation_ids', 'relation_set', 'relation_get', 'local_unit']7TO_PATCH = [
8 'current_relation_id',
9 'is_relation_made',
10 'local_unit',
11 'relation_get',
12 'relation_ids',
13 'relation_set',
14]
8FAKE_RELATION_NAME = 'cluster'15FAKE_RELATION_NAME = 'cluster'
9FAKE_RELATION = {16FAKE_RELATION = {
10 'cluster:0': {17 'cluster:0': {
@@ -67,3 +74,102 @@
67 def test_peer_echo_includes(self):74 def test_peer_echo_includes(self):
68 peerstorage.peer_echo(['key1'])75 peerstorage.peer_echo(['key1'])
69 self.relation_set.assert_called_with(relation_settings={'key1': 'value1'})76 self.relation_set.assert_called_with(relation_settings={'key1': 'value1'})
77
78 @patch.object(peerstorage, 'peer_store')
79 def test_peer_store_and_set_no_relation(self, peer_store):
80 self.is_relation_made.return_value = False
81 peerstorage.peer_store_and_set(relation_id='db', kwarg1='kwarg1_v')
82 self.relation_set.assert_called_with(relation_id='db',
83 relation_settings={},
84 kwarg1='kwarg1_v')
85 peer_store.assert_not_called()
86
87 @patch.object(peerstorage, 'peer_store')
88 def test_peer_store_and_set_no_relation_fatal(self, peer_store):
89 self.is_relation_made.return_value = False
90 self.assertRaises(ValueError,
91 peerstorage.peer_store_and_set,
92 relation_id='db',
93 kwarg1='kwarg1_v',
94 peer_store_fatal=True)
95
96 @patch.object(peerstorage, 'peer_store')
97 def test_peer_store_and_set_kwargs(self, peer_store):
98 self.is_relation_made.return_value = True
99 peerstorage.peer_store_and_set(relation_id='db', kwarg1='kwarg1_v')
100 self.relation_set.assert_called_with(relation_id='db',
101 relation_settings={},
102 kwarg1='kwarg1_v')
103 calls = [call('db_kwarg1', 'kwarg1_v', relation_name='cluster')]
104 peer_store.assert_has_calls(calls, any_order=True)
105
106 @patch.object(peerstorage, 'peer_store')
107 def test_peer_store_and_rel_settings(self, peer_store):
108 self.is_relation_made.return_value = True
109 rel_setting = {
110 'rel_set1': 'relset1_v'
111 }
112 peerstorage.peer_store_and_set(relation_id='db',
113 relation_settings=rel_setting)
114 self.relation_set.assert_called_with(relation_id='db',
115 relation_settings=rel_setting)
116 calls = [call('db_rel_set1', 'relset1_v', relation_name='cluster')]
117 peer_store.assert_has_calls(calls, any_order=True)
118
119 @patch.object(peerstorage, 'peer_store')
120 def test_peer_store_and_set(self, peer_store):
121 self.is_relation_made.return_value = True
122 rel_setting = {
123 'rel_set1': 'relset1_v'
124 }
125 peerstorage.peer_store_and_set(relation_id='db',
126 relation_settings=rel_setting,
127 kwarg1='kwarg1_v',
128 delimiter='+')
129 self.relation_set.assert_called_with(relation_id='db',
130 relation_settings=rel_setting,
131 kwarg1='kwarg1_v')
132 calls = [call('db+rel_set1', 'relset1_v', relation_name='cluster'),
133 call('db+kwarg1', 'kwarg1_v', relation_name='cluster')]
134 peer_store.assert_has_calls(calls, any_order=True)
135
136 @patch.object(peerstorage, 'peer_retrieve')
137 def test_peer_retrieve_by_prefix(self, peer_retrieve):
138 rel_id = 'db:2'
139 settings = {
140 'user': 'bob',
141 'pass': 'reallyhardpassword',
142 'host': 'myhost',
143 }
144 peer_settings = {rel_id + '_' + k: v for k, v in settings.items()}
145 peer_retrieve.return_value = peer_settings
146 self.assertEquals(peerstorage.peer_retrieve_by_prefix(rel_id), settings)
147
148 @patch.object(peerstorage, 'peer_retrieve')
149 def test_peer_retrieve_by_prefix_exc_list(self, peer_retrieve):
150 rel_id = 'db:2'
151 settings = {
152 'user': 'bob',
153 'pass': 'reallyhardpassword',
154 'host': 'myhost',
155 }
156 peer_settings = {rel_id + '_' + k: v for k, v in settings.items()}
157 del settings['host']
158 peer_retrieve.return_value = peer_settings
159 self.assertEquals(peerstorage.peer_retrieve_by_prefix(rel_id,
160 exc_list=['host']),
161 settings)
162
163 @patch.object(peerstorage, 'peer_retrieve')
164 def test_peer_retrieve_by_prefix_inc_list(self, peer_retrieve):
165 rel_id = 'db:2'
166 settings = {
167 'user': 'bob',
168 'pass': 'reallyhardpassword',
169 'host': 'myhost',
170 }
171 peer_settings = {rel_id + '_' + k: v for k, v in settings.items()}
172 peer_retrieve.return_value = peer_settings
173 self.assertEquals(peerstorage.peer_retrieve_by_prefix(rel_id,
174 inc_list=['host']),
175 {'host': 'myhost'})

Subscribers

People subscribed via source and target branches