Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#279 Made the nodebook testing running on SaaS [run-notebook-tests] #281

Merged
merged 20 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b86382e
#279 Made the nodebook testing running on SaaS [run-notebook-tests]
ahsimb Jun 4, 2024
7885c7f
#279 Enabled new fixture [run-notebook-tests]
ahsimb Jun 4, 2024
71a634f
#279 Added SaaS secrets to ci [run-notebook-tests]
ahsimb Jun 5, 2024
b0e5853
#279 Added SaaS secrets to ci [run-notebook-tests]
ahsimb Jun 5, 2024
acfc7e4
#279 Fixed a bug with a cfg name [run-notebook-tests]
ahsimb Jun 5, 2024
81efe05
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
65c6f8f
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
8afba76
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
330a0a5
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
c57940d
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
8e92bcc
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
56100f4
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
c54ddf6
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
2292f07
#279 Updated the dependency again [run-notebook-tests]
ahsimb Jun 5, 2024
5589958
#279 Looking at the permission error [run-notebook-tests]
ahsimb Jun 5, 2024
d9cbe50
#279 Looking at the permission error [run-notebook-tests]
ahsimb Jun 5, 2024
e930ae7
#279 Fixing the fixtures [run-notebook-tests]
ahsimb Jun 5, 2024
a92d14f
#279 Fixing the fixtures [run-notebook-tests]
ahsimb Jun 5, 2024
721b08b
#279 Enabled SageMaker test [run-notebook-tests]
ahsimb Jun 5, 2024
9ccdfc2
#279 Increased the database time-out [run-notebook-tests]
ahsimb Jun 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/check_ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,6 @@ jobs:
NBTEST_AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
NBTEST_AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY_SECRET }}
NBTEST_AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
SAAS_HOST: ${{ secrets.INTEGRATION_TEAM_SAAS_STAGING_HOST }}
SAAS_ACCOUNT_ID: ${{ secrets.INTEGRATION_TEAM_SAAS_STAGING_ACCOUNT_ID }}
SAAS_PAT: ${{ secrets.INTEGRATION_TEAM_SAAS_STAGING_PAT }}
1 change: 1 addition & 0 deletions doc/changes/changes_2.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Version: 2.1.0
## Features

* 277 Added the SaaS database parameters to the configuration page.
* 279 Made the notebooks tests running in SaaS as well as in the Docker-DB.

## Security

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,6 @@ def test_notebook(notebook_test_container_with_log, notebook_test_file):
)
environ = os.environ.copy()
environ["NBTEST_ACTIVE"] = "TRUE"
nbtest_environ = {key: value for key, value in environ.items() if key.startswith("NBTEST_")}
nbtest_environ = {key: value for key, value in environ.items() if (
key.startswith("NBTEST_") or key.startswith("SAAS_"))}
exec_command(command_run_test, container, print_output=True, environment=nbtest_environ, user="jupyter")
8 changes: 6 additions & 2 deletions test/notebooks/nbtest_sagemaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

import pytest
from exasol.nb_connector.secret_store import Secrets
from exasol.nb_connector.ai_lab_config import AILabConfig as CKey
from exasol.nb_connector.ai_lab_config import AILabConfig as CKey, StorageBackend

from notebook_test_utils import (access_to_temp_secret_store, run_notebook, uploading_hack)
from notebook_test_utils import (access_to_temp_secret_store,
access_to_temp_saas_secret_store,
run_notebook,
uploading_hack)


def _create_aws_s3_bucket() -> str:
Expand Down Expand Up @@ -173,6 +176,7 @@ def continuous_job_polling():
)


@pytest.mark.parametrize('access_to_temp_secret_store', [StorageBackend.onprem, StorageBackend.saas], indirect=True)
def test_sagemaker(access_to_temp_secret_store, uploading_hack):

store_path, store_password = access_to_temp_secret_store
Expand Down
8 changes: 7 additions & 1 deletion test/notebooks/nbtest_sklearn.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import os
import pytest

