예제 #1
0
def test_convergence_parametrization(client_library_server_current,
                                     mocked_session):
    MAX_ITER = 2
    WAIT_TIME = 1
    cl = ClientLibrary(
        url="https://0.0.0.0/fake_url/",
        username="******",
        password="******",
        convergence_wait_max_iter=MAX_ITER,
        convergence_wait_time=WAIT_TIME,
    )
    # check that passing of value from client to lab is working
    lab = cl.create_lab()
    assert lab.wait_max_iterations == MAX_ITER
    assert lab.wait_time == WAIT_TIME
    with patch.object(Lab, "has_converged", return_value=False):
        with pytest.raises(RuntimeError) as err:
            lab.wait_until_lab_converged()
        assert ("has not converged, maximum tries %s exceeded" %
                MAX_ITER) in err.value.args[0]

        # try to override values on function
        with pytest.raises(RuntimeError) as err:
            lab.wait_until_lab_converged(max_iterations=1)
        assert ("has not converged, maximum tries %s exceeded" %
                1) in err.value.args[0]
def test_import_lab_from_path_ng(
    client_library_compatible_version, mocked_session, tmp_path: Path
):
    client_library = ClientLibrary(
        url="http://0.0.0.0/fake_url/", username="******", password="******"
    )
    Lab.sync = Mock()

    topology_data = '{"nodes": [], "links": [], "interfaces": []}'
    (tmp_path / "topology.ng").write_text(topology_data)
    with patch.object(Lab, "sync", autospec=True) as sync_mock:
        lab = client_library.import_lab_from_path(
            topology=(tmp_path / "topology.ng").as_posix()
        )

    assert lab.title is not None
    assert lab.lab_base_url.startswith("https://0.0.0.0/fake_url/api/v0/labs/")

    client_library.session.post.assert_called_once_with(
        "https://0.0.0.0/fake_url/api/v0/import?is_json=true&title=topology.ng",
        data=topology_data,
    )
    client_library.session.post.assert_called_once()
    client_library.session.post.return_value.raise_for_status.assert_called_once()
    sync_mock.assert_called_once_with()
예제 #3
0
def test_client_library_init_url(client_library_server_current, monkeypatch,
                                 via, params):
    (fail, url) = params
    expected_parts = None if fail else urlsplit(url)
    if via == "environment":
        env = url
        url = None
    else:
        env = "http://badhost" if url else None
    if env is None:
        monkeypatch.delenv("VIRL2_URL", raising=False)
    else:
        monkeypatch.setenv("VIRL2_URL", env)
    if fail:
        with pytest.raises(
            (InitializationError, requests.exceptions.InvalidURL)):
            ClientLibrary(url=url,
                          username="******",
                          password="******",
                          allow_http=True)
    else:
        cl = ClientLibrary(url,
                           username="******",
                           password="******",
                           allow_http=True)
        url_parts = urlsplit(cl._context.base_url)
        assert url_parts.scheme == (expected_parts.scheme or "https")
        assert url_parts.hostname == (expected_parts.hostname
                                      or expected_parts.path)
        assert url_parts.port == expected_parts.port
        assert url_parts.path == "/api/v0/"
        assert cl._context.base_url.endswith("/api/v0/")
        assert cl.username == "virl2"
        assert cl.password == "virl2"
def test_import_lab_offline(
    client_library_compatible_version, mocked_session, tmp_path: Path
):
    client_library = ClientLibrary(
        url="http://0.0.0.0/fake_url/", username="******", password="******"
    )
    topology_file_path = "import_export/SampleData/topology-v0_0_4.json"
    topology = pkg_resources.resource_string("simple_common", topology_file_path)
    client_library.import_lab(topology, "topology-v0_0_4", offline=True)
예제 #5
0
def test_import_lab_offline(client_library_server_2_0_0, mocked_session,
                            tmp_path: Path):
    client_library = ClientLibrary(url="http://0.0.0.0/fake_url/",
                                   username="******",
                                   password="******")
    topology_file_path = "tests/test_data/sample_topology.json"
    with open(topology_file_path) as fh:
        topology_file = fh.read()
        client_library.import_lab(topology_file,
                                  "topology-v0_0_4",
                                  offline=True)
