From fe00bbf63283ca6f3842e470b88cdc5b6d266a0d Mon Sep 17 00:00:00 2001 From: Prince George <45705344+prgeor@users.noreply.github.com> Date: Fri, 17 Dec 2021 20:07:13 +0530 Subject: [PATCH] Revert "[sonic-package-manager] support sonic-cli-gen and packages with YANG model (#1650)" (#1972) This reverts commit f5e5a567f7e6f87eb3de81d29d988e042940e49a. --- config/config_mgmt.py | 110 ++--------- sonic_package_manager/main.py | 4 +- sonic_package_manager/manager.py | 21 +-- sonic_package_manager/manifest.py | 4 +- sonic_package_manager/metadata.py | 6 +- .../service_creator/creator.py | 172 ++---------------- .../service_creator/feature.py | 12 ++ tests/sonic_package_manager/conftest.py | 34 +--- .../test_service_creator.py | 113 +++--------- 9 files changed, 96 insertions(+), 380 deletions(-) diff --git a/config/config_mgmt.py b/config/config_mgmt.py index bbed677fa634..9b2021bef0c5 100644 --- a/config/config_mgmt.py +++ b/config/config_mgmt.py @@ -2,13 +2,8 @@ config_mgmt.py provides classes for configuration validation and for Dynamic Port Breakout. ''' - -import os import re -import shutil import syslog -import tempfile -import yang as ly from json import load from sys import flags from time import sleep as tsleep @@ -51,14 +46,27 @@ def __init__(self, source="configDB", debug=False, allowTablesWithoutYang=True): try: self.configdbJsonIn = None self.configdbJsonOut = None - self.source = source self.allowTablesWithoutYang = allowTablesWithoutYang # logging vars self.SYSLOG_IDENTIFIER = "ConfigMgmt" self.DEBUG = debug - self.__init_sonic_yang() + self.sy = sonic_yang.SonicYang(YANG_DIR, debug=debug) + # load yang models + self.sy.loadYangModel() + # load jIn from config DB or from config DB json file. + if source.lower() == 'configdb': + self.readConfigDB() + # treat any other source as file input + else: + self.readConfigDBJson(source) + # this will crop config, xlate and load. + self.sy.loadData(self.configdbJsonIn) + + # Raise if tables without YANG models are not allowed but exist. + if not allowTablesWithoutYang and len(self.sy.tablesWithOutYang): + raise Exception('Config has tables without YANG models') except Exception as e: self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e)) @@ -66,23 +74,6 @@ def __init__(self, source="configDB", debug=False, allowTablesWithoutYang=True): return - def __init_sonic_yang(self): - self.sy = sonic_yang.SonicYang(YANG_DIR, debug=self.DEBUG) - # load yang models - self.sy.loadYangModel() - # load jIn from config DB or from config DB json file. - if self.source.lower() == 'configdb': - self.readConfigDB() - # treat any other source as file input - else: - self.readConfigDBJson(self.source) - # this will crop config, xlate and load. - self.sy.loadData(self.configdbJsonIn) - - # Raise if tables without YANG models are not allowed but exist. - if not self.allowTablesWithoutYang and len(self.sy.tablesWithOutYang): - raise Exception('Config has tables without YANG models') - def __del__(self): pass @@ -222,69 +213,6 @@ def writeConfigDB(self, jDiff): return - def add_module(self, yang_module_str): - """ - Validate and add new YANG module to the system. - - Parameters: - yang_module_str (str): YANG module in string representation. - - Returns: - None - """ - - module_name = self.get_module_name(yang_module_str) - module_path = os.path.join(YANG_DIR, '{}.yang'.format(module_name)) - if os.path.exists(module_path): - raise Exception('{} already exists'.format(module_name)) - with open(module_path, 'w') as module_file: - module_file.write(yang_module_str) - try: - self.__init_sonic_yang() - except Exception: - os.remove(module_path) - raise - - def remove_module(self, module_name): - """ - Remove YANG module from the system and validate. - - Parameters: - module_name (str): YANG module name. - - Returns: - None - """ - - module_path = os.path.join(YANG_DIR, '{}.yang'.format(module_name)) - if not os.path.exists(module_path): - return - temp = tempfile.NamedTemporaryFile(delete=False) - try: - shutil.move(module_path, temp.name) - self.__init_sonic_yang() - except Exception: - shutil.move(temp.name, module_path) - raise - - @staticmethod - def get_module_name(yang_module_str): - """ - Read yangs module name from yang_module_str - - Parameters: - yang_module_str(str): YANG module string. - - Returns: - str: Module name - """ - - # Instantiate new context since parse_module_mem() loads the module into context. - sy = sonic_yang.SonicYang(YANG_DIR) - module = sy.ctx.parse_module_mem(yang_module_str, ly.LYS_IN_YANG) - return module.name() - - # End of Class ConfigMgmt class ConfigMgmtDPB(ConfigMgmt): @@ -489,8 +417,8 @@ def _deletePorts(self, ports=list(), force=False): deps.extend(dep) # No further action with no force and deps exist - if not force and deps: - return configToLoad, deps, False + if force == False and deps: + return configToLoad, deps, False; # delets all deps, No topological sort is needed as of now, if deletion # of deps fails, return immediately @@ -508,8 +436,8 @@ def _deletePorts(self, ports=list(), force=False): self.sy.deleteNode(str(xPathPort)) # Let`s Validate the tree now - if not self.validateConfigData(): - return configToLoad, deps, False + if self.validateConfigData()==False: + return configToLoad, deps, False; # All great if we are here, Lets get the diff self.configdbJsonOut = self.sy.getData() diff --git a/sonic_package_manager/main.py b/sonic_package_manager/main.py index 8a0aabb9016d..dfb88bd58d94 100644 --- a/sonic_package_manager/main.py +++ b/sonic_package_manager/main.py @@ -414,11 +414,10 @@ def reset(ctx, name, force, yes, skip_host_plugins): @cli.command() @add_options(PACKAGE_COMMON_OPERATION_OPTIONS) -@click.option('--keep-config', is_flag=True, help='Keep features configuration in CONFIG DB.') @click.argument('name') @click.pass_context @root_privileges_required -def uninstall(ctx, name, force, yes, keep_config): +def uninstall(ctx, name, force, yes): """ Uninstall package. """ manager: PackageManager = ctx.obj @@ -429,7 +428,6 @@ def uninstall(ctx, name, force, yes, keep_config): uninstall_opts = { 'force': force, - 'keep_config': keep_config, } try: diff --git a/sonic_package_manager/manager.py b/sonic_package_manager/manager.py index 7dc1ae773a20..f7bbd1afdd44 100644 --- a/sonic_package_manager/manager.py +++ b/sonic_package_manager/manager.py @@ -10,11 +10,8 @@ import docker import filelock -from config import config_mgmt from sonic_py_common import device_info -from sonic_cli_gen.generator import CliGenerator - from sonic_package_manager import utils from sonic_package_manager.constraint import ( VersionConstraint, @@ -48,10 +45,7 @@ run_command ) from sonic_package_manager.service_creator.feature import FeatureRegistry -from sonic_package_manager.service_creator.sonic_db import ( - INIT_CFG_JSON, - SonicDB -) +from sonic_package_manager.service_creator.sonic_db import SonicDB from sonic_package_manager.service_creator.utils import in_chroot from sonic_package_manager.source import ( PackageSource, @@ -441,16 +435,13 @@ def install_from_source(self, @under_lock @opt_check - def uninstall(self, name: str, - force: bool = False, - keep_config: bool = False): + def uninstall(self, name: str, force=False): """ Uninstall SONiC Package referenced by name. The uninstallation can be forced if force argument is True. Args: name: SONiC Package name. force: Force the installation. - keep_config: Keep feature configuration in databases. Raises: PackageManagerError """ @@ -491,7 +482,7 @@ def uninstall(self, name: str, self._systemctl_action(package, 'stop') self._systemctl_action(package, 'disable') self._uninstall_cli_plugins(package) - self.service_creator.remove(package, keep_config=keep_config) + self.service_creator.remove(package) self.service_creator.generate_shutdown_sequence_files( self._get_installed_packages_except(package) ) @@ -1009,13 +1000,9 @@ def get_manager() -> 'PackageManager': docker_api = DockerApi(docker.from_env(), ProgressManager()) registry_resolver = RegistryResolver() metadata_resolver = MetadataResolver(docker_api, registry_resolver) - cfg_mgmt = config_mgmt.ConfigMgmt(source=INIT_CFG_JSON) - cli_generator = CliGenerator(log) feature_registry = FeatureRegistry(SonicDB) service_creator = ServiceCreator(feature_registry, - SonicDB, - cli_generator, - cfg_mgmt) + SonicDB) return PackageManager(docker_api, registry_resolver, diff --git a/sonic_package_manager/manifest.py b/sonic_package_manager/manifest.py index 2d9f3514e784..e127fbb5384b 100644 --- a/sonic_package_manager/manifest.py +++ b/sonic_package_manager/manifest.py @@ -205,9 +205,7 @@ def unmarshal(self, value): ManifestField('mandatory', DefaultMarshaller(bool), False), ManifestField('show', DefaultMarshaller(str), ''), ManifestField('config', DefaultMarshaller(str), ''), - ManifestField('clear', DefaultMarshaller(str), ''), - ManifestField('auto-generate-show', DefaultMarshaller(bool), False), - ManifestField('auto-generate-config', DefaultMarshaller(bool), False), + ManifestField('clear', DefaultMarshaller(str), '') ]) ]) diff --git a/sonic_package_manager/metadata.py b/sonic_package_manager/metadata.py index 9cfa25e94ea3..1fc2cf3975eb 100644 --- a/sonic_package_manager/metadata.py +++ b/sonic_package_manager/metadata.py @@ -4,7 +4,7 @@ import json import tarfile -from typing import Dict, Optional +from typing import Dict from sonic_package_manager import utils from sonic_package_manager.errors import MetadataError @@ -54,7 +54,6 @@ class Metadata: manifest: Manifest components: Dict[str, Version] = field(default_factory=dict) - yang_module_str: Optional[str] = None class MetadataResolver: @@ -164,6 +163,5 @@ def from_labels(cls, labels: Dict[str, str]) -> Metadata: except ValueError as err: raise MetadataError(f'Failed to parse component version: {err}') - yang_module_str = sonic_metadata.get('yang-module') + return Metadata(Manifest.marshal(manifest_dict), components) - return Metadata(Manifest.marshal(manifest_dict), components, yang_module_str) diff --git a/sonic_package_manager/service_creator/creator.py b/sonic_package_manager/service_creator/creator.py index bdc0b434b909..6839ffa453f1 100644 --- a/sonic_package_manager/service_creator/creator.py +++ b/sonic_package_manager/service_creator/creator.py @@ -8,24 +8,17 @@ from typing import Dict, Type import jinja2 as jinja2 -from config.config_mgmt import ConfigMgmt from prettyprinter import pformat from toposort import toposort_flatten, CircularDependencyError -from config.config_mgmt import sonic_cfggen -from sonic_cli_gen.generator import CliGenerator from sonic_package_manager import utils from sonic_package_manager.logger import log from sonic_package_manager.package import Package -from sonic_package_manager.service_creator import ( - ETC_SONIC_PATH, - SONIC_CLI_COMMANDS, -) +from sonic_package_manager.service_creator import ETC_SONIC_PATH from sonic_package_manager.service_creator.feature import FeatureRegistry from sonic_package_manager.service_creator.sonic_db import SonicDB from sonic_package_manager.service_creator.utils import in_chroot - SERVICE_FILE_TEMPLATE = 'sonic.service.j2' TIMER_UNIT_TEMPLATE = 'timer.unit.j2' @@ -123,22 +116,16 @@ class ServiceCreator: def __init__(self, feature_registry: FeatureRegistry, - sonic_db: Type[SonicDB], - cli_gen: CliGenerator, - cfg_mgmt: ConfigMgmt): + sonic_db: Type[SonicDB]): """ Initialize ServiceCreator with: Args: feature_registry: FeatureRegistry object. sonic_db: SonicDB interface. - cli_gen: CliGenerator instance. - cfg_mgmt: ConfigMgmt instance. """ self.feature_registry = feature_registry self.sonic_db = sonic_db - self.cli_gen = cli_gen - self.cfg_mgmt = cfg_mgmt def create(self, package: Package, @@ -164,27 +151,25 @@ def create(self, self.generate_systemd_service(package) self.generate_dump_script(package) self.generate_service_reconciliation_file(package) - self.install_yang_module(package) + self.set_initial_config(package) - self.install_autogen_cli_all(package) self._post_operation_hook() if register_feature: - self.feature_registry.register(package.manifest, state, owner) + self.feature_registry.register(package.manifest, + state, owner) except (Exception, KeyboardInterrupt): - self.remove(package, deregister_feature=register_feature) + self.remove(package, register_feature) raise def remove(self, package: Package, - deregister_feature: bool = True, - keep_config: bool = False): + deregister_feature: bool = True): """ Uninstall SONiC service provided by the package. Args: package: Package object to uninstall. deregister_feature: Wether to deregister this package from FEATURE table. - keep_config: Whether to remove package configuration. Returns: None @@ -198,16 +183,11 @@ def remove(self, remove_if_exists(os.path.join(DEBUG_DUMP_SCRIPT_LOCATION, f'{name}')) remove_if_exists(os.path.join(ETC_SONIC_PATH, f'{name}_reconcile')) self.update_dependent_list_file(package, remove=True) - - if deregister_feature and not keep_config: - self.remove_config(package) - - self.uninstall_autogen_cli_all(package) - self.uninstall_yang_module(package) self._post_operation_hook() if deregister_feature: self.feature_registry.deregister(package.manifest['service']['name']) + self.remove_config(package) def generate_container_mgmt(self, package: Package): """ Generates container management script under /usr/bin/.sh for package. @@ -328,6 +308,7 @@ def update_dependent_list_file(self, package: Package, remove=False): remove: True if update for removal process. Returns: None. + """ name = package.manifest['service']['name'] @@ -495,11 +476,13 @@ def set_initial_config(self, package): cfg = conn.get_config() new_cfg = init_cfg.copy() utils.deep_update(new_cfg, cfg) - self.validate_config(new_cfg) conn.mod_config(new_cfg) def remove_config(self, package): - """ Remove configuration based on package YANG module. + """ Remove configuration based on init-cfg tables, so having + init-cfg even with tables without keys might be a good idea. + TODO: init-cfg should be validated with yang model + TODO: remove config from tables known to yang model Args: package: Package object remove initial configuration for. @@ -507,131 +490,14 @@ def remove_config(self, package): None """ - if not package.metadata.yang_module_str: - return - - module_name = self.cfg_mgmt.get_module_name(package.metadata.yang_module_str) - for tablename, module in self.cfg_mgmt.sy.confDbYangMap.items(): - if module.get('module') != module_name: - continue - - for conn in self.sonic_db.get_connectors(): - keys = conn.get_table(tablename).keys() - for key in keys: - conn.set_entry(tablename, key, None) - - def validate_config(self, config): - """ Validate configuration through YANG. - - Args: - config: Config DB data. - Returns: - None. - Raises: - Exception: if config does not pass YANG validation. - """ - - config = sonic_cfggen.FormatConverter.to_serialized(config) - log.debug(f'validating configuration {pformat(config)}') - # This will raise exception if configuration is not valid. - # NOTE: loadData() modifies the state of ConfigMgmt instance. - # This is not desired for configuration validation only purpose. - # Although the config loaded into ConfigMgmt instance is not - # interesting in this application so we don't care. - self.cfg_mgmt.loadData(config) - - def install_yang_module(self, package: Package): - """ Install package's yang module in the system. - - Args: - package: Package object. - Returns: - None - """ - - if not package.metadata.yang_module_str: - return - - self.cfg_mgmt.add_module(package.metadata.yang_module_str) - - def uninstall_yang_module(self, package: Package): - """ Uninstall package's yang module in the system. - - Args: - package: Package object. - Returns: - None - """ - - if not package.metadata.yang_module_str: - return - - module_name = self.cfg_mgmt.get_module_name(package.metadata.yang_module_str) - self.cfg_mgmt.remove_module(module_name) - - def install_autogen_cli_all(self, package: Package): - """ Install autogenerated CLI plugins for package. - - Args: - package: Package - Returns: - None - """ - - for command in SONIC_CLI_COMMANDS: - self.install_autogen_cli(package, command) - - def uninstall_autogen_cli_all(self, package: Package): - """ Remove autogenerated CLI plugins for package. - - Args: - package: Package - Returns: - None - """ - - for command in SONIC_CLI_COMMANDS: - self.uninstall_autogen_cli(package, command) - - def install_autogen_cli(self, package: Package, command: str): - """ Install autogenerated CLI plugins for package for particular command. - - Args: - package: Package. - command: Name of command to generate CLI for. - Returns: - None - """ - - if package.metadata.yang_module_str is None: - return - if f'auto-generate-{command}' not in package.manifest['cli']: - return - if not package.manifest['cli'][f'auto-generate-{command}']: + init_cfg = package.manifest['package']['init-cfg'] + if not init_cfg: return - module_name = self.cfg_mgmt.get_module_name(package.metadata.yang_module_str) - self.cli_gen.generate_cli_plugin(command, module_name) - log.debug(f'{command} command line interface autogenerated for {module_name}') - def uninstall_autogen_cli(self, package: Package, command: str): - """ Uninstall autogenerated CLI plugins for package for particular command. - - Args: - package: Package. - command: Name of command to remove CLI. - Returns: - None - """ - - if package.metadata.yang_module_str is None: - return - if f'auto-generate-{command}' not in package.manifest['cli']: - return - if not package.manifest['cli'][f'auto-generate-{command}']: - return - module_name = self.cfg_mgmt.get_module_name(package.metadata.yang_module_str) - self.cli_gen.remove_cli_plugin(command, module_name) - log.debug(f'{command} command line interface removed for {module_name}') + for conn in self.sonic_db.get_connectors(): + for table in init_cfg: + for key in init_cfg[table]: + conn.set_entry(table, key, None) def _post_operation_hook(self): """ Common operations executed after service is created/removed. """ diff --git a/sonic_package_manager/service_creator/feature.py b/sonic_package_manager/service_creator/feature.py index eb8e1a0710e0..97960a327d66 100644 --- a/sonic_package_manager/service_creator/feature.py +++ b/sonic_package_manager/service_creator/feature.py @@ -144,3 +144,15 @@ def get_non_configurable_feature_entries(manifest) -> Dict[str, str]: 'has_global_scope': str(manifest['service']['host-service']), 'has_timer': str(manifest['service']['delayed']), } + + def _get_tables(self): + tables = [] + running = self._sonic_db.running_table(FEATURE) + if running is not None: # it's Ok if there is no database container running + tables.append(running) + persistent = self._sonic_db.persistent_table(FEATURE) + if persistent is not None: # it's Ok if there is no config_db.json + tables.append(persistent) + tables.append(self._sonic_db.initial_table(FEATURE)) # init_cfg.json is must + + return tables diff --git a/tests/sonic_package_manager/conftest.py b/tests/sonic_package_manager/conftest.py index 1ec067657c99..2788a75cd3f2 100644 --- a/tests/sonic_package_manager/conftest.py +++ b/tests/sonic_package_manager/conftest.py @@ -7,8 +7,6 @@ import pytest from docker_image.reference import Reference -from config.config_mgmt import ConfigMgmt - from sonic_package_manager.database import PackageDatabase, PackageEntry from sonic_package_manager.manager import DockerApi, PackageManager from sonic_package_manager.manifest import Manifest @@ -64,17 +62,7 @@ def mock_service_creator(): @pytest.fixture def mock_sonic_db(): - yield MagicMock() - - -@pytest.fixture -def mock_config_mgmt(): - yield MagicMock() - - -@pytest.fixture -def mock_cli_gen(): - yield MagicMock() + yield Mock() @pytest.fixture @@ -119,7 +107,7 @@ def __init__(self): 'before': ['swss'], } ) - self.add('Azure/docker-test', '1.6.0', 'test-package', '1.6.0', yang='TEST') + self.add('Azure/docker-test', '1.6.0', 'test-package', '1.6.0') self.add('Azure/docker-test-2', '1.5.0', 'test-package-2', '1.5.0') self.add('Azure/docker-test-2', '2.0.0', 'test-package-2', '2.0.0') self.add('Azure/docker-test-3', 'latest', 'test-package-3', '1.6.0') @@ -136,26 +124,23 @@ def __init__(self): def from_registry(self, repository: str, reference: str): manifest = Manifest.marshal(self.metadata_store[repository][reference]['manifest']) components = self.metadata_store[repository][reference]['components'] - yang = self.metadata_store[repository][reference]['yang'] - return Metadata(manifest, components, yang) + return Metadata(manifest, components) def from_local(self, image: str): ref = Reference.parse(image) manifest = Manifest.marshal(self.metadata_store[ref['name']][ref['tag']]['manifest']) components = self.metadata_store[ref['name']][ref['tag']]['components'] - yang = self.metadata_store[ref['name']][ref['tag']]['yang'] - return Metadata(manifest, components, yang) + return Metadata(manifest, components) def from_tarball(self, filepath: str) -> Manifest: path, ref = filepath.split(':') manifest = Manifest.marshal(self.metadata_store[path][ref]['manifest']) components = self.metadata_store[path][ref]['components'] - yang = self.metadata_store[path][ref]['yang'] - return Metadata(manifest, components, yang) + return Metadata(manifest, components) def add(self, repo, reference, name, version, components=None, warm_shutdown=None, fast_shutdown=None, - processes=None, yang=None): + processes=None): repo_dict = self.metadata_store.setdefault(repo, {}) repo_dict[reference] = { 'manifest': { @@ -172,7 +157,6 @@ def add(self, repo, reference, name, version, components=None, 'processes': processes or [], }, 'components': components or {}, - 'yang': yang, } yield FakeMetadataResolver() @@ -268,7 +252,7 @@ def fake_db(fake_metadata_resolver): description='SONiC Package Manager Test Package', default_reference='1.6.0', installed=False, - built_in=False, + built_in=False ) add_package( content, @@ -418,8 +402,8 @@ def sonic_fs(fs): @pytest.fixture(autouse=True) def patch_pkgutil(): - with mock.patch('pkgutil.get_loader') as loader: - yield loader + with mock.patch('pkgutil.get_loader'): + yield @pytest.fixture diff --git a/tests/sonic_package_manager/test_service_creator.py b/tests/sonic_package_manager/test_service_creator.py index 9f496783a936..3e1a32b4d1af 100644 --- a/tests/sonic_package_manager/test_service_creator.py +++ b/tests/sonic_package_manager/test_service_creator.py @@ -60,25 +60,13 @@ def manifest(): }) -@pytest.fixture() -def service_creator(mock_feature_registry, - mock_sonic_db, - mock_cli_gen, - mock_config_mgmt): - yield ServiceCreator( - mock_feature_registry, - mock_sonic_db, - mock_cli_gen, - mock_config_mgmt - ) - - -def test_service_creator(sonic_fs, manifest, service_creator, package_manager): +def test_service_creator(sonic_fs, manifest, package_manager, mock_feature_registry, mock_sonic_db): + creator = ServiceCreator(mock_feature_registry, mock_sonic_db) entry = PackageEntry('test', 'azure/sonic-test') package = Package(entry, Metadata(manifest)) installed_packages = package_manager._get_installed_packages_and(package) - service_creator.create(package) - service_creator.generate_shutdown_sequence_files(installed_packages) + creator.create(package) + creator.generate_shutdown_sequence_files(installed_packages) assert sonic_fs.exists(os.path.join(ETC_SONIC_PATH, 'swss_dependent')) assert sonic_fs.exists(os.path.join(DOCKER_CTL_SCRIPT_LOCATION, 'test.sh')) @@ -94,116 +82,73 @@ def read_file(name): assert read_file('test_reconcile') == 'test-process test-process-3' -def test_service_creator_with_timer_unit(sonic_fs, manifest, service_creator): +def test_service_creator_with_timer_unit(sonic_fs, manifest, mock_feature_registry, mock_sonic_db): + creator = ServiceCreator(mock_feature_registry, mock_sonic_db) entry = PackageEntry('test', 'azure/sonic-test') package = Package(entry, Metadata(manifest)) - service_creator.create(package) + creator.create(package) assert not sonic_fs.exists(os.path.join(SYSTEMD_LOCATION, 'test.timer')) manifest['service']['delayed'] = True package = Package(entry, Metadata(manifest)) - service_creator.create(package) + creator.create(package) assert sonic_fs.exists(os.path.join(SYSTEMD_LOCATION, 'test.timer')) -def test_service_creator_with_debug_dump(sonic_fs, manifest, service_creator): +def test_service_creator_with_debug_dump(sonic_fs, manifest, mock_feature_registry, mock_sonic_db): + creator = ServiceCreator(mock_feature_registry, mock_sonic_db) entry = PackageEntry('test', 'azure/sonic-test') package = Package(entry, Metadata(manifest)) - service_creator.create(package) + creator.create(package) assert not sonic_fs.exists(os.path.join(DEBUG_DUMP_SCRIPT_LOCATION, 'test')) manifest['package']['debug-dump'] = '/some/command' package = Package(entry, Metadata(manifest)) - service_creator.create(package) + creator.create(package) assert sonic_fs.exists(os.path.join(DEBUG_DUMP_SCRIPT_LOCATION, 'test')) -def test_service_creator_yang(sonic_fs, manifest, mock_sonic_db, - mock_config_mgmt, service_creator): - test_yang = 'TEST YANG' - test_yang_module = 'sonic-test' - +def test_service_creator_initial_config(sonic_fs, manifest, mock_feature_registry, mock_sonic_db): mock_connector = Mock() + mock_connector.get_config = Mock(return_value={}) mock_sonic_db.get_connectors = Mock(return_value=[mock_connector]) - mock_connector.get_table = Mock(return_value={'key_a': {'field_1': 'value_1'}}) - mock_connector.get_config = Mock(return_value={ - 'TABLE_A': mock_connector.get_table('') - }) + + creator = ServiceCreator(mock_feature_registry, mock_sonic_db) entry = PackageEntry('test', 'azure/sonic-test') - package = Package(entry, Metadata(manifest, yang_module_str=test_yang)) - service_creator.create(package) + package = Package(entry, Metadata(manifest)) + creator.create(package) - mock_config_mgmt.add_module.assert_called_with(test_yang) - mock_config_mgmt.get_module_name = Mock(return_value=test_yang_module) + assert not sonic_fs.exists(os.path.join(DEBUG_DUMP_SCRIPT_LOCATION, 'test')) manifest['package']['init-cfg'] = { 'TABLE_A': { 'key_a': { - 'field_1': 'new_value_1', + 'field_1': 'value_1', 'field_2': 'value_2' }, }, } - package = Package(entry, Metadata(manifest, yang_module_str=test_yang)) - - service_creator.create(package) - - mock_config_mgmt.add_module.assert_called_with(test_yang) + package = Package(entry, Metadata(manifest)) + creator.create(package) mock_connector.mod_config.assert_called_with( { 'TABLE_A': { - 'key_a': { - 'field_1': 'value_1', - 'field_2': 'value_2', - }, - }, - } + 'key_a': { + 'field_1': 'value_1', + 'field_2': 'value_2', + }, + }, + } ) - mock_config_mgmt.sy.confDbYangMap = { - 'TABLE_A': {'module': test_yang_module} - } - - service_creator.remove(package) + creator.remove(package) mock_connector.set_entry.assert_called_with('TABLE_A', 'key_a', None) - mock_config_mgmt.remove_module.assert_called_with(test_yang_module) - - -def test_service_creator_autocli(sonic_fs, manifest, mock_cli_gen, - mock_config_mgmt, service_creator): - test_yang = 'TEST YANG' - test_yang_module = 'sonic-test' - - manifest['cli']['auto-generate-show'] = True - manifest['cli']['auto-generate-config'] = True - - entry = PackageEntry('test', 'azure/sonic-test') - package = Package(entry, Metadata(manifest, yang_module_str=test_yang)) - mock_config_mgmt.get_module_name = Mock(return_value=test_yang_module) - service_creator.create(package) - - mock_cli_gen.generate_cli_plugin.assert_has_calls( - [ - call('show', test_yang_module), - call('config', test_yang_module), - ], - any_order=True - ) - - service_creator.remove(package) - mock_cli_gen.remove_cli_plugin.assert_has_calls( - [ - call('show', test_yang_module), - call('config', test_yang_module), - ], - any_order=True - ) def test_feature_registration(mock_sonic_db, manifest):