Skip to content
Snippets Groups Projects
Commit e0c1abc1 authored by David Baumgold's avatar David Baumgold
Browse files

check for old mongo course

parent e18507f1
Branches
Tags
No related merge requests found
......@@ -49,6 +49,7 @@ coverage.xml
cover/
cover_html/
reports/
jscover.log
jscover.log.*
### Installation artifacts
......
......@@ -3,21 +3,21 @@ Django management command to rollback a migration to split. The way to do this
is to delete the course from the split mongo datastore.
"""
from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.django import modulestore, loc_mapper
from xmodule.modulestore.exceptions import ItemNotFoundError, InsufficientSpecificationError
from xmodule.modulestore.locator import CourseLocator
class Command(BaseCommand):
"Delete a course from the split Mongo datastore"
"Rollback a course that was migrated to the split Mongo datastore"
help = "Delete a course from the split Mongo datastore"
help = "Rollback a course that was migrated to the split Mongo datastore"
args = "locator"
def handle(self, *args, **options):
if len(args) < 1:
raise CommandError(
"delete_split_course requires at least one argument (locator)"
"rollback_split_course requires at least one argument (locator)"
)
try:
......@@ -25,7 +25,27 @@ class Command(BaseCommand):
except ValueError:
raise CommandError("Invalid locator string {}".format(args[0]))
location = loc_mapper().translate_locator_to_location(locator, get_course=True)
if not location:
raise CommandError(
"This course does not exist in the old Mongo store. "
"This command is designed to rollback a course, not delete "
"it entirely."
)
old_mongo_course = modulestore('direct').get_item(location)
if not old_mongo_course:
raise CommandError(
"This course does not exist in the old Mongo store. "
"This command is designed to rollback a course, not delete "
"it entirely."
)
try:
modulestore('split').delete_course(locator.package_id)
except ItemNotFoundError:
raise CommandError("No course found with locator {}".format(locator))
print(
'Course rolled back successfully. To delete this course entirely, '
'call the "delete_course" management command.'
)
......@@ -2,27 +2,32 @@
Unittests for deleting a split mongo course
"""
import unittest
from StringIO import StringIO
from mock import patch
from django.contrib.auth.models import User
from django.core.management import CommandError, call_command
from django.test.utils import override_settings
from contentstore.management.commands.delete_split_course import Command
from contentstore.management.commands.rollback_split_course import Command
from contentstore.tests.modulestore_config import TEST_MODULESTORE
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.persistent_factories import PersistentCourseFactory
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.django import modulestore, loc_mapper
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.split_migrator import SplitMigrator
# pylint: disable=E1101
class TestArgParsing(unittest.TestCase):
"""
Tests for parsing arguments for the `delete_split_course` management command
Tests for parsing arguments for the `rollback_split_course` management command
"""
def setUp(self):
self.command = Command()
def test_no_args(self):
errstring = "delete_split_course requires at least one argument"
errstring = "rollback_split_course requires at least one argument"
with self.assertRaisesRegexp(CommandError, errstring):
self.command.handle()
......@@ -31,27 +36,73 @@ class TestArgParsing(unittest.TestCase):
with self.assertRaisesRegexp(CommandError, errstring):
self.command.handle("!?!")
def test_nonexistant_locator(self):
errstring = "No course found with locator course/branch/name"
with self.assertRaisesRegexp(CommandError, errstring):
self.command.handle("course/branch/name")
@override_settings(MODULESTORE=TEST_MODULESTORE)
class TestDeleteSplitCourse(ModuleStoreTestCase):
class TestRollbackSplitCourseNoOldMongo(ModuleStoreTestCase):
"""
Unit tests for deleting a split-mongo course from command line
Unit tests for rolling back a split-mongo course from command line
"""
def setUp(self):
super(TestDeleteSplitCourse, self).setUp()
super(TestRollbackSplitCourseNoOldMongo, self).setUp()
self.course = PersistentCourseFactory()
def test_happy_path(self):
def test_no_old_course(self):
locator = self.course.location
errstring = "course does not exist in the old Mongo store"
with self.assertRaisesRegexp(CommandError, errstring):
Command().handle(str(locator))
@override_settings(MODULESTORE=TEST_MODULESTORE)
class TestRollbackSplitCourseNoSplitMongo(ModuleStoreTestCase):
"""
Unit tests for rolling back a split-mongo course from command line
"""
def setUp(self):
super(TestRollbackSplitCourseNoSplitMongo, self).setUp()
self.old_course = CourseFactory()
def test_nonexistent_locator(self):
locator = loc_mapper().translate_location(self.old_course.id, self.old_course.location)
errstring = "No course found with locator"
with self.assertRaisesRegexp(CommandError, errstring):
Command().handle(str(locator))
@override_settings(MODULESTORE=TEST_MODULESTORE)
class TestRollbackSplitCourse(ModuleStoreTestCase):
"""
Unit tests for rolling back a split-mongo course from command line
"""
def setUp(self):
super(TestRollbackSplitCourse, self).setUp()
self.old_course = CourseFactory()
uname = 'testuser'
email = 'test+courses@edx.org'
password = 'foo'
self.user = User.objects.create_user(uname, email, password)
# migrate old course to split
migrator = SplitMigrator(
draft_modulestore=modulestore('default'),
direct_modulestore=modulestore('direct'),
split_modulestore=modulestore('split'),
loc_mapper=loc_mapper(),
)
migrator.migrate_mongo_course(self.old_course.location, self.user)
locator = loc_mapper().translate_location(self.old_course.id, self.old_course.location)
self.course = modulestore('split').get_course(locator)
@patch("sys.stdout", new_callable=StringIO)
def test_happy_path(self, mock_stdout):
locator = self.course.location
call_command(
"delete_split_course",
"rollback_split_course",
str(locator),
)
with self.assertRaises(ItemNotFoundError):
modulestore('split').get_course(locator)
self.assertIn("Course rolled back successfully", mock_stdout.getvalue())
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment