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

SaaS/Edge organisations broken when importing into self-hosted #5021

Open
3 of 4 tasks
rolodato opened this issue Jan 20, 2025 · 0 comments
Open
3 of 4 tasks

SaaS/Edge organisations broken when importing into self-hosted #5021

rolodato opened this issue Jan 20, 2025 · 0 comments
Labels
bug Something isn't working

Comments

@rolodato
Copy link
Member

rolodato commented Jan 20, 2025

How are you running Flagsmith

  • Self Hosted with Docker
  • Self Hosted with Kubernetes
  • SaaS at flagsmith.com
  • Some other way (add details in description below)

Describe the bug

Projects imported from SaaS into a self-hosted environment with enable_dynamo_db: true cannot be used and require manual intervention. The API returns 500 on some requests, and the frontend incorrectly displays this error message:

Image

Steps To Reproduce

  1. Import an organisation from SaaS, making sure a project has enable_dynamo_db: true. Alternatively, manually enable enable_dynamo_db on any self-hosted project from Django Admin
  2. The frontend calls GET /api/v1/projects/<project_id>/features when loading, which returns a 500 and shows an incorrect error message. Users are blocked at this point
API stacktrace
django.request ERROR    Internal Server Error: /api/v1/projects/3/features/
Traceback (most recent call last):
  File "/build/.venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/rest_framework/viewsets.py", line 124, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/build/.venv/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/build/.venv/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/rest_framework/mixins.py", line 42, in list
    serializer = self.get_serializer(page, many=True)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/build/.venv/lib/python3.11/site-packages/rest_framework/generics.py", line 113, in get_serializer
    kwargs.setdefault('context', self.get_serializer_context())
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/features/views.py", line 218, in get_serializer_context
    context["overrides_data"] = get_overrides_data(
                                ^^^^^^^^^^^^^^^^^^^
  File "/app/features/features_service.py", line 33, in get_overrides_data
    return get_edge_overrides_data(environment, feature_ids)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/features/features_service.py", line 106, in get_edge_overrides_data
    for identity_overrides_v2_list in get_overrides_data_future.result():
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 449, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/edge_api/identities/edge_identity_service.py", line 33, in get_edge_identity_overrides_for_feature_ids
    ddb_environment_v2_wrapper.get_identity_overrides_by_environment_id(
  File "/app/environments/dynamodb/wrappers/environment_wrapper.py", line 103, in get_identity_overrides_by_environment_id
    results = [future.result() for future in futures]
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/environments/dynamodb/wrappers/environment_wrapper.py", line 103, in <listcomp>
    results = [future.result() for future in futures]
               ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 449, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/environments/dynamodb/wrappers/environment_wrapper.py", line 112, in get_identity_overrides_page
    query_response = self.table.query(
                     ^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'query'

Expected behavior

Support importing SaaS orgs directly without manual intervention, and display a correct error message in response to 500 errors.

I don't have an opinion as to how this can be achieved - for example, overriding the value of enable_dynamo_db during export or import, or ignoring its value altogether when self-hosting.

Screenshots

No response

@rolodato rolodato added the bug Something isn't working label Jan 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant