Adding a simple plugin to tutor

I’ve been searching for a simple example on how to add a local developed django app as a plugin into Tutor. Even the created app structure in the documentation is not consistent.
There is a mix between tutor commands and configurations and open-edx ones, a lot of confusion.

To make things easier, let’s assume I want to add an API endpoint into LMS under /api/hello/ that prints “Hello”.

Can anyone help, please?
And yes, I’ve been using all kinds of cookie cutters and nothing.

Hi @Raquel_Silva!
There is alwas confusion between Tutor plugins and Open edX plugins.
To add an API endpoint to the LMS you will need the latest. To do it, create your django app using the Open edX Cookiecutter, then add it to the OPENEDX_EXTRA_PIP_REQUIREMENTS Tutor setting. Finally rebuild your Open edX image.

1 Like

Hello! Thanks!
After encountering some issues with the cookiecutter, I’ve managed to just use the python shell and ran successfully (app named new_api):

from cookiecutter.main import cookiecutter
cookiecutter('cookiecutter-django-app/', output_dir='../')

Had to also update the dockerfile to do apt-get update prior to installing packages, since it was failing.
The app folder is /Users/raquelsilva/Documents/tutor_plugins/new_api, currently having a hard time trying to mount it for build time, keeps not having access.

On the tutor config file I have added this:

OPENEDX_EXTRA_PIP_REQUIREMENTS:
- -e /openedx/new_api

and did tutor config save.

Any help on how to mount the new_api folder with tutor and be accessible doing build time (tutor images build openedx) and not runtime?

Please check if this tutorial is of any help.

Yep, tried that and all other mount steps in here but no luck.
When I run tutor mounts list it never shows them in build_mounts.

It’s probably because your module is not recognized as a standard mount. Try this.

Also have tried that one. Have tried all possibilities from tutor documentation regarding mounts.
Apart from having update the docker file since the build (tutor images build openedx) was failing:

# the below was added in all install steps
RUN apt-get clean && \
    apt-get update --fix-missing && \
    apt-get install -y --fix-missing

Also changed to load my local directory:

COPY --from=new-api / /openedx/new_api
RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
    pip install -e /openedx/new_api

And then run like this:

docker buildx build --no-cache --tag=docker.io/overhangio/openedx:18.1.3 --output=type=docker --cache-from=type=registry,ref=docker.io/overhangio/openedx:18.1.3-cache --build-context=new-api=/Users/raquelsilva/Documents/tutor_plugins/new_api /Users/raquelsilva/Library/Application\ Support/tutor/env/build/openedx

Everything seems correct with the above but when I try to access the URL of the app created above:

{"level":"error","ts":XXXXXXXXX,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"XXXXXX","remote_port":"36752","client_ip":"XXXXXXX","proto":"HTTP/1.1","method":"GET","host":"local.edly.io","uri":"/hello_world/"},"bytes_read":0,"user_id":"","duration":0.177832042,"size":3130,"status":404}

I can see only this /openedx/venv/lib/python3.11/site-packages/new-api.egg-link inside the LMS container, not sure what else to look for. Shouldn’t I add it to INSTALLED_APPS ?

Ideally I would not want to change the docker file since that is not reliable nor scalable.

@Andres.Aulasneo why not go with tutor plugins? I would just like to have steps to do this. Also had a look at GitHub - openedx/openedx-tutor-plugins: A set of Tutor plugins maintained by the Open edX community.

If you see your new-api installed inside the container then the mount must be working. However if it’s not one of the INSTALLED_APPS then there must be something wrong in the setup.py or the apps.py.

The cookiecutter setup seemed ok, here is the relevant section of setup.py:

And the apps.py:
Screenshot 2024-10-14 at 13.55.41

Will try to manually add it to the INSTALLED_APPS via a tutor plugin maybe.

It has been quite difficult. Is there an alternative to this by using tutor plugins from the beginning? Is there anyone else that can help?

I can see that your AppConfig is empty. Checkout this document for more details.

Thanks, changed that and it is working!
I do not like the fact that I am overriding the dockerfile in order to make this work. Do you have any advice on this?

The override (apart from the installation of required libraries) is to install the local django app and copy it into the container.

you don’t have to overwrite the Dockerfile. Just add your plugin to the OPENEDX_EXTRA_PIP_REQUIREMENTS setting in your config.yml, save and rebuild openedx. it will add the pip install to the Dockerfile.

The problem with that is that the package is not hosted. It is not publicly reached, it is a local one.

You can write a Tutor plugin to patch the Dockerfile with openedx-dockerfile-post-python-requirements and there do your Dockerfile magic!

I wish it was that easy :sweat_smile:

It seems that you are providing a soon to be deprecated way of doing that (v0) according to Plugin API — Tutor documentation.

I will probably have to mount my folder during build time and runtime. Could be via tutor.hooks.Filters.COMPOSE_MOUNTS and tutor.hooks.Filters.IMAGES_BUILD_MOUNTS, still need to check how to make this work. Since, it can maybe be tutor.hooks.Filters.MOUNTED_DIRECTORIES.

Then will need to check the extra pip requirements option and see if it works. This still does not fix the fact that I had to override a lot of installation steps with apt-get update --fix-missing.

Update for anyone that sees this. First, created and enabled a plugin to load the django app into openedx service during build time and runtime once we want to mount a specific path. The content of plugin file must consist in something like:

from tutor import hooks
hooks.Filters.MOUNTED_DIRECTORIES.add_item(("openedx", r".*new_api$"))

More details on how the above will work is here.
Then we need to mount the directory where our django app is (new_api in this case).

tutor mounts add ~/Documents/tutor_plugins/new_api

After that, run tutor mounts list which should show this:

- name: ~/Documents/tutor_plugins/new_api
  build_mounts:
  - image: openedx
    context: mnt-new_api
  - image: openedx-dev
    context: mnt-new_api
  compose_mounts:
  - service: openedx
    container_path: /mnt/new_api
  - service: openedx-dev
    container_path: /mnt/new_api

Then rebuild your openedx image by tutor images build openedx and also do a clean launch with tutor local launch.

No, you can do with v1 plugins. That’s the recommended way to do it. Use mounts only for development.

You mean like hooks.Filters.ENV_PATCHES ?

I’m missing something with that then. How can I use patches without mounting my path?