← Back to team overview

cf-charmers team mailing list archive

[Merge] lp:~lomov-as/charm-helpers/cloud-foundry-multiple-units-in-relation-context into lp:~cf-charmers/charm-helpers/cloud-foundry

 

Alex Lomov has proposed merging lp:~lomov-as/charm-helpers/cloud-foundry-multiple-units-in-relation-context into lp:~cf-charmers/charm-helpers/cloud-foundry.

Requested reviews:
  Cloud Foundry Charmers (cf-charmers)

For more details, see:
https://code.launchpad.net/~lomov-as/charm-helpers/cloud-foundry-multiple-units-in-relation-context/+merge/220508

multiple units processing for relation context

As far as we moved relation context to core.templating we need to care about possobility to connect multimple units. Geting information from several units will be useful for etcd and cf-loggregator charms.
-- 
https://code.launchpad.net/~lomov-as/charm-helpers/cloud-foundry-multiple-units-in-relation-context/+merge/220508
Your team Cloud Foundry Charmers is requested to review the proposed merge of lp:~lomov-as/charm-helpers/cloud-foundry-multiple-units-in-relation-context into lp:~cf-charmers/charm-helpers/cloud-foundry.
=== modified file '.bzrignore'
--- .bzrignore	2014-05-09 02:08:58 +0000
+++ .bzrignore	2014-05-21 17:36:43 +0000
@@ -10,4 +10,5 @@
 .ropeproject/
 charmhelpers.egg-info/
 .DS_Store
-.tox/
\ No newline at end of file
+.tox/
+chdev/
\ No newline at end of file

=== modified file 'charmhelpers/core/templating.py'
--- charmhelpers/core/templating.py	2014-05-20 15:40:48 +0000
+++ charmhelpers/core/templating.py	2014-05-21 17:36:43 +0000
@@ -65,6 +65,7 @@
     """
     interface = None
     required_keys = []
+    with_multiple_units = False
 
     def __call__(self):
         if not hookenv.relation_ids(self.interface):
@@ -72,16 +73,22 @@
 
         ctx = {}
         for rid in hookenv.relation_ids(self.interface):
+            interface_name = self.interface.replace('-', '_')
+            if self.with_multiple_units:
+                units_list = ctx.setdefault(("%s_units" % interface_name), [])
             for unit in hookenv.related_units(rid):
                 reldata = hookenv.relation_get(rid=rid, unit=unit)
                 required = set(self.required_keys)
                 if set(reldata.keys()).issuperset(required):
-                    ns = ctx.setdefault(self.interface, {})
+                    ns = ctx.setdefault(interface_name, {})
                     for k, v in reldata.items():
                         ns[k] = v
-                    return ctx
-
-        return {}
+                    if self.with_multiple_units:
+                        ns['unit_name'] = unit
+                        units_list.append(ns.copy())
+                    else:
+                        return ctx
+        return ctx
 
 
 class StaticContext(ContextGenerator):

=== modified file 'tests/core/test_templating.py'
--- tests/core/test_templating.py	2014-05-16 21:48:06 +0000
+++ tests/core/test_templating.py	2014-05-21 17:36:43 +0000
@@ -171,6 +171,14 @@
         self.assertEqual(a(), 'a')
 
 
+class TestRelationContextWithMultipleUnits(unittest.TestCase):
+    def setUp(self):
+        self.context_provider = templating.RelationContext()
+        self.context_provider.interface = 'http'
+        self.context_provider.required_keys = ['foo', 'bar']
+
+
+
 class TestRelationContext(unittest.TestCase):
     def setUp(self):
         self.context_provider = templating.RelationContext()
@@ -184,12 +192,6 @@
         mhookenv.relation_ids.assert_called_once_with('http')
 
     @mock.patch.object(templating, 'hookenv')
-    def test_no_units(self, mhookenv):
-        mhookenv.relation_ids.return_value = ['nginx']
-        mhookenv.related_units.return_value = []
-        self.assertEqual(self.context_provider(), {})
-
-    @mock.patch.object(templating, 'hookenv')
     def test_incomplete(self, mhookenv):
         mhookenv.relation_ids.return_value = ['nginx', 'apache']
         mhookenv.related_units.side_effect = lambda i: [i+'/0']
@@ -211,3 +213,30 @@
             mock.call(rid='nginx', unit='nginx/0'),
             mock.call(rid='apache', unit='apache/0'),
         ])
+
+    @mock.patch.object(templating, 'hookenv')
+    def test_interface_name_with_dashes(self, mhookenv):
+        self.context_provider.interface = 'cf-mysql-service-broker'
+        mhookenv.relation_ids.return_value = ['cf-mysql-service-broker']
+        mhookenv.related_units.side_effect = lambda i: [i+'/0']
+        mhookenv.relation_get.side_effect = [{'foo': '1', 'bar': '2'}]
+        self.assertEqual(self.context_provider(), {'cf_mysql_service_broker': {'foo': '1', 'bar': '2'}})
+
+    @mock.patch.object(templating, 'hookenv')
+    def test_with_multiple_units(self, mhookenv):
+        self.context_provider.with_multiple_units = True
+        self.context_provider.interface = 'etcd'
+        self.context_provider.required_keys = ['message']
+        mhookenv.relation_ids.return_value = ['etcd']
+        mhookenv.related_units.side_effect = lambda i: [i+'/0', i+'/1']
+        mhookenv.relation_get.side_effect = lambda **i: {
+            'message': ("%s has unit %s" % (i['rid'], i['unit']))
+        }
+        print self.context_provider()
+        self.assertEqual(self.context_provider(), {
+            'etcd': {'message': 'etcd has unit etcd/1', 'unit_name': 'etcd/1'},
+            'etcd_units': [
+                {'message': 'etcd has unit etcd/0', 'unit_name': 'etcd/0'},
+                {'message': 'etcd has unit etcd/1', 'unit_name': 'etcd/1'}
+            ]
+        })


Follow ups