diff --git a/config/syslog.py b/config/syslog.py index 7533a7f71f..a5d520d9cf 100644 --- a/config/syslog.py +++ b/config/syslog.py @@ -5,7 +5,9 @@ import subprocess import utilities_common.cli as clicommon +import utilities_common.multi_asic as multi_asic_util from sonic_py_common import logger +from sonic_py_common import multi_asic from syslog_util import common as syslog_common @@ -457,20 +459,46 @@ def delete(db, server_ip_address): def rate_limit_host(db, interval, burst): """ Configure syslog rate limit for host """ syslog_common.rate_limit_validator(interval, burst) - syslog_common.save_rate_limit_to_db(db, None, interval, burst, log) + syslog_common.save_rate_limit_to_db(db.cfgdb, None, interval, burst, log) @syslog.command("rate-limit-container") @click.argument("service_name", required=True) @click.option("-i", "--interval", help="Configures syslog rate limit interval in seconds for specified containers", type=click.IntRange(0, 2147483647)) @click.option("-b", "--burst", help="Configures syslog rate limit burst in number of messages for specified containers", type=click.IntRange(0, 2147483647)) +@click.option('--namespace', '-n', 'namespace', default=None, + type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']), + show_default=True, help='Namespace name or all') @clicommon.pass_db -def rate_limit_container(db, service_name, interval, burst): +def rate_limit_container(db, service_name, interval, burst, namespace): """ Configure syslog rate limit for containers """ syslog_common.rate_limit_validator(interval, burst) - feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE) + features = db.cfgdb.get_table(syslog_common.FEATURE_TABLE) + syslog_common.service_validator(features, service_name) + + global_feature_data, per_ns_feature_data = syslog_common.extract_feature_data(features) + if not namespace: + # for all namespaces + for namespace, cfg_db in db.cfgdb_clients.items(): + if namespace == multi_asic.DEFAULT_NAMESPACE: + feature_data = global_feature_data + else: + feature_data = per_ns_feature_data + if service_name and service_name not in feature_data: + continue + syslog_common.service_validator(feature_data, service_name) + syslog_common.save_rate_limit_to_db(cfg_db, service_name, interval, burst, log) + return + elif namespace == 'default': + # for default/global namespace only + namespace = multi_asic.DEFAULT_NAMESPACE + feature_data = global_feature_data + else: + # for a specific namespace + feature_data = per_ns_feature_data + syslog_common.service_validator(feature_data, service_name) - syslog_common.save_rate_limit_to_db(db, service_name, interval, burst, log) + syslog_common.save_rate_limit_to_db(db.cfgdb_clients[namespace], service_name, interval, burst, log) @syslog.group( @@ -482,14 +510,70 @@ def rate_limit_feature(): pass +def get_feature_names_to_proceed(db, service_name, namespace): + """Get feature name list to be proceed by "config syslog rate-limit-feature enable" and + "config syslog rate-limit-feature disable" CLIs + + Args: + db (object): Db object + service_name (str): Nullable service name to be enable/disable + namespace (str): Namespace provided by user + + Returns: + list: A list of feature name + """ + features = db.cfgdb.get_table(syslog_common.FEATURE_TABLE) + if service_name: + syslog_common.service_validator(features, service_name) + + global_feature_data, per_ns_feature_data = syslog_common.extract_feature_data(features) + if not namespace: + if not service_name: + feature_list = [feature_name for feature_name in global_feature_data.keys()] + if multi_asic.is_multi_asic(): + asic_count = multi_asic.get_num_asics() + for i in range(asic_count): + feature_list.extend([f'{feature_name}{i}' for feature_name in per_ns_feature_data.keys()]) + else: + feature_config = features[service_name] + feature_list = [] + if feature_config[syslog_common.FEATURE_HAS_GLOBAL_SCOPE].lower() == 'true': + feature_list.append(service_name) + + if multi_asic.is_multi_asic(): + if feature_config[syslog_common.FEATURE_HAS_PER_ASIC_SCOPE].lower() == 'true': + asic_count = multi_asic.get_num_asics() + for i in range(asic_count): + feature_list.append(multi_asic.get_container_name_from_asic_id(service_name, i)) + elif namespace == 'default': + if not service_name: + feature_list = [feature_name for feature_name in global_feature_data.keys()] + else: + syslog_common.service_validator(global_feature_data, service_name) + feature_list = [service_name] + else: + asic_num = multi_asic.get_asic_id_from_name(namespace) + if not service_name: + feature_list = [multi_asic.get_container_name_from_asic_id(feature_name, asic_num) for feature_name in per_ns_feature_data.keys()] + else: + syslog_common.service_validator(per_ns_feature_data, service_name) + feature_list = [multi_asic.get_container_name_from_asic_id(service_name, asic_num)] + return feature_list + + @rate_limit_feature.command("enable") +@click.argument("service_name", required=False) +@click.option('--namespace', '-n', 'namespace', default=None, + type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']), + show_default=True, help='Namespace name or all') @clicommon.pass_db -def enable_rate_limit_feature(db): +def enable_rate_limit_feature(db, service_name, namespace): """ Enable syslog rate limit feature """ - feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE) - for feature_name in feature_data.keys(): + feature_list = get_feature_names_to_proceed(db, service_name, namespace) + for feature_name in feature_list: click.echo(f'Enabling syslog rate limit feature for {feature_name}') - output, _ = clicommon.run_command(['docker', 'ps', '-q', '-f', 'status=running', '-f', f'name={feature_name}'], return_cmd=True) + shell_cmd = f'docker ps -f status=running --format "{{{{.Names}}}}" | grep -E "^{feature_name}$"' + output, _ = clicommon.run_command(shell_cmd, return_cmd=True, shell=True) if not output: click.echo(f'{feature_name} is not running, ignoring...') continue @@ -517,16 +601,21 @@ def enable_rate_limit_feature(db): if not failed: click.echo(f'Enabled syslog rate limit feature for {feature_name}') - - + + @rate_limit_feature.command("disable") +@click.argument("service_name", required=False) +@click.option('--namespace', '-n', 'namespace', default=None, + type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']), + show_default=True, help='Namespace name or all') @clicommon.pass_db -def disable_rate_limit_feature(db): +def disable_rate_limit_feature(db, service_name, namespace): """ Disable syslog rate limit feature """ - feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE) - for feature_name in feature_data.keys(): + feature_list = get_feature_names_to_proceed(db, service_name, namespace) + for feature_name in feature_list: click.echo(f'Disabling syslog rate limit feature for {feature_name}') - output, _ = clicommon.run_command(['docker', 'ps', '-q', '-f', 'status=running', '-f', f'name={feature_name}'], return_cmd=True) + shell_cmd = f'docker ps -f status=running --format "{{{{.Names}}}}" | grep -E "^{feature_name}$"' + output, _ = clicommon.run_command(shell_cmd, return_cmd=True, shell=True) if not output: click.echo(f'{feature_name} is not running, ignoring...') continue @@ -553,4 +642,3 @@ def disable_rate_limit_feature(db): if not failed: click.echo(f'Disabled syslog rate limit feature for {feature_name}') - diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index 0709b6d4f1..e97922af65 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -10149,7 +10149,7 @@ This command displays rate limit configuration for containers. - Usage ``` - show syslog rate-limit-container [] + show syslog rate-limit-container [] -n [] ``` - Example: @@ -10173,6 +10173,37 @@ This command displays rate limit configuration for containers. SERVICE INTERVAL BURST -------------- ---------- ------- bgp 0 0 + + # Multi ASIC + show syslog rate-limit-container + SERVICE INTERVAL BURST + -------- ---------- -------- + bgp 500 N/A + snmp 300 20000 + swss 2000 12000 + Namespace asic0: + SERVICE INTERVAL BURST + -------- ---------- -------- + bgp 500 N/A + snmp 300 20000 + swss 2000 12000 + + # Multi ASIC + show syslog rate-limit-container bgp + SERVICE INTERVAL BURST + -------- ---------- -------- + bgp 500 5000 + Namespace asic0: + SERVICE INTERVAL BURST + -------- ---------- -------- + bgp 500 5000 + + # Multi ASIC + show syslog rate-limit-container bgp -n asic1 + Namespace asic1: + SERVICE INTERVAL BURST + -------- ---------- -------- + bgp 500 5000 ``` ### Syslog Config Commands @@ -10251,10 +10282,19 @@ This command is used to configure syslog rate limit for containers. - Parameters: - _interval_: determines the amount of time that is being measured for rate limiting. - _burst_: defines the amount of messages, that have to occur in the time limit of interval, to trigger rate limiting + - _namespace_: namespace name or all. Value "default" indicates global namespace. - Example: ``` + # Config bgp for all namespaces. For multi ASIC platforms, bgp service in all namespaces will be affected. + # For single ASIC platforms, bgp service in global namespace will be affected. admin@sonic:~$ sudo config syslog rate-limit-container bgp --interval 300 --burst 20000 + + # Config bgp for global namespace only. + config syslog rate-limit-container bgp --interval 300 --burst 20000 -n default + + # Config bgp for asic0 namespace only. + config syslog rate-limit-container bgp --interval 300 --burst 20000 -n asic0 ``` **config syslog rate-limit-feature enable** @@ -10263,12 +10303,28 @@ This command is used to enable syslog rate limit feature. - Usage: ``` - config syslog rate-limit-feature enable + config syslog rate-limit-feature enable [] -n [] ``` - Example: ``` + # Enable syslog rate limit for all services in all namespaces admin@sonic:~$ sudo config syslog rate-limit-feature enable + + # Enable syslog rate limit for all services in global namespace + config syslog rate-limit-feature enable -n default + + # Enable syslog rate limit for all services in asic0 namespace + config syslog rate-limit-feature enable -n asic0 + + # Enable syslog rate limit for database in all namespaces + config syslog rate-limit-feature enable database + + # Enable syslog rate limit for database in default namespace + config syslog rate-limit-feature enable database -n default + + # Enable syslog rate limit for database in asci0 namespace + config syslog rate-limit-feature enable database -n asci0 ``` **config syslog rate-limit-feature disable** @@ -10277,12 +10333,28 @@ This command is used to disable syslog rate limit feature. - Usage: ``` - config syslog rate-limit-feature disable + config syslog rate-limit-feature disable [] -n [] ``` - Example: ``` + # Disable syslog rate limit for all services in all namespaces admin@sonic:~$ sudo config syslog rate-limit-feature disable + + # Disable syslog rate limit for all services in global namespace + config syslog rate-limit-feature disable -n default + + # Disable syslog rate limit for all services in asic0 namespace + config syslog rate-limit-feature disable -n asic0 + + # Disable syslog rate limit for database in all namespaces + config syslog rate-limit-feature disable database + + # Disable syslog rate limit for database in default namespace + config syslog rate-limit-feature disable database -n default + + # Disable syslog rate limit for database in asci0 namespace + config syslog rate-limit-feature disable database -n asci0 ``` Go Back To [Beginning of the document](#) or [Beginning of this section](#syslog) diff --git a/show/syslog.py b/show/syslog.py index d258be3351..ad4e7b5b85 100644 --- a/show/syslog.py +++ b/show/syslog.py @@ -1,9 +1,12 @@ +from unicodedata import name import click import tabulate from natsort import natsorted import utilities_common.cli as clicommon +import utilities_common.multi_asic as multi_asic_util +from sonic_py_common import multi_asic from syslog_util import common as syslog_common @@ -83,8 +86,11 @@ def rate_limit_host(db): name='rate-limit-container' ) @click.argument('service_name', metavar='', required=False) +@click.option('--namespace', '-n', 'namespace', default=None, + type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']), + show_default=True, help='Namespace name or all') @clicommon.pass_db -def rate_limit_container(db, service_name): +def rate_limit_container(db, service_name, namespace): """ Show syslog rate limit configuration for containers """ header = [ @@ -92,16 +98,57 @@ def rate_limit_container(db, service_name): "INTERVAL", "BURST", ] - body = [] + + # Feature configuration in global DB features = db.cfgdb.get_table(syslog_common.FEATURE_TABLE) - + if service_name: + syslog_common.service_validator(features, service_name) + + global_feature_data, per_ns_feature_data = syslog_common.extract_feature_data(features) + if not namespace: + # for all namespaces + is_first = True + for namespace, cfg_db in natsorted(db.cfgdb_clients.items()): + if is_first: + is_first = False + else: + # add a new blank line between each namespace + click.echo('\n') + + if namespace == multi_asic.DEFAULT_NAMESPACE: + if service_name and service_name not in global_feature_data: + continue + echo_rate_limit_config(header, cfg_db, service_name, global_feature_data) + else: + if service_name and service_name not in per_ns_feature_data: + continue + echo_rate_limit_config(header, cfg_db, service_name, per_ns_feature_data, namespace) + elif namespace == 'default': + # for default/global namespace only + echo_rate_limit_config(header, db.cfgdb, service_name, global_feature_data) + else: + # for a specific namespace + echo_rate_limit_config(header, db.cfgdb_clients[namespace], service_name, per_ns_feature_data, namespace) + + +def echo_rate_limit_config(header, db, service_name, features, namespace=None): + """Echo rate limit configuration + + Args: + header (list): CLI headers + db (object): Db object + service_name (str): Nullable service name to be printed. + features (dict): Feature data got from CONFIG DB + namespace (str, optional): Namespace provided by user. Defaults to None. + """ + body = [] if service_name: syslog_common.service_validator(features, service_name) service_list = [service_name] else: - service_list = [name for name, service_config in features.items() if service_config.get(syslog_common.SUPPORT_RATE_LIMIT, '').lower() == 'true'] - - syslog_configs = db.cfgdb.get_table(syslog_common.SYSLOG_CONFIG_FEATURE_TABLE) + service_list = features.keys() + + syslog_configs = db.get_table(syslog_common.SYSLOG_CONFIG_FEATURE_TABLE) for service in natsorted(service_list): if service in syslog_configs: entry = syslog_configs[service] @@ -110,5 +157,11 @@ def rate_limit_container(db, service_name): entry.get(syslog_common.SYSLOG_RATE_LIMIT_BURST, 'N/A')]) else: body.append([service, 'N/A', 'N/A']) - - click.echo(format(header, body)) + + if namespace: + click.echo(f'Namespace {namespace}:') + + if body: + click.echo(format(header, body)) + else: + click.echo('N/A') diff --git a/syslog_util/common.py b/syslog_util/common.py index 5282c088e8..742e6ae059 100644 --- a/syslog_util/common.py +++ b/syslog_util/common.py @@ -1,4 +1,5 @@ import click +from sonic_py_common import multi_asic FEATURE_TABLE = "FEATURE" @@ -9,6 +10,8 @@ SYSLOG_RATE_LIMIT_INTERVAL = 'rate_limit_interval' SYSLOG_RATE_LIMIT_BURST = 'rate_limit_burst' SUPPORT_RATE_LIMIT = 'support_syslog_rate_limit' +FEATURE_HAS_GLOBAL_SCOPE = 'has_global_scope' +FEATURE_HAS_PER_ASIC_SCOPE = 'has_per_asic_scope' def rate_limit_validator(interval, burst): @@ -70,7 +73,33 @@ def save_rate_limit_to_db(db, service_name, interval, burst, log): data[SYSLOG_RATE_LIMIT_INTERVAL] = interval if burst is not None: data[SYSLOG_RATE_LIMIT_BURST] = burst - db.cfgdb.mod_entry(table, key, data) + db.mod_entry(table, key, data) log.log_notice(f"Configured syslog {service_name} rate-limits: interval={data.get(SYSLOG_RATE_LIMIT_INTERVAL, 'N/A')},\ burst={data.get(SYSLOG_RATE_LIMIT_BURST, 'N/A')}") + +def extract_feature_data(features): + """Extract feature data in global scope and feature data in per ASIC namespace scope + + Args: + features (dict): Feature data got from CONFIG DB + + Returns: + tuple: + """ + global_feature_data = {} + per_ns_feature_data = {} + is_multi_asic = multi_asic.is_multi_asic() + for feature_name, feature_config in features.items(): + if not feature_config.get(SUPPORT_RATE_LIMIT, '').lower() == 'true': + continue + + if is_multi_asic: + if feature_config.get(FEATURE_HAS_GLOBAL_SCOPE, '').lower() == 'true': + global_feature_data[feature_name] = feature_config + + if feature_config.get(FEATURE_HAS_PER_ASIC_SCOPE, '').lower() == 'true': + per_ns_feature_data[feature_name] = feature_config + else: + global_feature_data[feature_name] = feature_config + return global_feature_data, per_ns_feature_data diff --git a/tests/mock_tables/asic0/config_db.json b/tests/mock_tables/asic0/config_db.json index 3117115489..7b4cac3430 100644 --- a/tests/mock_tables/asic0/config_db.json +++ b/tests/mock_tables/asic0/config_db.json @@ -294,5 +294,13 @@ "monErrThreshRxCells": "61035156", "monPollThreshIsolation": "1", "monPollThreshRecovery": "8" + }, + "SYSLOG_CONFIG_FEATURE|bgp": { + "rate_limit_interval": "111", + "rate_limit_burst": "33333" + }, + "SYSLOG_CONFIG_FEATURE|database": { + "rate_limit_interval": "222", + "rate_limit_burst": "22222" } } diff --git a/tests/mock_tables/asic1/config_db.json b/tests/mock_tables/asic1/config_db.json index 95cf040544..56823ae113 100644 --- a/tests/mock_tables/asic1/config_db.json +++ b/tests/mock_tables/asic1/config_db.json @@ -234,5 +234,13 @@ "monErrThreshRxCells": "61035156", "monPollThreshIsolation": "1", "monPollThreshRecovery": "8" + }, + "SYSLOG_CONFIG_FEATURE|bgp": { + "rate_limit_interval": "444", + "rate_limit_burst": "44444" + }, + "SYSLOG_CONFIG_FEATURE|database": { + "rate_limit_interval": "555", + "rate_limit_burst": "55555" } } diff --git a/tests/mock_tables/config_db.json b/tests/mock_tables/config_db.json index 2a81f96bfa..8806595ede 100644 --- a/tests/mock_tables/config_db.json +++ b/tests/mock_tables/config_db.json @@ -793,13 +793,19 @@ "state": "enabled", "auto_restart": "enabled", "high_mem_alert": "disabled", - "set_owner": "local" + "set_owner": "local", + "support_syslog_rate_limit": "true", + "has_global_scope": "false", + "has_per_asic_scope": "true" }, "FEATURE|database": { "state": "always_enabled", "auto_restart": "always_enabled", "high_mem_alert": "disabled", - "set_owner": "local" + "set_owner": "local", + "support_syslog_rate_limit": "true", + "has_global_scope": "true", + "has_per_asic_scope": "true" }, "FEATURE|dhcp_relay": { "state": "enabled", @@ -823,7 +829,10 @@ "state": "enabled", "auto_restart": "enabled", "high_mem_alert": "disabled", - "set_owner": "kube" + "set_owner": "kube", + "support_syslog_rate_limit": "true", + "has_global_scope": "true", + "has_per_asic_scope": "false" }, "FEATURE|radv": { "state": "enabled", @@ -873,6 +882,14 @@ "high_mem_alert": "disabled", "set_owner": "kube" }, + "SYSLOG_CONFIG_FEATURE|database": { + "rate_limit_interval": "200", + "rate_limit_burst": "20000" + }, + "SYSLOG_CONFIG_FEATURE|pmon": { + "rate_limit_interval": "100", + "rate_limit_burst": "10000" + }, "DEVICE_METADATA|localhost": { "default_bgp_status": "down", "default_pfcwd_status": "enable", diff --git a/tests/syslog_multi_asic_test.py b/tests/syslog_multi_asic_test.py new file mode 100644 index 0000000000..7933edcd66 --- /dev/null +++ b/tests/syslog_multi_asic_test.py @@ -0,0 +1,281 @@ +import mock +import pytest +from click.testing import CliRunner +from importlib import reload +from utilities_common.db import Db + +show_all_config = """SERVICE INTERVAL BURST +--------- ---------- ------- +database 200 20000 +pmon 100 10000 + + +Namespace asic0: +SERVICE INTERVAL BURST +--------- ---------- ------- +bgp 111 33333 +database 222 22222 + + +Namespace asic1: +SERVICE INTERVAL BURST +--------- ---------- ------- +bgp 444 44444 +database 555 55555 +""" + +show_global_ns_config = """SERVICE INTERVAL BURST +--------- ---------- ------- +database 200 20000 +pmon 100 10000 +""" + +show_asic0_ns_config = """Namespace asic0: +SERVICE INTERVAL BURST +--------- ---------- ------- +bgp 111 33333 +database 222 22222 +""" + +show_all_ns_database_config = """SERVICE INTERVAL BURST +--------- ---------- ------- +database 200 20000 + + +Namespace asic0: +SERVICE INTERVAL BURST +--------- ---------- ------- +database 222 22222 + + +Namespace asic1: +SERVICE INTERVAL BURST +--------- ---------- ------- +database 555 55555 +""" + +show_global_ns_database_config = """SERVICE INTERVAL BURST +--------- ---------- ------- +database 200 20000 +""" + +show_asic0_ns_database_config = """Namespace asic0: +SERVICE INTERVAL BURST +--------- ---------- ------- +database 222 22222 +""" + + +@pytest.fixture(scope='module') +def setup_cmd_module(): + # Mock to multi ASIC + from .mock_tables import mock_multi_asic + from .mock_tables import dbconnector + reload(mock_multi_asic) + dbconnector.load_namespace_config() + + import show.main as show + import config.main as config + + # Refresh syslog module for show and config + import show.syslog as show_syslog + reload(show_syslog) + show.cli.add_command(show_syslog.syslog) + + import config.syslog as config_syslog + reload(config_syslog) + config.config.add_command(config_syslog.syslog) + + yield show, config + + # Mock back to single ASIC + from .mock_tables import mock_single_asic + reload(mock_single_asic) + + # Refresh syslog module for show and config + reload(show_syslog) + show.cli.add_command(show_syslog.syslog) + + reload(config_syslog) + config.config.add_command(config_syslog.syslog) + + +class TestSyslogRateLimitMultiAsic: + def test_show_rate_limit_container(self, setup_cmd_module): + show, _ = setup_cmd_module + + runner = CliRunner() + result = runner.invoke( + show.cli.commands["syslog"].commands["rate-limit-container"], + [] + ) + + assert result.output == show_all_config + assert result.exit_code == 0 + + result = runner.invoke( + show.cli.commands["syslog"].commands["rate-limit-container"], ["-n", "default"] + ) + + assert result.output == show_global_ns_config + assert result.exit_code == 0 + + result = runner.invoke( + show.cli.commands["syslog"].commands["rate-limit-container"], ["-n", "asic0"] + ) + + assert result.output == show_asic0_ns_config + assert result.exit_code == 0 + + result = runner.invoke( + show.cli.commands["syslog"].commands["rate-limit-container"], ["database"] + ) + + assert result.output == show_all_ns_database_config + assert result.exit_code == 0 + + result = runner.invoke( + show.cli.commands["syslog"].commands["rate-limit-container"], ["database", "-n", "default"] + ) + + assert result.output == show_global_ns_database_config + assert result.exit_code == 0 + + result = runner.invoke( + show.cli.commands["syslog"].commands["rate-limit-container"], ["database", "-n", "asic0"] + ) + + assert result.output == show_asic0_ns_database_config + assert result.exit_code == 0 + + def test_config_rate_limit_container(self, setup_cmd_module): + _, config = setup_cmd_module + + runner = CliRunner() + db = Db() + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-container"], + ["database", "--interval", 1, "--burst", 100], obj=db + ) + assert result.exit_code == 0 + for cfg_db in db.cfgdb_clients.values(): + data = cfg_db.get_entry('SYSLOG_CONFIG_FEATURE', 'database') + assert data['rate_limit_burst'] == '100' + assert data['rate_limit_interval'] == '1' + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-container"], + ["bgp", "--interval", 1, "--burst", 100], obj=db + ) + assert result.exit_code == 0 + for namespace, cfg_db in db.cfgdb_clients.items(): + if namespace != '': + data = cfg_db.get_entry('SYSLOG_CONFIG_FEATURE', 'bgp') + assert data['rate_limit_burst'] == '100' + assert data['rate_limit_interval'] == '1' + else: + table = cfg_db.get_table('SYSLOG_CONFIG_FEATURE') + assert 'bgp' not in table + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-container"], + ["pmon", "--interval", 1, "--burst", 100], obj=db + ) + assert result.exit_code == 0 + for namespace, cfg_db in db.cfgdb_clients.items(): + if namespace == '': + data = cfg_db.get_entry('SYSLOG_CONFIG_FEATURE', 'pmon') + assert data['rate_limit_burst'] == '100' + assert data['rate_limit_interval'] == '1' + else: + table = cfg_db.get_table('SYSLOG_CONFIG_FEATURE') + assert 'pmon' not in table + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-container"], + ["pmon", "--interval", 2, "--burst", 200, "-n", "default"], obj=db + ) + assert result.exit_code == 0 + cfg_db = db.cfgdb_clients[''] + data = cfg_db.get_entry('SYSLOG_CONFIG_FEATURE', 'pmon') + assert data['rate_limit_burst'] == '200' + assert data['rate_limit_interval'] == '2' + + @mock.patch('config.syslog.clicommon.run_command', mock.MagicMock(return_value=('', 0))) + def test_enable_syslog_rate_limit_feature(self, setup_cmd_module): + _, config = setup_cmd_module + + runner = CliRunner() + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['enable'], [] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['enable'], + ['-n', 'default'] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['enable'], + ['-n', 'asic0'] + ) + + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['enable'], ['database'] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['enable'], + ['database', '-n', 'default'] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['enable'], + ['database', '-n', 'asic0'] + ) + assert result.exit_code == 0 + + @mock.patch('config.syslog.clicommon.run_command', mock.MagicMock(return_value=('', 0))) + def test_disable_syslog_rate_limit_feature(self, setup_cmd_module): + _, config = setup_cmd_module + + runner = CliRunner() + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['disable'], [] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['disable'], + ['-n', 'default'] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['disable'], + ['-n', 'asic0'] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['disable'], ['database'] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['disable'], + ['database', '-n', 'default'] + ) + assert result.exit_code == 0 + + result = runner.invoke( + config.config.commands["syslog"].commands["rate-limit-feature"].commands['disable'], + ['database', '-n', 'asic0'] + ) + assert result.exit_code == 0 diff --git a/tests/syslog_test.py b/tests/syslog_test.py index 44915b6d36..c1cbee1127 100644 --- a/tests/syslog_test.py +++ b/tests/syslog_test.py @@ -484,4 +484,3 @@ def side_effect(*args, **kwargs): config.config.commands["syslog"].commands["rate-limit-feature"].commands["disable"], obj=db ) assert result.exit_code == SUCCESS -