Merge branch 'master' into bug/fix-invalid-annotations
[osm/N2VC.git] / juju / client / connection.py
index c24f8c1..b508a1a 100644 (file)
@@ -34,6 +34,8 @@ class Connection:
         # Connect to the currently active model
         client = await Connection.connect_current()
 
+    Note: Any connection method or constructor can accept an optional `loop`
+    argument to override the default event loop from `asyncio.get_event_loop`.
     """
     def __init__(
             self, endpoint, uuid, username, password, cacert=None,
@@ -94,8 +96,30 @@ class Connection:
         outgoing = json.dumps(msg, indent=2, cls=encoder)
         await self.ws.send(outgoing)
         result = await self.recv()
-        if result and 'error' in result:
+
+        if not result:
+            return result
+
+        if 'error' in result:
+            # API Error Response
             raise JujuAPIError(result)
+
+        if not 'response' in result:
+            # This may never happen
+            return result
+
+        if 'results' in result['response']:
+            # Check for errors in a result list.
+            errors = []
+            for res in result['response']['results']:
+                if res.get('error', {}).get('message'):
+                    errors.append(res['error']['message'])
+            if errors:
+                raise JujuError(errors)
+
+        elif result['response'].get('error', {}).get('message'):
+            raise JujuError(result['response']['error']['message'])
+
         return result
 
     def http_headers(self):
@@ -265,20 +289,24 @@ class Connection:
         jujudata = JujuData()
 
         if ':' in model:
+            # explicit controller given
             controller_name, model_name = model.split(':')
         else:
+            # use the current controller if one isn't explicitly given
             controller_name = jujudata.current_controller()
             model_name = model
 
+        accounts = jujudata.accounts()[controller_name]
+        username = accounts['user']
+        # model name must include a user prefix, so add it if it doesn't
+        if '/' not in model_name:
+            model_name = '{}/{}'.format(username, model_name)
+
         controller = jujudata.controllers()[controller_name]
         endpoint = controller['api-endpoints'][0]
         cacert = controller.get('ca-cert')
-        accounts = jujudata.accounts()[controller_name]
-        username = accounts['user']
         password = accounts.get('password')
         models = jujudata.models()[controller_name]
-        if '/' not in model_name:
-            model_name = '{}/{}'.format(username, model_name)
         model_uuid = models['models'][model_name]['uuid']
         macaroons = get_macaroons() if not password else None
 
@@ -339,7 +367,9 @@ class JujuData:
         return output.get('current-controller', '')
 
     def current_model(self, controller_name=None):
-        models = self.models()[controller_name or self.current_controller()]
+        if not controller_name:
+            controller_name = self.current_controller()
+        models = self.models()[controller_name]
         if 'current-model' not in models:
             raise JujuError('No current model')
         return models['current-model']