Revert "Remove vendored libjuju"
[osm/N2VC.git] / modules / libjuju / juju / application.py
index 620e9c9..3f7f02e 100644 (file)
@@ -52,6 +52,24 @@ class Application(model.ModelEntity):
         ]
 
     @property
+    def relations(self):
+        return [rel for rel in self.model.relations if rel.matches(self.name)]
+
+    def related_applications(self, endpoint_name=None):
+        apps = {}
+        for rel in self.relations:
+            if rel.is_peer:
+                local_ep, remote_ep = rel.endpoints[0]
+            else:
+                def is_us(ep):
+                    return ep.application.name == self.name
+                local_ep, remote_ep = sorted(rel.endpoints, key=is_us)
+            if endpoint_name is not None and endpoint_name != local_ep.name:
+                continue
+            apps[remote_ep.application.name] = remote_ep.application
+        return apps
+
+    @property
     def status(self):
         """Get the application status, as set by the charm's leader.
 
@@ -113,6 +131,31 @@ class Application(model.ModelEntity):
 
     add_units = add_unit
 
+    async def scale(self, scale=None, scale_change=None):
+        """
+        Set or adjust the scale of this (K8s) application.
+
+        One or the other of scale or scale_change must be provided.
+
+        :param int scale: Scale to which to set this application.
+        :param int scale_change: Amount by which to adjust the scale of this
+            application (can be positive or negative).
+        """
+        app_facade = client.ApplicationFacade.from_connection(self.connection)
+
+        if (scale, scale_change) == (None, None):
+            raise ValueError('Must provide either scale or scale_change')
+
+        log.debug(
+            'Scaling application %s %s %s',
+            self.name, 'to' if scale else 'by', scale or scale_change)
+
+        await app_facade.ScaleApplications([
+            client.ScaleApplicationParam(application_tag=self.tag,
+                                         scale=scale,
+                                         scale_change=scale_change)
+        ])
+
     def allocate(self, budget, value):
         """Allocate budget to this application.
 
@@ -210,22 +253,43 @@ class Application(model.ModelEntity):
         result = (await app_facade.Get(self.name)).constraints
         return vars(result) if result else result
 
-    def get_actions(self, schema=False):
+    async def get_actions(self, schema=False):
         """Get actions defined for this application.
 
         :param bool schema: Return the full action schema
-
+        :return dict: The charms actions, empty dict if none are defined.
         """
-        raise NotImplementedError()
-
-    def get_resources(self, details=False):
+        actions = {}
+        entity = [{"tag": self.tag}]
+        action_facade = client.ActionFacade.from_connection(self.connection)
+        results = (
+            await action_facade.ApplicationsCharmsActions(entity)).results
+        for result in results:
+            if result.application_tag == self.tag and result.actions:
+                actions = result.actions
+                break
+        if not schema:
+            actions = {k: v['description'] for k, v in actions.items()}
+        return actions
+
+    async def get_resources(self):
         """Return resources for this application.
 
-        :param bool details: Include detailed info about resources used by each
-            unit
-
+        Returns a dict mapping resource name to
+        :class:`~juju._definitions.CharmResource` instances.
         """
-        raise NotImplementedError()
+        facade = client.ResourcesFacade.from_connection(self.connection)
+        response = await facade.ListResources([client.Entity(self.tag)])
+
+        resources = dict()
+        for result in response.results:
+            for resource in result.charm_store_resources or []:
+                resources[resource.name] = resource
+            for resource in result.resources or []:
+                if resource.charmresource:
+                    resource = resource.charmresource
+                    resources[resource.name] = resource
+        return resources
 
     async def run(self, command, timeout=None):
         """Run command on all units for this application.
@@ -266,12 +330,10 @@ class Application(model.ModelEntity):
         )
         return await self.ann_facade.Set([ann])
 
-    async def set_config(self, config, to_default=False):
+    async def set_config(self, config):
         """Set configuration options for this application.
 
         :param config: Dict of configuration to set
-        :param bool to_default: Set application options to default values
-
         """
         app_facade = client.ApplicationFacade.from_connection(self.connection)
 
@@ -280,6 +342,20 @@ class Application(model.ModelEntity):
 
         return await app_facade.Set(self.name, config)
 
+    async def reset_config(self, to_default):
+        """
+        Restore application config to default values.
+
+        :param list to_default: A list of config options to be reset to their
+        default value.
+        """
+        app_facade = client.ApplicationFacade.from_connection(self.connection)
+
+        log.debug(
+            'Restoring default config for %s: %s', self.name, to_default)
+
+        return await app_facade.Unset(self.name, to_default)
+
     async def set_constraints(self, constraints):
         """Set machine constraints for this application.