def test_ssl_certificate_from_env_variable(
    client_library_compatible_version, monkeypatch, mocked_session
):
    monkeypatch.setitem(os.environ, "CA_BUNDLE", "/home/user/cert.pem")
    cl = ClientLibrary(url="http://0.0.0.0/fake_url/", username="******", password="******")

    assert cl.is_system_ready()
    assert cl.session.verify == "/home/user/cert.pem"
    assert cl.session.mock_calls[:4] == [
        call.get("https://0.0.0.0/fake_url/api/v0/authok"),
        call.get().raise_for_status(),
    ]
예제 #7
0
def test_ssl_certificate_from_env_variable(monkeypatch, mocked_session):
    monkeypatch.setitem(os.environ, "CA_BUNDLE", "/home/user/cert.pem")
    cl = ClientLibrary(url="http://0.0.0.0/fake_url/",
                       username="******",
                       password="******")
    cl.wait_for_lld_connected()

    assert cl.session.verify == "/home/user/cert.pem"
    assert cl.session.mock_calls == [
        call.get("https://0.0.0.0/fake_url/api/v0/labs"),
        call.get().raise_for_status(),
        call.get("https://0.0.0.0/fake_url/api/v0/wait_for_lld_connected"),
        call.get().raise_for_status()
    ]
예제 #8
0
def test_ssl_certificate(client_library_server_2_0_0, mocked_session):
    cl = ClientLibrary(
        url="http://0.0.0.0/fake_url/",
        username="******",
        password="******",
        ssl_verify="/home/user/cert.pem",
    )
    cl.is_system_ready(wait=True)

    assert cl.session.verify == "/home/user/cert.pem"
    assert cl.session.mock_calls[:4] == [
        call.get("https://0.0.0.0/fake_url/api/v0/authok"),
        call.get().raise_for_status(),
    ]
def test_client_library_str_and_repr(client_library_compatible_version):
    client_library = ClientLibrary("somehost", "virl2", password="******")
    assert (
        repr(client_library)
        == "ClientLibrary('somehost', 'virl2', 'virl2', True, False, False)"
    )
    assert str(client_library) == "ClientLibrary URL: https://somehost/api/v0/"
예제 #10
0
def test_ssl_certificate(mocked_session):
    cl = ClientLibrary(
        url="http://0.0.0.0/fake_url/",
        username="******",
        password="******",
        ssl_verify="/home/user/cert.pem",
    )
    cl.wait_for_lld_connected()

    assert cl.session.verify == "/home/user/cert.pem"
    assert cl.session.mock_calls == [
        call.get("https://0.0.0.0/fake_url/api/v0/labs"),
        call.get().raise_for_status(),
        call.get("https://0.0.0.0/fake_url/api/v0/wait_for_lld_connected"),
        call.get().raise_for_status()
    ]
예제 #11
0
def test_client_minor_version_lt_warn_1(client_library_server_2_19_0, caplog):
    with caplog.at_level(logging.WARNING):
        client_library = ClientLibrary("somehost", "virl2", password="******")
    assert client_library is not None
    assert (
        "Please ensure the client version is compatible with the controller version. "
        "Client {}, controller 2.19.0.".format(CURRENT_VERSION) in caplog.text)
예제 #12
0
def test_client_library_init_password(monkeypatch, via, parms):
    url = "validhostname"
    (fail, password) = parms
    if via == "environment":
        # can't set a None value for an environment variable
        monkeypatch.setenv("VIRL2_PASS", password or "")
        password = None
    if fail:
        with pytest.raises(
            (InitializationError, requests.exceptions.InvalidURL)):
            cl = ClientLibrary(url=url, username="******", password=password)
    else:
        cl = ClientLibrary(url, username="******", password=password)
        assert cl.username == "virl2"
        assert cl.password == parms[1]
        assert cl._context.base_url == "https://validhostname/api/v0/"
예제 #13
0
def test_major_version_mismatch(client_library_server_1_0_0):
    with pytest.raises(InitializationError) as err:
        ClientLibrary("somehost", "virl2", password="******")
    assert str(
        err.value
    ) == "Major version mismatch. Client {}, controller 1.0.0.".format(
        CURRENT_VERSION)