from notebook_test_utils import (access_to_temp_secret_store, notebook_runner)
from exasol.nb_connector.ai_lab_config import StorageBackend
from notebook_test_utils import (access_to_temp_secret_store,
access_to_temp_saas_secret_store,
notebook_runner)


@pytest.mark.parametrize('notebook_runner', [StorageBackend.onprem, StorageBackend.saas], indirect=True)
def test_regression(notebook_runner) -> None:

current_dir = os.getcwd()
Expand All @@ -18,6 +23,7 @@ def test_regression(notebook_runner) -> None:
os.chdir(current_dir)


@pytest.mark.parametrize('notebook_runner', [StorageBackend.onprem, StorageBackend.saas], indirect=True)
def test_classification(notebook_runner) -> None:

current_dir = os.getcwd()
Expand Down
6 changes: 5 additions & 1 deletion test/notebooks/nbtest_transformers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import textwrap
import pytest

from notebook_test_utils import (access_to_temp_secret_store, notebook_runner, uploading_hack)
from notebook_test_utils import (access_to_temp_secret_store,
access_to_temp_saas_secret_store,
notebook_runner,
uploading_hack)


@pytest.mark.parametrize(
Expand All @@ -17,6 +20,7 @@
'zero_shot_classification.ipynb'
]
)
@pytest.mark.skip(reason="The expected functionality is not yet implemented in the Transformers Extension")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest using xfail with a reason. This is usually the safest strategy for adding tests for unimplemented things. Additionally, once implemented, the failure of xfail will indicate that the test should now be "enabled".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With xfail the test still runs, which I don't want because it takes a long time.

def test_transformers(notebook_runner, uploading_hack, notebook_file) -> None:

