Compare commits

..

1 Commits

Author SHA1 Message Date
Muhammad Faraz Maqsood
97d34aa2ec chore: remove Python 3.8 references
- drop support for python 3.8 and set Python 3.9 as the minimum supported python version.
2024-11-12 12:26:42 +05:00
33 changed files with 116 additions and 426 deletions

View File

@ -4,9 +4,6 @@ on:
issues: issues:
types: types:
- opened - opened
pull_request_target:
types:
- opened
jobs: jobs:
# https://github.com/actions/add-to-project # https://github.com/actions/add-to-project

View File

@ -2,7 +2,7 @@ name: Sync with private repo
on: on:
push: push:
branches: [ release, main ] branches: [ master, main, nightly ]
jobs: jobs:
sync: sync:

View File

@ -2,9 +2,7 @@ name: Run tests
on: on:
pull_request: pull_request:
branches: [release, main] branches: [master]
push:
branches: [release, main]
jobs: jobs:
tests: tests:
@ -18,6 +16,8 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Upgrade pip
run: python -m pip install --upgrade pip setuptools
- name: Install dependencies - name: Install dependencies
run: | run: |
pip install .[dev] pip install .[dev]

View File

@ -1,22 +0,0 @@
# https://hatch.pypa.io/latest/how-to/config/dynamic-metadata/
import os
import typing as t
from hatchling.metadata.plugin.interface import MetadataHookInterface
HERE = os.path.dirname(__file__)
class MetaDataHook(MetadataHookInterface):
def update(self, metadata: dict[str, t.Any]) -> None:
about = load_about()
metadata["version"] = about["__version__"]
def load_about() -> dict[str, str]:
about: dict[str, str] = {}
with open(
os.path.join(HERE, "tutordiscovery", "__about__.py"), "rt", encoding="utf-8"
) as f:
exec(f.read(), about)
return about

View File

@ -19,41 +19,6 @@ instructions, because git commits are used to generate release notes:
<!-- scriv-insert-here --> <!-- scriv-insert-here -->
<a id='changelog-20.0.0'></a>
## v20.0.0 (2025-06-05)
- [Bugfix] Add support to consume events from event bus in discovery. Explanation can be viewed here: https://github.com/openedx/event-bus-redis/blob/main/docs/tutor_installation.rst. (by @Faraz32123)
- [Feature] Introduced a new environment variable to enable or disable programs. (by @Faraz32123)
- This aligns with the frontend, which now also utilizes this environment variable. To view the frontend related changes, click here: https://github.com/openedx/frontend-app-learner-dashboard/pull/506/files.
- Additionally, it automates the enabling of programs in the "programapiconfig" model on the LMS admin panel through init tasks.
- [Improvement] Migrate packaging from setup.py/setuptools to pyproject.toml/hatch. (by @Faraz32123)
- For more details view tutor core PR: https://github.com/overhangio/tutor/pull/1163
- [Improvement] Add hatch_build.py in sdist target to fix the installation issues (by @dawoudsheraz)
- [Improvement] Replace site-configuration script with create_or_update_site_configuration management command in the init task. (by @Danyal-Faheem)
- 💥[Feature] Upgrade to Teak. (by @mlabeeb03)
<a id='changelog-19.0.0'></a>
## v19.0.0 (2024-10-23)
- 💥[Feature] Upgrade to Sumac. (by @Faraz32123)
- [Feature] Add Elasticsearch support in tutor-discovery. As Tutor and Open edX have shifted to Meilisearch, and course-discovery still depends on Elasticsearch, running the Elasticsearch container with tutor-discovery will facilitate smoother operation for the course-discovery service. (by @Faraz32123)
- Please see related tutor core PR for context https://github.com/overhangio/tutor/pull/1141
- 💥 [Deprecation] Drop support for python 3.8 and set Python 3.9 as the minimum supported python version. (by @Faraz32123)
- 💥[Improvement] Rename Tutor's two branches (by @DawoudSheraz):
* Rename **master** to **release**, as this branch runs the latest official Open edX release tag.
* Rename **nightly** to **main**, as this branch runs the Open edX master branches, which are the basis for the next Open edX release.
- [Improvement] Move is_docker_rootless method related to elasticsearch from tutor core to tutor-discovery. (by @Faraz32123)
- 💥[Feature] Update Course Discovery Image to use Ubuntu 22.04 as base OS. (by @hinakhadim)
- [Bugfix] Fix catalog_service_user permissions and 403 while fetching pathways (by @dyudyunov)
- [BugFix] Fix images(media) persistance issue by mounting media directory in volumes through patches. (by @Faraz32123)
- [Bugfix] Fix legacy warnings during Docker build. (by @regisb)
<a id='changelog-18.0.0'></a> <a id='changelog-18.0.0'></a>
## v18.0.0 (2024-05-14) ## v18.0.0 (2024-05-14)

