Merge lp:~axwalk/charm-helpers/hookenv-storage into lp:charm-helpers

Proposed by Andrew Wilkins
Status: Merged
Merged at revision: 455
Proposed branch: lp:~axwalk/charm-helpers/hookenv-storage
Merge into: lp:charm-helpers
Diff against target: 126 lines (+108/-0)
2 files modified
charmhelpers/core/hookenv.py (+32/-0)
tests/core/test_hookenv.py (+76/-0)
To merge this branch: bzr merge lp:~axwalk/charm-helpers/hookenv-storage
Reviewer Review Type Date Requested Status
Tim Van Steenburgh Approve
Review via email: mp+272076@code.launchpad.net

Description of the change

This MP adds two new functions to hookenv: storage_list and storage_get. These will, respectively, list and get details of the unit's storage attachments.

storage_list will return [] of the storage-list hook tool cannot be found in $PATH. storage_get does not filter exceptions, because there's no reason to use it unless you're in a storage hook, or you've called it with the results of storage_list. As such, the following sort of code:
    for s in storage_list():
        storage_get(storage_id=s)
will work regardless of the version of Juju.

To post a comment you must log in.
Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

The last three tests all do:

    self.assertEqual(result, result)

...which will always be true. Presumably an oversight, but one of those 'result' vars needs to be renamed in each test.

review: Needs Fixing
456. By Andrew Wilkins

Fix tautological tests

Revision history for this message
Andrew Wilkins (axwalk) wrote :

> The last three tests all do:
>
> self.assertEqual(result, result)
>
> ...which will always be true. Presumably an oversight, but one of those
> 'result' vars needs to be renamed in each test.

Wow, sorry about that :/
Fixed.

Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

+1 LGTM. Bonus point for using "tautological" in a commit message.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmhelpers/core/hookenv.py'
--- charmhelpers/core/hookenv.py 2015-08-26 17:32:36 +0000
+++ charmhelpers/core/hookenv.py 2015-09-24 01:29:26 +0000
@@ -623,6 +623,38 @@
623 return unit_get('private-address')623 return unit_get('private-address')
624624
625625
626@cached
627def storage_get(attribute="", storage_id=""):
628 """Get storage attributes"""
629 _args = ['storage-get', '--format=json']
630 if storage_id:
631 _args.extend(('-s', storage_id))
632 if attribute:
633 _args.append(attribute)
634 try:
635 return json.loads(subprocess.check_output(_args).decode('UTF-8'))
636 except ValueError:
637 return None
638
639
640@cached
641def storage_list(storage_name=""):
642 """List the storage IDs for the unit"""
643 _args = ['storage-list', '--format=json']
644 if storage_name:
645 _args.append(storage_name)
646 try:
647 return json.loads(subprocess.check_output(_args).decode('UTF-8'))
648 except ValueError:
649 return None
650 except OSError as e:
651 import errno
652 if e.errno == errno.ENOENT:
653 # storage-list does not exist
654 return []
655 raise
656
657
626class UnregisteredHookError(Exception):658class UnregisteredHookError(Exception):
627 """Raised when an undefined hook is called"""659 """Raised when an undefined hook is called"""
628 pass660 pass
629661
=== modified file 'tests/core/test_hookenv.py'
--- tests/core/test_hookenv.py 2015-08-26 17:32:36 +0000
+++ tests/core/test_hookenv.py 2015-09-24 01:29:26 +0000
@@ -1500,3 +1500,79 @@
1500 def test_action_tag(self):1500 def test_action_tag(self):
1501 with patch.dict('os.environ', JUJU_ACTION_TAG='action-jack'):1501 with patch.dict('os.environ', JUJU_ACTION_TAG='action-jack'):
1502 self.assertEqual(hookenv.action_tag(), 'action-jack')1502 self.assertEqual(hookenv.action_tag(), 'action-jack')
1503
1504 @patch('subprocess.check_output')
1505 def test_storage_list(self, check_output):
1506 ids = ['data/0', 'data/1', 'data/2']
1507 check_output.return_value = json.dumps(ids).encode('UTF-8')
1508
1509 storage_name = 'arbitrary'
1510 result = hookenv.storage_list(storage_name)
1511
1512 self.assertEqual(result, ids)
1513 check_output.assert_called_with(['storage-list', '--format=json',
1514 storage_name])
1515
1516 @patch('subprocess.check_output')
1517 def test_storage_list_notexist(self, check_output):
1518 import errno
1519 e = OSError()
1520 e.errno = errno.ENOENT
1521 check_output.side_effect = e
1522
1523 result = hookenv.storage_list()
1524
1525 self.assertEqual(result, [])
1526 check_output.assert_called_with(['storage-list', '--format=json'])
1527
1528 @patch('subprocess.check_output')
1529 def test_storage_get_notexist(self, check_output):
1530 # storage_get does not catch ENOENT, because there's no reason why you
1531 # should be calling storage_get except from a storage hook, or with
1532 # the result of storage_list (which will return [] as shown above).
1533
1534 import errno
1535 e = OSError()
1536 e.errno = errno.ENOENT
1537 check_output.side_effect = e
1538 self.assertRaises(OSError, hookenv.storage_get)
1539
1540 @patch('subprocess.check_output')
1541 def test_storage_get(self, check_output):
1542 expect = {
1543 'location': '/dev/sda',
1544 'kind': 'block',
1545 }
1546 check_output.return_value = json.dumps(expect).encode('UTF-8')
1547
1548 result = hookenv.storage_get()
1549
1550 self.assertEqual(result, expect)
1551 check_output.assert_called_with(['storage-get', '--format=json'])
1552
1553 @patch('subprocess.check_output')
1554 def test_storage_get_attr(self, check_output):
1555 expect = '/dev/sda'
1556 check_output.return_value = json.dumps(expect).encode('UTF-8')
1557
1558 attribute = 'location'
1559 result = hookenv.storage_get(attribute)
1560
1561 self.assertEqual(result, expect)
1562 check_output.assert_called_with(['storage-get', '--format=json',
1563 attribute])
1564
1565 @patch('subprocess.check_output')
1566 def test_storage_get_with_id(self, check_output):
1567 expect = {
1568 'location': '/dev/sda',
1569 'kind': 'block',
1570 }
1571 check_output.return_value = json.dumps(expect).encode('UTF-8')
1572
1573 storage_id = 'data/0'
1574 result = hookenv.storage_get(storage_id=storage_id)
1575
1576 self.assertEqual(result, expect)
1577 check_output.assert_called_with(['storage-get', '--format=json',
1578 '-s', storage_id])

Subscribers

People subscribed via source and target branches