Commit e0c1abc1 by David Baumgold

check for old mongo course

parent e18507f1
...@@ -49,6 +49,7 @@ coverage.xml ...@@ -49,6 +49,7 @@ coverage.xml
cover/ cover/
cover_html/ cover_html/
reports/ reports/
jscover.log
jscover.log.* jscover.log.*
### Installation artifacts ### Installation artifacts
......
...@@ -3,21 +3,21 @@ Django management command to rollback a migration to split. The way to do this ...@@ -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. is to delete the course from the split mongo datastore.
""" """
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore, loc_mapper
from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.exceptions import ItemNotFoundError, InsufficientSpecificationError
from xmodule.modulestore.locator import CourseLocator from xmodule.modulestore.locator import CourseLocator
class Command(BaseCommand): 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" args = "locator"
def handle(self, *args, **options): def handle(self, *args, **options):
if len(args) < 1: if len(args) < 1:
raise CommandError( raise CommandError(
"delete_split_course requires at least one argument (locator)" "rollback_split_course requires at least one argument (locator)"
) )
try: try:
...@@ -25,7 +25,27 @@ class Command(BaseCommand): ...@@ -25,7 +25,27 @@ class Command(BaseCommand):
except ValueError: except ValueError:
raise CommandError("Invalid locator string {}".format(args[0])) 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: try:
modulestore('split').delete_course(locator.package_id) modulestore('split').delete_course(locator.package_id)
except ItemNotFoundError: except ItemNotFoundError:
raise CommandError("No course found with locator {}".format(locator)) 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 @@ ...@@ -2,27 +2,32 @@
Unittests for deleting a split mongo course Unittests for deleting a split mongo course
""" """
import unittest 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.core.management import CommandError, call_command
from django.test.utils import override_settings 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 contentstore.tests.modulestore_config import TEST_MODULESTORE
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.persistent_factories import PersistentCourseFactory 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.exceptions import ItemNotFoundError
from xmodule.modulestore.split_migrator import SplitMigrator
# pylint: disable=E1101 # pylint: disable=E1101
class TestArgParsing(unittest.TestCase): 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): def setUp(self):
self.command = Command() self.command = Command()
def test_no_args(self): 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): with self.assertRaisesRegexp(CommandError, errstring):
self.command.handle() self.command.handle()
...@@ -31,27 +36,73 @@ class TestArgParsing(unittest.TestCase): ...@@ -31,27 +36,73 @@ class TestArgParsing(unittest.TestCase):
with self.assertRaisesRegexp(CommandError, errstring): with self.assertRaisesRegexp(CommandError, errstring):
self.command.handle("!?!") 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) @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): def setUp(self):
super(TestDeleteSplitCourse, self).setUp() super(TestRollbackSplitCourseNoOldMongo, self).setUp()
self.course = PersistentCourseFactory() 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 locator = self.course.location
call_command( call_command(
"delete_split_course", "rollback_split_course",
str(locator), str(locator),
) )
with self.assertRaises(ItemNotFoundError): with self.assertRaises(ItemNotFoundError):
modulestore('split').get_course(locator) modulestore('split').get_course(locator)
self.assertIn("Course rolled back successfully", mock_stdout.getvalue())
Markdown is supported
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