Skip to content

Commit

Permalink
feat: introduce 'tutor dev quickstart'
Browse files Browse the repository at this point in the history
Add `tutor dev quickstart` command, which is equivalent to
`tutor local quickstart`, but uses dev containers instead
of local production ones. This should remove some friction
from the Open edX development setup process, which previously
required that users provision using local producation
containers but then stop them and switch to dev containers:
 * tutor local quickstart
 * tutor local stop
 * tutor dev start -d

Fixes openedx-unsupported/wg-developer-experience#58
  • Loading branch information
kdmccormick committed Mar 31, 2022
1 parent fa32269 commit 5733c39
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 134 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Note: Breaking changes between versions are indicated by "💥".

## Unreleased

- [Feature] Add `tutor dev quickstart` command, which is equivalent to `tutor local quickstart`, but uses dev containers instead of local production ones. This should remove some friction from the Open edX development setup process, which previously required that users provision using local producation containers (`tutor local quickstart`) but then stop them and switch to dev containers (`tutor local stop && tutor dev start -d`).

## v13.1.8 (2022-03-18)

- [Bugfix] Fix "evalsymlink failure" during `k8s quickstart` (#611).
Expand Down
4 changes: 3 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ Quickstart
----------

1. Install the `latest stable release <https://github.com/overhangio/tutor/releases>`_ of Tutor
2. Run ``tutor local quickstart``
2. Run one of these commands:
* ``tutor local quickstart`` (for production deployment)
* ``tutor dev quickstart`` (for development)
3. You're done!

Documentation
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This section does not cover :ref:`plugin development <plugins>`. For simple chan
Configuration
-------------

With Tutor, all Open edX deployment parameters are stored in a single ``config.yml`` file. This is the file that is generated when you run ``tutor local quickstart`` or ``tutor config save``. To view the content of this file, run::
With Tutor, all Open edX deployment parameters are stored in a single ``config.yml`` file. This is the file that is generated when you run ``tutor ... quickstart`` or ``tutor config save``. To view the content of this file, run::

cat "$(tutor config printroot)/config.yml"

Expand Down
19 changes: 19 additions & 0 deletions tests/commands/test_compose.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import unittest

from click.testing import CliRunner

from tutor.commands.compose import quickstart, upgrade


class ComposeTests(unittest.TestCase):
def test_compose_quickstart_help(self) -> None:
runner = CliRunner()
result = runner.invoke(quickstart, ["--help"])
self.assertEqual(0, result.exit_code)
self.assertIsNone(result.exception)

def test_compose_upgrade_help(self) -> None:
runner = CliRunner()
result = runner.invoke(upgrade, ["--help"])
self.assertEqual(0, result.exit_code)
self.assertIsNone(result.exception)
14 changes: 1 addition & 13 deletions tests/commands/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from click.testing import CliRunner

from tutor.commands.local import local, quickstart, upgrade
from tutor.commands.local import local


class LocalTests(unittest.TestCase):
Expand All @@ -11,15 +11,3 @@ def test_local_help(self) -> None:
result = runner.invoke(local, ["--help"])
self.assertEqual(0, result.exit_code)
self.assertIsNone(result.exception)

def test_local_quickstart_help(self) -> None:
runner = CliRunner()
result = runner.invoke(quickstart, ["--help"])
self.assertEqual(0, result.exit_code)
self.assertIsNone(result.exception)

def test_local_upgrade_help(self) -> None:
runner = CliRunner()
result = runner.invoke(upgrade, ["--help"])
self.assertEqual(0, result.exit_code)
self.assertIsNone(result.exception)
116 changes: 115 additions & 1 deletion tutor/commands/compose.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import os
from typing import List
from typing import List, Optional

import click

from .. import bindmounts
from .. import config as tutor_config
from .. import env as tutor_env
from .. import fmt, jobs, utils

from ..exceptions import TutorError
from ..types import Config
from .config import save as config_save_command
from .context import BaseJobContext
from .upgrade.compose import upgrade_from


class ComposeJobRunner(jobs.BaseComposeJobRunner):
Expand Down Expand Up @@ -60,6 +63,91 @@ def job_runner(self, config: Config) -> ComposeJobRunner:
raise NotImplementedError


@click.command(help="Configure and run Open edX from scratch")
@click.option("-I", "--non-interactive", is_flag=True, help="Run non-interactively")
@click.option("-p", "--pullimages", is_flag=True, help="Update docker images")
@click.pass_context
def quickstart(context: click.Context, non_interactive: bool, pullimages: bool) -> None:
try:
utils.check_macos_docker_memory()
except 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"))
context.invoke(config_save_command, interactive=(not non_interactive))

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(stop)
if pullimages:
click.echo(fmt.title("Docker image updates"))
context.invoke(dc_command, command="pull")
click.echo(fmt.title("Starting the platform in detached mode"))
context.invoke(start, detach=True)
click.echo(fmt.title("Database creation and migrations"))
context.invoke(init)

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"],
)
)