예제 #14
0
def test_exact_version_no_warn(client_library_server_current, caplog):
    with caplog.at_level(logging.WARNING):
        client_library = ClientLibrary("somehost", "virl2", password="******")
    assert client_library is not None
    assert (
        "Please ensure the client version is compatible with the controller version. "
        "Client {}, controller 2.0.0.".format(CURRENT_VERSION)
        not in caplog.text)
def test_exact_version_no_warn(client_library_exact_version, caplog):
    with caplog.at_level(logging.WARNING):
        client_library = ClientLibrary("somehost", "virl2", password="******")
    assert client_library is not None
    assert (
        "Please ensure the client version is compatible with the server version. client 2.1.0, server 2.0.0"
        not in caplog.text
    )
예제 #16
0
def test_client_library_init_url(monkeypatch, via, parms):
    (fail, url) = parms
    if via == "environment":
        monkeypatch.setenv("VIRL2_URL", url)
        url = None
    if fail:
        with pytest.raises(
            (InitializationError, requests.exceptions.InvalidURL)):
            cl = ClientLibrary(url=url, username="******", password="******")
    else:
        cl = ClientLibrary(url, username="******", password="******")
        url_parts = urlsplit(cl._context.base_url)
        assert url_parts.scheme == "https"
        assert url_parts.hostname == "somehost"
        assert url_parts.port == 443 or url_parts.port is None
        assert cl._context.base_url.endswith("/api/v0/")
        assert cl.username == "virl2"
        assert cl.password == "virl2"
예제 #17
0
def test_client_library_init_allow_http():
    cl = ClientLibrary("http://somehost", "virl2", "virl2", allow_http=True)
    url_parts = urlsplit(cl._context.base_url)
    assert url_parts.scheme == "http"
    assert url_parts.hostname == "somehost"
    assert url_parts.port is None
    assert cl._context.base_url.endswith("/api/v0/")
    assert cl.username == "virl2"
    assert cl.password == "virl2"
예제 #18
0
def test_incompatible_version(client_library_server_2_0_0):
    with pytest.raises(InitializationError) as err:
        with patch.object(ClientLibrary,
                          "INCOMPATIBLE_CONTROLLER_VERSIONS",
                          new=[Version("2.0.0")]):
            ClientLibrary("somehost", "virl2", password="******")
    assert (str(
        err.value) == "Controller version 2.0.0 is marked incompatible! "
            "List of versions marked explicitly as incompatible: [2.0.0].")
예제 #19
0
def test_import_lab_from_path_virl_title(client_library_server_current,
                                         mocked_session, tmp_path: Path):
    cl = ClientLibrary(url="https://0.0.0.0/fake_url/",
                       username="******",
                       password="******")
    Lab.sync = Mock()
    new_title = "new_title"
    (tmp_path /
     "topology.virl").write_text("<?xml version='1.0' encoding='UTF-8'?>")
    with patch.object(Lab, "sync", autospec=True) as sync_mock:
        lab = cl.import_lab_from_path(path=(tmp_path /
                                            "topology.virl").as_posix(),
                                      title=new_title)
    assert lab.title is not None
    assert lab.lab_base_url.startswith("https://0.0.0.0/fake_url/api/v0/labs/")

    cl.session.post.assert_called_once_with(
        f"https://0.0.0.0/fake_url/api/v0/import/virl-1x?title={new_title}",
        data="<?xml version='1.0' encoding='UTF-8'?>",
    )
def test_import_lab_from_path_virl(
    client_library_compatible_version, mocked_session, tmp_path: Path
):
    cl = ClientLibrary(url="http://0.0.0.0/fake_url/", username="******", password="******")
    Lab.sync = Mock()

    (tmp_path / "topology.virl").write_text("<?xml version='1.0' encoding='UTF-8'?>")
    with patch.object(Lab, "sync", autospec=True) as sync_mock:
        lab = cl.import_lab_from_path(topology=(tmp_path / "topology.virl").as_posix())

    assert lab.title is not None
    assert lab.lab_base_url.startswith("https://0.0.0.0/fake_url/api/v0/labs/")

    cl.session.post.assert_called_once_with(
        "https://0.0.0.0/fake_url/api/v0/import/virl-1x?title=topology.virl",
        data="<?xml version='1.0' encoding='UTF-8'?>",
    )
    cl.session.post.assert_called_once()
    cl.session.post.return_value.raise_for_status.assert_called_once()
    sync_mock.assert_called_once_with()
