def test_config_inventory_pass(request, monkeypatch, netcfgbu_envars): """ Test the case where an [[inventory]] section is properly configured. """ files_dir = request.fspath.dirname + "/files" monkeypatch.setenv("SCRIPT_DIR", files_dir) fileio = open(f"{files_dir}/test-inventory.toml") load(fileio=fileio)
def test_config_fail_asfilepath(tmpdir): """ Test use-case where the config is provided as a filepath, and the filep does not exist. """ noexist_filepath = str(tmpdir.join("noexist")) with pytest.raises(FileNotFoundError) as excinfo: load(filepath=noexist_filepath) assert excinfo.value.filename == noexist_filepath
def test_config_git_fail_badrepo(request, netcfgbu_envars, monkeypatch): """ Test the case where a [[git]] section has an improper GIT URL. """ fileio = open(f"{request.fspath.dirname}/files/test-gitspec-badrepo.toml") with pytest.raises(RuntimeError) as excinfo: load(fileio=fileio) exc_errmsgs = excinfo.value.args[0].splitlines() found = first([line for line in exc_errmsgs if "git.0.repo" in line]) assert found assert "Bad repo URL" in found
def test_config_linter_fail(netcfgbu_envars, request): """ Test the case where an [os_name] section defines a linter, but that linter is not defined in the configuration. """ fileio = open(f"{request.fspath.dirname}/files/test-linter-fail.toml") with pytest.raises(RuntimeError) as excinfo: load(fileio=fileio) exc_errmsgs = excinfo.value.args[0].splitlines() found = first([line for line in exc_errmsgs if "os_name" in line]) assert 'OS spec "ios" using undefined linter "ios"' in found
def test_config_inventory_fail_noscript(request, netcfgbu_envars): """ Test the case where an [[inventory]] section defined a script, but the script does not actually exist. """ fileio = open(f"{request.fspath.dirname}/files/test-inventory-fail.toml") with pytest.raises(RuntimeError) as excinfo: load(fileio=fileio) exc_errmsgs = excinfo.value.args[0].splitlines() found = first( [line for line in exc_errmsgs if "inventory.0.script" in line]) assert found assert "File not found:" in found
def test_inventory_fail_build_noscript(request, netcfgbu_envars): """ Test the use-case where the configuraiton contains an inventory build script. The script exists, it runs without error. """ config_fpath = f"{request.fspath.dirname}/files/test-inventory-noscript.toml" with pytest.raises(RuntimeError) as excinfo: config.load(filepath=config_fpath) exc_errmsgs = excinfo.value.args[0].splitlines() found = first( [line for line in exc_errmsgs if "inventory.0.script" in line]) assert found assert "field required" in found
def test_config_onlyenvars_fail_missing(): """ Execute a test where there is no configuration file. Omit the default environment variables and ensure that an exception is raised as expected. """ with pytest.raises(RuntimeError) as excinfo: load() exc_errmsg = excinfo.value.args[0] assert "defaults.inventory" in exc_errmsg assert "defaults.credentials.username" in exc_errmsg assert "defaults.credentials.password" in exc_errmsg
def test_config_onlyenvars_fail_bad_noinventory(monkeypatch): """ Test the case where NETCFGBU_INVENTORY is set but empty, but the file does not exist; which would generate an exception message. """ monkeypatch.setenv("NETCFGBU_INVENTORY", "") with pytest.raises(RuntimeError) as excinfo: load() exc_errmsgs = excinfo.value.args[0].splitlines() found = first( [line for line in exc_errmsgs if "defaults.inventory" in line]) assert found assert "inventory empty value not allowed" in found
def test_config_os_name_prompt_pattern(netcfgbu_envars, request): # noqa """ This test validates that a User provided prompt_pattern in the [os_name.$name] configuration section results in the User defined pattern used by the SSH connector instance. """ rec = {"host": "dummy", "os_name": "cumulus"} abs_filepath = (request.fspath.dirname + "/files/test-config-os-name-prompt-pattern.toml") app_cfg = load(filepath=abs_filepath) conn = os_specs.make_host_connector(rec, app_cfg) # this value is copied from the configuration toml file. If you # change the test data file then you'd have to change this expected pattern. expected_pattern = r"[a-z0-9.\-@:~]{10,65}\s*[#$]" # the conenctor code adds a capture group for processing reasons. expected_pattern = r"^\r?(" + expected_pattern + r")\s*$" expected_re = re.compile(expected_pattern.encode("utf-8")) # going to perform a PROMPT pattern match against a sample value. test_prompt_value = "cumulus@leaf01:mgmt-vrf:~$" assert isinstance(conn, BasicSSHConnector) assert expected_re.pattern == conn.PROMPT_PATTERN.pattern assert expected_re.match(test_prompt_value.encode("utf-8"))
def test_config_credentials_fail_missingvar(request, monkeypatch, fake_inventory_file): """ Test the case where the [[credentials]] section is provided that uses an environment variable, and that environment variable is missing. """ fileio = open(f"{request.fspath.dirname}/files/test-credentials.toml") with pytest.raises(RuntimeError) as excinfo: load(fileio=fileio) exc_errmsgs = excinfo.value.args[0].splitlines() found = first( [line for line in exc_errmsgs if "credentials.0.password" in line]) assert found assert 'Environment variable "ENABLE_PASSWORD" missing' in found
def invoke(self, ctx): try: ctx.obj["app_cfg"] = _config.load(fileio=ctx.params["config"]) super().invoke(ctx) except Exception as exc: ctx.fail(str(exc))
def invoke(self, ctx): try: app_cfg = ctx.obj["app_cfg"] = _config.load(fileio=ctx.params["config"]) if debug_ssh_lvl := ctx.params.get("debug_ssh"): # pragma: no cover from asyncssh import logging as assh_lgr import logging assh_lgr.set_log_level(logging.DEBUG) assh_lgr.set_debug_level(debug_ssh_lvl) if ctx.params["inventory"]: ctx.obj["app_cfg"].defaults.inventory = ctx.params["inventory"] inv = ctx.obj["inventory_recs"] = _inventory.load( app_cfg=app_cfg, limits=ctx.params["limit"], excludes=ctx.params["exclude"], ) if not inv: raise RuntimeError( f"No inventory matching limits in: {app_cfg.defaults.inventory}" ) # if there is jump host configuraiton then prepare for later use. if app_cfg.jumphost: jumphosts.init_jumphosts(jumphost_specs=app_cfg.jumphost, inventory=inv) super().invoke(ctx)
def test_os_name_pass_namefound(netcfgbu_envars, request): filepath = str(request.fspath.dirname + "/files/test-config-os_name.toml") app_cfg = config.load(filepath=filepath) rec = {"host": "dummy", "os_name": "ios"} conn = os_specs.make_host_connector(rec, app_cfg) assert conn.os_spec.get_config == "fake show running-config"
def test_config_jumphost_name(netcfgbu_envars, request): abs_filepath = request.fspath.dirname + "/files/test-config-jumphosts.toml" app_cfg = load(filepath=abs_filepath) jh = app_cfg.jumphost[0] assert jh.name == jh.proxy jh = app_cfg.jumphost[1] assert jh.name != jh.proxy
def test_config_credentials_fail_empytvar(request, monkeypatch, netcfgbu_envars): """ Test the case where the [[credentials]] section is provided that uses an environment variable, and that environment variable exists, but it the empty-string. """ fileio = open(f"{request.fspath.dirname}/files/test-credentials.toml") monkeypatch.setenv("ENABLE_PASSWORD", "") with pytest.raises(RuntimeError) as excinfo: load(fileio=fileio) exc_errmsgs = excinfo.value.args[0].splitlines() found = first( [line for line in exc_errmsgs if "credentials.0.password" in line]) assert found assert 'Environment variable "ENABLE_PASSWORD" empty' in found
def test_config_linter_pass(netcfgbu_envars, request): """ Test the case where an [os_name] section defines a linter, and that linter exists; no errors expected. """ fileio = open(f"{request.fspath.dirname}/files/test-linter.toml") app_cfg = load(fileio=fileio) assert app_cfg.os_name["ios"] assert app_cfg.os_name["ios"].linter == "ios" assert app_cfg.linters["ios"]
def test_os_name_pass(netcfgbu_envars): rec = {"host": "dummy", "os_name": "dummy"} app_cfg = config.load() conn = os_specs.make_host_connector(rec, app_cfg) assert isinstance(conn, BasicSSHConnector) assert conn.name == "dummy" creds_d = conn.creds[0] assert creds_d.username == "dummy-username" assert creds_d.password.get_secret_value() == "dummy-password"
def test_inventory_pass_build(request, monkeypatch, netcfgbu_envars): """ Test the use-case where the configuraiton contains an inventory build script. The script exists, it runs without error. """ files_dir = request.fspath.dirname + "/files" monkeypatch.setenv("SCRIPT_DIR", files_dir) config_fpath = files_dir + "/test-inventory-script-donothing.toml" app_cfg = config.load(filepath=config_fpath) inv_def = app_cfg.inventory[0] rc = inventory.build(inv_def) assert rc == 0
def test_config_onlyenvars_pass(monkeypatch, netcfgbu_envars): """ Execute a test where there is no configuration file. In this case the NETCFGBU_<fieldname> environment variables must exist. """ app_cfg = load() assert app_cfg.defaults.inventory == getenv("NETCFGBU_INVENTORY") assert app_cfg.defaults.credentials.username == getenv( "NETCFGBU_DEFAULT_USERNAME") assert app_cfg.defaults.credentials.password.get_secret_value() == getenv( "NETCFGBU_DEFAULT_PASSWORD")
def test_inventory_fail_nofilegiven(tmpdir, netcfgbu_envars): """ Test the use-case where the inventory is given in configuration file, but the inventory file does not actually exist. """ app_cfg = config.load() with pytest.raises(FileNotFoundError) as excinfo: inventory.load(app_cfg) errmsg = excinfo.value.args[0] assert "Inventory file does not exist" in errmsg
def test_config_credentials_pass_usesvar(request, monkeypatch, netcfgbu_envars): """ Test the case where the [[credentials]] section is provided that uses an environment variable, and that environment variable exists, and it is set to a non-empty value. """ fileio = open(f"{request.fspath.dirname}/files/test-credentials.toml") monkeypatch.setenv("ENABLE_PASSWORD", "foobaz") app_cfg = load(fileio=fileio) assert app_cfg.credentials[0].password.get_secret_value() == "foobaz"
def test_config_pass_noexistdir(tmpdir, netcfgbu_envars, monkeypatch): """ Test use-case where the provided configs-dir directory does not exist in the configuration; but as a result the configs-dir is created. """ dirpath = tmpdir.join("dummy-dir") monkeypatch.setenv("NETCFGBU_CONFIGSDIR", str(dirpath)) app_cfg = load() configs_dir: Path = app_cfg.defaults.configs_dir assert configs_dir == dirpath assert configs_dir.exists()
def test_config_inventory_fail_script_noexec(netcfgbu_envars, tmpdir): """ Test the case where an [[inventory]] section defines a script, the script file exists, but the script file is not executable. """ fake_script = tmpdir.join("dummy-script.sh") fake_script.ensure() config_data = {"inventory": [{"name": "foo", "script": str(fake_script)}]} strio = StringIO() strio.name = "fake-file" toml.dump(config_data, strio) strio.seek(0) with pytest.raises(RuntimeError) as excinfo: load(fileio=strio) exc_errmsgs = excinfo.value.args[0].splitlines() found = first( [line for line in exc_errmsgs if "inventory.0.script" in line]) assert found assert "is not executable" in found
def test_config_git_pass(request, netcfgbu_envars, monkeypatch): """ Test the case where a [[git]] section is properly configured. """ files_dir = Path(request.fspath.dirname).joinpath("files") monkeypatch.setenv("GIT_TOKEN", "fake-token") monkeypatch.setenv("GITKEY_PASSWORD", "fake-password") monkeypatch.setenv("GITKEY_DIR", str(files_dir.absolute())) fileio = files_dir.joinpath("test-gitspec.toml").open() app_cfg = load(fileio=fileio) assert app_cfg.git[0].token.get_secret_value() == "fake-token" assert app_cfg.git[2].deploy_passphrase.get_secret_value( ) == "fake-password"
def test_inventory_fail_build_exitnozero(request, monkeypatch, netcfgbu_envars): """ Test the use-case where the configuraiton contains an inventory build script. The script exists, it runs but exists with non-zero return code. """ files_dir = request.fspath.dirname + "/files" monkeypatch.setenv("SCRIPT_DIR", files_dir) config_fpath = files_dir + "/test-inventory-script-fails.toml" app_cfg = config.load(filepath=config_fpath) inv_def = app_cfg.inventory[0] rc = inventory.build(inv_def) assert rc != 0
def invoke(self, ctx): cfg_fileopt = ctx.params["config"] try: app_cfgs = ctx.obj["app_cfg"] = _config.load(fileio=cfg_fileopt) if not (spec := get_spec_nameorfirst(app_cfgs.git, ctx.params["name"])): err_msg = ( "No configuration file provided, required for vcs support" if not cfg_fileopt else f"No vcs config section found in configuration file: {cfg_fileopt.name}" ) raise RuntimeError(err_msg) ctx.obj["vcs_spec"] = spec super().invoke(ctx) stop_aiologging()
def test_inventory_pass(request, monkeypatch, netcfgbu_envars): """ Test the use-case where there is a small inventory file that is properlly formatted. Load the entire inventory as one subtest. Load a filtered set of records as another subtest. """ inventory_fpath = f"{request.fspath.dirname}/files/test-small-inventory.csv" monkeypatch.setenv("NETCFGBU_INVENTORY", inventory_fpath) app_cfg = config.load() # all records inv_recs = inventory.load(app_cfg) assert len(inv_recs) == 6 # filter records inv_recs = inventory.load(app_cfg, limits=["os_name=eos"], excludes=["host=switch1"]) assert len(inv_recs) == 1 assert inv_recs[0]["host"] == "switch2"
def test_config_pass_asfilepath(request): """ Test use-case where the config is provided as a filepath, and the file exists. """ abs_filepath = f"{request.fspath.dirname}/files/test-just-defaults.toml" load(filepath=abs_filepath)