Modify the output to action "cluster-status"

to make it user friendly (rabbitmq)

"rabbitmqctl cluster_status" uses escape codes to color/highlight the
output, and it does not have a way to suppress this. This makes the
output to the command "juju run-action rabbitmq-server/leader
cluster-status" not user friendly and difficult to read.

Add the json formatting option to the rabbitmqctl command and use
the json.dumps method to get a user friendly output.

Add unit test.

Closes-Bug: #1943198
Change-Id: I24380e24ff1edbede9c2db1671a4fc05d5a7cc63
This commit is contained in:
Anna Savchenko 2021-10-18 15:24:03 +03:00 committed by anna-savchenko
parent af48cfe8ad
commit 223ec26617
4 changed files with 50 additions and 13 deletions

View File

@ -67,6 +67,7 @@ from hooks.rabbit_utils import (
assess_status,
list_vhosts,
vhost_queue_info,
rabbitmq_version_newer_or_equal,
)
@ -86,9 +87,17 @@ def resume(args):
def cluster_status(args):
"""Return the output of 'rabbitmqctl cluster_status'."""
try:
clusterstat = check_output(['rabbitmqctl', 'cluster_status'],
universal_newlines=True)
action_set({'output': clusterstat})
if rabbitmq_version_newer_or_equal('3.7'):
clusterstat = check_output(['rabbitmqctl', 'cluster_status',
'--formatter', 'json'],
universal_newlines=True)
clusterstat = json.loads(clusterstat)
action_set({'output': json.dumps(clusterstat, indent=4)})
else:
clusterstat = check_output(['rabbitmqctl', 'cluster_status'],
universal_newlines=True)
action_set({'output': clusterstat})
except CalledProcessError as e:
action_set({'output': e.output})
action_fail('Failed to run rabbitmqctl cluster_status')

View File