running_hack = (
Expand Down
107 changes: 98 additions & 9 deletions test/notebooks/notebook_test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,33 @@
import random
import string
import textwrap
from contextlib import contextmanager, ExitStack
from datetime import timedelta
import os

import pytest
import nbformat
from nbclient import NotebookClient
import requests

from exasol.nb_connector.secret_store import Secrets
from exasol.nb_connector.ai_lab_config import AILabConfig as CKey
from exasol.nb_connector.ai_lab_config import AILabConfig as CKey, StorageBackend
from exasol.nb_connector.itde_manager import (
bring_itde_up,
take_itde_down
)
from exasol.saas.client.api_access import (
OpenApiAccess,
create_saas_client,
timestamp_name,
)


def _env(var: str) -> str:
result = os.environ.get(var)
if result:
return result
raise RuntimeError(f"Environment variable {var} is empty.")


def generate_password(pwd_length):
Expand All @@ -31,13 +46,22 @@ def url_exists(url):
return False


def _init_secret_store(secrets: Secrets) -> None:
def _init_onprem_secret_store(secrets: Secrets) -> None:
secrets.save(CKey.use_itde, 'yes')
secrets.save(CKey.mem_size, '4')
secrets.save(CKey.disk_size, '4')
secrets.save(CKey.db_schema, 'NOTEBOOK_TESTS')


def _init_saas_secret_store(secrets: Secrets) -> None:
secrets.save(CKey.storage_backend, StorageBackend.saas.name)
secrets.save(CKey.saas_url, _env("SAAS_HOST"))
secrets.save(CKey.saas_token, _env("SAAS_PAT"))
secrets.save(CKey.saas_account_id, _env("SAAS_ACCOUNT_ID"))
secrets.save(CKey.saas_database_name, timestamp_name('NBTEST'))
secrets.save(CKey.db_schema, 'NOTEBOOK_TESTS_SAAS')


def _insert_hacks(nb: nbformat.NotebookNode, hacks: List[Tuple[str, str]]):

def cell_match(nb_cell, ins_tag: str) -> bool:
Expand Down Expand Up @@ -89,8 +113,8 @@ def init_notebook_test():
nb_client.execute()


@pytest.fixture
def access_to_temp_secret_store(tmp_path: Path) -> Tuple[Path, str]:
@contextmanager
def access_to_temp_onprem_secret_store(tmp_path: Path) -> Tuple[Path, str]:
"""
Creates a temporary configuration store.
Brings up and subsequently destroys the Exasol Docker-DB.
Expand All @@ -109,7 +133,7 @@ def access_to_temp_secret_store(tmp_path: Path) -> Tuple[Path, str]:

# Set the configuration required by the ITDE manager and those the
# manager will not set after starting the Exasol Docker-DB.
_init_secret_store(secrets)
_init_onprem_secret_store(secrets)

# Start the Exasol Docker-DB and then destroy it after the test finishes.
bring_itde_up(secrets)
Expand All @@ -119,14 +143,79 @@ def access_to_temp_secret_store(tmp_path: Path) -> Tuple[Path, str]:
take_itde_down(secrets)


@pytest.fixture(scope='session')
def access_to_temp_saas_secret_store(tmp_path_factory) -> Tuple[Path, str]:
"""
Creates a temporary configuration store.
Initiates the creation of a temporary SaaS database and waits till this database
becomes operational.
Saves the SaaS connection parameters in the configuration store.
"""

store_path = tmp_path_factory.mktemp('tmp_config_dir') / 'tmp_config_saas.sqlite'
# See access_to_temp_onprem_secret_store for considerations about the store password.
store_password = generate_password(12)
secrets = Secrets(store_path, master_password=store_password)

_init_saas_secret_store(secrets)

with ExitStack() as stack:
client = stack.enter_context(create_saas_client(
host=secrets.get(CKey.saas_url),
pat=secrets.get(CKey.saas_token)))
api_access = OpenApiAccess(
client=client,
account_id=secrets.get(CKey.saas_account_id))
stack.enter_context(api_access.allowed_ip())
db = stack.enter_context(api_access.database(
name=secrets.get(CKey.saas_database_name),
idle_time=timedelta(hours=12)))
api_access.wait_until_running(db.id)
yield store_path, store_password


@pytest.fixture
def notebook_runner(access_to_temp_secret_store) -> Callable:
def access_to_temp_secret_store(request,
tmp_path: Path,
access_to_temp_saas_secret_store
) -> Tuple[Path, str]:
"""
A fixture for running a notebook.
Creates a temporary configuration store.
Ensures that the database (either on-prem or SaaS, depending on the request parameter)
is running for the duration of the fixture.
"""
if request.param == StorageBackend.onprem:
with access_to_temp_onprem_secret_store(tmp_path) as onprem_store:
yield onprem_store
elif request.param == StorageBackend.saas:
yield access_to_temp_saas_secret_store
else:
raise ValueError(('Unrecognised testing backend in the access_to_temp_secret_store. '
'Should be either "onprem" or "saas"'))

store_path, store_password = access_to_temp_secret_store
return partial(run_notebook, store_file=str(store_path), store_password=store_password)

@pytest.fixture
def notebook_runner(request,
tmp_path: Path,
access_to_temp_saas_secret_store
) -> Callable:
"""
A fixture for running a notebook.
"""
if request.param == StorageBackend.onprem:
with access_to_temp_onprem_secret_store(tmp_path) as onprem_store:
store_path, store_password = onprem_store
yield partial(run_notebook,
store_file=str(store_path),
store_password=store_password)
elif request.param == StorageBackend.saas:
store_path, store_password = access_to_temp_saas_secret_store
yield partial(run_notebook,
store_file=str(store_path),
store_password=store_password)
else:
raise ValueError(('Unrecognised testing backend in the notebook_runner. '
'Should be either "onprem" or "saas"'))


@pytest.fixture
Expand Down
4 changes: 3 additions & 1 deletion test/notebooks/test_dependencies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ nbclient
nbformat
pytest
testbook
pytest-check-links
pytest-check-links
exasol-saas-api @ git+https://github.com/exasol/saas-api-python.git@main

Loading