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

bug: infrahub returns HTTP 500 status code when loading a schema that removes a node, to which another node still has a relationship #4912

Closed
wvandeun opened this issue Nov 11, 2024 · 0 comments · Fixed by #5079
Assignees
Labels
group/schema Issue related to some schemas type/bug Something isn't working as expected
Milestone

Comments

@wvandeun
Copy link
Contributor

wvandeun commented Nov 11, 2024

Component

API Server / GraphQL

Infrahub version

1.0.3

Current Behavior

When you load a schema using the REST API endpoint /api/schema/load, that deletes a node from the schema, to which another node in the schema still has a relationship then you will get a HTTP 500 - internal server error response.

In the logs of the api server, we can find the following message, indicating we are catching the issue properly

{"event": "Exception in ASGI application
", "timestamp": "2024-11-11T12:46:40.047476Z", "logger": "uvicorn.error", "level": "error", "exception": "Traceback (most recent call last):
  File \"/usr/local/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py\", line 401, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py\", line 60, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/site-packages/fastapi/applications.py\", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/applications.py\", line 113, in __call__
    await self.middleware_stack(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/errors.py\", line 187, in __call__
    raise exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/errors.py\", line 165, in __call__
    await self.app(scope, receive, _send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/gzip.py\", line 20, in __call__
    await responder(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/gzip.py\", line 39, in __call__
    await self.app(scope, receive, self.send_with_gzip)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/cors.py\", line 85, in __call__
    await self.app(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette_exporter/middleware.py\", line 499, in __call__
    raise exception
  File \"/usr/local/lib/python3.12/site-packages/starlette_exporter/middleware.py\", line 405, in __call__
    await self.app(scope, receive, wrapped_send)
  File \"/usr/local/lib/python3.12/site-packages/asgi_correlation_id/middleware.py\", line 90, in __call__
    await self.app(scope, receive, handle_outgoing_request)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 185, in __call__
    with collapse_excgroups():
         ^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/contextlib.py\", line 158, in __exit__
    self.gen.throw(value)
  File \"/usr/local/lib/python3.12/site-packages/starlette/_utils.py\", line 82, in collapse_excgroups
    raise exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 187, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/source/backend/infrahub/server.py\", line 172, in add_telemetry_span_exception
    return await call_next(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 163, in call_next
    raise app_exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 149, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 185, in __call__
    with collapse_excgroups():
         ^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/contextlib.py\", line 158, in __exit__
    self.gen.throw(value)
  File \"/usr/local/lib/python3.12/site-packages/starlette/_utils.py\", line 82, in collapse_excgroups
    raise exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 187, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/source/backend/infrahub/server.py\", line 161, in add_process_time_header
    response = await call_next(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 163, in call_next
    raise app_exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 149, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 185, in __call__
    with collapse_excgroups():
         ^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/contextlib.py\", line 158, in __exit__
    self.gen.throw(value)
  File \"/usr/local/lib/python3.12/site-packages/starlette/_utils.py\", line 82, in collapse_excgroups
    raise exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 187, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/source/backend/infrahub/server.py\", line 154, in logging_middleware
    response = await call_next(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 163, in call_next
    raise app_exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 149, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File \"/usr/local/lib/python3.12/site-packages/opentelemetry/instrumentation/asgi/__init__.py\", line 631, in __call__
    await self.app(scope, otel_receive, otel_send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/exceptions.py\", line 62, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 62, in wrapped_app
    raise exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 51, in wrapped_app
    await app(scope, receive, sender)
  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 715, in __call__
    await self.middleware_stack(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 735, in app
    await route.handle(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 288, in handle
    await self.app(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 76, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 62, in wrapped_app
    raise exc
  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 51, in wrapped_app
    await app(scope, receive, sender)
  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 73, in app
    response = await f(request)
               ^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/site-packages/fastapi/routing.py\", line 301, in app
    raw_response = await run_endpoint_function(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/usr/local/lib/python3.12/site-packages/fastapi/routing.py\", line 212, in run_endpoint_function
    return await dependant.call(**values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/source/backend/infrahub/api/schema.py\", line 304, in load_schema
    await registry.schema.update_schema_branch(
  File \"/source/backend/infrahub/core/schema/manager.py\", line 172, in update_schema_branch
    updated_schema = await self.load_schema_from_db(
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File \"/source/backend/infrahub/core/schema/manager.py\", line 672, in load_schema_from_db
    schema.process(validate_schema=validate_schema)
  File \"/source/backend/infrahub/core/schema/schema_branch.py\", line 445, in process
    self.process_validate()
  File \"/source/backend/infrahub/core/schema/schema_branch.py\", line 460, in process_validate
    self.validate_kinds()
  File \"/source/backend/infrahub/core/schema/schema_branch.py\", line 899, in validate_kinds
    raise ValueError(
ValueError: TestingTestNode2: Relationship 'test_node_1' is referencing an invalid peer 'TestingTestNode1'"}

Expected Behavior

This is a problem with the schema that the user is trying to load. This should be detected by Infrahub and we should return a client error response with a precise reason for failure.

Steps to Reproduce

  • set up a instance of Infrahub
  • load the following schema
---
version: "1.0"
nodes:
  - name: TestNode1
    namespace: Testing
    attributes:
      - name: name
        kind: Text
        optional: false
        unique: true
  - name: TestNode2
    namespace: Testing
    attributes:
      - name: name
        kind: Text
        optional: false
        unique: true
    relationships:
      - name: test_node_1
        peer: TestingTestNode1
        kind: Attribute
        cardinality: one
        optional: true
  • load this schema, we are removing TestingTestNode1
---
version: "1.0"
nodes:
  - name: TestNode1
    namespace: Testing
    state: absent
    attributes:
      - name: name
        kind: Text
        optional: false
        unique: true
  - name: TestNode2
    namespace: Testing
    attributes:
      - name: name
        kind: Text
        optional: false
        unique: true
    relationships:
      - name: test_node_1
        peer: TestingTestNode1
        kind: Attribute
        cardinality: one
        optional: true

Additional Information

No response

@wvandeun wvandeun added type/bug Something isn't working as expected group/backend Issue related to the backend (API Server, Git Agent) labels Nov 11, 2024
@exalate-issue-sync exalate-issue-sync bot added the priority/2 This issue stalls work on the project or its dependents, it's a blocker for a release label Nov 11, 2024
@exalate-issue-sync exalate-issue-sync bot added this to the Infrahub - 1.0.x milestone Nov 11, 2024
@exalate-issue-sync exalate-issue-sync bot removed group/backend Issue related to the backend (API Server, Git Agent) priority/2 This issue stalls work on the project or its dependents, it's a blocker for a release labels Nov 11, 2024
@dgarros dgarros added the group/schema Issue related to some schemas label Nov 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
group/schema Issue related to some schemas type/bug Something isn't working as expected
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants