Skip to content

Commit d7bd114

Browse files
committed
Add error handling to sgr cloud load
Add a model for the response from the externals REST endpoint and output/raise introspection errors if they exist.
1 parent 5480fec commit d7bd114

5 files changed

Lines changed: 70 additions & 7 deletions

File tree

splitgraph/cloud/__init__.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from splitgraph.cloud.models import (
3333
AddExternalCredentialRequest,
3434
AddExternalRepositoriesRequest,
35+
AddExternalRepositoriesResponse,
3536
AddExternalRepositoryRequest,
3637
ExportJobStatus,
3738
ExternalResponse,
@@ -75,6 +76,7 @@
7576
from splitgraph.config.management import patch_and_save_config
7677
from splitgraph.exceptions import (
7778
AuthAPIError,
79+
DataSourceError,
7880
GQLAPIError,
7981
GQLRepoDoesntExistError,
8082
GQLUnauthenticatedError,
@@ -535,17 +537,33 @@ def bulk_upsert_external(
535537
self,
536538
repositories: List[AddExternalRepositoryRequest],
537539
introspection_mode: IntrospectionMode = IntrospectionMode.EMPTY,
538-
):
540+
raise_errors: bool = False,
541+
) -> None:
539542
request = AddExternalRepositoriesRequest(
540543
repositories=repositories, introspection_mode=introspection_mode
541544
)
542-
self._perform_request(
545+
response = self._perform_request(
543546
"/bulk-add",
544547
self.access_token,
545548
request,
546549
endpoint=self.externals_endpoint,
547550
jsonschema_endpoint=True,
551+
response_class=AddExternalRepositoriesResponse,
548552
)
553+
assert response
554+
if response.errors:
555+
for repo_errors in response.errors:
556+
for error in repo_errors.errors:
557+
logging.warning(
558+
"Error adding table %s/%s/%s: %s (%s)",
559+
repo_errors.namespace,
560+
repo_errors.repository,
561+
error.table_name,
562+
error.error,
563+
error.error_text,
564+
)
565+
if raise_errors:
566+
raise DataSourceError("Error introspecting some tables!")
549567

550568

551569
def AuthAPIClient(*args, **kwargs):

splitgraph/cloud/models.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
Source,
1717
Table,
1818
)
19-
from splitgraph.core.types import Params, TableSchema
19+
from splitgraph.core.types import MountError, Params, TableSchema
2020

2121

2222
class Plugin(BaseModel):
@@ -301,3 +301,13 @@ def from_external(
301301
class AddExternalRepositoriesRequest(BaseModel):
302302
repositories: List[AddExternalRepositoryRequest]
303303
introspection_mode: IntrospectionMode = IntrospectionMode.EMPTY
304+
305+
306+
class AddExternalRepositoriesResponse(BaseModel):
307+
class RepositoryMountError(BaseModel):
308+
namespace: str
309+
repository: str
310+
errors: List[MountError]
311+
312+
live_image_hashes: List[Optional[str]]
313+
errors: Optional[List[RepositoryMountError]] = None

splitgraph/commandline/cloud.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,11 @@ def dump_c(remote, readme_dir, repositories_file, limit_repositories):
620620
help="Whether to reintrospect tables. none: never reintrospect. all: reintrospect all tables. "
621621
"empty: only reintrospect tables with an empty schema.",
622622
)
623+
@click.option(
624+
"--ignore-introspection-errors",
625+
is_flag=True,
626+
help="If set, will ignore errors when introspecting tables.",
627+
)
623628
@click.argument("limit_repositories", type=str, nargs=-1)
624629
def load_c(
625630
remote,
@@ -629,6 +634,7 @@ def load_c(
629634
repositories_file,
630635
limit_repositories,
631636
introspection_mode,
637+
ignore_introspection_errors,
632638
):
633639
"""
634640
Load a Splitgraph catalog from a YAML file.
@@ -680,7 +686,9 @@ def load_c(
680686
)
681687
external_repositories.append(external_repository)
682688
rest_client.bulk_upsert_external(
683-
repositories=external_repositories, introspection_mode=introspection_mode
689+
repositories=external_repositories,
690+
introspection_mode=introspection_mode,
691+
raise_errors=not ignore_introspection_errors,
684692
)
685693
logging.info(f"Uploaded images for {pluralise('repository', len(external_repositories))}")
686694

test/splitgraph/commandline/http_fixtures.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ def add_external_credential(request, uri, response_headers):
399399
]
400400

401401

402-
def add_external_repo(initial_private=False):
402+
def add_external_repo(initial_private=False, error=False):
403403
def cb(request, uri, response_headers):
404404
data = json.loads(request.body)
405405

@@ -451,7 +451,26 @@ def cb(request, uri, response_headers):
451451
return [
452452
200,
453453
response_headers,
454-
json.dumps({"live_image_hashes": ["abcdef12" * 8, "ghijkl34" * 8, "mnoprs56" * 8]}),
454+
json.dumps(
455+
{
456+
"live_image_hashes": ["abcdef12" * 8, "ghijkl34" * 8, "mnoprs56" * 8],
457+
"errors": [
458+
{
459+
"namespace": "otheruser",
460+
"repository": "somerepo_2",
461+
"errors": [
462+
{
463+
"table_name": "table_1",
464+
"error": "SomeError",
465+
"error_text": "Something bad happened",
466+
}
467+
],
468+
}
469+
]
470+
if not error
471+
else [],
472+
}
473+
),
455474
]
456475

457476
return cb

test/splitgraph/commandline/test_cloud_metadata.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,9 @@ def test_commandline_dump(snapshot):
273273

274274

275275
@pytest.mark.parametrize("initial_private", [True, False])
276+
@pytest.mark.parametrize("errors", [True, False])
276277
@httpretty.activate(allow_net_connect=False)
277-
def test_commandline_load(initial_private):
278+
def test_commandline_load(initial_private, errors):
278279
runner = CliRunner()
279280

280281
httpretty.register_uri(
@@ -326,6 +327,7 @@ def get_remote_param(remote, param):
326327
os.path.join(RESOURCES, "splitgraph_yml", "readmes"),
327328
"-f",
328329
os.path.join(RESOURCES, "splitgraph_yml", "splitgraph.yml"),
330+
"--ignore-introspection-errors",
329331
],
330332
catch_exceptions=False,
331333
)
@@ -339,6 +341,12 @@ def get_remote_param(remote, param):
339341
reqs.pop() # discard duplicate request
340342
assert_repository_profiles(reqs.pop())
341343

344+
if errors:
345+
assert (
346+
"Error adding table otheruser/somerepo_2/table_1: "
347+
"SomeError (Something bad happened)" in result.output
348+
)
349+
342350

343351
def test_project_validate(snapshot):
344352
# Use the same file as the merging test

0 commit comments

Comments
 (0)