Merge pull request #15 from juju/run-action
authorTim Van Steenburgh <tvansteenburgh@gmail.com>
Tue, 22 Nov 2016 13:49:19 +0000 (08:49 -0500)
committerGitHub <noreply@github.com>
Tue, 22 Nov 2016 13:49:19 +0000 (08:49 -0500)
Implement Unit.run_action

1  2 
juju/unit.py

diff --combined juju/unit.py
@@@ -1,4 -1,3 +1,3 @@@
- import asyncio
  import logging
  from datetime import datetime
  
@@@ -57,6 -56,10 +56,10 @@@ class Unit(model.ModelEntity)
          """
          return self.data['workload-status']['message']
  
+     @property
+     def tag(self):
+         return 'unit-%s' % self.name.replace('/', '-')
      def add_storage(self, name, constraints=None):
          """Add unit storage dynamically.
  
          )
          return await self.model.wait_for_action(res.results[0].action.tag)
  
-     def run_action(self, action_name, **params):
-         """Run action on this unit.
+     async def run_action(self, action_name, **params):
+         """Run an action on this unit.
  
          :param str action_name: Name of action to run
          :param \*\*params: Action parameters
-         """
-         pass
+         :returns: An `juju.action.Action` instance.
+         Note that this only enqueues the action.  You will need to call
+         ``action.wait()`` on the resulting `Action` instance if you wish
+         to block until the action is complete.
+         """
+         action_facade = client.ActionFacade()
+         action_facade.connect(self.connection)
+         log.debug('Starting action `%s` on %s', action_name, self.name)
+         res = await action_facade.Enqueue([client.Action(
+             name=action_name,
+             parameters=params,
+             receiver=self.tag,
+         )])
+         action = res.results[0].action
+         error = res.results[0].error
+         if error and error.code == 'not found':
+             raise ValueError('Action `%s` not found on %s' % (action_name,
+                                                               self.name))
+         elif error:
+             raise Exception('Unknown action error: %s' % error.serialize())
+         action_id = action.tag[len('action-'):]
+         log.debug('Action started as %s', action_id)
+         # we can't use wait_for_new here because we don't
+         # consistently (ever?) get an "add" delta for the action
+         return await self.model._wait('action', action_id, None)
  
      def scp(
              self, source_path, user=None, destination_path=None, proxy=False,
  
          """
          pass
 +
 +    async def is_leader_from_status(self):
 +        """
 +        Check to see if this unit is the leader. Returns True if so, and
 +        False if it is not, or if leadership does not make sense
 +        (e.g., there is no leader in this application.)
 +
 +        This method is a kluge that calls FullStatus in the
 +        ClientFacade to get its information. Once
 +        https://bugs.launchpad.net/juju/+bug/1643691 is resolved, we
 +        should add a simple .is_leader property, and deprecate this
 +        method.
 +
 +        """
 +        app = self.name.split("/")[0]
 +
 +        c = client.ClientFacade()
 +        c.connect(self.model.connection)
 +
 +        status = await c.FullStatus(None)
 +
 +        return status.applications[app]['units'][self.name].get(
 +            'leader', False)