-
Notifications
You must be signed in to change notification settings - Fork 918
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Developer experience improvements around DB downloads and getting CMS…
… images (#15079) * Update "make preflight" command to allow a -- --retain-db flag This will help people avoid blatting their local DB and losing WIP CMS pages * Improve formatting (line breaks) for the boostrap_local_admin management command * Add tool to download images to match a fresh DB download * Expand set to default rendition sizes exported, so that downloaded images all have appropriate sizes made The 165x165 is what the Image Library in Wagtail needs, so we must ensure a local download of images regenerates that immediately * Add docs for the image-download tool * Exclude image renditions from the DB export These are not needed, and indeed block the [re]generation of renditions after download. If a DB row exists for a rendition, even though the image does not, Wagtail won't regenerate an image rendition to replace it because it thinks it already exists. * Test fixups * Add extra line to Makefile help explain how to use --retain-db flag via make * Add docs explaining how to get CMS state down to local dev * Minor fixups following code review
- Loading branch information
1 parent
ad6a263
commit a1a0ba7
Showing
11 changed files
with
205 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
bedrock/cms/management/commands/download_media_to_local.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
import os | ||
import sys | ||
|
||
from django.conf import settings | ||
from django.core.management.base import BaseCommand | ||
|
||
from google.cloud import storage | ||
|
||
from bedrock.cms.models import BedrockImage | ||
from bedrock.settings.base import path as build_path | ||
|
||
BUCKETS = { | ||
"dev": "bedrock-nonprod-dev-cms-media", | ||
"stage": "bedrock-nonprod-stage-cms-media", | ||
"prod": "bedrock-prod-prod-cms-media", | ||
} | ||
|
||
|
||
class Command(BaseCommand): | ||
help = """Downloads public media files from the appropriate cloud bucket | ||
so that they match the sqlite database being currently used.""" | ||
|
||
def add_arguments(self, parser): | ||
parser.add_argument( | ||
"--environment", | ||
default="dev", | ||
help="Which Bedrock environment are you downloading from? Values are dev | stage | prod (default is dev)", | ||
) | ||
parser.add_argument( | ||
"--redownload", | ||
action="store_true", | ||
dest="redownload", | ||
default=False, | ||
help="If passed, will force re-download of all the assets in the relevant bucket.", | ||
) | ||
|
||
def handle(self, *args, **options): | ||
# If we're not using sqlite, stop, because this tool isn't for that | ||
|
||
if settings.DATABASES["default"]["ENGINE"] != "django.db.backends.sqlite3": | ||
self.stderr.write(f"This command only works if you are using sqlite as your local DB. Got {settings.DATABASES['default']['ENGINE']}\n") | ||
sys.exit(1) | ||
|
||
try: | ||
bucket_name = BUCKETS[options["environment"]] | ||
except KeyError: | ||
self.stderr.write(f"Couldn't determine which bucket you wanted. Got {options['environment']}\n") | ||
sys.exit(1) | ||
|
||
storage_client = storage.Client.create_anonymous_client() | ||
bucket = storage_client.bucket(bucket_name) | ||
|
||
# Get the files, ideally in a way that checks whether we have them already | ||
# unless the --redownload param is passed | ||
redownload = options["redownload"] | ||
if redownload: | ||
self.stdout.write("Forcing redownload of all files.\n") | ||
|
||
for image in BedrockImage.objects.all(): | ||
image_key = f"media/cms/{image.file.name}" | ||
local_dest = build_path(settings.MEDIA_ROOT, image.file.name) | ||
|
||
if os.path.exists(local_dest) and not redownload: | ||
self.stdout.write(f"Skipping: {local_dest} already exists locally.\n") | ||
else: | ||
blob = bucket.blob(image_key) | ||
blob.download_to_filename(local_dest) | ||
self.stdout.write(f"Downloaded {image_key} from {bucket_name} to {local_dest}\n") | ||
|
||
image._pre_generate_expected_renditions() | ||
self.stdout.write("Triggered local generation of renditions\n") | ||
|
||
self.stdout.write("All done.\n") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ def test_no_env_vars_available(self, mock_write): | |
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL not defined in environment."), | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL not defined in environment\n"), | ||
], | ||
) | ||
|
||
|
@@ -31,7 +31,7 @@ def test_email_available(self, mock_write): | |
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Created Admin user [email protected] for local SSO use"), | ||
call("Created Admin user [email protected] for local SSO use\n"), | ||
], | ||
) | ||
|
||
|
@@ -40,7 +40,7 @@ def test_email_available_but_not_moco(self, mock_write): | |
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL is not a @mozilla.com email address."), | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL is not a @mozilla.com email address\n"), | ||
], | ||
) | ||
|
||
|
@@ -49,7 +49,7 @@ def test_email_and_password_available(self, mock_write): | |
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Created Admin user [email protected] with password 'secret'"), | ||
call("Created Admin user [email protected] with password 'secret'\n"), | ||
], | ||
) | ||
|
||
|
@@ -58,7 +58,7 @@ def test_only_password_available(self, mock_write): | |
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL not defined in environment."), | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL not defined in environment\n"), | ||
], | ||
) | ||
|
||
|
@@ -69,8 +69,8 @@ def test_existing_user_exists_email_only(self, mock_write): | |
call_command("bootstrap_local_admin", stdout=out) | ||
output = mock_write.call_args_list | ||
expected_output = [ | ||
call("Created Admin user [email protected] for local SSO use"), | ||
call("Admin user [email protected] already exists"), | ||
call("Created Admin user [email protected] for local SSO use\n"), | ||
call("Admin user [email protected] already exists\n"), | ||
] | ||
self.assertEqual(output, expected_output) | ||
|
||
|
@@ -81,7 +81,7 @@ def test_existing_user_exists_email_and_password(self, mock_write): | |
call_command("bootstrap_local_admin", stdout=out) | ||
output = mock_write.call_args_list | ||
expected_output = [ | ||
call("Created Admin user [email protected] with password 'secret'"), | ||
call("Admin user [email protected] already exists"), | ||
call("Created Admin user [email protected] with password 'secret'\n"), | ||
call("Admin user [email protected] already exists\n"), | ||
] | ||
self.assertEqual(output, expected_output) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.