# Adding a simple plugin to tutor

**URL:** <https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107>\
**Category:** Tutor Help\
**Tags:** api, tutor-plugin\
**Created:** [October 8, 2024, 12:56pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107 "2024-10-08T12:56:33Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 8, 2024, 12:56pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/1 "2024-10-08T12:56:33Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 9, 2024, 3:43pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/2 "2024-10-09T15:43:10Z")

</div>

Hi @Raquel_Silva!  
There is alwas confusion between [Tutor plugins](https://docs.tutor.edly.io/plugins/index.html) and [Open edX plugins](https://docs.openedx.org/projects/edx-platform/en/latest/concepts/extension_points.html#platform-features-integrating-python-code).  
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](https://github.com/openedx/edx-cookiecutters), then add it to the `OPENEDX_EXTRA_PIP_REQUIREMENTS` Tutor setting. Finally rebuild your Open edX image.

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 10, 2024, 12:25pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/3 "2024-10-10T12:25:17Z")

</div>

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):

```auto
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:

```auto
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?

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 10, 2024, 1:50pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/4 "2024-10-10T13:50:34Z")

</div>

Please check if [this tutorial](https://docs.tutor.edly.io/tutorials/edx-platform.html#working-on-edx-platform-python-dependencies) is of any help.

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 10, 2024, 2:38pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/5 "2024-10-10T14:38:07Z")

</div>

Yep, tried that and all other mount steps in [here](https://docs.tutor.edly.io/dev.html#sharing-directories-with-containers) but no luck.  
When I run `tutor mounts list` it never shows them in build\_mounts.

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 10, 2024, 2:52pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/6 "2024-10-10T14:52:20Z")

</div>

It’s probably because your module is not recognized as a standard mount. Try [this](https://docs.tutor.edly.io/tutorials/edx-platform.html#what-if-my-edx-platform-package-is-not-automatically-bind-mounted).

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 11, 2024, 8:36am UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/7 "2024-10-11T08:36:26Z")

</div>

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:

```auto
# 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:

```auto
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:

```auto
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:

```auto
{"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.

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 11, 2024, 2:05pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/8 "2024-10-11T14:05:22Z")

</div>

@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.](https://github.com/openedx/openedx-tutor-plugins)

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 11, 2024, 3:39pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/9 "2024-10-11T15:39:03Z")

</div>

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](https://github.com/openedx/edx-cookiecutters/blob/4d6e4f654ee73b303928b033991f51ed75c33c5a/cookiecutter-django-app/%7B%7Bcookiecutter.repo_name%7D%7D/%7B%7Bcookiecutter.app_name%7D%7D/apps.py#L8).

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 14, 2024, 12:58pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/10 "2024-10-14T12:58:02Z")

</div>

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

 ![Screenshot 2024-10-14 at 13.55.26](https://us1.discourse-cdn.com/flex020/uploads/openedx/original/2X/d/d2512f4a512ce1c381df74ab0e8ecac8848bbcc9.png)

And the apps.py:  
 ![Screenshot 2024-10-14 at 13.55.41](https://us1.discourse-cdn.com/flex020/uploads/openedx/original/2X/e/eed8aaf8bf6e37365d9249f37e51d63735651f45.png)

Will try to manually add it to the INSTALLED\_APPS via a tutor plugin maybe.

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 22, 2024, 3:03pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/11 "2024-10-22T15:03:20Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 22, 2024, 8:31pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/12 "2024-10-22T20:31:16Z")

</div>

I can see that your AppConfig is empty. Checkout this [document](https://github.com/openedx/edx-django-utils/blob/master/edx_django_utils/plugins/docs/how_tos/how_to_create_a_plugin_app.rst) for more details.

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 23, 2024, 8:04am UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/13 "2024-10-23T08:04:37Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 23, 2024, 2:49pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/14 "2024-10-23T14:49:58Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 23, 2024, 3:21pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/15 "2024-10-23T15:21:10Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 23, 2024, 7:04pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/16 "2024-10-23T19:04:50Z")

</div>

You can write a Tutor plugin to patch the Dockerfile with [openedx-dockerfile-post-python-requirements](https://github.com/overhangio/tutor/blob/97e9fa4751ee3afb67c25c2b4e58fe11cbfdea2d/tutor/templates/build/openedx/Dockerfile#L104C11-L104C54) and there do your Dockerfile magic!

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 24, 2024, 8:28am UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/17 "2024-10-24T08:28:37Z")

</div>

I wish it was that easy 😅

It seems that you are providing a soon to be deprecated way of doing that (v0) according to [Plugin API — Tutor documentation](https://docs.tutor.edly.io/plugins/v0/api.html#patches).

I will probably have to mount my folder during build time and runtime. Could be via [tutor.hooks.Filters.COMPOSE\_MOUNTS](https://docs.tutor.edly.io/reference/api/hooks/catalog.html#tutor.hooks.Filters.COMPOSE_MOUNTS) and [tutor.hooks.Filters.IMAGES\_BUILD\_MOUNTS](https://docs.tutor.edly.io/reference/api/hooks/catalog.html#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](https://docs.tutor.edly.io/reference/api/hooks/catalog.html#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`.

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 24, 2024, 3:10pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/18 "2024-10-24T15:10:49Z")

</div>

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:

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

```

More details on how the above will work is [here](https://docs.tutor.edly.io/reference/api/hooks/catalog.html#tutor.hooks.Filters.MOUNTED_DIRECTORIES).  
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:

```auto
- 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`.

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [October 24, 2024, 3:56pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/19 "2024-10-24T15:56:50Z")

</div>

> [@Raquel\_Silva](#):
>
> It seems that you are providing a soon to be deprecated way of doing that (v0)

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

---

<div class="post-metadata">

**Author:** ![Raquel\_Silva](https://avatars.discourse-cdn.com/v4/letter/r/91b2a8/32.png) [@Raquel\_Silva](https://discuss.openedx.org/u/Raquel_Silva)\
**Post date:** [October 24, 2024, 4:20pm UTC](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107/20 "2024-10-24T16:20:26Z")

</div>

You mean like `hooks.Filters.ENV_PATCHES` ?

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

[Next page](https://discuss.openedx.org/t/adding-a-simple-plugin-to-tutor/14107.md?page=2)