@ -426,7 +426,7 @@ def rabbitmqctl(action, *args):
#
# [1]: https://github.com/rabbitmq/rabbitmq-server/commit/3dd58ae1
WAIT_TIMEOUT_SECONDS = 180
focal_or_newer = _rabbitmq_version_newer_or_equal('3.8')
focal_or_newer = rabbitmq_version_newer_or_equal('3.8')
cmd = []
if 'wait' in action and not focal_or_newer:
@ -672,7 +672,7 @@ def disable_plugin(plugin):
def get_managment_port():
if _rabbitmq_version_newer_or_equal('3'):
if rabbitmq_version_newer_or_equal('3'):
return 15672
else:
return 55672
@ -1581,7 +1581,7 @@ def nrpe_update_cluster_check(nrpe_compat, user, password):
check_cmd='{}/check_rabbitmq_cluster.py'.format(NAGIOS_PLUGINS))
def _rabbitmq_version_newer_or_equal(version):
def rabbitmq_version_newer_or_equal(version):
"""Compare the installed RabbitMQ version
:param version: Version to compare with

View File

@ -15,6 +15,8 @@
import mock
from functools import wraps
import json
from unit_tests.test_utils import CharmTestCase
with mock.patch('charmhelpers.core.hookenv.cached') as cached:
@ -57,9 +59,34 @@ class ClusterStatusTestCase(CharmTestCase):
def setUp(self):
super(ClusterStatusTestCase, self).setUp(
actions, ["check_output", "action_set", "action_fail"])
actions, ["check_output", "action_set", "action_fail",
"rabbitmq_version_newer_or_equal"])
def test_cluster_status_json(self):
self.rabbitmq_version_newer_or_equal.return_value = True
self.check_output.return_value = json.dumps({"Status":
"Cluster status OK"})
actions.cluster_status([])
self.check_output.assert_called_once_with(['rabbitmqctl',
'cluster_status',
'--formatter', 'json'],
universal_newlines=True)
self.action_set.assert_called()
def test_cluster_status_exception_json(self):
self.rabbitmq_version_newer_or_equal.return_value = True
self.check_output.side_effect = actions.CalledProcessError(1,
"Failure")
actions.cluster_status([])
self.check_output.assert_called_once_with(['rabbitmqctl',
'cluster_status',
'--formatter', 'json'],
universal_newlines=True)
self.action_set.assert_called()
self.action_fail.assert_called()
def test_cluster_status(self):
self.rabbitmq_version_newer_or_equal.return_value = False
self.check_output.return_value = b'Cluster status OK'
actions.cluster_status([])
self.check_output.assert_called_once_with(['rabbitmqctl',
@ -68,6 +95,7 @@ class ClusterStatusTestCase(CharmTestCase):
self.action_set.assert_called()
def test_cluster_status_exception(self):
self.rabbitmq_version_newer_or_equal.return_value = False
self.check_output.side_effect = actions.CalledProcessError(1,
"Failure")
actions.cluster_status([])

View File

@ -422,7 +422,7 @@ class UtilsTests(CharmTestCase):
@mock.patch('rabbit_utils.leader_node')
@mock.patch('rabbit_utils.clustered')
@mock.patch('rabbit_utils.cmp_pkgrevno')
@mock.patch('rabbit_utils._rabbitmq_version_newer_or_equal')
@mock.patch('rabbit_utils.rabbitmq_version_newer_or_equal')
def test_cluster_with_not_clustered(
self, mock_new_rabbitmq, mock_cmp_pkgrevno, mock_clustered,
mock_leader_node, mock_running_nodes, mock_time, mock_check_output,
@ -686,7 +686,7 @@ class UtilsTests(CharmTestCase):
f.assert_called_once_with('assessor', services='s1', ports=None)
@mock.patch('rabbit_utils.subprocess.check_call')
@mock.patch('rabbit_utils._rabbitmq_version_newer_or_equal')
@mock.patch('rabbit_utils.rabbitmq_version_newer_or_equal')
def test_rabbitmqctl_wait_before_focal(self, mock_new_rabbitmq,
check_call):
mock_new_rabbitmq.return_value = False
@ -696,7 +696,7 @@ class UtilsTests(CharmTestCase):
'/var/lib/rabbitmq.pid'])
@mock.patch('rabbit_utils.subprocess.check_call')
@mock.patch('rabbit_utils._rabbitmq_version_newer_or_equal')
@mock.patch('rabbit_utils.rabbitmq_version_newer_or_equal')
def test_rabbitmqctl_wait_focal_or_newer(self, mock_new_rabbitmq,
check_call):
mock_new_rabbitmq.return_value = True
@ -711,7 +711,7 @@ class UtilsTests(CharmTestCase):
check_call.assert_called_with(['/usr/sbin/rabbitmqctl', 'start_app'])
@mock.patch('rabbit_utils.subprocess.check_call')
@mock.patch('rabbit_utils._rabbitmq_version_newer_or_equal')
@mock.patch('rabbit_utils.rabbitmq_version_newer_or_equal')
def test_rabbitmqctl_wait_fail(self, mock_new_rabbitmq,
check_call):
mock_new_rabbitmq.return_value = True
@ -883,12 +883,12 @@ class UtilsTests(CharmTestCase):
mock_cluster_ready.return_value = True
self.assertTrue(rabbit_utils.leader_node_is_ready())
@mock.patch('rabbit_utils._rabbitmq_version_newer_or_equal')
@mock.patch('rabbit_utils.rabbitmq_version_newer_or_equal')
def test_get_managment_port_legacy(self, mock_new_rabbitmq):
mock_new_rabbitmq.return_value = False
self.assertEqual(rabbit_utils.get_managment_port(), 55672)
@mock.patch('rabbit_utils._rabbitmq_version_newer_or_equal')
@mock.patch('rabbit_utils.rabbitmq_version_newer_or_equal')
def test_get_managment_port(self, mock_new_rabbitmq):
mock_new_rabbitmq.return_value = True
self.assertEqual(rabbit_utils.get_managment_port(), 15672)