Example #1
0
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)
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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"))
Example #10
0
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
Example #11
0
    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))
Example #12
0
    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)
Example #13
0
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"
Example #14
0
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
Example #15
0
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
Example #16
0
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"]
Example #17
0
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"
Example #18
0
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
Example #19
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")
Example #20
0
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
Example #21
0
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"
Example #22
0
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()
Example #23
0
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
Example #24
0
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"
Example #25
0
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
Example #26
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()
Example #27
0
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"
Example #28
0
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)