2
MANIFEST.in Normal file
View File

@ -0,0 +1,2 @@
recursive-include tutordiscovery/patches *
recursive-include tutordiscovery/templates *

View File

@ -1,33 +1,25 @@
.DEFAULT_GOAL := help .DEFAULT_GOAL := help
.PHONY: docs .PHONY: docs
SRC_DIRS = ./tutordiscovery ./tests SRC_DIRS = ./tutordiscovery
BLACK_OPTS = --exclude templates ${SRC_DIRS}
# Warning: These checks are run on every PR. # Warning: These checks are run on every PR.
test: test-lint test-types test-format test-unit test-pythonpackage # Run some static checks. test: test-lint test-types test-format # Run some static checks.
test-format: ## Run code formatting tests. test-format: ## Run code formatting tests.
ruff format --check --diff ${SRC_DIRS} black --check --diff $(BLACK_OPTS)
test-lint: ## Run code linting tests test-lint: ## Run code linting tests
ruff check ${SRC_DIRS} pylint --errors-only --enable=unused-import,unused-argument --ignore=templates --ignore=docs/_ext ${SRC_DIRS}
test-types: ## Run type checks. test-types: ## Run type checks.
mypy --exclude=templates --ignore-missing-imports --implicit-reexport --strict ${SRC_DIRS} mypy --exclude=templates --ignore-missing-imports --implicit-reexport --strict ${SRC_DIRS}
test-unit: ## Run unit tests
python -m unittest discover tests
build-pythonpackage: ## Build the "tutor-discovery" python package for upload to pypi
python -m build --sdist
test-pythonpackage: build-pythonpackage ## Test that package can be uploaded to pypi
twine check dist/tutor_discovery-$(shell make version).tar.gz
format: ## Format code automatically. format: ## Format code automatically.
ruff format ${SRC_DIRS} black $(BLACK_OPTS)
fix-lint: ## Fix lint errors automatically isort: ## Sort imports. This target is not mandatory because the output may be incompatible with black formatting. Provided for convenience purposes.
ruff check --fix ${SRC_DIRS} isort --skip=templates ${SRC_DIRS}
changelog-entry: ## Create a new changelog entry. changelog-entry: ## Create a new changelog entry.
scriv create scriv create
@ -35,9 +27,6 @@ changelog-entry: ## Create a new changelog entry.
changelog: ## Collect changelog entries in the CHANGELOG.md file. changelog: ## Collect changelog entries in the CHANGELOG.md file.
scriv collect scriv collect
version: ## Print the current tutor-discovery version
@python -c 'import io, os; about = {}; exec(io.open(os.path.join("tutordiscovery", "__about__.py"), "rt", encoding="utf-8").read(), about); print(about["__version__"])'
ESCAPE =  ESCAPE = 
help: ## Print this help. help: ## Print this help.
@grep -E '^([a-zA-Z_-]+:.*?## .*|######* .+)$$' Makefile \ @grep -E '^([a-zA-Z_-]+:.*?## .*|######* .+)$$' Makefile \

View File

