def test_save_load(self, _: Mock) -> None: with tempfile.TemporaryDirectory() as root: config1 = tutor_config.load_minimal(root) tutor_config.save_config_file(root, config1) config2 = tutor_config.load_minimal(root) self.assertEqual(config1, config2)
def test_config_disable_plugin(self) -> None: plugins_v0.DictPlugin({ "name": "plugin1", "config": { "set": { "KEY1": "value1" } } }) plugins_v0.DictPlugin({ "name": "plugin2", "config": { "set": { "KEY2": "value2" } } }) plugins.load("plugin1") plugins.load("plugin2") with temporary_root() as root: config = tutor_config.load_minimal(root) config_pre = config.copy() with patch.object(fmt, "STDOUT"): hooks.Actions.PLUGIN_UNLOADED.do("plugin1", "", config) config_post = tutor_config.load_minimal(root) self.assertEqual("value1", config_pre["KEY1"]) self.assertEqual("value2", config_pre["KEY2"]) self.assertNotIn("KEY1", config) self.assertNotIn("KEY1", config_post) self.assertEqual("value2", config["KEY2"])
def test_update_twice_should_return_same_config(self, _: Mock) -> None: with temporary_root() as root: config1 = tutor_config.load_minimal(root) tutor_config.save_config_file(root, config1) config2 = tutor_config.load_minimal(root) self.assertEqual(config1, config2)
def enable(context: Context, plugin_names: t.List[str]) -> None: config = tutor_config.load_minimal(context.root) for plugin in plugin_names: plugins.load(plugin) fmt.echo_info(f"Plugin {plugin} enabled") tutor_config.save_enabled_plugins(config) tutor_config.save_config_file(context.root, config) fmt.echo_info( "You should now re-generate your environment with `tutor config save`." )
def quickstart(context: click.Context, non_interactive: bool) -> None: run_upgrade_from_release = tutor_env.should_upgrade_from_release( context.obj.root) if run_upgrade_from_release is not None: click.echo(fmt.title("Upgrading from an older release")) context.invoke( upgrade, from_release=tutor_env.get_env_release(context.obj.root), ) click.echo(fmt.title("Interactive platform configuration")) config = tutor_config.load_minimal(context.obj.root) if not non_interactive: interactive_config.ask_questions(config, run_for_prod=True) tutor_config.save_config_file(context.obj.root, config) config = tutor_config.load_full(context.obj.root) tutor_env.save(context.obj.root, config) if run_upgrade_from_release and not non_interactive: question = f"""Your platform is being upgraded from {run_upgrade_from_release.capitalize()}. If you run custom Docker images, you must rebuild and push them to your private repository now by running the following commands in a different shell: tutor images build all # add your custom images here tutor images push all Press enter when you are ready to continue""" click.confirm(fmt.question(question), default=True, abort=True, prompt_suffix=" ") click.echo(fmt.title("Starting the platform")) context.invoke(start) click.echo(fmt.title("Database creation and migrations")) context.invoke(init, limit=None) config = tutor_config.load(context.obj.root) fmt.echo_info( """Your Open edX platform is ready and can be accessed at the following urls: {http}://{lms_host} {http}://{cms_host} """.format( http="https" if config["ENABLE_HTTPS"] else "http", lms_host=config["LMS_HOST"], cms_host=config["CMS_HOST"], ))
def test_interactive(self) -> None: def mock_prompt(*_args: None, **kwargs: str) -> str: return kwargs["default"] with temporary_root() as rootdir: with patch.object(click, "prompt", new=mock_prompt): with patch.object(click, "confirm", new=mock_prompt): config = tutor_config.load_minimal(rootdir) interactive.ask_questions(config) self.assertIn("MYSQL_ROOT_PASSWORD", config) self.assertEqual(8, len(get_typed(config, "MYSQL_ROOT_PASSWORD", str))) self.assertEqual("www.myopenedx.com", config["LMS_HOST"]) self.assertEqual("studio.www.myopenedx.com", config["CMS_HOST"])
def disable(context: Context, plugin_names: t.List[str]) -> None: config = tutor_config.load_minimal(context.root) disable_all = "all" in plugin_names disabled: t.List[str] = [] for plugin in tutor_config.get_enabled_plugins(config): if disable_all or plugin in plugin_names: fmt.echo_info(f"Disabling plugin {plugin}...") hooks.Actions.PLUGIN_UNLOADED.do(plugin, context.root, config) disabled.append(plugin) fmt.echo_info(f"Plugin {plugin} disabled") if disabled: tutor_config.save_config_file(context.root, config) fmt.echo_info( "You should now re-generate your environment with `tutor config save`." )
def quickstart(context: click.Context, non_interactive: bool, pullimages: bool) -> None: try: utils.check_macos_docker_memory() except exceptions.TutorError as e: fmt.echo_alert( f"""Could not verify sufficient RAM allocation in Docker: {e} Tutor may not work if Docker is configured with < 4 GB RAM. Please follow instructions from: https://docs.tutor.overhang.io/install.html""" ) click.echo(fmt.title("Interactive platform configuration")) config = tutor_config.load_minimal(context.obj.root) if not non_interactive: interactive_config.ask_questions(config, run_for_prod=False) tutor_config.save_config_file(context.obj.root, config) config = tutor_config.load_full(context.obj.root) tutor_env.save(context.obj.root, config) click.echo(fmt.title("Stopping any existing platform")) context.invoke(compose.stop) if pullimages: click.echo(fmt.title("Docker image updates")) context.invoke(compose.dc_command, command="pull") click.echo(fmt.title("Building Docker image for LMS and CMS development")) context.invoke(compose.dc_command, command="build", args=["lms"]) click.echo(fmt.title("Starting the platform in detached mode")) context.invoke(compose.start, detach=True) click.echo(fmt.title("Database creation and migrations")) context.invoke(compose.init) fmt.echo_info( """The Open edX platform is now running in detached mode Your Open edX platform is ready and can be accessed at the following urls: {http}://{lms_host}:8000 {http}://{cms_host}:8001 """.format( http="https" if config["ENABLE_HTTPS"] else "http", lms_host=config["LMS_HOST"], cms_host=config["CMS_HOST"], ) )
def quickstart( context: click.Context, mounts: t.Tuple[t.List[compose.MountParam.MountType]], non_interactive: bool, pullimages: bool, ) -> None: try: utils.check_macos_docker_memory() except exceptions.TutorError as e: fmt.echo_alert( f"""Could not verify sufficient RAM allocation in Docker: {e} Tutor may not work if Docker is configured with < 4 GB RAM. Please follow instructions from: https://docs.tutor.overhang.io/install.html""") run_upgrade_from_release = tutor_env.should_upgrade_from_release( context.obj.root) if run_upgrade_from_release is not None: click.echo(fmt.title("Upgrading from an older release")) if not non_interactive: to_release = tutor_env.get_package_release() question = f"""You are about to upgrade your Open edX platform from {run_upgrade_from_release.capitalize()} to {to_release.capitalize()} It is strongly recommended to make a backup before upgrading. To do so, run: tutor local stop sudo rsync -avr "$(tutor config printroot)"/ /tmp/tutor-backup/ In case of problem, to restore your backup you will then have to run: sudo rsync -avr /tmp/tutor-backup/ "$(tutor config printroot)"/ Are you sure you want to continue?""" click.confirm(fmt.question(question), default=True, abort=True, prompt_suffix=" ") context.invoke( upgrade, from_release=run_upgrade_from_release, ) click.echo(fmt.title("Interactive platform configuration")) config = tutor_config.load_minimal(context.obj.root) if not non_interactive: interactive_config.ask_questions(config) tutor_config.save_config_file(context.obj.root, config) config = tutor_config.load_full(context.obj.root) tutor_env.save(context.obj.root, config) if run_upgrade_from_release and not non_interactive: question = f"""Your platform is being upgraded from {run_upgrade_from_release.capitalize()}. If you run custom Docker images, you must rebuild them now by running the following command in a different shell: tutor images build all # list your custom images here See the documentation for more information: https://docs.tutor.overhang.io/install.html#upgrading-to-a-new-open-edx-release Press enter when you are ready to continue""" click.confirm(fmt.question(question), default=True, abort=True, prompt_suffix=" ") click.echo(fmt.title("Stopping any existing platform")) context.invoke(compose.stop) if pullimages: click.echo(fmt.title("Docker image updates")) context.invoke(compose.dc_command, command="pull") click.echo(fmt.title("Starting the platform in detached mode")) context.invoke(compose.start, mounts=mounts, detach=True) click.echo(fmt.title("Database creation and migrations")) context.invoke(compose.init, mounts=mounts) config = tutor_config.load(context.obj.root) fmt.echo_info("""The Open edX platform is now running in detached mode Your Open edX platform is ready and can be accessed at the following urls: {http}://{lms_host} {http}://{cms_host} """.format( http="https" if config["ENABLE_HTTPS"] else "http", lms_host=config["LMS_HOST"], cms_host=config["CMS_HOST"], ))