@click.command(
short_help="Run all or a selection of services.",
help="Run all or a selection of services. Docker images will be rebuilt where necessary.",
Expand Down Expand Up @@ -263,6 +351,31 @@ def logs(context: click.Context, follow: bool, tail: bool, service: str) -> None
context.invoke(dc_command, command="logs", args=args)


@click.command(
short_help="Perform release-specific upgrade tasks",
help="Perform release-specific upgrade tasks. To perform a full upgrade remember to run `quickstart`.",
)
@click.option(
"--from",
"from_release",
type=click.Choice(["ironwood", "juniper", "koa", "lilac"]),
)
@click.pass_context
def upgrade(context: click.Context, from_release: Optional[str]) -> None:
fmt.echo_alert(
"This command only performs a partial upgrade of your Open edX platform. "
"To perform a full upgrade, you should run `tutor local quickstart`."
)
if from_release is None:
from_release = tutor_env.get_env_release(context.obj.root)
if from_release is None:
fmt.echo_info("Your environment is already up-to-date")
else:
upgrade_from(context, from_release)
# We update the environment to update the version
context.invoke(config_save_command)


@click.command(
short_help="Direct interface to docker-compose.",
help=(
Expand Down Expand Up @@ -294,6 +407,7 @@ def dc_command(context: BaseComposeContext, command: str, args: List[str]) -> No


def add_commands(command_group: click.Group) -> None:
command_group.add_command(quickstart)
command_group.add_command(start)
command_group.add_command(stop)
command_group.add_command(restart)
Expand Down
118 changes: 0 additions & 118 deletions tutor/commands/local.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
from typing import Optional

import click

from tutor import config as tutor_config
from tutor import env as tutor_env
from tutor import exceptions, fmt, utils
from tutor.commands import compose
from tutor.commands.config import save as config_save_command
from tutor.commands.upgrade.local import upgrade_from
from tutor.types import Config, get_typed


Expand Down Expand Up @@ -41,116 +35,4 @@ def local(context: click.Context) -> None:
context.obj = LocalContext(context.obj.root)


@click.command(help="Configure and run Open edX from scratch")
@click.option("-I", "--non-interactive", is_flag=True, help="Run non-interactively")
@click.option("-p", "--pullimages", is_flag=True, help="Update docker images")
@click.pass_context
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"""
)

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"))
context.invoke(config_save_command, interactive=(not non_interactive))

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, detach=True)
click.echo(fmt.title("Database creation and migrations"))
context.invoke(compose.init)

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"],
)
)


@click.command(
short_help="Perform release-specific upgrade tasks",
help="Perform release-specific upgrade tasks. To perform a full upgrade remember to run `quickstart`.",
)
@click.option(
"--from",
"from_release",
type=click.Choice(["ironwood", "juniper", "koa", "lilac"]),
)
@click.pass_context
def upgrade(context: click.Context, from_release: Optional[str]) -> None:
fmt.echo_alert(
"This command only performs a partial upgrade of your Open edX platform. "
"To perform a full upgrade, you should run `tutor local quickstart`."
)
if from_release is None:
from_release = tutor_env.get_env_release(context.obj.root)
if from_release is None:
fmt.echo_info("Your environment is already up-to-date")
else:
upgrade_from(context, from_release)
# We update the environment to update the version
context.invoke(config_save_command)


local.add_command(quickstart)
local.add_command(upgrade)
compose.add_commands(local)
File renamed without changes.

0 comments on commit 5733c39

Please sign in to comment.