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

PADV-1557 Adjust storage backend definition via site configurations #9

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/001-custom-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,29 @@ This feature allows CCX coaches (ccx_coach in the course access role model) and
- Find the assignment and grade it.
- After grading the assignment, it should not be necessary to approve the grade.
- Go to the progress page, with the student user and check if the grade is assigned to the unit containing the SGA component.

## Custom Storage Backend

### Context

The SGA Xblock in its upstream repository approaches the storage capability by relaying on the Django's default storage
that is defined in the edx platform. There's also a feature where the storage backend to be used can be defined via
platform settings. For our fork, this feature adds the capability to define a site-aware backend via site configurations.

### Feature

To define a desired backend, follow the following format by defining the storage class and its kwargs.
As an example, below you will find the Site Configuration definition to use an AWS S3 bucket:

"SGA_STORAGE_SETTINGS": {
"STORAGE_CLASS": "storages.backends.s3boto3.S3Boto3Storage",
"STORAGE_KWARGS": {
"access_key": "aws_access_key",
"secret_key": "aws_secret_key",
"bucket_name": "aws-bucket-name",
"region_name": "us-east-1"
}
}

Once it has been done, the SGA xblocks for the given site will manage the media objects with the defined storage backend.
If no settings are defined, the Xblock would use the default Django storage.
27 changes: 19 additions & 8 deletions edx_sga/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Tests for SGA utility functions
"""
from django.test import override_settings
from unittest.mock import patch
from django.core.files.storage import default_storage
import pytest
import pytz
Expand Down Expand Up @@ -35,23 +35,34 @@ def test_utcnow():
assert is_near_now(now)
assert now.tzinfo.zone == pytz.utc.zone

@override_settings(SGA_STORAGE_SETTINGS={
'STORAGE_CLASS': 'storages.backends.s3boto3.S3Boto3Storage',
'STORAGE_KWARGS':
{'bucket_name': 'test', 'location': 'abc/def'}
})
def test_get_default_storage_with_settings_override():
patch("edx_sga.utils.configuration_helpers")
def test_get_default_storage_with_settings_override(mock_configuration_helpers):
"""
get_default_storage should return an S3Boto3Storage object
"""
mock_configuration_helpers.return_value.get_value.return_value = (
{
"SGA_STORAGE_SETTINGS": {
"STORAGE_CLASS": "storages.backends.s3boto3.S3Boto3Storage",
"STORAGE_KWARGS": {
"access_key": "test_key",
"secret_key": "test_secret",
"bucket_name": "test-bucket-1",
"region_name": "us-east-1",
},
},
},
)
storage = get_default_storage()
assert storage.__class__ == S3Boto3Storage
# make sure kwargs are passed through constructor
assert storage.bucket.name == 'test'

def test_get_default_storage_without_settings_override():
patch("edx_sga.utils.configuration_helpers")
def test_get_default_storage_without_settings_override(mock_configuration_helpers):
"""
get_default_storage should return default_storage object
"""
mock_configuration_helpers.return_value.get_value.return_value = {}
storage = get_default_storage()
assert storage == default_storage
6 changes: 3 additions & 3 deletions edx_sga/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
from functools import partial

import pytz
from django.conf import settings
from django.core.files.storage import default_storage as django_default_storage, get_storage_class
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from edx_sga.constants import BLOCK_SIZE


def get_default_storage():
"""
Get config for storage from settings, use Django's default_storage if no such settings are defined
Get config for storage from site configurations, use Django's default_storage if no such settings are defined
"""
# .. setting_name: SGA_STORAGE_SETTINGS
# .. setting_default: {}
Expand All @@ -25,7 +25,7 @@ def get_default_storage():
# STORAGE_CLASS: 'storage',
# STORAGE_KWARGS: {}
# }
sga_storage_settings = getattr(settings, "SGA_STORAGE_SETTINGS", None)
sga_storage_settings = configuration_helpers.get_value('SGA_STORAGE_SETTINGS', None)

if sga_storage_settings:
return get_storage_class(
Expand Down
Loading