Skip to content

Commit

Permalink
Merge pull request #45 from gechiang/202205
Browse files Browse the repository at this point in the history
[show] Update show run all to cover all asic config in multiasic (#3148)
  • Loading branch information
gechiang authored Feb 23, 2024
2 parents 6535704 + f068356 commit a364953
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 19 deletions.
51 changes: 34 additions & 17 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,24 @@ def get_cmd_output(cmd):
proc = subprocess.Popen(cmd, text=True, stdout=subprocess.PIPE)
return proc.communicate()[0], proc.returncode

def get_config_json_by_namespace(namespace):
cmd = ['sonic-cfggen', '-d', '--print-data']
if namespace is not None and namespace != multi_asic.DEFAULT_NAMESPACE:
cmd += ['-n', namespace]

stdout, rc = get_cmd_output(cmd)
if rc:
click.echo("Failed to get cmd output '{}':rc {}".format(cmd, rc))
raise click.Abort()

try:
config_json = json.loads(stdout)
except JSONDecodeError as e:
click.echo("Failed to load output '{}':{}".format(cmd, e))
raise click.Abort()

return config_json

# Lazy global class instance for SONiC interface name to alias conversion
iface_alias_converter = lazy_object_proxy.Proxy(lambda: clicommon.InterfaceAliasConverter())

Expand Down Expand Up @@ -1247,25 +1265,24 @@ def runningconfiguration():
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def all(verbose):
"""Show full running configuration"""
cmd = ['sonic-cfggen', '-d', '--print-data']
stdout, rc = get_cmd_output(cmd)
if rc:
click.echo("Failed to get cmd output '{}':rc {}".format(cmd, rc))
raise click.Abort()
output = {}
bgpraw_cmd = "show running-config"

try:
output = json.loads(stdout)
except JSONDecodeError as e:
click.echo("Failed to load output '{}':{}".format(cmd, e))
raise click.Abort()
import utilities_common.bgp_util as bgp_util
# In multiaisc, the namespace is changed to 'localhost' by design
host_config = get_config_json_by_namespace(multi_asic.DEFAULT_NAMESPACE)
output['localhost'] = host_config

if not multi_asic.is_multi_asic():
bgpraw_cmd = [constants.RVTYSH_COMMAND, '-c', 'show running-config']
bgpraw, rc = get_cmd_output(bgpraw_cmd)
if rc:
bgpraw = ""
output['bgpraw'] = bgpraw
click.echo(json.dumps(output, indent=4))
if multi_asic.is_multi_asic():
ns_list = multi_asic.get_namespace_list()
for ns in ns_list:
ns_config = get_config_json_by_namespace(ns)
ns_config['bgpraw'] = bgp_util.run_bgp_show_command(bgpraw_cmd, ns)
output[ns] = ns_config
click.echo(json.dumps(output, indent=4))
else:
host_config['bgpraw'] = bgp_util.run_bgp_show_command(bgpraw_cmd)
click.echo(json.dumps(output['localhost'], indent=4))


# 'acl' subcommand ("show runningconfiguration acl")
Expand Down
58 changes: 56 additions & 2 deletions tests/show_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os
import sys
import pytest
import importlib
import show.main as show
import utilities_common.bgp_util as bgp_util
from click.testing import CliRunner
from unittest import mock
from unittest.mock import call, MagicMock, patch
Expand All @@ -19,6 +21,12 @@ class TestShowRunAllCommands(object):
def setup_class(cls):
print("SETUP")
os.environ["UTILITIES_UNIT_TESTING"] = "1"
cls._old_run_bgp_command = bgp_util.run_bgp_command
bgp_util.run_bgp_command = mock.MagicMock(
return_value=cls.mock_run_bgp_command())

def mock_run_bgp_command():
return ""

def test_show_runningconfiguration_all_json_loads_failure(self):
def get_cmd_output_side_effect(*args, **kwargs):
Expand All @@ -42,16 +50,62 @@ def get_cmd_output_side_effect(*args, **kwargs):
with mock.patch('show.main.get_cmd_output',
mock.MagicMock(side_effect=get_cmd_output_side_effect)) as mock_get_cmd_output:
result = CliRunner().invoke(show.cli.commands['runningconfiguration'].commands['all'], [])
assert mock_get_cmd_output.call_count == 2
assert result.exit_code == 0
assert mock_get_cmd_output.call_count == 1
assert mock_get_cmd_output.call_args_list == [
call(['sonic-cfggen', '-d', '--print-data'])]

@classmethod
def teardown_class(cls):
print("TEARDOWN")
bgp_util.run_bgp_command = cls._old_run_bgp_command
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1])
os.environ["UTILITIES_UNIT_TESTING"] = "0"


class TestShowRunAllCommandsMasic(object):
@classmethod
def setup_class(cls):
print("SETUP")
os.environ['UTILITIES_UNIT_TESTING'] = "2"
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "multi_asic"
cls._old_run_bgp_command = bgp_util.run_bgp_command
bgp_util.run_bgp_command = mock.MagicMock(
return_value=cls.mock_run_bgp_command())
# change to multi asic config
from .mock_tables import dbconnector
from .mock_tables import mock_multi_asic
importlib.reload(mock_multi_asic)
dbconnector.load_namespace_config()

def mock_run_bgp_command():
return ""

def test_show_runningconfiguration_all_masic(self):
def get_cmd_output_side_effect(*args, **kwargs):
return "{}", 0
with mock.patch('show.main.get_cmd_output',
mock.MagicMock(side_effect=get_cmd_output_side_effect)) as mock_get_cmd_output:
result = CliRunner().invoke(show.cli.commands['runningconfiguration'].commands['all'], [])
assert result.exit_code == 0
assert mock_get_cmd_output.call_count == 3
assert mock_get_cmd_output.call_args_list == [
call(['sonic-cfggen', '-d', '--print-data']),
call(['rvtysh', '-c', 'show running-config'])]
call(['sonic-cfggen', '-d', '--print-data', '-n', 'asic0']),
call(['sonic-cfggen', '-d', '--print-data', '-n', 'asic1'])]

@classmethod
def teardown_class(cls):
print("TEARDOWN")
bgp_util.run_bgp_command = cls._old_run_bgp_command
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1])
os.environ["UTILITIES_UNIT_TESTING"] = "0"
# change back to single asic config
from .mock_tables import dbconnector
from .mock_tables import mock_single_asic
importlib.reload(mock_single_asic)
dbconnector.load_namespace_config()


@patch('show.main.run_command')
@pytest.mark.parametrize(
Expand Down

0 comments on commit a364953

Please sign in to comment.