예제 #21
0
def test_auth_and_reauth_token():
    # TODO: need to check what the purpose of this test is, and how it works with the automatic auth check on CL init
    # if there's environ vars for username and password set
    # then delete them b/c we rely on specific usernames
    # and passwords for this test!
    try:
        del os.environ["SIMPLE_PASS"]
        del os.environ["SIMPLE_USER"]
    except:
        pass

    # mock always successful authentication:
    responses.add(responses.POST,
                  "https://0.0.0.0/fake_url/api/v0/authenticate",
                  json="7bbcan78a98bch7nh3cm7hao3nc7")
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/wait_for_lld_connected")
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/wait_for_lld_connected",
                  status=401)
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/wait_for_lld_connected")
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/wait_for_lld_connected",
                  status=401)

    with pytest.raises(InitializationError):
        # Test returns custom exception when instructed to raise onk
        cl = ClientLibrary(url="http://0.0.0.0/fake_url/",
                           username="******",
                           password="******",
                           raise_for_auth_failure=True)

    cl = ClientLibrary(url="http://0.0.0.0/fake_url/",
                       username="******",
                       password="******")
    cl.wait_for_lld_connected()

    # last request fails as after reauthentication status code of response is still 401:
    # with pytest.raises(requests.exceptions.HTTPError) as:
    #     client_library.wait_for_lld_connected()
    #     assert exc.value.response.status_code ==1

    assert (responses.calls[0].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert json.loads(responses.calls[0].request.body) == {
        "username": "******",
        "password": "******",
    }
    assert (responses.calls[1].request.url ==
            "https://0.0.0.0/fake_url/api/v0/labs")
    assert responses.calls[1].request.method == "GET"
    assert (responses.calls[2].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert (responses.calls[3].request.url ==
            "https://0.0.0.0/fake_url/api/v0/labs")
    assert (responses.calls[4].request.url ==
            "https://0.0.0.0/fake_url/api/v0/wait_for_lld_connected")
    assert len(responses.calls) == 5
예제 #22
0
def test_client_library_init_password(client_library_server_current,
                                      monkeypatch, via, params):
    url = "validhostname"
    (fail, password) = params
    if via == "environment":
        # can't set a None value for an environment variable
        env = password or ""
        password = None
    else:
        env = "badpass" if password else None
    if env is None:
        monkeypatch.delenv("VIRL2_PASS", raising=False)
    else:
        monkeypatch.setenv("VIRL2_PASS", env)
    if fail:
        with pytest.raises(
            (InitializationError, requests.exceptions.InvalidURL)):
            ClientLibrary(url=url, username="******", password=password)
    else:
        cl = ClientLibrary(url, username="******", password=password)
        assert cl.username == "virl2"
        assert cl.password == params[1]
        assert cl._context.base_url == "https://validhostname/api/v0/"
예제 #23
0
def test_auth_and_reauth_token(client_library_server_current):
    # mock failed authentication:
    responses.add(responses.POST,
                  "https://0.0.0.0/fake_url/api/v0/authenticate",
                  status=403)
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/authok",
                  status=401)

    # mock successful authentication:
    responses.add(
        responses.POST,
        "https://0.0.0.0/fake_url/api/v0/authenticate",
        json="7bbcan78a98bch7nh3cm7hao3nc7",
    )
    responses.add(responses.GET, "https://0.0.0.0/fake_url/api/v0/authok")

    # mock get labs
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/labs",
                  json=[])

    with pytest.raises(InitializationError):
        # Test returns custom exception when instructed to raise on failure
        ClientLibrary(
            url="https://0.0.0.0/fake_url/",
            username="******",
            password="******",
            raise_for_auth_failure=True,
        )

    cl = ClientLibrary(url="https://0.0.0.0/fake_url/",
                       username="******",
                       password="******")

    cl.all_labs()

    # for idx, item in enumerate(responses.calls):
    #     print(idx, item.request.url)
    #
    # this is what we expect:
    # 0 https://0.0.0.0/fake_url/api/v0/authenticate
    # 1 https://0.0.0.0/fake_url/api/v0/authenticate
    # 2 https://0.0.0.0/fake_url/api/v0/authok
    # 3 https://0.0.0.0/fake_url/api/v0/authenticate
    # 4 https://0.0.0.0/fake_url/api/v0/authok
    # 5 https://0.0.0.0/fake_url/api/v0/labs

    assert (responses.calls[0].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert json.loads(responses.calls[0].request.body) == {
        "username": "******",
        "password": "******",
    }
    assert (responses.calls[1].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert responses.calls[
        2].request.url == "https://0.0.0.0/fake_url/api/v0/authok"
    assert (responses.calls[3].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert responses.calls[
        4].request.url == "https://0.0.0.0/fake_url/api/v0/authok"
    assert responses.calls[
        5].request.url == "https://0.0.0.0/fake_url/api/v0/labs"
    assert len(responses.calls) == 6
예제 #24
0
def test_auth_and_reauth_token(client_library_server_2_0_0):
    # TODO: need to check what the purpose of this test is, and how it
    # works with the automatic auth check on CL init
    # if there's environ vars for username and password set
    # then delete them b/c we rely on specific usernames
    # and passwords for this test!
    # docs: https://github.com/getsentry/responses
    try:
        del os.environ["VIRL2_PASS"]
        del os.environ["VIRL2_USER"]
    except KeyError:
        pass

    # mock failed authentication:
    responses.add(responses.POST,
                  "https://0.0.0.0/fake_url/api/v0/authenticate",
                  status=403)
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/authok",
                  status=401)

    # mock successful authentication:
    responses.add(
        responses.POST,
        "https://0.0.0.0/fake_url/api/v0/authenticate",
        json="7bbcan78a98bch7nh3cm7hao3nc7",
    )
    responses.add(responses.GET, "https://0.0.0.0/fake_url/api/v0/authok")

    # mock get labs
    responses.add(responses.GET,
                  "https://0.0.0.0/fake_url/api/v0/labs",
                  json=[])

    with pytest.raises(InitializationError):
        # Test returns custom exception when instructed to raise on failure
        ClientLibrary(
            url="http://0.0.0.0/fake_url/",
            username="******",
            password="******",
            raise_for_auth_failure=True,
        )

    cl = ClientLibrary(url="http://0.0.0.0/fake_url/",
                       username="******",
                       password="******")

    cl.all_labs()

    # for idx, item in enumerate(responses.calls):
    #     print(idx, item.request.url)
    #
    # this is what we expect:
    # 0 https://0.0.0.0/fake_url/api/v0/authenticate
    # 1 https://0.0.0.0/fake_url/api/v0/authenticate
    # 2 https://0.0.0.0/fake_url/api/v0/authok
    # 3 https://0.0.0.0/fake_url/api/v0/authenticate
    # 4 https://0.0.0.0/fake_url/api/v0/authok
    # 5 https://0.0.0.0/fake_url/api/v0/labs

    assert (responses.calls[0].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert json.loads(responses.calls[0].request.body) == {
        "username": "******",
        "password": "******",
    }
    assert (responses.calls[1].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert responses.calls[
        2].request.url == "https://0.0.0.0/fake_url/api/v0/authok"
    assert (responses.calls[3].request.url ==
            "https://0.0.0.0/fake_url/api/v0/authenticate")
    assert responses.calls[
        4].request.url == "https://0.0.0.0/fake_url/api/v0/authok"
    assert responses.calls[
        5].request.url == "https://0.0.0.0/fake_url/api/v0/labs"
    assert len(responses.calls) == 6
예제 #25
0
def test_client_library_init_disallow_http(client_library_server_current):
    with pytest.raises(InitializationError, match="must be https"):
        ClientLibrary("http://somehost", "virl2", "virl2")
    with pytest.raises(InitializationError, match="must be https"):
        ClientLibrary("http://somehost", "virl2", "virl2", allow_http=False)
def test_major_version_mismatch(client_library_incompatible_version):
    with pytest.raises(InitializationError) as err:
        ClientLibrary("somehost", "virl2", password="******")
    assert str(err.value) == "Major version mismatch. server 1.0.0, client 2.1.0"