@ -38,7 +38,7 @@ Operations
Creating a user Creating a user
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
The discovery user interface will be available at http://discovery.local.openedx.io for a local test instance, The discovery user interface will be available at http://discovery.local.edly.io for a local test instance,
and at ``DISCOVERY_HOST`` (by default: http(s)://discovery.<your lms host>) in production. To run and at ``DISCOVERY_HOST`` (by default: http(s)://discovery.<your lms host>) in production. To run
commands from the UI, a user must be created: commands from the UI, a user must be created:
@ -46,15 +46,11 @@ commands from the UI, a user must be created:
tutor local run discovery ./manage.py createsuperuser tutor local run discovery ./manage.py createsuperuser
Then, you must log in with this user at http://discovery.local.openedx.io/admin. Then, you must log in with this user at http://discovery.local.edly.io/admin.
Using SSO with LMS Alternatively, you can log in with oauth2 using a pre-existing user created on the LMS/CMS by accessing
~~~~~~~~~~~~~~~~~~ http(s)://discovery.<your lms host>/login. To do so, the proper domain names must exist and point to
the production server.
If you want to log in using Single Sign-On (SSO) with the LMS, ensure that the superuser you created
above in discovery has the same username and email as an existing admin user in the LMS/CMS. You can
then access the discovery interface via `http(s)://discovery.<your lms host>/login`. Make sure that
the proper domain names are configured and point to the production server.
Index configuration Index configuration
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
@ -112,43 +108,32 @@ extra argument to the command. i.e. ``--domain``. While running tutor in product
.. code-block:: bash .. code-block:: bash
tutor local run lms ./manage.py lms cache_programs --domain="local.openedx.io" tutor local run lms ./manage.py lms cache_programs --domain="local.edly.io"
While running tutor in development mode: While running tutor in development mode:
.. code-block:: bash .. code-block:: bash
tutor dev run lms ./manage.py lms cache_programs --domain="local.openedx.io:8000" tutor dev run lms ./manage.py lms cache_programs --domain="local.edly.io:8000"
This last step should be performed every time you create new or make changes to existing programs. This last step should be performed every time you create new or make changes to existing programs.
Show Programs Tab Show Programs Tab
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
By default, the **Programs** tab is available in the LMS dashboard. Users can enable or disable this tab as needed. To make the ``Programs`` tab work in the LMS dashboard, users will need to manually create an entry
To Disable Programs, run the following command: in the ``Programs api config`` model in the LMS Admin Panel. Go to http://local.edly.io/admin/programs/programsapiconfig/.
Add ``Marketing path`` equal to ``/programs`` and enable it. Then Programs tab will be shown on the LMS
.. code-block:: bash where users can view their registered programs. It will show like in the below picture.
tutor config save --set ENABLE_PROGRAMS=False
To Enable Programs, run the following command:
.. code-block:: bash
tutor config save --set ENABLE_PROGRAMS=True
Only programs in which learners are registered will appear on this page. If a learner is enrolled in any course that is part of a program, that program will be displayed here.
.. image:: https://github.com/overhangio/tutor-discovery/assets/122095701/e0224011-adc0-41e4-a104-af4cb0c24b82 .. image:: https://github.com/overhangio/tutor-discovery/assets/122095701/e0224011-adc0-41e4-a104-af4cb0c24b82
:alt: Programs Tab on LMS dashboard :alt: Programs Tab on LMS dashboard
In the image above, the **Explore Programs** button points to http://localhost:8080/programs by default. This link does not exist, so users can change it to their custom-built marketing site URL to display all programs. In the above image, the user can see explore programs button which is pointing to ``http://localhost:8080/programs`` by default.
To Modify the Link: This link does not exist. So, users can change this link to their custom-built marketing site URL to show all programs there.
This can be done by modifying the ``Site Configurations`` model in the LMS Admin Panel. Go to
1. Go to the **Site Configurations** model in the LMS Admin Panel: `http://local.openedx.io/admin/site_configuration/siteconfiguration/` http://local.edly.io/admin/site_configuration/siteconfiguration/. Open the respective LMS site configuration and add the below
2. Open the respective LMS site configuration. dictionary in ``site values`` field like the below image:
3. Add the following dictionary in the **site values** field like in the below image:
.. code-block:: python .. code-block:: python
@ -159,11 +144,6 @@ To Modify the Link:
.. image:: https://github.com/overhangio/tutor-discovery/assets/122095701/2d588ea9-a830-40b6-9845-8fab56d7cb5a .. image:: https://github.com/overhangio/tutor-discovery/assets/122095701/2d588ea9-a830-40b6-9845-8fab56d7cb5a
:alt: Add Custom Site for Explore Programs :alt: Add Custom Site for Explore Programs
By following above instructions, this link (https://custom-marketing-site-here.com) will be replaced by http://localhost:8080. Additionally, users can also replace "/programs" by following these below steps:
1. Go to: `http://local.openedx.io/admin/programs/programsapiconfig/`
2. Add **Marketing path** equal to "/programs" or your desired marketing site path and enable it.
Install extra requirements Install extra requirements
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -189,7 +169,7 @@ in the development container:
tutor dev start --mount /path/to/course-discovery/ discovery tutor dev start --mount /path/to/course-discovery/ discovery
You can then access the development server at http://discovery.local.openedx.io:8381. Feel free to add breakpoints You can then access the development server at http://discovery.local.edly.io:8381. Feel free to add breakpoints
(``import pdb; pdb.set_trace()``) anywhere in your source code to debug your application. (``import pdb; pdb.set_trace()``) anywhere in your source code to debug your application.
Once a local repository is mounted in the image, you will have to install nodejs dependencies and collect static assets: Once a local repository is mounted in the image, you will have to install nodejs dependencies and collect static assets:
@ -221,20 +201,10 @@ This entry may be present if you named your server with the LMS hostname.
.. _DigitalOcean: https://digitalocean.com/ .. _DigitalOcean: https://digitalocean.com/
Using event-bus with tutor-discovery
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Although tutor-discovery does not start event bus consumption by default, it supports running it. To consume events from event bus with tutor-discovery, follow these `instructions`_ provided by `event-bus-redis`_.
.. _instructions: https://github.com/openedx/event-bus-redis/blob/main/docs/tutor_installation.rst
.. _event-bus-redis: https://github.com/openedx/event-bus-redis
Troubleshooting Troubleshooting
--------------- ---------------
This Tutor plugin is maintained by Muhammad Labeeb from `Edly`_. This Tutor plugin is maintained by Muhammad Faraz Maqsood from `Edly`_.
Community support is available from the official `Open edX forum`_. Community support is available from the official `Open edX forum`_.
Do you need help with this plugin? See the `troubleshooting`_ Do you need help with this plugin? See the `troubleshooting`_
section from the Tutor documentation. section from the Tutor documentation.
@ -248,4 +218,4 @@ License
This work is licensed under the terms of the `GNU Affero General Public License (AGPL)`_. This work is licensed under the terms of the `GNU Affero General Public License (AGPL)`_.
.. _GNU Affero General Public License (AGPL): https://github.com/overhangio/tutor/blob/release/LICENSE.txt .. _GNU Affero General Public License (AGPL): https://github.com/overhangio/tutor/blob/master/LICENSE.txt

View File

@ -0,0 +1 @@
- [Bugfix] Fix legacy warnings during Docker build. (by @regisb)

View File

@ -0,0 +1 @@
- [BugFix] Fix images(media) persistance issue by mounting media directory in volumes through patches. (by @Faraz32123)

View File

@ -0,0 +1 @@
- [Bugfix] Fix catalog_service_user permissions and 403 while fetching pathways (by @dyudyunov)

View File

@ -0,0 +1 @@
- 💥 [Deprecation] Drop support for python 3.8 and set Python 3.9 as the minimum supported python version. (by @Faraz32123)

View File

@ -1,2 +0,0 @@
- [Improvement] Migrate from pylint and black to ruff. (by @mlabeeb03)
- [Improvement] Test python package distribution build when running make test. (by @mlabeeb03)

View File

@ -1,84 +1,2 @@
# https://packaging.python.org/en/latest/tutorials/packaging-projects/
# https://hatch.pypa.io/latest/config/build/
[project]
name = "tutor-discovery"
license = { text = "AGPL-3.0-only" }
authors = [
{name = "Edly"},
{email = "hello@edly.io"},
]
maintainers = [
{name = "Muhammad Labeeb"},
{email = "muhammad.labeeb@arbisoft.com"},
]
description="A Tutor plugin for course discovery, the Open edX service for providing access to consolidated course and program metadata"
readme = {file = "README.rst", content-type = "text/x-rst"}
requires-python = ">= 3.9"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"tutor>=20.0.0,<21.0.0",
]
# these fields will be set by hatch_build.py
dynamic = ["version"]
[project.optional-dependencies]
dev = [
"tutor[dev]>=20.0.0,<21.0.0",
"ruff",
]
# https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels
[project.urls]
Homepage = "https://docs.tutor.edly.io/"
Documentation = "https://docs.tutor.edly.io/"
Source = "https://github.com/overhangio/tutor-discovery"
Issues = "https://github.com/overhangio/tutor-discovery/issues"
Changelog = "https://github.com/overhangio/tutor-discovery/blob/release/CHANGELOG.md"
Community = "https://discuss.openedx.org/tag/tutor"
# hatch-specific configuration
[tool.hatch.metadata.hooks.custom]
path = ".hatch_build.py"
[build-system] [build-system]
requires = ["hatchling"] requires = ["setuptools", "wheel"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.sdist]
# Disable strict naming, otherwise twine is not able to detect name/version
strict-naming = false
include = [ "/tutordiscovery", ".hatch_build.py"]
exclude = ["tests*"]
[tool.hatch.build.targets.wheel]
packages = ["tutordiscovery"]
[tool.ruff]
exclude = ["templates", "docs/_ext"]
[tool.ruff.lint]
# E: pycodestyle errors
# I: isort
# N: pep8-naming
select = ["E", "I", "N"]
# F401: unused-import
# F841: unused-variable
# W292: missing-newline-at-end-of-file
extend-select = ["F401", "F841", "W292"]
[tool.ruff.format]
[project.entry-points."tutor.plugin.v1"]
discovery = "tutordiscovery.plugin"

52
setup.py Normal file
View File

@ -0,0 +1,52 @@
import io
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
with io.open(os.path.join(here, "README.rst"), "rt", encoding="utf8") as f:
readme = f.read()
about = {}
with io.open(
os.path.join(here, "tutordiscovery", "__about__.py"), "rt", encoding="utf-8"
) as f:
exec(f.read(), about)
setup(
name="tutor-discovery",
version=about["__version__"],
url="https://docs.tutor.edly.io/",
project_urls={
"Documentation": "https://docs.tutor.edly.io/",
"Code": "https://github.com/overhangio/tutor-discovery",
"Issue tracker": "https://github.com/overhangio/tutor-discovery/issues",
"Community": "https://discuss.openedx.org",
},
license="AGPLv3",
author="Edly",
author_email="hello@edly.io",
maintainer="Edly",
maintainer_email="faraz.maqsood@arbisoft.com",
description="A Tutor plugin for course discovery, the Open edX service for providing access to consolidated course and program metadata",
long_description=readme,
long_description_content_type="text/x-rst",
packages=find_packages(exclude=["tests*"]),
include_package_data=True,
install_requires=["tutor>=18.0.0,<19.0.0"],
extras_require={"dev": "tutor[dev]>=18.0.0,<19.0.0"},
python_requires=">=3.9",
entry_points={"tutor.plugin.v1": ["discovery = tutordiscovery.plugin"]},
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
)

View File

View File

@ -1,26 +0,0 @@
import subprocess
import unittest
from unittest.mock import MagicMock, patch
from tutordiscovery import utils
class UtilsTests(unittest.TestCase):
@patch("subprocess.run")
def test_is_docker_rootless(self, mock_run: MagicMock) -> None:
# Mock rootless `docker info` output
utils.is_docker_rootless.cache_clear()
mock_run.return_value.stdout = "some prefix\n rootless foo bar".encode("utf-8")
self.assertTrue(utils.is_docker_rootless())
# Mock regular `docker info` output
utils.is_docker_rootless.cache_clear()
mock_run.return_value.stdout = "some prefix, regular docker".encode("utf-8")
self.assertFalse(utils.is_docker_rootless())
@patch("subprocess.run")
def test_is_docker_rootless_podman(self, mock_run: MagicMock) -> None:
"""Test the `is_docker_rootless` when podman is used or any other error with `docker info`""" # noqa: E501
utils.is_docker_rootless.cache_clear()
mock_run.side_effect = subprocess.CalledProcessError(1, "docker info")
self.assertFalse(utils.is_docker_rootless())

View File

@ -1 +1 @@
__version__ = "20.0.0" __version__ = "18.0.0"

View File

@ -1 +0,0 @@
DISCOVERY_RUN_ELASTICSEARCH = {{ DISCOVERY_RUN_ELASTICSEARCH }}

View File

@ -15,8 +15,8 @@ spec:
app.kubernetes.io/name: discovery app.kubernetes.io/name: discovery
spec: spec:
securityContext: securityContext:
runAsUser: {{ APP_USER_ID }} runAsUser: 1000
runAsGroup: {{ APP_USER_ID }} runAsGroup: 1000
containers: containers:
- name: discovery - name: discovery
image: {{ DISCOVERY_DOCKER_IMAGE }} image: {{ DISCOVERY_DOCKER_IMAGE }}
@ -32,54 +32,3 @@ spec:
- name: settings - name: settings
configMap: configMap:
name: discovery-settings name: discovery-settings
{% if DISCOVERY_RUN_ELASTICSEARCH %}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: elasticsearch
labels:
app.kubernetes.io/name: elasticsearch
spec:
selector:
matchLabels:
app.kubernetes.io/name: elasticsearch
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: elasticsearch
spec:
securityContext:
runAsUser: {{ APP_USER_ID }}
runAsGroup: {{ APP_USER_ID }}
fsGroup: {{ APP_USER_ID }}
fsGroupChangePolicy: "OnRootMismatch"
containers:
- name: elasticsearch
image: {{ DISCOVERY_DOCKER_IMAGE_ELASTICSEARCH }}
env:
- name: cluster.name
value: "openedx"
- name: bootstrap.memory_lock
value: "true"
- name: discovery.type
value: "single-node"
- name: ES_JAVA_OPTS
value: "-Xms{{ DISCOVERY_ELASTICSEARCH_HEAP_SIZE }} -Xmx{{ DISCOVERY_ELASTICSEARCH_HEAP_SIZE }}"
- name: TAKE_FILE_OWNERSHIP
value: "1"
ports:
- containerPort: 9200
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: /usr/share/elasticsearch/data
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: elasticsearch
{% endif %}

View File

@ -23,3 +23,4 @@ spec:
- name: settings - name: settings
configMap: configMap:
name: discovery-settings name: discovery-settings

View File

@ -10,19 +10,3 @@ spec:
protocol: TCP protocol: TCP
selector: selector:
app.kubernetes.io/name: discovery app.kubernetes.io/name: discovery
{% if DISCOVERY_RUN_ELASTICSEARCH %}
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
labels:
app.kubernetes.io/name: elasticsearch
spec:
type: ClusterIP
ports:
- port: 9200
protocol: TCP
selector:
app.kubernetes.io/name: elasticsearch
{% endif %}

View File

@ -1,16 +0,0 @@
{% if DISCOVERY_RUN_ELASTICSEARCH %}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: elasticsearch
labels:
app.kubernetes.io/component: volume
app.kubernetes.io/name: elasticsearch
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
{% endif %}

View File

@ -15,12 +15,3 @@ discovery:
default: default:
aliases: aliases:
- "{{ DISCOVERY_HOST }}" - "{{ DISCOVERY_HOST }}"
{% if DISCOVERY_RUN_ELASTICSEARCH and is_docker_rootless() %}
elasticsearch:
ulimits:
memlock:
# Fixes error setting rlimits for ready process in rootless docker
soft: 0 # zero means "unset" in the memlock context
hard: 0
{% endif %}

View File

@ -1 +0,0 @@
{% if DISCOVERY_RUN_ELASTICSEARCH %}setowner {{ APP_USER_ID }} /mounts/elasticsearch{% endif %}

View File

@ -1 +0,0 @@
{% if DISCOVERY_RUN_ELASTICSEARCH %}- ../../data/elasticsearch:/mounts/elasticsearch{% endif %}

View File

@ -6,28 +6,7 @@ discovery:
volumes: volumes:
- ../plugins/discovery/apps/settings/tutor:/openedx/discovery/course_discovery/settings/tutor:ro - ../plugins/discovery/apps/settings/tutor:/openedx/discovery/course_discovery/settings/tutor:ro
- ../../data/discovery/media:/openedx/discovery/course_discovery/media - ../../data/discovery/media:/openedx/discovery/course_discovery/media
{% if DISCOVERY_RUN_ELASTICSEARCH %}- ../../data/elasticsearch:/mounts/elasticsearch{% endif %}
depends_on: depends_on:
- lms - lms
{% if RUN_MYSQL %}- mysql{% endif %} {% if RUN_MYSQL %}- mysql{% endif %}
{% if DISCOVERY_RUN_ELASTICSEARCH %}- elasticsearch{% endif %} {% if RUN_ELASTICSEARCH %}- elasticsearch{% endif %}
{% if DISCOVERY_RUN_ELASTICSEARCH -%}
elasticsearch:
image: {{ DISCOVERY_DOCKER_IMAGE_ELASTICSEARCH }}
environment:
- cluster.name=openedx
- bootstrap.memory_lock=true
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms{{ DISCOVERY_ELASTICSEARCH_HEAP_SIZE }} -Xmx{{ DISCOVERY_ELASTICSEARCH_HEAP_SIZE }}"
ulimits:
memlock:
soft: -1
hard: -1
restart: unless-stopped
user: "{{ APP_USER_ID }}:{{ APP_USER_ID }}"
volumes:
- ../../data/elasticsearch:/usr/share/elasticsearch/data
depends_on:
- permissions
{%- endif %}

View File

@ -1 +0,0 @@
MFE_CONFIG["ENABLE_PROGRAMS"] = {{ ENABLE_PROGRAMS }}

View File

@ -9,9 +9,8 @@ from tutor import hooks as tutor_hooks
from tutor.__about__ import __version_suffix__ from tutor.__about__ import __version_suffix__
from .__about__ import __version__ from .__about__ import __version__
from .utils import is_docker_rootless
# Handle version suffix in main mode, just like tutor core # Handle version suffix in nightly mode, just like tutor core
if __version_suffix__: if __version_suffix__:
__version__ += "-" + __version_suffix__ __version__ += "-" + __version_suffix__
@ -22,7 +21,7 @@ APP_NAME = "discovery"
config: t.Dict[str, t.Dict[str, t.Any]] = { config: t.Dict[str, t.Dict[str, t.Any]] = {
"defaults": { "defaults": {
"VERSION": __version__, "VERSION": __version__,
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY}}overhangio/openedx-discovery:{{ DISCOVERY_VERSION }}", # noqa: E501 "DOCKER_IMAGE": "{{ DOCKER_REGISTRY}}overhangio/openedx-discovery:{{ DISCOVERY_VERSION }}",
"HOST": "discovery.{{ LMS_HOST }}", "HOST": "discovery.{{ LMS_HOST }}",
"INDEX_OVERRIDES": {}, "INDEX_OVERRIDES": {},
"MYSQL_DATABASE": "discovery", "MYSQL_DATABASE": "discovery",
@ -37,12 +36,6 @@ config: t.Dict[str, t.Dict[str, t.Any]] = {
"EXTRA_PIP_REQUIREMENTS": [], "EXTRA_PIP_REQUIREMENTS": [],
"REPOSITORY": "https://github.com/openedx/course-discovery.git", "REPOSITORY": "https://github.com/openedx/course-discovery.git",
"REPOSITORY_VERSION": "{{ OPENEDX_COMMON_VERSION }}", "REPOSITORY_VERSION": "{{ OPENEDX_COMMON_VERSION }}",
"RUN_ELASTICSEARCH": True,
"DOCKER_IMAGE_ELASTICSEARCH": "docker.io/elasticsearch:7.17.13",
"ELASTICSEARCH_HOST": "elasticsearch",
"ELASTICSEARCH_PORT": 9200,
"ELASTICSEARCH_SCHEME": "http",
"ELASTICSEARCH_HEAP_SIZE": "1g",
}, },
"unique": { "unique": {
"MYSQL_PASSWORD": "{{ 8|random_string }}", "MYSQL_PASSWORD": "{{ 8|random_string }}",
@ -50,9 +43,6 @@ config: t.Dict[str, t.Dict[str, t.Any]] = {
"OAUTH2_SECRET": "{{ 8|random_string }}", "OAUTH2_SECRET": "{{ 8|random_string }}",
"OAUTH2_SECRET_SSO": "{{ 8|random_string }}", "OAUTH2_SECRET_SSO": "{{ 8|random_string }}",
}, },
"overrides": {
"ENABLE_PROGRAMS": True,
},
} }
# Initialization tasks # Initialization tasks
@ -131,10 +121,6 @@ tutor_hooks.Filters.ENV_TEMPLATE_TARGETS.add_items(
("discovery/apps", "plugins"), ("discovery/apps", "plugins"),
], ],
) )
# Template variables
tutor_hooks.Filters.ENV_TEMPLATE_VARIABLES.add_item(
("is_docker_rootless", is_docker_rootless),
)
# Load patches from files # Load patches from files
for path in glob( for path in glob(
os.path.join( os.path.join(

View File

@ -20,14 +20,8 @@ DATABASES = {
} }
} }
DISCOVERY_DOCKER_IMAGE_ELASTICSEARCH = "{{ DISCOVERY_DOCKER_IMAGE_ELASTICSEARCH }}"
DISCOVERY_ELASTICSEARCH_HOST = "{{ DISCOVERY_ELASTICSEARCH_HOST }}"
DISCOVERY_ELASTICSEARCH_PORT = "{{ DISCOVERY_ELASTICSEARCH_PORT }}"
DISCOVERY_ELASTICSEARCH_SCHEME = "{{ DISCOVERY_ELASTICSEARCH_SCHEME }}"
DISCOVERY_ELASTICSEARCH_HEAP_SIZE = "{{ DISCOVERY_ELASTICSEARCH_HEAP_SIZE }}"
ELASTICSEARCH_DSL['default'].update({ ELASTICSEARCH_DSL['default'].update({
'hosts': "{{ DISCOVERY_ELASTICSEARCH_SCHEME }}://{{ DISCOVERY_ELASTICSEARCH_HOST }}:{{ DISCOVERY_ELASTICSEARCH_PORT }}/" 'hosts': "{{ ELASTICSEARCH_SCHEME }}://{{ ELASTICSEARCH_HOST }}:{{ ELASTICSEARCH_PORT }}/"
}) })
{% for name, index in DISCOVERY_INDEX_OVERRIDES.items() %} {% for name, index in DISCOVERY_INDEX_OVERRIDES.items() %}

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1.4 # syntax=docker/dockerfile:1.4
###### Minimal image with base system requirements for most stages ###### Minimal image with base system requirements for most stages
FROM docker.io/ubuntu:22.04 AS minimal FROM docker.io/ubuntu:20.04 AS minimal
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
@ -8,10 +8,10 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
apt update && \ apt update && \
apt install -y curl git-core gettext language-pack-en \ apt install -y curl git-core gettext language-pack-en \
build-essential libcairo2 libffi-dev libmysqlclient-dev libxml2-dev libxslt-dev libjpeg-dev libssl-dev \ build-essential libcairo2 libffi-dev libmysqlclient-dev libxml2-dev libxslt-dev libjpeg-dev libssl-dev \
pkg-config libsqlite3-dev media-types mailcap libbz2-dev liblzma-dev pkg-config libsqlite3-dev mime-support
ENV LC_ALL=en_US.UTF-8 ENV LC_ALL=en_US.UTF-8
ARG APP_USER_ID={{ HOST_USER_ID }} ARG APP_USER_ID=1000
RUN if [ "$APP_USER_ID" = 0 ]; then echo "app user may not be root" && false; fi RUN if [ "$APP_USER_ID" = 0 ]; then echo "app user may not be root" && false; fi
RUN useradd --home-dir /openedx --create-home --shell /bin/bash --uid ${APP_USER_ID} app RUN useradd --home-dir /openedx --create-home --shell /bin/bash --uid ${APP_USER_ID} app
USER ${APP_USER_ID} USER ${APP_USER_ID}
@ -47,10 +47,10 @@ RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared pip install \
# https://pypi.org/project/setuptools/ # https://pypi.org/project/setuptools/
# https://pypi.org/project/pip/ # https://pypi.org/project/pip/
# https://pypi.org/project/wheel/ # https://pypi.org/project/wheel/
setuptools==77.0.3 pip==25.0.1 wheel==0.45.1 setuptools==69.1.1 pip==24.0 wheel==0.43.0
# Install a recent version of nodejs # Install a recent version of nodejs
RUN pip install nodeenv==1.9.1 RUN pip install nodeenv==1.8.0
# nodejs version picked from https://github.com/openedx/course-discovery/blob/master/Dockerfile # nodejs version picked from https://github.com/openedx/course-discovery/blob/master/Dockerfile
RUN nodeenv /openedx/nodeenv --node=16.14.2 --prebuilt RUN nodeenv /openedx/nodeenv --node=16.14.2 --prebuilt
ENV PATH=/openedx/nodeenv/bin:${PATH} ENV PATH=/openedx/nodeenv/bin:${PATH}
@ -73,7 +73,7 @@ RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared pip install \
# Use redis as a django cache https://pypi.org/project/django-redis/ # Use redis as a django cache https://pypi.org/project/django-redis/
django-redis==5.4.0 \ django-redis==5.4.0 \
# uwsgi server https://pypi.org/project/uWSGI/ # uwsgi server https://pypi.org/project/uWSGI/
uwsgi==2.0.28 uwsgi==2.0.24
{% if DISCOVERY_ATLAS_PULL %} {% if DISCOVERY_ATLAS_PULL %}
# Pull translations. Support the OEP-58 proposal behind a feature flag until it's fully implemented. # Pull translations. Support the OEP-58 proposal behind a feature flag until it's fully implemented.
@ -91,13 +91,13 @@ RUN mkdir course_discovery/media
# Run production server # Run production server
ENV DJANGO_SETTINGS_MODULE=course_discovery.settings.tutor.production ENV DJANGO_SETTINGS_MODULE=course_discovery.settings.tutor.production
EXPOSE 8000 EXPOSE 8000
CMD ["uwsgi", \ CMD uwsgi \
"--static-map", "/static=/openedx/discovery/course_discovery/assets", \ --static-map /static=/openedx/discovery/course_discovery/assets \
"--static-map", "/media=/openedx/discovery/course_discovery/media", \ --static-map /media=/openedx/discovery/course_discovery/media \
"--http", "0.0.0.0:8000", \ --http 0.0.0.0:8000 \
"--thunder-lock", \ --thunder-lock \
"--single-interpreter", \ --single-interpreter \
"--enable-threads", \ --enable-threads \
"--processes=2", \ --processes=2 \
"--buffer-size=8192", \ --buffer-size=8192 \
"--wsgi-file", "course_discovery/wsgi.py"] --wsgi-file course_discovery/wsgi.py

View File

@ -6,11 +6,6 @@
"from django.contrib.auth import get_user_model;\ "from django.contrib.auth import get_user_model;\
get_user_model().objects.filter(username='lms_catalog_service_user').exclude(email='lms_catalog_service_user@openedx').update(email='lms_catalog_service_user@openedx')" get_user_model().objects.filter(username='lms_catalog_service_user').exclude(email='lms_catalog_service_user@openedx').update(email='lms_catalog_service_user@openedx')"
./manage.py lms shell -c \
"from openedx.core.djangoapps.programs.models import ProgramsApiConfig;\
ProgramsApiConfig.current().enabled or \
ProgramsApiConfig.objects.create(marketing_path='/programs', enabled=True)"
./manage.py lms manage_user discovery discovery@openedx --staff --superuser --unusable-password ./manage.py lms manage_user discovery discovery@openedx --staff --superuser --unusable-password
./manage.py lms manage_user lms_catalog_service_user lms_catalog_service_user@openedx --staff --unusable-password ./manage.py lms manage_user lms_catalog_service_user lms_catalog_service_user@openedx --staff --unusable-password
@ -62,5 +57,5 @@
# configuration -- which means that it takes different values for different # configuration -- which means that it takes different values for different
# sites. This is important because the programs and courses returned for each # sites. This is important because the programs and courses returned for each
# site will differ. # site will differ.
./manage.py lms create_or_update_site_configuration {{ LMS_HOST }} --configuration '{"COURSE_CATALOG_API_URL": "{% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ DISCOVERY_HOST }}/api/v1"}' --enabled site-configuration set -d {{ LMS_HOST }} COURSE_CATALOG_API_URL {% if ENABLE_HTTPS %}https{% else %}http{% endif %}://{{ DISCOVERY_HOST }}/api/v1
./manage.py lms create_or_update_site_configuration {{ LMS_HOST }}:8000 --configuration '{"COURSE_CATALOG_API_URL": "http://{{ DISCOVERY_HOST }}:8381/api/v1"}' --enabled site-configuration set -d {{ LMS_HOST }}:8000 COURSE_CATALOG_API_URL http://{{ DISCOVERY_HOST }}:8381/api/v1

View File

@ -1,16 +0,0 @@
import subprocess
from functools import lru_cache
@lru_cache(maxsize=None)
def is_docker_rootless() -> bool:
"""
A helper function to determine if Docker is running in rootless mode.
- https://docs.docker.com/engine/security/rootless/
"""
try:
results = subprocess.run(["docker", "info"], capture_output=True, check=True)
return "rootless" in results.stdout.decode()
except subprocess.CalledProcessError:
return False