Fixed detecting controller for non-superuser
[osm/N2VC.git] / juju / client / connection.py
index 18111ce..5ed073f 100644 (file)
@@ -12,7 +12,7 @@ import websockets
 
 import yaml
 
-from juju.errors import JujuAPIError
+from juju.errors import JujuAPIError, JujuConnectionError
 
 log = logging.getLogger("websocket")
 
@@ -135,8 +135,7 @@ class Connection:
 
         redirect_info = await client.redirect_info()
         if not redirect_info:
-            server_info = await client.login(username, password, macaroons)
-            client.build_facades(server_info['facades'])
+            await client.login(username, password, macaroons)
             return client
 
         await client.close()
@@ -153,7 +152,6 @@ class Connection:
                 result = await client.login(username, password, macaroons)
                 if 'discharge-required-error' in result:
                     continue
-                client.build_facades(result['facades'])
                 return client
             except Exception as e:
                 await client.close()
@@ -175,6 +173,35 @@ class Connection:
         return await cls.connect_model(
             '{}:{}'.format(controller_name, model_name))
 
+    @classmethod
+    async def connect_current_controller(cls):
+        """Connect to the currently active controller.
+
+        """
+        jujudata = JujuData()
+        controller_name = jujudata.current_controller()
+        if not controller_name:
+            raise JujuConnectionError('No current controller')
+
+        return await cls.connect_controller(controller_name)
+
+    @classmethod
+    async def connect_controller(cls, controller_name):
+        """Connect to a controller by name.
+
+        """
+        jujudata = JujuData()
+        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')
+        macaroons = get_macaroons() if not password else None
+
+        return await cls.connect(
+            endpoint, None, username, password, cacert, macaroons)
+
     @classmethod
     async def connect_model(cls, model):
         """Connect to a model by name.
@@ -221,7 +248,10 @@ class Connection:
                 "nonce": "".join(random.sample(string.printable, 12)),
                 "macaroons": macaroons or []
             }})
-        return result['response']
+        response = result['response']
+        self.build_facades(response.get('facades', {}))
+        self.info = response.copy()
+        return response
 
     async def redirect_info(self):
         try:
@@ -243,10 +273,10 @@ class JujuData:
         self.path = os.path.abspath(os.path.expanduser(self.path))
 
     def current_controller(self):
-        cmd = shlex.split('juju show-controller --format yaml')
+        cmd = shlex.split('juju list-controllers --format yaml')
         output = subprocess.check_output(cmd)
         output = yaml.safe_load(output)
-        return list(output.keys())[0]
+        return output.get('current-controller', '')
 
     def controllers(self):
         return self._load_yaml('controllers.yaml', 'controllers')