Skip to content

Commit 620afe9

Browse files
authored
fix: import from saas to self-hosted (#5336)
1 parent 7064cef commit 620afe9

2 files changed

Lines changed: 74 additions & 30 deletions

File tree

api/import_export/export.py

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ class S3OrganisationExporter:
5656
def __init__(self, s3_client=None): # type: ignore[no-untyped-def]
5757
self.s3_client = s3_client or boto3.client("s3")
5858

59-
def export_to_s3(self, organisation_id: int, bucket_name: str, key: str): # type: ignore[no-untyped-def]
59+
def export_to_s3(
60+
self,
61+
organisation_id: int,
62+
bucket_name: str,
63+
key: str,
64+
) -> None:
6065
data = full_export(organisation_id)
6166
logger.debug("Got data export for organisation.")
6267

@@ -109,41 +114,52 @@ def export_metadata(organisation_id: int) -> typing.List[dict]: # type: ignore[
109114
)
110115

111116

112-
def export_projects(organisation_id: int) -> typing.List[dict]: # type: ignore[type-arg]
117+
def export_projects(
118+
organisation_id: int,
119+
) -> typing.List[dict]: # type: ignore[type-arg]
113120
default_filter = Q(project__organisation__id=organisation_id)
114121

115-
return _export_entities(
122+
exported_projects = _export_entities(
116123
_EntityExportConfig(Project, Q(organisation__id=organisation_id)),
117-
_EntityExportConfig(
118-
Segment, Q(project__organisation__id=organisation_id, id=F("version_of"))
119-
),
120-
_EntityExportConfig(
121-
SegmentRule,
122-
Q(
123-
segment__project__organisation__id=organisation_id,
124-
segment_id=F("segment__version_of"),
125-
)
126-
| Q(
127-
rule__segment__project__organisation__id=organisation_id,
128-
rule__segment_id=F("rule__segment__version_of"),
124+
)
125+
for project in exported_projects:
126+
project["fields"]["enable_dynamo_db"] = False
127+
128+
return [
129+
*exported_projects,
130+
*_export_entities(
131+
_EntityExportConfig(
132+
Segment,
133+
Q(project__organisation__id=organisation_id, id=F("version_of")),
129134
),
130-
),
131-
_EntityExportConfig(
132-
Condition,
133-
Q(
134-
rule__segment__project__organisation__id=organisation_id,
135-
rule__segment_id=F("rule__segment__version_of"),
136-
)
137-
| Q(
138-
rule__rule__segment__project__organisation__id=organisation_id,
139-
rule__rule__segment_id=F("rule__rule__segment__version_of"),
135+
_EntityExportConfig(
136+
SegmentRule,
137+
Q(
138+
segment__project__organisation__id=organisation_id,
139+
segment_id=F("segment__version_of"),
140+
)
141+
| Q(
142+
rule__segment__project__organisation__id=organisation_id,
143+
rule__segment_id=F("rule__segment__version_of"),
144+
),
140145
),
146+
_EntityExportConfig(
147+
Condition,
148+
Q(
149+
rule__segment__project__organisation__id=organisation_id,
150+
rule__segment_id=F("rule__segment__version_of"),
151+
)
152+
| Q(
153+
rule__rule__segment__project__organisation__id=organisation_id,
154+
rule__rule__segment_id=F("rule__rule__segment__version_of"),
155+
),
156+
),
157+
_EntityExportConfig(Tag, default_filter),
158+
_EntityExportConfig(DataDogConfiguration, default_filter),
159+
_EntityExportConfig(NewRelicConfiguration, default_filter),
160+
_EntityExportConfig(SlackConfiguration, default_filter),
141161
),
142-
_EntityExportConfig(Tag, default_filter),
143-
_EntityExportConfig(DataDogConfiguration, default_filter),
144-
_EntityExportConfig(NewRelicConfiguration, default_filter),
145-
_EntityExportConfig(SlackConfiguration, default_filter),
146-
)
162+
]
147163

148164

149165
def export_environments(organisation_id: int) -> typing.List[dict]: # type: ignore[type-arg]

api/tests/unit/import_export/test_unit_import_export_export.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from flag_engine.segments.constants import ALL_RULE, EQUAL
1212
from moto import mock_s3 # type: ignore[import-untyped]
1313
from mypy_boto3_dynamodb.service_resource import Table
14+
from pyfakefs.fake_filesystem import FakeFilesystem
1415
from pytest_mock import MockerFixture
1516

1617
from core.constants import STRING
@@ -597,3 +598,30 @@ def test_organisation_exporter_export_to_s3(organisation): # type: ignore[no-un
597598
# Then
598599
retrieved_object = s3_client.get_object(Bucket=bucket_name, Key=file_key)
599600
assert retrieved_object.get("ContentLength", 0) > 0
601+
602+
603+
def test_export_dynamo_project(
604+
organisation: Organisation, mocker: MockerFixture, fs: FakeFilesystem
605+
) -> None:
606+
# Given - dynamo db project
607+
project_name = "test project"
608+
project = Project.objects.create(
609+
organisation=organisation, name=project_name, enable_dynamo_db=True
610+
)
611+
612+
# When - we export the data
613+
data = export_projects(organisation.id)
614+
615+
# and delete the project
616+
project.hard_delete()
617+
618+
# Next, let's load the data
619+
file_path = f"/tmp/{uuid.uuid4()}.json"
620+
fs.create_file(file_path, contents=json.dumps(data, cls=DjangoJSONEncoder))
621+
622+
call_command("loaddata", file_path, format="json")
623+
624+
# Then
625+
assert (
626+
Project.objects.filter(uuid=project.uuid, enable_dynamo_db=False).count() == 1
627+
)

0 commit comments

Comments
 (0)