mirror of
https://github.com/ChristianLight/tutor.git
synced 2025-01-05 15:12:10 +00:00
v10.0.0 Upgrade to Juniper (2020-06-15)
Here, we upgrade the Open edX platform from Ironwood to Juniper. This upgrade does not come with many feature changes, but there are many technical improvements under the hood: - Upgrade from Python 2.7 to 3.5 - Upgrade from Mongodb v3.2 to v3.6 - Upgrade Ruby to 2.5.7 We took the opportunity to completely rething the way locally running platforms should be accessed for testing purposes. It is no longer possible to access a running platform from http://localhost and http://studio.localhost. Instead, users should access http://local.overhang.io and https://studio.local.overhang.io. This drastically simplifies internal communication between Docker containers. To upgrade, users should simply run: tutor local quickstart For Kubernetes platform, the upgrade process is outlined when running: tutor k8s upgrade --from=ironwood
This commit is contained in:
parent
5bbc196259
commit
4d6de0138a
@ -2,10 +2,11 @@
|
||||
|
||||
Note: Breaking changes between versions are indicated by "💥".
|
||||
|
||||
## Unreleased
|
||||
## v10.0.0 (2020-06-15)
|
||||
|
||||
- 💥[Improvement] Upgrade to Juniper 🍾
|
||||
- [Bugfix] Fix nginx resolver address to address container restarts
|
||||
- [Feature] Add `--limit=myplugin` option to `init` commands for limit execution of initialisation to certain services and plugins
|
||||
- [Feature] Add `--limit=myplugin` option to `init` commands to limit execution of initialisation to certain services and plugins
|
||||
|
||||
## v3.12.6 (2020-06-01)
|
||||
|
||||
|
3
Makefile
3
Makefile
@ -88,7 +88,8 @@ ci-bundle: bundle ## Create bundle and run basic tests
|
||||
yes "" | ./dist/tutor config save --interactive
|
||||
./dist/tutor config save
|
||||
./dist/tutor plugins list
|
||||
./dist/tutor plugins enable discovery ecommerce figures lts minio notes xqueue
|
||||
# ./dist/tutor plugins enable discovery ecommerce figures lts minio notes xqueue
|
||||
./dist/tutor plugins enable discovery ecommerce lts minio notes xqueue
|
||||
./dist/tutor plugins list
|
||||
./dist/tutor lts --help
|
||||
|
||||
|
@ -5,7 +5,7 @@ from tutor.plugins import OfficialPlugin
|
||||
for plugin_name in [
|
||||
"discovery",
|
||||
"ecommerce",
|
||||
"figures",
|
||||
# "figures",
|
||||
"lts",
|
||||
"minio",
|
||||
"notes",
|
||||
|
@ -207,7 +207,7 @@ openedx Docker Image build arguments
|
||||
When building the "openedx" Docker image, it is possible to specify a few `arguments <https://docs.docker.com/engine/reference/builder/#arg>`__:
|
||||
|
||||
- ``EDX_PLATFORM_REPOSITORY`` (default: ``"https://github.com/edx/edx-platform.git"``)
|
||||
- ``EDX_PLATFORM_VERSION`` (default: ``"open-release/ironwood.master"``)
|
||||
- ``EDX_PLATFORM_VERSION`` (default: ``"open-release/juniper.1"``)
|
||||
- ``EDX_PLATFORM_VERSION_DATE`` (default: ``"20200227"``)
|
||||
- ``NPM_REGISTRY`` (default: ``"https://registry.npmjs.org/"``)
|
||||
|
||||
@ -269,14 +269,14 @@ You may want to run your own flavor of edx-platform instead of the `official ver
|
||||
--build-arg EDX_PLATFORM_REPOSITORY=https://mygitrepo/edx-platform.git \
|
||||
--build-arg EDX_PLATFORM_VERSION=my-tag-or-branch
|
||||
|
||||
Note that your release must be a fork of Ironwood in order to work. Otherwise, you may have important compatibility issues with other services. In particular, **don't try to run Tutor with older versions of Open edX**.
|
||||
Note that your release must be a fork of the Juniper release in order to work. Otherwise, you may have important compatibility issues with other services. In particular, **don't try to run Tutor with older versions of Open edX**.
|
||||
|
||||
.. _i18n:
|
||||
|
||||
Adding custom translations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you are not running Open edX in English, chances are that some strings will not be properly translated. In most cases, this is because not enough contributors have helped translate Open edX in your language. It happens! With Tutor, available translated languages include those that come bundled with `edx-platform <https://github.com/edx/edx-platform/tree/open-release/ironwood.master/conf/locale>`__ as well as those from `openedx-i18n <https://github.com/openedx/openedx-i18n/tree/master/edx-platform/locale>`__.
|
||||
If you are not running Open edX in English, chances are that some strings will not be properly translated. In most cases, this is because not enough contributors have helped translate Open edX in your language. It happens! With Tutor, available translated languages include those that come bundled with `edx-platform <https://github.com/edx/edx-platform/tree/open-release/juniper.1/conf/locale>`__ as well as those from `openedx-i18n <https://github.com/openedx/openedx-i18n/tree/master/edx-platform/locale>`__.
|
||||
|
||||
Tutor offers a relatively simple mechanism to add custom translations to the openedx Docker image. You should create a folder that corresponds to your language code in the "build/openedx/locale" folder of the Tutor environment. This folder should contain a "LC_MESSAGES" folder. For instance::
|
||||
|
||||
@ -289,9 +289,9 @@ Then, add a "django.po" file there that will contain your custom translations::
|
||||
msgid "String to translate"
|
||||
msgstr "你翻译的东西 la traduction de votre bidule"
|
||||
|
||||
The "String to translate" part should match *exactly* the string that you would like to translate. You cannot make it up! The best way to find this string is to copy-paste it from the `upstream django.po file for the English language <https://github.com/edx/edx-platform/blob/open-release/ironwood.master/conf/locale/en/LC_MESSAGES/django.po>`__.
|
||||
The "String to translate" part should match *exactly* the string that you would like to translate. You cannot make it up! The best way to find this string is to copy-paste it from the `upstream django.po file for the English language <https://github.com/edx/edx-platform/blob/open-release/juniper.1/conf/locale/en/LC_MESSAGES/django.po>`__.
|
||||
|
||||
If you cannot find the string to translate in this file, then it means that you are trying to translate a string that is used in some piece of javascript code. Those strings are stored in a different file named "djangojs.po". You can check it out `in the edx-platform repo as well <https://github.com/edx/edx-platform/blob/open-release/ironwood.master/conf/locale/en/LC_MESSAGES/djangojs.po>`__. Your custom javascript strings should also be stored in a "djangojs.po" file that should be placed in the same directory.
|
||||
If you cannot find the string to translate in this file, then it means that you are trying to translate a string that is used in some piece of javascript code. Those strings are stored in a different file named "djangojs.po". You can check it out `in the edx-platform repo as well <https://github.com/edx/edx-platform/blob/open-release/juniper.1/conf/locale/en/LC_MESSAGES/djangojs.po>`__. Your custom javascript strings should also be stored in a "djangojs.po" file that should be placed in the same directory.
|
||||
|
||||
To recap, here is an example. To translate a few strings in French, both from django.po and djangojs.po, we would have the following file hierarchy::
|
||||
|
||||
|
23
docs/dev.rst
23
docs/dev.rst
@ -9,7 +9,9 @@ The following commands assume you have previously launched a :ref:`local <local>
|
||||
|
||||
tutor local quickstart
|
||||
|
||||
You should setup real host names for the LMS and the CMS (i.e: not "localhost"). It is not necessary to configure the DNS records for local development: in other words, it doesn't matter that the chosen domain names exist or not for your platform, as the LMS and the CMS will be accessed on ``localhost``. You should *not* activate HTTPS certificates, which will not work locally.
|
||||
In order to run the platform in development mode, you **must** answer no ("n") to the question "Are you configuring a production platform".
|
||||
|
||||
Note that the local.overhang.io `domain <https://dnschecker.org/#A/local.overhang.io>`__ and its `subdomains <https://dnschecker.org/#CNAME/studio.local.overhang.io>`__ all point to 127.0.0.1. This is just a domain name that was setup to conveniently access a locally running Open edX platform.
|
||||
|
||||
Once the local platform has been configured, you should stop it so that it does not interfere with the development environment::
|
||||
|
||||
@ -23,7 +25,7 @@ This ``openedx-dev`` development image differs from the ``openedx`` production i
|
||||
|
||||
- The user that runs inside the container has the same UID as the user on the host, in order to avoid permission problems inside mounted volumes (and in particular in the edx-platform repository).
|
||||
- Additional python and system requirements are installed for convenient debugging: `ipython <https://ipython.org/>`__, `ipdb <https://pypi.org/project/ipdb/>`__, vim, telnet.
|
||||
- The edx-platform `development requirements <https://github.com/edx/edx-platform/blob/open-release/ironwood.master/requirements/edx/development.in>`__ are installed.
|
||||
- The edx-platform `development requirements <https://github.com/edx/edx-platform/blob/open-release/juniper.1/requirements/edx/development.in>`__ are installed.
|
||||
|
||||
Since the ``openedx-dev`` is based upon the ``openedx`` docker image, it should be re-built every time the ``openedx`` docker image is modified.
|
||||
|
||||
@ -32,8 +34,8 @@ Run a local development webserver
|
||||
|
||||
::
|
||||
|
||||
tutor dev runserver lms # Access the lms at http://localhost:8000
|
||||
tutor dev runserver cms # Access the cms at http://localhost:8001
|
||||
tutor dev runserver lms # Access the lms at http://local.overhang.io:8000
|
||||
tutor dev runserver cms # Access the cms at http://studio.local.overhang.io:8001
|
||||
|
||||
Running arbitrary commands
|
||||
--------------------------
|
||||
@ -50,10 +52,9 @@ To open a python shell in the LMS or CMS, run::
|
||||
|
||||
You can then import edx-platform and django modules and execute python code.
|
||||
|
||||
To collect assets, you can use the standard ``update_assets`` Open edX command with the right settings::
|
||||
To collect assets, you can use the ``openedx-assets`` command that ships with Tutor::
|
||||
|
||||
tutor dev run lms paver update_assets --settings=tutor.development
|
||||
tutor dev run cms paver update_assets --settings=tutor.development
|
||||
tutor dev run openedx-assets --env=dev
|
||||
|
||||
Point to a local edx-platform
|
||||
-----------------------------
|
||||
@ -89,7 +90,7 @@ Then, add the following content::
|
||||
|
||||
This override file will be loaded when running any ``tutor dev ..`` command. The edx-platform repo mounted at the specified path will be automaticall mounted inside all LMS and CMS containers. With this file, you should no longer specify the ``-v`` option from the command line with the ``run`` or ``runserver`` commands.
|
||||
|
||||
**Note:** containers are built on the Ironwood release. If you are working on a different version of Open edX, you will have to rebuild the ``openedx`` docker images with the version. See the :ref:`fork edx-platform section <edx_platform_fork>`.
|
||||
**Note:** containers are built on the Juniper release. If you are working on a different version of Open edX, you will have to rebuild the ``openedx`` docker images with the version. See the :ref:`fork edx-platform section <edx_platform_fork>`.
|
||||
|
||||
Prepare the edx-platform repo
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -145,9 +146,9 @@ Then, run a local webserver::
|
||||
|
||||
tutor dev runserver lms
|
||||
|
||||
The LMS can then be accessed at http://localhost:8000. You will then have to :ref:`enable that theme <settheme>` for the development domain names::
|
||||
The LMS can then be accessed at http://local.overhang.io:8000. You will then have to :ref:`enable that theme <settheme>` for the development domain names::
|
||||
|
||||
tutor dev settheme mythemename localhost:8000 localhost:8001
|
||||
tutor dev settheme mythemename local.overhang.io:8000 studio.local.overhang.io:8001
|
||||
|
||||
Re-build development docker image (and compile assets)::
|
||||
|
||||
@ -157,7 +158,7 @@ Watch the themes folders for changes (in a different terminal)::
|
||||
|
||||
tutor dev run watchthemes
|
||||
|
||||
Make changes to some of the files inside the theme directory: the theme assets should be automatically recompiled and visible at http://localhost:8000.
|
||||
Make changes to some of the files inside the theme directory: the theme assets should be automatically recompiled and visible at http://local.overhang.io:8000.
|
||||
|
||||
Custom edx-platform settings
|
||||
----------------------------
|
||||
|
@ -39,18 +39,24 @@ This is the simplest and recommended installation method for most people. Note h
|
||||
|
||||
.. _install_source:
|
||||
|
||||
From source
|
||||
-----------
|
||||
Alternative installation methods
|
||||
--------------------------------
|
||||
|
||||
If you would like to inspect the Tutor source code, you are most welcome to install Tutor from `Pypi <https://pypi.org/project/tutor-openedx/>`_ or directly from `the Github repository <https://github.com/overhangio/tutor>`_. You will need python >= 3.6 and the libyaml development headers. On Ubuntu, these requirements can be installed by running::
|
||||
|
||||
sudo apt install python3 libyaml-dev
|
||||
|
||||
Installing from pypi::
|
||||
Installing from pypi
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
pip install tutor-openedx
|
||||
|
||||
Installing from a local clone of the repository::
|
||||
Installing from source
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
git clone https://github.com/overhangio/tutor
|
||||
cd tutor
|
||||
@ -59,7 +65,7 @@ Installing from a local clone of the repository::
|
||||
.. _cloud_install:
|
||||
|
||||
Zero-click AWS installation
|
||||
---------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Tutor can be launched on Amazon Web Services very quickly with the `official Tutor AMI <https://aws.amazon.com/marketplace/pp/B07PV3TB8X>`__. Shell access is not required, as all configuration will happen through the Tutor web user interface. For detailed installation instructions, we recommend watching the following video:
|
||||
|
||||
|
@ -47,7 +47,7 @@ On Minikube, run::
|
||||
|
||||
minikube addons enable ingress
|
||||
|
||||
With Kubernetes, your Open edX platform will *not* be available at localhost or studio.localhost. Instead, you will have to access your platform with the domain names you specified for the LMS and the CMS. To do so on a local computer, you will need to add the following line to /etc/hosts::
|
||||
With Kubernetes, your Open edX platform will *not* be available at localhost. Instead, you will have to access your platform with the domain names you specified for the LMS and the CMS. To do so on a local computer, you will need to add the following line to /etc/hosts::
|
||||
|
||||
MINIKUBEIP yourdomain.com studio.yourdomain.com preview.yourdomain.com notes.yourdomain.com
|
||||
|
||||
|
@ -12,6 +12,9 @@ In the following, environment and data files will be generated in a user-specifi
|
||||
export TUTOR_ROOT=/path/to/tutorroot
|
||||
tutor run ...
|
||||
|
||||
.. note::
|
||||
As of v10.0.0, a locally-running Open edX platform can no longer be accessed from http://localhost or http://studio.localhost. Instead, when running ``tutor local quickstart``, you must now decide whether you are running a platform that will be used in production. If not, the platform will be automatically be bound to http://local.overhang.io and http://studio.local.overhang.io, which are domain names that point to 127.0.0.1 (localhost). This change was made to facilitate internal communication between Docker containers.
|
||||
|
||||
Main commands
|
||||
-------------
|
||||
|
||||
@ -55,7 +58,7 @@ Running Open edX
|
||||
|
||||
tutor local start
|
||||
|
||||
This will launch the various docker containers required for your Open edX platform. The LMS and the Studio will then be reachable at the domain name you specified during the configuration step. You can also access them at http://localhost and http://studio.localhost.
|
||||
This will launch the various docker containers required for your Open edX platform. The LMS and the Studio will then be reachable at the domain name you specified during the configuration step.
|
||||
|
||||
To stop the running containers, just hit Ctrl+C.
|
||||
|
||||
@ -124,12 +127,9 @@ Setting a new theme
|
||||
|
||||
The default Open edX theme is rather bland, so Tutor makes it easy to switch to a different theme::
|
||||
|
||||
tutor local settheme mytheme localhost
|
||||
tutor local settheme mytheme $(tutor config printvalue LMS_HOST) $(tutor config printvalue CMS_HOST)
|
||||
|
||||
Notice the "localhost" argument: in Open edX, themes are assigned per domain name. That means that your custom theme will only be visible if you access your platform at http://localhost. So you might want to run this command with all possible domain names. For instance, to assign your custom theme both to the LMS and the studio, locally and in production, run::
|
||||
|
||||
tutor local settheme mytheme localhost studio.localhost \
|
||||
$(tutor config printvalue LMS_HOST) $(tutor config printvalue CMS_HOST)
|
||||
Notice that we pass the hostnames of the LMS and the CMS to the ``settheme`` command: this is because in Open edX, themes are assigned per domain name.
|
||||
|
||||
Out of the box, only the default "open-edx" theme is available. We also developed `Indigo, a beautiful, customizable theme <https://github.com/overhangio/indigo>`__ which is easy to install with Tutor.
|
||||
|
||||
|
@ -10,7 +10,7 @@ The ``podman`` CLI aims to be fully compatible with the ``docker`` CLI, and ``po
|
||||
|
||||
|
||||
Enabling Podman
|
||||
^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Podman is supported on a variety of development platforms, see the `installation instructions <https://podman.io/getting-started/installation>`_ for details.
|
||||
|
||||
@ -26,7 +26,7 @@ Once you have installed Podman and its dependencies on the platform of your choi
|
||||
|
||||
|
||||
Enabling podman-compose
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``podman-compose`` is available as a package from PyPI, and can thus be installed with ``pip``. See `its README <https://github.com/containers/podman-compose/blob/devel/README.md>`_ for installation instructions. Note that if you have installed Tutor in its own virtualenv, you'll need to run ``pip install podman-compose`` in that same virtualenv.
|
||||
|
||||
@ -42,7 +42,7 @@ Once installed, you'll again need to create a symbolic link that aliases ``docke
|
||||
|
||||
|
||||
Verifying your environment
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once you have configured your symbolic links as described, you should be able to run ``docker version`` and ``docker-compose --help`` and their output should agree, respectively, with ``podman version`` and ``podman-compose --help``.
|
||||
|
||||
|
@ -18,7 +18,7 @@ Yes :) This is what happens when you run ``tutor local quickstart``:
|
||||
2. Configuration files are generated from templates.
|
||||
3. Docker images are downloaded.
|
||||
4. Docker containers are provisioned.
|
||||
5. A full, production-ready Open edX platform (`Ironwood <https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/open-release-ironwood.master/platform_releases/ironwood.html#open-edx-ironwood-release>`__ release) is run with docker-compose.
|
||||
5. A full, production-ready Open edX platform (`Juniper <https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/open-release-juniper.master/platform_releases/juniper.html>`__ release) is run with docker-compose.
|
||||
|
||||
The whole procedure should require less than 10 minutes, on a server with a good bandwidth. Note that your host environment will not be affected in any way, since everything runs inside docker containers. Root access is not even necessary.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
User testimonials
|
||||
-----------------
|
||||
|
||||
*"Tutor simplifies the deployment of Open edX, so that we can directly focus on customizing our platform. Thanks a lot." -- Shashi Kiran G M
|
||||
*"Tutor simplifies the deployment of Open edX, so that we can directly focus on customizing our platform. Thanks a lot."* -- Shashi Kiran G M
|
||||
|
||||
*"Tutor is an absolutely fabulous initiative"* -- Lionel Meinertzhagen, Learning engineer - `Université Libre de Bruxelles <https://www.ulb.be/>`__
|
||||
|
||||
|
@ -101,11 +101,6 @@ The error produced should help you better understand what is happening.
|
||||
|
||||
This will occur if you try to run a development environment without patching the LOGGING configuration, as indicated in the `development_` section. Maybe you correctly patched the development settings, but they are not taken into account? For instance, you might have correctly defined the ``EDX_PLATFORM_SETTINGS`` environment variable, but ``paver`` uses the ``devstack`` settings (which does not patch the ``LOGGING`` variable). This is because calling ``paver lms --settings=development`` or ``paver cms --settings=development`` ignores the ``--settings`` argument. Yes, it might be considered an edx-platform bug... Instead, you should run the ``update_assets`` and ``runserver`` commands, as explained above.
|
||||
|
||||
"TypeError: get_logger_config() got an unexpected keyword argument 'debug'"
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
This might occur when you try to run the latest version of ``edx-platform``, and not a version close to ``ironwood.master``. It is no longer necessary to patch the ``LOGGING`` configuration in the latest ``edx-platform`` releases, as indicated in the `development_` section, so you should remove the call to ``get_logger_config`` altogether from your development settings.
|
||||
|
||||
The chosen default language does not display properly
|
||||
-----------------------------------------------------
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
appdirs
|
||||
click>=7.0
|
||||
click_repl
|
||||
pycryptodome
|
||||
jinja2>=2.9
|
||||
kubernetes
|
||||
pyyaml>=4.2b1
|
||||
|
@ -10,15 +10,16 @@ certifi==2020.4.5.1 # via kubernetes, requests
|
||||
chardet==3.0.4 # via requests
|
||||
click-repl==0.1.6
|
||||
click==7.1.1
|
||||
google-auth==1.14.0 # via kubernetes
|
||||
google-auth==1.14.1 # via kubernetes
|
||||
idna==2.9 # via requests
|
||||
jinja2==2.11.1
|
||||
jinja2==2.11.2
|
||||
kubernetes==11.0.0
|
||||
markupsafe==1.1.1 # via jinja2
|
||||
oauthlib==3.1.0 # via requests-oauthlib
|
||||
prompt-toolkit==3.0.5 # via click-repl
|
||||
pyasn1-modules==0.2.8 # via google-auth
|
||||
pyasn1==0.4.8 # via pyasn1-modules, rsa
|
||||
pycryptodome==3.9.7
|
||||
python-dateutil==2.8.1 # via kubernetes
|
||||
pyyaml==5.3.1
|
||||
requests-oauthlib==1.3.0 # via kubernetes
|
||||
|
@ -16,34 +16,35 @@ cffi==1.14.0 # via cryptography
|
||||
chardet==3.0.4
|
||||
click-repl==0.1.6
|
||||
click==7.1.1
|
||||
cryptography==2.8 # via secretstorage
|
||||
cryptography==2.9.2 # via secretstorage
|
||||
docutils==0.16 # via readme-renderer
|
||||
google-auth==1.14.0
|
||||
google-auth==1.14.1
|
||||
idna==2.9
|
||||
importlib-metadata==1.6.0 # via keyring, twine
|
||||
isort==4.3.21 # via pylint
|
||||
jeepney==0.4.3 # via keyring, secretstorage
|
||||
jinja2==2.11.1
|
||||
jinja2==2.11.2
|
||||
keyring==21.2.0 # via twine
|
||||
kubernetes==11.0.0
|
||||
lazy-object-proxy==1.4.3 # via astroid
|
||||
markupsafe==1.1.1
|
||||
mccabe==0.6.1 # via pylint
|
||||
oauthlib==3.1.0
|
||||
pathspec==0.7.0 # via black
|
||||
pip-tools==4.5.1
|
||||
pathspec==0.8.0 # via black
|
||||
pip-tools==5.0.0
|
||||
pkginfo==1.5.0.1 # via twine
|
||||
prompt-toolkit==3.0.5
|
||||
pyasn1-modules==0.2.8
|
||||
pyasn1==0.4.8
|
||||
pycparser==2.20 # via cffi
|
||||
pycryptodome==3.9.7
|
||||
pygments==2.6.1 # via readme-renderer
|
||||
pyinstaller==3.6
|
||||
pylint==2.4.4
|
||||
python-dateutil==2.8.1
|
||||
pyyaml==5.3.1
|
||||
readme-renderer==25.0 # via twine
|
||||
regex==2020.2.20 # via black
|
||||
readme-renderer==26.0 # via twine
|
||||
regex==2020.4.4 # via black
|
||||
requests-oauthlib==1.3.0
|
||||
requests-toolbelt==0.9.1 # via twine
|
||||
requests==2.23.0
|
||||
@ -51,7 +52,7 @@ rsa==4.0
|
||||
secretstorage==3.1.2 # via keyring
|
||||
six==1.14.0
|
||||
toml==0.10.0 # via black
|
||||
tqdm==4.44.1 # via twine
|
||||
tqdm==4.45.0 # via twine
|
||||
twine==3.1.1
|
||||
typed-ast==1.4.1 # via astroid, black
|
||||
urllib3==1.25.9
|
||||
@ -62,4 +63,5 @@ wrapt==1.11.2 # via astroid
|
||||
zipp==3.1.0 # via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# pip
|
||||
# setuptools
|
||||
|
@ -13,10 +13,10 @@ chardet==3.0.4
|
||||
click-repl==0.1.6
|
||||
click==7.1.1
|
||||
docutils==0.16 # via sphinx
|
||||
google-auth==1.14.0
|
||||
google-auth==1.14.1
|
||||
idna==2.9
|
||||
imagesize==1.2.0 # via sphinx
|
||||
jinja2==2.11.1
|
||||
jinja2==2.11.2
|
||||
kubernetes==11.0.0
|
||||
markupsafe==1.1.1
|
||||
oauthlib==3.1.0
|
||||
@ -24,8 +24,9 @@ packaging==20.3 # via sphinx
|
||||
prompt-toolkit==3.0.5
|
||||
pyasn1-modules==0.2.8
|
||||
pyasn1==0.4.8
|
||||
pycryptodome==3.9.7
|
||||
pygments==2.6.1 # via sphinx
|
||||
pyparsing==2.4.6 # via packaging
|
||||
pyparsing==2.4.7 # via packaging
|
||||
python-dateutil==2.8.1
|
||||
pytz==2019.3 # via babel
|
||||
pyyaml==5.3.1
|
||||
@ -35,7 +36,7 @@ rsa==4.0
|
||||
six==1.14.0
|
||||
snowballstemmer==2.0.0 # via sphinx
|
||||
sphinx-rtd-theme==0.4.3
|
||||
sphinx==2.4.4
|
||||
sphinx==3.0.3
|
||||
sphinxcontrib-applehelp==1.0.2 # via sphinx
|
||||
sphinxcontrib-devhelp==1.0.2 # via sphinx
|
||||
sphinxcontrib-htmlhelp==1.0.3 # via sphinx
|
||||
|
@ -1,6 +1,6 @@
|
||||
tutor-discovery
|
||||
tutor-ecommerce
|
||||
tutor-figures
|
||||
#tutor-figures
|
||||
tutor-lts
|
||||
tutor-minio
|
||||
tutor-notes
|
||||
|
@ -72,19 +72,22 @@ class EnvTests(unittest.TestCase):
|
||||
def test_save_full(self):
|
||||
defaults = tutor_config.load_defaults()
|
||||
with tempfile.TemporaryDirectory() as root:
|
||||
config = tutor_config.load_current(root, defaults)
|
||||
tutor_config.merge(config, defaults)
|
||||
with unittest.mock.patch.object(fmt, "STDOUT"):
|
||||
env.save(root, defaults)
|
||||
self.assertTrue(os.path.exists(os.path.join(root, "env", "version")))
|
||||
env.save(root, config)
|
||||
self.assertTrue(
|
||||
os.path.exists(os.path.join(root, "env", "local", "docker-compose.yml"))
|
||||
)
|
||||
|
||||
def test_save_full_with_https(self):
|
||||
defaults = tutor_config.load_defaults()
|
||||
defaults["ACTIVATE_HTTPS"] = True
|
||||
with tempfile.TemporaryDirectory() as root:
|
||||
config = tutor_config.load_current(root, defaults)
|
||||
tutor_config.merge(config, defaults)
|
||||
config["ACTIVATE_HTTPS"] = True
|
||||
with unittest.mock.patch.object(fmt, "STDOUT"):
|
||||
env.save(root, defaults)
|
||||
env.save(root, config)
|
||||
with open(os.path.join(root, "env", "apps", "nginx", "lms.conf")) as f:
|
||||
self.assertIn("ssl", f.read())
|
||||
|
||||
|
@ -1 +1 @@
|
||||
__version__ = "3.12.6"
|
||||
__version__ = "10.0.0"
|
||||
|
@ -4,6 +4,7 @@ import click
|
||||
|
||||
from . import compose
|
||||
from .context import Context
|
||||
from .. import config as tutor_config
|
||||
from .. import env as tutor_env
|
||||
from .. import fmt
|
||||
from .. import utils
|
||||
@ -15,7 +16,7 @@ class DevContext(Context):
|
||||
args = []
|
||||
for folder in ["local", "dev"]:
|
||||
# Add docker-compose.yml and docker-compose.override.yml (if it exists)
|
||||
# from "local" and "dev" folders
|
||||
# from "local" and "dev" folders (but not docker-compose.prod.yml)
|
||||
args += [
|
||||
"-f",
|
||||
tutor_env.pathjoin(root, folder, "docker-compose.yml"),
|
||||
@ -41,12 +42,15 @@ def dev(context):
|
||||
)
|
||||
@click.argument("options", nargs=-1, required=False)
|
||||
@click.argument("service")
|
||||
def runserver(options, service):
|
||||
@click.pass_obj
|
||||
def runserver(context, options, service):
|
||||
config = tutor_config.load(context.root)
|
||||
if service in ["lms", "cms"]:
|
||||
port = 8000 if service == "lms" else 8001
|
||||
host = config["LMS_HOST"] if service == "lms" else config["CMS_HOST"]
|
||||
fmt.echo_info(
|
||||
"The {} service will be available at http://localhost:{}".format(
|
||||
service, port
|
||||
"The {} service will be available at http://{}:{}".format(
|
||||
service, host, port
|
||||
)
|
||||
)
|
||||
args = ["--service-ports", *options, service]
|
||||
|
@ -201,6 +201,40 @@ def logs(context, container, follow, tail, service):
|
||||
utils.kubectl(*command)
|
||||
|
||||
|
||||
@click.command(help="Upgrade from a previous Open edX named release")
|
||||
@click.option(
|
||||
"--from", "from_version", default="ironwood", type=click.Choice(["ironwood"])
|
||||
)
|
||||
@click.pass_obj
|
||||
def upgrade(context, from_version):
|
||||
config = tutor_config.load(context.root)
|
||||
|
||||
if from_version == "ironwood":
|
||||
if not config["ACTIVATE_MONGODB"]:
|
||||
fmt.echo_info(
|
||||
"You are not running MongDB (ACTIVATE_MONGODB=false). It is your "
|
||||
"responsibility to upgrade your MongoDb instance to v3.6. There is "
|
||||
"nothing left to do."
|
||||
)
|
||||
return
|
||||
message = """Automatic release upgrade is unsupported in Kubernetes. To upgrade from Ironwood, you should upgrade your MongoDb cluster from v3.2 to v3.6. You should run something similar to:
|
||||
|
||||
# Upgrade from v3.2 to v3.4
|
||||
tutor k8s stop
|
||||
tutor config save --set DOCKER_IMAGE_MONGODB=mongo:3.4.24
|
||||
tutor k8s start
|
||||
tutor k8s exec mongodb mongo --eval 'db.adminCommand({ setFeatureCompatibilityVersion: "3.4" })'
|
||||
|
||||
# Upgrade from v3.4 to v3.6
|
||||
tutor k8s stop
|
||||
tutor config save --set DOCKER_IMAGE_MONGODB=mongo:3.6.18
|
||||
tutor k8s start
|
||||
tutor k8s exec mongodb mongo --eval 'db.adminCommand({ setFeatureCompatibilityVersion: "3.6" })'
|
||||
|
||||
tutor config save --unset DOCKER_IMAGE_MONGODB"""
|
||||
fmt.echo_info(message)
|
||||
|
||||
|
||||
class K8sClients:
|
||||
_instance = None
|
||||
|
||||
@ -392,3 +426,4 @@ k8s.add_command(importdemocourse)
|
||||
k8s.add_command(settheme)
|
||||
k8s.add_command(exec_command)
|
||||
k8s.add_command(logs)
|
||||
k8s.add_command(upgrade)
|
||||
|
@ -23,6 +23,8 @@ class LocalContext(Context):
|
||||
return utils.docker_compose(
|
||||
"-f",
|
||||
tutor_env.pathjoin(root, "local", "docker-compose.yml"),
|
||||
"-f",
|
||||
tutor_env.pathjoin(root, "local", "docker-compose.prod.yml"),
|
||||
*args,
|
||||
"--project-name",
|
||||
config["LOCAL_PROJECT_NAME"],
|
||||
@ -43,6 +45,13 @@ def local(context):
|
||||
)
|
||||
@click.pass_obj
|
||||
def quickstart(context, non_interactive, pullimages_):
|
||||
if tutor_env.needs_major_upgrade(context.root):
|
||||
click.echo(fmt.title("Upgrading from an older release"))
|
||||
upgrade.callback(
|
||||
from_version=tutor_env.current_release(context.root),
|
||||
non_interactive=non_interactive,
|
||||
)
|
||||
|
||||
click.echo(fmt.title("Interactive platform configuration"))
|
||||
config = interactive_config.update(context.root, interactive=(not non_interactive))
|
||||
click.echo(fmt.title("Updating the current environment"))
|
||||
@ -58,22 +67,17 @@ def quickstart(context, non_interactive, pullimages_):
|
||||
compose.start.callback(True, [])
|
||||
click.echo(fmt.title("Database creation and migrations"))
|
||||
compose.init.callback(limit=None)
|
||||
echo_platform_info(config)
|
||||
|
||||
|
||||
def echo_platform_info(config):
|
||||
fmt.echo_info("The Open edX platform is now running in detached mode")
|
||||
http = "https" if config["ACTIVATE_HTTPS"] else "http"
|
||||
urls = []
|
||||
if not config["ACTIVATE_HTTPS"] and not config["WEB_PROXY"]:
|
||||
urls += ["http://localhost", "http://studio.localhost"]
|
||||
urls.append("{http}://{lms_host}".format(http=http, lms_host=config["LMS_HOST"]))
|
||||
urls.append("{http}://{cms_host}".format(http=http, cms_host=config["CMS_HOST"]))
|
||||
fmt.echo_info(
|
||||
"""Your Open edX platform is ready and can be accessed at the following urls:
|
||||
"""The Open edX platform is now running in detached mode
|
||||
Your Open edX platform is ready and can be accessed at the following urls:
|
||||
|
||||
{}""".format(
|
||||
"\n ".join(urls)
|
||||
{http}://{lms_host}
|
||||
{http}://{cms_host}
|
||||
""".format(
|
||||
http="https" if config["ACTIVATE_HTTPS"] else "http",
|
||||
lms_host=config["LMS_HOST"],
|
||||
cms_host=config["CMS_HOST"],
|
||||
)
|
||||
)
|
||||
|
||||
@ -157,8 +161,81 @@ See the official certbot documentation for your platform: https://certbot.eff.or
|
||||
utils.docker_run(*docker_run)
|
||||
|
||||
|
||||
@click.command(help="Upgrade from a previous Open edX named release")
|
||||
@click.option(
|
||||
"--from", "from_version", default="ironwood", type=click.Choice(["ironwood"])
|
||||
)
|
||||
@click.option("-I", "--non-interactive", is_flag=True, help="Run non-interactively")
|
||||
@click.pass_obj
|
||||
def upgrade(context, from_version, non_interactive):
|
||||
config = tutor_config.load_no_check(context.root)
|
||||
|
||||
if not non_interactive:
|
||||
question = """You are about to upgrade your Open edX platform. 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=" "
|
||||
)
|
||||
|
||||
if from_version == "ironwood":
|
||||
upgrade_from_ironwood(context, config)
|
||||
|
||||
|
||||
def upgrade_from_ironwood(context, config):
|
||||
click.echo(fmt.title("Upgrading from Ironwood"))
|
||||
tutor_env.save(context.root, config)
|
||||
|
||||
click.echo(fmt.title("Stopping any existing platform"))
|
||||
compose.stop.callback([])
|
||||
|
||||
if not config["ACTIVATE_MONGODB"]:
|
||||
fmt.echo_info(
|
||||
"You are not running MongDB (ACTIVATE_MONGODB=false). It is your "
|
||||
"responsibility to upgrade your MongoDb instance to v3.6. There is "
|
||||
"nothing left to do."
|
||||
)
|
||||
return
|
||||
|
||||
# Note that the DOCKER_IMAGE_MONGODB value is never saved, because we only save the
|
||||
# environment, not the configuration.
|
||||
click.echo(fmt.title("Upgrading MongoDb from v3.2 to v3.4"))
|
||||
config["DOCKER_IMAGE_MONGODB"] = "mongo:3.4.24"
|
||||
tutor_env.save(context.root, config)
|
||||
compose.start.callback(detach=True, services=["mongodb"])
|
||||
compose.execute.callback(
|
||||
[
|
||||
"mongodb",
|
||||
"mongo",
|
||||
"--eval",
|
||||
'db.adminCommand({ setFeatureCompatibilityVersion: "3.4" })',
|
||||
]
|
||||
)
|
||||
compose.stop.callback([])
|
||||
|
||||
click.echo(fmt.title("Upgrading MongoDb from v3.4 to v3.6"))
|
||||
config["DOCKER_IMAGE_MONGODB"] = "mongo:3.6.18"
|
||||
tutor_env.save(context.root, config)
|
||||
compose.start.callback(detach=True, services=["mongodb"])
|
||||
compose.execute.callback(
|
||||
[
|
||||
"mongodb",
|
||||
"mongo",
|
||||
"--eval",
|
||||
'db.adminCommand({ setFeatureCompatibilityVersion: "3.6" })',
|
||||
]
|
||||
)
|
||||
compose.stop.callback([])
|
||||
|
||||
|
||||
https.add_command(https_create)
|
||||
https.add_command(https_renew)
|
||||
local.add_command(https)
|
||||
local.add_command(quickstart)
|
||||
local.add_command(upgrade)
|
||||
compose.add_commands(local)
|
||||
|
@ -24,6 +24,10 @@ def load(root):
|
||||
configuration in the project root.
|
||||
"""
|
||||
check_existing_config(root)
|
||||
return load_no_check(root)
|
||||
|
||||
|
||||
def load_no_check(root):
|
||||
config, defaults = load_all(root)
|
||||
merge(config, defaults)
|
||||
return config
|
||||
@ -101,6 +105,7 @@ def load_required(config, defaults):
|
||||
"OPENEDX_MYSQL_PASSWORD",
|
||||
"ANDROID_OAUTH2_SECRET",
|
||||
"ID",
|
||||
"JWT_RSA_PRIVATE_KEY",
|
||||
]:
|
||||
if key not in config:
|
||||
config[key] = env.render_unknown(config, defaults[key])
|
||||
|
23
tutor/env.py
23
tutor/env.py
@ -51,10 +51,13 @@ class Renderer:
|
||||
environment.filters["common_domain"] = utils.common_domain
|
||||
environment.filters["encrypt"] = utils.encrypt
|
||||
environment.filters["list_if"] = utils.list_if
|
||||
environment.filters["long_to_base64"] = utils.long_to_base64
|
||||
environment.filters["random_string"] = utils.random_string
|
||||
environment.filters["reverse_host"] = utils.reverse_host
|
||||
environment.filters["rsa_private_key"] = utils.rsa_private_key
|
||||
environment.filters["walk_templates"] = self.walk_templates
|
||||
environment.globals["patch"] = self.patch
|
||||
environment.globals["rsa_import_key"] = utils.rsa_import_key
|
||||
environment.globals["TUTOR_VERSION"] = __version__
|
||||
self.environment = environment
|
||||
|
||||
@ -293,14 +296,30 @@ def is_up_to_date(root):
|
||||
return current_version(root) == __version__
|
||||
|
||||
|
||||
def needs_major_upgrade(root):
|
||||
"""
|
||||
Return the current version as a tuple of int. E.g: (1, 0, 2).
|
||||
"""
|
||||
current = int(current_version(root).split(".")[0])
|
||||
required = int(__version__.split(".")[0])
|
||||
return current < required
|
||||
|
||||
|
||||
def current_release(root):
|
||||
"""
|
||||
Return the name of the current Open edX release.
|
||||
"""
|
||||
return {"3": "ironwood", "10": "juniper"}[current_version(root).split(".")[0]]
|
||||
|
||||
|
||||
def current_version(root):
|
||||
"""
|
||||
Return the current environment version. If the current environment has no version,
|
||||
return "0".
|
||||
return "0.0.0".
|
||||
"""
|
||||
path = pathjoin(root, VERSION_FILENAME)
|
||||
if not os.path.exists(path):
|
||||
return "0"
|
||||
return "0.0.0"
|
||||
return open(path).read().strip()
|
||||
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
import os
|
||||
|
||||
import click
|
||||
|
||||
from . import config as tutor_config
|
||||
from . import env
|
||||
from . import exceptions
|
||||
from . import fmt
|
||||
from .__about__ import __version__
|
||||
|
||||
@ -22,16 +21,41 @@ def load_all(root, interactive=True):
|
||||
"""
|
||||
Load configuration and interactively ask questions to collect param values from the user.
|
||||
"""
|
||||
defaults = tutor_config.load_defaults()
|
||||
config = tutor_config.load_current(root, defaults)
|
||||
config, defaults = tutor_config.load_all(root)
|
||||
if interactive:
|
||||
ask_questions(config, defaults)
|
||||
return config, defaults
|
||||
|
||||
|
||||
def ask_questions(config, defaults):
|
||||
ask("Your website domain name for students (LMS)", "LMS_HOST", config, defaults)
|
||||
ask("Your website domain name for teachers (CMS)", "CMS_HOST", config, defaults)
|
||||
run_for_prod = click.confirm(
|
||||
fmt.question(
|
||||
"Are you configuring a production platform? Type 'n' if you are just testing Tutor on your local computer"
|
||||
),
|
||||
prompt_suffix=" ",
|
||||
default=True,
|
||||
)
|
||||
if not run_for_prod:
|
||||
dev_values = {
|
||||
"LMS_HOST": "local.overhang.io",
|
||||
"CMS_HOST": "studio.local.overhang.io",
|
||||
"ACTIVATE_HTTPS": False,
|
||||
}
|
||||
fmt.echo_info(
|
||||
"""As you are not running this platform in production, we automatically set the following configuration values:"""
|
||||
)
|
||||
for k, v in dev_values.items():
|
||||
config[k] = v
|
||||
fmt.echo_info(" {} = {}".format(k, v))
|
||||
|
||||
if run_for_prod:
|
||||
ask("Your website domain name for students (LMS)", "LMS_HOST", config, defaults)
|
||||
if "localhost" in config["LMS_HOST"]:
|
||||
raise exceptions.TutorError(
|
||||
"You may not use 'localhost' as the LMS domain name. To run a local platform for testing purposes you should answer 'n' to the previous question."
|
||||
)
|
||||
ask("Your website domain name for teachers (CMS)", "CMS_HOST", config, defaults)
|
||||
|
||||
ask("Your platform name/title", "PLATFORM_NAME", config, defaults)
|
||||
ask("Your public contact email address", "CONTACT_EMAIL", config, defaults)
|
||||
ask_choice(
|
||||
@ -119,15 +143,16 @@ def ask_questions(config, defaults):
|
||||
"zh-tw",
|
||||
],
|
||||
)
|
||||
ask_bool(
|
||||
(
|
||||
"Activate SSL/TLS certificates for HTTPS access? Important note:"
|
||||
" this will NOT work in a development environment."
|
||||
),
|
||||
"ACTIVATE_HTTPS",
|
||||
config,
|
||||
defaults,
|
||||
)
|
||||
if run_for_prod:
|
||||
ask_bool(
|
||||
(
|
||||
"Activate SSL/TLS certificates for HTTPS access? Important note:"
|
||||
" this will NOT work in a development environment."
|
||||
),
|
||||
"ACTIVATE_HTTPS",
|
||||
config,
|
||||
defaults,
|
||||
)
|
||||
|
||||
|
||||
def ask(question, key, config, defaults):
|
||||
|
@ -1,10 +1,10 @@
|
||||
# See docs: https://openedx.atlassian.net/wiki/spaces/LEARNER/pages/48792067/App+Configuration+Flags
|
||||
API_HOST_URL: '{{ "https" if ACTIVATE_HTTPS else "http" }}://{{ LMS_HOST }}'
|
||||
ENVIRONMENT_DISPLAY_NAME: 'tutor'
|
||||
PLATFORM_NAME: '{{ PLATFORM_NAME }}'
|
||||
PLATFORM_DESTINATION_NAME: '{{ LMS_HOST }}'
|
||||
FEEDBACK_EMAIL_ADDRESS: 'support@{{ LMS_HOST }}'
|
||||
OAUTH_CLIENT_ID: 'android'
|
||||
API_HOST_URL: "{{ "https" if ACTIVATE_HTTPS else "http" }}://{{ LMS_HOST }}"
|
||||
ENVIRONMENT_DISPLAY_NAME: "tutor"
|
||||
PLATFORM_NAME: "{{ PLATFORM_NAME }}"
|
||||
PLATFORM_DESTINATION_NAME: "{{ LMS_HOST }}"
|
||||
FEEDBACK_EMAIL_ADDRESS: "{{ CONTACT_EMAIL }}"
|
||||
OAUTH_CLIENT_ID: "android"
|
||||
|
||||
COURSE_VIDEOS_ENABLED: true
|
||||
CERTIFICATES_ENABLED: true
|
||||
|
@ -13,7 +13,7 @@ server {
|
||||
|
||||
server {
|
||||
{% if ACTIVATE_HTTPS %}listen 443 {{ "" if WEB_PROXY else "ssl" }};{% else %}listen 80;{% endif %}
|
||||
server_name studio.localhost {{ CMS_HOST }};
|
||||
server_name {{ CMS_HOST }};
|
||||
|
||||
{% if ACTIVATE_HTTPS and not WEB_PROXY %}
|
||||
ssl_certificate /etc/letsencrypt/live/{{ LMS_HOST }}/fullchain.pem;
|
||||
|
@ -14,7 +14,7 @@ server {
|
||||
|
||||
server {
|
||||
{% if ACTIVATE_HTTPS %}listen 443 {{ "" if WEB_PROXY else "ssl" }};{% else %}listen 80;{% endif %}
|
||||
server_name localhost preview.localhost {{ LMS_HOST }} preview.{{ LMS_HOST }};
|
||||
server_name {{ LMS_HOST }} preview.{{ LMS_HOST }};
|
||||
|
||||
{% if ACTIVATE_HTTPS and not WEB_PROXY %}
|
||||
ssl_certificate /etc/letsencrypt/live/{{ LMS_HOST }}/fullchain.pem;
|
||||
|
@ -1 +0,0 @@
|
||||
{% include "apps/openedx/config/partials/auth.json" %}
|
@ -10,8 +10,8 @@
|
||||
{{ patch("cms-env-features", separator=",\n", suffix=",")|indent(4) }}
|
||||
"CERTIFICATES_HTML_VIEW": true,
|
||||
"PREVIEW_LMS_BASE": "preview.{{ LMS_HOST }}",
|
||||
"DISABLE_STUDIO_SSO_OVER_LMS": {{ "false" if ACTIVATE_HTTPS else "true" }},
|
||||
"ENABLE_COURSEWARE_INDEX": true,
|
||||
"ENABLE_CSMH_EXTENDED": false,
|
||||
"ENABLE_LIBRARY_INDEX": true
|
||||
},
|
||||
"LMS_ROOT_URL": "{{ "https" if ACTIVATE_HTTPS else "http" }}://{{ LMS_HOST }}",
|
||||
@ -24,6 +24,7 @@
|
||||
"CELERY_BROKER_USER": "{{ RABBITMQ_USERNAME }}",
|
||||
"CELERY_BROKER_PASSWORD": "{{ RABBITMQ_PASSWORD }}",
|
||||
"ALTERNATE_WORKER_QUEUES": "lms",
|
||||
"ENABLE_COMPREHENSIVE_THEMING": true,
|
||||
"COMPREHENSIVE_THEME_DIRS": ["/openedx/themes"],
|
||||
"STATIC_ROOT_BASE": "/openedx/staticfiles",
|
||||
"ELASTIC_SEARCH_CONFIG": [{
|
||||
@ -37,7 +38,7 @@
|
||||
"EMAIL_USE_TLS": {{ "true" if SMTP_USE_TLS else "false" }},
|
||||
"HTTPS": "{{ "on" if ACTIVATE_HTTPS else "off" }}",
|
||||
"LANGUAGE_CODE": "{{ LANGUAGE_CODE }}",
|
||||
{% if ACTIVATE_HTTPS %}"SESSION_COOKIE_DOMAIN": ".{{ LMS_HOST|common_domain(CMS_HOST) }}",{% endif %}
|
||||
"SESSION_COOKIE_DOMAIN": ".{{ LMS_HOST|common_domain(CMS_HOST) }}",
|
||||
{{ patch("cms-env", separator=",\n", suffix=",")|indent(2) }}
|
||||
"CACHES": {
|
||||
"default": {
|
||||
@ -86,5 +87,6 @@
|
||||
"KEY_FUNCTION": "util.memcache.safe_key",
|
||||
"LOCATION": "{{ MEMCACHED_HOST }}:{{ MEMCACHED_PORT }}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{% include "apps/openedx/config/partials/auth.json" %}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
{% include "apps/openedx/config/partials/auth.json" %}
|
@ -12,11 +12,13 @@
|
||||
"PREVIEW_LMS_BASE": "preview.{{ LMS_HOST }}",
|
||||
"ENABLE_COURSE_DISCOVERY": true,
|
||||
"ENABLE_COURSEWARE_SEARCH": true,
|
||||
"ENABLE_CSMH_EXTENDED": false,
|
||||
"ENABLE_DASHBOARD_SEARCH": true,
|
||||
"ENABLE_COMBINED_LOGIN_REGISTRATION": true,
|
||||
"ENABLE_GRADE_DOWNLOADS": true,
|
||||
"ENABLE_MOBILE_REST_API": true,
|
||||
"ENABLE_OAUTH2_PROVIDER": true
|
||||
"ENABLE_OAUTH2_PROVIDER": true,
|
||||
"ENABLE_THIRD_PARTY_AUTH": true
|
||||
},
|
||||
"LMS_ROOT_URL": "{{ "https" if ACTIVATE_HTTPS else "http" }}://{{ LMS_HOST }}",
|
||||
"CMS_ROOT_URL": "{{ "https" if ACTIVATE_HTTPS else "http" }}://{{ CMS_HOST }}",
|
||||
@ -29,6 +31,7 @@
|
||||
"CELERY_BROKER_PASSWORD": "{{ RABBITMQ_PASSWORD }}",
|
||||
"COMMENTS_SERVICE_URL": "http://{{ FORUM_HOST }}:4567",
|
||||
"COMMENTS_SERVICE_KEY": "forumapikey",
|
||||
"ENABLE_COMPREHENSIVE_THEMING": true,
|
||||
"COMPREHENSIVE_THEME_DIRS": ["/openedx/themes"],
|
||||
"STATIC_ROOT_BASE": "/openedx/staticfiles",
|
||||
"ELASTIC_SEARCH_CONFIG": [{
|
||||
@ -42,8 +45,7 @@
|
||||
"EMAIL_USE_TLS": {{ "true" if SMTP_USE_TLS else "false" }},
|
||||
"HTTPS": "{{ "on" if ACTIVATE_HTTPS else "off" }}",
|
||||
"LANGUAGE_CODE": "{{ LANGUAGE_CODE }}",
|
||||
"LOGIN_REDIRECT_WHITELIST": ["{{ CMS_HOST }}", "studio.localhost"],
|
||||
{% if ACTIVATE_HTTPS %}"SESSION_COOKIE_DOMAIN": ".{{ LMS_HOST|common_domain(CMS_HOST) }}",{% endif %}
|
||||
"SESSION_COOKIE_DOMAIN": ".{{ LMS_HOST|common_domain(CMS_HOST) }}",
|
||||
{{ patch("lms-env", separator=",\n", suffix=",")|indent(2) }}
|
||||
"CACHES": {
|
||||
"default": {
|
||||
@ -98,5 +100,6 @@
|
||||
"KEY_FUNCTION": "util.memcache.safe_key",
|
||||
"LOCATION": "{{ MEMCACHED_HOST }}:{{ MEMCACHED_PORT }}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{% include "apps/openedx/config/partials/auth.json" %}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
{
|
||||
"SECRET_KEY": "{{ OPENEDX_SECRET_KEY }}",
|
||||
"AWS_ACCESS_KEY_ID": "{{ OPENEDX_AWS_ACCESS_KEY }}",
|
||||
"AWS_SECRET_ACCESS_KEY": "{{ OPENEDX_AWS_SECRET_ACCESS_KEY }}",
|
||||
{{ patch("openedx-auth", separator=",\n", suffix=",")|indent(2) }}
|
||||
"XQUEUE_INTERFACE": {
|
||||
"django_auth": null,
|
||||
"url": null
|
||||
"django_auth": null,
|
||||
"url": null
|
||||
},
|
||||
"CONTENTSTORE": {
|
||||
"ENGINE": "xmodule.contentstore.mongo.MongoContentStore",
|
||||
@ -25,6 +24,9 @@
|
||||
{% if MONGODB_USERNAME and MONGODB_PASSWORD %}
|
||||
"user": "{{ MONGODB_USERNAME }}",
|
||||
"password": "{{ MONGODB_PASSWORD }}",
|
||||
{% else %}
|
||||
"user": null,
|
||||
"password": null,
|
||||
{% endif %}
|
||||
"db": "{{ MONGODB_DATABASE }}"
|
||||
},
|
||||
@ -38,10 +40,9 @@
|
||||
"PASSWORD": "{{ OPENEDX_MYSQL_PASSWORD }}",
|
||||
"ATOMIC_REQUESTS": true,
|
||||
"OPTIONS": {
|
||||
"init_command": "SET sql_mode='STRICT_TRANS_TABLES'"
|
||||
"init_command": "SET sql_mode='STRICT_TRANS_TABLES'"
|
||||
}
|
||||
}
|
||||
},
|
||||
"EMAIL_HOST_USER": "{{ SMTP_USERNAME }}",
|
||||
"EMAIL_HOST_PASSWORD": "{{ SMTP_PASSWORD }}"
|
||||
}
|
||||
"EMAIL_HOST_PASSWORD": "{{ SMTP_PASSWORD }}"
|
@ -2,10 +2,14 @@
|
||||
import os
|
||||
from cms.envs.devstack import *
|
||||
|
||||
LMS_BASE = "{{ LMS_HOST }}:8000"
|
||||
LMS_ROOT_URL = "http://" + LMS_BASE
|
||||
FEATURES["PREVIEW_LMS_BASE"] = "preview." + LMS_BASE
|
||||
|
||||
{% include "apps/openedx/settings/partials/common_cms.py" %}
|
||||
|
||||
# Setup correct webpack configuration file for development
|
||||
WEBPACK_CONFIG_PATH = "webpack.dev.config.js"
|
||||
|
||||
{{ patch("openedx-development-settings") }}
|
||||
{{ patch("openedx-cms-development-settings") }}
|
||||
{{ patch("openedx-cms-development-settings") }}
|
||||
|
@ -7,9 +7,6 @@ from cms.envs.production import *
|
||||
ALLOWED_HOSTS = [
|
||||
ENV_TOKENS.get("CMS_BASE"),
|
||||
"cms",
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
"studio.localhost",
|
||||
]
|
||||
|
||||
{{ patch("openedx-cms-production-settings") }}
|
||||
|
@ -7,5 +7,18 @@ from lms.envs.devstack import *
|
||||
# Setup correct webpack configuration file for development
|
||||
WEBPACK_CONFIG_PATH = "webpack.dev.config.js"
|
||||
|
||||
SESSION_COOKIE_DOMAIN = ".{{ LMS_HOST|common_domain(CMS_HOST) }}"
|
||||
|
||||
CMS_BASE = "{{ CMS_HOST}}:8001"
|
||||
CMS_ROOT_URL = "http://{}".format(CMS_BASE)
|
||||
LOGIN_REDIRECT_WHITELIST.append(CMS_BASE)
|
||||
|
||||
FEATURES['ENABLE_COURSEWARE_MICROFRONTEND'] = False
|
||||
|
||||
LOGGING["loggers"]["oauth2_provider"] = {
|
||||
"handlers": ["console"],
|
||||
"level": "DEBUG"
|
||||
}
|
||||
|
||||
{{ patch("openedx-development-settings") }}
|
||||
{{ patch("openedx-lms-development-settings") }}
|
||||
|
@ -8,9 +8,6 @@ ALLOWED_HOSTS = [
|
||||
ENV_TOKENS.get("LMS_BASE"),
|
||||
FEATURES["PREVIEW_LMS_BASE"],
|
||||
"lms",
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
"preview.localhost",
|
||||
]
|
||||
|
||||
# Required to display all courses on start page
|
||||
|
@ -1,4 +1,6 @@
|
||||
####### Settings common to LMS and CMS
|
||||
import json
|
||||
import os
|
||||
|
||||
DEFAULT_FROM_EMAIL = ENV_TOKENS["CONTACT_EMAIL"]
|
||||
DEFAULT_FEEDBACK_EMAIL = ENV_TOKENS["CONTACT_EMAIL"]
|
||||
@ -15,6 +17,9 @@ API_ACCESS_FROM_EMAIL = ENV_TOKENS["CONTACT_EMAIL"]
|
||||
|
||||
# Load module store settings from config files
|
||||
update_module_store_settings(MODULESTORE, doc_store_settings=DOC_STORE_CONFIG)
|
||||
DATA_DIR = "/openedx/data/"
|
||||
for store in MODULESTORE["default"]["OPTIONS"]["stores"]:
|
||||
store["OPTIONS"]["fs_root"] = DATA_DIR
|
||||
|
||||
# Set uploaded media file path
|
||||
MEDIA_ROOT = "/openedx/media/"
|
||||
@ -23,6 +28,10 @@ MEDIA_ROOT = "/openedx/media/"
|
||||
VIDEO_IMAGE_SETTINGS["STORAGE_KWARGS"]["location"] = MEDIA_ROOT
|
||||
VIDEO_TRANSCRIPTS_SETTINGS["STORAGE_KWARGS"]["location"] = MEDIA_ROOT
|
||||
|
||||
ORA2_FILEUPLOAD_BACKEND = "filesystem"
|
||||
ORA2_FILEUPLOAD_ROOT = "/openedx/data/ora2"
|
||||
ORA2_FILEUPLOAD_CACHE_NAME = "ora2-storage"
|
||||
|
||||
# Change syslog-based loggers which don't work inside docker containers
|
||||
LOGGING["handlers"]["local"] = {
|
||||
"class": "logging.handlers.WatchedFileHandler",
|
||||
@ -36,6 +45,15 @@ LOGGING["handlers"]["tracking"] = {
|
||||
"formatter": "standard",
|
||||
}
|
||||
LOGGING["loggers"]["tracking"]["handlers"] = ["console", "local", "tracking"]
|
||||
# Disable django/drf deprecation warnings
|
||||
import logging
|
||||
import warnings
|
||||
from django.utils.deprecation import RemovedInDjango30Warning, RemovedInDjango31Warning
|
||||
from rest_framework import RemovedInDRF310Warning, RemovedInDRF311Warning
|
||||
warnings.simplefilter('ignore', RemovedInDjango30Warning)
|
||||
warnings.simplefilter('ignore', RemovedInDjango31Warning)
|
||||
warnings.simplefilter('ignore', RemovedInDRF310Warning)
|
||||
warnings.simplefilter('ignore', RemovedInDRF311Warning)
|
||||
|
||||
# Email
|
||||
EMAIL_USE_SSL = {{ SMTP_USE_SSL }}
|
||||
@ -51,5 +69,40 @@ LOCALE_PATHS.append("/openedx/locale/user/locale")
|
||||
# Allow the platform to include itself in an iframe
|
||||
X_FRAME_OPTIONS = "SAMEORIGIN"
|
||||
|
||||
{% set jwt_rsa_key = rsa_import_key(JWT_RSA_PRIVATE_KEY) %}
|
||||
JWT_AUTH["JWT_ISSUER"] = "{{ JWT_COMMON_ISSUER }}"
|
||||
JWT_AUTH["JWT_AUDIENCE"] = "{{ JWT_COMMON_AUDIENCE }}"
|
||||
JWT_AUTH["JWT_SECRET_KEY"] = "{{ JWT_COMMON_SECRET_KEY }}"
|
||||
JWT_AUTH["JWT_PRIVATE_SIGNING_JWK"] = json.dumps(
|
||||
{
|
||||
"kid": "openedx",
|
||||
"kty": "RSA",
|
||||
"e": "{{ jwt_rsa_key.e|long_to_base64 }}",
|
||||
"d": "{{ jwt_rsa_key.d|long_to_base64 }}",
|
||||
"n": "{{ jwt_rsa_key.n|long_to_base64 }}",
|
||||
"p": "{{ jwt_rsa_key.p|long_to_base64 }}",
|
||||
"q": "{{ jwt_rsa_key.q|long_to_base64 }}",
|
||||
}
|
||||
)
|
||||
JWT_AUTH["JWT_PUBLIC_SIGNING_JWK_SET"] = json.dumps(
|
||||
{
|
||||
"keys": [
|
||||
{
|
||||
"kid": "openedx",
|
||||
"kty": "RSA",
|
||||
"e": "{{ jwt_rsa_key.e|long_to_base64 }}",
|
||||
"n": "{{ jwt_rsa_key.n|long_to_base64 }}",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
JWT_AUTH["JWT_ISSUERS"] = [
|
||||
{
|
||||
"ISSUER": "{{ JWT_COMMON_ISSUER }}",
|
||||
"AUDIENCE": "{{ JWT_COMMON_AUDIENCE }}",
|
||||
"SECRET_KEY": "{{ OPENEDX_SECRET_KEY }}"
|
||||
}
|
||||
]
|
||||
|
||||
{{ patch("openedx-common-settings") }}
|
||||
######## End of settings common to LMS and CMS
|
||||
######## End of settings common to LMS and CMS
|
||||
|
@ -2,10 +2,13 @@
|
||||
|
||||
######## Common CMS settings
|
||||
|
||||
|
||||
STUDIO_NAME = u"{{ PLATFORM_NAME }} - Studio"
|
||||
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB = 100
|
||||
|
||||
FRONTEND_LOGIN_URL = LMS_ROOT_URL + '/login'
|
||||
FRONTEND_LOGOUT_URL = LMS_ROOT_URL + '/logout'
|
||||
FRONTEND_REGISTER_URL = LMS_ROOT_URL + '/register'
|
||||
|
||||
# Create folders if necessary
|
||||
for folder in [LOG_DIR, MEDIA_ROOT, STATIC_ROOT_BASE]:
|
||||
if not os.path.exists(folder):
|
||||
|
@ -2,17 +2,14 @@
|
||||
|
||||
######## Common LMS settings
|
||||
|
||||
LOGIN_REDIRECT_WHITELIST = ["{{ CMS_HOST }}"]
|
||||
LEARNING_MICROFRONTEND_URL = None
|
||||
|
||||
# Fix media files paths
|
||||
VIDEO_IMAGE_SETTINGS["STORAGE_KWARGS"]["location"] = MEDIA_ROOT
|
||||
VIDEO_TRANSCRIPTS_SETTINGS["STORAGE_KWARGS"]["location"] = MEDIA_ROOT
|
||||
PROFILE_IMAGE_BACKEND["options"]["location"] = os.path.join(
|
||||
MEDIA_ROOT, "profile-images/"
|
||||
)
|
||||
|
||||
ORA2_FILEUPLOAD_BACKEND = "filesystem"
|
||||
ORA2_FILEUPLOAD_ROOT = "/openedx/data/ora2"
|
||||
ORA2_FILEUPLOAD_CACHE_NAME = "ora2-storage"
|
||||
|
||||
GRADES_DOWNLOAD = {
|
||||
"STORAGE_TYPE": "",
|
||||
"STORAGE_KWARGS": {
|
||||
@ -24,17 +21,11 @@ GRADES_DOWNLOAD = {
|
||||
COURSE_CATALOG_VISIBILITY_PERMISSION = "see_in_catalog"
|
||||
COURSE_ABOUT_VISIBILITY_PERMISSION = "see_about_page"
|
||||
|
||||
# JWT is authentication for other openedx services
|
||||
JWT_AUTH["JWT_ISSUER"] = "{{ JWT_COMMON_ISSUER }}"
|
||||
JWT_AUTH["JWT_AUDIENCE"] = "{{ JWT_COMMON_AUDIENCE }}"
|
||||
JWT_AUTH["JWT_SECRET_KEY"] = "{{ JWT_COMMON_SECRET_KEY }}"
|
||||
JWT_AUTH["JWT_PRIVATE_SIGNING_JWK"] = None
|
||||
|
||||
# Allow insecure oauth2 for local interaction with local containers
|
||||
OAUTH_ENFORCE_SECURE = False
|
||||
|
||||
# Create folders if necessary
|
||||
for folder in [LOG_DIR, MEDIA_ROOT, STATIC_ROOT_BASE, ORA2_FILEUPLOAD_ROOT]:
|
||||
for folder in [DATA_DIR, LOG_DIR, MEDIA_ROOT, STATIC_ROOT_BASE, ORA2_FILEUPLOAD_ROOT]:
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder)
|
||||
|
||||
|
@ -15,22 +15,22 @@ RUN wget -O /tmp/dockerize.tar.gz https://github.com/jwilder/dockerize/releases/
|
||||
|
||||
# Install ruby-build for building specific version of ruby
|
||||
# The ruby-build version should be periodically updated to reflect the latest release
|
||||
ARG RUBY_BUILD_VERSION=v20200224
|
||||
ARG RUBY_BUILD_VERSION=v20200401
|
||||
RUN git clone https://github.com/rbenv/ruby-build.git --branch $RUBY_BUILD_VERSION /openedx/ruby-build
|
||||
WORKDIR /openedx/ruby-build
|
||||
RUN PREFIX=/usr/local ./install.sh
|
||||
|
||||
# Install ruby and some specific dependencies
|
||||
ARG RUBY_VERSION=2.4.1
|
||||
ARG BUNDLER_VERSION=1.11.2
|
||||
ARG RAKE_VERSION=10.4.2
|
||||
ARG RUBY_VERSION=2.5.7
|
||||
ARG BUNDLER_VERSION=1.17.3
|
||||
ARG RAKE_VERSION=13.0.1
|
||||
RUN ruby-build $RUBY_VERSION /openedx/ruby
|
||||
ENV PATH "/openedx/ruby/bin:$PATH"
|
||||
RUN gem install bundler -v $BUNDLER_VERSION
|
||||
RUN gem install rake -v $RAKE_VERSION
|
||||
|
||||
# Install forum
|
||||
RUN git clone https://github.com/edx/cs_comments_service.git --branch open-release/ironwood.2 --depth 1 /openedx/cs_comments_service
|
||||
RUN git clone https://github.com/edx/cs_comments_service.git --branch open-release/juniper.1 --depth 1 /openedx/cs_comments_service
|
||||
WORKDIR /openedx/cs_comments_service
|
||||
RUN bundle install --deployment
|
||||
|
||||
@ -44,6 +44,7 @@ ENV NEW_RELIC_ENABLE false
|
||||
ENV API_KEY forumapikey
|
||||
ENV SEARCH_SERVER "http://elasticsearch:9200"
|
||||
ENV MONGODB_AUTH ""
|
||||
ENV MONGOID_AUTH_MECH ""
|
||||
ENV MONGODB_HOST "mongodb"
|
||||
ENV MONGODB_PORT "27017"
|
||||
EXPOSE 4567
|
||||
|
@ -8,7 +8,8 @@ RUN apt update && \
|
||||
|
||||
# Install dev python requirements
|
||||
RUN pip install -r requirements/edx/development.txt
|
||||
RUN pip install ipdb==0.12.2 ipython==5.8.0
|
||||
# Pinning the jedi library is required in python 3.5 to avoid deprecation warnings from ipython
|
||||
RUN pip install ipdb==0.13.2 ipython==7.9.0 jedi==0.15.2
|
||||
|
||||
# Recompile static assets: in development mode all static assets are stored in edx-platform,
|
||||
# and the location of these files is stored in webpack-stats.json. If we don't recompile
|
||||
|
@ -6,10 +6,19 @@ MAINTAINER Overhang.io <contact@overhang.io>
|
||||
# Install system requirements
|
||||
RUN apt update && \
|
||||
# Global requirements
|
||||
apt install -y language-pack-en git python-virtualenv build-essential software-properties-common curl git-core libxml2-dev libxslt1-dev python-virtualenv libmysqlclient-dev python-apt python-dev libxmlsec1-dev libfreetype6-dev swig gcc g++ \
|
||||
apt install -y language-pack-en git build-essential software-properties-common curl git-core libmysqlclient-dev libxml2-dev libxslt1-dev libxmlsec1-dev libfreetype6-dev swig gcc g++ \
|
||||
# pyenv/python requirements
|
||||
libbz2-dev libreadline-dev \
|
||||
# openedx requirements
|
||||
gettext gfortran graphviz graphviz-dev libffi-dev libfreetype6-dev libgeos-dev libjpeg8-dev liblapack-dev libpng12-dev libsqlite3-dev libxml2-dev libxmlsec1-dev libxslt1-dev lynx nodejs npm ntp pkg-config \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
|
||||
# Install python with pyenv
|
||||
ARG PYTHON_VERSION=3.5.9
|
||||
ENV PYENV_ROOT /opt/pyenv
|
||||
RUN git clone https://github.com/pyenv/pyenv $PYENV_ROOT --branch v1.2.18 --depth 1 \
|
||||
&& $PYENV_ROOT/bin/pyenv install $PYTHON_VERSION
|
||||
|
||||
# Dockerize will be useful to wait for mysql DB availability
|
||||
ARG DOCKERIZE_VERSION=v0.6.1
|
||||
@ -17,59 +26,51 @@ RUN curl -L -o /tmp/dockerize.tar.gz https://github.com/jwilder/dockerize/releas
|
||||
&& tar -C /usr/local/bin -xzvf /tmp/dockerize.tar.gz \
|
||||
&& rm /tmp/dockerize.tar.gz
|
||||
|
||||
# Checkout edx-platform code: https://github.com/edx/edx-platform/commits/open-release/ironwood.master
|
||||
# Because we are pulling from a branch, and not a tag, you should manually modify the
|
||||
# date hash below to force clearing the docker cache.
|
||||
# Checkout edx-platform code
|
||||
ARG EDX_PLATFORM_REPOSITORY=https://github.com/edx/edx-platform.git
|
||||
ARG EDX_PLATFORM_VERSION=open-release/ironwood.master
|
||||
ARG EDX_PLATFORM_VERSION_DATE=20200505
|
||||
ARG EDX_PLATFORM_VERSION=open-release/juniper.1
|
||||
RUN mkdir -p /openedx/edx-platform && \
|
||||
echo "Pulling $EDX_PLATFORM_VERSION tag from $EDX_PLATFORM_REPOSITORY ($EDX_PLATFORM_VERSION_DATE)" && \
|
||||
git clone $EDX_PLATFORM_REPOSITORY --branch $EDX_PLATFORM_VERSION --depth 1 /openedx/edx-platform
|
||||
WORKDIR /openedx/edx-platform
|
||||
|
||||
# Apply patches
|
||||
# Allow SigV4 authentication for video uploads to S3 https://github.com/edx/edx-platform/pull/22080
|
||||
RUN curl https://github.com/overhangio/edx-platform/commit/0d4f6cc3433013960b28e963c4094ef2a2a92f04.patch | git apply -
|
||||
# Resolve missing tasks in CMS
|
||||
# https://github.com/edx/edx-platform/pull/21297/
|
||||
# https://github.com/edx/edx-platform/pull/21305/
|
||||
RUN curl https://github.com/edx/edx-platform/commit/adb2c672e4d17cc1c42bdc206a0051e0fa16b5be.patch | git apply -
|
||||
RUN curl https://github.com/edx/edx-platform/commit/b7ecd80a2bef0d845c3bce97818e70fb3ed9e36d.patch | git apply -
|
||||
# Patch edx-platform
|
||||
# Get rid of lepl-related warnings
|
||||
# https://github.com/edx/edx-platform/pull/24059
|
||||
# https://github.com/overhangio/edx-platform/tree/overhangio/lepl-rfc6266-warning
|
||||
RUN curl https://github.com/overhangio/edx-platform/commit/5f21bbe77056d71ca61b97b6badcff3c1a31b858.patch | git apply -
|
||||
# Fix creation of LTI provider objects
|
||||
# https://github.com/edx/edx-platform/pull/24055
|
||||
# https://github.com/overhangio/edx-platform/tree/regisb/fix-lti-provider-admin
|
||||
RUN curl https://github.com/overhangio/edx-platform/commit/089b26eed0302ed1f9a5b24c5f3e563dd44abb04.patch | git apply -
|
||||
|
||||
# Download extra locales to /openedx/locale/contrib/locale
|
||||
RUN cd /tmp \
|
||||
&& curl -L -o openedx-i18n.tar.gz https://github.com/openedx/openedx-i18n/archive/ironwood.tar.gz \
|
||||
&& curl -L -o openedx-i18n.tar.gz https://github.com/openedx/openedx-i18n/archive/juniper.1.tar.gz \
|
||||
&& tar xzf /tmp/openedx-i18n.tar.gz \
|
||||
&& mkdir -p /openedx/locale/contrib \
|
||||
&& mv openedx-i18n-ironwood/edx-platform/locale /openedx/locale/contrib \
|
||||
&& mv openedx-i18n-juniper.1/edx-platform/locale /openedx/locale/contrib \
|
||||
&& rm -rf openedx-i18n*
|
||||
|
||||
# Install python requirements in a virtualenv
|
||||
RUN virtualenv /openedx/venv
|
||||
RUN $PYENV_ROOT/versions/$PYTHON_VERSION/bin/pyvenv /openedx/venv
|
||||
ENV PATH /openedx/venv/bin:${PATH}
|
||||
ENV VIRTUAL_ENV /openedx/venv/
|
||||
RUN pip install setuptools==39.0.1 pip==9.0.3
|
||||
RUN pip install setuptools==44.1.0 pip==20.0.2 wheel==0.34.2
|
||||
RUN pip install -r requirements/edx/base.txt
|
||||
|
||||
# Install patched version of ora2
|
||||
RUN pip uninstall -y ora2 && \
|
||||
pip install git+https://github.com/overhangio/edx-ora2.git@2.2.0-patched#egg=ora2==2.2.0
|
||||
RUN pip install https://github.com/overhangio/edx-ora2/archive/overhangio/boto2to3.zip
|
||||
|
||||
# Install patched version of edx-oauth2-provider
|
||||
RUN pip install git+https://github.com/overhangio/edx-oauth2-provider.git@1.2.3#egg=edx-oauth2-provider==1.2.3
|
||||
|
||||
# Install ironwood-compatible scorm xblock
|
||||
RUN pip install "openedx-scorm-xblock<10.0.0,>=9.2.0"
|
||||
# Install juniper-compatible scorm xblock
|
||||
RUN pip install "openedx-scorm-xblock<11.0.0,>=10.0.0"
|
||||
|
||||
# Install a recent version of nodejs
|
||||
RUN nodeenv /openedx/nodeenv --node=8.9.3 --prebuilt
|
||||
RUN nodeenv /openedx/nodeenv --node=12.13.0 --prebuilt
|
||||
ENV PATH /openedx/nodeenv/bin:${PATH}
|
||||
|
||||
# Install nodejs requirements
|
||||
ARG NPM_REGISTRY=https://registry.npmjs.org/
|
||||
RUN npm set progress=false \
|
||||
&& npm install --verbose --registry=$NPM_REGISTRY
|
||||
RUN npm install --verbose --registry=$NPM_REGISTRY
|
||||
ENV PATH ./node_modules/.bin:${PATH}
|
||||
|
||||
# Install private requirements: this is useful for installing custom xblocks.
|
||||
@ -78,10 +79,13 @@ RUN cd /openedx/requirements/ \
|
||||
&& touch ./private.txt \
|
||||
&& pip install -r ./private.txt
|
||||
|
||||
# Create folder that will store *.env.json and *.auth.json files, as well as
|
||||
# Create folder that will store lms/cms.env.json files, as well as
|
||||
# the tutor-specific settings files.
|
||||
RUN mkdir -p /openedx/config ./lms/envs/tutor ./cms/envs/tutor
|
||||
ENV CONFIG_ROOT /openedx/config
|
||||
COPY revisions.yml /openedx/config/
|
||||
ENV LMS_CFG /openedx/config/lms.env.json
|
||||
ENV STUDIO_CFG /openedx/config/cms.env.json
|
||||
ENV REVISION_CFG /openedx/config/revisions.yml
|
||||
COPY settings/lms/*.py ./lms/envs/tutor/
|
||||
COPY settings/cms/*.py ./cms/envs/tutor/
|
||||
|
||||
@ -111,6 +115,10 @@ ENV PATH /openedx/bin:${PATH}
|
||||
# and run each one individually to collect the production static assets to
|
||||
# /openedx/staticfiles.
|
||||
ENV NO_PYTHON_UNINSTALL 1
|
||||
ENV NO_PREREQ_INSTALL 1
|
||||
# We need to rely on a separate openedx-assets command to accelerate asset processing.
|
||||
# For instance, we don't want to run all steps of asset collection every time the theme
|
||||
# is modified.
|
||||
RUN openedx-assets xmodule \
|
||||
&& openedx-assets npm \
|
||||
&& openedx-assets webpack --env=prod \
|
||||
|
@ -9,7 +9,6 @@ import traceback
|
||||
from path import Path
|
||||
|
||||
from pavelib import assets
|
||||
from xmodule import static_content as xmodule_static_content
|
||||
|
||||
|
||||
DEFAULT_STATIC_ROOT = "/openedx/staticfiles"
|
||||
@ -99,8 +98,18 @@ def run_build(args):
|
||||
|
||||
|
||||
def run_xmodule(_args):
|
||||
# Collecting xmodule assets is incompatible with setting the django path, because
|
||||
# of an unfortunate call to settings.configure()
|
||||
django_settings_module = os.environ.get("DJANGO_SETTINGS_MODULE")
|
||||
if django_settings_module:
|
||||
os.environ.pop("DJANGO_SETTINGS_MODULE")
|
||||
|
||||
sys.argv[1:] = ["common/static/xmodule"]
|
||||
xmodule_static_content.main()
|
||||
import xmodule.static_content
|
||||
xmodule.static_content.main()
|
||||
|
||||
if django_settings_module:
|
||||
os.environ["DJANGO_SETTINGS_MODULE"] = django_settings_module
|
||||
|
||||
|
||||
def run_npm(_args):
|
||||
|
1
tutor/templates/build/openedx/revisions.yml
Normal file
1
tutor/templates/build/openedx/revisions.yml
Normal file
@ -0,0 +1 @@
|
||||
EDX_PLATFORM_REVISION: juniper
|
@ -4,7 +4,9 @@ Bare minimum settings for collecting production assets.
|
||||
from ..common import *
|
||||
from openedx.core.lib.derived import derive_settings
|
||||
|
||||
ENABLE_COMPREHENSIVE_THEMING = True
|
||||
COMPREHENSIVE_THEME_DIRS.append('/openedx/themes')
|
||||
|
||||
STATIC_ROOT_BASE = '/openedx/staticfiles'
|
||||
|
||||
SECRET_KEY = 'secret'
|
||||
|
@ -33,7 +33,7 @@ DOCKER_IMAGE_OPENEDX_DEV: "overhangio/openedx-dev:{{ TUTOR_VERSION }}"
|
||||
DOCKER_IMAGE_ANDROID: "overhangio/openedx-android:{{ TUTOR_VERSION }}"
|
||||
DOCKER_IMAGE_FORUM: "overhangio/openedx-forum:{{ TUTOR_VERSION }}"
|
||||
DOCKER_IMAGE_MEMCACHED: "memcached:1.4.38"
|
||||
DOCKER_IMAGE_MONGODB: "mongo:3.2.16"
|
||||
DOCKER_IMAGE_MONGODB: "mongo:3.6.18"
|
||||
DOCKER_IMAGE_MYSQL: "mysql:5.6.36"
|
||||
DOCKER_IMAGE_ELASTICSEARCH: "elasticsearch:1.5.2"
|
||||
DOCKER_IMAGE_NGINX: "nginx:1.13"
|
||||
@ -49,6 +49,7 @@ FORUM_HOST: "forum"
|
||||
JWT_COMMON_AUDIENCE: "openedx"
|
||||
JWT_COMMON_ISSUER: "{% if ACTIVATE_HTTPS %}https{% else %}http{% endif %}://{{ LMS_HOST }}/oauth2"
|
||||
JWT_COMMON_SECRET_KEY: "{{ OPENEDX_SECRET_KEY }}"
|
||||
JWT_RSA_PRIVATE_KEY: "{{ 2048|rsa_private_key }}"
|
||||
K8S_NAMESPACE: "openedx"
|
||||
LANGUAGE_CODE: "en"
|
||||
MEMCACHED_HOST: "memcached"
|
||||
@ -61,6 +62,7 @@ MONGODB_PASSWORD: ""
|
||||
OPENEDX_CMS_GUNICORN_WORKERS: 2
|
||||
OPENEDX_LMS_GUNICORN_WORKERS: 2
|
||||
OPENEDX_MYSQL_DATABASE: "openedx"
|
||||
OPENEDX_CSMH_MYSQL_DATABASE: "{{ OPENEDX_MYSQL_DATABASE }}_csmh"
|
||||
OPENEDX_MYSQL_USERNAME: "openedx"
|
||||
MYSQL_HOST: "mysql"
|
||||
MYSQL_PORT: 3306
|
||||
|
@ -6,6 +6,10 @@ x-openedx-service:
|
||||
environment:
|
||||
SETTINGS: ${TUTOR_EDX_PLATFORM_SETTINGS:-tutor.development}
|
||||
volumes:
|
||||
# Settings & config
|
||||
- ../apps/openedx/settings/lms/:/openedx/edx-platform/lms/envs/tutor/
|
||||
- ../apps/openedx/settings/cms/:/openedx/edx-platform/cms/envs/tutor/
|
||||
- ../apps/openedx/config/:/openedx/config/
|
||||
# theme files
|
||||
- ../build/openedx/themes:/openedx/themes
|
||||
# editable requirements
|
||||
@ -17,13 +21,20 @@ services:
|
||||
command: ./manage.py lms runserver 0.0.0.0:8000
|
||||
ports:
|
||||
- "8000:8000"
|
||||
networks:
|
||||
default:
|
||||
aliases:
|
||||
- "{{ LMS_HOST }}"
|
||||
|
||||
cms:
|
||||
<<: *openedx-service
|
||||
command: ./manage.py cms runserver 0.0.0.0:8000
|
||||
ports:
|
||||
- "8001:8000"
|
||||
|
||||
lms-worker:
|
||||
<<: *openedx-service
|
||||
|
||||
cms-worker:
|
||||
<<: *openedx-service
|
||||
|
||||
@ -32,5 +43,5 @@ services:
|
||||
<<: *openedx-service
|
||||
command: openedx-assets watch-themes --env dev
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
{{ patch("local-docker-compose-dev-services")|indent(2) }}
|
@ -2,8 +2,8 @@ export DJANGO_SETTINGS_MODULE=$SERVICE_VARIANT.envs.$SETTINGS
|
||||
echo "Loading settings $DJANGO_SETTINGS_MODULE"
|
||||
|
||||
# Import demo course
|
||||
git clone https://github.com/edx/edx-demo-course --branch open-release/ironwood.2 --depth 1 ../edx-demo-course
|
||||
git clone https://github.com/edx/edx-demo-course --branch open-release/juniper.1 --depth 1 ../edx-demo-course
|
||||
python ./manage.py cms import ../data ../edx-demo-course
|
||||
|
||||
# Re-index courses
|
||||
./manage.py cms reindex_course --all --setup
|
||||
./manage.py cms reindex_course --all --setup
|
@ -5,11 +5,14 @@ echo "Loading settings $DJANGO_SETTINGS_MODULE"
|
||||
|
||||
./manage.py lms migrate
|
||||
|
||||
./manage.py lms create_oauth2_client \
|
||||
"http://androidapp.com" "http://androidapp.com/redirect" public \
|
||||
--client_id android --client_secret {{ ANDROID_OAUTH2_SECRET }} \
|
||||
--trusted
|
||||
|
||||
# Create oauth credentials for Android application
|
||||
./manage.py lms create_dot_application \
|
||||
--client-id android \
|
||||
--client-secret {{ ANDROID_OAUTH2_SECRET }} \
|
||||
--grant-type password \
|
||||
android \
|
||||
login_service_user
|
||||
|
||||
# Fix incorrect uploaded file path
|
||||
if [ -d /openedx/data/uploads/ ]; then
|
||||
if [ -n "$(ls -A /openedx/data/uploads/)" ]; then
|
||||
|
@ -14,5 +14,6 @@ do
|
||||
done
|
||||
echo "MySQL is up and running"
|
||||
|
||||
# edx-platform database
|
||||
mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e 'CREATE DATABASE IF NOT EXISTS {{ OPENEDX_MYSQL_DATABASE }};'
|
||||
mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e 'GRANT ALL ON {{ OPENEDX_MYSQL_DATABASE }}.* TO "{{ OPENEDX_MYSQL_USERNAME }}"@"%" IDENTIFIED BY "{{ OPENEDX_MYSQL_PASSWORD }}";'
|
||||
mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e 'GRANT ALL ON {{ OPENEDX_MYSQL_DATABASE }}.* TO "{{ OPENEDX_MYSQL_USERNAME }}"@"%" IDENTIFIED BY "{{ OPENEDX_MYSQL_PASSWORD }}";'
|
||||
|
30
tutor/templates/local/docker-compose.prod.yml
Normal file
30
tutor/templates/local/docker-compose.prod.yml
Normal file
@ -0,0 +1,30 @@
|
||||
version: "3.7"
|
||||
services:
|
||||
openedx-assets:
|
||||
image: {{ DOCKER_REGISTRY }}{{ DOCKER_IMAGE_OPENEDX }}
|
||||
volumes:
|
||||
- ../../data/openedx:/var/www/openedx
|
||||
command: sh -c "rm -rf /var/www/openedx/staticfiles && cp -r /openedx/staticfiles/ /var/www/openedx/"
|
||||
|
||||
nginx:
|
||||
image: {{ DOCKER_REGISTRY }}{{ DOCKER_IMAGE_NGINX }}
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "{{ NGINX_HTTP_PORT }}:80"
|
||||
- "{{ NGINX_HTTPS_PORT }}:443"
|
||||
{% if not WEB_PROXY %}
|
||||
networks:
|
||||
default:
|
||||
aliases:
|
||||
- "{{ LMS_HOST }}"
|
||||
{{ patch("local-docker-compose-nginx-aliases")|indent(10) }}
|
||||
{% endif %}
|
||||
volumes:
|
||||
- ../apps/nginx:/etc/nginx/conf.d/:ro
|
||||
- ../../data/openedx:/var/www/openedx:ro
|
||||
- ../../data/openedx-media:/var/www/openedx-media:ro
|
||||
{% if ACTIVATE_HTTPS %}- ../../data/letsencrypt:/etc/letsencrypt/:ro{% endif %}
|
||||
{{ patch("local-docker-compose-nginx-volumes")|indent(6) }}
|
||||
depends_on: {{ [("lms", ACTIVATE_LMS), ("cms", ACTIVATE_CMS)]|list_if }}
|
||||
|
||||
{{ patch("local-docker-compose-prod-services")|indent(2) }}
|
@ -43,29 +43,6 @@ services:
|
||||
- ../../data/elasticsearch:/usr/share/elasticsearch/data
|
||||
{% endif %}
|
||||
|
||||
openedx-assets:
|
||||
image: {{ DOCKER_REGISTRY }}{{ DOCKER_IMAGE_OPENEDX }}
|
||||
volumes:
|
||||
- ../../data/openedx:/var/www/openedx
|
||||
command: sh -c "rm -rf /var/www/openedx/staticfiles && cp -r /openedx/staticfiles/ /var/www/openedx/"
|
||||
|
||||
nginx:
|
||||
image: {{ DOCKER_REGISTRY }}{{ DOCKER_IMAGE_NGINX }}
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "{{ NGINX_HTTP_PORT }}:80"
|
||||
- "{{ NGINX_HTTPS_PORT }}:443"
|
||||
networks:
|
||||
default:
|
||||
aliases: [{{ patch("local-docker-compose-nginx-aliases", separator=", ") }}]
|
||||
volumes:
|
||||
- ../apps/nginx:/etc/nginx/conf.d/:ro
|
||||
- ../../data/openedx:/var/www/openedx:ro
|
||||
- ../../data/openedx-media:/var/www/openedx-media:ro
|
||||
{% if ACTIVATE_HTTPS %}- ../../data/letsencrypt:/etc/letsencrypt/:ro{% endif %}
|
||||
{{ patch("local-docker-compose-nginx-volumes")|indent(6) }}
|
||||
depends_on: {{ [("lms", ACTIVATE_LMS), ("cms", ACTIVATE_CMS)]|list_if }}
|
||||
|
||||
{% if ACTIVATE_RABBITMQ %}
|
||||
rabbitmq:
|
||||
image: {{ DOCKER_REGISTRY }}{{ DOCKER_IMAGE_RABBITMQ }}
|
||||
@ -142,6 +119,7 @@ services:
|
||||
{% if ACTIVATE_MONGODB %}- mongodb{% endif %}
|
||||
{% if ACTIVATE_RABBITMQ %}- rabbitmq{% endif %}
|
||||
{% if ACTIVATE_SMTP %}- smtp{% endif %}
|
||||
{% if ACTIVATE_LMS %}- lms{% endif %}
|
||||
{{ patch("local-docker-compose-cms-dependencies")|indent(6) }}
|
||||
{% endif %}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import base64
|
||||
from crypt import crypt
|
||||
from hmac import compare_digest
|
||||
import json
|
||||
@ -5,10 +6,12 @@ import os
|
||||
import random
|
||||
import shutil
|
||||
import string
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import click
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
from . import exceptions
|
||||
from . import fmt
|
||||
@ -77,6 +80,41 @@ def reverse_host(domain):
|
||||
return ".".join(domain.split(".")[::-1])
|
||||
|
||||
|
||||
def rsa_private_key(bits=2048):
|
||||
"""
|
||||
Export an RSA private key in PEM format.
|
||||
"""
|
||||
key = RSA.generate(bits)
|
||||
return key.export_key().decode()
|
||||
|
||||
|
||||
def rsa_import_key(key):
|
||||
"""
|
||||
Import PEM-formatted RSA key and return the corresponding object.
|
||||
"""
|
||||
return RSA.import_key(key.encode())
|
||||
|
||||
|
||||
def long_to_base64(n):
|
||||
"""
|
||||
Borrowed from jwkest.__init__
|
||||
"""
|
||||
|
||||
def long2intarr(long_int):
|
||||
_bytes = []
|
||||
while long_int:
|
||||
long_int, r = divmod(long_int, 256)
|
||||
_bytes.insert(0, r)
|
||||
return _bytes
|
||||
|
||||
bys = long2intarr(n)
|
||||
data = struct.pack("%sB" % len(bys), *bys)
|
||||
if not data:
|
||||
data = "\x00"
|
||||
s = base64.urlsafe_b64encode(data).rstrip(b"=")
|
||||
return s.decode("ascii")
|
||||
|
||||
|
||||
def walk_files(path):
|
||||
"""
|
||||
Iterate on file paths located in directory.
|
||||
|
Loading…
Reference in New Issue
Block a user